diff --git a/Motate b/Motate index 76fc94edc..ee04b276a 160000 --- a/Motate +++ b/Motate @@ -1 +1 @@ -Subproject commit 76fc94edcab42d03f713e08786dea935ee9a560e +Subproject commit ee04b276a9301e4e4542471b2c461dc2532e0543 diff --git a/g2core/board/Archim/hardware.cpp b/g2core/board/Archim/0_hardware.cpp similarity index 100% rename from g2core/board/Archim/hardware.cpp rename to g2core/board/Archim/0_hardware.cpp diff --git a/g2core/board/Archim/board_gpio.cpp b/g2core/board/Archim/board_gpio.cpp new file mode 100644 index 000000000..4daf011d8 --- /dev/null +++ b/g2core/board/Archim/board_gpio.cpp @@ -0,0 +1,108 @@ +/* + * gpio.cpp - digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2107 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Switch Modes + * + * The switches are considered to be homing switches when cycle_state is + * CYCLE_HOMING. At all other times they are treated as limit switches: + * - Hitting a homing switch puts the current move into feedhold + * - Hitting a limit switch causes the machine to shut down and go into lockdown until reset + * + * The normally open switch modes (NO) trigger an interrupt on the falling edge + * and lockout subsequent interrupts for the defined lockout period. This approach + * beats doing debouncing as an integration as switches fire immediately. + * + * The normally closed switch modes (NC) trigger an interrupt on the rising edge + * and lockout subsequent interrupts for the defined lockout period. Ditto on the method. + */ + +#include "../../g2core.h" // #1 +#include "config.h" // #2 +#include "gpio.h" +#include "hardware.h" +#include "canonical_machine.h" + +#include "text_parser.h" +#include "controller.h" +#include "util.h" +#include "report.h" +#include "xio.h" + +#include "MotateTimers.h" + +/**** Setup Actual Objects ****/ + +gpioDigitalInputPin> din1 {DI1_MODE, 1}; +gpioDigitalInputPin> din2 {DI2_MODE, 2}; +gpioDigitalInputPin> din3 {DI3_MODE, 3}; +gpioDigitalInputPin> din4 {DI4_MODE, 4}; +gpioDigitalInputPin> din5 {DI5_MODE, 5}; +gpioDigitalInputPin> din6 {DI6_MODE, 6}; +gpioDigitalInputPin> din7 {DI7_MODE, 7}; +gpioDigitalInputPin> din8 {DI8_MODE, 8}; +gpioDigitalInputPin> din9 {DI9_MODE, 9}; +// gpioDigitalInputPin> din10 {DI10_MODE, 10}; +// gpioDigitalInputPin> din11 {DI11_MODE, 11}; +// gpioDigitalInputPin> din12 {DI12_MODE, 12}; + +gpioDigitalOutputPin> dout1 { DO1_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout2 { DO2_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout3 { DO3_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout4 { DO4_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout5 { DO5_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout6 { DO6_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout7 { DO7_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout8 { DO8_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout9 { DO9_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout10 { DO10_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout11 { DO11_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout12 { DO12_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout13 { DO13_MODE, (uint32_t)200000 }; + +/**** Setup Arrays - these are extern and MUST match the board_gpio.h ****/ + +gpioDigitalInput* const d_in[] = {&din1, &din2, &din3, &din4, &din5, &din6, &din7, &din8, &din9}; +gpioDigitalOutput* const d_out[] = {&dout1, &dout2, &dout3, &dout4, &dout5, &dout6, &dout7, &dout8, &dout9, &dout10, &dout11, &dout12, &dout13}; +// not yet used +// gpioAnalogInput* a_in[A_IN_CHANNELS]; +// gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +/************************************************************************************ + **** CODE ************************************************************************** + ************************************************************************************/ +/* + * gpio_reset() - reset inputs and outputs (no initialization) + */ + + +void outputs_reset(void) { + // nothing to do +} + +void inputs_reset(void) { + // nothing to do +} diff --git a/g2core/board/Archim/board_gpio.h b/g2core/board/Archim/board_gpio.h new file mode 100644 index 000000000..25a1cddcd --- /dev/null +++ b/g2core/board/Archim/board_gpio.h @@ -0,0 +1,90 @@ +/* + * gpio.h - Digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef BOARD_GPIO_H_ONCE +#define BOARD_GPIO_H_ONCE + +// this file is included from the bottom of gpio.h, but we do this for completeness +#include "../../gpio.h" + +/* + * GPIO defines + */ +//--- change as required for board and switch hardware ---// + +#define D_IN_CHANNELS 9 // v9 // number of digital inputs supported +#define D_OUT_CHANNELS 13 // number of digital outputs supported +#define A_IN_CHANNELS 0 // number of analog inputs supported +#define A_OUT_CHANNELS 0 // number of analog outputs supported + +#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing + +/* + * The GPIO objects themselves - this must match up with board_gpio.cpp! + */ + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; +// extern gpioAnalogInput* a_in[A_IN_CHANNELS]; +// extern gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +// prepare the objects as externs (for config_app to not bloat) +using Motate::IRQPin; +using Motate::PWMOutputPin; +using Motate::PWMLikeOutputPin; +template +using OutputType = typename std::conditional, PWMLikeOutputPin>::type; + +extern gpioDigitalInputPin> din1; +extern gpioDigitalInputPin> din2; +extern gpioDigitalInputPin> din3; +extern gpioDigitalInputPin> din4; +extern gpioDigitalInputPin> din5; +extern gpioDigitalInputPin> din6; +extern gpioDigitalInputPin> din7; +extern gpioDigitalInputPin> din8; +extern gpioDigitalInputPin> din9; +// extern gpioDigitalInputPin> din10; +// extern gpioDigitalInputPin> din11; +// extern gpioDigitalInputPin> din12; + +extern gpioDigitalOutputPin> dout1; +extern gpioDigitalOutputPin> dout2; +extern gpioDigitalOutputPin> dout3; +extern gpioDigitalOutputPin> dout4; +extern gpioDigitalOutputPin> dout5; +extern gpioDigitalOutputPin> dout6; +extern gpioDigitalOutputPin> dout7; +extern gpioDigitalOutputPin> dout8; +extern gpioDigitalOutputPin> dout9; +extern gpioDigitalOutputPin> dout10; +extern gpioDigitalOutputPin> dout11; +extern gpioDigitalOutputPin> dout12; +extern gpioDigitalOutputPin> dout13; + + +#endif // End of include guard: BOARD_GPIO_H_ONCE diff --git a/g2core/board/Archim/board_xio.h b/g2core/board/Archim/board_xio.h index 09f20fef8..ea0a3fa7b 100755 --- a/g2core/board/Archim/board_xio.h +++ b/g2core/board/Archim/board_xio.h @@ -37,10 +37,10 @@ #include "MotateUSBCDC.h" #if USB_SERIAL_PORTS_EXPOSED == 1 -typedef Motate::USBDevice< Motate::USBCDC > XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC > XIOUSBDevice_t; #endif #if USB_SERIAL_PORTS_EXPOSED == 2 -typedef Motate::USBDevice XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC, Motate::USBCDC > XIOUSBDevice_t; #endif extern XIOUSBDevice_t usb; diff --git a/g2core/board/ArduinoDue/hardware.cpp b/g2core/board/ArduinoDue/0_hardware.cpp similarity index 100% rename from g2core/board/ArduinoDue/hardware.cpp rename to g2core/board/ArduinoDue/0_hardware.cpp diff --git a/g2core/board/ArduinoDue/board_gpio.cpp b/g2core/board/ArduinoDue/board_gpio.cpp new file mode 100644 index 000000000..4daf011d8 --- /dev/null +++ b/g2core/board/ArduinoDue/board_gpio.cpp @@ -0,0 +1,108 @@ +/* + * gpio.cpp - digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2107 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Switch Modes + * + * The switches are considered to be homing switches when cycle_state is + * CYCLE_HOMING. At all other times they are treated as limit switches: + * - Hitting a homing switch puts the current move into feedhold + * - Hitting a limit switch causes the machine to shut down and go into lockdown until reset + * + * The normally open switch modes (NO) trigger an interrupt on the falling edge + * and lockout subsequent interrupts for the defined lockout period. This approach + * beats doing debouncing as an integration as switches fire immediately. + * + * The normally closed switch modes (NC) trigger an interrupt on the rising edge + * and lockout subsequent interrupts for the defined lockout period. Ditto on the method. + */ + +#include "../../g2core.h" // #1 +#include "config.h" // #2 +#include "gpio.h" +#include "hardware.h" +#include "canonical_machine.h" + +#include "text_parser.h" +#include "controller.h" +#include "util.h" +#include "report.h" +#include "xio.h" + +#include "MotateTimers.h" + +/**** Setup Actual Objects ****/ + +gpioDigitalInputPin> din1 {DI1_MODE, 1}; +gpioDigitalInputPin> din2 {DI2_MODE, 2}; +gpioDigitalInputPin> din3 {DI3_MODE, 3}; +gpioDigitalInputPin> din4 {DI4_MODE, 4}; +gpioDigitalInputPin> din5 {DI5_MODE, 5}; +gpioDigitalInputPin> din6 {DI6_MODE, 6}; +gpioDigitalInputPin> din7 {DI7_MODE, 7}; +gpioDigitalInputPin> din8 {DI8_MODE, 8}; +gpioDigitalInputPin> din9 {DI9_MODE, 9}; +// gpioDigitalInputPin> din10 {DI10_MODE, 10}; +// gpioDigitalInputPin> din11 {DI11_MODE, 11}; +// gpioDigitalInputPin> din12 {DI12_MODE, 12}; + +gpioDigitalOutputPin> dout1 { DO1_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout2 { DO2_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout3 { DO3_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout4 { DO4_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout5 { DO5_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout6 { DO6_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout7 { DO7_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout8 { DO8_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout9 { DO9_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout10 { DO10_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout11 { DO11_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout12 { DO12_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout13 { DO13_MODE, (uint32_t)200000 }; + +/**** Setup Arrays - these are extern and MUST match the board_gpio.h ****/ + +gpioDigitalInput* const d_in[] = {&din1, &din2, &din3, &din4, &din5, &din6, &din7, &din8, &din9}; +gpioDigitalOutput* const d_out[] = {&dout1, &dout2, &dout3, &dout4, &dout5, &dout6, &dout7, &dout8, &dout9, &dout10, &dout11, &dout12, &dout13}; +// not yet used +// gpioAnalogInput* a_in[A_IN_CHANNELS]; +// gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +/************************************************************************************ + **** CODE ************************************************************************** + ************************************************************************************/ +/* + * gpio_reset() - reset inputs and outputs (no initialization) + */ + + +void outputs_reset(void) { + // nothing to do +} + +void inputs_reset(void) { + // nothing to do +} diff --git a/g2core/board/ArduinoDue/board_gpio.h b/g2core/board/ArduinoDue/board_gpio.h new file mode 100644 index 000000000..25a1cddcd --- /dev/null +++ b/g2core/board/ArduinoDue/board_gpio.h @@ -0,0 +1,90 @@ +/* + * gpio.h - Digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef BOARD_GPIO_H_ONCE +#define BOARD_GPIO_H_ONCE + +// this file is included from the bottom of gpio.h, but we do this for completeness +#include "../../gpio.h" + +/* + * GPIO defines + */ +//--- change as required for board and switch hardware ---// + +#define D_IN_CHANNELS 9 // v9 // number of digital inputs supported +#define D_OUT_CHANNELS 13 // number of digital outputs supported +#define A_IN_CHANNELS 0 // number of analog inputs supported +#define A_OUT_CHANNELS 0 // number of analog outputs supported + +#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing + +/* + * The GPIO objects themselves - this must match up with board_gpio.cpp! + */ + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; +// extern gpioAnalogInput* a_in[A_IN_CHANNELS]; +// extern gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +// prepare the objects as externs (for config_app to not bloat) +using Motate::IRQPin; +using Motate::PWMOutputPin; +using Motate::PWMLikeOutputPin; +template +using OutputType = typename std::conditional, PWMLikeOutputPin>::type; + +extern gpioDigitalInputPin> din1; +extern gpioDigitalInputPin> din2; +extern gpioDigitalInputPin> din3; +extern gpioDigitalInputPin> din4; +extern gpioDigitalInputPin> din5; +extern gpioDigitalInputPin> din6; +extern gpioDigitalInputPin> din7; +extern gpioDigitalInputPin> din8; +extern gpioDigitalInputPin> din9; +// extern gpioDigitalInputPin> din10; +// extern gpioDigitalInputPin> din11; +// extern gpioDigitalInputPin> din12; + +extern gpioDigitalOutputPin> dout1; +extern gpioDigitalOutputPin> dout2; +extern gpioDigitalOutputPin> dout3; +extern gpioDigitalOutputPin> dout4; +extern gpioDigitalOutputPin> dout5; +extern gpioDigitalOutputPin> dout6; +extern gpioDigitalOutputPin> dout7; +extern gpioDigitalOutputPin> dout8; +extern gpioDigitalOutputPin> dout9; +extern gpioDigitalOutputPin> dout10; +extern gpioDigitalOutputPin> dout11; +extern gpioDigitalOutputPin> dout12; +extern gpioDigitalOutputPin> dout13; + + +#endif // End of include guard: BOARD_GPIO_H_ONCE diff --git a/g2core/board/ArduinoDue/board_xio.h b/g2core/board/ArduinoDue/board_xio.h index 09f20fef8..ea0a3fa7b 100755 --- a/g2core/board/ArduinoDue/board_xio.h +++ b/g2core/board/ArduinoDue/board_xio.h @@ -37,10 +37,10 @@ #include "MotateUSBCDC.h" #if USB_SERIAL_PORTS_EXPOSED == 1 -typedef Motate::USBDevice< Motate::USBCDC > XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC > XIOUSBDevice_t; #endif #if USB_SERIAL_PORTS_EXPOSED == 2 -typedef Motate::USBDevice XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC, Motate::USBCDC > XIOUSBDevice_t; #endif extern XIOUSBDevice_t usb; diff --git a/g2core/board/G2v9/hardware.cpp b/g2core/board/G2v9/0_hardware.cpp similarity index 100% rename from g2core/board/G2v9/hardware.cpp rename to g2core/board/G2v9/0_hardware.cpp diff --git a/g2core/board/G2v9/board_gpio.cpp b/g2core/board/G2v9/board_gpio.cpp new file mode 100644 index 000000000..4daf011d8 --- /dev/null +++ b/g2core/board/G2v9/board_gpio.cpp @@ -0,0 +1,108 @@ +/* + * gpio.cpp - digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2107 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Switch Modes + * + * The switches are considered to be homing switches when cycle_state is + * CYCLE_HOMING. At all other times they are treated as limit switches: + * - Hitting a homing switch puts the current move into feedhold + * - Hitting a limit switch causes the machine to shut down and go into lockdown until reset + * + * The normally open switch modes (NO) trigger an interrupt on the falling edge + * and lockout subsequent interrupts for the defined lockout period. This approach + * beats doing debouncing as an integration as switches fire immediately. + * + * The normally closed switch modes (NC) trigger an interrupt on the rising edge + * and lockout subsequent interrupts for the defined lockout period. Ditto on the method. + */ + +#include "../../g2core.h" // #1 +#include "config.h" // #2 +#include "gpio.h" +#include "hardware.h" +#include "canonical_machine.h" + +#include "text_parser.h" +#include "controller.h" +#include "util.h" +#include "report.h" +#include "xio.h" + +#include "MotateTimers.h" + +/**** Setup Actual Objects ****/ + +gpioDigitalInputPin> din1 {DI1_MODE, 1}; +gpioDigitalInputPin> din2 {DI2_MODE, 2}; +gpioDigitalInputPin> din3 {DI3_MODE, 3}; +gpioDigitalInputPin> din4 {DI4_MODE, 4}; +gpioDigitalInputPin> din5 {DI5_MODE, 5}; +gpioDigitalInputPin> din6 {DI6_MODE, 6}; +gpioDigitalInputPin> din7 {DI7_MODE, 7}; +gpioDigitalInputPin> din8 {DI8_MODE, 8}; +gpioDigitalInputPin> din9 {DI9_MODE, 9}; +// gpioDigitalInputPin> din10 {DI10_MODE, 10}; +// gpioDigitalInputPin> din11 {DI11_MODE, 11}; +// gpioDigitalInputPin> din12 {DI12_MODE, 12}; + +gpioDigitalOutputPin> dout1 { DO1_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout2 { DO2_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout3 { DO3_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout4 { DO4_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout5 { DO5_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout6 { DO6_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout7 { DO7_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout8 { DO8_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout9 { DO9_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout10 { DO10_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout11 { DO11_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout12 { DO12_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout13 { DO13_MODE, (uint32_t)200000 }; + +/**** Setup Arrays - these are extern and MUST match the board_gpio.h ****/ + +gpioDigitalInput* const d_in[] = {&din1, &din2, &din3, &din4, &din5, &din6, &din7, &din8, &din9}; +gpioDigitalOutput* const d_out[] = {&dout1, &dout2, &dout3, &dout4, &dout5, &dout6, &dout7, &dout8, &dout9, &dout10, &dout11, &dout12, &dout13}; +// not yet used +// gpioAnalogInput* a_in[A_IN_CHANNELS]; +// gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +/************************************************************************************ + **** CODE ************************************************************************** + ************************************************************************************/ +/* + * gpio_reset() - reset inputs and outputs (no initialization) + */ + + +void outputs_reset(void) { + // nothing to do +} + +void inputs_reset(void) { + // nothing to do +} diff --git a/g2core/board/G2v9/board_gpio.h b/g2core/board/G2v9/board_gpio.h new file mode 100644 index 000000000..25a1cddcd --- /dev/null +++ b/g2core/board/G2v9/board_gpio.h @@ -0,0 +1,90 @@ +/* + * gpio.h - Digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef BOARD_GPIO_H_ONCE +#define BOARD_GPIO_H_ONCE + +// this file is included from the bottom of gpio.h, but we do this for completeness +#include "../../gpio.h" + +/* + * GPIO defines + */ +//--- change as required for board and switch hardware ---// + +#define D_IN_CHANNELS 9 // v9 // number of digital inputs supported +#define D_OUT_CHANNELS 13 // number of digital outputs supported +#define A_IN_CHANNELS 0 // number of analog inputs supported +#define A_OUT_CHANNELS 0 // number of analog outputs supported + +#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing + +/* + * The GPIO objects themselves - this must match up with board_gpio.cpp! + */ + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; +// extern gpioAnalogInput* a_in[A_IN_CHANNELS]; +// extern gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +// prepare the objects as externs (for config_app to not bloat) +using Motate::IRQPin; +using Motate::PWMOutputPin; +using Motate::PWMLikeOutputPin; +template +using OutputType = typename std::conditional, PWMLikeOutputPin>::type; + +extern gpioDigitalInputPin> din1; +extern gpioDigitalInputPin> din2; +extern gpioDigitalInputPin> din3; +extern gpioDigitalInputPin> din4; +extern gpioDigitalInputPin> din5; +extern gpioDigitalInputPin> din6; +extern gpioDigitalInputPin> din7; +extern gpioDigitalInputPin> din8; +extern gpioDigitalInputPin> din9; +// extern gpioDigitalInputPin> din10; +// extern gpioDigitalInputPin> din11; +// extern gpioDigitalInputPin> din12; + +extern gpioDigitalOutputPin> dout1; +extern gpioDigitalOutputPin> dout2; +extern gpioDigitalOutputPin> dout3; +extern gpioDigitalOutputPin> dout4; +extern gpioDigitalOutputPin> dout5; +extern gpioDigitalOutputPin> dout6; +extern gpioDigitalOutputPin> dout7; +extern gpioDigitalOutputPin> dout8; +extern gpioDigitalOutputPin> dout9; +extern gpioDigitalOutputPin> dout10; +extern gpioDigitalOutputPin> dout11; +extern gpioDigitalOutputPin> dout12; +extern gpioDigitalOutputPin> dout13; + + +#endif // End of include guard: BOARD_GPIO_H_ONCE diff --git a/g2core/board/G2v9/board_xio.h b/g2core/board/G2v9/board_xio.h index 09f20fef8..ea0a3fa7b 100755 --- a/g2core/board/G2v9/board_xio.h +++ b/g2core/board/G2v9/board_xio.h @@ -37,10 +37,10 @@ #include "MotateUSBCDC.h" #if USB_SERIAL_PORTS_EXPOSED == 1 -typedef Motate::USBDevice< Motate::USBCDC > XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC > XIOUSBDevice_t; #endif #if USB_SERIAL_PORTS_EXPOSED == 2 -typedef Motate::USBDevice XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC, Motate::USBCDC > XIOUSBDevice_t; #endif extern XIOUSBDevice_t usb; diff --git a/g2core/board/gquadratic.mk b/g2core/board/gquadratic.mk index 9527cdc11..35837519a 100755 --- a/g2core/board/gquadratic.mk +++ b/g2core/board/gquadratic.mk @@ -18,6 +18,12 @@ ifeq ("$(BOARD)","gquadratic-b") DEVICE_DEFINES += SETTINGS_FILE=${SETTINGS_FILE} endif +ifeq ("$(BOARD)","gquadratic-c") + BASE_BOARD=gquadratic + DEVICE_DEFINES += MOTATE_BOARD="gquadratic-c" + DEVICE_DEFINES += SETTINGS_FILE=${SETTINGS_FILE} +endif + ########## # The general gquadratic BASE_BOARD. @@ -25,16 +31,16 @@ endif ifeq ("$(BASE_BOARD)","gquadratic") _BOARD_FOUND = 1 - DEVICE_DEFINES += MOTATE_CONFIG_HAS_USBSERIAL=0 + DEVICE_DEFINES += MOTATE_CONFIG_HAS_USBSERIAL=1 ENABLE_TCM=1 - FIRST_LINK_SOURCES += $(sort $(wildcard ${MOTATE_PATH}/Atmel_sam_common/*.cpp)) $(sort $(wildcard ${MOTATE_PATH}/Atmel_sams70/*.cpp)) + FIRST_LINK_SOURCES += $(sort $(wildcard ${MOTATE_PATH}/Atmel_sam_common/*.cpp)) $(sort $(wildcard ${MOTATE_PATH}/Atmel_sams70/*.cpp) $(wildcard ${BOARD_PATH}/*.cpp)) CHIP = SAMS70N19 export CHIP CHIP_LOWERCASE = sams70n19 BOARD_PATH = ./board/gquadratic - SOURCE_DIRS += ${BOARD_PATH} device/step_dir_driver device/step_dir_hobbyservo device/neopixel + SOURCE_DIRS += ${BOARD_PATH} device/trinamic device/step_dir_hobbyservo device/max31865 device/neopixel PLATFORM_BASE = ${MOTATE_PATH}/platform/atmel_sam include $(PLATFORM_BASE).mk diff --git a/g2core/board/gquadratic/hardware.cpp b/g2core/board/gquadratic/0_hardware.cpp similarity index 98% rename from g2core/board/gquadratic/hardware.cpp rename to g2core/board/gquadratic/0_hardware.cpp index d3674a2ee..465c7175d 100755 --- a/g2core/board/gquadratic/hardware.cpp +++ b/g2core/board/gquadratic/0_hardware.cpp @@ -73,6 +73,10 @@ namespace LEDs { } #endif // EXPERIMENTAL_NEOPIXEL_SUPPORT +#if QUADRATIC_REVISION == 'C' +HOT_DATA SPIBus_used_t spiBus; +#endif + /* * hardware_init() - lowest level hardware init */ @@ -82,6 +86,10 @@ void hardware_init() board_hardware_init(); // external_clk_pin = 0; // Force external clock to 0 for now. +#if QUADRATIC_REVISION == 'C' + spiBus.init(); +#endif + #if EXPERIMENTAL_NEOPIXEL_SUPPORT == 1 for (uint8_t pixel = 0; pixel < LEDs::rgbw_leds.count; pixel++) { LEDs::display_color[pixel].startTransition(100, 0, 0, 0); diff --git a/g2core/board/gquadratic/board_gpio.cpp b/g2core/board/gquadratic/board_gpio.cpp new file mode 100644 index 000000000..614f4e0e6 --- /dev/null +++ b/g2core/board/gquadratic/board_gpio.cpp @@ -0,0 +1,89 @@ +/* + * gpio.cpp - digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2107 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Switch Modes + * + * The switches are considered to be homing switches when cycle_state is + * CYCLE_HOMING. At all other times they are treated as limit switches: + * - Hitting a homing switch puts the current move into feedhold + * - Hitting a limit switch causes the machine to shut down and go into lockdown until reset + * + * The normally open switch modes (NO) trigger an interrupt on the falling edge + * and lockout subsequent interrupts for the defined lockout period. This approach + * beats doing debouncing as an integration as switches fire immediately. + * + * The normally closed switch modes (NC) trigger an interrupt on the rising edge + * and lockout subsequent interrupts for the defined lockout period. Ditto on the method. + */ + +#include "../../g2core.h" // #1 +#include "config.h" // #2 +#include "gpio.h" +#include "hardware.h" +#include "canonical_machine.h" + +#include "text_parser.h" +#include "controller.h" +#include "util.h" +#include "report.h" +#include "xio.h" + +#include "MotateTimers.h" + +/**** Setup Actual Objects ****/ + +gpioDigitalInputPin> din1 {DI1_ENABLED, DI1_POLARITY, 1, DI1_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din2 {DI2_ENABLED, DI2_POLARITY, 2, DI2_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din3 {DI3_ENABLED, DI3_POLARITY, 3, DI3_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din4 {DI4_ENABLED, DI4_POLARITY, 4, DI4_EXTERNAL_NUMBER}; + +gpioDigitalOutputPin> dout1 { DO1_ENABLED, DO1_POLARITY, DO1_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout2 { DO2_ENABLED, DO2_POLARITY, DO2_EXTERNAL_NUMBER, (uint32_t)200000 }; + +/**** Setup Arrays - these are extern and MUST match the board_gpio.h ****/ + +gpioDigitalInput* const d_in[] = {&din1, &din2, &din3, &din4}; +gpioDigitalOutput* const d_out[] = {&dout1, &dout2}; +// not yet used +// gpioAnalogInput* a_in[A_IN_CHANNELS]; +// gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +/************************************************************************************ + **** CODE ************************************************************************** + ************************************************************************************/ +/* + * gpio_reset() - reset inputs and outputs (no initialization) + */ + + +void outputs_reset(void) { + // nothing to do +} + +void inputs_reset(void) { + // nothing to do +} diff --git a/g2core/board/gquadratic/board_gpio.h b/g2core/board/gquadratic/board_gpio.h new file mode 100644 index 000000000..c596fc545 --- /dev/null +++ b/g2core/board/gquadratic/board_gpio.h @@ -0,0 +1,71 @@ +/* + * gpio.h - Digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef BOARD_GPIO_H_ONCE +#define BOARD_GPIO_H_ONCE + +// this file is included from the bottom of gpio.h, but we do this for completeness +#include "../../gpio.h" + +/* + * GPIO defines + */ +//--- change as required for board and switch hardware ---// + +#define D_IN_CHANNELS 4 // number of digital inputs supported +#define D_OUT_CHANNELS 2 // number of digital outputs supported +#define A_IN_CHANNELS 0 // number of analog inputs supported +#define A_OUT_CHANNELS 0 // number of analog outputs supported + +#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing + +/* + * The GPIO objects themselves - this must match up with board_gpio.cpp! + */ + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; +// extern gpioAnalogInput* a_in[A_IN_CHANNELS]; +// extern gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +// prepare the objects as externs (for config_app to not bloat) +using Motate::IRQPin; +using Motate::PWMOutputPin; +using Motate::PWMLikeOutputPin; +template +using OutputType = typename std::conditional, PWMLikeOutputPin>::type; + +extern gpioDigitalInputPin> din1; +extern gpioDigitalInputPin> din2; +extern gpioDigitalInputPin> din3; +extern gpioDigitalInputPin> din4; + +extern gpioDigitalOutputPin> dout1; +extern gpioDigitalOutputPin> dout2; + + +#endif // End of include guard: BOARD_GPIO_H_ONCE diff --git a/g2core/board/gquadratic/board_stepper.cpp b/g2core/board/gquadratic/board_stepper.cpp index bc927558a..cfe461447 100755 --- a/g2core/board/gquadratic/board_stepper.cpp +++ b/g2core/board/gquadratic/board_stepper.cpp @@ -2,8 +2,8 @@ * board_stepper.cpp - board-specific code for stepper.cpp * This file is part of the g2core project * - * Copyright (c) 2016 Alden S. Hart, Jr. - * Copyright (c) 2016 Robert Giseburt + * Copyright (c) 2016-2018 Alden S. Hart, Jr. + * Copyright (c) 2016-2018 Robert Giseburt * * This file ("the software") is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 as published by the @@ -29,54 +29,48 @@ #include "board_stepper.h" // These are identical to board_stepper.h, except for the word "extern" -StepDirStepper - motor_1{}; + motor_1 {}; -StepDirStepper - motor_2{}; + motor_2 {}; +#endif // QUADRATIC_REVISION == 'B' -StepDirHobbyServo motor_3; +#if QUADRATIC_REVISION == 'C' +#warning setting up trinamics +// Motate::SPIChipSelectPin motor_1_cs; +HOT_DATA Trinamic2130 + motor_1 {spiBus, Motate::SPIChipSelectPin{}}; -// StepDirStepper< -// Motate::kSocket4_StepPinNumber, -// Motate::kSocket4_DirPinNumber, -// Motate::kSocket4_EnablePinNumber, -// Motate::kSocket4_Microstep_0PinNumber, -// Motate::kSocket4_Microstep_1PinNumber, -// Motate::kSocket4_Microstep_2PinNumber, -// Motate::kSocket4_VrefPinNumber> motor_4 {}; -// -// StepDirStepper< -// Motate::kSocket5_StepPinNumber, -// Motate::kSocket5_DirPinNumber, -// Motate::kSocket5_EnablePinNumber, -// Motate::kSocket5_Microstep_0PinNumber, -// Motate::kSocket5_Microstep_1PinNumber, -// Motate::kSocket5_Microstep_2PinNumber, -// Motate::kSocket5_VrefPinNumber> motor_5 {}; +// Motate::SPIChipSelectPin motor_2_cs; +HOT_DATA Trinamic2130 + motor_2 {spiBus, Motate::SPIChipSelectPin{}}; +#endif // QUADRATIC_REVISION == 'C' -// StepDirStepper< -// Motate::kSocket6_StepPinNumber, -// Motate::kSocket6_DirPinNumber, -// Motate::kSocket6_EnablePinNumber, -// Motate::kSocket6_Microstep_0PinNumber, -// Motate::kSocket6_Microstep_1PinNumber, -// Motate::kSocket6_Microstep_2PinNumber, -// Motate::kSocket6_VrefPinNumber> motor_6 {}; -Stepper* Motors[MOTORS] = {&motor_1, &motor_2, &motor_3}; +HOT_DATA StepDirHobbyServo motor_3; + + +Stepper* const Motors[MOTORS] = {&motor_1, &motor_2, &motor_3}; void board_stepper_init() { for (uint8_t motor = 0; motor < MOTORS; motor++) { Motors[motor]->init(); } diff --git a/g2core/board/gquadratic/board_stepper.h b/g2core/board/gquadratic/board_stepper.h index 6e044efa3..8072ff338 100755 --- a/g2core/board/gquadratic/board_stepper.h +++ b/g2core/board/gquadratic/board_stepper.h @@ -29,9 +29,9 @@ #define BOARD_STEPPER_H_ONCE #include "hardware.h" // for MOTORS -#include "step_dir_driver.h" -#include "step_dir_hobbyservo.h" +#if QUADRATIC_REVISION == 'B' +#include "step_dir_driver.h" extern StepDirStepper motor_2; +#endif // QUADRATIC_REVISION == 'B' - extern StepDirHobbyServo motor_3; +#if QUADRATIC_REVISION == 'C' +#include "tmc2130.h" +extern Trinamic2130 + motor_1; +extern Trinamic2130 + motor_2; +#endif // QUADRATIC_REVISION == 'C' -// extern StepDirStepper< -// Motate::kSocket5_StepPinNumber, -// Motate::kSocket5_DirPinNumber, -// Motate::kSocket5_EnablePinNumber, -// Motate::kSocket5_Microstep_0PinNumber, -// Motate::kSocket5_Microstep_1PinNumber, -// Motate::kSocket5_Microstep_2PinNumber, -// Motate::kSocket5_VrefPinNumber> motor_5; -// -// extern StepDirStepper< -// Motate::kSocket6_StepPinNumber, -// Motate::kSocket6_DirPinNumber, -// Motate::kSocket6_EnablePinNumber, -// Motate::kSocket6_Microstep_0PinNumber, -// Motate::kSocket6_Microstep_1PinNumber, -// Motate::kSocket6_Microstep_2PinNumber, -// Motate::kSocket6_VrefPinNumber> motor_6 {}; +#include "step_dir_hobbyservo.h" +extern StepDirHobbyServo motor_3; -extern Stepper* Motors[MOTORS]; +extern Stepper* const Motors[MOTORS]; void board_stepper_init(); diff --git a/g2core/board/gquadratic/board_xio.cpp b/g2core/board/gquadratic/board_xio.cpp index c48356be1..d05ce1ff8 100755 --- a/g2core/board/gquadratic/board_xio.cpp +++ b/g2core/board/gquadratic/board_xio.cpp @@ -71,6 +71,7 @@ void board_hardware_init(void) // called 1st #if XIO_HAS_USB // Init USB usb.attach(); + usb.handleVbusChange(/*force:*/ true); #endif // XIO_HAS_USB } diff --git a/g2core/board/gquadratic/board_xio.h b/g2core/board/gquadratic/board_xio.h index 09f20fef8..659f68a4a 100755 --- a/g2core/board/gquadratic/board_xio.h +++ b/g2core/board/gquadratic/board_xio.h @@ -36,11 +36,13 @@ #include "MotateUSB.h" #include "MotateUSBCDC.h" +typedef Motate::USBDeviceHardwareVBus> USBDeviceHardware_t; + #if USB_SERIAL_PORTS_EXPOSED == 1 -typedef Motate::USBDevice< Motate::USBCDC > XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware_t, Motate::USBCDC > XIOUSBDevice_t; #endif #if USB_SERIAL_PORTS_EXPOSED == 2 -typedef Motate::USBDevice XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware_t, Motate::USBCDC, Motate::USBCDC > XIOUSBDevice_t; #endif extern XIOUSBDevice_t usb; diff --git a/g2core/board/gquadratic/gquadratic-b-pinout.h b/g2core/board/gquadratic/gquadratic-b-pinout.h index 6eab01841..7eb8946bb 100755 --- a/g2core/board/gquadratic/gquadratic-b-pinout.h +++ b/g2core/board/gquadratic/gquadratic-b-pinout.h @@ -2,8 +2,8 @@ * gquadratic-b-pinout.h - board pinout specification * This file is part of the g2core project * - * Copyright (c) 2016 Robert Giseburt - * Copyright (c) 2016 Alden S. Hart Jr. + * Copyright (c) 2016-2018 Robert Giseburt + * Copyright (c) 2016-2018 Alden S. Hart Jr. * * This file is part of the Motate Library. * @@ -108,6 +108,8 @@ #define OUTPUT12_PWM 0 // Unused #define OUTPUT13_PWM 0 // Unused +#define QUADRATIC_REVISION 'B' + namespace Motate { // Arduino pin name & function diff --git a/g2core/board/gquadratic/gquadratic-c-pinout.h b/g2core/board/gquadratic/gquadratic-c-pinout.h new file mode 100644 index 000000000..8c77c9d35 --- /dev/null +++ b/g2core/board/gquadratic/gquadratic-c-pinout.h @@ -0,0 +1,205 @@ +/* + * gquadratic-c-pinout.h - board pinout specification + * This file is part of the g2core project + * + * Copyright (c) 2018 Robert Giseburt + * Copyright (c) 2018 Alden S. Hart Jr. + * + * This file is part of the Motate Library. + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef GQUADRATIC_C_PINOUT_H +#define GQUADRATIC_C_PINOUT_H + +/* + * USAGE NOTES + * + * Read this first: + * https://github.com/synthetos/g2/wiki/Adding-a-new-G2-board-(or-revision)-to-G2#making-a-new-pin-assignment + * + * USAGE: + * + * This file is lays out all the pin capabilities of the SAM3X8C organized by pin number. + * Each pin has its associated functions listed at the bottom of the file, and is essentially + * immutable for each processor. + * + * To use, assign Motate pin numbers to the first value in the _MAKE_MOTATE_PIN() macro. + * ALL PINS MUST BE ASSIGNED A NUMBER, even if they are not used. There will NOT be a + * code-size or speed penalty for unused pins, but the WILL be a compiler-failure for + * unassigned pins. This new restriction allows for simplification of linkages deep in + * Motate. + */ +/* See motate_pin_assignments.h for pin names to be used int he rest of the G2 code. + * EXAMPLES: + * + * *** Vanilla pin example *** + * + * _MAKE_MOTATE_PIN(4, A, 'A', 27); // SPI0_SCKPinNumber + * + * This assigns Motate pin 4 to Port A, pin 27 (A27) + * Look in motate_pin_assignments.h to see that this is kSPI_SCKPinNumber + * + * ** Other pin functions *** + * + * Please look in /platform/atmel_sam/motate_chip_pin_functions.h + */ + + +#include + +// We don't have all of the inputs, so we have to indicate as much: +#define INPUT1_AVAILABLE 1 +#define INPUT2_AVAILABLE 1 +#define INPUT3_AVAILABLE 1 +#define INPUT4_AVAILABLE 1 +#define INPUT5_AVAILABLE 0 +#define INPUT6_AVAILABLE 0 +#define INPUT7_AVAILABLE 0 +#define INPUT8_AVAILABLE 0 +#define INPUT9_AVAILABLE 0 +#define INPUT10_AVAILABLE 0 +#define INPUT11_AVAILABLE 0 +#define INPUT12_AVAILABLE 0 +#define INPUT13_AVAILABLE 0 + +#define XIO_HAS_USB 1 +#define XIO_HAS_UART 1 +#define XIO_HAS_SPI 0 +#define XIO_HAS_I2C 0 + +#define TEMPERATURE_OUTPUT_ON 0 // NO ADC yet + +// Some pins, if the PWM capability is turned on, it will cause timer conflicts. +// So we have to explicitly enable them as PWM pins. +// Generated with: +// perl -e 'for($i=1;$i<14;$i++) { print "#define OUTPUT${i}_PWM 0\n";}' +#define OUTPUT1_PWM 1 // TC0.0 +#define OUTPUT2_PWM 1 // PWM0.0 +#define OUTPUT3_PWM 1 // TC0.1 +#define OUTPUT4_PWM 1 // PWM1.3 +#define OUTPUT5_PWM 0 // unused +#define OUTPUT6_PWM 0 // unused +#define OUTPUT7_PWM 0 // unused +#define OUTPUT8_PWM 0 // unused +#define OUTPUT9_PWM 0 // unused +#define OUTPUT10_PWM 0 // unused +#define OUTPUT11_PWM 0 // unused +#define OUTPUT12_PWM 0 // Unused +#define OUTPUT13_PWM 0 // Unused + +#define QUADRATIC_REVISION 'C' + +namespace Motate { + +// Arduino pin name & function +_MAKE_MOTATE_PIN(kOutput1_PinNumber, 'A', 0); // TC0.0 or PWM0 +_MAKE_MOTATE_PIN(kOutput2_PinNumber, 'A', 1); // TC0.1 or PWM1 +_MAKE_MOTATE_PIN(kUnassigned1, 'A', 2); // PWM1 +_MAKE_MOTATE_PIN(kI2C1_SDAPinNumber, 'A', 3); // +_MAKE_MOTATE_PIN(kI2C1_SCLPinNumber, 'A', 4); // +_MAKE_MOTATE_PIN(kSocket2_StepPinNumber, 'A', 5); // +_MAKE_MOTATE_PIN(kUnassigned2, 'A', 6); // Missing in 100-pin package +_MAKE_MOTATE_PIN(kUnassigned3, 'A', 7); // +_MAKE_MOTATE_PIN(kUnassigned4, 'A', 8); // +_MAKE_MOTATE_PIN(kSerial_RXPinNumber, 'A', 9); // +_MAKE_MOTATE_PIN(kSerial_TXPinNumber, 'A', 10); // +_MAKE_MOTATE_PIN(kSocket1_StepPinNumber, 'A', 11); // +_MAKE_MOTATE_PIN(kUnassigned5, 'A', 12); // +_MAKE_MOTATE_PIN(kUnassigned6, 'A', 13); // +_MAKE_MOTATE_PIN(kUnassigned7, 'A', 14); // +_MAKE_MOTATE_PIN(kUnassigned8, 'A', 15); // +_MAKE_MOTATE_PIN(kUnassigned9, 'A', 16); // +_MAKE_MOTATE_PIN(kUnassigned10, 'A', 17); // +_MAKE_MOTATE_PIN(kUnassigned11, 'A', 18); // +_MAKE_MOTATE_PIN(kUnassigned12, 'A', 19); // +_MAKE_MOTATE_PIN(kUnassigned13, 'A', 20); // +_MAKE_MOTATE_PIN(kUnassigned14, 'A', 21); // +_MAKE_MOTATE_PIN(kUnassigned15, 'A', 22); // +_MAKE_MOTATE_PIN(kUnassigned16, 'A', 23); // +_MAKE_MOTATE_PIN(kInput5_PinNumber, 'A', 24); // DIAG0 +_MAKE_MOTATE_PIN(kUnassigned17, 'A', 25); // +_MAKE_MOTATE_PIN(kSocket1_DirPinNumber, 'A', 26); // +_MAKE_MOTATE_PIN(kSocket2_EnablePinNumber, 'A', 27); // TC2.1 +_MAKE_MOTATE_PIN(kSerial_CTSPinNumber, 'A', 28); // +_MAKE_MOTATE_PIN(kUnassigned18, 'A', 29); // Missing in 100-pin package +_MAKE_MOTATE_PIN(kServo1_PinNumber, 'A', 30); // PWM2 - kOutput4_PinNumber +_MAKE_MOTATE_PIN(kInput4_PinNumber, 'A', 31); // + +_MAKE_MOTATE_PIN(kUnassigned19, 'B', 0); // +_MAKE_MOTATE_PIN(kUnassigned20, 'B', 1); // +_MAKE_MOTATE_PIN(kSocket3_SPISlaveSelectPinNumber, 'B', 2); // +_MAKE_MOTATE_PIN(kUnassigned21, 'B', 3); // +//_MAKE_MOTATE_PIN( , 'B', 4); // TDI +//_MAKE_MOTATE_PIN( , 'B', 5); // TRACESDO +//_MAKE_MOTATE_PIN( , 'B', 6); // SWDIO +//_MAKE_MOTATE_PIN( , 'B', 7); // SWDCLK +//_MAKE_MOTATE_PIN( , 'B', 8); // XOUT +//_MAKE_MOTATE_PIN( , 'B', 9); // XIN +//_MAKE_MOTATE_PIN( , 'B', 10); // USB_D- +//_MAKE_MOTATE_PIN( , 'B', 11); // USB_D+ +//_MAKE_MOTATE_PIN( , 'B', 12); // ERASE +_MAKE_MOTATE_PIN(kUnassigned22, 'B', 13); // + +_MAKE_MOTATE_PIN(kUSBVBUS_PinNumber, 'D', 0); // USB_VBUS +_MAKE_MOTATE_PIN(kInput1_PinNumber, 'D', 1); // +_MAKE_MOTATE_PIN(kInput2_PinNumber, 'D', 2); // +_MAKE_MOTATE_PIN(kUnassigned23, 'D', 3); // +_MAKE_MOTATE_PIN(kUnassigned24, 'D', 4); // +_MAKE_MOTATE_PIN(kUnassigned25, 'D', 5); // +_MAKE_MOTATE_PIN(kInput3_PinNumber, 'D', 6); // +_MAKE_MOTATE_PIN(kSerial_RTSPinNumber, 'D', 7); // +_MAKE_MOTATE_PIN(kOutput5_PinNumber, 'D', 8); // INTERRUPT_OUT +_MAKE_MOTATE_PIN(kUnassigned26, 'D', 9); // +_MAKE_MOTATE_PIN(kUnassigned27, 'D', 10); // +_MAKE_MOTATE_PIN(kLED_RGBWPixelPinNumber, 'D', 11); // PWM0 - kOutput3_PinNumber +_MAKE_MOTATE_PIN(kSocket4_SPISlaveSelectPinNumber, 'D', 12); // +_MAKE_MOTATE_PIN(kUnassigned28, 'D', 13); // +_MAKE_MOTATE_PIN(kUnassigned29, 'D', 14); // +_MAKE_MOTATE_PIN(kOutputSAFE_PinNumber, 'D', 15); // +_MAKE_MOTATE_PIN(kUnassigned30, 'D', 16); // +_MAKE_MOTATE_PIN(kUnassigned31, 'D', 17); // +_MAKE_MOTATE_PIN(kUnassigned32, 'D', 18); // +_MAKE_MOTATE_PIN(kUnassigned33, 'D', 19); // +_MAKE_MOTATE_PIN(kSPI0_MISOPinNumber, 'D', 20); // +_MAKE_MOTATE_PIN(kSPI0_MOSIPinNumber, 'D', 21); // +_MAKE_MOTATE_PIN(kSPI0_SCKPinNumber, 'D', 22); // +_MAKE_MOTATE_PIN(kUnassigned34, 'D', 23); // Missing in 100-pin package +_MAKE_MOTATE_PIN(kInput6_PinNumber, 'D', 24); // DIAG1 +_MAKE_MOTATE_PIN(kSocket1_SPISlaveSelectPinNumber, 'D', 25); // +_MAKE_MOTATE_PIN(kSocket1_EnablePinNumber, 'D', 26); // +_MAKE_MOTATE_PIN(kSocket2_SPISlaveSelectPinNumber, 'D', 27); // +_MAKE_MOTATE_PIN(kSocket2_DirPinNumber, 'D', 28); // +_MAKE_MOTATE_PIN(kUnassigned35, 'D', 29); // Missing in 100-pin package +_MAKE_MOTATE_PIN(kLEDPWM_PinNumber, 'D', 30); // +_MAKE_MOTATE_PIN(kUnassigned36, 'D', 31); // + +} // namespace Motate + +// We then allow each chip-type to have it's onw function definitions +// that will refer to these pin assignments. +#include "motate_chip_pin_functions.h" + +#endif + +// GQUADRATIC_C_PINOUT_H diff --git a/g2core/board/gquadratic/hardware.h b/g2core/board/gquadratic/hardware.h index 9c3b27504..827346fb4 100644 --- a/g2core/board/gquadratic/hardware.h +++ b/g2core/board/gquadratic/hardware.h @@ -29,6 +29,7 @@ */ #include "config.h" +#include "settings.h" #include "error.h" #ifndef HARDWARE_H_ONCE @@ -70,6 +71,11 @@ enum hwPlatform { // ARM specific code start here #include "MotatePins.h" +#if QUADRATIC_REVISION == 'C' +#define MOTOR_1_IS_TRINAMIC +#define MOTOR_2_IS_TRINAMIC +#include "MotateSPI.h" +#endif #include "MotateTimers.h" // for TimerChanel<> and related... #include "MotateServiceCall.h" // for ServiceCall<> @@ -89,43 +95,16 @@ using Motate::OutputPin; #define SYS_ID_DIGITS 12 // actual digits in system ID (up to 16) #define SYS_ID_LEN 24 // total length including dashes and NUL -/************************************************************************************ - **** ARM SAM3X8E SPECIFIC HARDWARE ************************************************* - ************************************************************************************/ - -/**** Resource Assignment via Motate **** - * - * This section defines resource usage for pins, timers, PWM channels, communications - * and other resources. Please refer to /motate/utility/SamPins.h, SamTimers.h and - * other files for pinouts and other configuration details. - * - * Commenting out or #ifdef'ing out definitions below will cause the compiler to - * drop references to these resources from the compiled code. This will reduce - * compiled code size and runtime CPU cycles. E.g. if you are compiling for a 3 motor, - * XYZ axis config commenting out the higher motors and axes here will remove them - * from later code (using the motate .isNull() test). - */ - -/* Interrupt usage and priority - * - * The following interrupts are defined w/indicated priorities - * - * 0 DDA_TIMER (9) for step pulse generation - * 1 DWELL_TIMER (10) for dwell timing - * 2 LOADER software generated interrupt (STIR / SGI) - * 3 Serial read character interrupt - * 4 EXEC software generated interrupt (STIR / SGI) - * 5 Serial write character interrupt - */ - /**** Stepper DDA and dwell timer settings ****/ //#define FREQUENCY_DDA 200000UL // Hz step frequency. Interrupts actually fire at 2x (400 KHz) -#define FREQUENCY_DDA 200000UL // Hz step frequency. Interrupts actually fire at 2x (300 KHz) +#define FREQUENCY_DDA 400000UL // Hz step frequency. Interrupts actually fire at 2x (300 KHz) #define FREQUENCY_DWELL 1000UL #define MIN_SEGMENT_MS ((float)0.125) // S70 can handle much much smaller segements +#define PLANNER_BUFFER_POOL_SIZE (60) + /**** Motate Definitions ****/ // Timer definitions. See stepper.h and other headers for setup @@ -137,14 +116,17 @@ typedef TimerChannel<11, 0> fwd_plan_timer_type; // request exec timer in step pin_number indicator_led_pin_num = Motate::kLEDPWM_PinNumber; static OutputPin IndicatorLed; +/**** SPI Setup ****/ +#if QUADRATIC_REVISION == 'C' +Motate::service_call_number kSPI_ServiceCallNumber = 3; + +typedef Motate::SPIBus SPIBus_used_t; +extern SPIBus_used_t spiBus; + +#endif + /**** Motate Global Pin Allocations ****/ -// static OutputPin spi_ss1_pin; -// static OutputPin spi_ss2_pin; -// static OutputPin spi_ss3_pin; -// static OutputPin spi_ss4_pin; -// static OutputPin spi_ss5_pin; -// static OutputPin spi_ss6_pin; static OutputPin kinen_sync_pin; static OutputPin grbl_reset_pin; @@ -152,14 +134,12 @@ static OutputPin grbl_feedhold_pin; static OutputPin grbl_cycle_start_pin; static OutputPin motor_common_enable_pin; -static OutputPin spindle_enable_pin; -static OutputPin spindle_dir_pin; - -// NOTE: In the v9 and the Due the flood and mist coolants are mapped to a the same pin -// static OutputPin coolant_enable_pin; -static OutputPin flood_enable_pin; -static OutputPin mist_enable_pin; +#define SPINDLE_OUTPUT_NUMBER 1 // drive our primary output as a spindle +#define SPINDLE_ENABLE_OUTPUT_NUMBER 2 // use output 2 as the enable line for the spindle +#define SPINDLE_DIRECTION_OUTPUT_NUMBER 0 // no direction control +#define MIST_ENABLE_OUTPUT_NUMBER 0 // no mist +#define FLOOD_ENABLE_OUTPUT_NUMBER 0 // no flood // Input pins are defined in gpio.cpp /******************************** diff --git a/g2core/board/gquadratic/motate_pin_assignments.h b/g2core/board/gquadratic/motate_pin_assignments.h index 0057a9e4c..57c099bb0 100755 --- a/g2core/board/gquadratic/motate_pin_assignments.h +++ b/g2core/board/gquadratic/motate_pin_assignments.h @@ -157,13 +157,14 @@ pin_number kDebug3_PinNumber = -1; // 116; //e Not the out-of-order numbering & pin_number kDebug4_PinNumber = -1; // 114; // END DEBUG PINS -pin_number kLED_USBRXPinNumber = 117; -pin_number kLED_USBTXPinNumber = 118; -pin_number kSD_CardDetectPinNumber = 119; -pin_number kSD_ChipSelectPinNumber = 120; -pin_number kInterlock_InPinNumber = 121; -pin_number kOutputSAFE_PinNumber = 122; // SAFE signal -pin_number kLEDPWM_PinNumber = 123; +pin_number kLED_USBRXPinNumber = 117; +pin_number kLED_USBTXPinNumber = 118; +pin_number kSD_CardDetectPinNumber = -1; +pin_number kSD_ChipSelectPinNumber = -1; +pin_number kUSBVBUS_PinNumber = 119; +pin_number kInterlock_InPinNumber = 121; +pin_number kOutputSAFE_PinNumber = 122; // SAFE signal +pin_number kLEDPWM_PinNumber = 123; pin_number kOutputInterrupt_PinNumber = 124; // to-host interrupt signal pin_number kLED_RGBWPixelPinNumber = 125; // 117; @@ -225,6 +226,8 @@ pin_number kServo3_PinNumber = 173; // // blank spots for unassigned pins - all unassigned pins need a unique number (do not re-use numbers) +pin_number kUnassigned40 = 215; +pin_number kUnassigned39 = 216; pin_number kUnassigned38 = 217; pin_number kUnassigned37 = 218; pin_number kUnassigned36 = 219; diff --git a/g2core/board/gquintic/board_gpio.cpp b/g2core/board/gquintic/board_gpio.cpp new file mode 100644 index 000000000..76f1ed70f --- /dev/null +++ b/g2core/board/gquintic/board_gpio.cpp @@ -0,0 +1,143 @@ +/* + * gpio.cpp - digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2107 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Switch Modes + * + * The switches are considered to be homing switches when cycle_state is + * CYCLE_HOMING. At all other times they are treated as limit switches: + * - Hitting a homing switch puts the current move into feedhold + * - Hitting a limit switch causes the machine to shut down and go into lockdown until reset + * + * The normally open switch modes (NO) trigger an interrupt on the falling edge + * and lockout subsequent interrupts for the defined lockout period. This approach + * beats doing debouncing as an integration as switches fire immediately. + * + * The normally closed switch modes (NC) trigger an interrupt on the rising edge + * and lockout subsequent interrupts for the defined lockout period. Ditto on the method. + */ + +#include "../../g2core.h" // #1 +#include "config.h" // #2 +#include "gpio.h" +#include "hardware.h" +#include "canonical_machine.h" + +#include "text_parser.h" +#include "controller.h" +#include "util.h" +#include "report.h" +#include "xio.h" + +#include "MotateTimers.h" + +/**** Setup Actual Objects ****/ + +gpioDigitalInputPin> din1 {DI1_ENABLED, DI1_POLARITY, 1, DI1_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din2 {DI2_ENABLED, DI2_POLARITY, 2, DI2_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din3 {DI3_ENABLED, DI3_POLARITY, 3, DI3_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din4 {DI4_ENABLED, DI4_POLARITY, 4, DI4_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din5 {DI5_ENABLED, DI5_POLARITY, 5, DI5_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din6 {DI6_ENABLED, DI6_POLARITY, 6, DI6_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din7 {DI7_ENABLED, DI7_POLARITY, 7, DI7_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din8 {DI8_ENABLED, DI8_POLARITY, 8, DI8_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din9 {DI9_ENABLED, DI9_POLARITY, 9, DI9_EXTERNAL_NUMBER}; +// gpioDigitalInputPin> din10 {DI10ENABLEDE, DI10_POLARITY, 10, DI10_EXTERNAL_NUMBER}; +// gpioDigitalInputPin> din11 {DI11ENABLEDE, DI11_POLARITY, 11, DI11_EXTERNAL_NUMBER}; +// gpioDigitalInputPin> din12 {DI12ENABLEDE, DI12_POLARITY, 12, DI12_EXTERNAL_NUMBER}; + +gpioDigitalInput* const d_in[] = {&din1, &din2, &din3, &din4, &din5, &din6, &din7, &din8, &din9}; + + +gpioDigitalOutputPin> dout1 { DO1_ENABLED, DO1_POLARITY, DO1_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout2 { DO2_ENABLED, DO2_POLARITY, DO2_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout3 { DO3_ENABLED, DO3_POLARITY, DO3_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout4 { DO4_ENABLED, DO4_POLARITY, DO4_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout5 { DO5_ENABLED, DO5_POLARITY, DO5_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout6 { DO6_ENABLED, DO6_POLARITY, DO6_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout7 { DO7_ENABLED, DO7_POLARITY, DO7_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout8 { DO8_ENABLED, DO8_POLARITY, DO8_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout9 { DO9_ENABLED, DO9_POLARITY, DO9_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout10 { DO10_ENABLED, DO10_POLARITY, DO10_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout11 { DO11_ENABLED, DO11_POLARITY, DO11_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout12 { DO12_ENABLED, DO12_POLARITY, DO12_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout13 { DO13_ENABLED, DO13_POLARITY, DO13_EXTERNAL_NUMBER, (uint32_t)200000 }; + +gpioDigitalOutput* const d_out[] = {&dout1, &dout2, &dout3, &dout4, &dout5, &dout6, &dout7, &dout8, &dout9, &dout10, &dout11, &dout12, &dout13}; + + +#if QUINTIC_REVISION == 'C' + +gpioAnalogInputPin> ai1 {AI1_ENABLED, gpioAnalogInput::AIN_TYPE_EXTERNAL, 1, AI1_EXTERNAL_NUMBER, spiBus, spiCSPinMux.getCS(5)}; +gpioAnalogInputPin> ai2 {AI2_ENABLED, gpioAnalogInput::AIN_TYPE_EXTERNAL, 2, AI2_EXTERNAL_NUMBER, spiBus, spiCSPinMux.getCS(6)}; +gpioAnalogInputPin> ai3 {AI3_ENABLED, gpioAnalogInput::AIN_TYPE_INTERNAL, 3, AI3_EXTERNAL_NUMBER}; +gpioAnalogInputPin> ai4 {AI4_ENABLED, gpioAnalogInput::AIN_TYPE_INTERNAL, 4, AI4_EXTERNAL_NUMBER}; + +gpioAnalogInput* const a_in[] = {&ain1, &ain2, &ain3, &ain4}; + +#endif // 'C' + +#if QUINTIC_REVISION == 'D' + +gpioAnalogInputPin> ai1 {AI1_ENABLED, gpioAnalogInput::AIN_TYPE_INTERNAL, 1, AI1_EXTERNAL_NUMBER}; +gpioAnalogInputPin> ai2 {AI2_ENABLED, gpioAnalogInput::AIN_TYPE_INTERNAL, 2, AI2_EXTERNAL_NUMBER}; +gpioAnalogInputPin> ai3 {AI3_ENABLED, gpioAnalogInput::AIN_TYPE_INTERNAL, 3, AI3_EXTERNAL_NUMBER}; +gpioAnalogInputPin> ai4 {AI4_ENABLED, gpioAnalogInput::AIN_TYPE_INTERNAL, 4, AI4_EXTERNAL_NUMBER}; + +gpioAnalogInput* const a_in[] = {&ai1, &ai2, &ai3, &ai4}; + +#endif // 'D' + + +/************************************************************************************ + **** CODE ************************************************************************** + ************************************************************************************/ + + + // Register a SysTick event to call start_sampling every temperature_sample_freq ms + const int16_t ain_sample_freq = 10; + int16_t ain_sample_counter = ain_sample_freq; + Motate::SysTickEvent ain_tick_event {[&] { + if (!--ain_sample_counter) { + ai1.startSampling(); + ai2.startSampling(); + ai3.startSampling(); + ai4.startSampling(); + ain_sample_counter = ain_sample_freq; + } + }, nullptr}; + +/* + * gpio_reset() - reset inputs and outputs (no initialization) + */ + +void outputs_reset(void) { + // nothing to do +} + +void inputs_reset(void) { + SysTickTimer.registerEvent(&ain_tick_event); +} diff --git a/g2core/board/gquintic/board_gpio.h b/g2core/board/gquintic/board_gpio.h new file mode 100644 index 000000000..1dedb7ad8 --- /dev/null +++ b/g2core/board/gquintic/board_gpio.h @@ -0,0 +1,197 @@ +/* + * gpio.h - Digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef BOARD_GPIO_H_ONCE +#define BOARD_GPIO_H_ONCE + +// this file is included from the bottom of gpio.h, but we do this for completeness +#include "../../gpio.h" +#include "hardware.h" + +/* + * GPIO defines + */ +//--- change as required for board and switch hardware ---// + +#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing + +/* + * The GPIO objects themselves - this must match up with board_gpio.cpp! + */ + +// prepare the objects as externs (for config_app to not bloat) +using Motate::IRQPin; +using Motate::PWMOutputPin; +using Motate::PWMLikeOutputPin; +using Motate::ADCPin; +using Motate::ADCDifferentialPair; +template +using OutputType = typename std::conditional, PWMLikeOutputPin>::type; + +#define D_IN_CHANNELS 9 // number of digital inputs supported + +extern gpioDigitalInputPin> din1; +extern gpioDigitalInputPin> din2; +extern gpioDigitalInputPin> din3; +extern gpioDigitalInputPin> din4; +extern gpioDigitalInputPin> din5; +extern gpioDigitalInputPin> din6; +extern gpioDigitalInputPin> din7; +extern gpioDigitalInputPin> din8; +extern gpioDigitalInputPin> din9; +// extern gpioDigitalInputPin> din10; +// extern gpioDigitalInputPin> din11; +// extern gpioDigitalInputPin> din12; + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; + + +#define D_OUT_CHANNELS 13 // number of digital outputs supported + +extern gpioDigitalOutputPin> dout1; +extern gpioDigitalOutputPin> dout2; +extern gpioDigitalOutputPin> dout3; +extern gpioDigitalOutputPin> dout4; +extern gpioDigitalOutputPin> dout5; +extern gpioDigitalOutputPin> dout6; +extern gpioDigitalOutputPin> dout7; +extern gpioDigitalOutputPin> dout8; +extern gpioDigitalOutputPin> dout9; +extern gpioDigitalOutputPin> dout10; +extern gpioDigitalOutputPin> dout11; +extern gpioDigitalOutputPin> dout12; +extern gpioDigitalOutputPin> dout13; + +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; + + +#if QUINTIC_REVISION == 'C' + +#define A_IN_CHANNELS 4 // number of analog inputs supported + +#include "device/max31865/max31865.h" +#define USING_A_MAX31865 1 + +#ifndef AI1_ENABLED +#define AI1_ENABLED IO_ENABLED +#endif +#ifndef AI1_TYPE +#define AI1_TYPE gpioAnalogInput::AIN_TYPE_EXTERNAL +#endif +#ifndef AI1_CIRCUIT +#define AI1_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_EXTERNAL +#endif +extern gpioAnalogInputPin> ain1; + +#ifndef AI2_ENABLED +#define AI2_ENABLED IO_ENABLED +#endif +#ifndef AI2_TYPE +#define AI2_TYPE gpioAnalogInput::AIN_TYPE_EXTERNAL +#endif +#ifndef AI2_CIRCUIT +#define AI2_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_EXTERNAL +#endif +extern gpioAnalogInputPin> ain2; + +#ifndef AI3_ENABLED +#define AI3_ENABLED IO_ENABLED +#endif +#ifndef AI3_TYPE +#define AI3_TYPE gpioAnalogInput::AIN_TYPE_INTERNAL +#endif +#ifndef AI3_CIRCUIT +#define AI3_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_PULLUP +#endif +extern gpioAnalogInputPin> ain3; + +#ifndef AI4_ENABLED +#define AI4_ENABLED IO_ENABLED +#endif +#ifndef AI4_TYPE +#define AI4_TYPE gpioAnalogInput::AIN_TYPE_INTERNAL +#endif +#ifndef AI4_CIRCUIT +#define AI4_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_PULLUP +#endif +extern gpioAnalogInputPin> ain4; + +#endif // 'C' + +#if QUINTIC_REVISION == 'D' + +#define A_IN_CHANNELS 4 // number of analog inputs supported + +#ifndef AI1_ENABLED +#define AI1_ENABLED IO_ENABLED +#endif +#ifndef AI1_TYPE +#define AI1_TYPE gpioAnalogInput::AIN_TYPE_INTERNAL +#endif +#ifndef AI1_CIRCUIT +#define AI1_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_CC_INV_OPAMP +#endif +extern gpioAnalogInputPin> ai1; + +#ifndef AI2_ENABLED +#define AI2_ENABLED IO_ENABLED +#endif +#ifndef AI2_TYPE +#define AI2_TYPE gpioAnalogInput::AIN_TYPE_INTERNAL +#endif +#ifndef AI2_CIRCUIT +#define AI2_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_CC_INV_OPAMP +#endif +extern gpioAnalogInputPin> ai2; + +#ifndef AI3_ENABLED +#define AI3_ENABLED IO_ENABLED +#endif +#ifndef AI3_TYPE +#define AI3_TYPE gpioAnalogInput::AIN_TYPE_INTERNAL +#endif +#ifndef AI3_CIRCUIT +#define AI3_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_INV_OPAMP +#endif +extern gpioAnalogInputPin> ai3; + +#ifndef AI4_ENABLED +#define AI4_ENABLED IO_ENABLED +#endif +#ifndef AI4_TYPE +#define AI4_TYPE gpioAnalogInput::AIN_TYPE_INTERNAL +#endif +#ifndef AI4_CIRCUIT +#define AI4_CIRCUIT gpioAnalogInput::AIN_CIRCUIT_INV_OPAMP +#endif +extern gpioAnalogInputPin> ai4; + +#endif // 'D' + +extern gpioAnalogInput* const a_in[A_IN_CHANNELS]; + +#endif // End of include guard: BOARD_GPIO_H_ONCE diff --git a/g2core/board/gquintic/board_stepper.cpp b/g2core/board/gquintic/board_stepper.cpp index 06028948d..a9606a768 100755 --- a/g2core/board/gquintic/board_stepper.cpp +++ b/g2core/board/gquintic/board_stepper.cpp @@ -2,8 +2,8 @@ * board_stepper.cpp - board-specific code for stepper.cpp * This file is part of the g2core project * - * Copyright (c) 2016 Alden S. Hart, Jr. - * Copyright (c) 2016 Robert Giseburt + * Copyright (c) 2016-2018 Alden S. Hart, Jr. + * Copyright (c) 2016-2018 Robert Giseburt * * This file ("the software") is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2 as published by the @@ -29,7 +29,7 @@ #include "board_stepper.h" // These are identical to board_stepper.h, except for the word "extern" and the initialization -#if defined(USING_A_MAX31865) && USING_A_MAX31865 == 1 +#if QUINTIC_REVISION == 'C' HOT_DATA Trinamic2130 motor_5; -Stepper* Motors[MOTORS] = {&motor_1, &motor_2, &motor_3, &motor_4, &motor_5}; -#else +Stepper* const Motors[MOTORS] = {&motor_1, &motor_2, &motor_3, &motor_4, &motor_5}; +#endif // 'C' + +#if QUINTIC_REVISION == 'D' HOT_DATA Trinamic2130 motor_6; -Stepper* Motors[MOTORS] = {&motor_1, &motor_2, &motor_3, &motor_4, &motor_5, &motor_6}; -#endif +Stepper* const Motors[MOTORS] = {&motor_1, &motor_2, &motor_3, &motor_4, &motor_5, &motor_6}; +#endif // 'D' void board_stepper_init() { for (uint8_t motor = 0; motor < MOTORS; motor++) { Motors[motor]->init(); } diff --git a/g2core/board/gquintic/board_stepper.h b/g2core/board/gquintic/board_stepper.h index 056bccc07..0204801db 100755 --- a/g2core/board/gquintic/board_stepper.h +++ b/g2core/board/gquintic/board_stepper.h @@ -33,7 +33,7 @@ #include "step_dir_hobbyservo.h" // These are identical to board_stepper.h, except for the word "extern" and the initialization -#if defined(USING_A_MAX31865) && USING_A_MAX31865 == 1 +#if QUINTIC_REVISION == 'C' extern Trinamic2130 motor_4; extern StepDirHobbyServo motor_5; -#else +#endif // 'C' + +#if QUINTIC_REVISION == 'D' extern Trinamic2130 motor_5; extern StepDirHobbyServo motor_6; -#endif +#endif // 'D' -extern Stepper* Motors[MOTORS]; +extern Stepper* const Motors[MOTORS]; void board_stepper_init(); diff --git a/g2core/board/gquintic/board_xio.cpp b/g2core/board/gquintic/board_xio.cpp index 551e7a10d..3fc7a7512 100755 --- a/g2core/board/gquintic/board_xio.cpp +++ b/g2core/board/gquintic/board_xio.cpp @@ -71,6 +71,7 @@ void board_hardware_init(void) // called 1st #if XIO_HAS_USB // Init USB usb.attach(); + usb.handleVbusChange(true); #endif // XIO_HAS_USB } diff --git a/g2core/board/gquintic/board_xio.h b/g2core/board/gquintic/board_xio.h index 09f20fef8..659f68a4a 100755 --- a/g2core/board/gquintic/board_xio.h +++ b/g2core/board/gquintic/board_xio.h @@ -36,11 +36,13 @@ #include "MotateUSB.h" #include "MotateUSBCDC.h" +typedef Motate::USBDeviceHardwareVBus> USBDeviceHardware_t; + #if USB_SERIAL_PORTS_EXPOSED == 1 -typedef Motate::USBDevice< Motate::USBCDC > XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware_t, Motate::USBCDC > XIOUSBDevice_t; #endif #if USB_SERIAL_PORTS_EXPOSED == 2 -typedef Motate::USBDevice XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware_t, Motate::USBCDC, Motate::USBCDC > XIOUSBDevice_t; #endif extern XIOUSBDevice_t usb; diff --git a/g2core/board/gquintic/gquintic-c-pinout.h b/g2core/board/gquintic/gquintic-c-pinout.h index d1c1659c4..ae7b7da3d 100755 --- a/g2core/board/gquintic/gquintic-c-pinout.h +++ b/g2core/board/gquintic/gquintic-c-pinout.h @@ -111,6 +111,8 @@ #define OUTPUT12_PWM 0 // Unused #define OUTPUT13_PWM 0 // Unused +#define QUINTIC_REVISION 'C' + namespace Motate { // Unused: @@ -171,7 +173,7 @@ _MAKE_MOTATE_PIN(kLED_USBRXPinNumber, 'B', 13); // LED_1 (Heartbeat _MAKE_MOTATE_PIN(kSocket4_SPISlaveSelectPinNumber, 'B', 14); // NOT CONNECTED -//_MAKE_MOTATE_PIN( 'D', 0); // USB_VBUS +_MAKE_MOTATE_PIN(kUSBVBUS_PinNumber 'D', 0); // USB_VBUS _MAKE_MOTATE_PIN(kInput9_PinNumber, 'D', 1); // _MAKE_MOTATE_PIN(kInput10_PinNumber, 'D', 2); // _MAKE_MOTATE_PIN(kInput8_PinNumber, 'D', 3); // diff --git a/g2core/board/gquintic/gquintic-d-pinout.h b/g2core/board/gquintic/gquintic-d-pinout.h index 72180b124..f24d81b20 100755 --- a/g2core/board/gquintic/gquintic-d-pinout.h +++ b/g2core/board/gquintic/gquintic-d-pinout.h @@ -111,6 +111,8 @@ #define OUTPUT12_PWM 0 // Unused #define OUTPUT13_PWM 0 // Unused +#define QUINTIC_REVISION 'D' + namespace Motate { // Unused: @@ -155,7 +157,7 @@ _MAKE_MOTATE_PIN(kInput1_PinNumber, 'A', 30); // _MAKE_MOTATE_PIN(kInput4_PinNumber, 'A', 31); // _MAKE_MOTATE_PIN(kSerial_CTSPinNumber, 'B', 0); // -_MAKE_MOTATE_PIN(kUnassigned9, 'B', 1); // AFEC1,0 +_MAKE_MOTATE_PIN(kUnassigned4, 'B', 1); // AFEC1,0 _MAKE_MOTATE_PIN(kSocket1_SPISlaveSelectPinNumber, 'B', 2); // _MAKE_MOTATE_PIN(kOutputSAFE_PinNumber, 'B', 3); // //_MAKE_MOTATE_PIN( , 'B', 4); // TDI @@ -168,10 +170,10 @@ _MAKE_MOTATE_PIN(kOutputSAFE_PinNumber, 'B', 3); // //_MAKE_MOTATE_PIN( , 'B', 11); // USB_D+ //_MAKE_MOTATE_PIN( , 'B', 12); // ERASE _MAKE_MOTATE_PIN(kLED_USBRXPinNumber, 'B', 13); // LED_1 (Heartbeat) - PWM2 -_MAKE_MOTATE_PIN(kUnassigned6, 'B', 14); // NOT CONNECTED +_MAKE_MOTATE_PIN(kUnassigned5, 'B', 14); // NOT CONNECTED -//_MAKE_MOTATE_PIN( 'D', 0); // USB_VBUS +_MAKE_MOTATE_PIN(kUSBVBUS_PinNumber, 'D', 0); // USB_VBUS _MAKE_MOTATE_PIN(kInput9_PinNumber, 'D', 1); // _MAKE_MOTATE_PIN(kInput10_PinNumber, 'D', 2); // _MAKE_MOTATE_PIN(kInput8_PinNumber, 'D', 3); // @@ -181,12 +183,12 @@ _MAKE_MOTATE_PIN(kInput5_PinNumber, 'D', 6); // _MAKE_MOTATE_PIN(kInput3_PinNumber, 'D', 7); // _MAKE_MOTATE_PIN(kInput2_PinNumber, 'D', 8); // ] _MAKE_MOTATE_PIN(kTMC2130_DIAG0_pinNumber, 'D', 9); // DIAG0 -_MAKE_MOTATE_PIN(kUnassigned4, 'D', 10); // +_MAKE_MOTATE_PIN(kUnassigned6, 'D', 10); // _MAKE_MOTATE_PIN(kSocket5_StepPinNumber, 'D', 11); // _MAKE_MOTATE_PIN(kSocket3_SPISlaveSelectPinNumber, 'D', 12); // _MAKE_MOTATE_PIN(kSocket5_DirPinNumber, 'D', 13); // _MAKE_MOTATE_PIN(kSocket5_EnablePinNumber, 'D', 14); // -_MAKE_MOTATE_PIN(kUnassigned5, 'D', 15); // +_MAKE_MOTATE_PIN(kUnassigned7, 'D', 15); // _MAKE_MOTATE_PIN(kSocket4_StepPinNumber, 'D', 16); // _MAKE_MOTATE_PIN(kSocket4_DirPinNumber, 'D', 17); // _MAKE_MOTATE_PIN(kSocket3_StepPinNumber, 'D', 18); // @@ -194,15 +196,15 @@ _MAKE_MOTATE_PIN(kSocket1_DirPinNumber, 'D', 19); // _MAKE_MOTATE_PIN(kSPI0_MISOPinNumber, 'D', 20); // _MAKE_MOTATE_PIN(kSPI0_MOSIPinNumber, 'D', 21); // _MAKE_MOTATE_PIN(kSPI0_SCKPinNumber, 'D', 22); // -_MAKE_MOTATE_PIN(kUnassigned7, 'D', 23); // NO PHYSICAL PIN +_MAKE_MOTATE_PIN(kUnassigned8, 'D', 23); // NO PHYSICAL PIN _MAKE_MOTATE_PIN(kSocket2_StepPinNumber, 'D', 24); // _MAKE_MOTATE_PIN(kSocket2_SPISlaveSelectPinNumber, 'D', 25); // _MAKE_MOTATE_PIN(kOutput9_PinNumber, 'D', 26); // PWM 2 _MAKE_MOTATE_PIN(kSocket4_SPISlaveSelectPinNumber, 'D', 27); // _MAKE_MOTATE_PIN(kSocket4_EnablePinNumber, 'D', 28); // -_MAKE_MOTATE_PIN(kUnassigned8, 'D', 29); // NO PHYSICAL PIN -_MAKE_MOTATE_PIN(kADC3_Neg_PinNumber, 'D', 30); // AFEC0,0 - was INTERRUPT_OUT -_MAKE_MOTATE_PIN(kUnassigned10, 'D', 31); // +_MAKE_MOTATE_PIN(kUnassigned9, 'D', 29); // NO PHYSICAL PIN +_MAKE_MOTATE_PIN(kUnassigned10, 'D', 30); // AFEC0,0 - was INTERRUPT_OUT +_MAKE_MOTATE_PIN(kUnassigned11, 'D', 31); // } // namespace Motate diff --git a/g2core/board/gquintic/hardware.h b/g2core/board/gquintic/hardware.h index 349818f9a..79ad75384 100644 --- a/g2core/board/gquintic/hardware.h +++ b/g2core/board/gquintic/hardware.h @@ -59,7 +59,7 @@ enum hwPlatform { #define AXES 6 // number of axes supported in this version #define HOMING_AXES 4 // number of axes that can be homed (assumes Zxyabc sequence) -#if defined(USING_A_MAX31865) && USING_A_MAX31865 == 1 +#if QUINTIC_REVISION == 'C' #define MOTORS 5 // number of motors on the board - 4 Trinamics + 1 servo #else #define MOTORS 6 // number of motors on the board - 5 Trinamics + 1 servo @@ -72,8 +72,7 @@ enum hwPlatform { #define MOTOR_2_IS_TRINAMIC #define MOTOR_3_IS_TRINAMIC #define MOTOR_4_IS_TRINAMIC -#if defined(USING_A_MAX31865) && USING_A_MAX31865 == 1 -#else +#if QUINTIC_REVISION == 'D' #define MOTOR_5_IS_TRINAMIC #endif //////////////////////////// @@ -147,14 +146,13 @@ typedef TimerChannel<9, 0> dda_timer_type; // stepper pulse generation in ste typedef TimerChannel<10, 0> exec_timer_type; // request exec timer in stepper.cpp typedef TimerChannel<11, 0> fwd_plan_timer_type; // request exec timer in stepper.cpp -Motate::service_call_number kSPI_ServiceCallNumber = 3; - /**** SPI Setup ****/ +Motate::service_call_number kSPI_ServiceCallNumber = 3; typedef Motate::SPIBus SPIBus_used_t; extern SPIBus_used_t spiBus; -typedef Motate::SPIChipSelectPinMux SPI_CS_PinMux_used_t; +typedef Motate::SPIChipSelectPinMux SPI_CS_PinMux_used_t; extern SPI_CS_PinMux_used_t spiCSPinMux; /**** Motate Global Pin Allocations ****/ @@ -169,13 +167,13 @@ static OutputPin grbl_feedhold_pin; static OutputPin grbl_cycle_start_pin; static OutputPin motor_common_enable_pin; -static OutputPin spindle_enable_pin; -static OutputPin spindle_dir_pin; +//static OutputPin spindle_enable_pin; +//static OutputPin spindle_dir_pin; // NOTE: In the v9 and the Due the flood and mist coolants are mapped to a the same pin //static OutputPin coolant_enable_pin; -static OutputPin flood_enable_pin; -static OutputPin mist_enable_pin; +//static OutputPin flood_enable_pin; +//static OutputPin mist_enable_pin; // Input pins are defined in gpio.cpp diff --git a/g2core/board/gquintic/motate_pin_assignments.h b/g2core/board/gquintic/motate_pin_assignments.h index 4be5c1dbb..cca19cd66 100755 --- a/g2core/board/gquintic/motate_pin_assignments.h +++ b/g2core/board/gquintic/motate_pin_assignments.h @@ -162,8 +162,9 @@ pin_number kDebug4_PinNumber = -1; // 114; pin_number kLED_USBRXPinNumber = 117; pin_number kLED_USBTXPinNumber = 118; -pin_number kSD_CardDetectPinNumber = 119; -pin_number kSD_ChipSelectPinNumber = 120; +pin_number kSD_CardDetectPinNumber = -1; +pin_number kSD_ChipSelectPinNumber = -1; +pin_number kUSBVBUS_PinNumber = 119; pin_number kInterlock_InPinNumber = 121; pin_number kOutputSAFE_PinNumber = 122; // SAFE signal pin_number kLEDPWM_PinNumber = 123; diff --git a/g2core/board/printrboardg2/board_gpio.cpp b/g2core/board/printrboardg2/board_gpio.cpp new file mode 100644 index 000000000..4daf011d8 --- /dev/null +++ b/g2core/board/printrboardg2/board_gpio.cpp @@ -0,0 +1,108 @@ +/* + * gpio.cpp - digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2107 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Switch Modes + * + * The switches are considered to be homing switches when cycle_state is + * CYCLE_HOMING. At all other times they are treated as limit switches: + * - Hitting a homing switch puts the current move into feedhold + * - Hitting a limit switch causes the machine to shut down and go into lockdown until reset + * + * The normally open switch modes (NO) trigger an interrupt on the falling edge + * and lockout subsequent interrupts for the defined lockout period. This approach + * beats doing debouncing as an integration as switches fire immediately. + * + * The normally closed switch modes (NC) trigger an interrupt on the rising edge + * and lockout subsequent interrupts for the defined lockout period. Ditto on the method. + */ + +#include "../../g2core.h" // #1 +#include "config.h" // #2 +#include "gpio.h" +#include "hardware.h" +#include "canonical_machine.h" + +#include "text_parser.h" +#include "controller.h" +#include "util.h" +#include "report.h" +#include "xio.h" + +#include "MotateTimers.h" + +/**** Setup Actual Objects ****/ + +gpioDigitalInputPin> din1 {DI1_MODE, 1}; +gpioDigitalInputPin> din2 {DI2_MODE, 2}; +gpioDigitalInputPin> din3 {DI3_MODE, 3}; +gpioDigitalInputPin> din4 {DI4_MODE, 4}; +gpioDigitalInputPin> din5 {DI5_MODE, 5}; +gpioDigitalInputPin> din6 {DI6_MODE, 6}; +gpioDigitalInputPin> din7 {DI7_MODE, 7}; +gpioDigitalInputPin> din8 {DI8_MODE, 8}; +gpioDigitalInputPin> din9 {DI9_MODE, 9}; +// gpioDigitalInputPin> din10 {DI10_MODE, 10}; +// gpioDigitalInputPin> din11 {DI11_MODE, 11}; +// gpioDigitalInputPin> din12 {DI12_MODE, 12}; + +gpioDigitalOutputPin> dout1 { DO1_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout2 { DO2_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout3 { DO3_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout4 { DO4_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout5 { DO5_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout6 { DO6_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout7 { DO7_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout8 { DO8_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout9 { DO9_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout10 { DO10_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout11 { DO11_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout12 { DO12_MODE, (uint32_t)200000 }; +gpioDigitalOutputPin> dout13 { DO13_MODE, (uint32_t)200000 }; + +/**** Setup Arrays - these are extern and MUST match the board_gpio.h ****/ + +gpioDigitalInput* const d_in[] = {&din1, &din2, &din3, &din4, &din5, &din6, &din7, &din8, &din9}; +gpioDigitalOutput* const d_out[] = {&dout1, &dout2, &dout3, &dout4, &dout5, &dout6, &dout7, &dout8, &dout9, &dout10, &dout11, &dout12, &dout13}; +// not yet used +// gpioAnalogInput* a_in[A_IN_CHANNELS]; +// gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +/************************************************************************************ + **** CODE ************************************************************************** + ************************************************************************************/ +/* + * gpio_reset() - reset inputs and outputs (no initialization) + */ + + +void outputs_reset(void) { + // nothing to do +} + +void inputs_reset(void) { + // nothing to do +} diff --git a/g2core/board/printrboardg2/board_gpio.h b/g2core/board/printrboardg2/board_gpio.h new file mode 100644 index 000000000..25a1cddcd --- /dev/null +++ b/g2core/board/printrboardg2/board_gpio.h @@ -0,0 +1,90 @@ +/* + * gpio.h - Digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef BOARD_GPIO_H_ONCE +#define BOARD_GPIO_H_ONCE + +// this file is included from the bottom of gpio.h, but we do this for completeness +#include "../../gpio.h" + +/* + * GPIO defines + */ +//--- change as required for board and switch hardware ---// + +#define D_IN_CHANNELS 9 // v9 // number of digital inputs supported +#define D_OUT_CHANNELS 13 // number of digital outputs supported +#define A_IN_CHANNELS 0 // number of analog inputs supported +#define A_OUT_CHANNELS 0 // number of analog outputs supported + +#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing + +/* + * The GPIO objects themselves - this must match up with board_gpio.cpp! + */ + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; +// extern gpioAnalogInput* a_in[A_IN_CHANNELS]; +// extern gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +// prepare the objects as externs (for config_app to not bloat) +using Motate::IRQPin; +using Motate::PWMOutputPin; +using Motate::PWMLikeOutputPin; +template +using OutputType = typename std::conditional, PWMLikeOutputPin>::type; + +extern gpioDigitalInputPin> din1; +extern gpioDigitalInputPin> din2; +extern gpioDigitalInputPin> din3; +extern gpioDigitalInputPin> din4; +extern gpioDigitalInputPin> din5; +extern gpioDigitalInputPin> din6; +extern gpioDigitalInputPin> din7; +extern gpioDigitalInputPin> din8; +extern gpioDigitalInputPin> din9; +// extern gpioDigitalInputPin> din10; +// extern gpioDigitalInputPin> din11; +// extern gpioDigitalInputPin> din12; + +extern gpioDigitalOutputPin> dout1; +extern gpioDigitalOutputPin> dout2; +extern gpioDigitalOutputPin> dout3; +extern gpioDigitalOutputPin> dout4; +extern gpioDigitalOutputPin> dout5; +extern gpioDigitalOutputPin> dout6; +extern gpioDigitalOutputPin> dout7; +extern gpioDigitalOutputPin> dout8; +extern gpioDigitalOutputPin> dout9; +extern gpioDigitalOutputPin> dout10; +extern gpioDigitalOutputPin> dout11; +extern gpioDigitalOutputPin> dout12; +extern gpioDigitalOutputPin> dout13; + + +#endif // End of include guard: BOARD_GPIO_H_ONCE diff --git a/g2core/board/printrboardg2/board_xio.h b/g2core/board/printrboardg2/board_xio.h index 75184f19a..50b69107c 100755 --- a/g2core/board/printrboardg2/board_xio.h +++ b/g2core/board/printrboardg2/board_xio.h @@ -38,10 +38,10 @@ #include "MotateUSBCDC.h" #if USB_SERIAL_PORTS_EXPOSED == 1 -typedef Motate::USBDevice< Motate::USBCDC > XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC > XIOUSBDevice_t; #endif #if USB_SERIAL_PORTS_EXPOSED == 2 -typedef Motate::USBDevice XIOUSBDevice_t; +typedef Motate::USBDevice< USBDeviceHardware, Motate::USBCDC, Motate::USBCDC > XIOUSBDevice_t; #endif extern XIOUSBDevice_t usb; diff --git a/g2core/board/sbv300/hardware.cpp b/g2core/board/sbv300/0_hardware.cpp similarity index 100% rename from g2core/board/sbv300/hardware.cpp rename to g2core/board/sbv300/0_hardware.cpp diff --git a/g2core/board/sbv300/board_gpio.cpp b/g2core/board/sbv300/board_gpio.cpp new file mode 100644 index 000000000..70f950b44 --- /dev/null +++ b/g2core/board/sbv300/board_gpio.cpp @@ -0,0 +1,111 @@ +/* + * gpio.cpp - digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2107 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Switch Modes + * + * The switches are considered to be homing switches when cycle_state is + * CYCLE_HOMING. At all other times they are treated as limit switches: + * - Hitting a homing switch puts the current move into feedhold + * - Hitting a limit switch causes the machine to shut down and go into lockdown until reset + * + * The normally open switch modes (NO) trigger an interrupt on the falling edge + * and lockout subsequent interrupts for the defined lockout period. This approach + * beats doing debouncing as an integration as switches fire immediately. + * + * The normally closed switch modes (NC) trigger an interrupt on the rising edge + * and lockout subsequent interrupts for the defined lockout period. Ditto on the method. + */ + +#include "../../g2core.h" // #1 +#include "config.h" // #2 +#include "gpio.h" +#include "hardware.h" +#include "canonical_machine.h" + +#include "text_parser.h" +#include "controller.h" +#include "util.h" +#include "report.h" +#include "xio.h" + +#include "MotateTimers.h" + +/**** Setup Actual Objects ****/ + +gpioDigitalInputPin> din1 {DI1_ENABLED, DI1_POLARITY, 1, DI1_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din2 {DI2_ENABLED, DI2_POLARITY, 2, DI2_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din3 {DI3_ENABLED, DI3_POLARITY, 3, DI3_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din4 {DI4_ENABLED, DI4_POLARITY, 4, DI4_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din5 {DI5_ENABLED, DI5_POLARITY, 5, DI5_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din6 {DI6_ENABLED, DI6_POLARITY, 6, DI6_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din7 {DI7_ENABLED, DI7_POLARITY, 7, DI7_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din8 {DI8_ENABLED, DI8_POLARITY, 8, DI8_EXTERNAL_NUMBER}; +gpioDigitalInputPin> din9 {DI9_ENABLED, DI9_POLARITY, 9, DI9_EXTERNAL_NUMBER}; +// gpioDigitalInputPin> din10 {DI10ENABLEDE, DI10_POLARITY, 10, DI10_EXTERNAL_NUMBER}; +// gpioDigitalInputPin> din11 {DI11ENABLEDE, DI11_POLARITY, 11, DI11_EXTERNAL_NUMBER}; +// gpioDigitalInputPin> din12 {DI12ENABLEDE, DI12_POLARITY, 12, DI12_EXTERNAL_NUMBER}; + +gpioDigitalInput* const d_in[] = {&din1, &din2, &din3, &din4, &din5, &din6, &din7, &din8, &din9}; + + +gpioDigitalOutputPin> dout1 { DO1_ENABLED, DO1_POLARITY, DO1_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout2 { DO2_ENABLED, DO2_POLARITY, DO2_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout3 { DO3_ENABLED, DO3_POLARITY, DO3_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout4 { DO4_ENABLED, DO4_POLARITY, DO4_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout5 { DO5_ENABLED, DO5_POLARITY, DO5_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout6 { DO6_ENABLED, DO6_POLARITY, DO6_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout7 { DO7_ENABLED, DO7_POLARITY, DO7_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout8 { DO8_ENABLED, DO8_POLARITY, DO8_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout9 { DO9_ENABLED, DO9_POLARITY, DO9_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout10 { DO10_ENABLED, DO10_POLARITY, DO10_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout11 { DO11_ENABLED, DO11_POLARITY, DO11_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout12 { DO12_ENABLED, DO12_POLARITY, DO12_EXTERNAL_NUMBER, (uint32_t)200000 }; +gpioDigitalOutputPin> dout13 { DO13_ENABLED, DO13_POLARITY, DO13_EXTERNAL_NUMBER, (uint32_t)200000 }; + +gpioDigitalOutput* const d_out[] = {&dout1, &dout2, &dout3, &dout4, &dout5, &dout6, &dout7, &dout8, &dout9, &dout10, &dout11, &dout12, &dout13}; + + +/**** Setup Arrays - these are extern and MUST match the board_gpio.h ****/ + +// not yet used +gpioAnalogInput* const a_in[] = {}; + +/************************************************************************************ + **** CODE ************************************************************************** + ************************************************************************************/ +/* + * gpio_reset() - reset inputs and outputs (no initialization) + */ + + +void outputs_reset(void) { + // nothing to do +} + +void inputs_reset(void) { + // nothing to do +} diff --git a/g2core/board/sbv300/board_gpio.h b/g2core/board/sbv300/board_gpio.h new file mode 100644 index 000000000..9bffbfe35 --- /dev/null +++ b/g2core/board/sbv300/board_gpio.h @@ -0,0 +1,96 @@ +/* + * gpio.h - Digital IO handling functions + * This file is part of the g2core project + * + * Copyright (c) 2015 - 2017 Alden S. Hart, Jr. + * Copyright (c) 2015 - 2017 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef BOARD_GPIO_H_ONCE +#define BOARD_GPIO_H_ONCE + +// this file is included from the bottom of gpio.h, but we do this for completeness +#include "../../gpio.h" + +/* + * GPIO defines + */ +//--- change as required for board and switch hardware ---// + +#define D_IN_CHANNELS 9 // v9 // number of digital inputs supported +#define D_OUT_CHANNELS 13 // number of digital outputs supported +#define A_IN_CHANNELS 0 // number of analog inputs supported +#define A_OUT_CHANNELS 0 // number of analog outputs supported + +#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing + +/* + * The GPIO objects themselves - this must match up with board_gpio.cpp! + */ + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; +// extern gpioAnalogInput* a_in[A_IN_CHANNELS]; +// extern gpioAnalogOutput* a_out[A_OUT_CHANNELS]; + +// prepare the objects as externs (for config_app to not bloat) +using Motate::IRQPin; +using Motate::PWMOutputPin; +using Motate::PWMLikeOutputPin; +template +using OutputType = typename std::conditional, PWMLikeOutputPin>::type; + +extern gpioDigitalInputPin> din1; +extern gpioDigitalInputPin> din2; +extern gpioDigitalInputPin> din3; +extern gpioDigitalInputPin> din4; +extern gpioDigitalInputPin> din5; +extern gpioDigitalInputPin> din6; +extern gpioDigitalInputPin> din7; +extern gpioDigitalInputPin> din8; +extern gpioDigitalInputPin> din9; +// extern gpioDigitalInputPin> din10; +// extern gpioDigitalInputPin> din11; +// extern gpioDigitalInputPin> din12; + +extern gpioDigitalInput* const d_in[D_IN_CHANNELS]; + + +extern gpioDigitalOutputPin> dout1; +extern gpioDigitalOutputPin> dout2; +extern gpioDigitalOutputPin> dout3; +extern gpioDigitalOutputPin> dout4; +extern gpioDigitalOutputPin> dout5; +extern gpioDigitalOutputPin> dout6; +extern gpioDigitalOutputPin> dout7; +extern gpioDigitalOutputPin> dout8; +extern gpioDigitalOutputPin> dout9; +extern gpioDigitalOutputPin> dout10; +extern gpioDigitalOutputPin> dout11; +extern gpioDigitalOutputPin> dout12; +extern gpioDigitalOutputPin> dout13; + +extern gpioDigitalOutput* const d_out[D_OUT_CHANNELS]; + +extern gpioAnalogInput* const a_in[A_IN_CHANNELS]; + +#endif // End of include guard: BOARD_GPIO_H_ONCE diff --git a/g2core/board/sbv300/board_xio.h b/g2core/board/sbv300/board_xio.h index 6bc4421f4..a6411948c 100755 --- a/g2core/board/sbv300/board_xio.h +++ b/g2core/board/sbv300/board_xio.h @@ -37,10 +37,10 @@ #include "MotateUSBCDC.h" #if USB_SERIAL_PORTS_EXPOSED == 1 -typedef Motate::USBDevice< Motate::USBCDC > XIOUSBDevice_t; +typedef Motate::USBDevice< Motate::USBDeviceHardware, Motate::USBCDC > XIOUSBDevice_t; #endif #if USB_SERIAL_PORTS_EXPOSED == 2 -typedef Motate::USBDevice XIOUSBDevice_t; +typedef Motate::USBDevice< Motate::USBDeviceHardware, Motate::USBCDC, Motate::USBCDC > XIOUSBDevice_t; #endif extern XIOUSBDevice_t usb; diff --git a/g2core/boards.mk b/g2core/boards.mk index bc75ad948..16e553ab6 100644 --- a/g2core/boards.mk +++ b/g2core/boards.mk @@ -143,7 +143,7 @@ endif ifeq ("$(CONFIG)","PrintrbotPlayQuintic") ifeq ("$(BOARD)","NONE") - BOARD=gquintic-c + BOARD=gquintic-d endif SETTINGS_FILE="settings_Printrbot_Play.h" endif @@ -170,13 +170,13 @@ endif ifeq ("$(CONFIG)","EggBot") ifeq ("$(BOARD)","NONE") - BOARD=gquadratic-b + BOARD=gquadratic-c endif SETTINGS_FILE="settings_eggbot.h" endif ifeq ("$(CONFIG)","AxiDrawv3") ifeq ("$(BOARD)","NONE") - BOARD=gquadratic-b + BOARD=gquadratic-c endif SETTINGS_FILE="settings_axidraw_v3.h" endif @@ -192,4 +192,24 @@ ifeq ("$(CONFIG)","Quintic-Ender") SETTINGS_FILE="settings_ender.h" endif +########## +# SMW3D r7 config: +# https://www.smw3d.com/r7-cnc-diy-kit/ + +ifeq ("$(CONFIG)","r7") + ifeq ("$(BOARD)","NONE") + BOARD=gquintic-d + endif + SETTINGS_FILE="settings_smw3d_r7.h" +endif + +########## +# Synthetos Pendulum v2 config: + +ifeq ("$(CONFIG)","pendulum") + ifeq ("$(BOARD)","NONE") + BOARD=gquintic-d + endif + SETTINGS_FILE="settings_synthetos_pendulum_v2.h" +endif include $(wildcard ./board/$(STAR).mk) diff --git a/g2core/canonical_machine.cpp b/g2core/canonical_machine.cpp index f78f11a87..4c6375680 100644 --- a/g2core/canonical_machine.cpp +++ b/g2core/canonical_machine.cpp @@ -116,6 +116,91 @@ cmSingleton_t cm; // canonical machine controller singleton +/* + * _hold_input_handler - a gpioDigitalInputHandler to capture pin change events + * Will be registered at init + */ +gpioDigitalInputHandler _hold_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return false; } + + cm_start_hold(); + + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with +}; + +/* + * _halt_input_handler - a gpioDigitalInputHandler to capture pin change events + * Will be registered at init + */ +gpioDigitalInputHandler _halt_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return false; } + + cm_halt_all(); + + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with +}; + + +/* + * _alarm_input_handler - a gpioDigitalInputHandler to capture pin change events + * Will be registered at init + */ +gpioDigitalInputHandler _alarm_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return false; } + + char msg[10]; + sprintf(msg, "input %d", triggering_pin_number); + cm_alarm(STAT_ALARM, msg); + + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with +}; + +/* + * _panic_input_handler - a gpioDigitalInputHandler to capture pin change events + * Will be registered at init + */ +gpioDigitalInputHandler _panic_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return false; } + + char msg[10]; + sprintf(msg, "input %d", triggering_pin_number); + cm_panic(STAT_PANIC, msg); + + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with +}; + +/* + * _reset_input_handler - a gpioDigitalInputHandler to capture pin change events + * Will be registered at init + */ +gpioDigitalInputHandler _reset_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return false; } + + hw_hard_reset(); + + return false; // this likely won't be seen, but just in case... + }, + 5, // priority + nullptr // next - nullptr to start with +}; + /*********************************************************************************** **** GENERIC STATIC FUNCTIONS AND VARIABLES *************************************** ***********************************************************************************/ @@ -748,7 +833,7 @@ stat_t cm_test_soft_limits(const float target[]) * canonical_machine_init() - initialize cm struct * canonical_machine_reset() - apply startup settings or reset to startup * run profile initialization beforehand - */ +*/ void canonical_machine_init() { @@ -760,6 +845,13 @@ void canonical_machine_init() canonical_machine_init_assertions(); // establish assertions ACTIVE_MODEL = MODEL; // setup initial Gcode model pointer cm_arc_init(); // Note: spindle and coolant inits are independent + + din_handlers[INPUT_ACTION_STOP].registerHandler(&_hold_input_handler); + din_handlers[INPUT_ACTION_FAST_STOP].registerHandler(&_hold_input_handler); + din_handlers[INPUT_ACTION_HALT].registerHandler(&_halt_input_handler); + din_handlers[INPUT_ACTION_ALARM].registerHandler(&_alarm_input_handler); + din_handlers[INPUT_ACTION_PANIC].registerHandler(&_panic_input_handler); + din_handlers[INPUT_ACTION_RESET].registerHandler(&_reset_input_handler); } void canonical_machine_reset_rotation() { @@ -785,7 +877,7 @@ void canonical_machine_reset() // NOTE: Should unhome axes here - // reset requests and flags + // reset requests and flags cm.queue_flush_state = FLUSH_OFF; cm.end_hold_requested = false; cm.limit_requested = 0; // resets switch closures that occurred during initialization @@ -938,6 +1030,7 @@ void cm_halt_motion(void) cm.hold_state = FEEDHOLD_OFF; } + /* * cm_alarm() - enter ALARM state * @@ -1119,7 +1212,7 @@ stat_t cm_set_g10_data(const uint8_t P_word, const bool P_flag, cm.offset[P_word][axis] = _to_millimeters(offset[axis]); } else { // Should L20 take into account G92 offsets? - cm.offset[P_word][axis] = + cm.offset[P_word][axis] = cm.gmx.position[axis] - _to_millimeters(offset[axis]) - cm.tl_offset[axis]; @@ -1223,7 +1316,7 @@ static void _exec_offset(float *value, bool *flag) float offsets[AXES]; for (uint8_t axis = AXIS_X; axis < AXES; axis++) { - offsets[axis] = cm.offset[coord_system][axis] + cm.tl_offset[axis] + + offsets[axis] = cm.offset[coord_system][axis] + cm.tl_offset[axis] + (cm.gmx.origin_offset[axis] * cm.gmx.origin_offset_enable); } mp_set_runtime_work_offset(offsets); @@ -1318,7 +1411,7 @@ stat_t cm_set_origin_offsets(const float offset[], const bool flag[]) for (uint8_t axis = AXIS_X; axis < AXES; axis++) { if (flag[axis]) { cm.gmx.origin_offset[axis] = cm.gmx.position[axis] - - cm.offset[cm.gm.coord_system][axis] - + cm.offset[cm.gm.coord_system][axis] - cm.tl_offset[axis] - _to_millimeters(offset[axis]); } @@ -1382,7 +1475,7 @@ stat_t cm_straight_traverse(const float target[], const bool flags[]) cm_cycle_start(); // required for homing & other cycles stat_t status = mp_aline(&cm.gm); // send the move to the planner cm_finalize_move(); - + if (status == STAT_MINIMUM_LENGTH_MOVE) { if (!mp_has_runnable_buffer()) { // handle condition where zero-length move is last or only move cm_cycle_end(); // ...otherwise cycle will not end properly @@ -1416,7 +1509,7 @@ stat_t _goto_stored_position(const float stored_position[], // always in mm target[i] *= INCHES_PER_MM; } } - + // Run the stored position move while (mp_planner_is_full()); // Make sure you have available buffers @@ -1905,7 +1998,6 @@ void cm_start_hold() cm.hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution } } - void cm_end_hold() { if (cm.hold_state == FEEDHOLD_HOLD) { @@ -2283,7 +2375,7 @@ static const char *const msg_frmo[] = { msg_g93, msg_g94, msg_g95 }; static int8_t _get_axis(const index_t index) { - // test if this is a SYS parameter (global), in which case there will be no axis + // test if this is a SYS parameter (global), in which case there will be no axis if (strcmp("sys", cfgArray[index].group) == 0) { return (AXIS_TYPE_SYSTEM); } @@ -2293,7 +2385,7 @@ static int8_t _get_axis(const index_t index) if (isdigit(cfgArray[index].token[0])) { return(st_cfg.mot[c-0x31].motor_map); } - + // otherwise it's an axis. Or undefined, which is usually a global. char *ptr; char axes[] = {"xyzabc"}; @@ -2487,12 +2579,12 @@ stat_t cm_get_am(nvObj_t *nv) stat_t cm_set_am(nvObj_t *nv) // axis mode { if (cm_get_axis_type(nv->index) == 0) { // linear - if (nv->value > AXIS_MODE_MAX_LINEAR) { + if (nv->value > AXIS_MODE_MAX_LINEAR) { nv->valuetype = TYPE_NULL; return (STAT_INPUT_EXCEEDS_MAX_VALUE); } } else { - if (nv->value > AXIS_MODE_MAX_ROTARY) { + if (nv->value > AXIS_MODE_MAX_ROTARY) { nv->valuetype = TYPE_NULL; return (STAT_INPUT_EXCEEDS_MAX_VALUE); } diff --git a/g2core/canonical_machine.h b/g2core/canonical_machine.h index ab825b4ff..2dfddb9a3 100644 --- a/g2core/canonical_machine.h +++ b/g2core/canonical_machine.h @@ -434,6 +434,7 @@ typedef struct cmSingleton { // struct to manage cm globals and c bool probe_report_enable; // 0=disabled, 1=enabled cmProbeState probe_state[PROBES_STORED]; // probing state machine (simple) + uint8_t probe_input; // probing digital input float probe_results[PROBES_STORED][AXES]; // probing results float rotation_matrix[3][3]; // three-by-three rotation matrix. We ignore rotary axes. diff --git a/g2core/config.cpp b/g2core/config.cpp index 596d34fb3..26335686a 100644 --- a/g2core/config.cpp +++ b/g2core/config.cpp @@ -256,7 +256,7 @@ stat_t set_noop(nvObj_t *nv) { return (STAT_OK); // hack until JSON is refactored } -stat_t set_nul(nvObj_t *nv) { +stat_t set_nul(nvObj_t *nv) { // nv->valuetype = TYPE_NULL; // return (STAT_PARAMETER_IS_READ_ONLY); // this is what it should be return (STAT_OK); // hack until JSON is refactored @@ -264,11 +264,11 @@ stat_t set_nul(nvObj_t *nv) { stat_t set_ro(nvObj_t *nv) { // hack. If setting an SR it doesn't fail - if (strcmp(nv_body->token, "sr") == 0) { - return (STAT_OK); + if (strcmp(nv_body->token, "sr") == 0) { + return (STAT_OK); } nv->valuetype = TYPE_NULL; - return (STAT_PARAMETER_IS_READ_ONLY); + return (STAT_PARAMETER_IS_READ_ONLY); } stat_t set_ui8(nvObj_t *nv) @@ -465,6 +465,14 @@ index_t nv_get_index(const char *group, const char *token) if (c != str[3]) continue; // 4th character mismatch if ((c = GET_TOKEN_BYTE(token[4])) == NUL) { if (str[4] == NUL) return(i);} // four character match if (c != str[4]) continue; // 5th character mismatch + if ((c = GET_TOKEN_BYTE(token[5])) == NUL) { if (str[5] == NUL) return(i);} // four character match + if (c != str[5]) continue; // 6th character mismatch + if ((c = GET_TOKEN_BYTE(token[6])) == NUL) { if (str[6] == NUL) return(i);} // four character match + if (c != str[6]) continue; // 7th character mismatch + if ((c = GET_TOKEN_BYTE(token[7])) == NUL) { if (str[7] == NUL) return(i);} // four character match + if (c != str[7]) continue; // 8th character mismatch + if ((c = GET_TOKEN_BYTE(token[8])) == NUL) { if (str[8] == NUL) return(i);} // four character match + if (c != str[8]) continue; // 9th character mismatch return (i); // five character match } return (NO_MATCH); @@ -617,7 +625,7 @@ nvObj_t *nv_add_object(const char *token) // add an object to the body usi if (nv->valuetype != TYPE_EMPTY) { if ((nv = nv->nx) == NULL) { // not supposed to find a NULL; here for safety return(NULL); - } + } continue; } // load the index from the token or die trying @@ -634,7 +642,7 @@ nvObj_t *nv_add_integer(const char *token, const uint32_t value)// add an intege for (uint8_t i=0; ivaluetype != TYPE_EMPTY) { if ((nv = nv->nx) == NULL) { // not supposed to find a NULL; here for safety - return(NULL); + return(NULL); } continue; } @@ -652,8 +660,8 @@ nvObj_t *nv_add_data(const char *token, const uint32_t value)// add an integer o for (uint8_t i=0; ivaluetype != TYPE_EMPTY) { if ((nv = nv->nx) == NULL) { // not supposed to find a NULL; here for safety - return(NULL); - } + return(NULL); + } continue; } strcpy(nv->token, token); @@ -672,7 +680,7 @@ nvObj_t *nv_add_float(const char *token, const float value) // add a float ob if (nv->valuetype != TYPE_EMPTY) { if ((nv = nv->nx) == NULL) { // not supposed to find a NULL; here for safety return(NULL); - } + } continue; } strncpy(nv->token, token, TOKEN_LEN); @@ -689,8 +697,8 @@ nvObj_t *nv_add_string(const char *token, const char *string) // add a string ob for (uint8_t i=0; ivaluetype != TYPE_EMPTY) { if ((nv = nv->nx) == NULL) { // not supposed to find a NULL; here for safety - return(NULL); - } + return(NULL); + } continue; } strncpy(nv->token, token, TOKEN_LEN); diff --git a/g2core/config.h b/g2core/config.h index a8b1ebddb..9fc566453 100644 --- a/g2core/config.h +++ b/g2core/config.h @@ -185,8 +185,8 @@ typedef uint32_t index_t; // use this because set/get_int is expec // Stuff you probably don't want to change -#define GROUP_LEN 4 // max length of group prefix -#define TOKEN_LEN 6 // mnemonic token string: group prefix + short token +#define GROUP_LEN 6 // max length of group prefix +#define TOKEN_LEN 9 // mnemonic token string: group prefix + short token #define NV_FOOTER_LEN 18 // sufficient space to contain a JSON footer array #define NV_LIST_LEN (NV_BODY_LEN+2) // +2 allows for a header and a footer #define NV_EXEC_FIRST (NV_BODY_LEN+2) // index of the first EXEC nv diff --git a/g2core/config_app.cpp b/g2core/config_app.cpp index 99260e1a5..aafa61931 100644 --- a/g2core/config_app.cpp +++ b/g2core/config_app.cpp @@ -174,6 +174,7 @@ const cfgItem_t cfgArray[] = { { "prb","prbc",_f0, 3, tx_print_nul, get_flt, set_ro, (float *)&cm.probe_results[0][AXIS_C], 0 }, { "prb","prbs",_f0, 0, tx_print_nul, get_nul, cm_set_probe, (float *)&cs.null, 0 }, // store probe { "prb","prbr",_f0, 0, tx_print_nul, cm_get_prbr, cm_set_prbr, nullptr, 0 }, // enable probe report. Init in cm_init + { "prb","prbin",_f0, 0, tx_print_nul, get_ui8, cm_set_hi, (float *)&cm.probe_input, PROBING_INPUT }, // probing state { "jog","jogx",_f0, 0, tx_print_nul, get_nul, cm_run_jogx, (float *)&cm.jogging_dest, 0}, { "jog","jogy",_f0, 0, tx_print_nul, get_nul, cm_run_jogy, (float *)&cm.jogging_dest, 0}, @@ -480,108 +481,256 @@ const cfgItem_t cfgArray[] = { { "c","czb",_fip, 3, cm_print_zb, get_flt, set_flt, (float *)&cm.a[AXIS_C].zero_backoff, C_ZERO_BACKOFF }, // Digital input configs - { "di1","di1mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[0].mode, DI1_MODE }, - { "di1","di1ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[0].action, DI1_ACTION }, - { "di1","di1fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[0].function, DI1_FUNCTION }, - - { "di2","di2mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[1].mode, DI2_MODE }, - { "di2","di2ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[1].action, DI2_ACTION }, - { "di2","di2fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[1].function, DI2_FUNCTION }, - - { "di3","di3mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[2].mode, DI3_MODE }, - { "di3","di3ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[2].action, DI3_ACTION }, - { "di3","di3fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[2].function, DI3_FUNCTION }, - - { "di4","di4mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[3].mode, DI4_MODE }, - { "di4","di4ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[3].action, DI4_ACTION }, - { "di4","di4fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[3].function, DI4_FUNCTION }, - - { "di5","di5mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[4].mode, DI5_MODE }, - { "di5","di5ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[4].action, DI5_ACTION }, - { "di5","di5fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[4].function, DI5_FUNCTION }, - - { "di6","di6mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[5].mode, DI6_MODE }, - { "di6","di6ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[5].action, DI6_ACTION }, - { "di6","di6fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[5].function, DI6_FUNCTION }, - - { "di7","di7mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[6].mode, DI7_MODE }, - { "di7","di7ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[6].action, DI7_ACTION }, - { "di7","di7fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[6].function, DI7_FUNCTION }, - - { "di8","di8mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[7].mode, DI8_MODE }, - { "di8","di8ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[7].action, DI8_ACTION }, - { "di8","di8fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[7].function, DI8_FUNCTION }, -#if (D_IN_CHANNELS >= 9) - { "di9","di9mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[8].mode, DI9_MODE }, - { "di9","di9ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[8].action, DI9_ACTION }, - { "di9","di9fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[8].function, DI9_FUNCTION }, + { "di1","di1en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din1, DI1_ENABLED }, + { "di1","di1po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din1, DI1_POLARITY }, + { "di1","di1ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din1, DI1_ACTION }, + // { "di1","di1fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din1, DI1_FUNCTION }, + { "di1","di1in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din1, DI1_EXTERNAL_NUMBER }, + + { "di2","di2en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din2, DI2_ENABLED }, + { "di2","di2po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din2, DI2_POLARITY }, + { "di2","di2ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din2, DI2_ACTION }, + // { "di2","di2fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din2, DI2_FUNCTION }, + { "di2","di2in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din2, DI2_EXTERNAL_NUMBER }, + +#if (D_IN_CHANNELS >= 3) + { "di3","di3en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din3, DI3_ENABLED }, + { "di3","di3po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din3, DI3_POLARITY }, + { "di3","di3ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din3, DI3_ACTION }, + // { "di3","di3fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din3, DI3_FUNCTION }, + { "di3","di3in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din3, DI3_EXTERNAL_NUMBER }, #endif -#if (D_IN_CHANNELS >= 10) - { "di10","di10mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[9].mode, DI10_MODE }, - { "di10","di10ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[9].action, DI10_ACTION }, - { "di10","di10fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[9].function, DI10_FUNCTION }, +#if (D_IN_CHANNELS >= 4) + { "di4","di4en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din4, DI4_ENABLED }, + { "di4","di4po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din4, DI4_POLARITY }, + { "di4","di4ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din4, DI4_ACTION }, + // { "di4","di4fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din4, DI4_FUNCTION }, + { "di4","di4in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din4, DI4_EXTERNAL_NUMBER }, #endif -#if (D_IN_CHANNELS >= 11) - { "di11","di11mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[10].mode, DI11_MODE }, - { "di11","di11ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[10].action, DI11_ACTION }, - { "di11","di11fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[10].function, DI11_FUNCTION }, +#if (D_IN_CHANNELS >= 5) + { "di5","di5en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din5, DI5_ENABLED }, + { "di5","di5po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din5, DI5_POLARITY }, + { "di5","di5ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din5, DI5_ACTION }, + // { "di5","di5fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din5, DI5_FUNCTION }, + { "di5","di5in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din5, DI5_EXTERNAL_NUMBER }, #endif -#if (D_IN_CHANNELS >= 12) - { "di12","di12mo",_fip, 0, io_print_mo, get_int8,io_set_mo, (float *)&d_in[11].mode, DI12_MODE }, - { "di12","di12ac",_fip, 0, io_print_ac, get_ui8, io_set_ac, (float *)&d_in[11].action, DI12_ACTION }, - { "di12","di12fn",_fip, 0, io_print_fn, get_ui8, io_set_fn, (float *)&d_in[11].function, DI12_FUNCTION }, +#if (D_IN_CHANNELS >= 6) + { "di6","di6en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din6, DI6_ENABLED }, + { "di6","di6po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din6, DI6_POLARITY }, + { "di6","di6ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din6, DI6_ACTION }, + // { "di6","di6fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din6, DI6_FUNCTION }, + { "di6","di6in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din6, DI6_EXTERNAL_NUMBER }, +#endif +#if (D_IN_CHANNELS >= 7) + { "di7","di7en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din7, DI7_ENABLED }, + { "di7","di7po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din7, DI7_POLARITY }, + { "di7","di7ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din7, DI7_ACTION }, + // { "di7","di7fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din7, DI7_FUNCTION }, + { "di7","di7in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din7, DI7_EXTERNAL_NUMBER }, +#endif +#if (D_IN_CHANNELS >= 8) + { "di8","di8en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din8, DI8_ENABLED }, + { "di3","di8po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din8, DI8_POLARITY }, + { "di8","di8ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din8, DI8_ACTION }, + // { "di8","di8fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din8, DI8_FUNCTION }, + { "di8","di8in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din8, DI8_EXTERNAL_NUMBER }, #endif - - // Digital input state readers - { "in","in1", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, - { "in","in2", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, - { "in","in3", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, - { "in","in4", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, - { "in","in5", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, - { "in","in6", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, - { "in","in7", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, - { "in","in8", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, #if (D_IN_CHANNELS >= 9) - { "in","in9", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, + { "di9","di9en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din9, DI9_ENABLED }, + { "di9","di9po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din9, DI9_POLARITY }, + { "di9","di9ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din9, DI9_ACTION }, + // { "di9","di9fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din9, DI9_FUNCTION }, + { "di9","di9in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din9, DI9_EXTERNAL_NUMBER }, #endif #if (D_IN_CHANNELS >= 10) - { "in","in10", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, + { "di10","di10en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din10, DI10_ENABLED }, + { "di10","di10po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din10, DI10_POLARITY }, + { "di10","di10ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din10, DI10_ACTION }, + // { "di10","di10fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din10, DI10_FUNCTION }, + { "di10","di10in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din10, DI10_EXTERNAL_NUMBER }, #endif #if (D_IN_CHANNELS >= 11) - { "in","in11", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, + { "di11","di11en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din11, DI11_ENABLED }, + { "di11","di11po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din11, DI11_POLARITY }, + { "di11","di11ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din11, DI11_ACTION }, + // { "di11","di11fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din11, DI11_FUNCTION }, + { "di11","di11in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din11, DI11_EXTERNAL_NUMBER }, #endif #if (D_IN_CHANNELS >= 12) - { "in","in12", _f0, 0, io_print_in, io_get_input, set_ro, (float *)&cs.null, 0 }, + { "di12","di12en",_fip, 0, din_print_en, din_get_en, din_set_en, (float *)&din12, DI12_ENABLED }, + { "di12","di12po",_fip, 0, din_print_po, din_get_po, din_set_po, (float *)&din12, DI12_POLARITY }, + { "di12","di12ac",_fip, 0, din_print_ac, din_get_ac, din_set_ac, (float *)&din12, DI12_ACTION }, + // { "di12","di12fn",_fip, 0, din_print_fn, din_get_fn, din_set_fn, (float *)&din12, DI12_FUNCTION }, + { "di12","di12in",_fip, 0, din_print_in, din_get_in, din_set_in, (float *)&din12, DI12_EXTERNAL_NUMBER }, #endif - // digital output configs - { "do1", "do1mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[0].mode, DO1_MODE }, - { "do2", "do2mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[1].mode, DO2_MODE }, - { "do3", "do3mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[2].mode, DO3_MODE }, - { "do4", "do4mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[3].mode, DO4_MODE }, - { "do5", "do5mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[4].mode, DO5_MODE }, - { "do6", "do6mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[5].mode, DO6_MODE }, - { "do7", "do7mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[6].mode, DO7_MODE }, - { "do8", "do8mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[7].mode, DO8_MODE }, - { "do9", "do9mo", _fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[8].mode, DO9_MODE }, - { "do10","do10mo",_fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[9].mode, DO10_MODE }, - { "do11","do11mo",_fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[10].mode, DO11_MODE }, - { "do12","do12mo",_fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[11].mode, DO12_MODE }, - { "do13","do13mo",_fip, 0, io_print_domode, get_int8, io_set_domode, (float *)&d_out[12].mode, DO13_MODE }, + // Digital input state readers + { "in","in1", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in1, 0 }, + { "in","in2", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in2, 0 }, + { "in","in3", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in3, 0 }, + { "in","in4", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in4, 0 }, + { "in","in5", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in5, 0 }, + { "in","in6", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in6, 0 }, + { "in","in7", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in7, 0 }, + { "in","in8", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in8, 0 }, + { "in","in9", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in9, 0 }, + { "in","in10", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in10, 0 }, + { "in","in11", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in11, 0 }, + { "in","in12", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in12, 0 }, + { "in","in13", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in13, 0 }, + { "in","in14", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in14, 0 }, + { "in","in15", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in15, 0 }, + { "in","in16", _f0, 0, din_print_state, din_get_input, set_ro, (float *)&in16, 0 }, + // digital output configs + { "do1", "do1en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout1, DO1_ENABLED }, + { "do1", "do1po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout1, DO1_POLARITY }, + { "do1", "do1out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout1, DO1_EXTERNAL_NUMBER }, +#if (D_OUT_CHANNELS >= 2) + { "do2", "do2en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout2, DO2_ENABLED }, + { "do2", "do2po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout2, DO2_POLARITY }, + { "do2", "do2out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout2, DO2_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 3) + { "do3", "do3en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout3, DO3_ENABLED }, + { "do3", "do3po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout3, DO3_POLARITY }, + { "do3", "do3out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout3, DO3_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 4) + { "do4", "do4en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout4, DO4_ENABLED }, + { "do4", "do4po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout4, DO4_POLARITY }, + { "do4", "do4out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout4, DO4_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 5) + { "do5", "do5en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout5, DO5_ENABLED }, + { "do5", "do5po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout5, DO5_POLARITY }, + { "do5", "do5out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout5, DO5_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 6) + { "do6", "do6en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout6, DO6_ENABLED }, + { "do6", "do6po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout6, DO6_POLARITY }, + { "do6", "do6out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout6, DO6_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 7) + { "do7", "do7en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout7, DO7_ENABLED }, + { "do7", "do7po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout7, DO7_POLARITY }, + { "do7", "do7out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout7, DO7_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 8) + { "do8", "do8en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout8, DO8_ENABLED }, + { "do8", "do8po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout8, DO8_POLARITY }, + { "do8", "do8out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout8, DO8_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 9) + { "do9", "do9en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout9, DO9_ENABLED }, + { "do9", "do9po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout9, DO9_POLARITY }, + { "do9", "do9out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout9, DO9_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 10) + { "do10", "do10en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout10, DO10_ENABLED }, + { "do10", "do10po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout10, DO10_POLARITY }, + { "do10", "do10out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout10, DO10_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 11) + { "do11", "do11en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout11, DO11_ENABLED }, + { "do11", "do11po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout11, DO11_POLARITY }, + { "do11", "do11out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout11, DO11_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 12) + { "do12", "do12en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout12, DO12_ENABLED }, + { "do12", "do12po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout12, DO12_POLARITY }, + { "do12", "do12out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout12, DO12_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 13) + { "do13", "do13en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout13, DO13_ENABLED }, + { "do13", "do13po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout13, DO13_POLARITY }, + { "do13", "do13out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout13, DO13_EXTERNAL_NUMBER }, +#endif +#if (D_OUT_CHANNELS >= 14) + { "do14", "do14en", _fip, 0, dout_print_en, dout_get_en, dout_set_en, (float *)&dout14, DO14_ENABLED }, + { "do14", "do14po", _fip, 0, dout_print_po, dout_get_po, dout_set_po, (float *)&dout14, DO14_POLARITY }, + { "do14", "do14out",_fip, 0, dout_print_out, dout_get_out, dout_set_out, (float *)&dout14, DO14_EXTERNAL_NUMBER }, +#endif // Digital output state readers (default to non-active) - { "out","out1", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out2", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out3", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out4", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out5", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out6", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out7", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out8", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out9", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out10", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out11", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, - { "out","out12", _f0, 2, io_print_out, io_get_output, io_set_output, (float *)&cs.null, 0 }, + { "out","out1", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out1, 0 }, + { "out","out2", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out2, 0 }, + { "out","out3", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out3, 0 }, + { "out","out4", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out4, 0 }, + { "out","out5", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out5, 0 }, + { "out","out6", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out6, 0 }, + { "out","out7", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out7, 0 }, + { "out","out8", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out8, 0 }, + { "out","out9", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out9, 0 }, + { "out","out10", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out10, 0 }, + { "out","out11", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out11, 0 }, + { "out","out12", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out12, 0 }, + { "out","out13", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out13, 0 }, + { "out","out14", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out14, 0 }, + { "out","out15", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out15, 0 }, + { "out","out16", _f0, 2, dout_print_out, dout_get_output, dout_set_output, (float *)&out16, 0 }, + + // Analog input configs +#if (A_IN_CHANNELS >= 1) + { "ai1","ai1en",_fip, 0, ai_print_en, ai_get_en, ai_set_en, (float *)&ai1, AI1_ENABLED }, + { "ai1","ai1ain",_fip,0, ai_print_ain, ai_get_ain, ai_set_ain, (float *)&ai1, AI1_EXTERNAL_NUMBER }, + { "ai1","ai1ty",_fip, 0, ai_print_type, ai_get_type, ai_set_type, (float *)&ai1, AI1_TYPE }, + { "ai1","ai1ct",_fip, 0, ai_print_circuit, ai_get_circuit, ai_set_circuit, (float *)&ai1, AI1_CIRCUIT }, + { "ai1","ai1p1",_fip, 4, ai_print_p, ai_get_p1, ai_set_p1, (float *)&ai1, AI1_P1 }, + { "ai1","ai1p2",_fip, 4, ai_print_p, ai_get_p2, ai_set_p2, (float *)&ai1, AI1_P2 }, + { "ai1","ai1p3",_fip, 4, ai_print_p, ai_get_p3, ai_set_p3, (float *)&ai1, AI1_P3 }, + { "ai1","ai1p4",_fip, 4, ai_print_p, ai_get_p4, ai_set_p4, (float *)&ai1, AI1_P4 }, + { "ai1","ai1p5",_fip, 4, ai_print_p, ai_get_p5, ai_set_p5, (float *)&ai1, AI1_P5 }, +#endif +#if (A_IN_CHANNELS >= 2) + { "ai2","ai2en",_fip, 0, ai_print_en, ai_get_en, ai_set_en, (float *)&ai2, AI2_ENABLED }, + { "ai2","ai2ain",_fip,0, ai_print_ain, ai_get_ain, ai_set_ain, (float *)&ai2, AI2_EXTERNAL_NUMBER }, + { "ai2","ai2ty",_fip, 0, ai_print_type, ai_get_type, ai_set_type, (float *)&ai2, AI2_TYPE }, + { "ai2","ai2ct",_fip, 0, ai_print_circuit, ai_get_circuit, ai_set_circuit, (float *)&ai2, AI2_CIRCUIT }, + { "ai2","ai2p1",_fip, 4, ai_print_p, ai_get_p1, ai_set_p1, (float *)&ai2, AI2_P1 }, + { "ai2","ai2p2",_fip, 4, ai_print_p, ai_get_p2, ai_set_p2, (float *)&ai2, AI2_P2 }, + { "ai2","ai2p3",_fip, 4, ai_print_p, ai_get_p3, ai_set_p3, (float *)&ai2, AI2_P3 }, + { "ai2","ai2p4",_fip, 4, ai_print_p, ai_get_p4, ai_set_p4, (float *)&ai2, AI2_P4 }, + { "ai2","ai2p5",_fip, 4, ai_print_p, ai_get_p5, ai_set_p5, (float *)&ai2, AI2_P5 }, +#endif +#if (A_IN_CHANNELS >= 3) + { "ai3","ai3en",_fip, 0, ai_print_en, ai_get_en, ai_set_en, (float *)&ai3, AI3_ENABLED }, + { "ai3","ai3ain",_fip,0, ai_print_ain, ai_get_ain, ai_set_ain, (float *)&ai3, AI3_EXTERNAL_NUMBER }, + { "ai3","ai3ty",_fip, 0, ai_print_type, ai_get_type, ai_set_type, (float *)&ai3, AI3_TYPE }, + { "ai3","ai3ct",_fip, 0, ai_print_circuit, ai_get_circuit, ai_set_circuit, (float *)&ai3, AI3_CIRCUIT }, + { "ai3","ai3p1",_fip, 4, ai_print_p, ai_get_p1, ai_set_p1, (float *)&ai3, AI3_P1 }, + { "ai3","ai3p2",_fip, 4, ai_print_p, ai_get_p2, ai_set_p2, (float *)&ai3, AI3_P2 }, + { "ai3","ai3p3",_fip, 4, ai_print_p, ai_get_p3, ai_set_p3, (float *)&ai3, AI3_P3 }, + { "ai3","ai3p4",_fip, 4, ai_print_p, ai_get_p4, ai_set_p4, (float *)&ai3, AI3_P4 }, + { "ai3","ai3p5",_fip, 4, ai_print_p, ai_get_p5, ai_set_p5, (float *)&ai3, AI3_P5 }, +#endif +#if (A_IN_CHANNELS >= 4) + { "ai4","ai4en",_fip, 0, ai_print_en, ai_get_en, ai_set_en, (float *)&ai4, AI4_ENABLED }, + { "ai4","ai4ain",_fip,0, ai_print_ain, ai_get_ain, ai_set_ain, (float *)&ai4, AI4_EXTERNAL_NUMBER }, + { "ai4","ai4ty",_fip, 0, ai_print_type, ai_get_type, ai_set_type, (float *)&ai4, AI4_TYPE }, + { "ai4","ai4ct",_fip, 0, ai_print_circuit, ai_get_circuit, ai_set_circuit, (float *)&ai4, AI4_CIRCUIT }, + { "ai4","ai4p1",_fip, 4, ai_print_p, ai_get_p1, ai_set_p1, (float *)&ai4, AI4_P1 }, + { "ai4","ai4p2",_fip, 4, ai_print_p, ai_get_p2, ai_set_p2, (float *)&ai4, AI4_P2 }, + { "ai4","ai4p3",_fip, 4, ai_print_p, ai_get_p3, ai_set_p3, (float *)&ai4, AI4_P3 }, + { "ai4","ai4p4",_fip, 4, ai_print_p, ai_get_p4, ai_set_p4, (float *)&ai4, AI4_P4 }, + { "ai4","ai4p5",_fip, 4, ai_print_p, ai_get_p5, ai_set_p5, (float *)&ai4, AI4_P5 }, +#endif + + { "ain1","ain1vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain1, 0 }, + { "ain1","ain1rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain1, 0 }, + { "ain2","ain2vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain2, 0 }, + { "ain2","ain2rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain2, 0 }, + { "ain3","ain3vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain3, 0 }, + { "ain3","ain3rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain3, 0 }, + { "ain4","ain4vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain4, 0 }, + { "ain4","ain4rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain4, 0 }, + { "ain5","ain5vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain5, 0 }, + { "ain5","ain5rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain5, 0 }, + { "ain6","ain6vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain6, 0 }, + { "ain6","ain6rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain6, 0 }, + { "ain7","ain7vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain7, 0 }, + { "ain7","ain7rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain7, 0 }, + { "ain8","ain8vv",_f0, 4, ain_print_value, ain_get_value, set_ro, (float *)&ain8, 0 }, + { "ain8","ain8rv",_f0, 2, ain_print_resistance, ain_get_resistance, set_ro, (float *)&ain8, 0 }, // PWM settings { "p1","p1frq",_fip, 0, pwm_print_p1frq, get_flt, pwm_set_pwm,(float *)&pwm.c[PWM_1].frequency, P1_PWM_FREQUENCY }, @@ -980,8 +1129,8 @@ const cfgItem_t cfgArray[] = { { "sys","mfo", _fipn,3, cm_print_mfo, get_flt,cm_set_mfo,(float *)&cm.gmx.mfo_factor, FEED_OVERRIDE_FACTOR}, { "sys","mtoe",_fipn,0, cm_print_mtoe,get_ui8, set_01, (float *)&cm.gmx.mto_enable, TRAVERSE_OVERRIDE_ENABLE}, { "sys","mto", _fipn,3, cm_print_mto, get_flt,cm_set_mto,(float *)&cm.gmx.mto_factor, TRAVERSE_OVERRIDE_FACTOR}, - - // Power management + + // Power management { "sys","mt", _fipn,2, st_print_mt, get_flt, st_set_mt, (float *)&st_cfg.motor_power_timeout, MOTOR_POWER_TIMEOUT}, { "", "me", _f0, 0, st_print_me, st_set_me, st_set_me,(float *)&cs.null, 0 }, // SET to enable motors (null value sets to maintain compatability) { "", "md", _f0, 0, st_print_md, st_set_md, st_set_md,(float *)&cs.null, 0 }, // SET to disable motors (null value sets to maintain compatability) @@ -1240,6 +1389,11 @@ const cfgItem_t cfgArray[] = { { "","do12", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, { "","do13", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // +14 = 36 + { "","ain1", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // analog input configs + { "","ain2", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, + { "","ain3", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, + { "","ain4", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, + // +4 = 40 { "","g54",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // coord offset groups { "","g55",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, { "","g56",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, @@ -1249,7 +1403,7 @@ const cfgItem_t cfgArray[] = { { "","g92",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // origin offsets { "","g28",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // g28 home position { "","g30",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // g30 home position - // +9 = 45 + // +9 = 49 { "","tof",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // tool offsets { "","tt1",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // tt offsets { "","tt2",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // tt offsets @@ -1267,7 +1421,7 @@ const cfgItem_t cfgArray[] = { { "","tt14",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // tt offsets { "","tt15",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // tt offsets { "","tt16",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // tt offsets - // +17 = 62 + // +17 = 66 { "","mpo",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // machine position group { "","pos",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // work position group { "","ofs",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // work offset group @@ -1276,14 +1430,14 @@ const cfgItem_t cfgArray[] = { { "","pwr",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // motor power enagled group { "","jog",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // axis jogging state group { "","jid",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // job ID group - // +8 = 70 + // +8 = 74 { "","he1", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // heater 1 group { "","he2", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // heater 2 group { "","he3", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // heater 3 group { "","pid1",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // PID 1 group { "","pid2",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // PID 2 group { "","pid3",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // PID 3 group - // +6 = 76 + // +6 = 80 #ifdef __USER_DATA { "","uda", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0 }, // user data group @@ -1520,6 +1674,10 @@ static stat_t _do_inputs(nvObj_t *nv) // print parameters for all input groups sprintf(group, "di%d", i); _do_group(nv, group); } + for (uint8_t i=1; i < A_IN_CHANNELS+1; i++) { + sprintf(group, "ain%d", i); + _do_group(nv, group); + } return (STAT_COMPLETE); // STAT_COMPLETE suppresses the normal response line } diff --git a/g2core/controller.cpp b/g2core/controller.cpp index 419c8a534..14ab71498 100644 --- a/g2core/controller.cpp +++ b/g2core/controller.cpp @@ -81,6 +81,44 @@ static stat_t _controller_state(void); // manage controller state trans static Motate::OutputPin safe_pin; +gpioDigitalInputHandler _shutdown_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return false; } + + cm.shutdown_requested = triggering_pin_number; + + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with +}; + +gpioDigitalInputHandler _limit_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return false; } + + cm.limit_requested = triggering_pin_number; + + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with +}; + +gpioDigitalInputHandler _interlock_input_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge == INPUT_EDGE_LEADING) { + cm.safety_interlock_disengaged = triggering_pin_number; + } else { // edge == INPUT_EDGE_TRAILING + cm.safety_interlock_reengaged = triggering_pin_number; + } + + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with +}; + /*********************************************************************************** **** CODE ************************************************************************* ***********************************************************************************/ @@ -105,6 +143,10 @@ void controller_init() cs.controller_state = CONTROLLER_CONNECTED; } // IndicatorLed.setFrequency(100000); + + din_handlers[INPUT_ACTION_SHUTDOWN].registerHandler(&_shutdown_input_handler); + din_handlers[INPUT_ACTION_LIMIT].registerHandler(&_limit_input_handler); + din_handlers[INPUT_ACTION_INTERLOCK].registerHandler(&_interlock_input_handler); } void controller_request_enquiry() @@ -297,7 +339,7 @@ static void _dispatch_kernel(const devflags_t flags) nv_copy_string(nv, cs.bufp); // copy the Gcode line nv->valuetype = TYPE_STRING; status = gcode_parser(cs.bufp); - + #if MARLIN_COMPAT_ENABLED == true if (js.json_mode == MARLIN_COMM_MODE) { // in case a marlin-specific M-code was found cs.comm_request_mode = MARLIN_COMM_MODE; // mode of this command @@ -340,7 +382,7 @@ static stat_t _controller_state() { if (cs.controller_state == CONTROLLER_CONNECTED) { // first time through after reset cs.controller_state = CONTROLLER_STARTUP; - + // This is here just to put a small delay in before the startup message. #if MARLIN_COMPAT_ENABLED == true // For Marlin compatibility, we need this to be long enough for the UI to say something and reveal @@ -349,7 +391,7 @@ static stat_t _controller_state() // xio_connected will only return true for USB and other non-permanent connections _connection_timeout.set(2000); } else { - _connection_timeout.set(1); + _connection_timeout.set(10); } #else _connection_timeout.set(10); @@ -462,8 +504,11 @@ static stat_t _sync_to_planner() /* ALARM STATE HANDLERS * * _shutdown_handler() - put system into shutdown state + * _shutdown_input_handler - a gpioDigitalInputHandler to capture pin change events * _limit_switch_handler() - shut down system if limit switch fired - * _interlock_handler() - feedhold and resume depending on edge + * _limit_input_handler - a gpioDigitalInputHandler to capture pin change events + * _interlock_input_handler() - feedhold and resume depending on edge + * _interlock_handler - a gpioDigitalInputHandler to capture pin change events * * Some handlers return EAGAIN causing the control loop to never advance beyond that point. * @@ -472,6 +517,7 @@ static stat_t _sync_to_planner() * - safety_interlock_requested == INPUT_EDGE_LEADING is interlock onset * - safety_interlock_requested == INPUT_EDGE_TRAILING is interlock offset */ + static stat_t _shutdown_handler(void) { if (cm.shutdown_requested != 0) { // request may contain the (non-zero) input number @@ -558,5 +604,3 @@ stat_t _test_system_assertions() xio_test_assertions(); return (STAT_OK); } - - diff --git a/g2core/coolant.cpp b/g2core/coolant.cpp index f19cea957..c553c6a6b 100755 --- a/g2core/coolant.cpp +++ b/g2core/coolant.cpp @@ -30,6 +30,7 @@ #include "canonical_machine.h" // #3 #include "text_parser.h" // #4 +#include "gpio.h" #include "coolant.h" #include "planner.h" #include "hardware.h" @@ -39,6 +40,17 @@ cmCoolantSingleton_t coolant; +gpioDigitalOutput *mist_enable_output = nullptr; +gpioDigitalOutput *flood_enable_output = nullptr; + +#ifndef MIST_ENABLE_OUTPUT_NUMBER +#define MIST_ENABLE_OUTPUT_NUMBER 6 +#endif + +#ifndef FLOOD_ENABLE_OUTPUT_NUMBER +#define FLOOD_ENABLE_OUTPUT_NUMBER 7 +#endif + /**** Static functions ****/ static void _exec_coolant_control(float* value, bool* flags); @@ -48,6 +60,17 @@ static void _exec_coolant_control(float* value, bool* flags); * coolant_reset() */ void coolant_init() { + if (MIST_ENABLE_OUTPUT_NUMBER > 0) { + mist_enable_output = d_out[MIST_ENABLE_OUTPUT_NUMBER-1]; + mist_enable_output->setEnabled(IO_ENABLED); + mist_enable_output->setPolarity((ioPolarity)COOLANT_MIST_POLARITY); + } + if (FLOOD_ENABLE_OUTPUT_NUMBER > 0) { + flood_enable_output = d_out[FLOOD_ENABLE_OUTPUT_NUMBER-1]; + flood_enable_output->setEnabled(IO_ENABLED); + flood_enable_output->setPolarity((ioPolarity)COOLANT_FLOOD_POLARITY); + } + coolant.mist_enable = COOLANT_OFF; coolant.flood_enable = COOLANT_OFF; } @@ -129,26 +152,32 @@ stat_t cm_mist_coolant_control(uint8_t mist_enable) { } // NOTE: flood and mist coolants are mapped to the same pin - see hardware.h -#define _set_flood_enable_bit_hi() flood_enable_pin.set() -#define _set_flood_enable_bit_lo() flood_enable_pin.clear() -#define _set_mist_enable_bit_hi() mist_enable_pin.set() -#define _set_mist_enable_bit_lo() mist_enable_pin.clear() +//#define _set_flood_enable_bit_hi() flood_enable_pin.set() +//#define _set_flood_enable_bit_lo() flood_enable_pin.clear() +//#define _set_mist_enable_bit_hi() mist_enable_pin.set() +//#define _set_mist_enable_bit_lo() mist_enable_pin.clear() static void _exec_coolant_control(float* value, bool* flags) { if (flags[COOLANT_FLOOD]) { coolant.flood_enable = (cmCoolantEnable)value[COOLANT_FLOOD]; - if (!((coolant.flood_enable & 0x01) ^ coolant.flood_polarity)) { // inverted XOR - _set_flood_enable_bit_hi(); - } else { - _set_flood_enable_bit_lo(); +// if (!((coolant.flood_enable & 0x01) ^ coolant.flood_polarity)) { // inverted XOR +// _set_flood_enable_bit_hi(); +// } else { +// _set_flood_enable_bit_lo(); +// } + if (flood_enable_output != nullptr) { + flood_enable_output->setValue(coolant.flood_enable); } } if (flags[COOLANT_MIST]) { coolant.mist_enable = (cmCoolantEnable)value[COOLANT_MIST]; - if (!((coolant.mist_enable & 0x01) ^ coolant.mist_polarity)) { - _set_mist_enable_bit_hi(); - } else { - _set_mist_enable_bit_lo(); +// if (!((coolant.mist_enable & 0x01) ^ coolant.mist_polarity)) { +// _set_mist_enable_bit_hi(); +// } else { +// _set_mist_enable_bit_lo(); +// } + if (mist_enable_output != nullptr) { + mist_enable_output->setValue(coolant.mist_enable); } } } diff --git a/g2core/cycle_homing.cpp b/g2core/cycle_homing.cpp index 93c4d130c..c05767d9a 100644 --- a/g2core/cycle_homing.cpp +++ b/g2core/cycle_homing.cpp @@ -96,6 +96,26 @@ static stat_t _set_homing_func(stat_t (*func)(int8_t axis)) { return (STAT_EAGAIN); } +/* + * _homing_handler - a gpioDigitalInputHandler to capture pin change events + * Will be registered only during homing mode - see gpio.h for more info + */ +gpioDigitalInputHandler _homing_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (cm.cycle_state != CYCLE_HOMING) { return false; } + if (triggering_pin_number != hm.homing_input) { return false; } + if (edge != INPUT_EDGE_LEADING) { return false; } + + en_take_encoder_snapshot(); + cm_start_hold(); + + return false; // allow others to see this notice + }, + 100, // priority + nullptr // next - nullptr to start with +}; + + /*********************************************************************************** **** G28.2 Homing Cycle *********************************************************** ***********************************************************************************/ @@ -224,7 +244,7 @@ static stat_t _homing_axis_start(int8_t axis) { cm.homed[axis] = false; // trap axis mis-configurations - if (fp_ZERO(cm.a[axis].homing_input)) { + if (cm.a[axis].homing_input) { return (_homing_error_exit(axis, STAT_HOMING_ERROR_HOMING_INPUT_MISCONFIGURED)); } if (fp_ZERO(cm.a[axis].search_velocity)) { @@ -243,7 +263,8 @@ static stat_t _homing_axis_start(int8_t axis) { // Nothing to do about direction now that direction is explicit // However, here's a good place to stash the homing_switch: hm.homing_input = cm.a[axis].homing_input; - gpio_set_homing_mode(hm.homing_input, true); + din_handlers[INPUT_ACTION_INTERNAL].registerHandler(&_homing_handler); + hm.axis = axis; // persist the axis hm.search_velocity = std::abs(cm.a[axis].search_velocity); // search velocity is always positive hm.latch_velocity = std::abs(cm.a[axis].latch_velocity); // latch velocity is always positive @@ -328,7 +349,7 @@ static stat_t _homing_axis_set_position(int8_t axis) // set axis zero / max and } cm_set_axis_jerk(axis, hm.saved_jerk); // restore the max jerk value - gpio_set_homing_mode(hm.homing_input, false); // end homing mode + din_handlers[INPUT_ACTION_INTERNAL].deregisterHandler(&_homing_handler); // end homing mode return (_set_homing_func(_homing_axis_start)); } diff --git a/g2core/cycle_probing.cpp b/g2core/cycle_probing.cpp index 1e49f6af1..b19af1000 100644 --- a/g2core/cycle_probing.cpp +++ b/g2core/cycle_probing.cpp @@ -123,6 +123,24 @@ static void _motion_end_callback(float* vect, bool* flag) pb.wait_for_motion_end = false; } +/* + * _probing_handler - a gpioDigitalInputHandler to capture pin change events + * Will be registered only during homing mode - see gpio.h for more info + */ +gpioDigitalInputHandler _probing_handler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (cm.cycle_state != CYCLE_PROBE) { return false; } + if (triggering_pin_number != pb.probe_input) { return false; } + + en_take_encoder_snapshot(); + cm_start_hold(); + + return false; // allow others to see this notice + }, + 100, // priority + nullptr // next - nullptr to start with +}; + /*********************************************************************************** **** G38.x Probing Cycle ********************************************************** ***********************************************************************************/ @@ -130,8 +148,8 @@ static void _motion_end_callback(float* vect, bool* flag) /*********************************************************************************** * cm_probing_cycle_start() - G38.x probing cycle using contact (digital input) * - * cm_probe_cycle_start() is the entry point for a probe cycle. It checks for - * some errors, sets up the cycle, then prevents any new commands from queuing + * cm_probe_cycle_start() is the entry point for a probe cycle. It checks for + * some errors, sets up the cycle, then prevents any new commands from queuing * to the planner so that the planner can move to a stop and report motion stopped. * * --- Some further details --- @@ -154,12 +172,12 @@ static void _motion_end_callback(float* vect, bool* flag) * PROBE_SUCCEEDED, then we roll 0 to 1, and 1 to 2, up to PROBES_STORED-1. * The oldest probe is "lost." * - * Alarms and exceptions: It is *not* necessarily an error condition for the - * probe not to trigger, depending on the G38.x command received. It is an error + * Alarms and exceptions: It is *not* necessarily an error condition for the + * probe not to trigger, depending on the G38.x command received. It is an error * for the limit or homing switches to fire, or for some other configuration error. * These are trapped and cause Alarms. - * - * Note: Spindle and coolant are not affected during probing. Some probes require + * + * Note: Spindle and coolant are not affected during probing. Some probes require * the spindle to be turned on. * * Note: When coding a cycle (like this one) you get to perform one queued @@ -168,15 +186,15 @@ static void _motion_end_callback(float* vect, bool* flag) * sets a flag in the probing object (pb.waiting_for_motion_end) to tell us that * the move has finished. The runtime has a special exception for probing and * homing where if a move is interrupted it clears it out of the queue. - * - * You must also wait until the last move has actually completed before declaring - * the cycle to be done. Otherwise there is a nasty race condition in the - * _controller_HSM() that may accept the next command before the position of the - * final move has been recorded in the Gcode model. That's part of what what the + * + * You must also wait until the last move has actually completed before declaring + * the cycle to be done. Otherwise there is a nasty race condition in the + * _controller_HSM() that may accept the next command before the position of the + * final move has been recorded in the Gcode model. That's part of what what the * wait_for_motion_end callback is about. */ -uint8_t cm_straight_probe(float target[], bool flags[], bool trip_sense, bool alarm_flag) +uint8_t cm_straight_probe(float target[], bool flags[], bool trip_sense, bool alarm_flag) { // error if zero feed rate if (fp_ZERO(cm.gm.feed_rate)) { @@ -190,7 +208,7 @@ uint8_t cm_straight_probe(float target[], bool flags[], bool trip_sense, bool al } // initialize the probe input; error if no probe input specified - if ((pb.probe_input = gpio_get_probing_input()) == -1) { + if ((pb.probe_input = cm.probe_input) == -1) { return(cm_alarm(STAT_NO_PROBE_INPUT_CONFIGURED, "No probe input")); } @@ -213,19 +231,19 @@ uint8_t cm_straight_probe(float target[], bool flags[], bool trip_sense, bool al pb.wait_for_motion_end = true; mp_queue_command(_motion_end_callback, nullptr, nullptr); // note: these args are ignored return (STAT_OK); -} +} /*********************************************************************************** * cm_probing_cycle_callback() - handle probing progress * - * This is called regularly from the controller. If we report NOOP, the controller - * will continue with other tasks. Otherwise the controller will not execute any + * This is called regularly from the controller. If we report NOOP, the controller + * will continue with other tasks. Otherwise the controller will not execute any * later tasks, including read any more "data". */ -uint8_t cm_probing_cycle_callback(void) +uint8_t cm_probing_cycle_callback(void) { - if ((cm.cycle_state != CYCLE_PROBE) && (cm.probe_state[0] != PROBE_WAITING)) { + if ((cm.cycle_state != CYCLE_PROBE) && (cm.probe_state[0] != PROBE_WAITING)) { return (STAT_NOOP); // exit if not in a probing cycle } if (pb.wait_for_motion_end) { // sync to planner move ends (using callback) @@ -238,14 +256,14 @@ uint8_t cm_probing_cycle_callback(void) * _probing_start() - start the probe or skip it if contact is already active */ -static uint8_t _probing_start() +static uint8_t _probing_start() { // so optimistic... ;) // These initializations are required before starting the probing cycle but must - // be done after the planner has exhausted all current moves as they affect the - // runtime (specifically the digital input modes). Side effects would include + // be done after the planner has exhausted all current moves as they affect the + // runtime (specifically the digital input modes). Side effects would include // limit switches initiating probe actions instead of just killing movement - + cm.probe_state[0] = PROBE_FAILED; cm.machine_state = MACHINE_CYCLE; cm.cycle_state = CYCLE_PROBE; @@ -255,7 +273,7 @@ static uint8_t _probing_start() pb.saved_units_mode = (cmUnitsMode)cm_get_units_mode(ACTIVE_MODEL); pb.saved_soft_limits = cm_get_soft_limits(); cm_set_soft_limits(false); - + // set working values cm_set_distance_mode(ABSOLUTE_DISTANCE_MODE); cm_set_units_mode(MILLIMETERS); @@ -271,7 +289,7 @@ static uint8_t _probing_start() return(_probing_exception_exit(STAT_PROBE_TRAVEL_TOO_SMALL)); } - gpio_set_probing_mode(pb.probe_input, true); + din_handlers[INPUT_ACTION_INTERNAL].registerHandler(&_probing_handler); // Get initial probe state, and don't probe if we're already tripped. // If the initial input is the same as the trip_sense it's an error. @@ -279,7 +297,7 @@ static uint8_t _probing_start() return(_probing_exception_exit(STAT_PROBE_IS_ALREADY_TRIPPED)); } - // Everything checks out. Run the probe move + // Everything checks out. Run the probe move _probe_move(pb.target, pb.flags); pb.func = _probing_backoff; return (STAT_EAGAIN); @@ -291,10 +309,10 @@ static uint8_t _probing_start() * Back off to the measured touch position captured by encoder snapshot */ -static stat_t _probing_backoff() +static stat_t _probing_backoff() { - // Test if we've contacted. If so, do the backoff. Convert the contact position - // captured from the encoder in step space to steps to mm. The encoder snapshot + // Test if we've contacted. If so, do the backoff. Convert the contact position + // captured from the encoder in step space to steps to mm. The encoder snapshot // was taken by input interrupt at the time of closure. if (pb.trip_sense == gpio_read_input(pb.probe_input)) { // exclusive or for booleans @@ -318,7 +336,7 @@ static stat_t _probing_backoff() static stat_t _probe_move(const float target[], const bool flags[]) { - cm_set_absolute_override(MODEL, ABSOLUTE_OVERRIDE_ON); + cm_set_absolute_override(MODEL, ABSOLUTE_OVERRIDE_ON); pb.wait_for_motion_end = true; // set this BEFORE the motion starts cm_straight_feed(target, flags); mp_queue_command(_motion_end_callback, nullptr, nullptr); // the last two arguments are ignored anyway @@ -331,12 +349,12 @@ static stat_t _probe_move(const float target[], const bool flags[]) * _probing_finish() - exit for successful and non-contacted (failed) probes */ -static void _probe_restore_settings() +static void _probe_restore_settings() { - gpio_set_probing_mode(pb.probe_input, false); // set input back to normal operation + din_handlers[INPUT_ACTION_INTERNAL].deregisterHandler(&_probing_handler); for (uint8_t axis = 0; axis < AXES; axis++) { // restore axis jerks - cm.a[axis].jerk_max = pb.saved_jerk[axis]; + cm.a[axis].jerk_max = pb.saved_jerk[axis]; } cm_set_absolute_override(MODEL, ABSOLUTE_OVERRIDE_OFF); // release abs override and restore work offsets cm_set_distance_mode(pb.saved_distance_mode); diff --git a/g2core/device/max31865/max31865.h b/g2core/device/max31865/max31865.h index 9908860f0..ab9bf6006 100644 --- a/g2core/device/max31865/max31865.h +++ b/g2core/device/max31865/max31865.h @@ -405,6 +405,13 @@ struct MAX31865 final { return _rtd_value; }; + float getPullupResistance() { + return _pullup_resistance; + } + void setPullupResistance(const float r) { + _pullup_resistance = r; + } + // getValue is supposed to request a new value, block, and then return the result // PUNT - return the same as getRaw() int32_t getValue() { @@ -463,4 +470,119 @@ struct MAX31865 final { }; + +// A gpioAnalogInputPin subclass for the MAX31865 + +template +struct gpioAnalogInputPin> : gpioAnalogInput { +protected: // so we know if anyone tries to reach in + ioEnabled enabled; // -1=unavailable, 0=disabled, 1=enabled + AnalogInputType_t type; + + uint8_t ext_pin_number; // the number used externally for this pin ("in" + ext_pin_number) + + using ADCPin_t = MAX31865; + + ADCPin_t pin; // the actual pin object itself + +public: + // In constructor, simply forward all values to the pin + // To get a different behavior, override this object. + template + gpioAnalogInputPin(const ioEnabled _enabled, const AnalogInputType_t _type, const uint8_t _ext_pin_number, T&&... additional_values) : + gpioAnalogInput{}, + enabled{_enabled}, + type{_type}, + ext_pin_number{_ext_pin_number}, + pin{Motate::kNormal, [&](bool e){this->adc_has_new_value(e);}, additional_values...} + { + // nothing to do here + }; + + // functions for use by other parts of the code, and are overridden + + ioEnabled getEnabled() override + { + return enabled; + }; + bool setEnabled(const ioEnabled m) override + { + if (enabled == IO_UNAVAILABLE) { + return false; + } + enabled = m; + return true; + }; + + float getValue() override + { + if (enabled != IO_ENABLED) { + return 0; + } + return pin.getVoltage(); + }; + float getResistance() override + { + if (enabled != IO_ENABLED) { + return -1; + } + return pin.getResistance(); + }; + + AnalogInputType_t getType() override + { + return type; + }; + bool setType(const AnalogInputType_t t) override + { + // NOTE: Allow setting type to AIN_TYPE_EXTERNAL + if (t == AIN_TYPE_INTERNAL) { + return false; + } + type = t; + return true; + }; + + AnalogCircuit_t getCircuit() override + { + return AIN_CIRCUIT_EXTERNAL; + }; + bool setCircuit(const AnalogCircuit_t c) override + { + // prevent setting circuit to anything but AIN_CIRCUIT_EXTERNAL + if (c == AIN_CIRCUIT_EXTERNAL) { + return true; + } + return false; + }; + + float getParameter(const uint8_t p) override + { + if (p == 0) { + return pin.getPullupResistance(); + } + return 0; + }; + bool setParameter(const uint8_t p, const float v) override + { + if (p == 0) { + pin.setPullupResistance(v); + return true; + } + return false; + }; + + + void startSampling() override { + pin.startSampling(); + }; + + // support function for pin value update interrupt handling + + void adc_has_new_value(bool err) { +// float raw_adc_value = pin.getRaw(); +// history.add_sample(raw_adc_value); + }; +}; + #endif // max31865_h diff --git a/g2core/g2core.xcodeproj/project.pbxproj b/g2core/g2core.xcodeproj/project.pbxproj index 289068333..acf15e30c 100644 --- a/g2core/g2core.xcodeproj/project.pbxproj +++ b/g2core/g2core.xcodeproj/project.pbxproj @@ -344,6 +344,20 @@ passBuildSettingsInEnvironment = 1; productName = g3_due; }; + D4C9C2FD20164DE200487D7F /* G2 gQuadratic SMW3D r7 */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION) VERBOSE=1 COLOR=0 CONFIG=r7 DEBUG=0"; + buildConfigurationList = D4C9C2FE20164DE200487D7F /* Build configuration list for PBXLegacyTarget "G2 gQuadratic SMW3D r7" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + buildWorkingDirectory = .; + dependencies = ( + ); + name = "G2 gQuadratic SMW3D r7"; + passBuildSettingsInEnvironment = 1; + productName = g3_due; + }; D4CBBAD01A0D51FE00150DE2 /* G2 G2V9k Ultimaker */ = { isa = PBXLegacyTarget; buildArgumentsString = "$(ACTION) VERBOSE=1 COLOR=0 CONFIG=UltimakerTests BOARD=g2v9k"; @@ -441,6 +455,7 @@ D4782AB61D9E39EC00B32136 /* G2 EggBot */, D492E5AE1E54C2B4005ED97D /* G2 gQuadratic AxiDraw v3 */, D43DFE011E8C84B400A2030D /* G2 gQuadratic Ultimaker2+ */, + D4C9C2FD20164DE200487D7F /* G2 gQuadratic SMW3D r7 */, ); }; /* End PBXProject section */ @@ -791,6 +806,22 @@ }; name = Release; }; + D4C9C2FF20164DE200487D7F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PATH = "$PATH:/usr/local/gcc-arm-none-eabi/bin"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D4C9C30020164DE200487D7F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PATH = "$PATH:/usr/local/gcc-arm-none-eabi/bin"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; D4CBBAD21A0D51FE00150DE2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -950,6 +981,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D4C9C2FE20164DE200487D7F /* Build configuration list for PBXLegacyTarget "G2 gQuadratic SMW3D r7" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D4C9C2FF20164DE200487D7F /* Debug */, + D4C9C30020164DE200487D7F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D4CBBAD11A0D51FE00150DE2 /* Build configuration list for PBXLegacyTarget "G2 G2V9k Ultimaker" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/g2core/g2core.xcodeproj/xcshareddata/xcschemes/G2 gQuadratic SMW3d r7.xcscheme b/g2core/g2core.xcodeproj/xcshareddata/xcschemes/G2 gQuadratic SMW3d r7.xcscheme new file mode 100644 index 000000000..10dea5ad5 --- /dev/null +++ b/g2core/g2core.xcodeproj/xcshareddata/xcschemes/G2 gQuadratic SMW3d r7.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/g2core/gpio.cpp b/g2core/gpio.cpp index e731386ca..3abe812b0 100644 --- a/g2core/gpio.cpp +++ b/g2core/gpio.cpp @@ -57,245 +57,13 @@ #include "MotateTimers.h" using namespace Motate; -/**** Allocate structures ****/ - -d_in_t d_in[D_IN_CHANNELS]; -d_out_t d_out[D_OUT_CHANNELS]; -a_in_t a_in[A_IN_CHANNELS]; -a_out_t a_out[A_OUT_CHANNELS]; - -/**** Extended DI structure ****/ - -// To be merged with ioDigitalInput later. -// For now, we use a pointer to the correct d_in, since the old code did. -// input_pin_num is the Motate pin number. -// ext_pin_number is the JSON ("external") pin number, as in "di1". -template -struct ioDigitalInputExt { - IRQPin input_pin; - - /* Priority only needs set once in the system during startup. - * However, if we wish to switch the interrupt trigger, here are other options: - * kPinInterruptOnRisingEdge - * kPinInterruptOnFallingEdge - * - * To change the trigger or priority provide a third paramater intValue that will - * be called as pin.setInterrupts(intValue), or call pin.setInterrupts at any point. - * Note that it may cause an interrupt to fire *immediately*! - * intValue defaults to kPinInterruptOnChange|kPinInterruptPriorityMedium if not specified. - */ - ioDigitalInputExt() : input_pin {kPullUp|kDebounce, [&]{this->pin_changed();}} { - }; - - ioDigitalInputExt(const ioDigitalInputExt&) = delete; // delete copy - ioDigitalInputExt(ioDigitalInputExt&&) = delete; // delete move - - static constexpr d_in_t *in = &d_in[ext_pin_number-1]; - - void reset() { - if (D_IN_CHANNELS < ext_pin_number) { return; } - - if (in->mode == IO_MODE_DISABLED) { - in->state = INPUT_DISABLED; - return; - } - - bool pin_value = (bool)input_pin; - int8_t pin_value_corrected = (pin_value ^ ((int)in->mode ^ 1)); // correct for NO or NC mode - in->state = (ioState)pin_value_corrected; - } - - void pin_changed() { - if (D_IN_CHANNELS < ext_pin_number) { return; } - - // return if input is disabled (not supposed to happen) - if (in->mode == IO_MODE_DISABLED) { - in->state = INPUT_DISABLED; - return; - } - - // return if the input is in lockout period (take no action) - if (in->lockout_timer.isSet() && !in->lockout_timer.isPast()) { - return; - } - - // return if no change in state - bool pin_value = (bool)input_pin; - int8_t pin_value_corrected = (pin_value ^ ((int)in->mode ^ 1)); // correct for NO or NC mode - if (in->state == (ioState)pin_value_corrected) { - return; - } - - // lockout the pin for lockout_ms - in->lockout_timer.set(in->lockout_ms); - - // record the changed state - in->state = (ioState)pin_value_corrected; - if (pin_value_corrected == INPUT_ACTIVE) { - in->edge = INPUT_EDGE_LEADING; - } else { - in->edge = INPUT_EDGE_TRAILING; - } - - // perform homing operations if in homing mode - if (in->homing_mode) { - if (in->edge == INPUT_EDGE_LEADING) { // we only want the leading edge to fire - en_take_encoder_snapshot(); - cm_start_hold(); - } - return; - } - - // perform probing operations if in probing mode - if (in->probing_mode) { - // We want to capture either way. - // Probing tests the start condition for the correct direction ahead of time. - // If we see any edge, it's the right one. - en_take_encoder_snapshot(); - cm_start_hold(); - return; - } - - // *** NOTE: From this point on all conditionals assume we are NOT in homing or probe mode *** - - // trigger the action on leading edges - if (in->edge == INPUT_EDGE_LEADING) { - if (in->action == INPUT_ACTION_STOP) { - cm_start_hold(); - } - if (in->action == INPUT_ACTION_FAST_STOP) { - cm_start_hold(); // for now is same as STOP - } - if (in->action == INPUT_ACTION_HALT) { - cm_halt_all(); // hard stop, including spindle and coolant - } - if (in->action == INPUT_ACTION_ALARM) { - char msg[10]; - sprintf(msg, "input %d", ext_pin_number); - cm_alarm(STAT_ALARM, msg); - } - if (in->action == INPUT_ACTION_SHUTDOWN) { - char msg[10]; - sprintf(msg, "input %d", ext_pin_number); - cm_shutdown(STAT_SHUTDOWN, msg); - } - if (in->action == INPUT_ACTION_PANIC) { - char msg[10]; - sprintf(msg, "input %d", ext_pin_number); - cm_panic(STAT_PANIC, msg); - } - if (in->action == INPUT_ACTION_RESET) { - hw_hard_reset(); - } - - // these functions also trigger on the leading edge - - if (in->function == INPUT_FUNCTION_LIMIT) { - cm.limit_requested = ext_pin_number; - - } else if (in->function == INPUT_FUNCTION_SHUTDOWN) { - cm.shutdown_requested = ext_pin_number; - - } else if (in->function == INPUT_FUNCTION_INTERLOCK) { - cm.safety_interlock_disengaged = ext_pin_number; - } - } // if (in->edge == INPUT_EDGE_LEADING) - - // trigger interlock release on trailing edge - if (in->edge == INPUT_EDGE_TRAILING) { - if (in->function == INPUT_FUNCTION_INTERLOCK) { - cm.safety_interlock_reengaged = ext_pin_number; - } - } - - sr_request_status_report(SR_REQUEST_TIMED); //+++++ Put this one back in. - }; -}; +/**** + * + * Important: Do not directly allocate or access pins here! + * Do that in board_gpio.cpp! + * + ****/ -/**** Setup Low Level Stuff ****/ - -ioDigitalInputExt _din1; -ioDigitalInputExt _din2; -ioDigitalInputExt _din3; -ioDigitalInputExt _din4; -ioDigitalInputExt _din5; -ioDigitalInputExt _din6; -ioDigitalInputExt _din7; -ioDigitalInputExt _din8; -ioDigitalInputExt _din9; -ioDigitalInputExt _din10; -ioDigitalInputExt _din11; -ioDigitalInputExt _din12; - -// Generated with: -// perl -e 'for($i=1;$i<14;$i++) { print "#if OUTPUT${i}_PWM == 1\nstatic PWMOutputPin output_${i}_pin;\n#else\nstatic PWMLikeOutputPin output_${i}_pin;\n#endif\n";}' -// BEGIN generated -#if OUTPUT1_PWM == 1 -static PWMOutputPin output_1_pin {(DO1_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_1_pin {(DO1_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT2_PWM == 1 -static PWMOutputPin output_2_pin {(DO2_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_2_pin {(DO2_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT3_PWM == 1 -static PWMOutputPin output_3_pin {(DO3_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_3_pin {(DO3_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT4_PWM == 1 -static PWMOutputPin output_4_pin {(DO4_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_4_pin {(DO4_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT5_PWM == 1 -static PWMOutputPin output_5_pin {(DO5_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_5_pin {(DO5_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT6_PWM == 1 -static PWMOutputPin output_6_pin {(DO6_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_6_pin {(DO6_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT7_PWM == 1 -static PWMOutputPin output_7_pin {(DO7_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_7_pin {(DO7_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT8_PWM == 1 -static PWMOutputPin output_8_pin {(DO8_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_8_pin {(DO8_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT9_PWM == 1 -static PWMOutputPin output_9_pin {(DO9_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_9_pin {(DO9_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT10_PWM == 1 -static PWMOutputPin output_10_pin {(DO10_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_10_pin {(DO10_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT11_PWM == 1 -static PWMOutputPin output_11_pin {(DO11_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_11_pin {(DO11_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT12_PWM == 1 -static PWMOutputPin output_12_pin {(DO12_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_12_pin {(DO12_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -#if OUTPUT13_PWM == 1 -static PWMOutputPin output_13_pin {(DO13_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#else -static PWMLikeOutputPin output_13_pin {(DO13_MODE == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow, 200000}; -#endif -// END generated /************************************************************************************ **** CODE ************************************************************************** @@ -307,99 +75,11 @@ static PWMLikeOutputPin output_13_pin {(DO13_MODE == IO_AC void gpio_init(void) { - // These are here due to an unfound glitch where for Timer-based pins the frequency isn't getting set. - - // Generated with: - // perl -e 'for($i=1;$i<14;$i++) { print "output_${i}_pin.setFrequency(200000);\n";}' - // BEGIN generated -// output_1_pin.setFrequency(200000); -// output_2_pin.setFrequency(200000); -// output_3_pin.setFrequency(200000); -// output_4_pin.setFrequency(200000); -// output_5_pin.setFrequency(200000); -// output_6_pin.setFrequency(200000); -// output_7_pin.setFrequency(200000); -// output_8_pin.setFrequency(200000); -// output_9_pin.setFrequency(200000); -// output_10_pin.setFrequency(200000); -// output_11_pin.setFrequency(200000); -// output_12_pin.setFrequency(200000); -// output_13_pin.setFrequency(200000); - // END generated - return(gpio_reset()); } -void outputs_reset(void) { - // If the output is ACTIVE_LOW set it to 1. ACTIVE_HIGH gets set to 0. -#if D_OUT_CHANNELS >= 1 - if (d_out[1-1].mode != IO_MODE_DISABLED) { (output_1_pin = (d_out[1-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 2 - if (d_out[2-1].mode != IO_MODE_DISABLED) { (output_2_pin = (d_out[2-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 3 - if (d_out[3-1].mode != IO_MODE_DISABLED) { (output_3_pin = (d_out[3-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 4 - if (d_out[4-1].mode != IO_MODE_DISABLED) { (output_4_pin = (d_out[4-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 5 - if (d_out[5-1].mode != IO_MODE_DISABLED) { (output_5_pin = (d_out[5-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 6 - if (d_out[6-1].mode != IO_MODE_DISABLED) { (output_6_pin = (d_out[6-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 7 - if (d_out[7-1].mode != IO_MODE_DISABLED) { (output_7_pin = (d_out[7-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 8 - if (d_out[8-1].mode != IO_MODE_DISABLED) { (output_8_pin = (d_out[8-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 9 - if (d_out[9-1].mode != IO_MODE_DISABLED) { (output_9_pin = (d_out[9-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 10 - if (d_out[10-1].mode != IO_MODE_DISABLED) { (output_10_pin = (d_out[10-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 11 - if (d_out[11-1].mode != IO_MODE_DISABLED) { (output_11_pin = (d_out[11-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 12 - if (d_out[12-1].mode != IO_MODE_DISABLED) { (output_12_pin = (d_out[12-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -#if D_OUT_CHANNELS >= 13 - if (d_out[13-1].mode != IO_MODE_DISABLED) { (output_13_pin = (d_out[13-1].mode == IO_ACTIVE_LOW) ? 1.0 : 0.0); } -#endif -} - -void inputs_reset(void) { - d_in_t *in; - - for (uint8_t i=0; imode == IO_MODE_DISABLED) { - in->state = INPUT_DISABLED; - continue; - } - in->lockout_ms = INPUT_LOCKOUT_MS; - in->lockout_timer.clear(); - } - - _din1.reset(); - _din2.reset(); - _din3.reset(); - _din4.reset(); - _din5.reset(); - _din6.reset(); - _din7.reset(); - _din8.reset(); - _din9.reset(); - _din10.reset(); - _din11.reset(); - _din12.reset(); - -} +// implement void outputs_reset(void) in board_gpio.cpp +// implement void inputs_reset(void) in board_gpio.cpp void gpio_reset(void) { @@ -407,65 +87,22 @@ void gpio_reset(void) outputs_reset(); } -/****************************** - * Interrupt Service Routines * - ******************************/ -/* - * ARM pin change interrupts are setup above when defining the IRQPins (inside the ioDigitalInputExt). - */ - /******************************************** **** Digital Input Supporting Functions **** ********************************************/ -/* - * switch_rtc_callback() - called from RTC for each RTC tick. - * - * Each switch has a counter which is initially set to negative SW_DEGLITCH_TICKS. - * When a switch closure is DETECTED the count increments for each RTC tick. - * When the count reaches zero the switch is tripped and action occurs. - * The counter continues to increment positive until the lockout is exceeded. - */ /* - * gpio_set_homing_mode() - set/clear input to homing mode - * gpio_set_probing_mode() - set/clear input to probing mode - * gpio_get_probing_input() - get probing input * gpio_read_input() - read conditioned input * - (* Note: input_num_ext means EXTERNAL input number -- 1-based + * Note: input_num means the actual input number (1-based), not the exposed-as number */ -void gpio_set_homing_mode(const uint8_t input_num_ext, const bool is_homing) -{ - if (input_num_ext == 0) { - return; - } - d_in[input_num_ext-1].homing_mode = is_homing; -} -void gpio_set_probing_mode(const uint8_t input_num_ext, const bool is_probing) +bool gpio_read_input(const uint8_t input_num) { - if (input_num_ext == 0) { - return; - } - d_in[input_num_ext-1].probing_mode = is_probing; -} - -int8_t gpio_get_probing_input(void) -{ - for (uint8_t i = 0; i <= D_IN_CHANNELS; i++) { - if (d_in[i-1].function == INPUT_FUNCTION_PROBE) { - return (i); - } - } - return (-1); -} - -bool gpio_read_input(const uint8_t input_num_ext) -{ - if (input_num_ext == 0) { + if (input_num == 0) { return false; } - return (d_in[input_num_ext-1].state); + return (d_in[input_num-1]->getState()); } @@ -475,209 +112,262 @@ bool gpio_read_input(const uint8_t input_num_ext) * These functions are not part of the NIST defined functions ***********************************************************************************/ -static stat_t _input_set_helper(nvObj_t *nv, const int8_t lower_bound, const int8_t upper_bound) +// internal helpers to get input and output object from the cfgArray target +// specified by an nv pointer + +template +type* _io(const nvObj_t *nv) { + return reinterpret_cast(cfgArray[nv->index].target); +}; + +gpioDigitalInput* _i(const nvObj_t *nv) { return _io(nv); } +gpioDigitalInputReader* _ir(const nvObj_t *nv) { return _io(nv); } +gpioDigitalOutput* _o(const nvObj_t *nv) { return _io(nv); } +gpioDigitalOutputWriter* _ow(const nvObj_t *nv) { return _io(nv); } +gpioAnalogInput* _ai(const nvObj_t *nv) { return _io(nv); } +gpioAnalogInputReader* _air(const nvObj_t *nv) { return _io(nv); } + +gpioDigitalInputReader in1; +gpioDigitalInputReader in2; +gpioDigitalInputReader in3; +gpioDigitalInputReader in4; +gpioDigitalInputReader in5; +gpioDigitalInputReader in6; +gpioDigitalInputReader in7; +gpioDigitalInputReader in8; +gpioDigitalInputReader in9; +gpioDigitalInputReader in10; +gpioDigitalInputReader in11; +gpioDigitalInputReader in12; +gpioDigitalInputReader in13; +gpioDigitalInputReader in14; +gpioDigitalInputReader in15; +gpioDigitalInputReader in16; + +gpioDigitalInputReader* const in_r[16] = {&in1, &in2, &in3, &in4, &in5, &in6, &in7, &in8, &in9, &in10, &in11, &in12, &in13, &in14, &in15, &in16}; + +gpioDigitalOutputWriter out1; +gpioDigitalOutputWriter out2; +gpioDigitalOutputWriter out3; +gpioDigitalOutputWriter out4; +gpioDigitalOutputWriter out5; +gpioDigitalOutputWriter out6; +gpioDigitalOutputWriter out7; +gpioDigitalOutputWriter out8; +gpioDigitalOutputWriter out9; +gpioDigitalOutputWriter out10; +gpioDigitalOutputWriter out11; +gpioDigitalOutputWriter out12; +gpioDigitalOutputWriter out13; +gpioDigitalOutputWriter out14; +gpioDigitalOutputWriter out15; +gpioDigitalOutputWriter out16; + +gpioDigitalOutputWriter* const out_w[16] = {&out1, &out2, &out3, &out4, &out5, &out6, &out7, &out8, &out9, &out10, &out11, &out12, &out13, &out14, &out15, &out16}; + +// lists for the various inputAction events +gpioDigitalInputHandlerList din_handlers[INPUT_ACTION_ACTUAL_MAX+1]; + +gpioAnalogInputReader ain1; +gpioAnalogInputReader ain2; +gpioAnalogInputReader ain3; +gpioAnalogInputReader ain4; +gpioAnalogInputReader ain5; +gpioAnalogInputReader ain6; +gpioAnalogInputReader ain7; +gpioAnalogInputReader ain8; + +gpioAnalogInputReader* const ain_r[8] = {&ain1, &ain2, &ain3, &ain4, &ain5, &ain6, &ain7, &ain8}; + +/* + * Get/set enabled + */ +stat_t din_get_en(nvObj_t *nv) { - if ((nv->value < lower_bound) || (nv->value >= upper_bound)) { - return (STAT_INPUT_VALUE_RANGE_ERROR); - } - set_ui8(nv); // will this work in -1 is a valid value? - if (cm_get_machine_state() != MACHINE_INITIALIZING) { - inputs_reset(); - } - return (STAT_OK); + return _i(nv)->getEnabled(nv); +} +stat_t din_set_en(nvObj_t *nv) +{ + return _i(nv)->setEnabled(nv); } -static stat_t _output_set_helper(nvObj_t *nv, const int8_t lower_bound, const int8_t upper_bound) +/* + * Get/set input polarity + */ +stat_t din_get_po(nvObj_t *nv) { - if ((nv->value < lower_bound) || (nv->value >= upper_bound)) { - return (STAT_INPUT_VALUE_RANGE_ERROR); - } - set_ui8(nv); // will this work in -1 is a valid value? - if (cm_get_machine_state() != MACHINE_INITIALIZING) { - outputs_reset(); - } - return (STAT_OK); + return _i(nv)->getPolarity(nv); +} +stat_t din_set_po(nvObj_t *nv) +{ + return _i(nv)->setPolarity(nv); } -stat_t io_set_mo(nvObj_t *nv) // input type or disabled +/* + * Get/set input action + */ +stat_t din_get_ac(nvObj_t *nv) +{ + return _i(nv)->getAction(nv); +} +stat_t din_set_ac(nvObj_t *nv) { -// return (_io_set_helper(nv, IO_MODE_DISABLED, IO_MODE_MAX)); - return (_input_set_helper(nv, IO_ACTIVE_LOW, IO_MODE_MAX)); + return _i(nv)->setAction(nv); } -stat_t io_set_ac(nvObj_t *nv) // input action +/* + * Get/set input function + */ + +/* + * Get/set input function + */ +stat_t din_get_in(nvObj_t *nv) +{ + return _i(nv)->getExternalNumber(nv); +} +stat_t din_set_in(nvObj_t *nv) { - return (_input_set_helper(nv, INPUT_ACTION_NONE, INPUT_ACTION_MAX)); + return _i(nv)->setExternalNumber(nv); } -stat_t io_set_fn(nvObj_t *nv) // input function +/* + * Get input state given an nv object + * Note: if this is not forwarded to an input or the input is disabled, + * it returns NULL. + */ +stat_t din_get_input(nvObj_t *nv) { - return (_input_set_helper(nv, INPUT_FUNCTION_NONE, INPUT_FUNCTION_MAX)); + return _ir(nv)->getState(nv); } + /* - * io_get_input() - return input state given an nv object + * Get/set enabled */ -stat_t io_get_input(nvObj_t *nv) +stat_t dout_get_en(nvObj_t *nv) { - char *num_start = nv->token; - if (*(nv->group) == 0) { - // if we don't have a group, then the group name is in the token - // skip over "in" - num_start+=2; - } - nv->value = d_in[strtol(num_start, NULL, 10)-1].state; + return _o(nv)->getEnabled(nv); +} +stat_t dout_set_en(nvObj_t *nv) +{ + return _o(nv)->setEnabled(nv); +} - if (nv->value > 1.1) { - nv->valuetype = TYPE_NULL; - } else { - nv->valuetype = TYPE_BOOL; - } - return (STAT_OK); +/* + * Get/set output polarity + */ +stat_t dout_get_po(nvObj_t *nv) +{ + return _o(nv)->getPolarity(nv); +} +stat_t dout_set_po(nvObj_t *nv) +{ + return _o(nv)->setPolarity(nv); } -stat_t io_set_domode(nvObj_t *nv) // output function +/* + * Get/set output external number + */ +stat_t dout_get_out(nvObj_t *nv) { - char *num_start = nv->token; - if (*(nv->group) == 0) { - // if we don't have a group, then the group name is in the token - // skip over "out" - num_start+=3; - } - // the token has been stripped down to an ASCII digit string - use it as an index - uint8_t output_num = strtol(num_start, NULL, 10); + return _o(nv)->getExternalNumber(nv); +} +stat_t dout_set_out(nvObj_t *nv) +{ + return _o(nv)->setExternalNumber(nv); +} - if (output_num > D_OUT_CHANNELS) { - nv->valuetype = TYPE_NULL; - return(STAT_NO_GPIO); - } - // Force pins that aren't available to be "disabled" - switch (output_num) { - case 1: if (output_1_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 2: if (output_2_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 3: if (output_3_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 4: if (output_4_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 5: if (output_5_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 6: if (output_6_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 7: if (output_7_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 8: if (output_8_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 9: if (output_9_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 10: if (output_10_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 11: if (output_11_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 12: if (output_12_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - case 13: if (output_13_pin.isNull()) { nv->value = IO_MODE_DISABLED; } break; - - default: - break; - } +/* + * Get/set output state given an nv object + */ +stat_t dout_get_output(nvObj_t *nv) +{ + return _ow(nv)->getValue(nv); +} +stat_t dout_set_output(nvObj_t *nv) +{ + return _ow(nv)->setValue(nv); +} + - return (_output_set_helper(nv, IO_ACTIVE_LOW, IO_MODE_MAX)); +/* + * Get/set enabled + */ +stat_t ai_get_en(nvObj_t *nv) +{ + return _ai(nv)->getEnabled(nv); +} +stat_t ai_set_en(nvObj_t *nv) +{ + return _ai(nv)->setEnabled(nv); } /* - * io_get_output() - return output state given an nv object + * Get/set output external number */ -stat_t io_get_output(nvObj_t *nv) +stat_t ai_get_ain(nvObj_t *nv) { - char *num_start = nv->token; - if (*(nv->group) == 0) { - // if we don't have a group, then the group name is in the token - // skip over "out" - num_start+=3; - } - // the token has been stripped down to an ASCII digit string - use it as an index - uint8_t output_num = strtol(num_start, NULL, 10); + return _ai(nv)->getExternalNumber(nv); +} +stat_t ai_set_ain(nvObj_t *nv) +{ + return _ai(nv)->setExternalNumber(nv); +} - if (output_num > D_OUT_CHANNELS) { - nv->valuetype = TYPE_NULL; - return(STAT_NO_GPIO); - } +/* + * ain_get_value() - get the measured voltage level of the analog input + */ +stat_t ain_get_value(nvObj_t *nv) { + return _air(nv)->getValue(nv); +} +// no ain_set_value - ioMode outMode = d_out[output_num-1].mode; - if (outMode == IO_MODE_DISABLED) { -// nv->value = 0; - nv->valuetype = TYPE_NULL; // reports back as NULL - } else { - nv->valuetype = TYPE_FLOAT; - nv->precision = 2; - bool invert = (outMode == 0); - // Note: !! forces a value to boolean 0 or 1 - switch (output_num) { - case 1: { nv->value = (float)output_1_pin; } break; - case 2: { nv->value = (float)output_2_pin; } break; - case 3: { nv->value = (float)output_3_pin; } break; - case 4: { nv->value = (float)output_4_pin; } break; - case 5: { nv->value = (float)output_5_pin; } break; - case 6: { nv->value = (float)output_6_pin; } break; - case 7: { nv->value = (float)output_7_pin; } break; - case 8: { nv->value = (float)output_8_pin; } break; - case 9: { nv->value = (float)output_9_pin; } break; - case 10: { nv->value = (float)output_10_pin; } break; - case 11: { nv->value = (float)output_11_pin; } break; - case 12: { nv->value = (float)output_12_pin; } break; - case 13: { nv->value = (float)output_13_pin; } break; - - default: - { -// nv->value = 0; // inactive - nv->valuetype = TYPE_NULL; // reports back as NULL - } - } - if (invert) { - nv->value = 1.0 - nv->value; - } - } - return (STAT_OK); +/* + * ai_get_resistance() - get the measured resistance of the analog input + * NOTE: Requires the circuit type to be configured and the relevant parameters set + */ +stat_t ain_get_resistance(nvObj_t *nv) { + return _air(nv)->getResistance(nv); } +// no ai_set_resistance /* - * io_set_output() - return input state given an nv object + * ai_get_type() - get the measured voltage level of the analog input */ -stat_t io_set_output(nvObj_t *nv) -{ - char *num_start = nv->token; - if (*(nv->group) == 0) { - // if we don't have a group, then the group name is in the token - // skip over "out" - num_start+=3; - } - // the token has been stripped down to an ASCII digit string - use it as an index - uint8_t output_num = strtol(num_start, NULL, 10); - - ioMode outMode = d_out[output_num-1].mode; - if (outMode == IO_MODE_DISABLED) { - nv->value = 0; // Inactive? - } else { - bool invert = (outMode == 0); - float value = nv->value; - if (invert) { - value = 1.0 - value; - } - switch (output_num) { - // Generated with: - // perl -e 'for($i=1;$i<14;$i++) { print "case ${i}: { output_${i}_pin = value; } break;\n";}' - // BEGIN generated - case 1: { output_1_pin = value; } break; - case 2: { output_2_pin = value; } break; - case 3: { output_3_pin = value; } break; - case 4: { output_4_pin = value; } break; - case 5: { output_5_pin = value; } break; - case 6: { output_6_pin = value; } break; - case 7: { output_7_pin = value; } break; - case 8: { output_8_pin = value; } break; - case 9: { output_9_pin = value; } break; - case 10: { output_10_pin = value; } break; - case 11: { output_11_pin = value; } break; - case 12: { output_12_pin = value; } break; - case 13: { output_13_pin = value; } break; - // END generated - default: { nv->value = 0; } // inactive - } - } - return (STAT_OK); +stat_t ai_get_type(nvObj_t *nv) { + return _ai(nv)->getType(nv); +} +stat_t ai_set_type(nvObj_t *nv) { + return _ai(nv)->setType(nv); +} + +stat_t ai_get_circuit(nvObj_t *nv) { + return _ai(nv)->getCircuit(nv); +} +stat_t ai_set_circuit(nvObj_t *nv) { + return _ai(nv)->setCircuit(nv); } +stat_t ai_get_parameter(nvObj_t *nv, const uint8_t p) { + return _ai(nv)->getParameter(nv, p); +} +stat_t ai_set_parameter(nvObj_t *nv, const uint8_t p) { + return _ai(nv)->setParameter(nv, p); +} + +stat_t ai_get_p1(nvObj_t *nv) { return ai_get_parameter(nv, 0); }; +stat_t ai_set_p1(nvObj_t *nv) { return ai_set_parameter(nv, 0); }; +stat_t ai_get_p2(nvObj_t *nv) { return ai_get_parameter(nv, 1); }; +stat_t ai_set_p2(nvObj_t *nv) { return ai_set_parameter(nv, 1); }; +stat_t ai_get_p3(nvObj_t *nv) { return ai_get_parameter(nv, 2); }; +stat_t ai_set_p3(nvObj_t *nv) { return ai_set_parameter(nv, 2); }; +stat_t ai_get_p4(nvObj_t *nv) { return ai_get_parameter(nv, 3); }; +stat_t ai_set_p4(nvObj_t *nv) { return ai_set_parameter(nv, 3); }; +stat_t ai_get_p5(nvObj_t *nv) { return ai_get_parameter(nv, 4); }; +stat_t ai_set_p5(nvObj_t *nv) { return ai_set_parameter(nv, 4); }; + /*********************************************************************************** * TEXT MODE SUPPORT * Functions to print variables from the cfgArray table @@ -685,30 +375,77 @@ stat_t io_set_output(nvObj_t *nv) #ifdef __TEXT_MODE - static const char fmt_gpio_mo[] = "[%smo] input mode%17d [0=active-low,1=active-hi,2=disabled]\n"; + static const char fmt_gpio_in_en[] = "[%smo] input enabled%13d [-1=unavailable,0=disabled,1=enabled]\n"; + static const char fmt_gpio_in_po[] = "[%smo] input polarity%13d [0=normal/active-high,1=inverted/active-low]\n"; static const char fmt_gpio_ac[] = "[%sac] input action%15d [0=none,1=stop,2=fast_stop,3=halt,4=alarm,5=shutdown,6=panic,7=reset]\n"; static const char fmt_gpio_fn[] = "[%sfn] input function%13d [0=none,1=limit,2=interlock,3=shutdown,4=probe]\n"; - static const char fmt_gpio_in[] = "Input %s state: %5d\n"; - - static const char fmt_gpio_domode[] = "[%smo] output mode%16d [0=active low,1=active high,2=disabled]\n"; - static const char fmt_gpio_out[] = "Output %s state: %5d\n"; + static const char fmt_gpio_in[] = "[%sin] input external number%6d [0=none,1-16=inX shows the value of this din]\n"; + static const char fmt_gpio_state[] = "Input %s state: %5d\n"; + + static const char fmt_gpio_out_en[] = "[%smo] output enabled%12d [-1=unavailable,0=disabled,1=enabled]\n"; + static const char fmt_gpio_out_po[] = "[%smo] output polarity%12d [0=normal/active-high,1=inverted/active-low]\n"; + static const char fmt_gpio_out_out[] = "[%sout] output external number%5d [0=none,1-16=outX shows the value of this dout]\n"; + static const char fmt_gpio_out_state[] = "Output %s state: %5d\n"; + + static const char fmt_ain_value[] = "Analog input %s voltage: %5.2fV\n"; + static const char fmt_ain_resistance[] = "Analog input %s resistance: %5.2fohm\n"; + static const char fmt_gpio_ai_en[] = "[%smo] analog input enabled%12d [-1=unavailable,0=disabled,1=enabled]\n"; + static const char fmt_gpio_ai_ain[] = "[%sout] analog input external number%5d [0=none,1-8=ainX shows the value of this ai]\n"; + static const char fmt_ai_type[] = "[%s] input type%17d [0=disabled,1=internal,2=external]\n"; + static const char fmt_ai_circuit[] = "[%s] analog circuit%13d [0=disabled,1=pull-up,2=external,3=inverted op-amp,4=constant current inverted op-amp]\n"; + static const char fmt_ai_parameter[] = "[%s] circuit parameter%6.4f [usage varies by circuit type]\n"; static void _print_di(nvObj_t *nv, const char *format) { sprintf(cs.out_buf, format, nv->group, (int)nv->value); xio_writeline(cs.out_buf); } - void io_print_mo(nvObj_t *nv) {_print_di(nv, fmt_gpio_mo);} - void io_print_ac(nvObj_t *nv) {_print_di(nv, fmt_gpio_ac);} - void io_print_fn(nvObj_t *nv) {_print_di(nv, fmt_gpio_fn);} - void io_print_in(nvObj_t *nv) { - sprintf(cs.out_buf, fmt_gpio_in, nv->token, (int)nv->value); + void din_print_en(nvObj_t *nv) {_print_di(nv, fmt_gpio_in_en);} + void din_print_po(nvObj_t *nv) {_print_di(nv, fmt_gpio_in_po);} + void din_print_ac(nvObj_t *nv) {_print_di(nv, fmt_gpio_ac);} + void din_print_fn(nvObj_t *nv) {_print_di(nv, fmt_gpio_fn);} + void din_print_in(nvObj_t *nv) {_print_di(nv, fmt_gpio_in);} + void din_print_state(nvObj_t *nv) { + sprintf(cs.out_buf, fmt_gpio_state, nv->token, (int)nv->value); xio_writeline(cs.out_buf); } - void io_print_domode(nvObj_t *nv) {_print_di(nv, fmt_gpio_domode);} - void io_print_out(nvObj_t *nv) { - sprintf(cs.out_buf, fmt_gpio_out, nv->token, (int)nv->value); + void dout_print_en(nvObj_t *nv) {_print_di(nv, fmt_gpio_out_en);} + void dout_print_po(nvObj_t *nv) {_print_di(nv, fmt_gpio_out_po);} + void dout_print_out(nvObj_t *nv) {_print_di(nv, fmt_gpio_out_out);} + void dout_print_out_state(nvObj_t *nv) { + sprintf(cs.out_buf, fmt_gpio_out_state, nv->token, (int)nv->value); xio_writeline(cs.out_buf); } + + void ain_print_value(nvObj_t *nv) + { + sprintf(cs.out_buf, fmt_ain_value, nv->token, (float)nv->value); + xio_writeline(cs.out_buf); + } + void ain_print_resistance(nvObj_t *nv) + { + sprintf(cs.out_buf, fmt_ain_resistance, nv->token, (float)nv->value); + xio_writeline(cs.out_buf); + } + void ai_print_en(nvObj_t *nv) {_print_di(nv, fmt_gpio_ai_en);} + void ai_print_ain(nvObj_t *nv) {_print_di(nv, fmt_gpio_ai_ain);} + void ai_print_type(nvObj_t *nv) + { + sprintf(cs.out_buf, fmt_ai_type, nv->token, (int)nv->value); + xio_writeline(cs.out_buf); + } + + void ai_print_circuit(nvObj_t *nv) + { + sprintf(cs.out_buf, fmt_ai_circuit, nv->token, (int)nv->value); + xio_writeline(cs.out_buf); + } + + void ai_print_p(nvObj_t *nv) + { + sprintf(cs.out_buf, fmt_ai_parameter, nv->token, (float)nv->value); + xio_writeline(cs.out_buf); + } + #endif diff --git a/g2core/gpio.h b/g2core/gpio.h index 9a44623a8..cab712b90 100644 --- a/g2core/gpio.h +++ b/g2core/gpio.h @@ -25,55 +25,66 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + #ifndef GPIO_H_ONCE #define GPIO_H_ONCE +#include "g2core.h" // #1 +#include "config.h" // #2 +#include "encoder.h" // for post-probe/homing encoder grabbing +#include "report.h" // for sr triggering +#include "canonical_machine.h" // for pin-change function/action handling + +// Note: "board_gpio.h" is inlcluded at the end of this file + +#include // for std::forward + +#include "MotatePins.h" +using Motate::kPullUp; +using Motate::kDebounce; +using Motate::kStartHigh; +using Motate::kStartLow; +using Motate::kPWMPinInverted; + /* * GPIO defines */ -//--- change as required for board and switch hardware ---// - -#define D_IN_CHANNELS 9 // v9 // number of digital inputs supported -#define D_OUT_CHANNELS 13 // number of digital outputs supported -//#define D_OUT_CHANNELS 9 // number of digital outputs supported -#define A_IN_CHANNELS 0 // number of analog inputs supported -#define A_OUT_CHANNELS 0 // number of analog outputs supported -//#define INPUT_LOCKOUT_MS 50 // milliseconds to go dead after input firing -#define INPUT_LOCKOUT_MS 10 // milliseconds to go dead after input firing +// moved to board_gpio.h, which is copied for each board in subfolders of board/ //--- do not change from here down ---// typedef enum { - IO_ACTIVE_LOW = 0, // input is active low (aka normally open) - IO_ACTIVE_HIGH = 1, // input is active high (aka normally closed) - IO_MODE_DISABLED = 2, // input is disabled - IO_MODE_MAX // unused. Just for range checking -} ioMode; + IO_UNAVAILABLE = -1, // input/output is missing/used/unavailable + IO_DISABLED = 0, // input/output is disabled + IO_ENABLED = 1 // input/output enabled +} ioEnabled; + +typedef enum { + IO_ACTIVE_HIGH = 0, // input/output is active high (aka normally closed) + IO_ACTIVE_LOW = 1, // input/output is active low (aka normally open) +} ioPolarity; #define NORMALLY_OPEN IO_ACTIVE_LOW // equivalent #define NORMALLY_CLOSED IO_ACTIVE_HIGH // equivalent typedef enum { // actions are initiated from within the input's ISR INPUT_ACTION_NONE = 0, - INPUT_ACTION_STOP, // stop at normal jerk - preserves positional accuracy - INPUT_ACTION_FAST_STOP, // stop at high jerk - preserves positional accuracy - INPUT_ACTION_HALT, // stop immediately - not guaranteed to preserve position - INPUT_ACTION_CYCLE_START, // start / restart cycle after feedhold (RESERVED) - INPUT_ACTION_ALARM, // initiate an alarm. stops everything immediately - preserves position - INPUT_ACTION_SHUTDOWN, // initiate a shutdown. stops everything immediately - does not preserve position - INPUT_ACTION_PANIC, // initiate a panic. stops everything immediately - does not preserve position - INPUT_ACTION_RESET, // reset system - INPUT_ACTION_MAX // unused. Just for range checking -} inputAction; + INPUT_ACTION_STOP, // 1 - stop at normal jerk - preserves positional accuracy + INPUT_ACTION_FAST_STOP, // 2 - stop at high jerk - preserves positional accuracy + INPUT_ACTION_HALT, // 3 - stop immediately - not guaranteed to preserve position + INPUT_ACTION_CYCLE_START, // 4 - start / restart cycle after feedhold (RESERVED) + INPUT_ACTION_ALARM, // 5 - initiate an alarm. stops everything immediately - preserves position + INPUT_ACTION_SHUTDOWN, // 6 - initiate a shutdown. stops everything immediately - does not preserve position + INPUT_ACTION_PANIC, // 7 - initiate a panic. stops everything immediately - does not preserve position + INPUT_ACTION_RESET, // 8 - reset system + + INPUT_ACTION_LIMIT, // 9 - limit switch processing + INPUT_ACTION_INTERLOCK, // 10 - interlock processing -typedef enum { // functions are requested from the ISR, run from the main loop - INPUT_FUNCTION_NONE = 0, - INPUT_FUNCTION_LIMIT = 1, // limit switch processing - INPUT_FUNCTION_INTERLOCK = 2, // interlock processing - INPUT_FUNCTION_SHUTDOWN = 3, // shutdown in support of external emergency stop - INPUT_FUNCTION_PROBE = 4, // assign input as probe input - INPUT_FUNCTION_MAX // unused. Just for range checking -} inputFunc; + INPUT_ACTION_INTERNAL, // 11 - homing/probing processing (internal only) +} inputAction; +#define INPUT_ACTION_MAX INPUT_ACTION_INTERLOCK // for range checking +#define INPUT_ACTION_ACTUAL_MAX INPUT_ACTION_INTERNAL // for internal checking and resource allocation typedef enum { INPUT_INACTIVE = 0, // aka switch open, also read as 'false' @@ -87,37 +98,1295 @@ typedef enum { INPUT_EDGE_TRAILING // flag is set when trailing edge is detected } inputEdgeFlag; +// forward declare +struct gpioDigitalInputReader; +extern gpioDigitalInputReader* const in_r[16]; + /* - * GPIO structures + * gpioDigitalInputHandler - superclass of objects that wish to be informed of + * digital input changes + * + * Notes about the callback function: + * The first parameter is the current state (honoring polarity) - true = ACTIVE + * The second parameter is the inputEdgeFlag value + * The third parameter is the external number (N in `diN`) of the pin that changed + * The return value indicates if it has been "handled" - return true and no other + * gpioDigitalInputHandler callbacks will be triggered *for this event* + * Generally, return false unless there is a good reason to stop propagation. + * + * Example gpioDigitalInputHandler object creation: + + gpioDigitalInputHandler limitHandler { + [&](const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + if (edge != INPUT_EDGE_LEADING) { return; } + limit_requested = true; // record that a limit was requested for later processing + return false; // allow others to see this notice + }, + 5, // priority + nullptr // next - nullptr to start with + }; + + // register this listener for limit events: + din_handlers[INPUT_ACTION_LIMIT].registerHandler(limitHandler); */ -typedef struct ioDigitalInput { // one struct per digital input - ioMode mode; // -1=disabled, 0=active low (NO), 1= active high (NC) + +struct gpioDigitalInputHandler { + // const means it must be provided at compile time + const std::function callback; // the function to call + const int8_t priority; // higher is higher + + gpioDigitalInputHandler *next; // form a simple linked list +}; + + +struct gpioDigitalInputHandlerList { + gpioDigitalInputHandler * _first_handler; + + void registerHandler(gpioDigitalInputHandler * const new_handler) { + if (!_first_handler) { + // there is only one - now + _first_handler = new_handler; + return; + } else if (new_handler->priority > _first_handler->priority) { + // this is the new first one + new_handler->next = _first_handler; + _first_handler = new_handler; + return; + } + + gpioDigitalInputHandler * current_handler = _first_handler; + + while (current_handler != nullptr) { + if (new_handler->priority <= current_handler->priority) { + // new_handler will be immediately after current_handler + new_handler->next = current_handler->next; + current_handler->next = new_handler; + return; + } + current_handler = current_handler->next; + } + }; + + void deregisterHandler(gpioDigitalInputHandler * const old_handler) { + if (!_first_handler) { + return; + } else if (_first_handler == old_handler) { + _first_handler = _first_handler->next; + return; + } + + gpioDigitalInputHandler * current_handler = _first_handler; + + while (current_handler->next != nullptr) { + if (current_handler->next == old_handler) { + current_handler->next = old_handler->next; + return; + } + current_handler = current_handler->next; + } + }; + + bool call(const bool state, const inputEdgeFlag edge, const uint8_t triggering_pin_number) { + gpioDigitalInputHandler * current_handler = _first_handler; + while (current_handler != nullptr) { + if (current_handler->callback(state, edge, triggering_pin_number)) { + return true; + } + current_handler = current_handler->next; + } + return false; + } +}; + +// lists for the various inputAction events +extern gpioDigitalInputHandlerList din_handlers[INPUT_ACTION_ACTUAL_MAX+1]; + +/* + * gpioDigitalInput - digital input base class + */ +struct gpioDigitalInput { + // this is the generic implementation for a "any"" digital input pin + // see gpioDigitalInputPin for a real pin + + // functions for use by other parts of the code + + virtual bool getState(); + + + virtual inputAction getAction(); + virtual bool setAction(const inputAction); + + virtual ioEnabled getEnabled(); + virtual bool setEnabled(const ioEnabled); + + virtual ioPolarity getPolarity(); + virtual bool setPolarity(const ioPolarity); + + virtual bool setExternalNumber(const uint8_t); + virtual const uint8_t getExternalNumber(); + + + + // functions that take nvObj_t* and return stat_t, NOT overridden + + stat_t getState(nvObj_t *nv) + { + if (getEnabled() <= IO_DISABLED) { + nv->valuetype = TYPE_NULL; + return (STAT_OK); + } + nv->value = getState(); + nv->valuetype = TYPE_BOOL; + return (STAT_OK); + }; + // no setState + + stat_t getEnabled(nvObj_t *nv) + { + nv->value = getEnabled(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setEnabled(nvObj_t *nv) + { + if ((nv->value < IO_DISABLED) || (nv->value > IO_ENABLED)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setEnabled((ioEnabled)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + stat_t getPolarity(nvObj_t *nv) + { + nv->value = getPolarity(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setPolarity(nvObj_t *nv) + { + if ((nv->value < IO_ACTIVE_HIGH) || (nv->value > IO_ACTIVE_LOW)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setPolarity((ioPolarity)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + stat_t getAction(nvObj_t *nv) + { + nv->value = getAction(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setAction(nvObj_t *nv) + { + if ((nv->value < INPUT_ACTION_NONE) || (nv->value > INPUT_ACTION_MAX)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setAction((inputAction)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + + stat_t getExternalNumber(nvObj_t *nv) + { + nv->value = getExternalNumber(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setExternalNumber(nvObj_t *nv) + { + if ((nv->value < 0) || (nv->value > 14)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setExternalNumber(nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; +}; + + +/* + * gpioDigitalInputReader - digital input reader class - the "in1" - "inX" objects + */ + +struct gpioDigitalInputReader final { + gpioDigitalInput* pin; + + // functions for use by other parts of the code + + bool setPin(gpioDigitalInput * const new_pin) { + pin = new_pin; // might be null + return true; + }; + + gpioDigitalInput* getPin() { + return pin; // might be null + }; + + bool getState() { + if (!pin) { return false; } + return pin->getState(); + }; + + + // functions that take nvObj_t* and return stat_t, NOT overridden + + stat_t getState(nvObj_t *nv) + { + if (!pin) { + nv->valuetype = TYPE_NULL; + return (STAT_OK); + } + return pin->getState(nv); + }; +}; + +// setup the gpioDigitalInputReader objects as extern +extern gpioDigitalInputReader in1; +extern gpioDigitalInputReader in2; +extern gpioDigitalInputReader in3; +extern gpioDigitalInputReader in4; +extern gpioDigitalInputReader in5; +extern gpioDigitalInputReader in6; +extern gpioDigitalInputReader in7; +extern gpioDigitalInputReader in8; +extern gpioDigitalInputReader in9; +extern gpioDigitalInputReader in10; +extern gpioDigitalInputReader in11; +extern gpioDigitalInputReader in12; +extern gpioDigitalInputReader in13; +extern gpioDigitalInputReader in14; +extern gpioDigitalInputReader in15; +extern gpioDigitalInputReader in16; + + +/* + * gpioDigitalInputPin - concrete child of gpioDigitalInput + */ +template +struct gpioDigitalInputPin final : gpioDigitalInput { + ioEnabled enabled; // -1=unavailable, 0=disabled, 1=enabled + ioPolarity polarity; // 0=normal/active high, 1=inverted/active low inputAction action; // 0=none, 1=stop, 2=halt, 3=stop_steps, 4=reset - inputFunc function; // function to perform when activated / deactivated - ioState state; // input state 0=inactive, 1=active, -1=disabled + // inputFunc input_function; // function to perform when activated / deactivated + inputEdgeFlag edge; // keeps a transient record of edges for immediate inquiry + bool homing_mode; // set true when input is in homing mode. bool probing_mode; // set true when input is in probing mode. + + const uint8_t ext_pin_number; // the number used externally for this pin ("din" + ext_pin_number) + uint8_t proxy_pin_number; // the number used externally for this pin ("in" + proxy_pin_number) + uint16_t lockout_ms; // number of milliseconds for debounce lockout Motate::Timeout lockout_timer; // time to expire current debounce lockout, or 0 if no lockout -} d_in_t; -typedef struct gpioDigitalOutput { // one struct per digital output - ioMode mode; -} d_out_t; + Pin_t pin; // the actual pin object itself + + // In constructor, simply forward all values to the Pin_t + // To get a different behavior, override this object. + template + gpioDigitalInputPin(const ioEnabled _enabled, const ioPolarity _polarity, const uint8_t _ext_pin_number, const uint8_t _proxy_pin_number, T&&... V) : + gpioDigitalInput{}, + enabled{_enabled}, + polarity{_polarity}, + ext_pin_number{ _ext_pin_number }, + proxy_pin_number{ 0 }, + pin{((polarity == IO_ACTIVE_LOW) ? kPullUp|kDebounce : kDebounce), [&]{this->pin_changed();}, std::forward(V)...} + { + if (pin.isNull()) { + enabled = IO_UNAVAILABLE; + proxy_pin_number = 0; + } else { + setExternalNumber(_proxy_pin_number); + } + }; + + // functions for use by other parts of the code, and are overridden + + bool getState() override + { + if (enabled <= IO_DISABLED) { + return false; + } + const bool v = (const bool)pin; + return (polarity == IO_ACTIVE_HIGH) ? v : !v; + }; + + + inputAction getAction() override + { + return action; + }; + bool setAction(const inputAction a) override + { + action = a; + return true; + }; + + ioEnabled getEnabled() override + { + return enabled; + }; + bool setEnabled(const ioEnabled m) override + { + if (enabled == IO_UNAVAILABLE) { + return false; + } + enabled = m; + return true; + }; + + ioPolarity getPolarity() override + { + return polarity; + }; + bool setPolarity(const ioPolarity new_polarity) override + { + polarity = new_polarity; + pin.setOptions((polarity == IO_ACTIVE_LOW) ? kPullUp|kDebounce : kDebounce); + return true; + }; + + bool setExternalNumber(const uint8_t e) override + { + if (e == proxy_pin_number) { return true; } + if (proxy_pin_number > 0) { + // clear the old pin + in_r[proxy_pin_number-1]->setPin(nullptr); + } + proxy_pin_number = e; + if (proxy_pin_number > 0) { + // set the new pin + in_r[proxy_pin_number-1]->setPin(this); + } + return true; + }; + + const uint8_t getExternalNumber() override + { + return proxy_pin_number; + }; + + + // support function for pin change interrupt handling + + void pin_changed() + { + // return if input is disabled + if (enabled == IO_DISABLED) { + return; + } + + // return if the input is in lockout period (take no action) + if (lockout_timer.isSet() && !lockout_timer.isPast()) { + return; + } + + ioState pin_value = (ioState)(bool)pin; + ioState pin_value_corrected = (ioState)(pin_value ^ ((bool)polarity)); // correct for NO or NC mode + + // This shouldn't be necessary - the processor shouldn't call without an edge + // if (state == (ioState)pin_value_corrected) { + // return; + // } + + // lockout the pin for lockout_ms + lockout_timer.set(lockout_ms); + + // record the changed state + if (pin_value_corrected == INPUT_ACTIVE) { + edge = INPUT_EDGE_LEADING; + } else { + edge = INPUT_EDGE_TRAILING; + } + + // start with INPUT_ACTION_INTERNAL for transient event processing like homing and probing + if (!din_handlers[INPUT_ACTION_INTERNAL].call(pin_value_corrected, edge, ext_pin_number)) { + din_handlers[action].call(pin_value_corrected, edge, ext_pin_number); + } +#if 0 + // TODO - refactor homing_mode and probing_mode out to use a dynamically + // configured linked list of functions + + // perform homing operations if in homing mode + if (homing_mode) { + if (edge == INPUT_EDGE_LEADING) { // we only want the leading edge to fire + en_take_encoder_snapshot(); + cm_start_hold(); + } + return; + } + + // perform probing operations if in probing mode + if (probing_mode) { + // We want to capture either way. + // Probing tests the start condition for the correct direction ahead of time. + // If we see any edge, it's the right one. + en_take_encoder_snapshot(); + cm_start_hold(); + return; + } + + // *** NOTE: From this point on all conditionals assume we are NOT in homing or probe mode *** + + // trigger the action on leading edges + if (edge == INPUT_EDGE_LEADING) { + if (action == INPUT_ACTION_STOP) { + cm_start_hold(); + } + if (action == INPUT_ACTION_FAST_STOP) { + cm_start_hold(); // for now is same as STOP + } + if (action == INPUT_ACTION_HALT) { + cm_halt_all(); // hard stop, including spindle and coolant + } + if (action == INPUT_ACTION_ALARM) { + char msg[10]; + sprintf(msg, "input %d", ext_pin_number); + cm_alarm(STAT_ALARM, msg); + } + if (action == INPUT_ACTION_SHUTDOWN) { + char msg[10]; + sprintf(msg, "input %d", ext_pin_number); + cm_shutdown(STAT_SHUTDOWN, msg); + } + if (action == INPUT_ACTION_PANIC) { + char msg[10]; + sprintf(msg, "input %d", ext_pin_number); + cm_panic(STAT_PANIC, msg); + } + if (action == INPUT_ACTION_RESET) { + hw_hard_reset(); + } + + // these functions also trigger on the leading edge + + if (input_function == INPUT_ACTION_LIMIT) { + cm.limit_requested = ext_pin_number; + + } else if (input_function == INPUT_ACTION_SHUTDOWN) { + cm.shutdown_requested = ext_pin_number; + + } else if (input_function == INPUT_FUNCTION_INTERLOCK) { + cm.safety_interlock_disengaged = ext_pin_number; + } + } // if (edge == INPUT_EDGE_LEADING) + + // trigger interlock release on trailing edge + if (edge == INPUT_EDGE_TRAILING) { + if (input_function == INPUT_FUNCTION_INTERLOCK) { + cm.safety_interlock_reengaged = ext_pin_number; + } + } +#endif + + sr_request_status_report(SR_REQUEST_TIMED); //+++++ Put this one back in. + }; +}; + + +// forward declare +struct gpioDigitalOutputWriter; +extern gpioDigitalOutputWriter* const out_w[16]; + +/* + * gpioDigitalOutput - digital/PWM output base class + */ +struct gpioDigitalOutput { + // this is the generic implementation for a "any"" output pin (PWM or Digital) + // see gpioDigitalOutputPin for a real pin + + // functions for use by other parts of the code, and are what to override + virtual ioEnabled getEnabled(); + virtual bool setEnabled(const ioEnabled); + + virtual ioPolarity getPolarity(); + virtual bool setPolarity(const ioPolarity); + + virtual float getValue(); + virtual bool setValue(const float); + + virtual float getFrequency(); + virtual bool setFrequency(const float); + + virtual bool setExternalNumber(const uint8_t); + virtual const uint8_t getExternalNumber(); + + // functions that take nvObj_t* and return stat_t, NOT overridden + + stat_t getEnabled(nvObj_t *nv) + { + nv->value = getEnabled(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setEnabled(nvObj_t *nv) + { + int32_t value = nv->value; + if ((value != IO_DISABLED) && (value != IO_ENABLED)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setEnabled((ioEnabled)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + stat_t getPolarity(nvObj_t *nv) + { + nv->value = getPolarity(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setPolarity(nvObj_t *nv) + { + if ((nv->value < IO_ACTIVE_HIGH) || (nv->value > IO_ACTIVE_LOW)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setPolarity((ioPolarity)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + stat_t getValue(nvObj_t *nv) + { + auto enabled = getEnabled(); + if (enabled != IO_ENABLED) { + nv->value = 0; + nv->valuetype = TYPE_NULL; // reports back as NULL + } else { + nv->valuetype = TYPE_FLOAT; + nv->precision = 2; + nv->value = getValue(); // read it as a float + + bool invert = (getPolarity() == IO_ACTIVE_LOW); + if (invert) { + nv->value = 1.0 - nv->value; + } + } + return (STAT_OK); + }; + stat_t setValue(nvObj_t *nv) + { + auto enabled = getEnabled(); + if (enabled != IO_ENABLED) { + nv->valuetype = TYPE_NULL; // reports back as NULL + } else { + float value = nv->value; // read it as a float + + bool invert = (getPolarity() == IO_ACTIVE_LOW); + if (invert) { + value = 1.0 - value; + } + + if (!setValue(value)) { + return STAT_INPUT_VALUE_RANGE_ERROR; + } + } + return (STAT_OK); + }; -typedef struct gpioAnalogInput { // one struct per analog input - ioMode mode; -} a_in_t; + stat_t getExternalNumber(nvObj_t *nv) + { + nv->value = getExternalNumber(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setExternalNumber(nvObj_t *nv) + { + if ((nv->value < 0) || (nv->value > 14)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setExternalNumber(nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; +}; -typedef struct gpioAnalogOutput { // one struct per analog output - ioMode mode; -} a_out_t; -extern d_in_t d_in[D_IN_CHANNELS]; -extern d_out_t d_out[D_OUT_CHANNELS]; -extern a_in_t a_in[A_IN_CHANNELS]; -extern a_out_t a_out[A_OUT_CHANNELS]; +/* + * gpioDigitalOutputWriter - digital output writer class - the "out1" - "outX" objects + */ + +struct gpioDigitalOutputWriter final { + gpioDigitalOutput* pin; + + // functions for use by other parts of the code + + bool setPin(gpioDigitalOutput * const new_pin) { + pin = new_pin; // might be null + return true; + }; + + gpioDigitalOutput* getPin() { + return pin; // might be null + }; + + float getValue() { + if (!pin) { return false; } + return pin->getValue(); + }; + bool setValue(const float v) { + if (!pin) { return false; } + return pin->setValue(v); + }; + + + // functions that take nvObj_t* and return stat_t, NOT overridden + + stat_t getValue(nvObj_t *nv) + { + if (!pin) { + nv->value = 0; + nv->valuetype = TYPE_NULL; // reports back as NULL + return (STAT_OK); + } + return pin->getValue(nv); + }; + stat_t setValue(nvObj_t *nv) + { + if (!pin) { + nv->valuetype = TYPE_NULL; // reports back as NULL + return (STAT_OK); + } + return pin->setValue(nv); + }; +}; + +// setup the gpioDigitalInputReader objects as extern +extern gpioDigitalOutputWriter out1; +extern gpioDigitalOutputWriter out2; +extern gpioDigitalOutputWriter out3; +extern gpioDigitalOutputWriter out4; +extern gpioDigitalOutputWriter out5; +extern gpioDigitalOutputWriter out6; +extern gpioDigitalOutputWriter out7; +extern gpioDigitalOutputWriter out8; +extern gpioDigitalOutputWriter out9; +extern gpioDigitalOutputWriter out10; +extern gpioDigitalOutputWriter out11; +extern gpioDigitalOutputWriter out12; +extern gpioDigitalOutputWriter out13; +extern gpioDigitalOutputWriter out14; +extern gpioDigitalOutputWriter out15; +extern gpioDigitalOutputWriter out16; + + +/* + * gpioDigitalOutputPin - concrete child of gpioDigitalOutput + */ +template +struct gpioDigitalOutputPin final : gpioDigitalOutput { + ioEnabled enabled; // -1=unavailable, 0=disabled, 1=enabled + ioPolarity polarity; // 0=normal/active high, 1=inverted/active low + uint8_t proxy_pin_number; // the number used externally for this pin ("in" + proxy_pin_number) + Pin_t pin; + + // In constructor, simply forward all values to the Pin_t + template + gpioDigitalOutputPin(const ioEnabled _enabled, const ioPolarity _polarity, const uint8_t _proxy_pin_number, T&&... V) : + gpioDigitalOutput{}, + enabled{ _enabled }, + polarity{ _polarity }, + proxy_pin_number{ 0 }, + pin{((polarity == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow), std::forward(V)...} + { + if (pin.isNull()) { + enabled = IO_UNAVAILABLE; + proxy_pin_number = 0; + } else { + setExternalNumber(_proxy_pin_number); + } + }; + + // functions for use by other parts of the code, and are overridden + + ioEnabled getEnabled() override + { + return enabled; + }; + bool setEnabled(const ioEnabled m) override + { + if (enabled == IO_UNAVAILABLE) { + return false; + } + enabled = m; + return true; + }; + + ioPolarity getPolarity() override + { + return polarity; + }; + bool setPolarity(const ioPolarity new_polarity) override + { + polarity = new_polarity; + pin.setOptions((polarity == IO_ACTIVE_LOW) ? kStartHigh|kPWMPinInverted : kStartLow); + return true; + }; + + float getValue() override + { + return (const float)pin; + }; + bool setValue(const float v) override + { + if (pin.isNull()) { + return false; + } + pin = v; + return true; + }; + + float _last_set_frequency = 0; + // it must be set through this interface at least once before it can be read back + float getFrequency() override + { + return _last_set_frequency; + }; + bool setFrequency(const float freq) override + { + pin.setFrequency(freq); + _last_set_frequency = freq; + return true; + }; + + bool setExternalNumber(const uint8_t e) override + { + if (e == proxy_pin_number) { return true; } + if (proxy_pin_number > 0) { + // clear the old pin + out_w[proxy_pin_number-1]->setPin(nullptr); + } + proxy_pin_number = e; + if (proxy_pin_number > 0) { + // set the new pin + out_w[proxy_pin_number-1]->setPin(this); + } + return true; + }; + + const uint8_t getExternalNumber() override + { + return proxy_pin_number; + }; + +}; + +// forward declare +struct gpioAnalogInputReader; +extern gpioAnalogInputReader* const ain_r[8]; + +/* + * gpioAnalogInput - analog (ADC) input base class + */ +struct gpioAnalogInput { + // type of analog input source - read only - defined by the board + enum AnalogInputType_t { + AIN_TYPE_INTERNAL = 0, // single-ended or differential + AIN_TYPE_EXTERNAL = 1, // for externally (SPI) connected inputs + }; + + // type of circuit connected - for use in determining the resistance + enum AnalogCircuit_t { + AIN_CIRCUIT_DISABLED = 0, // there is no circuit, resistance will read -1 + // no additional configuration + AIN_CIRCUIT_PULLUP = 1, // resistance being measured is pulling up to VCC + // the pull-up resistance is measured (rt) + // p1 is the set pull-down resistance (r1) + AIN_CIRCUIT_EXTERNAL = 2, // for externally (SPI) connected inputs + // no additional configuration + AIN_CIRCUIT_INV_OPAMP = 3, // inverted op-amp connected + // the pull-up resistance is measured (rt) + // p1 is the set pull-down resistance of the bias(+) (r1) + // p2 is the set pull-up resistance of the gain(-) (r2) + // p3 is the set pull-down to output of the gain(-) (r3) + AIN_CIRCUIT_CC_INV_OPAMP = 4, // for externally (SPI) connected inputs + // the pull-up resistance to the current source is measured (rt) + // p4 is the set pull-up resistance of the bias(+) (r4) + // p1 is the set pull-down resistance of the bias(+) (r1) + // p2 is the set pull-up resistance of the gain(-) (r2) + // p3 is the set pull-down to output of the gain(-) (r3) + // p5 is the set constant current in millivolts (c1) + }; + static const auto AIN_CIRCUIT_MAX = AIN_CIRCUIT_CC_INV_OPAMP; + + // this is the generic implementation for a "any"" analog input pin + // see gpioAnalogInputPin for a real pin + + // functions for use by other parts of the code + + virtual ioEnabled getEnabled(); + virtual bool setEnabled(const ioEnabled); + + virtual float getValue(); + virtual float getResistance(); + + virtual AnalogInputType_t getType(); + virtual bool setType(const AnalogInputType_t); + + virtual AnalogCircuit_t getCircuit(); + virtual bool setCircuit(const AnalogCircuit_t); + + virtual float getParameter(const uint8_t p); + virtual bool setParameter(const uint8_t p, const float v); + + virtual bool setExternalNumber(const uint8_t); + virtual const uint8_t getExternalNumber(); + + virtual void startSampling(); + + // functions that take nvObj_t* and return stat_t, NOT overridden + + stat_t getEnabled(nvObj_t *nv) + { + nv->value = getEnabled(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setEnabled(nvObj_t *nv) + { + int32_t value = nv->value; + if ((value != IO_DISABLED) && (value != IO_ENABLED)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setEnabled((ioEnabled)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + stat_t getValue(nvObj_t *nv) + { + if (getEnabled() != IO_ENABLED) { + nv->valuetype = TYPE_NULL; + return (STAT_OK); + } + nv->value = getValue(); + nv->valuetype = TYPE_FLOAT; + return (STAT_OK); + }; + // no setValue + + stat_t getResistance(nvObj_t *nv) + { + if (getEnabled() != IO_ENABLED || getCircuit() == AIN_CIRCUIT_DISABLED) { + nv->valuetype = TYPE_NULL; + return (STAT_OK); + } + nv->value = getResistance(); + nv->valuetype = TYPE_FLOAT; + return (STAT_OK); + }; + // no setResistance + + stat_t getType(nvObj_t *nv) + { + nv->value = getType(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setType(nvObj_t *nv) + { + if ((getEnabled() != IO_ENABLED) || (nv->value > AIN_TYPE_EXTERNAL)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setType((AnalogInputType_t)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + stat_t getCircuit(nvObj_t *nv) + { + nv->value = getCircuit(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setCircuit(nvObj_t *nv) + { + if ((nv->value < AIN_CIRCUIT_DISABLED) || (nv->value > AIN_CIRCUIT_MAX)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setCircuit((AnalogCircuit_t)nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + stat_t getParameter(nvObj_t *nv, const uint8_t p) + { + nv->value = getParameter(p); + nv->valuetype = TYPE_FLOAT; + return (STAT_OK); + }; + stat_t setParameter(nvObj_t *nv, const uint8_t p) + { + if (!setParameter(p, nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; + + + stat_t getExternalNumber(nvObj_t *nv) + { + nv->value = getExternalNumber(); + nv->valuetype = TYPE_INT; + return (STAT_OK); + }; + stat_t setExternalNumber(nvObj_t *nv) + { + if ((nv->value < 0) || (nv->value > 14)) { + return (STAT_INPUT_VALUE_RANGE_ERROR); + } + if (!setExternalNumber(nv->value)) { + return STAT_PARAMETER_IS_READ_ONLY; + } + return (STAT_OK); + }; +}; + + + +/* + * gpioAnalogInputReader - analog input reader class - the "ain1" - "ainX" objects + */ + +struct gpioAnalogInputReader final { + gpioAnalogInput* pin; + + // functions for use by other parts of the code + + bool setPin(gpioAnalogInput * const new_pin) { + pin = new_pin; // might be null + return true; + }; + + gpioAnalogInput* getPin() { + return pin; // might be null + }; + + float getValue() { + if (!pin) { return -1; } + return pin->getValue(); + }; + float getResistance() { + if (!pin) { return -1; } + return pin->getResistance(); + }; + + + // functions that take nvObj_t* and return stat_t, NOT overridden + + stat_t getValue(nvObj_t *nv) { + if (!pin) { + nv->value = 0; + nv->valuetype = TYPE_NULL; // reports back as NULL + return (STAT_OK); + } + return pin->getValue(nv); + }; + stat_t getResistance(nvObj_t *nv) { + if (!pin) { + nv->value = 0; + nv->valuetype = TYPE_NULL; // reports back as NULL + return (STAT_OK); + } + return pin->getResistance(nv); + }; +}; + +// setup the gpioDigitalInputReader objects as extern +extern gpioAnalogInputReader ain1; +extern gpioAnalogInputReader ain2; +extern gpioAnalogInputReader ain3; +extern gpioAnalogInputReader ain4; +extern gpioAnalogInputReader ain5; +extern gpioAnalogInputReader ain6; +extern gpioAnalogInputReader ain7; +extern gpioAnalogInputReader ain8; + +// statistical sampling utility class +template +struct ValueHistory { + + float variance_max = 2.0; + ValueHistory() {}; + ValueHistory(float v_max) : variance_max{v_max} {}; + + struct sample_t { + float value; + float value_sq; + void set(float v) { value = v; value_sq = v*v; } + }; + sample_t samples[sample_count]; + uint16_t next_sample = 0; + void _bump_index(uint16_t &v) { + ++v; + if (v == sample_count) { + v = 0; + } + }; + uint16_t sampled = 0; + + float rolling_sum = 0; + float rolling_sum_sq = 0; + float rolling_mean = 0; + void add_sample(float t) { + last_value_valid = false; + + rolling_sum -= samples[next_sample].value; + rolling_sum_sq -= samples[next_sample].value_sq; + + samples[next_sample].set(t); + + rolling_sum += samples[next_sample].value; + rolling_sum_sq += samples[next_sample].value_sq; + + _bump_index(next_sample); + if (sampled < sample_count) { ++sampled; } + + rolling_mean = rolling_sum/(float)sampled; + }; + + float get_std_dev() { + // Important note: this is a POPULATION standard deviation, not a population standard deviation + float variance = (rolling_sum_sq/(float)sampled) - (rolling_mean*rolling_mean); + return std::sqrt(std::abs(variance)); + }; + + float last_value = 0; + bool last_value_valid = false; + float value() { + if (last_value_valid) { return last_value; } + // we'll shoot through the samples and ignore the outliers + uint16_t samples_kept = 0; + float temp = 0; + float std_dev = get_std_dev(); + + for (uint16_t i=0; i +struct gpioAnalogInputPin : gpioAnalogInput { +protected: // so we know if anyone tries to reach in + ioEnabled enabled; // -1=unavailable, 0=disabled, 1=enabled + AnalogInputType_t type; + AnalogCircuit_t circuit; + float parameters[6]; + + const uint8_t ext_pin_number; // the number used externally for this pin ("in" + ext_pin_number) + uint8_t proxy_pin_number; // the number used externally for this pin ("in" + proxy_pin_number) + + const float variance_max = 1.1; + ValueHistory<20> history {variance_max}; + + float last_raw_value; + + ADCPin_t pin; // the actual pin object itself + +public: + // In constructor, simply forward all values to the pin + // To get a different behavior, override this object. + template + gpioAnalogInputPin(const ioEnabled _enabled, const AnalogInputType_t _type, const uint8_t _ext_pin_number, const uint8_t _proxy_pin_number, T&&... additional_values) : + gpioAnalogInput{}, + enabled{_enabled}, + type{_type}, + ext_pin_number{ _ext_pin_number }, + proxy_pin_number{ 0 }, + pin{Motate::kNormal, [&]{this->adc_has_new_value();}, std::forward(additional_values)...} + { + if (pin.isNull()) { + enabled = IO_UNAVAILABLE; + proxy_pin_number = 0; + } else { + pin.setInterrupts(Motate::kPinInterruptOnChange|Motate::kInterruptPriorityLow); + pin.setVoltageRange(3.29, 0.0, 3.29, 100.0); + setExternalNumber(_proxy_pin_number); + } + }; + + // functions for use by other parts of the code, and are overridden + + ioEnabled getEnabled() override + { + return enabled; + }; + bool setEnabled(const ioEnabled m) override + { + if (enabled == IO_UNAVAILABLE) { + return false; + } + enabled = m; + return true; + }; + + float getValue() override + { + if (enabled != IO_ENABLED) { + return 0; + } + return history.value(); + }; + float getResistance() override + { + // NOTE: AIN_CIRCUIT_EXTERNAL is NOT handled here! + // That needs to be handled in a separate override! + if (enabled != IO_ENABLED || circuit == AIN_CIRCUIT_DISABLED) { + return -1; + } + const float v = history.value(); + const float s = pin.getTopVoltage(); + switch (circuit) { + + case AIN_CIRCUIT_PULLUP: + { + float r1 = parameters[0]; // pull-up + + if (ADCPin_t::is_differential) { + return (v * 2.0 * r1)/(s - v); + } else { + return (v * r1)/(s - v); + } + break; + } + + case AIN_CIRCUIT_INV_OPAMP: + { + float r1 = parameters[0]; // pull-down from bias(+) side of op-amp + float r2 = parameters[1]; // pull-up from gain(-) side of op-amp + float r3 = parameters[2]; // pull-to-output from gain(-) side of op-amp + + return (r1 * r2 * (s - v))/(r2 * v + r3 * s); + break; + } + + case AIN_CIRCUIT_CC_INV_OPAMP: + { + // the pull-up resistance to the current source is measured (rt) + float r4 = parameters[3]; // pull-up resistance of the bias(+) side of op-amp + float r1 = parameters[0]; // pull-down from bias(+) side of op-amp + float r2 = parameters[1]; // pull-up from gain(-) side of op-amp + float r3 = parameters[2]; // pull-to-output from gain(-) side of op-amp + float c = parameters[4]; // constant current in volts (c1) + + // r_0 = (r_1 (r_2 (s - v) + r_3 s) - v r_2 r_4)/(c r_3 (r_1 + r_4)) + return (r1 * (r2 * (s - v) + r3 * s) - v * r2 * r4)/(c * r3 * (r1 + r4)); + break; + } + + // AIN_CIRCUIT_EXTERNAL is specifically missing! + + default: + return -1; + } + + }; + + AnalogInputType_t getType() override + { + return type; + }; + bool setType(const AnalogInputType_t t) override + { + // NOTE: AIN_TYPE_EXTERNAL is NOT handled here! + // That needs to be handled in a separate override! + if (t == AIN_TYPE_EXTERNAL) { + return false; + } + type = t; + return true; + }; + + AnalogCircuit_t getCircuit() override + { + return circuit; + }; + bool setCircuit(const AnalogCircuit_t c) override + { + // prevent setting circuit to AIN_CIRCUIT_EXTERNAL + if (c == AIN_CIRCUIT_EXTERNAL) { + return false; + } + circuit = c; + return true; + }; + + float getParameter(const uint8_t p) override + { + if (p < 0 || p >= 6) { + return 0; + } + return parameters[p]; + }; + bool setParameter(const uint8_t p, const float v) override + { + if (p < 0 || p >= 6) { + return false; + } + parameters[p] = v; + return true; + }; + + void startSampling() override { + pin.startSampling(); + }; + + bool setExternalNumber(const uint8_t e) override + { + if (e == proxy_pin_number) { return true; } + if (proxy_pin_number > 0) { + // clear the old pin + ain_r[proxy_pin_number-1]->setPin(nullptr); + } + proxy_pin_number = e; + if (proxy_pin_number > 0) { + // set the new pin + ain_r[proxy_pin_number-1]->setPin(this); + } + return true; + }; + + const uint8_t getExternalNumber() override + { + return proxy_pin_number; + }; + + // support function for pin value update interrupt handling + + void adc_has_new_value() { + last_raw_value = pin.getRaw(); + history.add_sample(pin.getVoltage()); + }; +}; /* * GPIO function prototypes @@ -125,40 +1394,207 @@ extern a_out_t a_out[A_OUT_CHANNELS]; void gpio_init(void); void gpio_reset(void); -void input_reset(void); -void output_reset(void); +void inputs_reset(void); +void outputs_reset(void); bool gpio_read_input(const uint8_t input_num); -void gpio_set_homing_mode(const uint8_t input_num, const bool is_homing); -void gpio_set_probing_mode(const uint8_t input_num, const bool is_probing); -int8_t gpio_get_probing_input(void); - -stat_t io_set_mo(nvObj_t *nv); -stat_t io_set_ac(nvObj_t *nv); -stat_t io_set_fn(nvObj_t *nv); -stat_t io_get_input(nvObj_t *nv); +stat_t din_get_en(nvObj_t *nv); // enabled +stat_t din_set_en(nvObj_t *nv); +stat_t din_get_po(nvObj_t *nv); // input sense +stat_t din_set_po(nvObj_t *nv); +stat_t din_get_ac(nvObj_t *nv); // input action +stat_t din_set_ac(nvObj_t *nv); +stat_t din_get_in(nvObj_t *nv); // input external number +stat_t din_set_in(nvObj_t *nv); +stat_t din_get_input(nvObj_t *nv); +stat_t dout_get_en(nvObj_t *nv); // enabled +stat_t dout_set_en(nvObj_t *nv); +stat_t dout_get_po(nvObj_t *nv); // output sense +stat_t dout_set_po(nvObj_t *nv); +stat_t dout_get_out(nvObj_t *nv); // external number +stat_t dout_set_out(nvObj_t *nv); +stat_t dout_get_output(nvObj_t *nv); // actual output value (float) +stat_t dout_set_output(nvObj_t *nv); -stat_t io_set_domode(nvObj_t *nv); // output sense -stat_t io_get_output(nvObj_t *nv); -stat_t io_set_output(nvObj_t *nv); +stat_t ain_get_value(nvObj_t *nv); // get the voltage level +// no ain_set_value +stat_t ain_get_resistance(nvObj_t *nv); // get the resistance in ohms +// no ain_set_resistance +stat_t ai_get_en(nvObj_t *nv); // enabled +stat_t ai_set_en(nvObj_t *nv); // enabled +stat_t ai_get_ain(nvObj_t *nv); // external number +stat_t ai_set_ain(nvObj_t *nv); +stat_t ai_get_type(nvObj_t *nv); // get the ADC type (or disabled) +stat_t ai_set_type(nvObj_t *nv); // set the type (used to disable/enable) +stat_t ai_get_circuit(nvObj_t *nv); // get the circuit type +stat_t ai_set_circuit(nvObj_t *nv); // set the circuit type +stat_t ai_get_parameter(nvObj_t *nv, const uint8_t p); // get the value of parameter p +stat_t ai_set_parameter(nvObj_t *nv, const uint8_t p); // set the value of parameter p +stat_t ai_get_p1(nvObj_t *nv); +stat_t ai_set_p1(nvObj_t *nv); +stat_t ai_get_p2(nvObj_t *nv); +stat_t ai_set_p2(nvObj_t *nv); +stat_t ai_get_p3(nvObj_t *nv); +stat_t ai_set_p3(nvObj_t *nv); +stat_t ai_get_p4(nvObj_t *nv); +stat_t ai_set_p4(nvObj_t *nv); +stat_t ai_get_p5(nvObj_t *nv); +stat_t ai_set_p5(nvObj_t *nv); #ifdef __TEXT_MODE - void io_print_mo(nvObj_t *nv); - void io_print_ac(nvObj_t *nv); - void io_print_fn(nvObj_t *nv); - void io_print_in(nvObj_t *nv); - void io_print_domode(nvObj_t *nv); - void io_print_out(nvObj_t *nv); + void din_print_en(nvObj_t *nv); + void din_print_po(nvObj_t *nv); + void din_print_ac(nvObj_t *nv); + void din_print_fn(nvObj_t *nv); + void din_print_in(nvObj_t *nv); + void din_print_state(nvObj_t *nv); + + void dout_print_en(nvObj_t *nv); + void dout_print_po(nvObj_t *nv); + void dout_print_out(nvObj_t *nv); + + void ain_print_value(nvObj_t *nv); + void ain_print_resistance(nvObj_t *nv); + void ai_print_ain(nvObj_t *nv); + void ai_print_en(nvObj_t *nv); + void ai_print_type(nvObj_t *nv); + void ai_print_circuit(nvObj_t *nv); + void ai_print_p(nvObj_t *nv); #else - #define io_print_mo tx_print_stub - #define io_print_ac tx_print_stub - #define io_print_fn tx_print_stub - #define io_print_in tx_print_stub - #define io_print_st tx_print_stub - #define io_print_domode tx_print_stub - #define io_print_out tx_print_stub + #define din_print_en tx_print_stub + #define din_print_po tx_print_stub + #define din_print_ac tx_print_stub + #define din_print_fn tx_print_stub + #define din_print_in tx_print_stub + + #define dout_print_en tx_print_stub + #define dout_print_po tx_print_stub + #define dout_print_out tx_print_stub + + #define ain_print_value tx_print_stub + #define ain_print_resistance tx_print_stub + #define ai_print_en tx_print_stub + #define ai_print_ain tx_print_stub + #define ai_print_type tx_print_stub + #define ai_print_circuit tx_print_stub + #define ai_print_p tx_print_stub #endif // __TEXT_MODE +#include "board_gpio.h" + +#ifndef AI1_ENABLED +#define AI1_ENABLED IO_DISABLED +#endif +#ifndef AI1_EXTERNAL_NUMBER +#define AI1_EXTERNAL_NUMBER 1 +#endif +#ifndef AI1_TYPE +#define AI1_TYPE AIN_TYPE_INTERNAL +#endif +#ifndef AI1_CIRCUIT +#define AI1_CIRCUIT AIN_CIRCUIT_DISABLED +#endif +#ifndef AI1_P1 +#define AI1_P1 0.0 +#endif +#ifndef AI1_P2 +#define AI1_P2 0.0 +#endif +#ifndef AI1_P3 +#define AI1_P3 0.0 +#endif +#ifndef AI1_P4 +#define AI1_P4 0.0 +#endif +#ifndef AI1_P5 +#define AI1_P5 0.0 +#endif + + +#ifndef AI2_ENABLED +#define AI2_ENABLED IO_DISABLED +#endif +#ifndef AI2_EXTERNAL_NUMBER +#define AI2_EXTERNAL_NUMBER 2 +#endif +#ifndef AI2_TYPE +#define AI2_TYPE AIN_TYPE_INTERNAL +#endif +#ifndef AI2_CIRCUIT +#define AI2_CIRCUIT AIN_CIRCUIT_DISABLED +#endif +#ifndef AI2_P1 +#define AI2_P1 0.0 +#endif +#ifndef AI2_P2 +#define AI2_P2 0.0 +#endif +#ifndef AI2_P3 +#define AI2_P3 0.0 +#endif +#ifndef AI2_P4 +#define AI2_P4 0.0 +#endif +#ifndef AI2_P5 +#define AI2_P5 0.0 +#endif + +#ifndef AI3_ENABLED +#define AI3_ENABLED IO_DISABLED +#endif +#ifndef AI3_EXTERNAL_NUMBER +#define AI3_EXTERNAL_NUMBER 3 +#endif +#ifndef AI3_TYPE +#define AI3_TYPE AIN_TYPE_INTERNAL +#endif +#ifndef AI3_CIRCUIT +#define AI3_CIRCUIT AIN_CIRCUIT_DISABLED +#endif +#ifndef AI3_P1 +#define AI3_P1 0.0 +#endif +#ifndef AI3_P2 +#define AI3_P2 0.0 +#endif +#ifndef AI3_P3 +#define AI3_P3 0.0 +#endif +#ifndef AI3_P4 +#define AI3_P4 0.0 +#endif +#ifndef AI3_P5 +#define AI3_P5 0.0 +#endif + +#ifndef AI4_ENABLED +#define AI4_ENABLED IO_DISABLED +#endif +#ifndef AI4_EXTERNAL_NUMBER +#define AI4_EXTERNAL_NUMBER 4 +#endif +#ifndef AI4_TYPE +#define AI4_TYPE AIN_TYPE_INTERNAL +#endif +#ifndef AI4_CIRCUIT +#define AI4_CIRCUIT AIN_CIRCUIT_DISABLED +#endif +#ifndef AI4_P1 +#define AI4_P1 0.0 +#endif +#ifndef AI4_P2 +#define AI4_P2 0.0 +#endif +#ifndef AI4_P3 +#define AI4_P3 0.0 +#endif +#ifndef AI4_P4 +#define AI4_P4 0.0 +#endif +#ifndef AI4_P5 +#define AI4_P5 0.0 +#endif + #endif // End of include guard: GPIO_H_ONCE diff --git a/g2core/plan_exec.cpp b/g2core/plan_exec.cpp index 17a46785f..e43f3b0d7 100644 --- a/g2core/plan_exec.cpp +++ b/g2core/plan_exec.cpp @@ -1019,6 +1019,9 @@ static stat_t _exec_aline_segment() // Otherwise if not at a section waypoint compute target from segment time and velocity // Don't do waypoint correction if you are going into a hold. + // See https://en.wikipedia.org/wiki/Kahan_summation_algorithm + // for the description of the summation compensation used. + if ((--mr.segment_count == 0) && (cm.motion_state != MOTION_HOLD)) { copy_vector(mr.gm.target, mr.waypoint[mr.section]); } else { @@ -1042,7 +1045,6 @@ static stat_t _exec_aline_segment() // NB: The direct manipulation of steps to compute travel_steps only works for Cartesian kinematics. // Other kinematics may require transforming travel distance as opposed to simply subtracting steps. - for (uint8_t m=0; mtarget[0] * cm.rotation_matrix[0][0] + + target_rotated[0] = gm_in->target[0] * cm.rotation_matrix[0][0] + gm_in->target[1] * cm.rotation_matrix[0][1] + gm_in->target[2] * cm.rotation_matrix[0][2]; - target_rotated[1] = gm_in->target[0] * cm.rotation_matrix[1][0] + + target_rotated[1] = gm_in->target[0] * cm.rotation_matrix[1][0] + gm_in->target[1] * cm.rotation_matrix[1][1] + gm_in->target[2] * cm.rotation_matrix[1][2]; - target_rotated[2] = gm_in->target[0] * cm.rotation_matrix[2][0] + + target_rotated[2] = gm_in->target[0] * cm.rotation_matrix[2][0] + gm_in->target[1] * cm.rotation_matrix[2][1] + - gm_in->target[2] * cm.rotation_matrix[2][2] + + gm_in->target[2] * cm.rotation_matrix[2][2] + cm.rotation_z_offset; // copy rotation axes ABC @@ -239,7 +239,7 @@ stat_t mp_aline(GCodeState_t* gm_in) * a replan, which is useful for feedholds and feed overrides. */ -void mp_plan_block_list() +void mp_plan_block_list() { mpBuf_t* bf = mp.p; bool planned_something = false; @@ -273,7 +273,7 @@ void mp_plan_block_list() * _plan_block() - the block chain using pessimistic assumptions */ -static mpBuf_t* _plan_block(mpBuf_t* bf) +static mpBuf_t* _plan_block(mpBuf_t* bf) { // First time blocks - set vmaxes for as many blocks as possible (forward loading of priming blocks) // Note: cruise_vmax was computed in _calculate_vmaxes() in aline() @@ -609,7 +609,7 @@ static void _calculate_jerk(mpBuf_t* bf) * so that the elapsed time from the start to the end of the motion is T plus * any time required for acceleration or deceleration. */ -static void _calculate_vmaxes(mpBuf_t* bf, const float axis_length[], const float axis_square[]) +static void _calculate_vmaxes(mpBuf_t* bf, const float axis_length[], const float axis_square[]) { float feed_time = 0; // one of: XYZ time, ABC time or inverse time. Mutually exclusive float max_time = 0; // time required for the rate-limiting axis @@ -694,7 +694,7 @@ static void _calculate_vmaxes(mpBuf_t* bf, const float axis_length[], const floa * C) The last move (there is not "next move" yet) will have to compate to a unit vector of zero. */ -static void _calculate_junction_vmax(mpBuf_t* bf) +static void _calculate_junction_vmax(mpBuf_t* bf) { // (C) special case for planning the last block if (bf->nx->buffer_state == MP_BUFFER_EMPTY) { diff --git a/g2core/planner.h b/g2core/planner.h index e097b79f2..a10cac314 100644 --- a/g2core/planner.h +++ b/g2core/planner.h @@ -28,7 +28,7 @@ /*x * --- Planner Background --- * - * The planner is a complicated beast that takes a lot of things into account. + * The planner is a complicated beast that takes a lot of things into account. * Planner documentation is scattered about and co-located with the functions * that perform the actions. Key files are: * @@ -42,31 +42,31 @@ * * --- Planner Overview --- * - * At high level the planner's job is to reconstruct smooth motion from a set of linear - * approximations while observing and operating within the physical constraints of the - * machine and the physics of motion. Gcode - which consists of a series of into linear - * motion segments - is interpreted, queued to the planner, and joined together to produce - * continuous, synchronized motion. Non-motion commands such as pauses (dwells) and - * peripheral controls such as spindles can also be synchronized in the queue. Arcs are + * At high level the planner's job is to reconstruct smooth motion from a set of linear + * approximations while observing and operating within the physical constraints of the + * machine and the physics of motion. Gcode - which consists of a series of into linear + * motion segments - is interpreted, queued to the planner, and joined together to produce + * continuous, synchronized motion. Non-motion commands such as pauses (dwells) and + * peripheral controls such as spindles can also be synchronized in the queue. Arcs are * just a special case consisting of many linear moves. Arcs are not interpreted directly. * - * The planner sits in the middle of three system layers: + * The planner sits in the middle of three system layers: * - The Gcode interpreter and canonical machine (the 'model'), which feeds... * - The planner - taking generic commands from the model and queuing them for... * - The runtime layer - pulling from the planner and driving stepper motors or other devices - * + * * The planner queue is the heart of the planner. It's a circular list of ~48 complex structures * that carry the state of the system needs to execute a linear motion, run a pre-planned command, * like turning on a spindle, or executing an arbitrary JSON command such as an active comment. * * The queue can be viewed as a list of instructions that will execute in exact sequence. - * Some instructions control motion and need to be joined to their forward and backwards - * neighbors so that position, velocity, acceleration, and jerk constraints are not - * violated when moving from one motion to the next. + * Some instructions control motion and need to be joined to their forward and backwards + * neighbors so that position, velocity, acceleration, and jerk constraints are not + * violated when moving from one motion to the next. * * Others are "commands" that are actually just function callbacks that happen to execute * at a particular point in time (synchronized with motion commands). Commands can control - * anything you can reasonably program, such as digital IO, serial communications, or + * anything you can reasonably program, such as digital IO, serial communications, or * interpreted commands encoded in JSON. * * The buffers in the planner queue are treated as a 'closure' - with all state needed for @@ -79,56 +79,56 @@ * - mp_aline() - plan and queue a move with acceleration management * - mp_dwell() - plan and queue a pause (dwell) to the planner queue * - mp_queue_command() - queue a canned command - * - mp_json_command() - queue a JSON command for run-time interpretation and execution (M100) + * - mp_json_command() - queue a JSON command for run-time interpretation and execution (M100) * - mp_json_wait() - queue a JSON wait for run-time interpretation and execution (M101) - * - - * In addition, cm_arc_feed() valaidates and sets up a arc paramewters and calls mp_aline() + * - + * In addition, cm_arc_feed() valaidates and sets up a arc paramewters and calls mp_aline() * repeatedly to spool out the arc segments into the planner queue. * * All the above queueing commands other than mp_aline() are relatively trivial; they just - * post callbacks into the next available planner buffer. Command functions are in 2 parts: - * the part that posts to the queue, and the callback that is executed when the command is + * post callbacks into the next available planner buffer. Command functions are in 2 parts: + * the part that posts to the queue, and the callback that is executed when the command is * finally reached in the queue - the _exec(). * - * All mp_aline() does is some preliminary math and then posts an initialized buffer to + * All mp_aline() does is some preliminary math and then posts an initialized buffer to * the planner queue. The rest of the move planning operations takes place in background; - * via mp_planner_callback() called from the main loop, and as 'pulls' from the runtime + * via mp_planner_callback() called from the main loop, and as 'pulls' from the runtime * stepper operations. * - * Motion planning is separated into backward planning and forward planning stages. - * Backward planning is initiated by mp_planner_callback() which is called repeatedly - * from the main loop. Backwards planning is performed by mp_plan_block_list() and - * _plan_block(). It starts at the most recently arrived Gcode block. Backward - * planning can occur multiple times for a given buffer, as new moves arriving + * Motion planning is separated into backward planning and forward planning stages. + * Backward planning is initiated by mp_planner_callback() which is called repeatedly + * from the main loop. Backwards planning is performed by mp_plan_block_list() and + * _plan_block(). It starts at the most recently arrived Gcode block. Backward + * planning can occur multiple times for a given buffer, as new moves arriving * can make the motion profile more optimal. * * Backward planning uses velocity and jerk constraints to set maximum entry, - * travel (cruise) and exit velocities for the moves in the queue. In addition, - * it observes the maximum cornering velocities that adjoining moves can sustain - * in a corner or a 'kink' to ensure that the jerk limit of any axis participating + * travel (cruise) and exit velocities for the moves in the queue. In addition, + * it observes the maximum cornering velocities that adjoining moves can sustain + * in a corner or a 'kink' to ensure that the jerk limit of any axis participating * in the move is not violated. See mp_planner_callback() header comments for more detail. * - * Forward planning is performed just-in-time and only once, right before the + * Forward planning is performed just-in-time and only once, right before the * planner runtime needs the next buffer. Forward planning provides the final - * contouring of the move. It is invoked by mp_forward_plan() and executed by + * contouring of the move. It is invoked by mp_forward_plan() and executed by * mp_calculate_ramps() in plan_zoid.cpp. * * Planner timing operates at a few different levels: * - * - New lines of ASCII containing commands and moves arriving from the USB are + * - New lines of ASCII containing commands and moves arriving from the USB are * parsed and executed as the lowest priority background task from the main loop. * - * - Backward planning is invoked by a main loop callback, so it also executes as + * - Backward planning is invoked by a main loop callback, so it also executes as * a background task, albeit a higher priority one. * - * - Forward planning and the ultimate preparation of the move for the runtime runs - * as an interrupt as a 'pull' from the planner queue that uses a series of - * interrupts at progressively lower priorities to ensure that the next planner + * - Forward planning and the ultimate preparation of the move for the runtime runs + * as an interrupt as a 'pull' from the planner queue that uses a series of + * interrupts at progressively lower priorities to ensure that the next planner * buffer is ready before the runtime runs out of forward-planned moves and starves. * * Some other functions performed by the planner include: * - * - Velocity throttling to ensure that very short moves do not execute faster + * - Velocity throttling to ensure that very short moves do not execute faster * than the serial interface can deliver them * * - Feed hold and cycle start (resume) operations @@ -364,7 +364,7 @@ struct mpBuffer_to_clear { void reset() { //memset((void *)(this), 0, sizeof(mpBuffer_to_clear)); - + bf_func = nullptr; cm_func = nullptr; diff --git a/g2core/pwm.cpp b/g2core/pwm.cpp index ecc5212b4..fe91d3f20 100755 --- a/g2core/pwm.cpp +++ b/g2core/pwm.cpp @@ -28,6 +28,7 @@ #include "g2core.h" // #1 #include "config.h" // #2 #include "hardware.h" +#include "gpio.h" #include "spindle.h" #include "text_parser.h" #include "pwm.h" @@ -40,8 +41,19 @@ pwmSingleton_t pwm; // Setup motate PWM pins -Motate::PWMOutputPin spindle_pwm_pin {Motate::kNormal, P1_PWM_FREQUENCY}; -Motate::PWMOutputPin secondary_pwm_pin {Motate::kNormal, P1_PWM_FREQUENCY}; // assume the same frequency, to start with at least +//Motate::PWMOutputPin spindle_pwm_pin {Motate::kNormal, P1_PWM_FREQUENCY}; +//Motate::PWMOutputPin secondary_pwm_pin {Motate::kNormal, P1_PWM_FREQUENCY}; // assume the same frequency, to start with at least + +gpioDigitalOutput *spindle_pwm_output = nullptr; +gpioDigitalOutput *secondary_pwm_output = nullptr; + +#ifndef SPINDLE_OUTPUT_NUMBER +#define SPINDLE_OUTPUT_NUMBER 6 +#endif + +#ifndef SECONDARY_PWM_OUTPUT_NUMBER +#define SECONDARY_PWM_OUTPUT_NUMBER 0 +#endif /***** PWM code *****/ /* @@ -53,7 +65,17 @@ Motate::PWMOutputPin secondary_pwm_pin {Motate:: * - See system.h for timer and port assignments * - Don't do this: memset(&TIMER_PWM1, 0, sizeof(PWM_TIMER_t)); // zero out the timer registers */ -void pwm_init() {} +void pwm_init() { + if (SPINDLE_OUTPUT_NUMBER > 0) { + spindle_pwm_output = d_out[SPINDLE_OUTPUT_NUMBER-1]; + spindle_pwm_output->setFrequency(P1_PWM_FREQUENCY); + + } + if (SECONDARY_PWM_OUTPUT_NUMBER > 0) { + secondary_pwm_output = d_out[SECONDARY_PWM_OUTPUT_NUMBER-1]; + secondary_pwm_output->setFrequency(P1_PWM_FREQUENCY); + } +} /* * pwm_set_freq() - set PWM channel frequency @@ -72,9 +94,13 @@ stat_t pwm_set_freq(uint8_t chan, float freq) //if (freq > PWM_MAX_FREQ) { return (STAT_INPUT_EXCEEDS_MAX_VALUE);} if (chan == PWM_1) { - spindle_pwm_pin.setFrequency(freq); + if (spindle_pwm_output != nullptr) { + spindle_pwm_output->setFrequency(freq); + } } else if (chan == PWM_2) { - secondary_pwm_pin.setFrequency(freq); + if (secondary_pwm_output != nullptr) { + secondary_pwm_output->setFrequency(freq); + } } return (STAT_OK); @@ -99,15 +125,13 @@ stat_t pwm_set_duty(uint8_t chan, float duty) if (duty > 1.0) { return (STAT_INPUT_EXCEEDS_MAX_VALUE);} if (chan == PWM_1) { -// if (spindle_pwm_pin.isNull()) { -// cm_alarm(STAT_ALARM, "attempt to turn on a non-existant spindle"); -// } - spindle_pwm_pin = duty; + if (spindle_pwm_output != nullptr) { + spindle_pwm_output->setValue(duty); + } } else if (chan == PWM_2) { -// if (secondary_pwm_pin.isNull()) { -// cm_alarm(STAT_ALARM, "attempt to turn on a non-existant spindle"); -// } - secondary_pwm_pin = duty; + if (secondary_pwm_output != nullptr) { + secondary_pwm_output->setValue(duty); + } } return (STAT_OK); diff --git a/g2core/settings/settings_Ultimaker_2_Plus.h b/g2core/settings/settings_Ultimaker_2_Plus.h index 56b6f88a6..350ebeb7f 100644 --- a/g2core/settings/settings_Ultimaker_2_Plus.h +++ b/g2core/settings/settings_Ultimaker_2_Plus.h @@ -88,7 +88,7 @@ // #define STATUS_REPORT_DEFAULTS "line","posx","posy","posz","posa","he1t","he1st","he1at","he1op","he3t","he3st","he3at","he3op","feed","vel","unit","path","stat","1ts","1sgr","1csa","2ts","2sgr","2csa","3ts","3sgr","3csa","4ts","4sgr","4csa" // Defaults for thermistor tuning: cut out: ,"he2t","he2st","he2at","he2tr","he2tv","he2op", -#define STATUS_REPORT_DEFAULTS "line","posx","posy","posz","posa","he1t","he1st","he1at","he1tr","he1tv","he1op","he3t","he3st","he3at","he3tr","he3tv","he3op","feed","vel","unit","path","stat","_xs1","_xs2","_xs3","_xs4","_fe1","_fe2","_fe3","_fe4" +#define STATUS_REPORT_DEFAULTS "line","posx","posy","posz","posa","aso","he1t","he1st","he1at","he1tr","he1tv","he1op","he3t","he3st","he3at","he3tr","he3tv","he3op","feed","vel","unit","path","stat","_xs1","_xs2","_xs3","_xs4","_fe1","_fe2","_fe3","_fe4" // Gcode startup defaults #define GCODE_DEFAULT_UNITS MILLIMETERS // MILLIMETERS or INCHES #define GCODE_DEFAULT_PLANE CANON_PLANE_XY // CANON_PLANE_XY, CANON_PLANE_XZ, or CANON_PLANE_YZ @@ -126,7 +126,7 @@ #define M1_MICROSTEPS 128 // 1mi 1,2,4,8,16,32 #define M1_POLARITY 0 // 1po 0=normal, 1=reversed #define M1_POWER_MODE MOTOR_POWERED_IN_CYCLE // 1pm standard -#define M1_POWER_LEVEL 0.8 // 1pl +#define M1_POWER_LEVEL 0.65 // 1pl #define M1_TMC2130_TPWMTHRS 1200 // 1pth #define M1_TMC2130_TCOOLTHRS 1000 // 1cth #define M1_TMC2130_THIGH 10 // 1hth @@ -149,7 +149,7 @@ #define M2_MICROSTEPS 128 #define M2_POLARITY 1 #define M2_POWER_MODE MOTOR_POWERED_IN_CYCLE -#define M2_POWER_LEVEL 0.8 +#define M2_POWER_LEVEL 0.65 #define M2_TMC2130_TPWMTHRS 1200 #define M2_TMC2130_TCOOLTHRS 1000 #define M2_TMC2130_THIGH 10 @@ -189,10 +189,10 @@ #define M4_MOTOR_MAP AXIS_A #define M4_STEP_ANGLE 1.8 #define M4_TRAVEL_PER_REV 360 // degrees moved per motor rev -#define M4_MICROSTEPS 128 +#define M4_MICROSTEPS 16 #define M4_POLARITY 0 #define M4_POWER_MODE MOTOR_POWER_MODE -#define M4_POWER_LEVEL 0.8 +#define M4_POWER_LEVEL 0.7 #define M4_TMC2130_TPWMTHRS 180000 #define M4_TMC2130_TCOOLTHRS 100000 #define M4_TMC2130_THIGH 10 @@ -231,7 +231,7 @@ // *** axis settings ********************************************************************************** #define X_AXIS_MODE AXIS_STANDARD // xam see canonical_machine.h cmAxisMode for valid values -#define X_VELOCITY_MAX 8700 // xvm G0 max velocity in mm/min +#define X_VELOCITY_MAX 15000 // xvm G0 max velocity in mm/min #define X_FEEDRATE_MAX X_VELOCITY_MAX // xfr G1 max feed rate in mm/min #define X_TRAVEL_MIN 0 // xtn minimum travel - used by soft limits and homing #define X_TRAVEL_MAX 230 // xtm travel between switches or crashes @@ -247,7 +247,7 @@ //{yjm:5000} #define Y_AXIS_MODE AXIS_STANDARD -#define Y_VELOCITY_MAX 8700 +#define Y_VELOCITY_MAX 15000 #define Y_FEEDRATE_MAX Y_VELOCITY_MAX #define Y_TRAVEL_MIN 0 #define Y_TRAVEL_MAX 224.5 @@ -299,18 +299,18 @@ #define A_AXIS_MODE AXIS_RADIUS #define A_RADIUS 1.428 -//#define A_VELOCITY_MAX 288886.4 +#define A_VELOCITY_MAX 288886.4 // {avm:288886.4} //#define A_VELOCITY_MAX 144443.0 // G0 rate ~60 mm/s, 3,600 mm/min -#define A_VELOCITY_MAX 72221.5 // G0 rate ~30 mm/s, 3,600 mm/min +//#define A_VELOCITY_MAX 72221.5 // G0 rate ~30 mm/s, 3,600 mm/min //NYLON //#define A_VELOCITY_MAX 30000.0 // G0 rate ~20 mm/s {avm:60000.0} //#define A_FEEDRATE_MAX 48147.7 // ~20 mm/s //#define A_FEEDRATE_MAX 36110.8 // ~15 mm/s //#define A_FEEDRATE_MAX 24073.9 // ~10 mm/s -//#define A_FEEDRATE_MAX 12036.95 // ~5 mm/s +#define A_FEEDRATE_MAX 12036.95 // ~5 mm/s //#define A_FEEDRATE_MAX 6018.475 // ~2.5 mm/s -#define A_FEEDRATE_MAX 3000.0 // ~0.415 mm/s {afr:2000} +//#define A_FEEDRATE_MAX 3000.0 // ~0.415 mm/s {afr:2000} // NYLON //#define A_FEEDRATE_MAX 800.0 // {afr:800} //#define A_FEEDRATE_MAX 500.0 // ~0.2075 mm/s @@ -318,7 +318,8 @@ #define A_TRAVEL_MAX 10 //#define A_JERK_MAX 288886.4 // ~120 million mm/min^3 //#define A_JERK_MAX 144443.2 // ~60 million mm/min^3 -#define A_JERK_MAX 40000.0 // ~20 million mm/min^3 {ajm:48147.7} +//#define A_JERK_MAX 40000.0 // ~20 million mm/min^3 {ajm:48147.7} +#define A_JERK_MAX 2000.0 // ~20 million mm/min^3 {ajm:48147.7} //NYLON //#define A_JERK_MAX 25000.0 // ~20 million mm/min^3 {ajm:15000.0} #define A_HOMING_INPUT 0 @@ -330,8 +331,9 @@ //#define A_JERK_HIGH_SPEED 288886.4 // ~120 million mm/min^3 //#define A_JERK_HIGH_SPEED 240739.0 // ~100 million mm/min^3 //#define A_JERK_HIGH_SPEED 144443.2 // ~60 million mm/min^3 -#define A_JERK_HIGH_SPEED 120000.0 // +//#define A_JERK_HIGH_SPEED 120000.0 // //#define A_JERK_HIGH_SPEED 95000.0 // ~40 million mm/min^3 +#define A_JERK_HIGH_SPEED 2000.0 // NYLON //#define A_JERK_HIGH_SPEED 35000.0 // ~30 million mm/min^3 {ajh:35000.0} @@ -356,7 +358,7 @@ M100.1 ({{avm:90000.0}}) M100.1 ({{afr:1000}}) M100.1 ({{ajm:25000.0}}) M100.1 ({{ajh:144000.0}}) - + {ajh:50000.0} {ajh:60000.0} @@ -371,11 +373,7 @@ M100.1 ({{ajh:144000.0}}) //** Temperature Sensors ** -#include "device/max31865/max31865.h" - -#define USING_A_MAX31865 1 - -#define HAS_TEMPERATURE_SENSOR_1 true +#define HAS_TEMPERATURE_SENSOR_1 false #if HAS_TEMPERATURE_SENSOR_1 // #define TEMPERATURE_SENSOR_1_CIRCUIT_TYPE ADCCircuitDifferentialPullup // #define TEMPERATURE_SENSOR_1_CIRCUIT_INIT { /*pullup_resistance:*/ 200 } @@ -406,7 +404,7 @@ M100.1 ({{ajh:144000.0}}) #define EXTRUDER_2_OUTPUT_PIN kHeaterOutput2_PinNumber -#define HAS_TEMPERATURE_SENSOR_3 true +#define HAS_TEMPERATURE_SENSOR_3 false #if HAS_TEMPERATURE_SENSOR_3 // #define TEMPERATURE_SENSOR_3_CIRCUIT_TYPE ADCCircuitDifferentialPullup // #define TEMPERATURE_SENSOR_3_CIRCUIT_INIT { /*pullup_resistance:*/ 200 } diff --git a/g2core/settings/settings_axidraw_v3.h b/g2core/settings/settings_axidraw_v3.h index 3b5df8ed7..f4795dd9b 100755 --- a/g2core/settings/settings_axidraw_v3.h +++ b/g2core/settings/settings_axidraw_v3.h @@ -91,18 +91,9 @@ #define KINEMATICS KINE_CORE_XY // X and Y MUST use the same settings! -#if MOTORS == 3 -// gQuadratic -#define A_B_POWER_LEVEL 0.4 -#define A_B_MICROSTEPS 32 -#define JERK_MAX 2000 -#endif -#if MOTORS == 6 -// gQuintic #define A_B_POWER_LEVEL 0.7 #define A_B_MICROSTEPS 64 #define JERK_MAX 3000 -#endif #define M1_MOTOR_MAP AXIS_COREXY_A // 1ma #define M1_STEP_ANGLE 1.8 // 1sa @@ -121,6 +112,8 @@ #define M2_POWER_LEVEL A_B_POWER_LEVEL #if MOTORS == 3 +// gQuadratic +// #warning Autodetected gQuadratic settings #define M3_MOTOR_MAP AXIS_Z // This "stepper" is a hobby servo. Note that all hobby // servo settings are per full servo range, instead of @@ -135,6 +128,8 @@ #endif #if MOTORS == 6 +// gQuintic +#warning Autodetected gQuintic settings #define M6_MOTOR_MAP AXIS_Z // This "stepper" is a hobby servo. Note that all hobby // servo settings are per full servo range, instead of @@ -194,153 +189,19 @@ #define Z_ZERO_BACKOFF 2 //*** Input / output settings *** -/* - IO_MODE_DISABLED - IO_ACTIVE_LOW aka NORMALLY_OPEN - IO_ACTIVE_HIGH aka NORMALLY_CLOSED - - INPUT_ACTION_NONE - INPUT_ACTION_STOP - INPUT_ACTION_FAST_STOP - INPUT_ACTION_HALT - INPUT_ACTION_RESET - - INPUT_FUNCTION_NONE - INPUT_FUNCTION_LIMIT - INPUT_FUNCTION_INTERLOCK - INPUT_FUNCTION_SHUTDOWN - INPUT_FUNCTION_PANIC -*/ -// Inputs are defined for the g2ref(a) board -// Xmn (board label) -#define DI1_MODE IO_ACTIVE_HIGH -#define DI1_ACTION INPUT_ACTION_NONE -#define DI1_FUNCTION INPUT_FUNCTION_NONE - -// Xmax -#define DI2_MODE IO_MODE_DISABLED +#define DI1_POLARITY IO_ACTIVE_HIGH +#define DI1_ACTION INPUT_ACTION_STOP + +#define DI2_POLARITY IO_ACTIVE_HIGH #define DI2_ACTION INPUT_ACTION_NONE -#define DI2_FUNCTION INPUT_FUNCTION_NONE -// Ymin -#define DI3_MODE IO_MODE_DISABLED +#define DI3_POLARITY IO_ACTIVE_HIGH #define DI3_ACTION INPUT_ACTION_NONE -#define DI3_FUNCTION INPUT_FUNCTION_NONE -// Ymax #define DI4_MODE IO_ACTIVE_HIGH #define DI4_ACTION INPUT_ACTION_NONE -#define DI4_FUNCTION INPUT_FUNCTION_NONE - -// Zmin -#define DI5_MODE IO_ACTIVE_LOW // Z probe -#define DI5_ACTION INPUT_ACTION_NONE -#define DI5_FUNCTION INPUT_FUNCTION_NONE - -// Zmax -#define DI6_MODE IO_MODE_DISABLED -#define DI6_ACTION INPUT_ACTION_STOP -#define DI6_FUNCTION INPUT_FUNCTION_NONE - -// Shutdown (Amin on v9 board) -#define DI7_MODE IO_MODE_DISABLED -#define DI7_ACTION INPUT_ACTION_NONE -#define DI7_FUNCTION INPUT_FUNCTION_NONE - -// High Voltage Z Probe In (Amax on v9 board) -#define DI8_MODE IO_ACTIVE_LOW -#define DI8_ACTION INPUT_ACTION_NONE -#define DI8_FUNCTION INPUT_FUNCTION_NONE - -// Hardware interlock input -#define DI9_MODE IO_MODE_DISABLED -#define DI9_ACTION INPUT_ACTION_NONE -#define DI9_FUNCTION INPUT_FUNCTION_NONE - -//Extruder1_PWM -#define DO1_MODE IO_ACTIVE_HIGH -//Extruder2_PWM +#define DO1_MODE IO_ACTIVE_HIGH #define DO2_MODE IO_ACTIVE_HIGH - -//Fan1A_PWM #define DO3_MODE IO_ACTIVE_HIGH - -//Fan1B_PWM #define DO4_MODE IO_ACTIVE_HIGH - -#define DO5_MODE IO_ACTIVE_HIGH -#define DO6_MODE IO_ACTIVE_HIGH -#define DO7_MODE IO_ACTIVE_HIGH -#define DO8_MODE IO_ACTIVE_HIGH - -//SAFEin (Output) signal -#define DO9_MODE IO_ACTIVE_HIGH - -#define DO10_MODE IO_ACTIVE_HIGH - -//Header Bed FET -#define DO11_MODE IO_ACTIVE_HIGH - -//Indicator_LED -#define DO12_MODE IO_ACTIVE_HIGH - -#define DO13_MODE IO_ACTIVE_HIGH - - -// *** PWM SPINDLE CONTROL *** - -#define P1_PWM_FREQUENCY 100 // in Hz -#define P1_CW_SPEED_LO 1000 // in RPM (arbitrary units) -#define P1_CW_SPEED_HI 2000 -#define P1_CW_PHASE_LO 0.125 // phase [0..1] -#define P1_CW_PHASE_HI 0.2 -#define P1_CCW_SPEED_LO 1000 -#define P1_CCW_SPEED_HI 2000 -#define P1_CCW_PHASE_LO 0.125 -#define P1_CCW_PHASE_HI 0.2 -#define P1_PWM_PHASE_OFF 0.1 - -// *** DEFAULT COORDINATE SYSTEM OFFSETS *** - -#define G54_X_OFFSET 0 // G54 is traditionally set to all zeros -#define G54_Y_OFFSET 0 -#define G54_Z_OFFSET 0 -#define G54_A_OFFSET 0 -#define G54_B_OFFSET 0 -#define G54_C_OFFSET 0 - -#define G55_X_OFFSET (X_TRAVEL_MAX/2) // set to middle of table -#define G55_Y_OFFSET (Y_TRAVEL_MAX/2) -#define G55_Z_OFFSET 0 -#define G55_A_OFFSET 0 -#define G55_B_OFFSET 0 -#define G55_C_OFFSET 0 - -#define G56_X_OFFSET 0 -#define G56_Y_OFFSET 0 -#define G56_Z_OFFSET 0 -#define G56_A_OFFSET 0 -#define G56_B_OFFSET 0 -#define G56_C_OFFSET 0 - -#define G57_X_OFFSET 0 -#define G57_Y_OFFSET 0 -#define G57_Z_OFFSET 0 -#define G57_A_OFFSET 0 -#define G57_B_OFFSET 0 -#define G57_C_OFFSET 0 - -#define G58_X_OFFSET 0 -#define G58_Y_OFFSET 0 -#define G58_Z_OFFSET 0 -#define G58_A_OFFSET 0 -#define G58_B_OFFSET 0 -#define G58_C_OFFSET 0 - -#define G59_X_OFFSET 0 -#define G59_Y_OFFSET 0 -#define G59_Z_OFFSET 0 -#define G59_A_OFFSET 0 -#define G59_B_OFFSET 0 -#define G59_C_OFFSET 0 diff --git a/g2core/settings/settings_default.h b/g2core/settings/settings_default.h index 24aa3b208..8a2713863 100644 --- a/g2core/settings/settings_default.h +++ b/g2core/settings/settings_default.h @@ -927,199 +927,411 @@ INPUT_ACTION_RESET INPUT_FUNCTION_NONE - INPUT_FUNCTION_LIMIT + INPUT_ACTION_LIMIT INPUT_FUNCTION_INTERLOCK INPUT_FUNCTION_SHUTDOWN INPUT_FUNCTION_PANIC */ // Xmin on v9 board -#ifndef DI1_MODE -#define DI1_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI1_ENABLED +#define DI1_ENABLED IO_ENABLED +#endif +#ifndef DI1_POLARITY +#define DI1_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI1_ACTION #define DI1_ACTION INPUT_ACTION_NONE #endif -#ifndef DI1_FUNCTION -#define DI1_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI1_EXTERNAL_NUMBER +#define DI1_EXTERNAL_NUMBER 1 #endif // Xmax -#ifndef DI2_MODE -#define DI2_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI2_ENABLED +#define DI2_ENABLED IO_ENABLED +#endif +#ifndef DI2_POLARITY +#define DI2_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI2_ACTION #define DI2_ACTION INPUT_ACTION_NONE #endif -#ifndef DI2_FUNCTION -#define DI2_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI2_EXTERNAL_NUMBER +#define DI2_EXTERNAL_NUMBER 2 #endif // Ymin -#ifndef DI3_MODE -#define DI3_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI3_ENABLED +#define DI3_ENABLED IO_ENABLED +#endif +#ifndef DI3_POLARITY +#define DI3_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI3_ACTION #define DI3_ACTION INPUT_ACTION_NONE #endif -#ifndef DI3_FUNCTION -#define DI3_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI3_EXTERNAL_NUMBER +#define DI3_EXTERNAL_NUMBER 3 #endif // Ymax -#ifndef DI4_MODE -#define DI4_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI4_ENABLED +#define DI4_ENABLED IO_ENABLED +#endif +#ifndef DI4_POLARITY +#define DI4_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI4_ACTION #define DI4_ACTION INPUT_ACTION_NONE #endif -#ifndef DI4_FUNCTION -#define DI4_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI4_EXTERNAL_NUMBER +#define DI4_EXTERNAL_NUMBER 4 #endif // Zmin -#ifndef DI5_MODE -#define DI5_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI5_ENABLED +#define DI5_ENABLED IO_ENABLED +#endif +#ifndef DI5_POLARITY +#define DI5_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI5_ACTION #define DI5_ACTION INPUT_ACTION_NONE #endif -#ifndef DI5_FUNCTION -#define DI5_FUNCTION INPUT_FUNCTION_PROBE +#ifndef DI5_EXTERNAL_NUMBER +#define DI5_EXTERNAL_NUMBER 5 #endif // Zmax -#ifndef DI6_MODE -#define DI6_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI6_ENABLED +#define DI6_ENABLED IO_ENABLED +#endif +#ifndef DI6_POLARITY +#define DI6_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI6_ACTION #define DI6_ACTION INPUT_ACTION_NONE #endif -#ifndef DI6_FUNCTION -#define DI6_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI6_EXTERNAL_NUMBER +#define DI6_EXTERNAL_NUMBER 6 #endif // Amin -#ifndef DI7_MODE -#define DI7_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI7_ENABLED +#define DI7_ENABLED IO_ENABLED +#endif +#ifndef DI7_POLARITY +#define DI7_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI7_ACTION #define DI7_ACTION INPUT_ACTION_NONE #endif -#ifndef DI7_FUNCTION -#define DI7_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI7_EXTERNAL_NUMBER +#define DI7_EXTERNAL_NUMBER 7 #endif // Amax -#ifndef DI8_MODE -#define DI8_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI8_ENABLED +#define DI8_ENABLED IO_ENABLED +#endif +#ifndef DI8_POLARITY +#define DI8_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI8_ACTION #define DI8_ACTION INPUT_ACTION_NONE #endif -#ifndef DI8_FUNCTION -#define DI8_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI8_EXTERNAL_NUMBER +#define DI8_EXTERNAL_NUMBER 8 #endif // Safety line -#ifndef DI9_MODE -#define DI9_MODE IO_ACTIVE_HIGH // Normally closed +#ifndef DI9_ENABLED +#define DI9_ENABLED IO_ENABLED +#endif +#ifndef DI9_POLARITY +#define DI9_POLARITY IO_ACTIVE_HIGH // Normally closed #endif #ifndef DI9_ACTION #define DI9_ACTION INPUT_ACTION_NONE #endif -#ifndef DI9_FUNCTION -#define DI9_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI9_EXTERNAL_NUMBER +#define DI9_EXTERNAL_NUMBER 9 #endif -#ifndef DI10_MODE -#define DI10_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI10_ENABLED +#define DI10_ENABLED IO_ENABLED +#endif +#ifndef DI10_POLARITY +#define DI10_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI10_ACTION #define DI10_ACTION INPUT_ACTION_NONE #endif -#ifndef DI10_FUNCTION -#define DI10_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI10_EXTERNAL_NUMBER +#define DI10_EXTERNAL_NUMBER 10 #endif -#ifndef DI11_MODE -#define DI11_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI11_ENABLED +#define DI11_ENABLED IO_ENABLED +#endif +#ifndef DI11_POLARITY +#define DI11_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI11_ACTION #define DI11_ACTION INPUT_ACTION_NONE #endif -#ifndef DI11_FUNCTION -#define DI11_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI11_EXTERNAL_NUMBER +#define DI11_EXTERNAL_NUMBER 11 #endif -#ifndef DI12_MODE -#define DI12_MODE IO_ACTIVE_LOW // Normally open +#ifndef DI12_ENABLED +#define DI12_ENABLED IO_ENABLED +#endif +#ifndef DI12_POLARITY +#define DI12_POLARITY IO_ACTIVE_LOW // Normally open #endif #ifndef DI12_ACTION #define DI12_ACTION INPUT_ACTION_NONE #endif -#ifndef DI12_FUNCTION -#define DI12_FUNCTION INPUT_FUNCTION_NONE +#ifndef DI12_EXTERNAL_NUMBER +#define DI12_EXTERNAL_NUMBER 12 +#endif + + +#ifndef PROBING_INPUT +#define PROBING_INPUT Z_HOMING_INPUT // default to the z homing input #endif // DIGITAL OUTPUTS - Currently these are hard-wired to extruders //Extruder1_PWM -#ifndef DO1_MODE -#define DO1_MODE IO_ACTIVE_HIGH +#ifndef DO1_ENABLED +#define DO1_ENABLED IO_ENABLED +#endif +#ifndef DO1_POLARITY +#define DO1_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO1_EXTERNAL_NUMBER +#define DO1_EXTERNAL_NUMBER 1 #endif //Extruder2_PWM -#ifndef DO2_MODE -#define DO2_MODE IO_ACTIVE_HIGH +#ifndef DO2_ENABLED +#define DO2_ENABLED IO_ENABLED +#endif +#ifndef DO2_POLARITY +#define DO2_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO2_EXTERNAL_NUMBER +#define DO2_EXTERNAL_NUMBER 2 #endif //Fan1A_PWM -#ifndef DO3_MODE -#define DO3_MODE IO_ACTIVE_HIGH +#ifndef DO3_ENABLED +#define DO3_ENABLED IO_ENABLED +#endif +#ifndef DO3_POLARITY +#define DO3_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO3_EXTERNAL_NUMBER +#define DO3_EXTERNAL_NUMBER 3 #endif //Fan1B_PWM -#ifndef DO4_MODE -#define DO4_MODE IO_ACTIVE_HIGH +#ifndef DO4_ENABLED +#define DO4_ENABLED IO_ENABLED +#endif +#ifndef DO4_POLARITY +#define DO4_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO4_EXTERNAL_NUMBER +#define DO4_EXTERNAL_NUMBER 4 #endif -#ifndef DO5_MODE -#define DO5_MODE IO_ACTIVE_HIGH +#ifndef DO5_ENABLED +#define DO5_ENABLED IO_ENABLED +#endif +#ifndef DO5_POLARITY +#define DO5_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO5_EXTERNAL_NUMBER +#define DO5_EXTERNAL_NUMBER 5 #endif -#ifndef DO6_MODE -#define DO6_MODE IO_ACTIVE_HIGH + +#ifndef DO6_ENABLED +#define DO6_ENABLED IO_ENABLED #endif -#ifndef DO7_MODE -#define DO7_MODE IO_ACTIVE_HIGH +#ifndef DO6_POLARITY +#define DO6_POLARITY IO_ACTIVE_HIGH #endif -#ifndef DO8_MODE -#define DO8_MODE IO_ACTIVE_HIGH +#ifndef DO6_EXTERNAL_NUMBER +#define DO6_EXTERNAL_NUMBER 6 #endif -//SAFEin (Output) signal -#ifndef DO9_MODE -#define DO9_MODE IO_ACTIVE_HIGH +#ifndef DO7_ENABLED +#define DO7_ENABLED IO_ENABLED +#endif +#ifndef DO7_POLARITY +#define DO7_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO7_EXTERNAL_NUMBER +#define DO7_EXTERNAL_NUMBER 7 #endif -#ifndef DO10_MODE -#define DO10_MODE IO_ACTIVE_HIGH +#ifndef DO8_ENABLED +#define DO8_ENABLED IO_ENABLED +#endif +#ifndef DO8_POLARITY +#define DO8_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO8_EXTERNAL_NUMBER +#define DO8_EXTERNAL_NUMBER 8 #endif -//Header Bed FET -#ifndef DO11_MODE -#define DO11_MODE IO_ACTIVE_HIGH +//SAFEin (Output) signal +#ifndef DO9_ENABLED +#define DO9_ENABLED IO_ENABLED +#endif +#ifndef DO9_POLARITY +#define DO9_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO9_EXTERNAL_NUMBER +#define DO9_EXTERNAL_NUMBER 9 #endif -//Indicator_LED -#ifndef DO12_MODE -#define DO12_MODE IO_ACTIVE_HIGH +#ifndef DO10_ENABLED +#define DO10_ENABLED IO_ENABLED +#endif +#ifndef DO10_POLARITY +#define DO10_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO10_EXTERNAL_NUMBER +#define DO10_EXTERNAL_NUMBER 10 #endif -#ifndef DO13_MODE -#define DO13_MODE IO_ACTIVE_HIGH +//Header Bed FET +#ifndef DO11_ENABLED +#define DO11_ENABLED IO_ENABLED +#endif +#ifndef DO11_POLARITY +#define DO11_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO11_EXTERNAL_NUMBER +#define DO11_EXTERNAL_NUMBER 11 #endif +//Indicator_LED +#ifndef DO12_ENABLED +#define DO12_ENABLED IO_ENABLED +#endif +#ifndef DO12_POLARITY +#define DO12_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO12_EXTERNAL_NUMBER +#define DO12_EXTERNAL_NUMBER 12 +#endif + +#ifndef DO13_ENABLED +#define DO13_ENABLED IO_ENABLED +#endif +#ifndef DO13_POLARITY +#define DO13_POLARITY IO_ACTIVE_HIGH +#endif +#ifndef DO13_EXTERNAL_NUMBER +#define DO13_EXTERNAL_NUMBER 13 +#endif + +// foind in gpio.h: +// #ifndef AI1_TYPE +// #define AI1_TYPE AIN_TYPE_DISABLED +// #endif +// #ifndef AI1_CIRCUIT +// #define AI1_CIRCUIT AIN_CIRCUIT_DISABLED +// #endif +// #ifndef AI1_P1 +// #define AI1_P1 0.0 +// #endif +// #ifndef AI1_P2 +// #define AI1_P2 0.0 +// #endif +// #ifndef AI1_P3 +// #define AI1_P3 0.0 +// #endif +// #ifndef AI1_P4 +// #define AI1_P4 0.0 +// #endif +// #ifndef AI1_P5 +// #define AI1_P5 0.0 +// #endif +// +// +// #ifndef AI2_TYPE +// #define AI2_TYPE AIN_TYPE_DISABLED +// #endif +// #ifndef AI2_CIRCUIT +// #define AI2_CIRCUIT AIN_CIRCUIT_DISABLED +// #endif +// #ifndef AI2_P1 +// #define AI2_P1 0.0 +// #endif +// #ifndef AI2_P2 +// #define AI2_P2 0.0 +// #endif +// #ifndef AI2_P3 +// #define AI2_P3 0.0 +// #endif +// #ifndef AI2_P4 +// #define AI2_P4 0.0 +// #endif +// #ifndef AI2_P5 +// #define AI2_P5 0.0 +// #endif +// +// #ifndef AI3_TYPE +// #define AI3_TYPE AIN_TYPE_DISABLED +// #endif +// #ifndef AI3_CIRCUIT +// #define AI3_CIRCUIT AIN_CIRCUIT_DISABLED +// #endif +// #ifndef AI3_P1 +// #define AI3_P1 0.0 +// #endif +// #ifndef AI3_P2 +// #define AI3_P2 0.0 +// #endif +// #ifndef AI3_P3 +// #define AI3_P3 0.0 +// #endif +// #ifndef AI3_P4 +// #define AI3_P4 0.0 +// #endif +// #ifndef AI3_P5 +// #define AI3_P5 0.0 +// #endif +// +// #ifndef AI4_TYPE +// #define AI4_TYPE AIN_TYPE_DISABLED +// #endif +// #ifndef AI4_CIRCUIT +// #define AI4_CIRCUIT AIN_CIRCUIT_DISABLED +// #endif +// #ifndef AI4_P1 +// #define AI4_P1 0.0 +// #endif +// #ifndef AI4_P2 +// #define AI4_P2 0.0 +// #endif +// #ifndef AI4_P3 +// #define AI4_P3 0.0 +// #endif +// #ifndef AI4_P4 +// #define AI4_P4 0.0 +// #endif +// #ifndef AI4_P5 +// #define AI4_P5 0.0 +// #endif + // *** PWM Settings *** // #ifndef P1_PWM_FREQUENCY diff --git a/g2core/settings/settings_smw3d_r7.h b/g2core/settings/settings_smw3d_r7.h new file mode 100644 index 000000000..6840275fa --- /dev/null +++ b/g2core/settings/settings_smw3d_r7.h @@ -0,0 +1,274 @@ +/* + * settings_smw3d_r7.h - SMW3d r7 machine with VFD + * This file is part of the g2core project + * + * Copyright (c) 2010 - 2016 Alden S. Hart, Jr. + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/***********************************************************************/ +/**** Shapeoko2 500mm profile ******************************************/ +/***********************************************************************/ + +// ***> NOTE: The init message must be a single line with no CRs or LFs +#define INIT_MESSAGE "Initializing configs to SMW3d r7" + +//**** GLOBAL / GENERAL SETTINGS ****************************************************** + +// Machine configuration settings + +#define JUNCTION_INTEGRATION_TIME 0.75 // cornering - between 0.10 and 2.00 (higher is faster) +#define CHORDAL_TOLERANCE 0.01 // chordal tolerance for arcs (in mm) + +#define SOFT_LIMIT_ENABLE 0 // 0=off, 1=on +#define HARD_LIMIT_ENABLE 0 // 0=off, 1=on +#define SAFETY_INTERLOCK_ENABLE 1 // 0=off, 1=on + +#define SPINDLE_ENABLE_POLARITY 1 // 0=active low, 1=active high +#define SPINDLE_DIR_POLARITY 0 // 0=clockwise is low, 1=clockwise is high +#define SPINDLE_PAUSE_ON_HOLD true +#define SPINDLE_DWELL_TIME 1.0 + +#define COOLANT_MIST_POLARITY 1 // 0=active low, 1=active high +#define COOLANT_FLOOD_POLARITY 1 // 0=active low, 1=active high +#define COOLANT_PAUSE_ON_HOLD false + +// Communications and reporting settings + +#define USB_SERIAL_PORTS_EXPOSED 1 // 1=single endpoint usb, 2=dual endpoint usb +#define COMM_MODE JSON_MODE // one of: TEXT_MODE, JSON_MODE +#define XIO_ENABLE_FLOW_CONTROL FLOW_CONTROL_RTS // FLOW_CONTROL_OFF, FLOW_CONTROL_RTS + +#define TEXT_VERBOSITY TV_VERBOSE // one of: TV_SILENT, TV_VERBOSE +#define JSON_VERBOSITY JV_MESSAGES // one of: JV_SILENT, JV_FOOTER, JV_CONFIGS, JV_MESSAGES, JV_LINENUM, JV_VERBOSE +#define QUEUE_REPORT_VERBOSITY QR_OFF // one of: QR_OFF, QR_SINGLE, QR_TRIPLE + +#define STATUS_REPORT_VERBOSITY SR_FILTERED // one of: SR_OFF, SR_FILTERED, SR_VERBOSE + +#define STATUS_REPORT_MIN_MS 100 // milliseconds - enforces a viable minimum +#define STATUS_REPORT_INTERVAL_MS 250 // milliseconds - set $SV=0 to disable + +//#define STATUS_REPORT_DEFAULTS "line","posx","posy","posz","posa","feed","vel","unit","coor","dist","admo","frmo","momo","stat" +#define STATUS_REPORT_DEFAULTS "line","posx","posy","posz","feed","vel","momo","stat" + +// Alternate SRs that report in drawable units +//#define STATUS_REPORT_DEFAULTS "line","vel","mpox","mpoy","mpoz","mpoa","coor","ofsa","ofsx","ofsy","ofsz","dist","unit","stat","homz","homy","homx","momo" +//#define STATUS_REPORT_DEFAULTS "_ts1","_cs1","_es1","_xs1","_fe1","line","posx","posy","posz","vel","stat" + +// Gcode startup defaults +#define GCODE_DEFAULT_UNITS MILLIMETERS // MILLIMETERS or INCHES +#define GCODE_DEFAULT_PLANE CANON_PLANE_XY // CANON_PLANE_XY, CANON_PLANE_XZ, or CANON_PLANE_YZ +#define GCODE_DEFAULT_COORD_SYSTEM G54 // G54, G55, G56, G57, G58 or G59 +#define GCODE_DEFAULT_PATH_CONTROL PATH_CONTINUOUS +#define GCODE_DEFAULT_DISTANCE_MODE ABSOLUTE_DISTANCE_MODE + +// *** motor settings ************************************************************************************ + +#define MOTOR_POWER_MODE MOTOR_POWERED_IN_CYCLE // default motor power mode (see cmMotorPowerMode in stepper.h) +#define MOTOR_POWER_TIMEOUT 2.00 // motor power timeout in seconds + +#define M1_MOTOR_MAP AXIS_X // 1ma +#define M1_STEP_ANGLE 1.8 // 1sa +#define M1_TRAVEL_PER_REV 8.0934060625 // 1tr +#define M1_MICROSTEPS 64 // 1mi 1,2,4,8,16,32 +#define M1_POLARITY 1 // 1po 0=normal, 1=reversed +#define M1_POWER_MODE MOTOR_ALWAYS_POWERED // 1pm TRUE=low power idle enabled +#define M1_POWER_LEVEL 0.500 + +#define M2_MOTOR_MAP AXIS_Y +#define M2_STEP_ANGLE 1.8 +#define M2_TRAVEL_PER_REV 8.0934060625 +#define M2_MICROSTEPS 64 +#define M2_POLARITY 0 +#define M2_POWER_MODE MOTOR_ALWAYS_POWERED +#define M2_POWER_LEVEL 0.500 + +#define M3_MOTOR_MAP AXIS_Y +#define M3_STEP_ANGLE 1.8 +#define M3_TRAVEL_PER_REV 8.0934060625 +#define M3_MICROSTEPS 64 +#define M3_POLARITY 0 +#define M3_POWER_MODE MOTOR_ALWAYS_POWERED +#define M3_POWER_LEVEL 0.500 + +#define M4_MOTOR_MAP AXIS_Z +#define M4_STEP_ANGLE 1.8 +#define M4_TRAVEL_PER_REV 8.0934060625 +#define M4_MICROSTEPS 64 +#define M4_POLARITY 1 +#define M4_POWER_MODE MOTOR_ALWAYS_POWERED +#define M4_POWER_LEVEL 0.750 + +// *** axis settings ********************************************************************************** + +#define JERK_MAX 5000 + +#define X_AXIS_MODE AXIS_STANDARD // xam see canonical_machine.h cmAxisMode for valid values +#define X_VELOCITY_MAX 5000 // xvm G0 max velocity in mm/min +#define X_FEEDRATE_MAX X_VELOCITY_MAX // xfr G1 max feed rate in mm/min +#define X_TRAVEL_MIN 0 // xtn minimum travel for soft limits +#define X_TRAVEL_MAX 824 // xtm travel between switches or crashes +#define X_JERK_MAX 3500 // xjm jerk * 1,000,000 +#define X_JERK_HIGH_SPEED 20000 // xjh +#define X_HOMING_INPUT 1 // xhi input used for homing or 0 to disable +#define X_HOMING_DIRECTION 1 // xhd 0=search moves negative, 1= search moves positive +#define X_SEARCH_VELOCITY 2000 // xsv minus means move to minimum switch +#define X_LATCH_VELOCITY 100 // xlv mm/min +#define X_LATCH_BACKOFF 4 // xlb mm +#define X_ZERO_BACKOFF 2 // xzb mm + +#define Y_AXIS_MODE AXIS_STANDARD +#define Y_VELOCITY_MAX 5000 +#define Y_FEEDRATE_MAX Y_VELOCITY_MAX +#define Y_TRAVEL_MIN 0 +#define Y_TRAVEL_MAX 781 +#define Y_JERK_MAX 3500 +#define Y_JERK_HIGH_SPEED 20000 +#define Y_HOMING_INPUT 2 +#define Y_HOMING_DIRECTION 1 +#define Y_SEARCH_VELOCITY 2000 +#define Y_LATCH_VELOCITY 100 +#define Y_LATCH_BACKOFF 4 +#define Y_ZERO_BACKOFF 2 + +#define Z_AXIS_MODE AXIS_STANDARD +#define Z_VELOCITY_MAX 1200 +#define Z_FEEDRATE_MAX Z_VELOCITY_MAX +#define Z_TRAVEL_MAX 75 +#define Z_TRAVEL_MIN -15 +#define Z_JERK_MAX 500 +#define Z_JERK_HIGH_SPEED 1000 +#define Z_HOMING_INPUT 3 +#define Z_HOMING_DIRECTION 1 +#define Z_SEARCH_VELOCITY (Z_VELOCITY_MAX * 0.66666) +#define Z_LATCH_VELOCITY 25 +#define Z_LATCH_BACKOFF 4 +#define Z_ZERO_BACKOFF 2 + +//*** Input / output settings *** +/* + IO_MODE_DISABLED + IO_ACTIVE_LOW aka NORMALLY_OPEN + IO_ACTIVE_HIGH aka NORMALLY_CLOSED + + INPUT_ACTION_NONE + INPUT_ACTION_STOP + INPUT_ACTION_FAST_STOP + INPUT_ACTION_HALT + INPUT_ACTION_RESET + + INPUT_FUNCTION_NONE + INPUT_FUNCTION_LIMIT + INPUT_FUNCTION_INTERLOCK + INPUT_FUNCTION_SHUTDOWN + INPUT_FUNCTION_PANIC +*/ +// Xmin on v9 board +#define DI1_POLARITY NORMALLY_CLOSED +//#define DI1_ACTION INPUT_ACTION_STOP +#define DI1_ACTION INPUT_ACTION_NONE +#define DI1_FUNCTION INPUT_FUNCTION_LIMIT + +// Xmax +#define DI2_POLARITY NORMALLY_CLOSED +//#define DI2_ACTION INPUT_ACTION_STOP +#define DI2_ACTION INPUT_ACTION_NONE +#define DI2_FUNCTION INPUT_FUNCTION_LIMIT + +// Ymin +#define DI3_POLARITY NORMALLY_CLOSED +//#define DI3_ACTION INPUT_ACTION_STOP +#define DI3_ACTION INPUT_ACTION_NONE +#define DI3_FUNCTION INPUT_FUNCTION_LIMIT + +// Ymax +#define DI4_POLARITY NORMALLY_CLOSED +//#define DI4_ACTION INPUT_ACTION_STOP +#define DI4_ACTION INPUT_ACTION_NONE +#define DI4_FUNCTION INPUT_FUNCTION_PROBE + +// Zmin +#define DI5_POLARITY IO_ACTIVE_HIGH // Z probe +#define DI5_ACTION INPUT_ACTION_NONE +#define DI5_FUNCTION INPUT_FUNCTION_NONE + +// Zmax +#define DI6_POLARITY NORMALLY_CLOSED +//#define DI6_ACTION INPUT_ACTION_STOP +#define DI6_ACTION INPUT_ACTION_NONE +#define DI6_FUNCTION INPUT_FUNCTION_LIMIT + +// Amin +#define DI7_ENABLED IO_DISABLED +#define DI7_ACTION INPUT_ACTION_NONE +#define DI7_FUNCTION INPUT_FUNCTION_NONE + +// Amax +#define DI8_ENABLED IO_DISABLED +#define DI8_ACTION INPUT_ACTION_NONE +#define DI8_FUNCTION INPUT_FUNCTION_NONE + +// Hardware interlock input +#define DI9_ENABLED IO_DISABLED +#define DI9_ACTION INPUT_ACTION_NONE +#define DI9_FUNCTION INPUT_FUNCTION_NONE + + +// *** PWM SPINDLE CONTROL *** + +/* VFD settings: + P0 settings need to be changed: + P0-000 = 1 (Select command source = Analog terminal control) + P0-001 = 3 (Select frequency source = max(Main frequency source x,Assistant frequency source y)) + P0-002 = 2 (Main frequency source x selection = AIN1) + + P0-007 = 400 + P0-024 = 400 (set maximum frequency at 100%) + + For run/stop and direction control: + P0-016 = 1 (factory) (X1 terminal function = forward run) + P0-017 = 2 (factory was 24) (X2 terminal function = reverse run) + P0-020 = 1 (2-wire mode = 2) + P0-021 = 0 (set minimum input) + P0-022 = 0 (set minimum speed) + + Disconnect X1, X2, set P0-24 to 10, and P0-023 to 10, and read the monitor, + then set the g2 to 100% output (via M3 or direct json), then use the shown value for P0-23 + + P0-023 = 9.22 for me (set maximum input voltage) + + + X1 = running + X2 = reverse direction (low = forward) + +*/ + +#define P1_PWM_FREQUENCY 100000 // in Hz +#define P1_CW_SPEED_LO 1 // in RPM (arbitrary units) +#define P1_CW_SPEED_HI 24000 +#define P1_CW_PHASE_LO 0.05 // phase [0..1] +#define P1_CW_PHASE_HI 1.0 +#define P1_CCW_SPEED_LO 1 +#define P1_CCW_SPEED_HI 24000.0 +#define P1_CCW_PHASE_LO 0.05 +#define P1_CCW_PHASE_HI 1.0 +#define P1_PWM_PHASE_OFF 0.0 diff --git a/g2core/settings/settings_synthetos_pendulum_v2.h b/g2core/settings/settings_synthetos_pendulum_v2.h new file mode 100644 index 000000000..d5a77e6a8 --- /dev/null +++ b/g2core/settings/settings_synthetos_pendulum_v2.h @@ -0,0 +1,282 @@ +/* + * settings_smw3d_r7.h - Synthetos Pendulum v2 + * This file is part of the g2core project + * + * Copyright (c) 2010 - 2016 Alden S. Hart, Jr. + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/***********************************************************************/ +/**** Shapeoko2 500mm profile ******************************************/ +/***********************************************************************/ + +// ***> NOTE: The init message must be a single line with no CRs or LFs +#define INIT_MESSAGE "Initializing configs to Pendulum v2" + +//**** GLOBAL / GENERAL SETTINGS ****************************************************** + +// Machine configuration settings + +#define JUNCTION_INTEGRATION_TIME 0.75 // cornering - between 0.10 and 2.00 (higher is faster) +#define CHORDAL_TOLERANCE 0.01 // chordal tolerance for arcs (in mm) + +#define SOFT_LIMIT_ENABLE 0 // 0=off, 1=on +#define HARD_LIMIT_ENABLE 0 // 0=off, 1=on +#define SAFETY_INTERLOCK_ENABLE 1 // 0=off, 1=on + +#define SPINDLE_ENABLE_POLARITY 1 // 0=active low, 1=active high +#define SPINDLE_DIR_POLARITY 0 // 0=clockwise is low, 1=clockwise is high +#define SPINDLE_PAUSE_ON_HOLD true +#define SPINDLE_DWELL_TIME 1.0 + +#define COOLANT_MIST_POLARITY 1 // 0=active low, 1=active high +#define COOLANT_FLOOD_POLARITY 1 // 0=active low, 1=active high +#define COOLANT_PAUSE_ON_HOLD false + +// Communications and reporting settings + +#define USB_SERIAL_PORTS_EXPOSED 1 // 1=single endpoint usb, 2=dual endpoint usb +#define COMM_MODE JSON_MODE // one of: TEXT_MODE, JSON_MODE +#define XIO_ENABLE_FLOW_CONTROL FLOW_CONTROL_RTS // FLOW_CONTROL_OFF, FLOW_CONTROL_RTS + +#define TEXT_VERBOSITY TV_VERBOSE // one of: TV_SILENT, TV_VERBOSE +#define JSON_VERBOSITY JV_MESSAGES // one of: JV_SILENT, JV_FOOTER, JV_CONFIGS, JV_MESSAGES, JV_LINENUM, JV_VERBOSE +#define QUEUE_REPORT_VERBOSITY QR_OFF // one of: QR_OFF, QR_SINGLE, QR_TRIPLE + +#define STATUS_REPORT_VERBOSITY SR_FILTERED // one of: SR_OFF, SR_FILTERED, SR_VERBOSE + +#define STATUS_REPORT_MIN_MS 100 // milliseconds - enforces a viable minimum +#define STATUS_REPORT_INTERVAL_MS 250 // milliseconds - set $SV=0 to disable + +//#define STATUS_REPORT_DEFAULTS "line","posx","posy","posz","posa","feed","vel","unit","coor","dist","admo","frmo","momo","stat" +#define STATUS_REPORT_DEFAULTS "line","posx","posy","posz","feed","vel","momo","stat" + +// Alternate SRs that report in drawable units +//#define STATUS_REPORT_DEFAULTS "line","vel","mpox","mpoy","mpoz","mpoa","coor","ofsa","ofsx","ofsy","ofsz","dist","unit","stat","homz","homy","homx","momo" +//#define STATUS_REPORT_DEFAULTS "_ts1","_cs1","_es1","_xs1","_fe1","line","posx","posy","posz","vel","stat" + +// Gcode startup defaults +#define GCODE_DEFAULT_UNITS MILLIMETERS // MILLIMETERS or INCHES +#define GCODE_DEFAULT_PLANE CANON_PLANE_XY // CANON_PLANE_XY, CANON_PLANE_XZ, or CANON_PLANE_YZ +#define GCODE_DEFAULT_COORD_SYSTEM G54 // G54, G55, G56, G57, G58 or G59 +#define GCODE_DEFAULT_PATH_CONTROL PATH_CONTINUOUS +#define GCODE_DEFAULT_DISTANCE_MODE ABSOLUTE_DISTANCE_MODE + +// *** motor settings ************************************************************************************ + +#define MOTOR_POWER_MODE MOTOR_POWERED_IN_CYCLE // default motor power mode (see cmMotorPowerMode in stepper.h) +#define MOTOR_POWER_TIMEOUT 2.00 // motor power timeout in seconds + +#define M1_MOTOR_MAP AXIS_X // 1ma +#define M1_STEP_ANGLE 1.8 // 1sa +#define M1_TRAVEL_PER_REV 60 // 1tr +#define M1_MICROSTEPS 64 // 1mi 1,2,4,8,16,32 +#define M1_POLARITY 1 // 1po 0=normal, 1=reversed +#define M1_POWER_MODE MOTOR_POWERED_IN_CYCLE // 1pm TRUE=low power idle enabled +#define M1_POWER_LEVEL 0.500 + +#define M5_MOTOR_MAP AXIS_X // 1ma +#define M5_STEP_ANGLE 1.8 // 1sa +#define M5_TRAVEL_PER_REV 60 // 1tr +#define M5_MICROSTEPS 64 // 1mi 1,2,4,8,16,32 +#define M5_POLARITY 1 // 1po 0=normal, 1=reversed +#define M5_POWER_MODE MOTOR_POWERED_IN_CYCLE // 1pm TRUE=low power idle enabled +#define M5_POWER_LEVEL 0.500 + +#define M2_MOTOR_MAP AXIS_X +#define M2_STEP_ANGLE 1.8 +#define M2_TRAVEL_PER_REV 60 +#define M2_MICROSTEPS 64 +#define M2_POLARITY 0 +#define M2_POWER_MODE MOTOR_POWERED_IN_CYCLE +#define M2_POWER_LEVEL 0.500 + +#define M3_MOTOR_MAP AXIS_X +#define M3_STEP_ANGLE 1.8 +#define M3_TRAVEL_PER_REV 60 +#define M3_MICROSTEPS 64 +#define M3_POLARITY 0 +#define M3_POWER_MODE MOTOR_POWERED_IN_CYCLE +#define M3_POWER_LEVEL 0.500 + +#define M4_MOTOR_MAP AXIS_X +#define M4_STEP_ANGLE 1.8 +#define M4_TRAVEL_PER_REV 60 +#define M4_MICROSTEPS 64 +#define M4_POLARITY 1 +#define M4_POWER_MODE MOTOR_POWERED_IN_CYCLE +#define M4_POWER_LEVEL 0.750 + +// *** axis settings ********************************************************************************** + +#define JERK_MAX 5000 + +#define X_AXIS_MODE AXIS_STANDARD // xam see canonical_machine.h cmAxisMode for valid values +#define X_VELOCITY_MAX 5000 // xvm G0 max velocity in mm/min +#define X_FEEDRATE_MAX X_VELOCITY_MAX // xfr G1 max feed rate in mm/min +#define X_TRAVEL_MIN 0 // xtn minimum travel for soft limits +#define X_TRAVEL_MAX 1370 // xtm travel between switches or crashes +#define X_JERK_MAX 3500 // xjm jerk * 1,000,000 +#define X_JERK_HIGH_SPEED 20000 // xjh +#define X_HOMING_INPUT 1 // xhi input used for homing or 0 to disable +#define X_HOMING_DIRECTION 1 // xhd 0=search moves negative, 1= search moves positive +#define X_SEARCH_VELOCITY 2000 // xsv minus means move to minimum switch +#define X_LATCH_VELOCITY 100 // xlv mm/min +#define X_LATCH_BACKOFF 4 // xlb mm +#define X_ZERO_BACKOFF 2 // xzb mm + +#define Y_AXIS_MODE AXIS_STANDARD +#define Y_VELOCITY_MAX 5000 +#define Y_FEEDRATE_MAX Y_VELOCITY_MAX +#define Y_TRAVEL_MIN 0 +#define Y_TRAVEL_MAX 781 +#define Y_JERK_MAX 3500 +#define Y_JERK_HIGH_SPEED 20000 +#define Y_HOMING_INPUT 2 +#define Y_HOMING_DIRECTION 1 +#define Y_SEARCH_VELOCITY 2000 +#define Y_LATCH_VELOCITY 100 +#define Y_LATCH_BACKOFF 4 +#define Y_ZERO_BACKOFF 2 + +#define Z_AXIS_MODE AXIS_STANDARD +#define Z_VELOCITY_MAX 1200 +#define Z_FEEDRATE_MAX Z_VELOCITY_MAX +#define Z_TRAVEL_MAX 75 +#define Z_TRAVEL_MIN -15 +#define Z_JERK_MAX 500 +#define Z_JERK_HIGH_SPEED 1000 +#define Z_HOMING_INPUT 3 +#define Z_HOMING_DIRECTION 1 +#define Z_SEARCH_VELOCITY (Z_VELOCITY_MAX * 0.66666) +#define Z_LATCH_VELOCITY 25 +#define Z_LATCH_BACKOFF 4 +#define Z_ZERO_BACKOFF 2 + +//*** Input / output settings *** +/* + IO_MODE_DISABLED + IO_ACTIVE_LOW aka NORMALLY_OPEN + IO_ACTIVE_HIGH aka NORMALLY_CLOSED + + INPUT_ACTION_NONE + INPUT_ACTION_STOP + INPUT_ACTION_FAST_STOP + INPUT_ACTION_HALT + INPUT_ACTION_RESET + + INPUT_FUNCTION_NONE + INPUT_FUNCTION_LIMIT + INPUT_FUNCTION_INTERLOCK + INPUT_FUNCTION_SHUTDOWN + INPUT_FUNCTION_PANIC +*/ +// Xmin on v9 board +#define DI1_POLARITY NORMALLY_CLOSED +//#define DI1_ACTION INPUT_ACTION_STOP +#define DI1_ACTION INPUT_ACTION_NONE +#define DI1_FUNCTION INPUT_FUNCTION_LIMIT + +// Xmax +#define DI2_POLARITY NORMALLY_CLOSED +//#define DI2_ACTION INPUT_ACTION_STOP +#define DI2_ACTION INPUT_ACTION_NONE +#define DI2_FUNCTION INPUT_FUNCTION_LIMIT + +// Ymin +#define DI3_POLARITY NORMALLY_CLOSED +//#define DI3_ACTION INPUT_ACTION_STOP +#define DI3_ACTION INPUT_ACTION_NONE +#define DI3_FUNCTION INPUT_FUNCTION_LIMIT + +// Ymax +#define DI4_POLARITY NORMALLY_CLOSED +//#define DI4_ACTION INPUT_ACTION_STOP +#define DI4_ACTION INPUT_ACTION_NONE +#define DI4_FUNCTION INPUT_FUNCTION_PROBE + +// Zmin +#define DI5_POLARITY IO_ACTIVE_HIGH // Z probe +#define DI5_ACTION INPUT_ACTION_NONE +#define DI5_FUNCTION INPUT_FUNCTION_NONE + +// Zmax +#define DI6_POLARITY NORMALLY_CLOSED +//#define DI6_ACTION INPUT_ACTION_STOP +#define DI6_ACTION INPUT_ACTION_NONE +#define DI6_FUNCTION INPUT_FUNCTION_LIMIT + +// Amin +#define DI7_ENABLED IO_DISABLED +#define DI7_ACTION INPUT_ACTION_NONE +#define DI7_FUNCTION INPUT_FUNCTION_NONE + +// Amax +#define DI8_ENABLED IO_DISABLED +#define DI8_ACTION INPUT_ACTION_NONE +#define DI8_FUNCTION INPUT_FUNCTION_NONE + +// Hardware interlock input +#define DI9_ENABLED IO_DISABLED +#define DI9_ACTION INPUT_ACTION_NONE +#define DI9_FUNCTION INPUT_FUNCTION_NONE + + +// *** PWM SPINDLE CONTROL *** + +/* VFD settings: + P0 settings need to be changed: + P0-000 = 1 (Select command source = Analog terminal control) + P0-001 = 3 (Select frequency source = max(Main frequency source x,Assistant frequency source y)) + P0-002 = 2 (Main frequency source x selection = AIN1) + + P0-007 = 400 + P0-024 = 400 (set maximum frequency at 100%) + + For run/stop and direction control: + P0-016 = 1 (factory) (X1 terminal function = forward run) + P0-017 = 2 (factory was 24) (X2 terminal function = reverse run) + P0-020 = 1 (2-wire mode = 2) + P0-021 = 0 (set minimum input) + P0-022 = 0 (set minimum speed) + + Disconnect X1, X2, set P0-24 to 10, and P0-023 to 10, and read the monitor, + then set the g2 to 100% output (via M3 or direct json), then use the shown value for P0-23 + + P0-023 = 9.22 for me (set maximum input voltage) + + + X1 = running + X2 = reverse direction (low = forward) + +*/ + +#define P1_PWM_FREQUENCY 100000 // in Hz +#define P1_CW_SPEED_LO 1 // in RPM (arbitrary units) +#define P1_CW_SPEED_HI 24000 +#define P1_CW_PHASE_LO 0.05 // phase [0..1] +#define P1_CW_PHASE_HI 1.0 +#define P1_CCW_SPEED_LO 1 +#define P1_CCW_SPEED_HI 24000.0 +#define P1_CCW_PHASE_LO 0.05 +#define P1_CCW_PHASE_HI 1.0 +#define P1_PWM_PHASE_OFF 0.0 diff --git a/g2core/spindle.cpp b/g2core/spindle.cpp index e61e1ee4d..a24891a9c 100644 --- a/g2core/spindle.cpp +++ b/g2core/spindle.cpp @@ -30,6 +30,7 @@ #include "canonical_machine.h" // #3 #include "text_parser.h" // #4 +#include "gpio.h" #include "spindle.h" #include "planner.h" #include "hardware.h" @@ -40,6 +41,18 @@ cmSpindleton_t spindle; + +gpioDigitalOutput *spindle_enable_output = nullptr; +gpioDigitalOutput *spindle_direction_output = nullptr; + +#ifndef SPINDLE_ENABLE_OUTPUT_NUMBER +#define SPINDLE_ENABLE_OUTPUT_NUMBER 4 +#endif + +#ifndef SPINDLE_DIRECTION_OUTPUT_NUMBER +#define SPINDLE_DIRECTION_OUTPUT_NUMBER 5 +#endif + /**** Static functions ****/ static void _exec_spindle_speed(float *value, bool *flag); @@ -52,6 +65,17 @@ static float _get_spindle_pwm (cmSpindleEnable enable, cmSpindleDir direction); */ void spindle_init() { + if (SPINDLE_ENABLE_OUTPUT_NUMBER > 0) { + spindle_enable_output = d_out[SPINDLE_ENABLE_OUTPUT_NUMBER-1]; + spindle_enable_output->setEnabled(IO_ENABLED); + spindle_enable_output->setPolarity((ioPolarity)SPINDLE_ENABLE_POLARITY); + } + if (SPINDLE_DIRECTION_OUTPUT_NUMBER > 0) { + spindle_direction_output = d_out[SPINDLE_DIRECTION_OUTPUT_NUMBER-1]; + spindle_direction_output->setEnabled(IO_ENABLED); + spindle_direction_output->setPolarity((ioPolarity)SPINDLE_DIR_POLARITY); + } + if( pwm.c[PWM_1].frequency < 0 ) { pwm.c[PWM_1].frequency = 0; } @@ -153,10 +177,10 @@ stat_t cm_spindle_control(uint8_t control) // requires SPINDLE_CONTROL_xxx styl return(STAT_OK); } - #define _set_spindle_enable_bit_hi() spindle_enable_pin.set() - #define _set_spindle_enable_bit_lo() spindle_enable_pin.clear() - #define _set_spindle_direction_bit_hi() spindle_dir_pin.set() - #define _set_spindle_direction_bit_lo() spindle_dir_pin.clear() +// #define _set_spindle_enable_bit_hi() spindle_enable_pin.set() +// #define _set_spindle_enable_bit_lo() spindle_enable_pin.clear() +// #define _set_spindle_direction_bit_hi() spindle_dir_pin.set() +// #define _set_spindle_direction_bit_lo() spindle_dir_pin.clear() static void _exec_spindle_control(float *value, bool *flag) { @@ -164,10 +188,13 @@ static void _exec_spindle_control(float *value, bool *flag) if (flag[1]) { spindle.direction = (cmSpindleDir)value[1]; // record spindle direction in the struct - if (spindle.direction ^ spindle.dir_polarity) { - _set_spindle_direction_bit_hi(); - } else { - _set_spindle_direction_bit_lo(); +// if (spindle.direction ^ spindle.dir_polarity) { +// _set_spindle_direction_bit_hi(); +// } else { +// _set_spindle_direction_bit_lo(); +// } + if (spindle_direction_output != nullptr) { + spindle_direction_output->setValue(spindle.direction); } } @@ -175,10 +202,13 @@ static void _exec_spindle_control(float *value, bool *flag) { // set on/off. Mask out PAUSE and consider it OFF spindle.enable = (cmSpindleEnable)value[0]; // record spindle enable in the struct - if ((spindle.enable & 0x01) ^ spindle.enable_polarity) { - _set_spindle_enable_bit_lo(); - } else { - _set_spindle_enable_bit_hi(); +// if ((spindle.enable & 0x01) ^ spindle.enable_polarity) { +// _set_spindle_enable_bit_lo(); +// } else { +// _set_spindle_enable_bit_hi(); +// } + if (spindle_enable_output != nullptr) { + spindle_enable_output->setValue(spindle.enable); } } diff --git a/g2core/stepper.h b/g2core/stepper.h index b8bc2c96f..29f12ac2c 100644 --- a/g2core/stepper.h +++ b/g2core/stepper.h @@ -245,19 +245,18 @@ * degrees of phase angle results in a step being generated. */ -// These includes must be BEFORE the STEPPER_H_ONCE is defined -#include "g2core.h" -#include "report.h" -#include "board_stepper.h" // include board specific stuff, in particular the Stepper objects - -// NOW we can do this: #ifndef STEPPER_H_ONCE #define STEPPER_H_ONCE +#include "g2core.h" +#include "report.h" + #include "MotateUtilities.h" // for HOT_DATA and HOT_FUNC #include "planner.h" // planner.h must precede stepper.h for moveType typedef +// Note: "board_stepper.h" is inlcluded at the end of this file + /********************************* * Stepper configs and constants * *********************************/ @@ -467,7 +466,7 @@ struct Stepper { } if (_power_state == MOTOR_IDLE) { return (0.0); - } + } return (st_cfg.mot[motor].power_level); }; @@ -475,7 +474,7 @@ struct Stepper { // { // return (_power_mode == MOTOR_DISABLED); // }; - + // turn on motor in all cases unless it's disabled // this version is called from the loader, and explicitly does NOT have floating point computations // HOT - called from the DDA interrupt @@ -519,7 +518,7 @@ struct Stepper { _motor_disable_timeout.clear(); _power_state = MOTOR_IDLE; // or MOTOR_OFF }; - + // turn off motor is only powered when moving // HOT - called from the DDA interrupt void motionStopped() //HOT_FUNC @@ -533,7 +532,7 @@ struct Stepper { } } }; - + virtual void periodicCheck(bool have_actually_stopped) // can be overridden { if (_was_enabled) { @@ -644,4 +643,6 @@ stat_t st_set_me(nvObj_t *nv); #endif // __TEXT_MODE +#include "board_stepper.h" // include board specific stuff, in particular the Stepper objects + #endif // End of include guard: STEPPER_H_ONCE diff --git a/g2core/temperature.cpp b/g2core/temperature.cpp index c7898d8a2..d668baf24 100755 --- a/g2core/temperature.cpp +++ b/g2core/temperature.cpp @@ -313,7 +313,7 @@ struct Thermistor { template Thermistor(const float temp_low, const float temp_med, const float temp_high, const float res_low, const float res_med, const float res_high, const ADCCircuit *_circuit, Ts&&... additional_values) : circuit{_circuit}, - adc_pin{kNormal, [&]{this->adc_has_new_value();}, additional_values...} + adc_pin{kNormal, [&]{this->adc_has_new_value();}, std::forward(additional_values)...} { setup(temp_low, temp_med, temp_high, res_low, res_med, res_high); adc_pin.setInterrupts(kPinInterruptOnChange|kInterruptPriorityLow); @@ -718,10 +718,6 @@ struct PID { } } - // Now tha we've done all the checks, square the error, maintaining the sign. - // The is because the energy required to heat an object is the number of degrees of change needed squared. - e = std::abs(e)*e; - // P = Proportional float p = _p_factor * e; @@ -755,8 +751,9 @@ struct PID { _derivative = (input - _previous_input)*(derivative_contribution) + (_derivative * (1.0-derivative_contribution)); float d = _derivative * _d_factor; + // F = feed-forward + _feed_forward = (_set_point-21); // 21 is for a roughly ideal room temperature - _feed_forward = std::abs(_feed_forward)*_feed_forward; float f = _f_factor * _feed_forward;