diff --git a/.gitignore b/.gitignore index c32dd46c..3c26b4e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ .pio .vscode venv -.venv -__pycache__ .idea cmake-* CMakeLists.txt @@ -11,3 +9,6 @@ build_cache Configuration_local* MeadeToWikiOutput.txt + +!Configuration_local_examples/ +!Configuration_local_examples/* diff --git a/Changelog.md b/Changelog.md index dbb8a601..32c3e3f9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,42 +1,3 @@ -**V1.13.19 - Updates** -- Support inverting and mirroring InfoDisplays. - -**V1.13.18 - Updates** -- Final changes for OAE - -**V1.13.17 - Updates** -- Store AZ/ALT steps per degree and allow them to be set from Meade -- Added more output to the InfoDisplay during boot and fixed a bug in console mode. -- Fixed a bug that was causing the firmware to hang after a slew, if a :Q# command was issued (thanks to user c3n for tracking it down, pun intended). - -**V1.13.16 - Updates** -- Throttled InfoDisplay updates. Turned off on two axis slew, limited to 5Hz on one-axis slew. -- Guide pulses are now ignored for DEC as well when at the limits. - -**V1.13.15 - Updates** -- Changes necessary for OAE, add OAE board -- Check `INFO_DISPLAY_TYPE` builds in CI -- Fix `INFO_DISPLAY_TYPE_I2C_SSD1306_128x64` for esp32 builds - -**V1.13.14 - Updates** -- Improved Serial command handling (made it less 'blocking'), which should improve general performance -- Guide pulses are ignored when tracking is disabled (for example, when at the limits) - -**V1.13.13 - Updates** -- Improved Meade command documentation -- Fixed a bug that was not correctly showing the stepper direction in the :GX# command reply./ - -**V1.13.12 - Updates** -- Parallelize matrix_build.py for faster CI builds -- Added basic test mode that can be run via terminal connection. - -**V1.13.11 - Updates** -- Fixed DEBUG macro usage. -- Clarified some Meade documentation. - -**V1.13.10 - Updates** -- Fixed dependency specification for git tags - **V1.13.9 - Updates** - Added guide logging support. - Fixed some Meade documentation errors. @@ -68,6 +29,7 @@ NOTE: Make sure to do a Factory Reset when using this version. - Lowered ESP32 second core priority - Added support for informational display - You must upgrade to OATControl V1.1.2.0 to use with this version (at least if you want to use teh DEC park/unpark feature) + **V1.13.2 - Updates** - Fix for RA steps being incorrectly set on every boot. diff --git a/Configuration.hpp b/Configuration.hpp index 010fb040..a4862044 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -266,14 +266,16 @@ #include "boards/RAMPS/pins_RAMPS.hpp" #elif (BOARD == BOARD_ESP32_ESP32DEV) #include "boards/ESP32_ESP32DEV/pins_ESP32DEV.hpp" -#elif (BOARD == BOARD_OAE_V1) - #include "boards/ESP32_ESP32DEV/pins_OAE_V1.hpp" #elif (BOARD == BOARD_AVR_MKS_GEN_L_V1) #include "boards/AVR_MKS_GEN_L_V1/pins_MKS_GEN_L_V1.h" #elif (BOARD == BOARD_AVR_MKS_GEN_L_V2) #include "boards/AVR_MKS_GEN_L_V2/pins_MKS_GEN_L_V2.h" #elif (BOARD == BOARD_AVR_MKS_GEN_L_V21) #include "boards/AVR_MKS_GEN_L_V21/pins_MKS_GEN_L_V21.h" +#elif (BOARD == BOARD_RP2040_JACKW01) + #include "boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp" +#elif (BOARD == BOARD_RP2040_SKR_PICO) + #include "boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp" #endif #include "Configuration_adv.hpp" diff --git a/ConfigurationValidation.hpp b/ConfigurationValidation.hpp index eb31aedb..7a42c202 100644 --- a/ConfigurationValidation.hpp +++ b/ConfigurationValidation.hpp @@ -17,7 +17,7 @@ #endif // Platform -#if defined(ESP32) || defined(__AVR_ATmega2560__) +#if defined(ESP32) || defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) // Valid platform #else #error Unsupported platform configuration. Use at own risk. @@ -30,6 +30,8 @@ && ((DISPLAY_TYPE == DISPLAY_TYPE_NONE) || (DISPLAY_TYPE == DISPLAY_TYPE_LCD_KEYPAD) || (DISPLAY_TYPE_LCD_KEYPAD_I2C_MCP23008) \ || (DISPLAY_TYPE_LCD_KEYPAD_I2C_MCP23017)) // Valid display for ATmega +#elif defined(ARDUINO_ARCH_RP2040) && (DISPLAY_TYPE == DISPLAY_TYPE_NONE) +// Valid display for RP2040 (no display in Phase 1) #else #error Unsupported display configuration. Use at own risk. #endif @@ -81,7 +83,7 @@ #else #error Defined an AZ driver, but no AZ stepper. #endif -#elif defined(__AVR_ATmega2560__) +#elif defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) // Azimuth configuration #if (AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) #ifndef AZ_DRIVER_ADDRESS @@ -89,8 +91,7 @@ #error AZ driver address for DRIVER_TYPE_TMC2209_UART not specified. #endif #endif -#elif defined(OAE) -// Valid OAE configuration + #else #error Configuration does not support AZ. Use at own risk. #endif @@ -102,7 +103,7 @@ #else #error Defined an ALT driver, but no ALT stepper. #endif -#elif defined(__AVR_ATmega2560__) +#elif defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) // Altitude configuration #if (ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) #ifndef ALT_DRIVER_ADDRESS @@ -166,8 +167,8 @@ // External sensors #if (USE_GPS == 0) // Baseline configuration without GPS is valid -#elif defined(ESP32) || defined(__AVR_ATmega2560__) -// GPS is supported on ESP32 and ATmega +#elif defined(ESP32) || defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) +// GPS is supported on ESP32, ATmega, and RP2040 #else #error Unsupported GPS configuration. Use at own risk. #endif @@ -197,7 +198,7 @@ #warning Missing pin assignments for MS pins #endif #elif (DEC_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) - #if !defined(DEC_STEP_PIN) || !defined(DEC_DIR_PIN) || !defined(DEC_EN_PIN) + #if !defined(DEC_STEP_PIN) || !defined(DEC_DIR_PIN) || !defined(DEC_EN_PIN) || !defined(DEC_DIAG_PIN) // Required pin assignments missing #error Missing pin assignments for configured DEC DRIVER_TYPE_TMC2209_UART driver #endif @@ -217,7 +218,7 @@ #warning Missing pin assignments for MS pins #endif #elif (RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) - #if !defined(RA_STEP_PIN) || !defined(RA_DIR_PIN) || !defined(RA_EN_PIN) + #if !defined(RA_STEP_PIN) || !defined(RA_DIR_PIN) || !defined(RA_EN_PIN) || !defined(RA_DIAG_PIN) // Required pin assignments missing #error Missing pin assignments for configured RA DRIVER_TYPE_TMC2209_UART driver #endif @@ -229,7 +230,7 @@ #if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) #if (AZ_DRIVER_TYPE == DRIVER_TYPE_A4988_GENERIC) || (AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_STANDALONE) - #if !defined(AZ_STEP_PIN) || !defined(AZ_DIR_PIN) || !defined(AZ_EN_PIN) + #if !defined(AZ_STEP_PIN) || !defined(AZ_DIR_PIN) || !defined(AZ_EN_PIN) || !defined(AZ_DIAG_PIN) // Required pin assignments missing #error Missing pin assignments for configured AZ DRIVER_TYPE_A4988_GENERIC or DRIVER_TYPE_TMC2209_STANDALONE driver #endif @@ -238,6 +239,12 @@ // Required pin assignments missing (ATmega uses SoftwareSerial for this driver) #error Missing pin assignments for configured AZ DRIVER_TYPE_TMC2209_UART driver #endif + #if !defined(AZ_DIAG_PIN) + // AZ_DIAG_PIN (TMC2209 DIAG output) is used only for stallGuard-based homing. + // It is optional: omit it if your hardware does not wire the DIAG output to a GPIO. + // Without it, stallGuard homing is unavailable but all other AZ motion works normally. + #pragma message "AZ_DIAG_PIN not defined. StallGuard homing unavailable for AZ axis." + #endif #if !((defined(AZ_SERIAL_PORT_TX) && defined(AZ_SERIAL_PORT_RX)) || defined(AZ_SERIAL_PORT)) // Required pin assignments missing for UART serial #error Missing pin assignments for configured AZ DRIVER_TYPE_TMC2209_UART driver serial connection @@ -247,7 +254,7 @@ #if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) #if (ALT_DRIVER_TYPE == DRIVER_TYPE_A4988_GENERIC) || (ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_STANDALONE) - #if !defined(ALT_STEP_PIN) || !defined(ALT_DIR_PIN) || !defined(ALT_EN_PIN) + #if !defined(ALT_STEP_PIN) || !defined(ALT_DIR_PIN) || !defined(ALT_EN_PIN) || !defined(ALT_DIAG_PIN) // Required pin assignments missing #error Missing pin assignments for configured AZ DRIVER_TYPE_A4988_GENERIC or DRIVER_TYPE_TMC2209_STANDALONE driver #endif @@ -256,6 +263,12 @@ // Required pin assignments missing (ATmega uses SoftwareSerial for this driver) #error Missing pin assignments for configured ALT DRIVER_TYPE_TMC2209_UART driver #endif + #if !defined(ALT_DIAG_PIN) + // ALT_DIAG_PIN (TMC2209 DIAG output) is used only for stallGuard-based homing. + // It is optional: omit it if your hardware does not wire the DIAG output to a GPIO. + // Without it, stallGuard homing is unavailable but all other ALT motion works normally. + #pragma message "ALT_DIAG_PIN not defined. StallGuard homing unavailable for ALT axis." + #endif #if !((defined(ALT_SERIAL_PORT_TX) && defined(ALT_SERIAL_PORT_RX)) || defined(ALT_SERIAL_PORT)) // Required pin assignments missing for UART serial #error Missing pin assignments for configured ALT DRIVER_TYPE_TMC2209_UART driver serial connection diff --git a/Configuration_adv.hpp b/Configuration_adv.hpp index bec77a73..e03ec5a4 100644 --- a/Configuration_adv.hpp +++ b/Configuration_adv.hpp @@ -22,15 +22,6 @@ #define BUFFER_LOGS false #endif -#ifndef OAM - #ifndef OAE - #define OAT "OAT" - #endif -#endif -#if defined(OAE) && defined(OAM) - #error "OAE and OAM cannot be defined at the same time" -#endif - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // //////// // MOTOR & DRIVER SETTINGS //////// @@ -241,14 +232,14 @@ #endif #ifndef DEC_LIMIT_UP - #if defined(OAM) || defined(OAE) + #ifdef OAM #define DEC_LIMIT_UP 135.0f #else #define DEC_LIMIT_UP 0.0f #endif #endif #ifndef DEC_LIMIT_DOWN - #if defined(OAM) || defined(OAE) + #ifdef OAM #define DEC_LIMIT_DOWN 135.0f #else #define DEC_LIMIT_DOWN 0.0f @@ -341,34 +332,16 @@ #define AZ_STEPPER_ACCELERATION (100 * AZ_MICROSTEPPING) #endif - // the Circumference of the AZ rotation. 808mm dia (OAT) + // the Circumference of the AZ rotation. 808mm dia. #ifndef AZ_CIRCUMFERENCE - #ifdef OAE - // Roughly from the joint to the rod placement is 70mm - #define AZ_CIRCUMFERENCE 56.0f * 2 * PI - #ifndef AZ_ROD_PITCH - #define AZ_ROD_PITCH 0.5 - #endif - #define AZIMUTH_STEPS_PER_REV \ - +(AZ_CORRECTION_FACTOR * (AZ_CIRCUMFERENCE / AZ_ROD_PITCH) * AZ_STEPPER_SPR * AZ_MICROSTEPPING) // Actually u-steps/rev - #else - #define AZ_CIRCUMFERENCE 2538.4f - #endif + #define AZ_CIRCUMFERENCE 2538.4f #endif - - #ifndef OAE - #define AZ_WORMGEAR_RATIO 1.0f - #endif - #ifndef AZIMUTH_STEPS_PER_REV #define AZIMUTH_STEPS_PER_REV \ (AZ_CORRECTION_FACTOR * (AZ_CIRCUMFERENCE / (AZ_PULLEY_TEETH * GT2_BELT_PITCH)) * AZ_STEPPER_SPR \ * AZ_MICROSTEPPING) // Actually u-steps/rev #endif - - #ifndef AZIMUTH_STEPS_PER_ARC_MINUTE - #define AZIMUTH_STEPS_PER_ARC_MINUTE (AZIMUTH_STEPS_PER_REV / (360 * 60.0f)) // Used to determine move distance in steps - #endif + #define AZIMUTH_STEPS_PER_ARC_MINUTE (AZIMUTH_STEPS_PER_REV / (360 * 60.0f)) // Used to determine move distance in steps // AZ TMC2209 UART settings // These settings work only with TMC2209 in UART connection (single wire to TX) @@ -400,7 +373,7 @@ #define ALT_MICROSTEPPING 4 #endif #ifndef ALT_STEPPER_SPR - #define ALT_STEPPER_SPR (400.0) // NEMA 0.9° = 400 | NEMA 1.8° = 200 + #define ALT_STEPPER_SPR 400 // NEMA 0.9° = 400 | NEMA 1.8° = 200 #endif #ifndef ALT_STEPPER_SPEED #define ALT_STEPPER_SPEED 2000 @@ -418,37 +391,24 @@ #define ALT_ROD_PITCH 1.0 // mm/rev #endif // the Circumference of the AZ rotation. 209.1mm radius. - #ifndef ALT_CIRCUMFERENCE - #define ALT_CIRCUMFERENCE 209.1 * 2 * PI - #endif + #define ALT_CIRCUMFERENCE 209.1 * 2 * PI #define ALTITUDE_STEPS_PER_REV \ (ALT_CORRECTION_FACTOR * (ALT_CIRCUMFERENCE / ALT_ROD_PITCH) * ALT_STEPPER_SPR * ALT_MICROSTEPPING) // Actually u-steps/rev #else - #ifdef OAE - #ifndef ALT_ROD_PITCH - #define ALT_ROD_PITCH 1.25 // mm/rev - #endif - // the Circumference of the ALT rotation. Roughly 146mm radius. - #define ALT_CIRCUMFERENCE 130.0f * 2 * PI - #define ALTITUDE_STEPS_PER_REV \ - +(ALT_CORRECTION_FACTOR * (ALT_CIRCUMFERENCE / ALT_ROD_PITCH) * ALT_STEPPER_SPR \ - * ALT_MICROSTEPPING) // Actually u-steps/rev + // the Circumference of the AZ rotation. 770mm dia. + #define ALT_CIRCUMFERENCE 2419.0f + #if AUTOPA_VERSION == 1 + // the ratio of the ALT gearbox for AutoPA V1 (40:3) + #define ALT_WORMGEAR_RATIO (40.0f / 3.0f) #else - // the Circumference of the AZ rotation. 770mm dia. - #define ALT_CIRCUMFERENCE 2419.0f - #if AUTOPA_VERSION == 1 - // the ratio of the ALT gearbox for AutoPA V1 (40:3) - #define ALT_WORMGEAR_RATIO (40.0f / 3.0f) - #else - // the ratio of the ALT gearbox for AutoPA V2 (40:1) - #define ALT_WORMGEAR_RATIO (40.0f) - #endif - #ifndef ALTITUDE_STEPS_PER_REV - #define ALTITUDE_STEPS_PER_REV \ - (ALT_CORRECTION_FACTOR * (ALT_CIRCUMFERENCE / (ALT_PULLEY_TEETH * GT2_BELT_PITCH)) * ALT_STEPPER_SPR \ - * ALT_MICROSTEPPING * ALT_WORMGEAR_RATIO) // Actually u-steps/rev - #endif + // the ratio of the ALT gearbox for AutoPA V2 (40:1) + #define ALT_WORMGEAR_RATIO (40.0f) + #endif + #ifndef ALTITUDE_STEPS_PER_REV + #define ALTITUDE_STEPS_PER_REV \ + (ALT_CORRECTION_FACTOR * (ALT_CIRCUMFERENCE / (ALT_PULLEY_TEETH * GT2_BELT_PITCH)) * ALT_STEPPER_SPR * ALT_MICROSTEPPING \ + * ALT_WORMGEAR_RATIO) // Actually u-steps/rev #endif #endif @@ -658,6 +618,23 @@ // //////// //////////////////////////////////////////// +// Stepper drivers +#if (RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) + #if defined(ESP32) + #define RA_SERIAL_PORT Serial2 // Can be shared with DEC_SERIAL_PORT + #elif defined(__AVR_ATmega2560__) + // Uses SoftwareSerial + #endif +#endif + +#if (DEC_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) + #if defined(ESP32) + #define DEC_SERIAL_PORT Serial2 // Can be shared with RA_SERIAL_PORT + #elif defined(__AVR_ATmega2560__) + // Uses SoftwareSerial + #endif +#endif + // Focuser #if (FOCUS_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) #if defined(ESP32) diff --git a/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp b/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp new file mode 100644 index 00000000..16fe2038 --- /dev/null +++ b/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp @@ -0,0 +1,154 @@ +/** + * @brief Local hardware configuration for a Raspberry Pi Pico (RP2040) + * on the BigTreeTech SKR Pico v1.0 printer controller board. + * + * This file is NOT tracked by Git and will survive branch changes. + * It is automatically included by LocalConfiguration.hpp when + * BOARD == BOARD_RP2040_SKR_PICO. + * + * Hardware summary + * ---------------- + * MCU : RP2040 (Raspberry Pi Pico) + * Board : BTT SKR Pico v1.0 + * Stepper slot : X -> RA (TMC2209, UART addr 0) + * Stepper slot : Y -> DEC (TMC2209, UART addr 2) + * Stepper slot : Z -> AZ (TMC2209, UART addr 1) + * Stepper slot : E0 -> ALT (TMC2209, UART addr 3) + * Motor rating : 0.9 deg / step (400 SPR), 470 mA + * Pulley : 16T aluminium GT2 + * RA homing : Hall sensor on GPIO4 (X-STOP / RA_DIAG_PIN) + * + * All pin assignments are in boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp. + * R_SENSE (0.11 ohm) is set globally in src/a_inits.hpp for all TMC2209_UART + * builds and does not need to be repeated here. + * + * Key difference from JackW01: each stepper driver has its own EN pin. + * AZ_ALWAYS_ON and ALT_ALWAYS_ON are NOT required on this board. + */ +#pragma once + +// ── Board ───────────────────────────────────────────────────────────────────── +#define BOARD BOARD_RP2040_SKR_PICO + +// ── Hemisphere ──────────────────────────────────────────────────────────────── +#define NORTHERN_HEMISPHERE 1 + +// ── Display (none) ──────────────────────────────────────────────────────────── +#define DISPLAY_TYPE DISPLAY_TYPE_NONE +#define INFO_DISPLAY_TYPE INFO_DISPLAY_TYPE_NONE + +// ── Stepper motor types ─────────────────────────────────────────────────────── +#define RA_STEPPER_TYPE STEPPER_TYPE_ENABLED +#define DEC_STEPPER_TYPE STEPPER_TYPE_ENABLED +#define AZ_STEPPER_TYPE STEPPER_TYPE_ENABLED +#define ALT_STEPPER_TYPE STEPPER_TYPE_ENABLED + +// ── Stepper driver types ────────────────────────────────────────────────────── +#define RA_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART +#define DEC_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART +#define AZ_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART +#define ALT_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART + +// ── Steps per revolution (0.9 deg motor = 400 full steps/rev) ───────────────── +#define RA_STEPPER_SPR 400 +#define DEC_STEPPER_SPR 400 +#define AZ_STEPPER_SPR 400 +#define ALT_STEPPER_SPR 400 + +// ── Pulley tooth count (16T aluminium GT2) ──────────────────────────────────── +#define RA_PULLEY_TEETH 16 +#define DEC_PULLEY_TEETH 16 +#define AZ_PULLEY_TEETH 16 +#define ALT_PULLEY_TEETH 16 + +// ── Microstepping ───────────────────────────────────────────────────────────── +// TMC2209 UART mode can switch microstepping dynamically at runtime. +// RA switches between slew (8×) and fine tracking (256×). +// DEC switches between slew (16×) and fine guiding (256×). +// AZ and ALT use a fixed microstepping mode (no dynamic switching). +#define RA_SLEW_MICROSTEPPING 8 // µsteps used while slewing RA +#define RA_TRACKING_MICROSTEPPING 256 // µsteps used for sidereal tracking +#define DEC_SLEW_MICROSTEPPING 16 // µsteps used while slewing DEC +#define DEC_GUIDE_MICROSTEPPING 256 // µsteps used for guide pulses +#define AZ_MICROSTEPPING 64 +#define ALT_MICROSTEPPING 4 + +// ── Motor direction ─────────────────────────────────────────────────────────── +// Set to 1 to reverse the direction of an axis if it moves the wrong way. +// Verify with manual move commands: :Mw#/:Me# (RA), :Mn#/:Ms# (DEC), +// :MAL#/:MAR# (AZ), :MAU#/:MAD# (ALT). Then set the appropriate flag to 1. +#define RA_INVERT_DIR 0 +#define DEC_INVERT_DIR 1 +#define AZ_INVERT_DIR 0 +#define ALT_INVERT_DIR 0 + +// ── StealthChop (silent mode) ───────────────────────────────────────────────── +// Configuration_adv.hpp defaults both to 0 (SpreadCycle = noisy). +// Set to 1 to enable StealthChop (silent) for RA tracking and DEC moves. +#define RA_UART_STEALTH_MODE 1 +#define DEC_UART_STEALTH_MODE 1 + +// ── Motor current ───────────────────────────────────────────────────────────── +// Motors are rated at 470 mA. Run at 75 % of rated current to reduce heat +// while maintaining adequate torque. RMS current is computed automatically: +// RMSCURRENT = RATING * (SETTING / 100) / sqrt(2) => ~249 mA RMS +// Do NOT define XXX_RMSCURRENT directly; Configuration_adv.hpp will error. +#define RA_MOTOR_CURRENT_RATING 470 // mA +#define RA_OPERATING_CURRENT_SETTING 75 // % + +#define DEC_MOTOR_CURRENT_RATING 470 // mA +#define DEC_OPERATING_CURRENT_SETTING 75 // % + +#define AZ_MOTOR_CURRENT_RATING 470 // mA +#define AZ_OPERATING_CURRENT_SETTING 75 // % + +#define ALT_MOTOR_CURRENT_RATING 470 // mA +#define ALT_OPERATING_CURRENT_SETTING 75 // % + +// ── AZ/ALT hold current ─────────────────────────────────────────────────────── +// AZ must hold position against backlash forces; use 40 % of run current. +// ALT is held by friction and gearing; bleed hold current to zero. +// These are percentages (0-100) converted to TMC2209 IHOLD by the firmware. +#define AZ_MOTOR_HOLD_SETTING 40 // % +#define ALT_MOTOR_HOLD_SETTING 0 // % + +// ── DEC axis travel limits ──────────────────────────────────────────────────── +// Physical limits measured from the home (level) position. +// These must be defined here; Configuration_adv.hpp defaults to 0.0f for +// non-OAM builds, which makes :Mn#/:Ms# target position 0 and do nothing. +#ifndef DEC_LIMIT_UP + #define DEC_LIMIT_UP 135.0f // 135° north of home +#endif +#ifndef DEC_LIMIT_DOWN + #define DEC_LIMIT_DOWN 35.0f // 35° south of home +#endif + +// ── RA Hall sensor auto-home ────────────────────────────────────────────────── +// Hall sensor is wired to GPIO4 (X-STOP input / RA_DIAG_PIN on SKR Pico). +// Active state LOW: sensor pulls GPIO4 LOW when the magnet is present. +// Search distance: 30° default (RA_HOMING_SENSOR_SEARCH_DEGREES in Configuration_adv.hpp). +// GPIO4 is configured INPUT (no pull-up); add external 10kΩ to 3.3V if sensor +// is open-drain, or change to INPUT_PULLUP in b_setup.hpp. +#define USE_HALL_SENSOR_RA_AUTOHOME 1 +#define RA_HOMING_SENSOR_PIN 4 // GPIO4 = RA_DIAG_PIN (X-STOP) +#define RA_HOMING_SENSOR_ACTIVE_STATE LOW // sensor pulls LOW when active + +// ── GPS ─────────────────────────────────────────────────────────────────────── +// ATGM336H-5N wired to left-side header: GPS TX→IO1, GPS RX→IO0, VCC→5V, GND. +// GPS_SERIAL_PORT, RP2040_GPS_TX_PIN, RP2040_GPS_RX_PIN defined in pins file. +// GPS_BAUD_RATE defaults to 9600 in Configuration_adv.hpp (matches module default). +#define USE_GPS 1 + +// ── FAN ─────────────────────────────────────────────────────────────────────── +// FAN1 power level as a percentage (0 = off, 100 = full speed). +// The pin and PWM are defined in pins_RP2040_SKR_PICO.hpp. +#define RP2040_FAN1_POWER_PERCENT 60 + +// Track immediately after boot +#define TRACK_ON_BOOT 0 + +// Uncomment to override defaults for stepper speeds and accelerations +//#define RA_STEPPER_SPEED 1200 // You can change the speed and acceleration of the steppers here. Max. Speed = 3000. +//#define RA_STEPPER_ACCELERATION 6000 +//#define DEC_STEPPER_SPEED 1300 // You can change the speed and acceleration of the steppers here. Max. Speed = 3000. +//#define DEC_STEPPER_ACCELERATION 6000 diff --git a/Constants.hpp b/Constants.hpp index f4a9ddd0..9c139e7e 100644 --- a/Constants.hpp +++ b/Constants.hpp @@ -18,7 +18,12 @@ // ESP32 based boards #define BOARD_ESP32_ESP32DEV 1001 -#define BOARD_OAE_V1 1002 + +// RP2040 based boards (2000-2999) +// 2101-2199: Pico family + JackW01 printer carrier board +// 2201-2299: BTT SKR Pico family +#define BOARD_RP2040_JACKW01 2101 // Raspberry Pi Pico (RP2040) + JackW01 printer board +#define BOARD_RP2040_SKR_PICO 2201 // Raspberry Pi Pico (RP2040) on BTT SKR Pico v1.0 /** * Supported keypad/display types. Use one of these values for DISPLAY_TYPE configuration matching your used display and keypad. diff --git a/LocalConfiguration.hpp b/LocalConfiguration.hpp index 14a00510..047f8164 100644 --- a/LocalConfiguration.hpp +++ b/LocalConfiguration.hpp @@ -16,8 +16,10 @@ #include "Configuration_local_mksgenlv1.hpp" #elif BOARD == BOARD_ESP32_ESP32DEV && __has_include("Configuration_local_esp32dev.hpp") #include "Configuration_local_esp32dev.hpp" -#elif BOARD == BOARD_OAE_V1 && __has_include("Configuration_local_oae.hpp") - #include "Configuration_local_oae.hpp" +#elif BOARD == BOARD_RP2040_JACKW01 && __has_include("Configuration_local_rp2040_jackw01.hpp") + #include "Configuration_local_rp2040_jackw01.hpp" +#elif BOARD == BOARD_RP2040_SKR_PICO && __has_include("Configuration_local_rp2040_skr_pico.hpp") + #include "Configuration_local_rp2040_skr_pico.hpp" #elif __has_include("Configuration_local.hpp") #include "Configuration_local.hpp" #endif \ No newline at end of file diff --git a/README.md b/README.md index f27b7423..07612870 100644 --- a/README.md +++ b/README.md @@ -57,14 +57,3 @@ When using `avr-stub` as a debug interface, it requires 2 things: Debugging is still a bit flakey, so you may need to try multiple times in order to get a solid debugging session. More information is available in the [avr-stub documentation](https://github.com/jdolinay/avr_debug/tree/master/doc) - -### Meade Command Documentation -The Meade commands page on the Wiki is generated by running: -```shell -python .\scripts\MeadeCommandParser.py -``` -from the main directory. The page is generated in the scripts folder and needs to be copy pasted into the Wiki manually. Please add the version manually (for now) by pasting something like this: -``` -> This documentation is current as of Firmware **V1.13.9** -{.is-warning} -``` diff --git a/Version.h b/Version.h index 1f1c5155..c65ec5df 100644 --- a/Version.h +++ b/Version.h @@ -3,4 +3,4 @@ // Also, numbers are interpreted as simple numbers. _ __ _ // So 1.8 is actually 1.08, meaning that 1.12 is a later version than 1.8. \_(..)_/ -#define VERSION "V1.13.19" +#define VERSION "V1.13.9" diff --git a/boards/ESP32_ESP32DEV/pins_OAE_V1.hpp b/boards/ESP32_ESP32DEV/pins_OAE_V1.hpp deleted file mode 100644 index c27116b3..00000000 --- a/boards/ESP32_ESP32DEV/pins_OAE_V1.hpp +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @brief a pins configuration file for an OAE board v1.0 - */ - -#pragma once - -// DRIVER_TYPE_TMC2209_UART requires 4 digital pins in Arduino pin numbering -#ifndef RA_STEP_PIN - #define RA_STEP_PIN 14 // STEP -#endif -#ifndef RA_DIR_PIN - #define RA_DIR_PIN 26 // DIR -#endif -#ifndef RA_EN_PIN - #define RA_EN_PIN 27 // Enable -#endif - -// DRIVER_TYPE_TMC2209_UART HardwareSerial port, can be shared across all drivers -#ifndef RA_SERIAL_PORT - #define RA_SERIAL_PORT Serial1 -#endif -#ifndef RA_TX_PIN - #define RA_TX_PIN 17 -#endif -#ifndef RA_RX_PIN - #define RA_RX_PIN 16 -#endif -#ifndef RA_DRIVER_ADDRESS - #define RA_DRIVER_ADDRESS 0b00 // Set by MS1/MS2. LOW/LOW in this case -#endif -// DRIVER_TYPE_TMC2209_UART requires 4 digital pins in Arduino pin numbering -#ifndef DEC_STEP_PIN - #define DEC_STEP_PIN 25 // STEP -#endif -#ifndef DEC_DIR_PIN - #define DEC_DIR_PIN 5 // DIR -#endif -#ifndef DEC_EN_PIN - #define DEC_EN_PIN 33 // Enable -#endif - -// DRIVER_TYPE_TMC2209_UART HardwareSerial port, can be shared across all drivers -#ifndef DEC_SERIAL_PORT - #define DEC_SERIAL_PORT Serial1 // SoftwareSerial TX port -#endif -#ifndef DEC_TX_PIN - #define DEC_TX_PIN 17 -#endif -#ifndef DEC_RX_PIN - #define DEC_RX_PIN 16 -#endif -#ifndef DEC_DRIVER_ADDRESS - #define DEC_DRIVER_ADDRESS 0b01 // Set by MS1/MS2 (MS1 HIGH, MS2 LOW) -#endif - -#define SW_SERIAL_UART 0 - -#ifndef ALT_STEP_PIN - #define ALT_STEP_PIN 13 // STEP -#endif -#ifndef ALT_DIR_PIN - #define ALT_DIR_PIN 23 // DIR -#endif -#ifndef ALT_EN_PIN - #define ALT_EN_PIN 4 // Enable -#endif - -#ifndef AZ_STEP_PIN - #define AZ_STEP_PIN 18 // STEP -#endif -#ifndef AZ_DIR_PIN - #define AZ_DIR_PIN 19 // DIR -#endif -#ifndef AZ_EN_PIN - #define AZ_EN_PIN 32 // Enable -#endif - -// DISPLAY_TYPE_LCD_JOY_I2C_SSD1306 requires 3 analog inputs in Arduino pin numbering -#ifndef LCD_KEY_SENSE_X_PIN -//#define LCD_KEY_SENSE_X_PIN 34 -#endif -#ifndef LCD_KEY_SENSE_Y_PIN -//#define LCD_KEY_SENSE_Y_PIN 39 -#endif -#ifndef LCD_KEY_SENSE_PUSH_PIN -//#define LCD_KEY_SENSE_PUSH_PIN 36 -#endif - -//Serial port for external debugging -#if DEBUG_SEPARATE_SERIAL == 1 - #ifndef DEBUG_SERIAL_PORT - #error "There is no default separate serial port for ESP32, please define DEBUG_SERIAL_PORT" - #endif -#else - #ifndef DEBUG_SERIAL_PORT - #define DEBUG_SERIAL_PORT Serial2 - #endif -#endif - -// Defines for OAE /////////////////////// - -#ifndef RA_WHEEL_CIRCUMFERENCE - #define RA_WHEEL_CIRCUMFERENCE 704.97f -#endif -#ifndef DEC_TRANSMISSION - #define DEC_TRANSMISSION (DEC_WHEEL_CIRCUMFERENCE / (DEC_PULLEY_TEETH * 1.0)) -#endif -#ifndef RA_LIMIT_LEFT - #define RA_LIMIT_LEFT 5.0f -#endif -#ifndef RA_LIMIT_RIGHT - #define RA_LIMIT_RIGHT 7.0f -#endif -#ifndef RA_TRACKING_LIMIT - #define RA_TRACKING_LIMIT 6.75f -#endif -#ifndef DEC_WHEEL_CIRCUMFERENCE - #define DEC_WHEEL_CIRCUMFERENCE 1.0f -#endif -#ifndef RA_STEPPER_SPR - #define RA_STEPPER_SPR (400 * 9) // change to (200 * 9) for 1.8° stepper -#endif -#ifndef DEC_STEPPER_SPR - #define DEC_STEPPER_SPR (200 * 50 * 4.5f) // change to (200 * 9) for 1.8° stepper -#endif -#ifndef DEC_PULLEY_TEETH - #define DEC_PULLEY_TEETH 1 -#endif diff --git a/boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp b/boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp new file mode 100644 index 00000000..a467647b --- /dev/null +++ b/boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp @@ -0,0 +1,141 @@ +/** + * @brief Pin configuration for a Raspberry Pi Pico (RP2040/RP2350) mounted on + * the JackW01 pi-pico-printer-board carrier (https://github.com/jackw01/pi-pico-printer-board). + * + * Stepper slot mapping: + * X slot -> RA (TMC2209 UART address 0) + * Y slot -> DEC (TMC2209 UART address 1) + * Z slot -> AZ (TMC2209 UART address 2) + * E slot -> ALT (TMC2209 UART address 3) + * + * All four stepper enable lines are tied together to a single GPIO on this + * board (GPIO5). Define every axis EN pin to the same value so the firmware + * compiles cleanly; in practice enabling/disabling one axis affects all. + * Per-axis power management should be handled via the TMC2209 IHOLD register + * over UART rather than toggling EN. + * + * TMC2209 UART: all four drivers share a single-wire bus on UART1. + * TX -> GPIO8 (UART1 TX) + * RX -> GPIO9 (UART1 RX) + * Pin remapping must be applied before Serial2.begin() in platform setup: + * Serial2.setTX(RP2040_UART1_TX_PIN); + * Serial2.setRX(RP2040_UART1_RX_PIN); + */ + +#pragma once + +// ── RA axis (X slot, TMC2209 address 0) ────────────────────────────────────── +#ifndef RA_STEP_PIN + #define RA_STEP_PIN 7 +#endif +#ifndef RA_DIR_PIN + #define RA_DIR_PIN 6 +#endif +#ifndef RA_EN_PIN + #define RA_EN_PIN 5 // Shared with all axes on this board +#endif +#ifndef RA_DIAG_PIN + #define RA_DIAG_PIN 4 // X endstop input - used for Hall sensor RA homing +#endif + +// RA TMC2209 UART +#ifndef RA_SERIAL_PORT + #define RA_SERIAL_PORT Serial2 // UART1 via Philhower Serial2 +#endif +#ifndef RA_DRIVER_ADDRESS + #define RA_DRIVER_ADDRESS 0b00 // MS1=LOW, MS2=LOW +#endif + +// ── DEC axis (Y slot, TMC2209 address 2) ───────────────────────────────────── +#ifndef DEC_STEP_PIN + #define DEC_STEP_PIN 11 +#endif +#ifndef DEC_DIR_PIN + #define DEC_DIR_PIN 10 +#endif +#ifndef DEC_EN_PIN + #define DEC_EN_PIN 5 // Shared with all axes on this board +#endif +#ifndef DEC_DIAG_PIN + #define DEC_DIAG_PIN 3 // Y endstop input +#endif + +// DEC TMC2209 UART +#ifndef DEC_SERIAL_PORT + #define DEC_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef DEC_DRIVER_ADDRESS + #define DEC_DRIVER_ADDRESS 0b01 // MS1=HIGH, MS2=LOW -> address 1 +#endif + +// ── AZ axis (Z slot, TMC2209 address 1) ────────────────────────────────────── +#ifndef AZ_STEP_PIN + #define AZ_STEP_PIN 13 +#endif +#ifndef AZ_DIR_PIN + #define AZ_DIR_PIN 12 +#endif +#ifndef AZ_EN_PIN + #define AZ_EN_PIN 5 // Shared with all axes on this board +#endif + +// AZ TMC2209 UART +#ifndef AZ_SERIAL_PORT + #define AZ_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef AZ_DRIVER_ADDRESS + #define AZ_DRIVER_ADDRESS 0b10 // MS1=LOW, MS2=HIGH -> address 2 +#endif + +// ── ALT axis (Extruder slot, TMC2209 address 3) ─────────────────────────────── +#ifndef ALT_STEP_PIN + #define ALT_STEP_PIN 15 +#endif +#ifndef ALT_DIR_PIN + #define ALT_DIR_PIN 14 +#endif +#ifndef ALT_EN_PIN + #define ALT_EN_PIN 5 // Shared with all axes on this board +#endif + +// ALT TMC2209 UART +#ifndef ALT_SERIAL_PORT + #define ALT_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef ALT_DRIVER_ADDRESS + #define ALT_DRIVER_ADDRESS 0b11 // MS1=HIGH, MS2=HIGH -> address 3 +#endif + +// ── UART1 physical pin assignments ─────────────────────────────────────────── +// The JackW01 board routes UART to the TMC2209 drivers as follows: +// GPIO8 → R202 (1kΩ) → RESET/TX pad (UART1 TX) +// GPIO9 → R201 (100Ω) → MS3/RX pad (UART1 RX) +// +// BigTreeTech TMC2209 modules have an onboard resistor bridging their +// RESET/TX and MS3/RX pads to PDN_UART, so both JackW01 lines reach +// the TMC2209 PDN_UART pin. Standard two-wire hardware UART1 is used: +// TX: GPIO8 (native UART1 TX mux function) +// RX: GPIO9 (native UART1 RX mux function) +// +// b_setup.hpp calls Serial2.setTX()/setRX() before Serial2.begin() to +// remap UART1 to these pins. +#ifndef RP2040_UART1_TX_PIN + #define RP2040_UART1_TX_PIN 8 +#endif +#ifndef RP2040_UART1_RX_PIN + #define RP2040_UART1_RX_PIN 9 +#endif + +// All drivers use hardware UART (Serial2). +#define SW_SERIAL_UART 0 + +// ── Shared EN pin override ──────────────────────────────────────────────────── +// All four TMC2209 EN lines are wired together to GPIO5 on this board. +// After per-axis init leaves GPIO5 in an indeterminate state, b_setup.hpp will +// drive RP2040_SHARED_EN_PIN LOW once to enable all drivers together. +#define RP2040_SHARED_EN_PIN 5 + +// ── Debug serial port ───────────────────────────────────────────────────────── +#ifndef DEBUG_SERIAL_PORT + #define DEBUG_SERIAL_PORT Serial // USB CDC serial via Philhower core +#endif diff --git a/boards/RP2040_PICO/pins_RP2040_PICO.hpp b/boards/RP2040_PICO/pins_RP2040_PICO.hpp new file mode 100644 index 00000000..cc78cdb1 --- /dev/null +++ b/boards/RP2040_PICO/pins_RP2040_PICO.hpp @@ -0,0 +1,43 @@ +/** + * @brief Pin configuration for a bare Raspberry Pi Pico (RP2040/RP2350) + * with user-defined wiring. + * + * This file provides no default pin assignments because there is no standard + * wiring for a bare Pico build. All pin definitions MUST be supplied in your + * local configuration file (e.g. Configuration_local_rp2040_pico.hpp). + * + * Required definitions (set in your local config): + * + * RA_STEP_PIN, RA_DIR_PIN, RA_EN_PIN + * DEC_STEP_PIN, DEC_DIR_PIN, DEC_EN_PIN + * + * If using TMC2209 UART: + * RA_SERIAL_PORT, RA_DRIVER_ADDRESS + * DEC_SERIAL_PORT, DEC_DRIVER_ADDRESS + * RP2040_UART1_TX_PIN, RP2040_UART1_RX_PIN (if using Serial2/UART1) + * + * If using Hall sensor homing: + * RA_DIAG_PIN + * + * Optional axes (AutoPA): + * AZ_STEP_PIN, AZ_DIR_PIN, AZ_EN_PIN, AZ_SERIAL_PORT, AZ_DRIVER_ADDRESS + * ALT_STEP_PIN, ALT_DIR_PIN, ALT_EN_PIN, ALT_SERIAL_PORT, ALT_DRIVER_ADDRESS + * + * Debug serial port: + * DEBUG_SERIAL_PORT (defaults to Serial / USB CDC if not defined) + */ + +#pragma once + +// ── Validate that the user has provided the minimum required pins ───────────── +#if !defined(RA_STEP_PIN) || !defined(RA_DIR_PIN) || !defined(RA_EN_PIN) + #error "BOARD_RP2040_PICO / BOARD_RP2350_PICO2: RA step/dir/en pins must be defined in your local configuration file." +#endif +#if !defined(DEC_STEP_PIN) || !defined(DEC_DIR_PIN) || !defined(DEC_EN_PIN) + #error "BOARD_RP2040_PICO / BOARD_RP2350_PICO2: DEC step/dir/en pins must be defined in your local configuration file." +#endif + +// ── Fallback debug serial ───────────────────────────────────────────────────── +#ifndef DEBUG_SERIAL_PORT + #define DEBUG_SERIAL_PORT Serial // USB CDC serial via Philhower core +#endif diff --git a/boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp b/boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp new file mode 100644 index 00000000..0f8c835a --- /dev/null +++ b/boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp @@ -0,0 +1,163 @@ +/** + * @brief Pin configuration for a Raspberry Pi Pico (RP2040) on the + * BigTreeTech SKR Pico v1.0 printer controller board. + * + * Hardware reference: https://github.com/bigtreetech/SKR-Pico + * Authoritative pin source: Klipper/SKR Pico klipper.cfg + * + * Stepper slot mapping (OAT axis -> board slot -> TMC2209 UART address): + * X slot -> RA (TMC2209 UART address 0) + * Y slot -> DEC (TMC2209 UART address 2) + * Z slot -> AZ (TMC2209 UART address 1) + * E0 slot -> ALT (TMC2209 UART address 3) + * + * Note: DEC uses address 2 and AZ uses address 1 — the opposite of the + * JackW01 board. This reflects the MS1/MS2 resistor strapping on + * the SKR Pico PCB. + * + * Each stepper driver has its own dedicated EN pin (unlike the JackW01 + * board where all EN lines share a single GPIO). No RP2040_SHARED_EN_PIN + * is needed; AZ_ALWAYS_ON / ALT_ALWAYS_ON are not required. + * + * TMC2209 UART: all four drivers share a two-wire bus on UART1. + * TX -> GPIO8 (UART1 TX, same physical assignment as JackW01) + * RX -> GPIO9 (UART1 RX, same physical assignment as JackW01) + * Pin remapping is applied in b_setup.hpp via: + * Serial2.setTX(RP2040_UART1_TX_PIN); + * Serial2.setRX(RP2040_UART1_RX_PIN); + * + * The SKR Pico has on-board TMC2209 ICs with proper PDN_UART wiring + * (both TX and RX reach each driver). No jumper is required. + * + * Endstop inputs (also usable as homing sensors): + * X-STOP -> GPIO4 (RA Hall sensor / diag input) + * Y-STOP -> GPIO3 + * Z-STOP -> GPIO25 + * E-STOP -> GPIO16 + * + * Additional I/O: + * BLTouch sensor -> GPIO22 + * BLTouch control -> GPIO29 + * NeoPixel data -> GPIO24 + */ + +#pragma once + +// ── RA axis (X slot, TMC2209 address 0) ────────────────────────────────────── +#ifndef RA_STEP_PIN + #define RA_STEP_PIN 11 +#endif +#ifndef RA_DIR_PIN + #define RA_DIR_PIN 10 +#endif +#ifndef RA_EN_PIN + #define RA_EN_PIN 12 // Individual EN pin (active LOW) +#endif +#ifndef RA_DIAG_PIN + #define RA_DIAG_PIN 4 // X-STOP input - used for Hall sensor RA homing +#endif + +// RA TMC2209 UART +#ifndef RA_SERIAL_PORT + #define RA_SERIAL_PORT Serial2 // UART1 via Philhower Serial2 +#endif +#ifndef RA_DRIVER_ADDRESS + #define RA_DRIVER_ADDRESS 0b00 // MS1=LOW, MS2=LOW -> address 0 +#endif + +// ── DEC axis (Y slot, TMC2209 address 2) ───────────────────────────────────── +#ifndef DEC_STEP_PIN + #define DEC_STEP_PIN 6 +#endif +#ifndef DEC_DIR_PIN + #define DEC_DIR_PIN 5 +#endif +#ifndef DEC_EN_PIN + #define DEC_EN_PIN 7 // Individual EN pin (active LOW) +#endif +#ifndef DEC_DIAG_PIN + #define DEC_DIAG_PIN 3 // Y-STOP input +#endif + +// DEC TMC2209 UART +#ifndef DEC_SERIAL_PORT + #define DEC_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef DEC_DRIVER_ADDRESS + #define DEC_DRIVER_ADDRESS 0b10 // MS1=LOW, MS2=HIGH -> address 2 +#endif + +// ── AZ axis (Z slot, TMC2209 address 1) ────────────────────────────────────── +#ifndef AZ_STEP_PIN + #define AZ_STEP_PIN 19 +#endif +#ifndef AZ_DIR_PIN + #define AZ_DIR_PIN 28 +#endif +#ifndef AZ_EN_PIN + #define AZ_EN_PIN 2 // Individual EN pin (active LOW) +#endif + +// AZ TMC2209 UART +#ifndef AZ_SERIAL_PORT + #define AZ_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef AZ_DRIVER_ADDRESS + #define AZ_DRIVER_ADDRESS 0b01 // MS1=HIGH, MS2=LOW -> address 1 +#endif + +// ── ALT axis (E0 slot, TMC2209 address 3) ──────────────────────────────────── +#ifndef ALT_STEP_PIN + #define ALT_STEP_PIN 14 +#endif +#ifndef ALT_DIR_PIN + #define ALT_DIR_PIN 13 +#endif +#ifndef ALT_EN_PIN + #define ALT_EN_PIN 15 // Individual EN pin (active LOW) +#endif + +// ALT TMC2209 UART +#ifndef ALT_SERIAL_PORT + #define ALT_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef ALT_DRIVER_ADDRESS + #define ALT_DRIVER_ADDRESS 0b11 // MS1=HIGH, MS2=HIGH -> address 3 +#endif + +// ── UART1 physical pin assignments ─────────────────────────────────────────── +// The SKR Pico routes UART1 to all four on-board TMC2209 ICs via a shared +// two-wire bus. GPIO8 and GPIO9 are the native UART1 TX/RX mux functions. +// b_setup.hpp calls Serial2.setTX()/setRX() before Serial2.begin(). +#ifndef RP2040_UART1_TX_PIN + #define RP2040_UART1_TX_PIN 8 +#endif +#ifndef RP2040_UART1_RX_PIN + #define RP2040_UART1_RX_PIN 9 +#endif + +// All drivers use hardware UART (Serial2). +#define SW_SERIAL_UART 0 + +// ── Debug serial port ───────────────────────────────────────────────────────── +#ifndef DEBUG_SERIAL_PORT + #define DEBUG_SERIAL_PORT Serial // USB CDC serial via Philhower core +#endif + +// ── GPS (UART0 on left-side header) ────────────────────────────────────────── +// Left-side 5-pin header: IO0=GPIO0, IO1=GPIO1, GND, 5V. +// RP2040 pin mux is fixed: GPIO0 = UART0 TX only, GPIO1 = UART0 RX only. +// GPS RX → GPIO0 / IO0 (RP2040 UART0 TX) +// GPS TX → GPIO1 / IO1 (RP2040 UART0 RX) +#define GPS_SERIAL_PORT Serial1 +#define RP2040_GPS_TX_PIN 0 // GPIO0 — UART0 TX → GPS RX +#define RP2040_GPS_RX_PIN 1 // GPIO1 — UART0 RX ← GPS TX + +// ── FAN outputs ─────────────────────────────────────────────────────────────── +// FAN1 connector: switched 12/24V via N-channel MOSFET gated by GPIO17. +// Power is set via analogWrite (0-100 %). Override RP2040_FAN1_POWER_PERCENT +// in your local config file to reduce fan speed. +#define RP2040_FAN1_PIN 17 +#ifndef RP2040_FAN1_POWER_PERCENT + #define RP2040_FAN1_POWER_PERCENT 100 +#endif diff --git a/matrix_build.py b/matrix_build.py index 8bc80b12..6dc9622c 100644 --- a/matrix_build.py +++ b/matrix_build.py @@ -4,29 +4,20 @@ import os import shutil import signal +import subprocess import click -import sys -from pathlib import Path -from typing import List import tabulate from constraint import * -from matrix_build_parallel import Executor, execute, get_available_executor_idx, get_finished_executor_idx, \ - cleanup_tempdirs, create_executors, get_source_files_to_link, wait_for_executor_to_finish, copy_caches_to_executors - CONTINUE_ON_ERROR = False -MKS_GENL_BOARDS = [ +BOARDS = [ "mksgenlv21", "mksgenlv2", "mksgenlv1", -] -AVR_BOARDS = MKS_GENL_BOARDS + [ - "ramps", -] -BOARDS = AVR_BOARDS + [ "esp32", + "ramps", ] STEPPER_TYPES = [ @@ -51,11 +42,6 @@ "DISPLAY_TYPE_LCD_JOY_I2C_SSD1306", ] -INFO_DISPLAY_TYPES = [ - "INFO_DISPLAY_TYPE_NONE", - "INFO_DISPLAY_TYPE_I2C_SSD1306_128x64", -] - BUILD_FLAGS = { "CONFIG_VERSION": "1", "RA_STEPPER_TYPE": [x for x in STEPPER_TYPES if x != "STEPPER_TYPE_NONE"], @@ -71,8 +57,6 @@ "FOCUS_STEPPER_TYPE": STEPPER_TYPES, "FOCUS_DRIVER_TYPE": DRIVER_TYPES, "DISPLAY_TYPE": DISPLAY_TYPES, - "INFO_DISPLAY_TYPE": INFO_DISPLAY_TYPES, - "TEST_VERIFY_MODE": BOOLEAN_VALUES, "DEBUG_LEVEL": ["DEBUG_NONE", "DEBUG_ANY"], "RA_MOTOR_CURRENT_RATING": "1", "RA_OPERATING_CURRENT_SETTING": "1", @@ -246,25 +230,6 @@ def driver_supports_stepper(d, s): problem.addConstraint(driver_supports_stepper, ["AZ_DRIVER_TYPE", "AZ_STEPPER_TYPE"]) problem.addConstraint(driver_supports_stepper, ["FOCUS_DRIVER_TYPE", "FOCUS_STEPPER_TYPE"]) - # AVR boards can't have both DISPLAY_TYPE and INFO_DISPLAY_TYPE enabled - def avr_display_exclusivity(board, display, info_display): - if board not in AVR_BOARDS: - return True - return ( - display == "DISPLAY_TYPE_NONE" or - info_display == "INFO_DISPLAY_TYPE_NONE" - ) - problem.addConstraint(avr_display_exclusivity, ["BOARD", "DISPLAY_TYPE", "INFO_DISPLAY_TYPE"]) - - # MKS GenL boards must not have a focus stepper when info display is enabled - def mksgenl_focus_exclusivity(board, info_display, focus_stepper): - if board not in MKS_GENL_BOARDS: - return True - if info_display != "INFO_DISPLAY_TYPE_NONE": - return focus_stepper == "STEPPER_TYPE_NONE" - return True - problem.addConstraint(mksgenl_focus_exclusivity, ["BOARD", "INFO_DISPLAY_TYPE", "FOCUS_STEPPER_TYPE"]) - # Define constraints for excluded tests def set_test_constraints(problem): @@ -296,14 +261,6 @@ def set_ci_constraints(problem): problem.addConstraint(InSetConstraint({"DISPLAY_TYPE_NONE", "DISPLAY_TYPE_LCD_KEYPAD"}), ["DISPLAY_TYPE"]) # problem.addConstraint(InSetConstraint({"DRIVER_TYPE_ULN2003"}), ["ALT_DRIVER_TYPE"]) - # Restrict INFO_DISPLAY_TYPE_I2C_SSD1306_128x64 to mksgenlv21 and esp32 only - # (just to reduce compile times) - def info_display_constraint(board, info_display): - if info_display == "INFO_DISPLAY_TYPE_I2C_SSD1306_128x64": - return board in ["mksgenlv21", "esp32"] - return True - problem.addConstraint(info_display_constraint, ["BOARD", "INFO_DISPLAY_TYPE"]) - def print_solutions_matrix(solutions, short_strings=False): def get_value(vb, vk): @@ -322,28 +279,43 @@ def get_value(vb, vk): print(tabulate.tabulate(rows, tablefmt="grid", showindex=map(shorten, keys), colalign=("right",))) -def print_failed_executor(executor: Executor): - print(f'Error for the following configuration ({executor.proj_dir}):', file=sys.stderr) - print_solutions_matrix([executor.solution]) - configuration_path = Path(executor.proj_dir, 'Configuration_local_matrix.hpp') - print(f'{configuration_path}:') - with open(configuration_path, 'r') as fp: - print(fp.read()) - out_bytes, err_bytes = executor.proc.communicate() - if out_bytes: - print(out_bytes.decode()) - if err_bytes: - print(err_bytes.decode(), file=sys.stderr) +def generate_config_file(flag_values): + content = "#pragma once\n\n" + for key, value in flag_values.items(): + content += "#define {} {}\n".format(key, value) + + with open("Configuration_local_matrix.hpp", 'w') as f: + f.write(content) + print("Generated local config") + print("Path: {}".format(os.path.abspath(f.name))) + print("Content:") + print(content) + + +def create_run_environment(flag_values): + build_env = dict(os.environ) + build_flags = " ".join(["-D{}={}".format(key, value) for key, value in flag_values.items()]) + build_env["PLATFORMIO_BUILD_FLAGS"] = build_flags + return build_env -def run_solution_blocking(executor: Executor, solution: dict) -> int: - executor.solution = copy.deepcopy(solution) - board = solution.pop("BOARD") - executor.proc = execute(executor.proj_dir, board, solution, jobs=os.cpu_count(), out_pipe=False) - executor.proc.wait() - if executor.proc.returncode != 0: - print_failed_executor(executor) - return executor.proc.returncode +def execute(board, flag_values, use_config_file=True): + if use_config_file: + build_env = dict(os.environ) + build_env["PLATFORMIO_BUILD_FLAGS"] = "-DMATRIX_LOCAL_CONFIG=1" + generate_config_file(flag_values) + else: + build_env = create_run_environment(flag_values) + + proc = subprocess.Popen( + "pio run -e {}".format(board), + # stdout=subprocess.PIPE, + # stderr=subprocess.PIPE, + shell=True, + env=build_env, + ) + (stdout, stderr) = proc.communicate() + return stdout, stdout, proc.returncode class GracefulKiller: @@ -381,60 +353,17 @@ def solve(board): solutions = problem.getSolutions() print_solutions_matrix(solutions, short_strings=False) - total_solutions = len(solutions) - print(f'Testing {total_solutions} combinations') - - nproc = min(os.cpu_count(), len(solutions)) - - local_paths_to_link = get_source_files_to_link() - executor_list: List[Executor] = create_executors(nproc, local_paths_to_link) - - print('First run to fill cache') - solution = solutions.pop() - retcode = run_solution_blocking(executor_list[0], solution) - if retcode != 0 and not CONTINUE_ON_ERROR: - exit(retcode) - - copy_caches_to_executors(executor_list[0].proj_dir, executor_list[1:]) - - solutions_built = 2 # We've already built one solution, and we're 1-indexing - exit_early = False # Exit trigger - while solutions: - # First fill any open execution slots - while get_available_executor_idx(executor_list) is not None: - available_executor_idx = get_available_executor_idx(executor_list) - executor = executor_list[available_executor_idx] - try: - solution = solutions.pop() - except IndexError: - # No more solutions to try! - break - print(f'[{solutions_built}/{total_solutions}] Building ...') - executor.solution = copy.deepcopy(solution) - board = solution.pop("BOARD") - executor.proc = execute(executor.proj_dir, board, solution) - solutions_built += 1 - - # Next wait for any processes to finish - wait_for_executor_to_finish(executor_list) - - # Go through all the finished processes and check their status - while get_finished_executor_idx(executor_list) is not None: - finished_executor_idx = get_finished_executor_idx(executor_list) - executor = executor_list[finished_executor_idx] - if executor.proc.returncode != 0: - print_failed_executor(executor) - if not CONTINUE_ON_ERROR: - exit_early = True - del executor.proc - executor.proc = None - - if exit_early: - break - if exit_early: - exit(1) - print('Done!') - cleanup_tempdirs(executor_list) + print("Testing {} combinations".format(len(solutions))) + + for num, solution in enumerate(solutions, start=1): + print("[{}/{}] Building ...".format(num, len(solutions)), flush=True) + print_solutions_matrix([solution]) + + board = solution.pop("BOARD") + (o, e, c) = execute(board, solution) + if c and not CONTINUE_ON_ERROR: + exit(c) + print(flush=True) if __name__ == '__main__': diff --git a/matrix_build_parallel.py b/matrix_build_parallel.py deleted file mode 100644 index 3b7fea41..00000000 --- a/matrix_build_parallel.py +++ /dev/null @@ -1,193 +0,0 @@ -""" -Module where all functionality that purely relates to how we parallelize matrix_build.py -should live. It's not a perfect split of course, but it helps to separate the 'matrix' -logic from the 'how we build' logic. -""" -import os -import shutil -import subprocess -import tempfile -import time -from pathlib import Path -from typing import Optional, List -from dataclasses import dataclass - - -@dataclass -class Executor: - """ - Core data that defines a solution that is being built - """ - # The directory where we are building the solution - proj_dir: Path - # The solution dictionary - solution: Optional[dict] = None - # The process building the solution - proc: Optional[subprocess.Popen] = None - # Object that holds tempdir data, so that it can be cleaned up later - tempdir_obj: Optional[tempfile.TemporaryDirectory] = None - - -def generate_config_file(project_location: Path, flag_values: dict): - content = "#pragma once\n\n" - for key, value in flag_values.items(): - content += "#define {} {}\n".format(key, value) - - with open(Path(project_location, "Configuration_local_matrix.hpp"), 'w') as f: - f.write(content) - f.flush() - - -def execute(project_location: Path, board: str, flag_values: dict, jobs: int = 1, out_pipe=True) -> subprocess.Popen: - """ - Start up an executor that is building a solution - :param project_location: The directory where to build the solution - :param board: The board type (aka environment) - :param flag_values: Dictionary of #defines to create a config file from - :param jobs: How many jobs the build process should use - :param out_pipe: If the executor's stdout/stderr should be pipes - :return: Process object that is executing the solution - """ - build_env = dict(os.environ) - build_env["PLATFORMIO_BUILD_FLAGS"] = "-DMATRIX_LOCAL_CONFIG=1" - generate_config_file(project_location, flag_values) - - proc = subprocess.Popen( - ['pio', - 'run', - f'--project-dir={str(project_location.resolve())}', - f'--environment={board}', - f'--jobs={jobs}', - ], - stdout=subprocess.PIPE if out_pipe else None, - stderr=subprocess.PIPE if out_pipe else None, - env=build_env, - close_fds=True, - ) - return proc - - -def get_available_executor_idx(e_list: List[Executor]) -> Optional[int]: - """ - Get the index of an idle executor - :param e_list: List of executors - :return: Idle executor index, else None if all are busy - """ - for i, executor in enumerate(e_list): - if executor.proc is None: - return i - return None - - -def get_finished_executor_idx(e_list: List[Executor]) -> Optional[int]: - """ - Get the index of a finished executor - :param e_list: List of executors - :return: Finished executor index, else None if all are busy - """ - for i, executor in enumerate(e_list): - if executor.proc is not None and executor.proc.poll() is not None: - return i - return None - - -def cleanup_tempdirs(e_list: List[Executor]): - """ - Delete all the temporary directories that executors were using - :param e_list: List of executors - """ - for executor in e_list: - if executor.tempdir_obj is not None: - tempdir_path = executor.tempdir_obj.name - print(f'Deleting {tempdir_path}') - shutil.rmtree(tempdir_path, ignore_errors=True) - - -def create_executors(num_executors: int, local_paths_to_link: List[Path]) -> List[Executor]: - """ - Create a number of executors and their associated temporary directories, then - soft-link all needed project files - :param num_executors: Number of executors to create - :param local_paths_to_link: List of files to soft-link into the executor projects - :return: List of executors - """ - executor_list: List[Executor] = [] - print(f'Creating {num_executors} executors') - for executor_idx in range(num_executors): - tempdir = tempfile.TemporaryDirectory() - temp_proj_path = Path(tempdir.name) - for local_path in local_paths_to_link: - temp_dst_path = Path(temp_proj_path, local_path).resolve() - os.makedirs(temp_dst_path.parent, exist_ok=True) - os.symlink(local_path.resolve(), temp_dst_path) - executor_list.append(Executor(temp_proj_path, tempdir_obj=tempdir)) - print(f'{executor_idx} ', end='') - print() - return executor_list - - -def copy_caches_to_executors(src_proj_dir: Path, dst_executors: List[Executor]): - """ - Copy cache directories from a source directory to a number of executor project directories - :param src_proj_dir: Directory to copy from - :param dst_executors: List of executors to copy to - """ - print('Copying caches to other executors') - dir_names_to_copy = ['.pio', 'build_cache'] - for dir_name_to_copy in dir_names_to_copy: - src_path = Path(src_proj_dir, dir_name_to_copy) - for dst_executor in dst_executors: - dst_path = Path(dst_executor.proj_dir, dir_name_to_copy) - shutil.copytree(src_path, dst_path) - - -def get_source_files_to_link() -> List[Path]: - """ - Create a list of the important files from the local project. I didn't want to - use git here, since that might not pick up untracked (but needed) files. - :return: List of source files that a project needs in order to compile - """ - local_proj_path = Path('.') - venv_dirs = list(local_proj_path.glob('*venv*/')) - # Don't link the .pio directory because the builds need to be independent - pio_dirs = list(local_proj_path.glob('*.pio*/')) - cmake_dirs = list(local_proj_path.glob('*cmake-build*/')) - - local_dirs_to_not_link = [Path('.git/'), Path('build_cache/')] + venv_dirs + pio_dirs + cmake_dirs - local_filenames_to_not_link = [ - Path('Configuration_local.hpp'), - Path('Configuration_local_matrix.hpp'), - ] - - local_paths_to_link = [] - for local_dir_str, local_subdirs, local_files in os.walk(local_proj_path): - local_dir_path = Path(local_dir_str) - dir_shouldnt_be_linked = any(d == local_dir_path or d in local_dir_path.parents for d in local_dirs_to_not_link) - if dir_shouldnt_be_linked: - continue - for local_file in local_files: - local_file_full_path = Path(local_dir_path, local_file) - file_shouldnt_be_linked = any(local_file_full_path == f for f in local_filenames_to_not_link) - if file_shouldnt_be_linked: - continue - local_paths_to_link.append(local_file_full_path) - return local_paths_to_link - - -def wait_for_executor_to_finish(executor_list: List[Executor], timeout=0.1, poll_time=0.2): - """ - Block until an executor has finished building - :param executor_list: List of executors - :param timeout: Time to communicate() with the running process (kind of a hack) - :param poll_time: Time to wait before checking all executors again - """ - while get_finished_executor_idx(executor_list) is None: - for e in executor_list: - if e.proc is not None and e.proc.poll() is None: - # Communicate with the running processes to stop them from blocking - # (i.e. they spew too much output) - try: - _ = e.proc.communicate(timeout=timeout) - except subprocess.TimeoutExpired: - pass # This is expected and what should happen - time.sleep(poll_time) diff --git a/platformio.ini b/platformio.ini index 32102b8c..76117d5f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -52,6 +52,7 @@ src_build_flags = -Wno-unused-parameter ; -Wold-style-cast -Wlogical-op + -Wuseless-cast ; Wdouble-promotion can't be enabled until GCC bug 55578 is fixed, since floats are ; implicitly converted to doubles when passed to a variadic function (i.e. a printf-like). ; Else we could disable Wdouble-promotion only for our logv function inside of the LOG macro @@ -82,9 +83,6 @@ upload_protocol = wiring build_flags = ${env.build_flags} -D BOARD=BOARD_AVR_RAMPS -src_build_flags = - ${env.src_build_flags} - -Wuseless-cast debug_tool = avr-stub debug_build_flags = ${env.debug_build_flags} @@ -130,11 +128,35 @@ lib_deps = ${common.lib_deps} WiFi -[env:oaeboardv1] -extends = env:esp32 +[common_rp2xxx] +extends = common_embedded +; Use maxgerhardt platform wrapper to access Earle Philhower arduino-pico core. +; The official platform-raspberrypi uses the Arduino-mbed core which has poorer +; library compatibility and no flexible UART pin remapping. +platform = https://github.com/maxgerhardt/platform-raspberrypi.git +board_build.core = earlephilhower +lib_deps = + teemuatlut/TMCStepper @ ^0.7.1 + waspinator/AccelStepper @ ^1.61 + mikalhart/TinyGPSPlus @ ^1.0.2 +; TimerInterrupt is AVR-only (uses OCR1A etc.); RP2040 uses hardware/timer.h directly +lib_ignore = TimerInterrupt + +[env:rp2040_jackw01] +extends = common_rp2xxx +board = rpipico +build_flags = + ${env.build_flags} + -Wno-deprecated-declarations ; arduino-pico core deprecates the B00000000-style Arduino::Binary.h macros used throughout the shared Mount code + -D BOARD=BOARD_RP2040_JACKW01 + +[env:rp2040_skr_pico] +extends = common_rp2xxx +board = rpipico build_flags = ${env.build_flags} - -D BOARD=BOARD_OAE_V1 -D ESP32BOARD + -Wno-deprecated-declarations ; arduino-pico core deprecates the B00000000-style Arduino::Binary.h macros used throughout the shared Mount code + -D BOARD=BOARD_RP2040_SKR_PICO [env:native] platform = native diff --git a/post_script_remove_patched_files.py b/post_script_remove_patched_files.py index bc7fcb61..73735819 100644 --- a/post_script_remove_patched_files.py +++ b/post_script_remove_patched_files.py @@ -2,7 +2,6 @@ import os import tempfile -from pathlib import Path def cprint(*args, **kwargs): @@ -14,13 +13,7 @@ def clean_up_patched_files(*_, **__): Removes all temporary patched files created previously in the build process """ # patch_path_key needs to be kept in sync with pre_script_patch_debug.py - # We put the current directory name in the key so that we only remove - # patched files that we know were built by the current build process. - # This is only useful in safeguarding against multiple builds being done in - # different directories at the same time. (i.e. we don't want to remove another - # processes' files while they are still in use) - project_dir_name = Path.cwd().name - patch_path_key = f'_{project_dir_name}_patched_' + patch_path_key = '_patched_' tempdir_path = tempfile.gettempdir() cprint(f'Temp file dir is {tempdir_path}') patched_filepaths = [] @@ -30,11 +23,7 @@ def clean_up_patched_files(*_, **__): patched_filepaths.append(full_filepath) for patched_filepath in patched_filepaths: cprint(f'Removing {patched_filepath}') - try: - os.remove(patched_filepath) - pass - except FileNotFoundError: - cprint('Not found (deleted already?)') + os.remove(patched_filepath) env.AddPostAction('buildprog', clean_up_patched_files) diff --git a/pre_script_patch_debug.py b/pre_script_patch_debug.py index bad10b26..5c166dd6 100644 --- a/pre_script_patch_debug.py +++ b/pre_script_patch_debug.py @@ -2,7 +2,6 @@ import os import tempfile -from pathlib import Path def cprint(*args, **kwargs): @@ -32,8 +31,7 @@ def patch_function_factory(src_path, output_suffix, replacement_list): def out_func(node): # patch_path_key needs to be kept in sync with post_script_remove_patched_files.py # so that after a successful build the patched file can be removed - project_dir_name = Path.cwd().name # See post_script_remove_patched_files.py on why this is needed - patch_path_key = f'_{project_dir_name}_patched_' + patch_path_key = '_patched_' with tempfile.NamedTemporaryFile(mode='w', suffix=f'{patch_path_key}{output_suffix}', delete=False) as tf: patched_filepath = tf.name cprint(f'Patching {src_path}') diff --git a/scripts/MeadeCommandParser.py b/scripts/MeadeCommandParser.py index 40f41d9a..22524f3d 100644 --- a/scripts/MeadeCommandParser.py +++ b/scripts/MeadeCommandParser.py @@ -11,8 +11,7 @@ import os import re -MEADE_CPP = "..\\src\\MeadeCommandProcessor.cpp" -VERSION_FILE = "..\\Version.h" +MEADE_HPP = "..\\src\\MeadeCommandProcessor.cpp" MODULE_PATH = os.path.dirname(os.path.realpath(__file__)) START_LINE = 0 END_LINE = 0 @@ -123,13 +122,8 @@ def check_command_sepparator(line): else: return False - -# *************************************************************** -# PARSE MEADE COMMANDS -# *************************************************************** - -# Meade cpp File -with open(os.path.join(MODULE_PATH, MEADE_CPP)) as f: +# Meade hpp File +with open(os.path.join(MODULE_PATH, MEADE_HPP)) as f: content = f.readlines() content = [x.strip() for x in content] @@ -210,7 +204,7 @@ def check_command_sepparator(line): m = l+1 while not check_command_sepparator(content[m]): command.remarks = remove_line_prefix(content[m]) - m += 1 + m += 1 l = m # Parameters @@ -232,24 +226,6 @@ def check_command_sepparator(line): new_family.commands.append(command) all_commands.append(new_family) -# *************************************************************** -# PARSE MEADE COMMANDS -# *************************************************************** -CURRENT_VERSION = "0.0" -with open(os.path.join(MODULE_PATH, VERSION_FILE)) as f: - version_content = f.readlines() -version_content = [x.strip() for x in version_content] - -for line in version_content: - if "#define VERSION" in line: - CURRENT_VERSION = line.replace("#define VERSION ", "") - CURRENT_VERSION = CURRENT_VERSION.replace("\"", "") - print(f"Found current version: {CURRENT_VERSION}") - -if CURRENT_VERSION == "0.0": - raise Exception("Could not find current version to parse from") - - def output_wiki(): """ Writes content to a MeadeToWikiOutput.txt file @@ -257,13 +233,9 @@ def output_wiki(): f = open("./scripts/MeadeToWikiOutput.txt", "w") - f.write("> AUTOMATICALLY GENERATED FROM FIRMWARE - DO NOT EDIT\n") - f.write("{.is-danger}\n\n") - - f.write(f"> This documentation is current as of Firmware **{CURRENT_VERSION}**\n") - f.write("{.is-warning}\n\n") - for fam in all_commands: + f.write("> AUTOMATICALLY GENERATED FROM FIRMWARE - DO NOT EDIT\n") + f.write("{.is-danger}\n\n") f.write(f"## {fam.name}\n") f.write("
\n\n") @@ -274,7 +246,7 @@ def output_wiki(): if cmd.information: #f.write("**Information:**\n") for line in cmd.information: - f.write(f"{line} ") + f.write(f"{line}") f.write("\n\n") f.write(f"**Command:**\n") @@ -309,12 +281,6 @@ def output_wiki(): f.write("\n") f.write("\n\n") - - f.write("> AUTOMATICALLY GENERATED FROM FIRMWARE - DO NOT EDIT\n") - f.write("{.is-danger}\n\n") - - f.write(f"> This documentation is current as of Firmware **{CURRENT_VERSION}**\n") - f.write("{.is-warning}\n\n") f.close() print("File written to: ./scripts/MeadeToWikiOutput.txt") diff --git a/src/DayTime.hpp b/src/DayTime.hpp index bfce4233..ceca7a47 100644 --- a/src/DayTime.hpp +++ b/src/DayTime.hpp @@ -16,6 +16,7 @@ class DayTime DayTime(); DayTime(const DayTime &other); + DayTime& operator=(const DayTime&) = default; DayTime(int h, int m, int s); // From hours diff --git a/src/Declination.hpp b/src/Declination.hpp index 42c0fda5..eaca35a0 100644 --- a/src/Declination.hpp +++ b/src/Declination.hpp @@ -11,6 +11,7 @@ class Declination : public DayTime public: Declination(); Declination(const Declination &other); + Declination& operator=(const Declination&) = default; Declination(int h, int m, int s); Declination(float inDegrees); diff --git a/src/EPROMStore.cpp b/src/EPROMStore.cpp index 5784c177..46b1e6b9 100644 --- a/src/EPROMStore.cpp +++ b/src/EPROMStore.cpp @@ -84,6 +84,41 @@ uint8_t EEPROMStore::read(uint8_t location) return value; } +#elif defined(ARDUINO_ARCH_RP2040) + +// Initialize the flash-backed EEPROM emulation provided by the Philhower +// arduino-pico core. API is identical to the ESP32 path. +void EEPROMStore::initialize() +{ + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Startup with %d bytes", STORE_SIZE); + EEPROM.begin(STORE_SIZE); + + displayContents(); +} + +// Update the given location with the given value +void EEPROMStore::update(uint8_t location, uint8_t value) +{ + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Writing %x to %d", value, location); + EEPROM.write(location, value); +} + +// Complete the transaction (flush RAM cache to flash) +void EEPROMStore::commit() +{ + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Committing"); + EEPROM.commit(); +} + +// Read the value at the given location +uint8_t EEPROMStore::read(uint8_t location) +{ + uint8_t value; + value = EEPROM.read(location); + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Read %x from %d", value, location); + return value; +} + #else // Initialize the EEPROM storage in a platform-independent abstraction @@ -141,8 +176,6 @@ void EEPROMStore::displayContents() LOG(DEBUG_INFO, "[EEPROM]: Stored RA Homing Offset: %l", getRAHomingOffset()); LOG(DEBUG_INFO, "[EEPROM]: Stored AZ Position: %l", getAZPosition()); LOG(DEBUG_INFO, "[EEPROM]: Stored ALT Position: %l", getALTPosition()); - LOG(DEBUG_INFO, "[EEPROM]: Stored AZ Steps per Degree: %f", getAZStepsPerDegree()); - LOG(DEBUG_INFO, "[EEPROM]: Stored ALT Steps per Degree: %f", getALTStepsPerDegree()); LOG(DEBUG_INFO, "[EEPROM]: Stored DEC Homing Offset : %l", getDECHomingOffset()); LOG(DEBUG_INFO, "[EEPROM]: Stored DEC Lower Limit: %l", getDECLowerLimit()); LOG(DEBUG_INFO, "[EEPROM]: Stored DEC Upper Limit: %l", getDECUpperLimit()); @@ -465,100 +498,6 @@ void EEPROMStore::storeDECStepsPerDegree(float decStepsPerDegree) commit(); // Complete the transaction } -// Return the AZ steps per degree (actually microsteps per degree). -// If it is not present then the default uncalibrated AZ_STEPS_PER_DEGREE value is returned. -float EEPROMStore::getAZStepsPerDegree() -{ -#if AZ_STEPPER_TYPE != STEPPER_TYPE_NONE - float azStepsPerDegree(AZIMUTH_STEPS_PER_REV / 360); // Default value -#else - float azStepsPerDegree(1); // Default value -#endif - - if (isPresentExtended(AZ_NORM_STEPS_MARKER_FLAG)) - { -#if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) - // Latest version stores 100x steps/deg for 256 MS - const float factor = SteppingStorageNormalized / AZ_MICROSTEPPING; - azStepsPerDegree = readInt32(AZ_NORM_STEPS_DEGREE_ADDR) / factor; - LOG(DEBUG_EEPROM, "[EEPROM]: AZ Normed Marker Present! AZ steps/deg is %f", azStepsPerDegree); -#else - LOG(DEBUG_EEPROM, "[EEPROM]: AZ marker present but AZ axis disabled; ignoring stored value"); -#endif - } - else - { - LOG(DEBUG_EEPROM, "[EEPROM]: No stored value for AZ steps"); - } - - return azStepsPerDegree; // microsteps per degree -} - -// Store the AZ steps per degree (actually microsteps per degree). -void EEPROMStore::storeAZStepsPerDegree(float azStepsPerDegree) -{ - // Store steps as 100x steps/deg at 256 MS. -#if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) - const float factor = SteppingStorageNormalized / AZ_MICROSTEPPING; - int32_t val = azStepsPerDegree * factor; - LOG(DEBUG_EEPROM, "[EEPROM]: Storing AZ steps to %l (%f)", val, azStepsPerDegree); - - updateInt32(AZ_NORM_STEPS_DEGREE_ADDR, val); - updateFlagsExtended(AZ_NORM_STEPS_MARKER_FLAG); - commit(); // Complete the transaction -#else - LOG(DEBUG_EEPROM, "[EEPROM]: Skipping AZ steps store; AZ axis disabled"); - (void) azStepsPerDegree; -#endif -} - -// Return the ALT steps per degree (actually microsteps per degree). -// If it is not present then the default uncalibrated ALT_STEPS_PER_DEGREE value is returned. -float EEPROMStore::getALTStepsPerDegree() -{ -#if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) - float azStepsPerDegree(ALTITUDE_STEPS_PER_REV / 360); // Default value -#else - float azStepsPerDegree(1); // Default value -#endif - - if (isPresentExtended(ALT_NORM_STEPS_MARKER_FLAG)) - { -#if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) - // Latest version stores 100x steps/deg for 256 MS - const float factor = SteppingStorageNormalized / ALT_MICROSTEPPING; - azStepsPerDegree = readInt32(ALT_NORM_STEPS_DEGREE_ADDR) / factor; - LOG(DEBUG_EEPROM, "[EEPROM]: ALT Normed Marker Present! ALT steps/deg is %f", azStepsPerDegree); -#else - LOG(DEBUG_EEPROM, "[EEPROM]: ALT marker present but ALT axis disabled; ignoring stored value"); -#endif - } - else - { - LOG(DEBUG_EEPROM, "[EEPROM]: No stored value for ALT steps"); - } - - return azStepsPerDegree; // microsteps per degree -} - -// Store the ALT steps per degree (actually microsteps per degree). -void EEPROMStore::storeALTStepsPerDegree(float azStepsPerDegree) -{ - // Store steps as 100x steps/deg at 256 MS. -#if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) - const float factor = SteppingStorageNormalized / ALT_MICROSTEPPING; - int32_t val = azStepsPerDegree * factor; - LOG(DEBUG_EEPROM, "[EEPROM]: Storing ALT steps to %l (%f)", val, azStepsPerDegree); - - updateInt32(ALT_NORM_STEPS_DEGREE_ADDR, val); - updateFlagsExtended(ALT_NORM_STEPS_MARKER_FLAG); - commit(); // Complete the transaction -#else - LOG(DEBUG_EEPROM, "[EEPROM]: Skipping ALT steps store; ALT axis disabled"); - (void) azStepsPerDegree; -#endif -} - int16_t EEPROMStore::getLastFlashedVersion() { if (isPresentExtended(LAST_FLASHED_MARKER_FLAG)) diff --git a/src/EPROMStore.hpp b/src/EPROMStore.hpp index 506e987c..dd943350 100644 --- a/src/EPROMStore.hpp +++ b/src/EPROMStore.hpp @@ -29,12 +29,6 @@ class EEPROMStore static float getDECStepsPerDegree(); static void storeDECStepsPerDegree(float decStepsPerDegree); - static float getAZStepsPerDegree(); - static void storeAZStepsPerDegree(float azStepsPerDegree); - - static float getALTStepsPerDegree(); - static void storeALTStepsPerDegree(float altStepsPerDegree); - static float getSpeedFactor(); static void storeSpeedFactor(float speed); @@ -97,15 +91,13 @@ class EEPROMStore // If Location 5 is 0xCF, then an extended 16-bit flag is stored in 21/22 and // indicates the additional fields that have been stored: 0000 0000 0000 0000 // ^^^^ ^^^^ ^^^^ ^^^^ - // |||| |||| |||| - // ALT Steps/deg, normalized to 256MS (70-73) -------------+||| |||| |||| - // AZ Steps/deg, normalized to 256MS (66-69) --------------+|| |||| |||| + // || |||| |||| // ALT position (62-65) ---------------+| |||| |||| // AZ Position (58-61) ----------------+ |||| |||| // Last flashed version (56-57) ------------------+||| |||| // DEC Homing Offet (52-55) -------------------+|| |||| - // DEC Steps/deg, normalized to 256MS (48-51) --------------------+| |||| - // RA Steps/deg, normalized to 256MS (44-47) ---------------------+ |||| + // DEC Steps/deg, normalized to 256MS (48-51) -------------------+| |||| + // RA Steps/deg, normalized to 256MS (44-47) --------------------+ |||| // RA Homing Offet (40-43) -----------------------+||| // UTC Offset (39) ------------------------+|| // DEC lower (31-34) and upper (35-38) limits -------------------------+| @@ -145,8 +137,6 @@ class EEPROMStore LAST_FLASHED_MARKER_FLAG = 0x0080, AZ_POSITION_MARKER_FLAG = 0x0100, ALT_POSITION_MARKER_FLAG = 0x0200, - AZ_NORM_STEPS_MARKER_FLAG = 0x0400, - ALT_NORM_STEPS_MARKER_FLAG = 0x0800, }; // These are the offsets to each item stored in the EEPROM @@ -219,15 +209,7 @@ class EEPROMStore _ALT_POSITION_ADDR_1, _ALT_POSITION_ADDR_2, _ALT_POSITION_ADDR_3, - AZ_NORM_STEPS_DEGREE_ADDR = 66, - _AZ_NORM_STEPS_DEGREE_ADDR_1, - _AZ_NORM_STEPS_DEGREE_ADDR_2, - _AZ_NORM_STEPS_DEGREE_ADDR_3, // Int32 - ALT_NORM_STEPS_DEGREE_ADDR = 70, - _ALT_NORM_STEPS_DEGREE_ADDR_1, - _ALT_NORM_STEPS_DEGREE_ADDR_2, - _ALT_NORM_STEPS_DEGREE_ADDR_3, // Int32 - STORE_SIZE = 74 + STORE_SIZE = 66 }; // Helper functions diff --git a/src/HallSensorHoming.cpp b/src/HallSensorHoming.cpp index 57a289a9..a53704b4 100644 --- a/src/HallSensorHoming.cpp +++ b/src/HallSensorHoming.cpp @@ -210,7 +210,6 @@ void HallSensorHoming::processHomingProgress() { // First time the pin has triggered, record that position _homingData.position[HOMING_START_PIN_POSITION] = _pMount->getCurrentStepperPosition(_axis); - LOG(DEBUG_STEPPERS, "[HOMING]: Potentially found start of sensor at %l", _homingData.position[HOMING_START_PIN_POSITION]); @@ -231,10 +230,6 @@ void HallSensorHoming::processHomingProgress() // Make sure we continue moving far enough to reach end long distance = _homingData.initialDir * _stepsPerDegree * _homingData.searchDistance; _pMount->moveStepperBy(_axis, distance); - LOG(DEBUG_STEPPERS, - "[HOMING]: Making sure stepper keeps going by another %l steps. New target is %l", - distance, - _pMount->getCurrentStepperPosition(_axis) + distance); _homingData.lastPinState = homingPinState; _homingData.pinChangeCount = 0; @@ -294,10 +289,6 @@ void HallSensorHoming::processHomingProgress() // Make sure we continue moving far enough to reach end long distance = -_homingData.initialDir * _stepsPerDegree * _homingData.searchDistance; _pMount->moveStepperBy(_axis, distance); - LOG(DEBUG_STEPPERS, - "[HOMING]: Making sure stepper keeps going by another %l steps. New target is %l", - distance, - _pMount->getCurrentStepperPosition(_axis) + distance); _homingData.lastPinState = homingPinState; _homingData.pinChangeCount = 0; diff --git a/src/InfoDisplayRender.hpp b/src/InfoDisplayRender.hpp index 3f9569bd..ed8cf2a5 100644 --- a/src/InfoDisplayRender.hpp +++ b/src/InfoDisplayRender.hpp @@ -1,121 +1,17 @@ #pragma once #include -#include "OLEDDisplay.h" -#include "fonts128x64.h" -#include "../Configuration.hpp" + +class Mount; // Base class to implement a class InfoDisplayRender { - const static int MAX_CONSOLE_LINES = 16; // Maximum number of lines of text to buffer in console mode - const static int DISPLAY_CONSOLE_LINES = 6; // Number of lines to display in console mode - - protected: - OLEDDisplay *_display; - long _lastNumCmds; - bool _consoleMode; - String _textList[MAX_CONSOLE_LINES]; - int _curLine; - public: - InfoDisplayRender() - { - _consoleMode = true; - _curLine = 0; - for (int i = 0; i < MAX_CONSOLE_LINES; i++) - { - _textList[i] = ""; - } - }; - - virtual void init() - { - _display->init(); -#if (INFO_DISPLAY_UPSIDE_DOWN == 1) - _display->flipScreenVertically(); -#endif -#if (INFO_DISPLAY_MIRRORED == 1) - _display->mirrorScreen(); -#endif - _display->clear(); - _display->displayOn(); - }; - - OLEDDisplay *getDisplayDevice() - { - return _display; - }; - - virtual void renderScreen(void *context) = 0; - - // Build the display from the mount - virtual void render(void (*drawContentFunction)(void *)) - { - _display->clear(); - if (drawContentFunction) - { - drawContentFunction(this); - } - - if (_consoleMode) - { - // Console lines - int y = 21; - _display->setFont(Bitmap3x5); - // Start 6 lines back from current line and display next 6 lines - int indexStart = max(0, _curLine - DISPLAY_CONSOLE_LINES); - int indexEnd = min(indexStart + DISPLAY_CONSOLE_LINES, MAX_CONSOLE_LINES); - for (int i = indexStart; i < indexEnd; i++) - { - if (_textList[i].length() != 0) - { - String text = _textList[i]; - text.toUpperCase(); - _display->drawString(0, y, text); - } - y += 7; - } - } - else - { - } - - _display->display(); - }; - - virtual void setConsoleMode(bool active) - { - _consoleMode = active; - }; - - virtual int addConsoleText(const String &text, bool tinyFont = true) - { - int returnIndex = 0; - if (_curLine > MAX_CONSOLE_LINES - 1) - { - for (int i = 0; i < MAX_CONSOLE_LINES - 1; i++) - { - _textList[i] = _textList[i + 1]; - } - _curLine = MAX_CONSOLE_LINES - 1; - _textList[_curLine] = text; - returnIndex = _curLine; - } - else - { - returnIndex = _curLine; - _textList[_curLine++] = text; - } - render(nullptr); - return returnIndex; - }; + InfoDisplayRender() {}; - virtual void updateConsoleText(int line, String text) - { - if (line >= 0 && line < MAX_CONSOLE_LINES) - { - _textList[line] = text; - } - render(nullptr); - }; + virtual void init() {}; + virtual void render(Mount *mount) {}; + virtual void setConsoleMode(bool active) {}; + virtual int addConsoleText(String text, bool tinyFont = true); + virtual void updateConsoleText(int line, String newText); }; diff --git a/src/InterruptCallback.cpp b/src/InterruptCallback.cpp index 2a7d5694..54a68df1 100644 --- a/src/InterruptCallback.cpp +++ b/src/InterruptCallback.cpp @@ -20,6 +20,11 @@ PUSH_NO_WARNINGS #include "libs/TimerInterrupt/TimerInterrupt.h" POP_NO_WARNINGS + #elif defined(ARDUINO_ARCH_RP2040) + // Earle Philhower arduino-pico core exposes the Pico SDK alarm API. + // add_repeating_timer_us() fires a hardware alarm callback at a precise + // interval without relying on FreeRTOS or a second core. + #include #else #error Unrecognized board selected. Either implement interrupt code or define the board here. #endif @@ -47,5 +52,47 @@ void InterruptCallback::start() ITimer2.restartTimer(); } + #elif defined(ARDUINO_ARCH_RP2040) + +// Storage for the repeating timer handle and the user callback+payload. +static repeating_timer_t _rp2040_timer; +static interrupt_callback_p _rp2040_callback = nullptr; +static void *_rp2040_payload = nullptr; + +// The Pico SDK alarm callback signature returns bool; returning true keeps +// the timer repeating. +static bool rp2040_timer_isr(repeating_timer_t * /* rt */) +{ + if (_rp2040_callback) + { + _rp2040_callback(_rp2040_payload); + } + return true; // Keep repeating +} + +bool InterruptCallback::setInterval(float intervalMs, interrupt_callback_p callback, void *payload) +{ + _rp2040_callback = callback; + _rp2040_payload = payload; + + // Positive delay_us means the period is measured from callback-start to + // callback-start (fixed wall-clock rate), which is what the stepper + // controller needs for consistent timing. + int32_t intervalUs = static_cast(intervalMs * 1000.0f); + return add_repeating_timer_us(intervalUs, rp2040_timer_isr, nullptr, &_rp2040_timer); +} + +void InterruptCallback::stop() +{ + cancel_repeating_timer(&_rp2040_timer); +} + +void InterruptCallback::start() +{ + // Re-arm with the same interval. The stored callback/payload are still set. + int32_t intervalUs = static_cast(_rp2040_timer.delay_us); + add_repeating_timer_us(intervalUs, rp2040_timer_isr, nullptr, &_rp2040_timer); +} + #endif -#endif \ No newline at end of file +#endif diff --git a/src/Latitude.hpp b/src/Latitude.hpp index 4e47a363..450f02b4 100644 --- a/src/Latitude.hpp +++ b/src/Latitude.hpp @@ -10,6 +10,7 @@ class Latitude : public DayTime { } Latitude(const Latitude &other); + Latitude& operator=(const Latitude&) = default; Latitude(int h, int m, int s); Latitude(float inDegrees); diff --git a/src/Longitude.hpp b/src/Longitude.hpp index 3375a034..083c9c87 100644 --- a/src/Longitude.hpp +++ b/src/Longitude.hpp @@ -10,6 +10,7 @@ class Longitude : public DayTime { } Longitude(const Longitude &other); + Longitude& operator=(const Longitude&) = default; Longitude(int h, int m, int s); Longitude(float inDegrees); diff --git a/src/MeadeCommandProcessor.cpp b/src/MeadeCommandProcessor.cpp index de66f0f3..64630108 100644 --- a/src/MeadeCommandProcessor.cpp +++ b/src/MeadeCommandProcessor.cpp @@ -180,7 +180,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Parameters: // "s" is the sign // "HH" is the number of hours -// Remarks: +// Remarks // Note that this is NOT simply the timezone offset you are in (like -8 for Pacific Standard Time), it is the negative of it. So how many hours need to be added to your local time to get to UTC. // // :Ga# @@ -271,28 +271,25 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Description: // Get Mount Status // Information: -// String reflecting the mounts' status. The string is a comma-delimited list of statuses. +// String reflecting the mounts' status. The string is a comma-delimited list of statuses // Returns: -// "Idle,--T--,11219,0,927,071906,+900000,,#" +// "Idle,--T--,11219,0,927,071906,+900000,#" // Parameters: // [0] The mount status. One of 'Idle', 'Parked', 'Parking', 'Guiding', 'SlewToTarget', 'FreeSlew', 'ManualSlew', 'Tracking', 'Homing' -// [1] The motion state (see Remarks below). +// [1] The motion state. // [2] The RA stepper position // [3] The DEC stepper position // [4] The Tracking stepper position -// [5] The current RA coordinate -// [6] The current DEC coordinate -// [7] The FOC stepper position (if FOC enabled, else empty) +// [5] The current RA position +// [6] The current DEC position // Remarks: -// The motion state consists of 6 characters. If the character is a '-', the corresponding axis is not moving. +// The motion state // First character is RA slewing state ('R' is East, 'r' is West, '-' is stopped). // Second character is DEC slewing state ('d' is North, 'D' is South, '-' is stopped). // Third character is TRK slewing state ('T' is Tracking, '-' is stopped). // Fourth character is AZ slewing state ('Z' and 'z' is adjusting, '-' is stopped). // Fifth character is ALT slewing state ('A' and 'a' is adjusting, '-' is stopped). -// Sixth character is FOC slewing state ('F' and 'f' is adjusting, '-' is stopped). -// AZ, ALT, and FOC are only set if the corresponding axis is enabled. If not, the character is always '-'. -// Since AZ/ALT rarely move, their positions are not returned here. To get the AZ and ALT stepper positions, use the ":XGAA#" command. +// Az and Alt are optional. The string may only be 3 characters long // //------------------------------------------------------------------ // SET FAMILY @@ -427,7 +424,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Description: // Synchronize Declination and Right Ascension. // Information: -// This tells the scope what exact coordinates it is currently pointing at. These coordinates become the new current RA/DEC coordinates of the mount. +// This tells the scope what it is currently pointing at. // Returns: // "1" if successfully set // "0" otherwise @@ -467,7 +464,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Description: // Run a Guide pulse // Information: -// This runs the RA or DEC steppers at an increased or decreased speed (in the case of RA) or a constant speed (in the case of DEC) for a short period of time. It is used for guiding. +// This runs the motors at increased speed for a short period of time. // Parameters: // "d" is one of 'N', 'E', 'W', or 'S' // "nnnn" is the duration in ms @@ -488,8 +485,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Description: // Start slewing // Information: -// This starts slewing the mount in the given direction. You must issue a stop command (such as the corresponding ":Qc#", -// where 'c' is the same direction as passed to this command) or ":Q#" (stops all steppers) to stop it. +// This starts slewing the mount in the given direction. // Parameters: // "c" is one of 'n', 'e', 'w', or 's' // Returns: @@ -499,9 +495,9 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Description: // Move stepper // Information: -// This starts moving one of the steppers by the given amount of steps and returns immediately. Steps can be positive or negative. +// This starts moving one of the steppers by the given amount of steps and returns immediately. // Parameters: -// "x" is the stepper to move (r for RA, d for DEC, f for FOC, z for AZ, l for ALT) +// "x" is the stepper to move (r for RA, d for DEC, f for FOC, z for AZ, t for ALT) // "nnnn" is the number of steps // Returns: // "1" if successfully scheduled, else "0" @@ -513,7 +509,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // This attempts to find the hall sensor and to home the RA ring accordingly. // Parameters: // "x" is either 'R' or 'L' and determines the direction in which the search starts (L is CW, R is CCW). -// "n" (Optional) is the maximum number of degrees to move while searching for the sensor location. Defaults to 30degs. Limited to the range 5degs - 75degs. +// "n" (Optional) is the maximum number of degrees to move while searching for the sensor location. Defaults to 30degs. Limited to the range 15degs - 75degs. // Remarks: // The ring is first moved 30 degrees (or the given amount) in the initial direction. If no hall sensor is encountered, // it will move twice the amount (60 degrees by default) in the opposite direction. @@ -525,7 +521,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // specified direction. // Returns: // "1" if search is started -// "0" if homing has not been enabled in the local configuration file +// "0" if homing has not been enabled in the local config // // :MHDxn# // Description: @@ -534,7 +530,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // This attempts to find the hall sensor and to home the DEC axis accordingly. // Parameters: // "x" is either 'U' or 'D' and determines the direction in which the search starts (U is up, D is down). -// "n" (Optional) is the maximum number of degrees to move while searching for the sensor location. Defaults to 30degs. Limited to the range 5degs - 75degs. +// "n" (Optional) is the maximum number of degrees to move while searching for the sensor location. Defaults to 30degs. Limited to the range 15degs - 75degs. // Remarks: // The ring is first moved 30 degrees (or the given amount) in the initial direction. If no hall sensor is encountered, // it will move twice the amount (60 degrees by default) in the opposite direction. @@ -546,13 +542,13 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // specified direction. // Returns: // "1" if search is started -// "0" if homing has not been enabled in the local configuration file +// "0" if homing has not been enabled in the local config // // :MAAH# // Description: // Move Azimuth and Altitude to home // Information: -// If the scope supports automated azimuth and altitude operations, move AZ and ALT axis to their zero positions. +// If the scope supports automated azimuth and altitutde operations, move AZ and ALT axis to their zero positions. // Returns: // "1" // @@ -626,7 +622,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Information: // This stops all motors, including tracking. Note that deceleration curves are still followed. // Returns: -// nothing +// "1" when all motors have stopped // // :Qd# // Description: @@ -648,7 +644,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // nothing // //------------------------------------------------------------------ -// EXTRA OAT FAMILY - These are used by the PC control application OATControl +// EXTRA OAT FAMILY - These are meant for the PC control app // // :XFR# // Description: @@ -727,7 +723,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Sets the reference pitch value of the mount (Digital Level addon). This is the value // at which the mount is level. // Returns: -// "1#" if successful +// "1#" if succsessful // "0#" if there is no Digital Level // // :XGAA# @@ -805,24 +801,6 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Returns: // "float#" // -// :XGZ# -// Description: -// Get AZ steps -// Information: -// Get the number of steps the AZ stepper motor needs to take to rotate AZ by one degree -// Returns: -// "float#" if AZ motor is present -// "0#" if AZ is not configured -// -// :XGA# -// Description: -// Get ALT steps -// Information: -// Get the number of steps the ALT stepper motor needs to take to rotate ALT by one degree -// Returns: -// "float#" if ALT motor is present -// "0#" if ALT is not configured -// // :XGDLx# // Description: // Get DEC limits @@ -917,12 +895,12 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // "" is a pipe-delimited string of Motor type (NEMA or 28BYJ), Pulley Teeth, Steps per revolution) // "" is either NO_GPS or GPS, depending on whether a GPS module is present // "" is either NO_AZ_ALT, AUTO_AZ_ALT, AUTO_AZ, or AUTO_ALT, depending on which AutoPA stepper motors are present -// "" is either NO_GYRO or GYRO depending on whether the Digital level is present +// "" is either NO_GYRO or GYRO depending on whether the Digial level is present // "" is either NO_LCD or LCD_display_type depending on whether LCD is present and if so, which one // "" is either NO_FOC or FOC depending on whether the focuser motor is enabled // "" is either NO_HSAH or HSAH depending on whether the Hall sensor based auto homing for RA is enabled // "" is either NO_ENDSW or ENDS_RA, ENDSW_DEC, or ENDSW_RA_DEC depending on which axis have end switches installed -// Remarks: +// Remarks // As OAT/OAM firmware supports more features, these may be appended, separated by a comma. Any further features will // have a 'NO_xxxxx' if the feature is not supported. // To differentiate between OAT and OAM, use the Get Product Name (#GVP) command. @@ -974,7 +952,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // This offset is added to the position of the RA ring when it is centered on the hall sensor triggered range after running. // the RA homing command (:MHRx#) // Parameters: -// "n" is the (positive or negative) number of steps that are needed from the center of the Hall sensor trigger range to the actual home position. +// "n" is the number of steps that are needed from the center of the Hall senser trigger range to the actual home position. // Returns: // nothing // @@ -985,7 +963,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // This offset is added to the position of the DEC ring when it is centered on the hall sensor triggered range after running. // the DEC homing command (:MHDx#) // Parameters: -// "n" is the (positive or negative) number of steps that are needed from the center of the Hall sensor trigger range to the actual home position. +// "n" is the number of steps that are needed from the center of the Hall senser trigger range to the actual home position. // Returns: // nothing // @@ -995,7 +973,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Information: // Set the number of steps the RA stepper motor needs to take to rotate by one degree. // Parameters: -// "n.n" is the number of steps (only one decimal point is supported, must be positive) +// "n.n" is the number of steps (only one decimal point is supported) // Returns: // nothing // @@ -1005,27 +983,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Information: // Set the number of steps the DEC stepper motor needs to take to rotate by one degree. // Parameters: -// "n.n" is the number of steps (only one decimal point is supported, must be positive) -// Returns: -// nothing -// -// :XSAn.n# -// Description: -// Set AZ steps -// Information: -// Set the number of steps the AZ stepper motor needs to take to rotate by one degree. -// Parameters: -// "n.n" is the number of steps (only one decimal point is supported, must be positive) -// Returns: -// nothing -// -// :XSLn.n# -// Description: -// Set ALT steps -// Information: -// Set the number of steps the ALT stepper motor needs to take to rotate by one degree. -// Parameters: -// "n.n" is the number of steps (only one decimal point is supported, must be positive) +// "n.n" is the number of steps (only one decimal point is supported) // Returns: // nothing // @@ -1037,7 +995,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // otherwise to the given angle (in degrees from the home position). // Parameters: // "nnnnn" is the number of steps from home that the DEC ring can travel upwards. Passing 0 will reset it to the -// limits defined in your configuration file. Omitting this parameter sets it to the current DEC position. +// limits defined in your config file. Omitting this parameter sets it to the current DEC position. // Returns: // nothing // @@ -1046,7 +1004,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Clear DEC upper limit // Information: // Resets the upper limit for the DEC axis to the configuration-defined position. -// If not configured, the limit is cleared. +// If unconfigured, the limit is cleared. // Returns: // nothing // @@ -1058,7 +1016,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // otherwise to the given angle (in degrees from the home position). // Parameters: // "nnnnn" is the number of steps from home that the DEC ring can travel downwards. Passing 0 will reset it to the -// limits defined in your configuration file. Omitting this parameter sets it to the current DEC position. +// limits defined in your config file. Omitting this parameter sets it to the current DEC position. // Returns: // nothing // @@ -1067,7 +1025,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Clear DEC lower limit // Information: // Resets the lower limit for the DEC axis to the configuration-defined position. -// If not configured, the limit is cleared. +// If unconfigured, the limit is cleared. // Returns: // nothing // @@ -1076,8 +1034,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Set DEC parking position offset // Information: // This stores the number of steps needed to move from home to the parking position. -// Returns: -// nothing +// Returns: nothing // // :XSSn.nnn# // Description: @@ -1152,7 +1109,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Description: // Set speed factor // Information: -// Set focuser speed to where is an ASCII digit 1..4. 1 is slowest, 4 is fastest +// Set focuser speed to where is an ASCII digit 1..4. 1 is slowest, 4 i fastest // Returns: // nothing // @@ -1180,6 +1137,7 @@ bool gpsAqcuisitionComplete(int &indicator); // defined in c72_menuHA_GPS.hpp // Returns: // "nnn#" "nnn" is the current position of the stepper // +// // :FPnnn# // Description: // Set position @@ -1273,8 +1231,6 @@ String MeadeCommandProcessor::handleMeadeGetInfo(String inCmd) { #ifdef OAM return "OpenAstroMount#"; -#elif defined(OAE) - return "OpenAstroExplorer#"; #else return "OpenAstroTracker#"; #endif @@ -1561,7 +1517,6 @@ String MeadeCommandProcessor::handleMeadeSetInfo(String inCmd) ///////////////////////////// String MeadeCommandProcessor::handleMeadeMovement(String inCmd) { - LOG(DEBUG_MEADE, "[MEADE]: Process Move command: [%s]", inCmd.c_str()); if (inCmd[0] == 'S') // :MS# { _mount->startSlewingToTarget(); @@ -1858,14 +1813,6 @@ String MeadeCommandProcessor::handleMeadeExtraCommands(String inCmd) { return String(_mount->getBacklashCorrection()) + "#"; } - else if ((inCmd[1] == 'A') && (inCmd.length() == 2)) // :XGA# - { - return String(_mount->getStepsPerDegree(ALTITUDE_STEPS), 1) + "#"; - } - else if ((inCmd[1] == 'Z') && (inCmd.length() == 2)) // :XGZ# - { - return String(_mount->getStepsPerDegree(AZIMUTH_STEPS), 1) + "#"; - } else if ((inCmd[1] == 'A') && (inCmd.length() > 2) && (inCmd[2] == 'H')) // :XGAH# { return _mount->getAutoHomingStates() + "#"; @@ -1959,14 +1906,6 @@ String MeadeCommandProcessor::handleMeadeExtraCommands(String inCmd) { _mount->setStepsPerDegree(RA_STEPS, inCmd.substring(2).toFloat()); } - else if (inCmd[1] == 'A') // :XSA# - { - _mount->setStepsPerDegree(AZIMUTH_STEPS, inCmd.substring(2).toFloat()); - } - else if (inCmd[1] == 'L') // :XSL# - { - _mount->setStepsPerDegree(ALTITUDE_STEPS, inCmd.substring(2).toFloat()); - } else if (inCmd[1] == 'D') // :XSD { if ((inCmd.length() > 2) && (inCmd[2] == 'L')) // :XSDL @@ -2125,10 +2064,7 @@ String MeadeCommandProcessor::handleMeadeQuit(String inCmd) if (inCmd.length() == 0) { _mount->stopSlewing(ALL_DIRECTIONS | TRACKING); - _mount->stopSlewing(AZIMUTH_STEPS); - _mount->stopSlewing(ALTITUDE_STEPS); - _mount->stopSlewing(FOCUS_STEPS); - _mount->waitUntilAllStopped(); + _mount->waitUntilStopped(ALL_DIRECTIONS); return ""; } @@ -2263,7 +2199,7 @@ String MeadeCommandProcessor::processCommand(String inCmd) { if (inCmd[0] == ':') { - LOG(DEBUG_MEADE, "[MEADE]: Received command '%s'", inCmd.c_str()); + LOG(DEBUG_MEADE, "[MEADE]: Received command '%s'", inCmd.c_str()); // Apparently some LX200 implementations put spaces in their commands..... remove them with impunity. int spacePos; diff --git a/src/Mount.cpp b/src/Mount.cpp index e41eb05a..a4f0fd14 100644 --- a/src/Mount.cpp +++ b/src/Mount.cpp @@ -194,15 +194,6 @@ void Mount::readPersistentData() _stepsPerDECDegree = EEPROMStore::getDECStepsPerDegree(); LOG(DEBUG_INFO, "[MOUNT]: EEPROM: DEC steps/deg is %f", _stepsPerDECDegree); -#if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) - _stepsPerAZDegree = EEPROMStore::getAZStepsPerDegree(); - LOG(DEBUG_INFO, "[MOUNT]: EEPROM: AZ steps/deg is %f", _stepsPerAZDegree); -#endif - -#if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) - _stepsPerALTDegree = EEPROMStore::getALTStepsPerDegree(); - LOG(DEBUG_INFO, "[MOUNT]: EEPROM: ALT steps/deg is %f", _stepsPerALTDegree); -#endif float speed = EEPROMStore::getSpeedFactor(); LOG(DEBUG_INFO, "[MOUNT]: EEPROM: Speed factor is %f", speed); setSpeedCalibration(speed, false); @@ -498,7 +489,7 @@ void Mount::configureRAdriver(Stream *serial, float rsense, byte driveraddress, _driverRA->rms_current(rmscurrent, 1.0f); //holdMultiplier = 1 to set ihold = irun _driverRA->pdn_disable(1); _driverRA->ihold(31); - _driverRA->toff(1); + _driverRA->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverRA->en_spreadCycle(RA_UART_STEALTH_MODE == 0); _driverRA->blank_time(24); _driverRA->microsteps(RA_TRACKING_MICROSTEPPING == 1 ? 0 : RA_TRACKING_MICROSTEPPING); // System starts in tracking mode @@ -537,7 +528,7 @@ void Mount::configureRAdriver(uint16_t RA_SW_RX, uint16_t RA_SW_TX, float rsense #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested RA motor rms_current: %d mA", rmscurrent); _driverRA->rms_current(rmscurrent, 1.0f); //holdMultiplier = 1 to set ihold = irun - _driverRA->toff(1); + _driverRA->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverRA->en_spreadCycle(RA_UART_STEALTH_MODE == 0); _driverRA->blank_time(24); _driverRA->semin(0); //disable CoolStep so that current is consistent @@ -585,7 +576,7 @@ void Mount::configureDECdriver(Stream *serial, float rsense, byte driveraddress, _driverDEC->ihold(31); _driverDEC->iholddelay(15); _driverDEC->TPOWERDOWN(255); - _driverDEC->toff(1); + _driverDEC->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverDEC->en_spreadCycle(DEC_UART_STEALTH_MODE == 0); _driverDEC->blank_time(24); _driverDEC->microsteps( @@ -624,7 +615,7 @@ void Mount::configureDECdriver(uint16_t DEC_SW_RX, uint16_t DEC_SW_TX, float rse #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested DEC motor rms_current: %d mA", rmscurrent); _driverDEC->rms_current(rmscurrent, 1.0f); //holdMultiplier = 1 to set ihold = irun - _driverDEC->toff(1); + _driverDEC->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverDEC->en_spreadCycle(DEC_UART_STEALTH_MODE == 0); _driverDEC->blank_time(24); _driverDEC->microsteps( @@ -668,7 +659,7 @@ void Mount::configureAZdriver(Stream *serial, float rsense, byte driveraddress, #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested AZ motor rms_current: %d mA", rmscurrent); _driverAZ->rms_current(rmscurrent, AZ_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun - _driverAZ->toff(1); + _driverAZ->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverAZ->en_spreadCycle(0); _driverAZ->blank_time(24); _driverAZ->microsteps(AZ_MICROSTEPPING == 1 ? 0 : AZ_MICROSTEPPING); // If 1 then disable microstepping @@ -706,7 +697,7 @@ void Mount::configureAZdriver(uint16_t AZ_SW_RX, uint16_t AZ_SW_TX, float rsense #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested AZ motor rms_current: %d mA", rmscurrent); _driverAZ->rms_current(rmscurrent, AZ_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun - _driverAZ->toff(1); + _driverAZ->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverAZ->en_spreadCycle(0); _driverAZ->blank_time(24); _driverAZ->microsteps(AZ_MICROSTEPPING == 1 ? 0 : AZ_MICROSTEPPING); // If 1 then disable microstepping @@ -749,7 +740,7 @@ void Mount::configureALTdriver(Stream *serial, float rsense, byte driveraddress, #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested ALT motor rms_current: %d mA", rmscurrent); _driverALT->rms_current(rmscurrent, ALT_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun - _driverALT->toff(1); + _driverALT->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverALT->en_spreadCycle(0); _driverALT->blank_time(24); _driverALT->microsteps(ALT_MICROSTEPPING == 1 ? 0 : ALT_MICROSTEPPING); // If 1 then disable microstepping @@ -787,7 +778,7 @@ void Mount::configureALTdriver(uint16_t ALT_SW_RX, uint16_t ALT_SW_TX, float rse #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested ALT motor rms_current: %d mA", rmscurrent); _driverALT->rms_current(rmscurrent, ALT_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun - _driverALT->toff(1); + _driverALT->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverALT->en_spreadCycle(0); _driverALT->blank_time(24); _driverALT->microsteps(ALT_MICROSTEPPING == 1 ? 0 : ALT_MICROSTEPPING); // If 1 then disable microstepping @@ -832,7 +823,7 @@ void Mount::configureFocusDriver(Stream *serial, float rsense, byte driveraddres #endif LOG(DEBUG_STEPPERS | DEBUG_FOCUS, "[FOCUS]: Requested Focus motor rms_current: %d mA", rmscurrent); _driverFocus->rms_current(rmscurrent, FOCUSER_MOTOR_HOLD_SETTING / 100.f); //holdMultiplier = 1 to set ihold = irun - _driverFocus->toff(1); + _driverFocus->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverFocus->en_spreadCycle(FOCUS_UART_STEALTH_MODE == 0); _driverFocus->blank_time(24); _driverFocus->microsteps(FOCUS_MICROSTEPPING == 1 ? 0 : FOCUS_MICROSTEPPING); // If 1 then disable microstepping @@ -878,7 +869,7 @@ void Mount::configureFocusDriver( #endif LOG(DEBUG_STEPPERS | DEBUG_FOCUS, "[FOCUS]: Requested Focus motor rms_current: %d mA", rmscurrent); _driverFocus->rms_current(rmscurrent, FOCUSER_MOTOR_HOLD_SETTING / 100.f); //holdMultiplier = 1 to set ihold = irun - _driverFocus->toff(1); + _driverFocus->toff(4); // toff>=3 required for StealthChop slow-decay phase _driverFocus->en_spreadCycle(FOCUS_UART_STEALTH_MODE == 0); _driverFocus->blank_time(24); _driverFocus->microsteps(FOCUS_MICROSTEPPING == 1 ? 0 : FOCUS_MICROSTEPPING); // If 1 then disable microstepping @@ -1048,14 +1039,12 @@ void Mount::setStepsPerDegree(StepperAxis which, float steps) else if (which == AZIMUTH_STEPS) { _stepsPerAZDegree = steps; - EEPROMStore::storeAZStepsPerDegree(_stepsPerAZDegree); } #endif #if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) else if (which == ALTITUDE_STEPS) { _stepsPerALTDegree = steps; - EEPROMStore::storeALTStepsPerDegree(_stepsPerALTDegree); } #endif } diff --git a/src/Mount.hpp b/src/Mount.hpp index 7cf00a73..a6cdc2c5 100644 --- a/src/Mount.hpp +++ b/src/Mount.hpp @@ -36,21 +36,21 @@ using StepperFocusSlew = InterruptAccelStepper; #else #include "AccelStepper.h" class AccelStepper; -using StepperRaSlew = AccelStepper; -using StepperRaTrk = AccelStepper; -using StepperDecSlew = AccelStepper; -using StepperDecTrk = AccelStepper; +using StepperRaSlew = AccelStepper; +using StepperRaTrk = AccelStepper; +using StepperDecSlew = AccelStepper; +using StepperDecTrk = AccelStepper; #if AZ_STEPPER_TYPE != STEPPER_TYPE_NONE -using StepperAzSlew = AccelStepper; +using StepperAzSlew = AccelStepper; #endif #if ALT_STEPPER_TYPE != STEPPER_TYPE_NONE -using StepperAltSlew = AccelStepper; +using StepperAltSlew = AccelStepper; #endif #if ALT_STEPPER_TYPE != STEPPER_TYPE_NONE -using StepperAltSlew = AccelStepper; +using StepperAltSlew = AccelStepper; #endif #if FOCUS_STEPPER_TYPE != STEPPER_TYPE_NONE @@ -61,21 +61,21 @@ using StepperFocusSlew = AccelStepper; #else #include "AccelStepper.h" class AccelStepper; -using StepperRaSlew = AccelStepper; -using StepperRaTrk = AccelStepper; -using StepperDecSlew = AccelStepper; -using StepperDecTrk = AccelStepper; +using StepperRaSlew = AccelStepper; +using StepperRaTrk = AccelStepper; +using StepperDecSlew = AccelStepper; +using StepperDecTrk = AccelStepper; #if AZ_STEPPER_TYPE != STEPPER_TYPE_NONE -using StepperAzSlew = AccelStepper; +using StepperAzSlew = AccelStepper; #endif #if ALT_STEPPER_TYPE != STEPPER_TYPE_NONE -using StepperAltSlew = AccelStepper; +using StepperAltSlew = AccelStepper; #endif #if ALT_STEPPER_TYPE != STEPPER_TYPE_NONE -using StepperAltSlew = AccelStepper; +using StepperAltSlew = AccelStepper; #endif #if FOCUS_STEPPER_TYPE != STEPPER_TYPE_NONE @@ -264,6 +264,9 @@ class Mount void setSlewRate(int rate); int getSlewRate(); + // Get the number of hours we've been tracking + float getTrackedHours() const; + // Set the HA time (HA is derived from LST, the setter calculates and sets LST) void setHA(const DayTime &haTime); const DayTime HA() const; @@ -391,6 +394,7 @@ class Mount // Returns a comma-delimited string with all the mounts' information String getStatusString(); + void setStatus(int state); void setStatusFlag(int flag); void clearStatusFlag(int flag); diff --git a/src/SSD1306_128x64_Display.cpp b/src/SSD1306_128x64_Display.cpp deleted file mode 100644 index bae3c33b..00000000 --- a/src/SSD1306_128x64_Display.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include "SSD1306_128x64_Display.hpp" - -#if defined(ESP32) - /* - * ESP32 PROGMEM is fake, and its pgm_read_byte macro makes a useless cast - * which errors out with Werror=useless-cast, which can't be suppressed by - * our PUSH/POP_NO_WARNINGS because the macro expands in OUR code, not their - * header :/ - */ - #undef pgm_read_byte - #define pgm_read_byte(addr) (*(addr)) -#endif - -Mount *SDD1306OLED128x64::_mount = nullptr; - -float sinLookup(float deg) -{ - while (deg < 0.0f) - deg += 360.0f; - while (deg > 360.0f) - deg -= 360.0f; - - if (deg <= 90) - { - int index = (int) roundf(sineSize * deg / 90.0f); - return 1.0f * pgm_read_byte(sineTable + index) / 255.0; - } - else if (deg <= 180) - { - int index = (int) roundf(sineSize * (180.0f - deg) / 90.0f); - return 1.0f * pgm_read_byte(sineTable + index) / 255.0; - } - else if (deg <= 270) - { - int index = (int) roundf(sineSize * (deg - 180.0f) / 90.0f); - return -1.0f * pgm_read_byte(sineTable + index) / 255.0; - } - else if (deg <= 360) - { - int index = (int) roundf(sineSize * (360.0f - deg) / 90.0f); - return -1.0f * pgm_read_byte(sineTable + index) / 255.0; - } - return 0.0f; -} - -SDD1306OLED128x64::SDD1306OLED128x64(uint8_t addr, int sda, int scl) : InfoDisplayRender() -{ - _display = new SSD1306Wire(addr, sda, scl, GEOMETRY_128_64); - _commLetter = ' '; -} - -void SDD1306OLED128x64::renderCallback(void *context) -{ - SDD1306OLED128x64 *display = static_cast(context); - display->drawScreen(); -} - -void SDD1306OLED128x64::drawScreen() -{ - _display->setColor(WHITE); - if (_consoleMode) - { - // Draw header only in console mode, in the area 0,0 to 127,20 - // Logo on the left. Base class renders console output text. - _display->setFont(OATLogo); - _display->drawString(0, 0, "!"); - - // Name on the right - _display->setFont(Bitmap5x7); -#ifdef OAE - _display->drawString(32, 6, F("OpenAstroExplorer")); -#elif defined(OAM) - _display->drawString(32, 6, F("OpenAstroMount")); -#else - _display->drawString(32, 6, F("OpenAstroTracker")); -#endif - } - else - { - // Draw indicators in all other modes - drawIndicators(SDD1306OLED128x64::_mount); - } -} - -// Build the display from the mount -void SDD1306OLED128x64::renderScreen(void *mount) -{ - _mount = (Mount *) mount; - // Call the base - this->InfoDisplayRender::render(renderCallback); -}; - -// Display the tiem left before tracking hits the limit -void SDD1306OLED128x64::drawTime(Mount *mount, String label, const DayTime &time) -{ - char achTemp[24]; - _display->setColor(WHITE); - _display->setFont(Bitmap3x5); - sprintf(achTemp, "%s%02d:%02d", label.c_str(), time.getHours(), time.getMinutes()); - _display->drawString(55, 59, achTemp); -} - -// Draw all the indicators on screen -void SDD1306OLED128x64::drawIndicators(Mount *mount) -{ - char scratchBuffer[24]; - _display->setFont(Bitmap5x7); - _display->setColor(WHITE); - - drawStepperStates(mount); - int ra, dec; - // If a slew is in progress, we don't display the safe time, version, and - // comms indicator, since the progress bar takes up the same space - if (mount->getStepperProgress(ra, dec)) - { - drawProgressBar(ra, dec); - } - else - { - long timeSecs = millis() / 2000; // Change every 2 secs - int index = timeSecs % 5; // Cycle through multiple data displays - - _display->setFont(CommSymbols); - _display->drawString(11, 59, F("L")); // Memory chip icon - _display->setFont(Bitmap3x5); - long availMem = freeMemory(); - if (availMem > 9999) - { - _display->drawString(20, 59, String(availMem / 1024) + "K"); - } - else - { - _display->drawString(20, 59, String(availMem)); - } - - switch (index) - { - case 0: - { - float hoursLeft = mount->checkRALimit(); - DayTime dt(hoursLeft); - drawTime(mount, F("REM "), dt); - } - break; - case 1: - { - drawTime(mount, F("LST "), mount->calculateLst()); - } - break; - case 2: - { - long now = millis(); - long msPerDay = 60L * 60 * 24 * 1000; - int days = (int) (now / msPerDay); - now -= days * msPerDay; - DayTime elapsed(1.0 * now / (1000.0 * 3600.0)); - drawTime(mount, F("UPT "), elapsed); - } - break; - case 3: - { - _display->drawString(55, 59, (String(F(" FW ")) + String(VERSION)).c_str()); - } - break; - case 4: - { - float lat = fabsf(mount->latitude().getTotalHours()); - float lng = fabsf(mount->longitude().getTotalHours()); - const char dirLat = (mount->latitude().getTotalHours() < 0) ? 'S' : 'N'; - const char dirLong = (mount->longitude().getTotalHours() < 0) ? 'W' : 'E'; - sprintf(scratchBuffer, "LOC %s%c %s%c", String(lat, 0).c_str(), dirLat, String(lng, 0).c_str(), dirLong); - _display->drawString(55, 59, scratchBuffer); - } - break; - } - drawCommunicationStatus(mount); - } - drawCoordinates(mount); - drawMountPosition(mount); - drawStatus(mount); -} - -// Display two 2-pixel high progress bar in the last 4 lines of the display -void SDD1306OLED128x64::drawProgressBar(int percRA, int percDEC) -{ - _display->setColor(WHITE); - _display->drawVerticalLine(127, 60, 4); - int raWidth = round(1.28f * percRA); - _display->fillRect(0, 60, raWidth, 2); - int decWidth = round(1.28f * percDEC); - _display->fillRect(0, 62, decWidth, 2); -} - -// Display a rectangle with the stepper label in it -void SDD1306OLED128x64::drawStepperState(String name, bool active, int xoff, int width, int textOffX) -{ - _display->setColor(WHITE); - if (active) - { - _display->fillRect(xoff, 0, width, 11); - } - else - { - _display->drawRect(xoff, 0, width, 11); - } - _display->setColor(INVERSE); - _display->drawString(xoff + 2 + textOffX, 2, name); -} - -// Display all the configured stepper status rectangles -// Focuser is currently not supported, but could be added here, if possible. -void SDD1306OLED128x64::drawStepperStates(Mount *mount) -{ - _display->setFont(Bitmap5x7); - drawStepperState(F("RA"), mount->isAxisRunning(RA_STEPS), 0, 15); - drawStepperState(F("DEC"), mount->isAxisRunning(DEC_STEPS), 16, 21); -#if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) - drawStepperState(F("ALT"), mount->isRunningALT(), 38, 21); -#endif -#if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) - drawStepperState(F("AZ"), mount->isRunningAZ(), 60, 16); -#endif - drawStepperState(F("GDE"), mount->isGuiding(), 83, 21); - drawStepperState(F("TRK"), mount->isSlewingTRK(), 105, 23, 1); -} - -void SDD1306OLED128x64::drawCommunicationStatus(Mount *mount) -{ - long recvdCmds = mount->getNumCommandsReceived(); - // If we have received any commands since the last display, draw the marker. - - if (_commLetter != ' ') - { - _display->setFont(CommSymbols); - _display->drawString(1, 59, String(_commLetter)); - _commLetter++; - if (_commLetter == 'G') // Past last communication animation frame (F) - { - _commLetter = ' '; - } - } - else if (recvdCmds != _lastNumCmds) - { - _commLetter = 'C'; // First communication animation frame - _lastNumCmds = recvdCmds; - } -} - -// Draw the given coordinate string at the given point -void SDD1306OLED128x64::drawCoordinate(int x, int y, const char *coord) -{ - char achCoord[30]; - char *n = achCoord; - // Since this is not a full font, remap the supported letters to the right character - for (const char *p = coord; *p != 0; p++) - { - switch (*p) - { - case 'R': - *n = '!'; - break; - case 'A': - *n = '&'; - break; - case 'D': - *n = '#'; - break; - case 'E': - *n = '$'; - break; - case 'C': - *n = '%'; - break; - case 'h': - *n = '<'; - break; - case 'm': - *n = ';'; - break; - case 's': - *n = '='; - break; - case '@': - *n = '('; - break; - default: - *n = *p; - break; - } - n++; - } - *n = 0; - _display->setFont(Bitmap7x15); - _display->setColor(WHITE); - _display->drawString(x, y, achCoord); -} - -// Draw the mounts celestial RA and DEC coordinates -void SDD1306OLED128x64::drawCoordinates(Mount *mount) -{ - String rc = mount->RAString(LCD_STRING | CURRENT_STRING); - String dc = mount->DECString(LCD_STRING | CURRENT_STRING); - drawCoordinate(8, 24, rc.c_str()); - drawCoordinate(0, 42, dc.c_str()); -} - -// Map the given RA coordinate to the pixel position on the display -int SDD1306OLED128x64::xRAPixel(float ra) -{ - float rangeRA = rightRA - leftRA; - int x = 4 + (int) round(1.0f * (_raSize - 9) * ((ra - leftRA) / rangeRA)); - return (_leftEdgeMount + x); -} - -// Map the given DEC coordinate to the pixel position on the display -int SDD1306OLED128x64::yDECPixel(float dec) -{ - int y = (int) round(1.0f * (_decSize) * ((dec - bottomDEC) / rangeDEC)); - return (_topEdgeMount + _decSize - y); -} - -// Draw the rectangle with the current and target positions -void SDD1306OLED128x64::drawMountPosition(Mount *mount) -{ - _display->setColor(WHITE); - _display->setFont(Bitmap3x5); - - // DEC tickmarks - for (int p = _topEdgeMount; p <= _topEdgeMount + _decSize; p += 2) - { - _display->setPixel(_decScalePos, p); - } -#if defined(OAM) || defined(OAE) - _display->drawHorizontalLine(_decScalePos - 1, yDECPixel(-180.0), 2); -#endif - _display->drawHorizontalLine(_decScalePos - 1, yDECPixel(-90.0), 2); - _display->drawHorizontalLine(_decScalePos - 1, yDECPixel(0.0), 2); - _display->drawHorizontalLine(_decScalePos - 1, yDECPixel(90.0), 2); - _display->drawHorizontalLine(_decScalePos - 1, yDECPixel(180.0), 2); -// DEC tickmark labels -#if defined(OAM) || defined(OAE) - _display->drawString(_decScalePos + 6, yDECPixel(-180.0f) - 2, F("180")); - _display->drawHorizontalLine(_decScalePos + 3, yDECPixel(-180.0), 2); // Smaller minus sign -#endif - _display->drawString(_decScalePos + 6, yDECPixel(-90.0f) - 2, F("90")); - _display->drawHorizontalLine(_decScalePos + 3, yDECPixel(-90.0), 2); // Smaller minus sign - _display->drawString(_decScalePos + 3, yDECPixel(0.0f) - 2, "0"); - _display->drawString(_decScalePos + 3, yDECPixel(90.0f) - 2, F("90")); - _display->drawString(_decScalePos + 3, yDECPixel(180.0f) - 2, F("180")); - - // DEC Pos Marker - float decStepsPerDeg = mount->getStepsPerDegree(StepperAxis::DEC_STEPS); - long decSteps = mount->getCurrentStepperPosition(StepperAxis::DEC_STEPS); - float decDegrees = decSteps / decStepsPerDeg; - int yMark = yDECPixel(decDegrees); - _display->setPixel(_decScalePos - 2, yMark); - _display->drawVerticalLine(_decScalePos - 3, yMark - 1, 3); - _display->drawVerticalLine(_decScalePos - 4, yMark - 2, 5); - - // RA tickmarks - for (int p = _leftEdgeMount; p <= _leftEdgeMount + _raSize; p += 2) - { - _display->setPixel(p, _raScalePos); - } - _display->drawVerticalLine(xRAPixel(-6.0f), _raScalePos - 1, 2); - _display->drawVerticalLine(xRAPixel(-3.0f), _raScalePos - 1, 2); - _display->drawVerticalLine(xRAPixel(0.0f), _raScalePos - 1, 2); - _display->drawVerticalLine(xRAPixel(3.0f), _raScalePos - 1, 2); - _display->drawVerticalLine(xRAPixel(6.0f), _raScalePos - 1, 2); - - // RA tickmark labels - _display->drawString(xRAPixel(-6.0f) - 1, _raScalePos + 2, "6"); - _display->drawHorizontalLine(xRAPixel(-6.0f) - 4, _raScalePos + 2 + 2, 2); // Smaller minus sign - _display->drawString(xRAPixel(-3.0f) - 1, _raScalePos + 2, "3"); - _display->drawHorizontalLine(xRAPixel(-3.0f) - 4, _raScalePos + 2 + 2, 2); // Smaller minus sign - _display->drawString(xRAPixel(0.0f) - 1, _raScalePos + 2, "0"); - _display->drawString(xRAPixel(3.0f) - 1, _raScalePos + 2, "3"); - _display->drawString(xRAPixel(6.0f) - 1, _raScalePos + 2, "6"); - - float raStepsPerDeg = mount->getStepsPerDegree(StepperAxis::RA_STEPS); - float trkSteps = 1.0f * mount->getCurrentStepperPosition(TRACKING) / (1.0f * RA_TRACKING_MICROSTEPPING / RA_SLEW_MICROSTEPPING); - long raSteps = mount->getCurrentStepperPosition(StepperAxis::RA_STEPS); - float raHours = (trkSteps + raSteps) / raStepsPerDeg / 15.0f; - - // RA Position Marker - int xMark = xRAPixel(raHours); - _display->setPixel(xMark, _raScalePos - 2); - _display->drawHorizontalLine(xMark - 1, _raScalePos - 3, 3); - _display->drawHorizontalLine(xMark - 2, _raScalePos - 4, 5); -} - -// Display the tiem left before tracking hits the limit -void SDD1306OLED128x64::drawSafeTime(Mount *mount) -{ - char achTemp[10]; - float hoursLeft = mount->checkRALimit(); - DayTime dt(hoursLeft); - _display->setColor(WHITE); - _display->setFont(CommSymbols); - _display->drawString(48, 59, "M"); // Clock sign - _display->setFont(Bitmap3x5); - sprintf(achTemp, "%02d:%02d", dt.getHours(), dt.getMinutes()); - _display->drawString(55, 59, achTemp); -} - -// Display the mount status string -void SDD1306OLED128x64::drawStatus(Mount *mount) -{ - _display->setColor(WHITE); - _display->setFont(Bitmap5x7); - String state = mount->getStatusStateString(); - state.toUpperCase(); - _display->drawString(4, 14, state.c_str()); - - // Bouncing pixel (bounce frequency every 1.5s). 180 degrees is one cap. - float deg = 180.0f * (millis() % 1500) / 1500.0f; - int pixPos = (int) round(1.0f * yMaxStatus * sinLookup(deg)); - _display->setPixel(0, 11 + yMaxStatus - pixPos); -} diff --git a/src/SSD1306_128x64_Display.hpp b/src/SSD1306_128x64_Display.hpp index 32f14633..f3e04ed4 100644 --- a/src/SSD1306_128x64_Display.hpp +++ b/src/SSD1306_128x64_Display.hpp @@ -1,33 +1,18 @@ #pragma once -#include #include "SSD1306Wire.h" -#include "Configuration.hpp" #include "Utility.hpp" #include "Version.h" #include "fonts128x64.h" #include "Mount.hpp" #include "InfoDisplayRender.hpp" -#if defined(ESP32) - /* - * ESP32 PROGMEM is fake, and its pgm_read_byte macro makes a useless cast - * which errors out with Werror=useless-cast, which can't be suppressed by - * our PUSH/POP_NO_WARNINGS because the macro expands in OUR code, not their - * header :/ - */ - #undef pgm_read_byte - #define pgm_read_byte(addr) (*(addr)) -#endif - const float sineSize = 18.0; const uint8_t sineTable[] PROGMEM = {0, 22, 44, 66, 87, 108, 128, 146, 164, 180, 195, 209, 221, 231, 240, 246, 251, 254, 255, 255}; -class Mount; - // This class renders the mount status to a 128x64 pixel display controlled by a SSD1306 chip. class SDD1306OLED128x64 : public InfoDisplayRender { -#if defined(OAM) || defined(OAE) +#ifdef OAM const float bottomDEC = -180.0f; const float rangeDEC = 360.0; #else @@ -47,52 +32,453 @@ class SDD1306OLED128x64 : public InfoDisplayRender const int yMaxStatus = 63 - 11; + SSD1306Wire *display; + int _sizeMount; + int _yStatus; + int _dirStatus; char _commLetter; - static Mount *_mount; + long _lastNumCmds; + long _lastUpdate; + bool _consoleMode; + String _textList[6]; // At most 6 lines of text in console mode + int _curLine; public: - SDD1306OLED128x64(uint8_t addr, int sda, int scl); - void static renderCallback(void *context); - void drawScreen(); + SDD1306OLED128x64(byte addr, int sda, int scl) : InfoDisplayRender() + { + display = new SSD1306Wire(addr, sda, scl, GEOMETRY_128_64); + _sizeMount = 128 - _leftEdgeMount; + _consoleMode = true; + _curLine = 0; + _yStatus = 0; + _dirStatus = 1; + _commLetter = ' '; + for (int i = 0; i < 6; i++) + { + _textList[i] = ""; + } + } + + // Initialize the display + virtual void init() + { + display->init(); + display->clear(); + display->displayOn(); + }; // Build the display from the mount - void renderScreen(void *mount); + virtual void render(Mount *mount) + { + display->clear(); + if (_consoleMode) + { + display->setColor(WHITE); + + // Logo on the left + display->setFont(OATLogo); + display->drawString(0, 0, "!"); + + // Name on the right + display->setFont(Bitmap5x7); +#ifdef OAM + display->drawString(32, 6, F("OpenAstroMount")); +#else + display->drawString(32, 6, F("OpenAstroTracker")); +#endif + + // Other lines + int y = 21; + display->setFont(Bitmap3x5); + for (int i = 0; i < 6; i++) + { + if (_textList[i].length() != 0) + { + display->drawString(0, y, _textList[i]); + } + y += 7; + } + } + else + { + drawIndicators(mount); + } + display->display(); + }; + + virtual void setConsoleMode(bool active) + { + _consoleMode = active; + }; + + virtual int addConsoleText(String text, bool tinyFont) + { + _textList[_curLine++] = text; + render(NULL); + return _curLine - 1; + }; + + virtual void updateConsoleText(int line, String text) + { + _textList[line] = text; + render(NULL); + }; // Display the tiem left before tracking hits the limit - void drawTime(Mount *mount, String label, const DayTime &time); + void drawTime(Mount *mount, String label, const DayTime &time) + { + char achTemp[24]; + display->setColor(WHITE); + display->setFont(Bitmap3x5); + sprintf(achTemp, "%s%02d:%02d", label.c_str(), time.getHours(), time.getMinutes()); + display->drawString(55, 59, achTemp); + } // Draw all the indicators on screen - void drawIndicators(Mount *mount); + void drawIndicators(Mount *mount) + { + char scratchBuffer[24]; + display->setFont(Bitmap5x7); + display->setColor(WHITE); + + drawStepperStates(mount); + int ra, dec; + // If a slew is in progress, we don't display the safe time, version, and + // comms indicator, since the progress bar takes up the same space + if (mount->getStepperProgress(ra, dec)) + { + drawProgressBar(ra, dec); + } + else + { + long timeSecs = millis() / 2000; // Change every 2 secs + int index = timeSecs % 5; // Cycle through multiple data displays + + display->setFont(CommSymbols); + display->drawString(11, 59, F("L")); // Memory chip icon + display->setFont(Bitmap3x5); + long availMem = freeMemory(); + if (availMem > 9999) + { + display->drawString(20, 59, String(availMem / 1024) + "K"); + } + else + { + display->drawString(20, 59, String(availMem)); + } + + switch (index) + { + case 0: + { + float hoursLeft = mount->checkRALimit(); + DayTime dt(hoursLeft); + drawTime(mount, F("REM "), dt); + } + break; + case 1: + { + drawTime(mount, F("LST "), mount->calculateLst()); + } + break; + case 2: + { + long now = millis(); + long msPerDay = 60L * 60 * 24 * 1000; + int days = (int) (now / msPerDay); + now -= days * msPerDay; + DayTime elapsed(1.0 * now / (1000.0 * 3600.0)); + drawTime(mount, F("UPT "), elapsed); + } + break; + case 3: + { + display->drawString(55, 59, (String(F(" FW ")) + String(VERSION)).c_str()); + } + break; + case 4: + { + float lat = fabsf(mount->latitude().getTotalHours()); + float lng = fabsf(mount->longitude().getTotalHours()); + const char dirLat = (mount->latitude().getTotalHours() < 0) ? 'S' : 'N'; + const char dirLong = (mount->longitude().getTotalHours() < 0) ? 'W' : 'E'; + sprintf(scratchBuffer, "LOC %s%c %s%c", String(lat, 0).c_str(), dirLat, String(lng, 0).c_str(), dirLong); + display->drawString(55, 59, scratchBuffer); + } + break; + } + drawCommunicationStatus(mount); + } + drawCoordinates(mount); + drawMountPosition(mount); + drawStatus(mount); + } // Display two 2-pixel high progress bar in the last 4 lines of the display - void drawProgressBar(int percRA, int percDEC); + void drawProgressBar(int percRA, int percDEC) + { + display->setColor(WHITE); + display->drawVerticalLine(127, 60, 4); + int raWidth = round(1.28f * percRA); + display->fillRect(0, 60, raWidth, 2); + int decWidth = round(1.28f * percDEC); + display->fillRect(0, 62, decWidth, 2); + } // Display a rectangle with the stepper label in it - void drawStepperState(String name, bool active, int xoff, int width, int textOffX = 0); + void drawStepperState(String name, bool active, int xoff, int width, int textOffX = 0) + { + display->setColor(WHITE); + if (active) + { + display->fillRect(xoff, 0, width, 11); + } + else + { + display->drawRect(xoff, 0, width, 11); + } + display->setColor(INVERSE); + display->drawString(xoff + 2 + textOffX, 2, name); + } // Display all the configured stepper status rectangles // Focuser is currently not supported, but could be added here, if possible. - void drawStepperStates(Mount *mount); + void drawStepperStates(Mount *mount) + { + display->setFont(Bitmap5x7); + drawStepperState(F("RA"), mount->isAxisRunning(RA_STEPS), 0, 15); + drawStepperState(F("DEC"), mount->isAxisRunning(DEC_STEPS), 16, 21); +#if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) + drawStepperState(F("ALT"), mount->isRunningALT(), 38, 21); +#endif +#if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) + drawStepperState(F("AZ"), mount->isRunningAZ(), 60, 16); +#endif + drawStepperState(F("GDE"), mount->isGuiding(), 83, 21); + drawStepperState(F("TRK"), mount->isSlewingTRK(), 105, 23, 1); + } - void drawCommunicationStatus(Mount *mount); + void drawCommunicationStatus(Mount *mount) + { + long recvdCmds = mount->getNumCommandsReceived(); + // If we have received any commands since the last display, draw the marker. + + if (_commLetter != ' ') + { + display->setFont(CommSymbols); + display->drawString(1, 59, String(_commLetter)); + _commLetter++; + if (_commLetter == 'G') // Past last communication animation frame (F) + { + _commLetter = ' '; + } + } + else if (recvdCmds != _lastNumCmds) + { + _commLetter = 'C'; // First communication animation frame + _lastNumCmds = recvdCmds; + } + } // Draw the given coordinate string at the given point - void drawCoordinate(int x, int y, const char *coord); + void drawCoordinate(int x, int y, const char *coord) + { + char achCoord[30]; + char *n = achCoord; + // Since this is not a full font, remap the supported letters to the right character + for (const char *p = coord; *p != 0; p++) + { + switch (*p) + { + case 'R': + *n = '!'; + break; + case 'A': + *n = '&'; + break; + case 'D': + *n = '#'; + break; + case 'E': + *n = '$'; + break; + case 'C': + *n = '%'; + break; + case 'h': + *n = '<'; + break; + case 'm': + *n = ';'; + break; + case 's': + *n = '='; + break; + case '@': + *n = '('; + break; + default: + *n = *p; + break; + } + n++; + } + *n = 0; + display->setFont(Bitmap7x15); + display->setColor(WHITE); + display->drawString(x, y, achCoord); + } // Draw the mounts celestial RA and DEC coordinates - void drawCoordinates(Mount *mount); + void drawCoordinates(Mount *mount) + { + String rc = mount->RAString(LCD_STRING | CURRENT_STRING); + String dc = mount->DECString(LCD_STRING | CURRENT_STRING); + drawCoordinate(8, 24, rc.c_str()); + drawCoordinate(0, 42, dc.c_str()); + } // Map the given RA coordinate to the pixel position on the display - int xRAPixel(float ra); + int xRAPixel(float ra) + { + float rangeRA = rightRA - leftRA; + int x = 4 + (int) round(1.0f * (_raSize - 9) * ((ra - leftRA) / rangeRA)); + return (_leftEdgeMount + x); + } // Map the given DEC coordinate to the pixel position on the display - int yDECPixel(float dec); + int yDECPixel(float dec) + { + int y = (int) round(1.0f * (_decSize) * ((dec - bottomDEC) / rangeDEC)); + return (_topEdgeMount + _decSize - y); + } // Draw the rectangle with the current and target positions - void drawMountPosition(Mount *mount); + void drawMountPosition(Mount *mount) + { + display->setColor(WHITE); + display->setFont(Bitmap3x5); + + // DEC tickmarks + for (int p = _topEdgeMount; p <= _topEdgeMount + _decSize; p += 2) + { + display->setPixel(_decScalePos, p); + } +#ifdef OAM + display->drawHorizontalLine(_decScalePos - 1, yDECPixel(-180.0), 2); +#endif + display->drawHorizontalLine(_decScalePos - 1, yDECPixel(-90.0), 2); + display->drawHorizontalLine(_decScalePos - 1, yDECPixel(0.0), 2); + display->drawHorizontalLine(_decScalePos - 1, yDECPixel(90.0), 2); + display->drawHorizontalLine(_decScalePos - 1, yDECPixel(180.0), 2); +// DEC tickmark labels +#ifdef OAM + display->drawString(_decScalePos + 6, yDECPixel(-180.0f) - 2, F("180")); + display->drawHorizontalLine(_decScalePos + 3, yDECPixel(-180.0), 2); // Smaller minus sign +#endif + display->drawString(_decScalePos + 6, yDECPixel(-90.0f) - 2, F("90")); + display->drawHorizontalLine(_decScalePos + 3, yDECPixel(-90.0), 2); // Smaller minus sign + display->drawString(_decScalePos + 3, yDECPixel(0.0f) - 2, "0"); + display->drawString(_decScalePos + 3, yDECPixel(90.0f) - 2, F("90")); + display->drawString(_decScalePos + 3, yDECPixel(180.0f) - 2, F("180")); + + // DEC Pos Marker + float decStepsPerDeg = mount->getStepsPerDegree(StepperAxis::DEC_STEPS); + long decSteps = mount->getCurrentStepperPosition(StepperAxis::DEC_STEPS); + float decDegrees = decSteps / decStepsPerDeg; + int yMark = yDECPixel(decDegrees); + display->setPixel(_decScalePos - 2, yMark); + display->drawVerticalLine(_decScalePos - 3, yMark - 1, 3); + display->drawVerticalLine(_decScalePos - 4, yMark - 2, 5); + + // RA tickmarks + for (int p = _leftEdgeMount; p <= _leftEdgeMount + _raSize; p += 2) + { + display->setPixel(p, _raScalePos); + } + display->drawVerticalLine(xRAPixel(-6.0f), _raScalePos - 1, 2); + display->drawVerticalLine(xRAPixel(-3.0f), _raScalePos - 1, 2); + display->drawVerticalLine(xRAPixel(0.0f), _raScalePos - 1, 2); + display->drawVerticalLine(xRAPixel(3.0f), _raScalePos - 1, 2); + display->drawVerticalLine(xRAPixel(6.0f), _raScalePos - 1, 2); + + // RA tickmark labels + display->drawString(xRAPixel(-6.0f) - 1, _raScalePos + 2, "6"); + display->drawHorizontalLine(xRAPixel(-6.0f) - 4, _raScalePos + 2 + 2, 2); // Smaller minus sign + display->drawString(xRAPixel(-3.0f) - 1, _raScalePos + 2, "3"); + display->drawHorizontalLine(xRAPixel(-3.0f) - 4, _raScalePos + 2 + 2, 2); // Smaller minus sign + display->drawString(xRAPixel(0.0f) - 1, _raScalePos + 2, "0"); + display->drawString(xRAPixel(3.0f) - 1, _raScalePos + 2, "3"); + display->drawString(xRAPixel(6.0f) - 1, _raScalePos + 2, "6"); + + float raStepsPerDeg = mount->getStepsPerDegree(StepperAxis::RA_STEPS); + float trkSteps = 1.0f * mount->getCurrentStepperPosition(TRACKING) / (1.0f * RA_TRACKING_MICROSTEPPING / RA_SLEW_MICROSTEPPING); + long raSteps = mount->getCurrentStepperPosition(StepperAxis::RA_STEPS); + float raHours = (trkSteps + raSteps) / raStepsPerDeg / 15.0f; + + // RA Position Marker + int xMark = xRAPixel(raHours); + display->setPixel(xMark, _raScalePos - 2); + display->drawHorizontalLine(xMark - 1, _raScalePos - 3, 3); + display->drawHorizontalLine(xMark - 2, _raScalePos - 4, 5); + } + // Display the tiem left before tracking hits the limit - void drawSafeTime(Mount *mount); + void drawSafeTime(Mount *mount) + { + char achTemp[10]; + float hoursLeft = mount->checkRALimit(); + DayTime dt(hoursLeft); + display->setColor(WHITE); + display->setFont(CommSymbols); + display->drawString(48, 59, "M"); // Clock sign + display->setFont(Bitmap3x5); + sprintf(achTemp, "%02d:%02d", dt.getHours(), dt.getMinutes()); + display->drawString(55, 59, achTemp); + } + + float sinLookup(float deg) + { + while (deg < 0.0f) + deg += 360.0f; + while (deg > 360.0f) + deg -= 360.0f; + + if (deg <= 90) + { + int index = (int) roundf(sineSize * deg / 90.0f); + return 1.0f * pgm_read_byte(sineTable + index) / 255.0; + } + else if (deg <= 180) + { + int index = (int) roundf(sineSize * (180.0f - deg) / 90.0f); + return 1.0f * pgm_read_byte(sineTable + index) / 255.0; + } + else if (deg <= 270) + { + int index = (int) roundf(sineSize * (deg - 180.0f) / 90.0f); + return -1.0f * pgm_read_byte(sineTable + index) / 255.0; + } + else if (deg <= 360) + { + int index = (int) roundf(sineSize * (360.0f - deg) / 90.0f); + return -1.0f * pgm_read_byte(sineTable + index) / 255.0; + } + return 0.0f; + } // Display the mount status string - void drawStatus(Mount *mount); + void drawStatus(Mount *mount) + { + display->setColor(WHITE); + display->setFont(Bitmap5x7); + String state = mount->getStatusStateString(); + state.toUpperCase(); + display->drawString(4, 14, state.c_str()); + + // Bouncing pixel (bounce frequency every 1.5s). 180 degrees is one cap. + float deg = 180.0f * (millis() % 1500) / 1500.0f; + int pixPos = (int) round(1.0f * yMaxStatus * sinLookup(deg)); + display->setPixel(0, 11 + yMaxStatus - pixPos); + } }; diff --git a/src/Utility.cpp b/src/Utility.cpp index 7937dda4..8f3f647e 100644 --- a/src/Utility.cpp +++ b/src/Utility.cpp @@ -226,46 +226,6 @@ float atanf(float x) return static_cast(atan(static_cast(x))); } -String *splitStringBy(String str, char splitChar) -{ - unsigned int count = 1; // At least one string if input is non-empty - - // Count occurrences of splitChar to determine the number of splits - for (unsigned int i = 0; i < str.length(); i++) - { - if (str[i] == splitChar) - { - count++; - } - } - - // Dynamically allocate memory for the resulting array - String *array = new String[count + 1]; // +1 for the nullptr terminator - unsigned int r = 0; // Start of the substring - unsigned int t = 0; // Index in the result array - - // Iterate through the string to split it - for (unsigned int i = 0; i < str.length(); i++) - { - if (str[i] == splitChar) - { - array[t++] = str.substring(r, i); // Store substring - r = i + 1; // Move start to next character - } - } - - // Add the last part of the string - if (r < str.length()) - { - array[t++] = str.substring(r); - } - - // Mark the end of the array with "" - array[t] = ""; - - return array; -} - #if defined(ESP32) int freeMemory() { @@ -284,7 +244,7 @@ int freeMemory() { char top; #ifdef __arm__ - return &top - reinterpret_cast(sbrk(0)); + return &top - sbrk(0); #elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151) return &top - __brkval; #else // __arm__ @@ -334,7 +294,7 @@ String formatArg(const char *input, va_list args) case 'd': { - String s = String((int) va_arg(args, int)); + String s = String(va_arg(args, int)); strcpy(p, s.c_str()); p += s.length(); } @@ -342,7 +302,7 @@ String formatArg(const char *input, va_list args) case 'x': { - int n = (int) va_arg(args, int); + int n = va_arg(args, int); int shift = 12; unsigned int mask = 0xF000; *p++ = '0'; @@ -361,7 +321,7 @@ String formatArg(const char *input, va_list args) case 'l': { - String s = String((long) va_arg(args, long)); + String s = String(va_arg(args, long)); strcpy(p, s.c_str()); p += s.length(); } diff --git a/src/Utility.hpp b/src/Utility.hpp index d8801ebd..cebf3a08 100644 --- a/src/Utility.hpp +++ b/src/Utility.hpp @@ -173,11 +173,5 @@ int sign(long num); int fsign(float num); #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -#define CASERETURN(c, r) \ - case c: \ - return r - -// Return an array of String* with a nullptr sentinel -String *splitStringBy(String str, char splitChar); #endif diff --git a/src/b_setup.hpp b/src/b_setup.hpp index 1757782c..e17254f3 100644 --- a/src/b_setup.hpp +++ b/src/b_setup.hpp @@ -12,10 +12,6 @@ PUSH_NO_WARNINGS POP_NO_WARNINGS #endif -#if TEST_VERIFY_MODE == 1 - #include "testmenu.hpp" -#endif - #ifndef NEW_STEPPER_LIB #include "InterruptCallback.hpp" #endif @@ -94,22 +90,6 @@ void stepperControlTimerCallback(void *payload) #endif #endif -int addConsoleText(String text) -{ -#if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) - return mount.getInfoDisplay()->addConsoleText(text, false); -#else - return -1; -#endif -} - -void updateConsoleText(int line, String newText) -{ -#if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) - mount.getInfoDisplay()->updateConsoleText(line, newText); -#endif -} - ///////////////////////////////// // // Main program setup @@ -126,72 +106,83 @@ void setup() #endif #else Serial.begin(SERIAL_BAUDRATE); + #if defined(ARDUINO_ARCH_RP2040) + // OATControl (and other apps using C# SerialPort) open the port with DTR=false. + // The Philhower USB CDC SerialUSB::write() gates TX on tud_cdc_connected() which + // requires DTR=true, so all responses are silently dropped for those hosts. + // ignoreFlowControl(true) bypasses the DTR check and always sends TX data. + Serial.ignoreFlowControl(true); + #endif #if DEBUG_LEVEL > 0 && DEBUG_SEPARATE_SERIAL == 1 DEBUG_SERIAL_PORT.begin(DEBUG_SERIAL_BAUDRATE); #endif -#endif - -#if TEST_VERIFY_MODE == 1 - #ifdef OAM - Serial.print(F("Booting OAM Firmware ")); - #elif defined(OAE) - Serial.print(F("Booting OAE Firmware ")); - #else - Serial.print(F("Booting OAT Firmware ")); - #endif - Serial.print(VERSION); - Serial.println(F(" ...")); -#else - #ifdef OAM - LOG(DEBUG_ANY, "[SYSTEM]: Hello, universe, this is OAM Firmware %s!", VERSION); - #else - LOG(DEBUG_ANY, "[SYSTEM]: Hello, universe, this is OAT Firmware %s!", VERSION); + // RP2040 USB CDC: wait up to 3 s for the host to open the port so that + // LOG() calls below are not dropped (or do not block indefinitely). + // This only matters when DEBUG_LEVEL > 0 — in release builds LOG() is + // a no-op, so the wait is compiled out. + #if defined(ARDUINO_ARCH_RP2040) && DEBUG_LEVEL > 0 + { + uint32_t _cdcWaitStart = millis(); + while (!Serial && (millis() - _cdcWaitStart) < 3000UL) { /* spin */ } + } #endif #endif + LOG(DEBUG_ANY, "[SYSTEM]: Hello, universe, this is OAT %s!", VERSION); + #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) LOG(DEBUG_ANY, "[SYSTEM]: Get OLED info screen ready..."); mount.setupInfoDisplay(); - addConsoleText(F("BOOTING " VERSION)); LOG(DEBUG_ANY, "[SYSTEM]: OLED info screen ready!"); + mount.getInfoDisplay()->addConsoleText(F("BOOTING " VERSION), false); #endif #if USE_GPS == 1 - LOG(DEBUG_ANY, "[SYSTEM]: Initializing GPS..."); - #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) - int gpsLine = addConsoleText(F("Initialize GPS...")); + #if defined(ARDUINO_ARCH_RP2040) && defined(RP2040_GPS_TX_PIN) && defined(RP2040_GPS_RX_PIN) + GPS_SERIAL_PORT.setTX(RP2040_GPS_TX_PIN); + GPS_SERIAL_PORT.setRX(RP2040_GPS_RX_PIN); #endif GPS_SERIAL_PORT.begin(GPS_BAUD_RATE); - #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) - updateConsoleText(gpsLine, F("Initialize GPS... OK")); - #endif #endif //Turn on dew heater #if DEW_HEATER == 1 - LOG(DEBUG_ANY, "[SYSTEM]: Initializing dew heater..."); - int dewHeaterLine = addConsoleText(F("Enable Dew Heater...")); #if defined(DEW_HEATER_1_PIN) digitalWrite(DEW_HEATER_1_PIN, HIGH); #endif #if defined(DEW_HEATER_2_PIN) digitalWrite(DEW_HEATER_2_PIN, HIGH); #endif - updateConsoleText(dewHeaterLine, F("Enable Dew Heater... OK")); +#endif + +#if defined(RP2040_FAN1_PIN) + pinMode(RP2040_FAN1_PIN, OUTPUT); + analogWrite(RP2040_FAN1_PIN, (RP2040_FAN1_POWER_PERCENT * 255) / 100); #endif #if (USE_RA_END_SWITCH == 1 || USE_DEC_END_SWITCH == 1) - int endSwitchesLine = addConsoleText(F("Init End Switches...")); LOG(DEBUG_ANY, "[SYSTEM]: Init EndSwitches..."); mount.setupEndSwitches(); - updateConsoleText(endSwitchesLine, F("Init End Switches... OK")); +#endif + + ///////////////////////////////// + // RP2040: UART pin remapping + ///////////////////////////////// + // The Philhower arduino-pico core requires setTX()/setRX() to be called + // before begin() to remap UART pins away from their defaults. This must + // happen before any Serial2.begin() calls in the driver setup below. + // RP2040_UART1_TX_PIN / RP2040_UART1_RX_PIN are defined in the board's + // pins file only for RP2040 targets that use a non-default UART1 mapping. +#if defined(ARDUINO_ARCH_RP2040) && defined(RP2040_UART1_TX_PIN) && defined(RP2040_UART1_RX_PIN) + Serial2.setTX(RP2040_UART1_TX_PIN); + Serial2.setRX(RP2040_UART1_RX_PIN); + Serial2.setPollingMode(true); // Must be called before begin(); avoids IRQ/CoreMutex blocking in TMCStepper read path + Serial2.begin(115200); // TMCStepper HW-serial path never calls begin(); must do it here. #endif ///////////////////////////////// // Microstepping/driver pins ///////////////////////////////// - int raLine = addConsoleText(F("Init RA axis...")); - LOG(DEBUG_ANY, "[SYSTEM]: Initializing RA microstepping/driver pins..."); pinMode(RA_EN_PIN, OUTPUT); digitalWrite(RA_EN_PIN, LOW); // ENABLE, LOW to enable #if RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_STANDALONE || RA_DRIVER_TYPE == DRIVER_TYPE_A4988_GENERIC @@ -206,25 +197,12 @@ void setup() #endif #endif #if RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - LOG(DEBUG_ANY, "[SYSTEM]: Initializing TMC2209 UART pins and Serial port for RA..."); // include TMC2209 UART pins - #if defined(RA_DIAG_PIN) pinMode(RA_DIAG_PIN, INPUT); - #endif - #ifdef RA_SERIAL_PORT - #ifdef OAE - RA_SERIAL_PORT.begin(57600, SERIAL_8N1, RA_RX_PIN, RA_TX_PIN); - #else - RA_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver - #endif - // + RA_SERIAL_PORT.begin(115200); // Start HardwareSerial comms with driver (TMCStepper requires 115200) #endif #endif - updateConsoleText(raLine, F("Init RA axis... OK")); - - int decLine = addConsoleText(F("Init DEC axis...")); - LOG(DEBUG_ANY, "[SYSTEM]: Initializing DEC driver pin %s...", String(DEC_EN_PIN).c_str()); pinMode(DEC_EN_PIN, OUTPUT); digitalWrite(DEC_EN_PIN, LOW); // ENABLE, LOW to enable #if DEC_DRIVER_TYPE == DRIVER_TYPE_TMC2209_STANDALONE || DEC_DRIVER_TYPE == DRIVER_TYPE_A4988_GENERIC @@ -238,56 +216,43 @@ void setup() digitalWrite(DEC_MS2_PIN, HIGH); // MS3 #endif #endif - #if DEC_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - LOG(DEBUG_ANY, "[SYSTEM]: Initializing TMC2209 UART pins and Serial port for DEC..."); // include TMC2209 UART pins - #if defined(DEC_DIAG_PIN) pinMode(DEC_DIAG_PIN, INPUT); - #endif #ifdef DEC_SERIAL_PORT - #ifdef OAE - DEC_SERIAL_PORT.begin(57600, SERIAL_8N1, DEC_RX_PIN, DEC_TX_PIN); - #else - DEC_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver - #endif + DEC_SERIAL_PORT.begin(115200); // Start HardwareSerial comms with driver (TMCStepper requires 115200) #endif #endif - updateConsoleText(decLine, F("Init DEC axis... OK")); - LOG(DEBUG_ANY, "[SYSTEM]: RA/DEC init complete..."); #if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) - int azLine = addConsoleText(F("Init AZ axis...")); - LOG(DEBUG_ANY, "[SYSTEM]: Initializing AZ microstepping/driver pins..."); pinMode(AZ_EN_PIN, OUTPUT); digitalWrite(AZ_EN_PIN, HIGH); // Logic HIGH to disable the driver initally #if AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART // include TMC2209 UART pins + #if defined(AZ_DIAG_PIN) pinMode(AZ_DIAG_PIN, INPUT); + #endif #ifdef AZ_SERIAL_PORT - AZ_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver + AZ_SERIAL_PORT.begin(115200); // Start HardwareSerial comms with driver (TMCStepper requires 115200) #endif #endif - updateConsoleText(azLine, F("Init AZ axis... OK")); #endif #if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) - int altLine = addConsoleText(F("Init ALT axis...")); - LOG(DEBUG_ANY, "[SYSTEM]: Initializing ALT microstepping/driver pins..."); pinMode(ALT_EN_PIN, OUTPUT); digitalWrite(ALT_EN_PIN, HIGH); // Logic HIGH to disable the driver initally #if ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART // include TMC2209 UART pins + #if defined(ALT_DIAG_PIN) pinMode(ALT_DIAG_PIN, INPUT); + #endif #ifdef ALT_SERIAL_PORT - ALT_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver + ALT_SERIAL_PORT.begin(115200); // Start HardwareSerial comms with driver (TMCStepper requires 115200) #endif #endif - updateConsoleText(altLine, F("Init ALT axis... OK")); #endif #if (FOCUS_STEPPER_TYPE != STEPPER_TYPE_NONE) - int focusLine = addConsoleText(F("Init Focuser...")); LOG(DEBUG_FOCUS, "[FOCUS]: setup(): focus disabling enable pin"); pinMode(FOCUS_EN_PIN, OUTPUT); digitalWrite(FOCUS_EN_PIN, HIGH); // Logic HIGH to disable the driver initally @@ -295,44 +260,51 @@ void setup() // include TMC2209 UART pins #ifdef FOCUS_SERIAL_PORT LOG(DEBUG_FOCUS, "[FOCUS]: setup(): focus TMC2209U starting comms"); - FOCUS_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver + FOCUS_SERIAL_PORT.begin(115200); // Start HardwareSerial comms with driver (TMCStepper requires 115200) #endif #endif - updateConsoleText(focusLine, F("Init Focuser... OK")); +#endif + +#if defined(RP2040_SHARED_EN_PIN) + // On boards where all stepper EN lines share one GPIO (e.g. JackW01 carrier), + // the per-axis init sequence leaves that GPIO HIGH (logic disabled) after the + // AZ/ALT blocks run. Force it LOW here so every driver is enabled once all + // UART addresses have been configured. Per-axis power management is handled + // via the TMC2209 IHOLD register over UART rather than toggling this pin. + pinMode(RP2040_SHARED_EN_PIN, OUTPUT); + digitalWrite(RP2040_SHARED_EN_PIN, LOW); #endif // end microstepping ------------------- -#if USE_HALL_SENSOR_RA_AUTOHOME == 1 || USE_HALL_SENSOR_DEC_AUTOHOME == 1 - int homingLine = addConsoleText(F("Init homing sensors...")); - #if USE_HALL_SENSOR_RA_AUTOHOME == 1 +#if USE_HALL_SENSOR_RA_AUTOHOME == 1 pinMode(RA_HOMING_SENSOR_PIN, INPUT); - #endif +#endif - #if USE_HALL_SENSOR_DEC_AUTOHOME == 1 +#if USE_HALL_SENSOR_DEC_AUTOHOME == 1 pinMode(DEC_HOMING_SENSOR_PIN, INPUT); - #endif - updateConsoleText(homingLine, F("Init homing sensors... OK")); #endif - LOG(DEBUG_ANY, "[SYSTEM]: Initializing EEPROM store..."); - int eepromLine = addConsoleText(F("INIT EEPROM...")); +#if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) + int eepromLine = mount.getInfoDisplay()->addConsoleText(F("INIT EEPROM...")); +#endif + LOG(DEBUG_ANY, "[SYSTEM]: Get EEPROM store ready..."); EEPROMStore::initialize(); LOG(DEBUG_ANY, "[SYSTEM]: EEPROM store ready!"); - updateConsoleText(eepromLine, F("INIT EEPROM... OK")); + +#if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) + mount.getInfoDisplay()->updateConsoleText(eepromLine, F("INIT EEPROM... OK")); +#endif // Calling the LCD startup here, I2C can't be found if called earlier #if DISPLAY_TYPE != DISPLAY_TYPE_NONE LOG(DEBUG_ANY, "[SYSTEM]: Get LCD ready..."); - int lcdLine = addConsoleText(F("Init LCD...")); lcdMenu.startup(); // Show a splash screen lcdMenu.setCursor(0, 0); #ifdef OAM lcdMenu.printMenu(" OpenAstroMount"); - #elif defined(OAE) - lcdMenu.printMenu("OpenAstroExplorer"); #else lcdMenu.printMenu("OpenAstroTracker"); #endif @@ -395,7 +367,6 @@ void setup() #if SUPPORT_INFO_DISPLAY == 1 lcdMenu.addItem("INFO", Status_Menu); #endif - updateConsoleText(lcdLine, F("Init LCD... OK")); #endif // DISPLAY_TYPE > 0 @@ -403,16 +374,16 @@ void setup() // Create the command processor singleton LOG(DEBUG_ANY, "[SYSTEM]: Initialize LX200 handler..."); - int commandProcessorLine = addConsoleText(F("Init MEADE handler...")); MeadeCommandProcessor::createProcessor(&mount, &lcdMenu); - updateConsoleText(commandProcessorLine, F("Init MEADE handler... OK")); #if (WIFI_ENABLED == 1) LOG(DEBUG_ANY, "[SYSTEM]: Setup Wifi..."); wifiControl.setup(); #endif - int stepperLine = addConsoleText(F("Energize Steppers...")); +#if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) + int stepperLine = mount.getInfoDisplay()->addConsoleText(F("INIT STEPPERS...")); +#endif // Configure the mount // Delay for a while to get UARTs booted... @@ -423,6 +394,7 @@ void setup() // Set the stepper motor parameters #if (RA_STEPPER_TYPE != STEPPER_TYPE_NONE) LOG(DEBUG_ANY, "[STEPPERS]: Configure RA stepper NEMA."); + LOG(DEBUG_ANY, "[STEPPERS]: Stepper SPR : %d", RA_STEPPER_SPR); LOG(DEBUG_ANY, "[STEPPERS]: Slew Microsteps : %d", RA_SLEW_MICROSTEPPING); LOG(DEBUG_ANY, "[STEPPERS]: Trk Microsteps : %d", RA_TRACKING_MICROSTEPPING); LOG(DEBUG_ANY, "[STEPPERS]: Stepper SPR : %d", RA_STEPPER_SPR); @@ -446,18 +418,17 @@ void setup() #if (DEC_STEPPER_TYPE != STEPPER_TYPE_NONE) LOG(DEBUG_ANY, "[STEPPERS]: Configure DEC stepper NEMA."); - LOG(DEBUG_ANY, "[STEPPERS]: Slew Microsteps : %d", DEC_SLEW_MICROSTEPPING); - LOG(DEBUG_ANY, "[STEPPERS]: Guide Microsteps : %d", DEC_GUIDE_MICROSTEPPING); - LOG(DEBUG_ANY, "[STEPPERS]: Stepper SPR : %d", DEC_STEPPER_SPR); - LOG(DEBUG_ANY, "[STEPPERS]: Transmission : %f", DEC_TRANSMISSION); + LOG(DEBUG_ANY, "[STEPPERS]: Slew Microsteps : %d", DEC_SLEW_MICROSTEPPING); + LOG(DEBUG_ANY, "[STEPPERS]: Stepper SPR : %d", DEC_STEPPER_SPR); + LOG(DEBUG_ANY, "[STEPPERS]: Transmission : %f", DEC_TRANSMISSION); #ifdef NEW_STEPPER_LIB - LOG(DEBUG_ANY, "[STEPPERS]: Driver Slew SPR : %l", config::Dec::DRIVER_SPR_SLEW); - LOG(DEBUG_ANY, "[STEPPERS]: Driver Trk SPR : %l", config::Dec::DRIVER_SPR_TRK); - LOG(DEBUG_ANY, "[STEPPERS]: SPR Slew : %f", config::Dec::SPR_SLEW); - LOG(DEBUG_ANY, "[STEPPERS]: SPR Trk : %f", config::Dec::SPR_TRK); - LOG(DEBUG_ANY, "[STEPPERS]: Speed Slew : %f", config::Dec::SPEED_SLEW); - LOG(DEBUG_ANY, "[STEPPERS]: Accel Slew : %f", config::Dec::ACCEL_SLEW); - LOG(DEBUG_ANY, "[STEPPERS]: Speed Trk : %f", config::Dec::SPEED_TRK); + LOG(DEBUG_ANY, "[STEPPERS]: Driver Slew SPR : %l", config::Dec::DRIVER_SPR_SLEW); + LOG(DEBUG_ANY, "[STEPPERS]: Driver Trk SPR : %l", config::Dec::DRIVER_SPR_TRK); + LOG(DEBUG_ANY, "[STEPPERS]: SPR Slew : %f", config::Dec::SPR_SLEW); + LOG(DEBUG_ANY, "[STEPPERS]: SPR Trk : %f", config::Dec::SPR_TRK); + LOG(DEBUG_ANY, "[STEPPERS]: Speed Slew : %f", config::Dec::SPEED_SLEW); + LOG(DEBUG_ANY, "[STEPPERS]: Accel Slew : %f", config::Dec::ACCEL_SLEW); + LOG(DEBUG_ANY, "[STEPPERS]: Speed Trk : %f", config::Dec::SPEED_TRK); LOG(DEBUG_ANY, "[STEPPERS]: Configure DEC stepper NEMA..."); mount.configureDECStepper(DECmotorPin1, DECmotorPin2, config::Dec::SPEED_SLEW, config::Dec::ACCEL_SLEW); #else @@ -485,12 +456,6 @@ void setup() #if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) LOG(DEBUG_ANY, "[STEPPERS]: Configure AZ stepper..."); - LOG(DEBUG_ANY, "[STEPPERS]: AZ Microsteps : %d", AZ_MICROSTEPPING); - LOG(DEBUG_ANY, "[STEPPERS]: AZ Stepper SPR : %d", AZ_STEPPER_SPR); - LOG(DEBUG_ANY, "[STEPPERS]: AZ Circumference : %f", AZ_CIRCUMFERENCE); - LOG(DEBUG_ANY, "[STEPPERS]: AZ steps/rev : %f", AZIMUTH_STEPS_PER_REV); - LOG(DEBUG_ANY, "[STEPPERS]: AZ steps/deg : %f", mount.getStepsPerDegree(AZIMUTH_STEPS)); - LOG(DEBUG_ANY, "[STEPPERS]: AZ steps/minute : %f", AZIMUTH_STEPS_PER_ARC_MINUTE); mount.configureAZStepper(AZmotorPin1, AZmotorPin2, AZ_STEPPER_SPEED, AZ_STEPPER_ACCELERATION); #if AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART LOG(DEBUG_ANY, "[STEPPERS]: Configure AZ driver..."); @@ -503,12 +468,6 @@ void setup() #endif #if (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) LOG(DEBUG_ANY, "[STEPPERS]: Configure Alt stepper..."); - LOG(DEBUG_ANY, "[STEPPERS]: ALT Microsteps : %d", ALT_MICROSTEPPING); - LOG(DEBUG_ANY, "[STEPPERS]: ALT Stepper SPR : %d", ALT_STEPPER_SPR); - LOG(DEBUG_ANY, "[STEPPERS]: ALT Circumference : %f", ALT_CIRCUMFERENCE); - LOG(DEBUG_ANY, "[STEPPERS]: ALT steps/rev : %f", ALTITUDE_STEPS_PER_REV); - LOG(DEBUG_ANY, "[STEPPERS]: ALT steps/deg : %f", mount.getStepsPerDegree(ALTITUDE_STEPS)); - LOG(DEBUG_ANY, "[STEPPERS]: ALT steps/minute : %f", ALTITUDE_STEPS_PER_ARC_MINUTE); mount.configureALTStepper(ALTmotorPin1, ALTmotorPin2, ALT_STEPPER_SPEED, ALT_STEPPER_ACCELERATION); #if ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART LOG(DEBUG_ANY, "[STEPPERS]: Configure ALT driver..."); @@ -535,10 +494,22 @@ void setup() #endif #endif - LOG(DEBUG_ANY, "[SYSTEM]: Energize Steppers... OK"); - updateConsoleText(stepperLine, F("Energize Steppers... OK")); +#if defined(RP2040_SHARED_EN_PIN) + // Re-assert EN LOW after all driver configs. Each configureXXXdriver() that + // fails its UART connection test calls digitalWrite(X_EN_PIN, HIGH) as a + // safety measure; on JackW01 all EN lines share one GPIO so all four failures + // leave that GPIO HIGH (motors disabled). Override it here unconditionally so + // the motors are always enabled after initialization. + digitalWrite(RP2040_SHARED_EN_PIN, LOW); +#endif - int configureLine = addConsoleText(F("Configure Mount...")); +#if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) + mount.getInfoDisplay()->updateConsoleText(stepperLine, F("INIT STEPPERS... OK")); +#endif + +#if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) + mount.getInfoDisplay()->addConsoleText(F("CONFIGURING...")); +#endif LOG(DEBUG_ANY, "[SYSTEM]: Read Configuration..."); @@ -559,7 +530,7 @@ void setup() // Setup service to periodically service the steppers. #if defined(ESP32) - LOG(DEBUG_ANY, "[SYSTEM]: Setup StepperControlTask on Core 0..."); + disableCore0WDT(); xTaskCreatePinnedToCore(stepperControlTask, // Function to run on this core "StepperControl", // Name of this task @@ -579,10 +550,10 @@ void setup() #endif #endif - updateConsoleText(configureLine, F("Configure Mount... OK")); - #if UART_CONNECTION_TEST_TX == 1 - int testLine = addConsoleText(F("Test UARTs...")); + #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) + int testLine = mount.getInfoDisplay()->addConsoleText(F("TEST STEPPERS...")); + #endif #if RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART LOG(DEBUG_STEPPERS, "[STEPPERS]: Moving RA axis using UART commands..."); mount.testRA_UART_TX(); @@ -594,7 +565,9 @@ void setup() mount.testDEC_UART_TX(); LOG(DEBUG_STEPPERS, "[STEPPERS]: Finished moving DEC axis using UART commands."); #endif - updateConsoleText(testLine, F("Test UARTs... OK")); + #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) + mount.getInfoDisplay()->updateConsoleText(testLine, F("TEST STEPPERS... OK")); + #endif #endif LOG(DEBUG_ANY, "[SYSTEM]: Setting %s hemisphere...", inNorthernHemisphere ? "northern" : "southern"); @@ -608,13 +581,9 @@ void setup() mount.bootComplete(); LOG(DEBUG_ANY, "[SYSTEM]: Boot complete!"); - addConsoleText(F("BOOT COMPLETE!")); #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) - delay(500); + mount.getInfoDisplay()->addConsoleText(F("BOOT COMPLETE!")); + delay(250); mount.getInfoDisplay()->setConsoleMode(false); #endif - -#if TEST_VERIFY_MODE == 1 - TestMenu::getCurrentMenu()->display(); -#endif } diff --git a/src/c_buttons.hpp b/src/c_buttons.hpp index d594cb2c..8c58c2cb 100644 --- a/src/c_buttons.hpp +++ b/src/c_buttons.hpp @@ -98,6 +98,13 @@ void loop() lcdMenu.setCursor(0, 1); #if SUPPORT_SERIAL_CONTROL == 1 + #if defined(ARDUINO_ARCH_RP2040) + // On RP2040, the Philhower core does not reliably call serialEvent() for the + // USB CDC Serial port when a host application opens the port and immediately + // sends data (e.g. OATControl). Poll explicitly on every loop() iteration so + // that commands are always processed regardless of inSerialControl state. + processSerialData(); + #endif if (inSerialControl) { if (lcdButtons.keyChanged(&lcd_key)) diff --git a/src/f_serial.hpp b/src/f_serial.hpp index ad3741a7..9d6e8dd4 100644 --- a/src/f_serial.hpp +++ b/src/f_serial.hpp @@ -1,10 +1,5 @@ #pragma once -#if TEST_VERIFY_MODE == 1 - #include "testmenu.hpp" - #include "testmenudef.hpp" -#endif - #include "b_setup.hpp" #if SUPPORT_SERIAL_CONTROL == 1 @@ -26,10 +21,6 @@ void serialLoop() #if (WIFI_ENABLED == 1) wifiControl.loop(); #endif - - #if TEST_VERIFY_MODE == 1 - mainTestMenu.tick(); - #endif } ////////////////////////////////////////////////// @@ -41,117 +32,41 @@ void serialEvent() } #endif - #if TEST_VERIFY_MODE == 1 - -void processTestState() -{ - static char buffer[32]; - static unsigned int index = 0; - switch (TestMenu::getMenuState()) - { - case testMenuState_t::CLEAR: - TestMenu::setMenuState(testMenuState_t::WAITING_ON_INPUT); - break; - - case testMenuState_t::WAITING_ON_INPUT: - while (Serial.available() > 0) - { - if (Serial.readBytes(buffer, 1) == 1) - { - if ((buffer[0] >= '0') && (buffer[0] <= '9')) - { - Serial.println(buffer[0]); - int pressedKey = buffer[0] - '0'; - TestMenu::getCurrentMenu()->onKeyPressed(pressedKey); - } - } - } - break; - - case testMenuState_t::WAITING_ON_COMMAND: - while (Serial.available() > 0) - { - char ch; - if (Serial.readBytes(&ch, 1) == 1) - { - if (isascii(ch)) - { - buffer[index] = ch; - if (ch == '#') - { - buffer[index + 1] = '\0'; - TestMenu::getCurrentMenu()->onCommandReceived(buffer); - TestMenu::setMenuState(testMenuState_t::WAITING_ON_INPUT); - TestMenu::getCurrentMenu()->display(); - index = 0; - } - else - { - index++; - if (index > ARRAY_SIZE(buffer) - 1) - { - Serial.println(F("Buffer overflow, too many chars received")); - index = 0; - } - } - } - } - } - break; - } -} - -void processSerialData() -{ - processTestState(); -} - #else // ESP needs to call this in a loop :_( void processSerialData() { - static char buffer[20]; - static unsigned int index = 0; + char buffer[2]; while (Serial.available() > 0) { - if (Serial.readBytes((buffer + index), 1) == 1) + if (Serial.readBytes(buffer, 1) == 1) { - if (buffer[index] == 0x06) + if (buffer[0] == 0x06) { LOG(DEBUG_SERIAL, "[SERIAL]: Received: ACK request, replying P"); - // When not debugging, print the result to the serial port . - // When debugging, only print the result to Serial if we're on seperate ports. - #if (DEBUG_LEVEL == DEBUG_NONE) || (DEBUG_SEPARATE_SERIAL == 1) + // When not debugging, print the result to the serial port . + // When debugging, only print the result to Serial if we're on seperate ports. + #if (DEBUG_LEVEL == DEBUG_NONE) || (DEBUG_SEPARATE_SERIAL == 1) Serial.print('P'); - #endif - index = 0; + #endif } - else if (buffer[index] == '#') + else { - // Ignoring trailing hash - buffer[index] = '\0'; - const String inCmd = String(buffer); + String inCmd = String(buffer[0]) + Serial.readStringUntil('#'); LOG(DEBUG_SERIAL, "[SERIAL]: ReceivedCommand(%d chars): [%s]", inCmd.length(), inCmd.c_str()); - const String retVal = MeadeCommandProcessor::instance()->processCommand(inCmd); + String retVal = MeadeCommandProcessor::instance()->processCommand(inCmd); if (retVal != "") { LOG(DEBUG_SERIAL, "[SERIAL]: RepliedWith: [%s]", retVal.c_str()); - // When not debugging, print the result to the serial port . - // When debugging, only print the result to Serial if we're on seperate ports. - #if (DEBUG_LEVEL == DEBUG_NONE) || (DEBUG_SEPARATE_SERIAL == 1) + // When not debugging, print the result to the serial port . + // When debugging, only print the result to Serial if we're on seperate ports. + #if (DEBUG_LEVEL == DEBUG_NONE) || (DEBUG_SEPARATE_SERIAL == 1) Serial.print(retVal); - #endif + #endif } - // Wait for next command - index = 0; - } - else if (buffer[index] >= ' ') - { - index++; - if (index >= sizeof(buffer)) + else { - LOG(DEBUG_SERIAL, "[SERIAL]: Command buffer overflow! Ignoring received data."); - index = 0; + LOG(DEBUG_SERIAL, "[SERIAL]: NoReply"); } } } @@ -160,5 +75,4 @@ void processSerialData() } } - #endif #endif diff --git a/src/fonts128x64.h b/src/fonts128x64.h index a0aae3dd..be6c8bcb 100644 --- a/src/fonts128x64.h +++ b/src/fonts128x64.h @@ -1,4 +1,3 @@ -#pragma once #include // Font generated or edited with the glyphEditor diff --git a/src/testmenu.cpp b/src/testmenu.cpp deleted file mode 100644 index 1b0d1763..00000000 --- a/src/testmenu.cpp +++ /dev/null @@ -1,671 +0,0 @@ -#include "../Configuration.hpp" -#include "Utility.hpp" -#include "Mount.hpp" -#include "MeadeCommandProcessor.hpp" - -#if TEST_VERIFY_MODE == 1 - - #include "MappedDict.hpp" - #include "testmenu.hpp" - -extern Mount mount; - -TestMenu *TestMenu::_currentMenu = nullptr; -TestMenuItem *TestMenu::_backItem = nullptr; -testMenuState_t TestMenu::_menuState = testMenuState_t::CLEAR; -testMenuInternalState TestMenu::_internalState = testMenuInternalState::IDLE; - -inline testMenuInternalState operator|=(testMenuInternalState &a, testMenuInternalState b) -{ - return a = static_cast(static_cast(a) | static_cast(b)); -}; - -inline testMenuInternalState operator|=(testMenuInternalState &a, int b) -{ - return a = static_cast(static_cast(a) | b); -}; - -long TestMenu::_targetRA = 0; -long TestMenu::_startRA = 0; -long TestMenu::_targetDEC = 0; -long TestMenu::_startDEC = 0; -long TestMenu::_startAZ = 0; -long TestMenu::_targetAZ = 0; -long TestMenu::_startALT = 0; -long TestMenu::_targetALT = 0; - -String getMenuLabel(menuText_t labelId) -{ - switch (labelId) - { - CASERETURN(MENU_BACK, F("Back")); - CASERETURN(MENU_CONNECT_RA, F("Connect to RA Driver")); - CASERETURN(MENU_CONNECT_DEC, F("Connect to DEC Driver")); - CASERETURN(MENU_CONNECT_ALT, F("Connect to ALT Driver")); - CASERETURN(MENU_CONNECT_AZ, F("Connect to AZ Driver")); - CASERETURN(MENU_CONNECT_FOC, F("Connect to FOCUS Driver")); - CASERETURN(MENU_PRIMARY_RA_CW, F("Move RA Axis 1h clockwise")); - CASERETURN(MENU_PRIMARY_RA_CCW, F("Move RA Axis 1h counter-clockwise")); - CASERETURN(MENU_PRIMARY_DEC_UP, F("Move DEC Axis 15deg up")); - CASERETURN(MENU_PRIMARY_DEC_DOWN, F("Move DEC Axis 15deg down")); - CASERETURN(MENU_TOGGLE_TRK, F("Stop/Start Tracking")); - CASERETURN(MENU_SECONDARY_RATE_1, F("Set distance to 0.1 arcmin")); - CASERETURN(MENU_SECONDARY_RATE_2, F("Set distance to 0.5 arcmin")); - CASERETURN(MENU_SECONDARY_RATE_3, F("Set distance to 2 arcmin")); - CASERETURN(MENU_SECONDARY_RATE_4, F("Set distance to 5 arcmin")); - CASERETURN(MENU_SECONDARY_RATE_5, F("Set distance to 15 arcmin")); - CASERETURN(MENU_SECONDARY_ALT_UP, F("Move ALT Axis Up")); - CASERETURN(MENU_SECONDARY_ALT_DOWN, F("Move ALT Axis Down")); - CASERETURN(MENU_SECONDARY_AZ_LEFT, F("Move AZ Axis Left")); - CASERETURN(MENU_SECONDARY_AZ_RIGHT, F("Move AZ Axis Right")); - CASERETURN(MENU_FACTORY_RESET, F("Factory Reset (Erase EEPROM)")); - CASERETURN(MENU_PASSTHROUGH_COMMAND, F("Issue LX200 Command")); - CASERETURN(MENU_MAIN_LIST_HARDWARE, F("List Hardware")); - CASERETURN(MENU_MAIN_CONNECT_DRIVERS, F("Connect Drivers")); - CASERETURN(MENU_MAIN_PRIMARY_AXIS_MOVES, F("Primary Axis Moves (RA/DEC)")); - CASERETURN(MENU_MAIN_SECONDARY_AXIS_MOVES, F("Secondary Axis Moves (ALT/AZ)")); - CASERETURN(MENU_PRIMARY_SET_HOME, F("Set current as Home")); - CASERETURN(MENU_PRIMARY_GO_HOME, F("Go Home")); - default: - return F("Unknown"); - } -} - -String getMenuAction(menuText_t labelId) -{ - switch (labelId) - { - CASERETURN(MENU_BACK, F("Action:Back")); - CASERETURN(MENU_CONNECT_RA, F("Action:Connect|RA")); - CASERETURN(MENU_CONNECT_DEC, F("Action:Connect|DEC")); - CASERETURN(MENU_CONNECT_ALT, F("Action:Connect|ALT")); - CASERETURN(MENU_CONNECT_AZ, F("Action:Connect|AZ")); - CASERETURN(MENU_CONNECT_FOC, F("Action:Connect|FOC")); - CASERETURN(MENU_PRIMARY_RA_CW, F("Action:MoveRAAxis|CW")); - CASERETURN(MENU_PRIMARY_RA_CCW, F("Action:MoveRAAxis|CCW")); - CASERETURN(MENU_PRIMARY_SET_HOME, F("Action:SetHome")); - CASERETURN(MENU_PRIMARY_GO_HOME, F("Action:GoHome")); - CASERETURN(MENU_PRIMARY_DEC_UP, F("Action:MoveDECAxis|UP")); - CASERETURN(MENU_PRIMARY_DEC_DOWN, F("Action:MoveDECAxis|DOWN")); - CASERETURN(MENU_TOGGLE_TRK, F("Action:ToggleTRK")); - - CASERETURN(MENU_SECONDARY_RATE_1, F("Action:SetSecDist|0.1")); - CASERETURN(MENU_SECONDARY_RATE_2, F("Action:SetSecDist|0.5")); - CASERETURN(MENU_SECONDARY_RATE_3, F("Action:SetSecDist|2")); - CASERETURN(MENU_SECONDARY_RATE_4, F("Action:SetSecDist|5")); - CASERETURN(MENU_SECONDARY_RATE_5, F("Action:SetSecDist|15")); - - CASERETURN(MENU_SECONDARY_ALT_UP, F("Action:MoveALTAxis|UP")); - CASERETURN(MENU_SECONDARY_ALT_DOWN, F("Action:MoveALTAxis|DOWN")); - CASERETURN(MENU_SECONDARY_AZ_LEFT, F("Action:MoveAZAxis|LEFT")); - CASERETURN(MENU_SECONDARY_AZ_RIGHT, F("Action:MoveAZAxis|RIGHT")); - CASERETURN(MENU_FACTORY_RESET, F("Action:FactoryReset")); - CASERETURN(MENU_PASSTHROUGH_COMMAND, F("Action:PassthroughCmd")); - CASERETURN(MENU_MAIN_LIST_HARDWARE, F("Action:ListHardware")); - CASERETURN(MENU_MAIN_CONNECT_DRIVERS, F("Submenu:ConnectDrivers")); - CASERETURN(MENU_MAIN_PRIMARY_AXIS_MOVES, F("Submenu:PrimaryAxisMoves")); - CASERETURN(MENU_MAIN_SECONDARY_AXIS_MOVES, F("Submenu:SecondaryAxisMoves")); - default: - return F("Unknown"); - } -} -TestMenuItem::TestMenuItem(menuText_t labelId, TestMenu *subMenu) -{ - _key = -1; - _label = getMenuLabel(labelId); - _action = getMenuAction(labelId); - _isSubMenu = subMenu != nullptr; - _subMenu = subMenu; -} - -void TestMenuItem::display() const -{ - Serial.print(" ["); - Serial.print(_key); - Serial.print("] "); - Serial.println(_label); -} - -int TestMenuItem::getKey() const -{ - return _key; -} - -void TestMenuItem::setKey(int key) -{ - _key = key; -} - -String TestMenuItem::getAction() const -{ - return _action; -} - -TestMenu *TestMenuItem::getSubMenu() const -{ - return _subMenu; -} - -void TestMenu::setParentMenu(TestMenu *parentMenu) -{ - _parentMenu = parentMenu; -} - -TestMenu::TestMenu(int level, String name, String parent, TestMenuItem *choices, int numChoices, TestMenu *parentMenu) -{ - _lastTick = 0; - _level = level; - _name = name; - _parent = parent; - _choices = choices; - _numChoices = numChoices; - _parentMenu = parentMenu; - _secondaryDistance = 1; - if (_currentMenu == nullptr) - { - _backItem = new TestMenuItem(MENU_BACK); - TestMenu::_backItem->setKey(0); - } - _currentMenu = this; // Set the last created menu as the current menu - for (int i = 0; i < _numChoices; i++) - { - if (_choices[i].getSubMenu() != nullptr) - { - _choices[i].getSubMenu()->setParentMenu(this); - } - } -} -String getComponent(const String &comp) -{ - MappedDict::DictEntry_t lookupTable[] = { - {F("AUTO_AZ_ALT"), F("AZ and ALT steppers (AutoPA)")}, - {F("AUTO_AZ"), F("AZ stepper")}, - {F("AUTO_ALT"), F("ALT stepper")}, - {F("GPS"), F("GPS receiver")}, - {F("GYRO"), F("Digital Level")}, - {F("LCD_KEYPAD"), F("LCD display and keypad")}, - {F("LCD_I2C_MCP23008"), F("LCD display (MCP23008)")}, - {F("LCD_I2C_MCP23017"), F("LCD display (MCP23017)")}, - {F("LCD_JOY_I2C_SSD1306"), F("LCD display (SSD1306) with joystick")}, - {F("INFO_I2C_SSD1306_128x64"), F("Info display (SSD1306)")}, - {F("INFO_UNKNOWN"), F("Info display (unknown type)")}, - {F("FOC"), F("Focuser stepper")}, - {F("HSAH"), F("RA Hall Sensor Auto-Homing")}, - {F("HSAV"), F("DEC Hall Sensor Auto-Homing")}, - {F("ENDSW_RA"), F("End switches on RA")}, - {F("ENDSW_DEC"), F("End switches on DEC")}, - {F("ENDSW_RA_DEC"), F("End switches on RA and DEC")}, - }; - auto driverLookup = MappedDict(lookupTable, ARRAY_SIZE(lookupTable)); - - String rtn; - if (driverLookup.tryGet(comp, &rtn)) - { - return rtn; - } - return F("Unknown component"); -} - -void printStepperInfo(StepperAxis axis, String info) -{ - String *splitInfo = splitStringBy(info, '|'); - String *stp = splitInfo; - Serial.println(axis == RA_STEPS ? "RA Info" : "DEC Info"); - Serial.println(F("--------")); - Serial.print(F(" Stepper type: ")); - Serial.println(*stp); - stp++; - Serial.print(F(" Gear: ")); - Serial.print(*stp); - Serial.println(F("-tooth")); - stp++; - if (*stp == "400") - { - Serial.println(F(" Resolution: 0.9 deg (400 steps/revolution)")); - } - else if (*stp == "200") - { - Serial.println(F(" Resolution: 1.8 deg (200 steps/revolution)")); - } - else - { - Serial.print(F(" Resolution: ")); - Serial.print(*stp); - Serial.println(F(" steps/revolution")); - } - Serial.print(F(" Slew Microsteps: ")); - Serial.println(axis == RA_STEPS ? RA_SLEW_MICROSTEPPING : DEC_SLEW_MICROSTEPPING); - if (axis == RA_STEPS) - { - Serial.print(F("Tracking Microsteps: ")); - Serial.println(RA_TRACKING_MICROSTEPPING); - Serial.print(F(" Tracking Speed: ")); - Serial.println(mount.getSpeed(TRACKING)); - } - else - { - Serial.print(F(" Guiding Microsteps: ")); - Serial.println(DEC_GUIDE_MICROSTEPPING); - } - - Serial.print(F(" Steps/degree: ")); - Serial.println(mount.getStepsPerDegree(axis)); - delete[] splitInfo; -} - -void TestMenu::listHardware() const -{ - Serial.println(F("Firmware is configured to support these hardware components:")); - String *hw = splitStringBy(mount.getMountHardwareInfo(), ','); - String *p = hw; - int index = 0; - Serial.print(F(" Mount: ")); - #ifdef OAM - Serial.println(F("OpenAstroMount (OAM)")); - #else - #ifdef OAE - Serial.println(F("OpenAstroExplorer (OAE)")); - #else - Serial.println(F("OpenAstroTracker (OAT)")); - #endif - #endif - - while (p->length() > 0) - { - switch (index) - { - case 0: - Serial.print(F(" Board: ")); - Serial.println(*p); - Serial.print(F(" Stepper library: ")); - #ifdef NEW_STEPPER_LIB - Serial.println(F("InterruptAccelStepper (new)")); - #else - Serial.println(F("AccelStepper (old)")); - #endif - break; - case 1: - printStepperInfo(RA_STEPS, *p); - break; - case 2: - printStepperInfo(DEC_STEPS, *p); - Serial.println(F("Add-Ons")); - Serial.println(F("--------")); - break; - default: - if (!p->startsWith("NO_")) - { - String component = getComponent(*p); - Serial.print(F(" Component: ")); - Serial.println(component); - } - break; - } - p++; - index++; - } - delete[] hw; -} - -void TestMenu::connectDriver(String axisStr) -{ - #if RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART || DEC_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART \ - || AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART || ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART \ - || FOCUS_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - uint16_t current = 0; - Serial.print(F("Connecting to ")); - Serial.print(axisStr); - Serial.print(F(" driver....")); - bool connected = mount.connectToDriver(axisStr, ¤t); - Serial.println(connected ? "OK" : "FAIL"); - if (connected) - { - Serial.print(F("Stepper is configured to use: ")); - Serial.println(String(current) + " mA"); - } - #else - Serial.print(F("ERROR: Can only connect to TMC2209 UART drivers.")); - #endif -} - -void TestMenu::onCommandReceived(String s) -{ - Serial.println(s); - if (s.startsWith(":") && s.endsWith("#")) - { - s = s.substring(0, s.length() - 1); - } - - String reply = MeadeCommandProcessor::instance()->processCommand(s); - - if (reply.length() > 0) - { - Serial.println(F("-- Command Response --------")); - Serial.println(reply); - Serial.println(F("----------------------------")); - } -} - -void TestMenu::onKeyPressed(int key) -{ - if ((key == TestMenu::_backItem->getKey()) && (_parentMenu)) - { - _currentMenu = _parentMenu; - _currentMenu->display(); - return; - } - - Serial.println(); - for (int i = 0; i < _numChoices; i++) - { - if (_choices[i].getKey() == key) - { - if (_choices[i].getAction().startsWith("Submenu:")) - { - _currentMenu = _choices[i].getSubMenu(); - _currentMenu->display(); - return; - } - String cmd = _choices[i].getAction(); - int sep = cmd.indexOf(':'); - String verb = cmd.substring(0, sep); - String action = cmd.substring(sep + 1); - String actionArg = ""; - int argSep = action.indexOf('|'); - if (argSep > 0) - { - actionArg = action.substring(argSep + 1); - action = action.substring(0, argSep); - } - if (verb == "Action") - { - if (action == F("ListHardware")) - { - listHardware(); - _currentMenu->display(); - } - else if (action.startsWith("Connect")) - { - connectDriver(actionArg); - } - else if (action == F("SetHome")) - { - mount.setHome(false); - _currentMenu->display(); - } - else if (action == F("GoHome")) - { - _startDEC = mount.getCurrentStepperPosition(DEC_STEPS); - _startRA = mount.getCurrentStepperPosition(RA_STEPS); - _targetDEC = 0; - _targetRA = 0; - mount.startSlewingToHome(); - _internalState |= (DISPLAY_RA | DISPLAY_DEC); - } - else if (action == F("SetSecDist")) - { - _secondaryDistance = actionArg.toFloat(); - _currentMenu->display(); - } - else if (action == F("MoveRAAxis")) - { - long stepsPerDegree = mount.getStepsPerDegree(RA_STEPS); - String output = F("Moving RA axis by 1hr (15 degrees, "); - output += stepsPerDegree * 15; - output += " steps) " + actionArg; - Serial.println(output); - TestMenu::_startRA = mount.getCurrentStepperPosition(RA_STEPS); - long steps = (actionArg == "CCW" ? -1 : 1) * stepsPerDegree * 15; - TestMenu::_targetRA = TestMenu::_startRA + steps; - mount.moveStepperBy(RA_STEPS, steps); - _internalState |= DISPLAY_RA; - } - else if (action == F("MoveDECAxis")) - { - long stepsPerDegree = mount.getStepsPerDegree(DEC_STEPS); - String output = F("Moving DEC axis by 15 degrees ("); - output += stepsPerDegree * 15; - output += " steps) " + actionArg; - Serial.println(output); - TestMenu::_startDEC = mount.getCurrentStepperPosition(DEC_STEPS); - long steps = (actionArg == "DOWN" ? -1 : 1) * stepsPerDegree * 15; - TestMenu::_targetDEC = TestMenu::_startDEC + steps; - mount.moveStepperBy(DEC_STEPS, steps); - _internalState |= DISPLAY_DEC; - } - #if AZ_STEPPER_TYPE != STEPPER_TYPE_NONE - else if (action == F("MoveAZAxis")) - { - String output = String(F("Moving AZ axis by ")) + String(_secondaryDistance, 1) + String(F(" arcMins (")); - output += String(AZIMUTH_STEPS_PER_ARC_MINUTE * _secondaryDistance, 0) + " steps) " + actionArg; - Serial.println(output); - float arcmins = actionArg == "LEFT" ? _secondaryDistance : -_secondaryDistance; - TestMenu::_startAZ = mount.getCurrentStepperPosition(AZIMUTH_STEPS); - TestMenu::_targetAZ = TestMenu::_startAZ + arcmins * AZIMUTH_STEPS_PER_ARC_MINUTE; - mount.moveBy(AZIMUTH_STEPS, arcmins); - _internalState |= DISPLAY_AZ; - } - #endif - #if ALT_STEPPER_TYPE != STEPPER_TYPE_NONE - else if (action == F("MoveALTAxis")) - { - String output = String(F("Moving ALT axis by ")) + String(_secondaryDistance, 1) + String(F(" arcMins (")); - output += String(ALTITUDE_STEPS_PER_ARC_MINUTE * _secondaryDistance, 0) + " steps) " + actionArg; - Serial.println(output); - float arcmins = actionArg == "UP" ? _secondaryDistance : -_secondaryDistance; - TestMenu::_startALT = mount.getCurrentStepperPosition(ALTITUDE_STEPS); - TestMenu::_targetALT = TestMenu::_startALT + arcmins * ALTITUDE_STEPS_PER_ARC_MINUTE; - mount.moveBy(ALTITUDE_STEPS, arcmins); - _internalState |= DISPLAY_ALT; - } - #endif - else if (action == F("ToggleTRK")) - { - if (mount.isSlewingTRK()) - { - mount.stopSlewing(TRACKING); - Serial.println(F("Tracking stopped.")); - } - else - { - mount.startSlewing(TRACKING); - Serial.println(F("Tracking started.")); - } - _currentMenu->display(); - } - else if (action == F("FactoryReset")) - { - mount.clearConfiguration(); - Serial.println(F("Mount reset, EEPROM erased.")); - _currentMenu->display(); - } - else if (action = F("PassthroughCmd")) - { - Serial.print(F("Enter LX200-OAT command to send to mount: ")); - TestMenu::setMenuState(testMenuState_t::WAITING_ON_COMMAND); - } - } - if (TestMenu::getMenuState() == testMenuState_t::CLEAR) - { - _currentMenu->display(); - } - return; - } - } - Serial.println(F("Invalid key pressed.")); - - _currentMenu->display(); -} - -void TestMenu::displayStepperPos() const -{ - char buffer[64]; - snprintf_P(buffer, - sizeof(buffer), - (const char *) F(" RA: %8ld%c ALT: %8ld%c TRK: %8ld%c"), - mount.getCurrentStepperPosition(RA_STEPS), - mount.isAxisRunning(RA_STEPS) ? '^' : ' ', - mount.getCurrentStepperPosition(ALTITUDE_STEPS), - mount.isAxisRunning(ALTITUDE_STEPS) ? '^' : ' ', - mount.getCurrentStepperPosition(TRACKING), - mount.isSlewingTRK() ? '^' : ' '); - Serial.println(buffer); - - snprintf_P(buffer, - sizeof(buffer), - (const char *) F(" DEC: %8ld%c AZ: %8ld%c FOC: %8ld%c"), - mount.getCurrentStepperPosition(DEC_STEPS), - mount.isAxisRunning(DEC_STEPS) ? '^' : ' ', - mount.getCurrentStepperPosition(AZIMUTH_STEPS), - mount.isAxisRunning(AZIMUTH_STEPS) ? '^' : ' ', - mount.getCurrentStepperPosition(FOCUS_STEPS), - mount.isAxisRunning(FOCUS_STEPS) ? '^' : ' '); - Serial.println(buffer); -} - -void TestMenu::display() const -{ - Serial.println(""); - - if (_level == 0) - { - Serial.println(F("**************************************")); - #ifdef OAM - Serial.println(F("*** OpenAstroMount (OAM) Test Menu ***")); - #else - #ifdef OAE - Serial.println(F("*** OpenAstroExplorer (OAE) Test Menu ***")); - #else - Serial.println(F("** OpenAstroTracker (OAT) Test Menu **")); - #endif - #endif - Serial.print(F("************* ")); - Serial.print(freeMemory()); - Serial.println(F(" bytes *************")); - displayStepperPos(); - Serial.println(F("**************************************")); - } - else - { - Serial.print(F("---------------- ")); - Serial.print(freeMemory()); - Serial.println(F(" bytes -------------")); - displayStepperPos(); - Serial.println(F("-----------------------------------------")); - Serial.print(" "); - Serial.print(_name); - Serial.println(F(" Menu")); - Serial.println(F("--------------------------")); - } - - for (int i = 0; i < _numChoices; i++) - { - _choices[i].setKey(i + 1); - _choices[i].display(); - } - - if (_parentMenu) - { - Serial.println(); - TestMenu::_backItem->display(); - } - Serial.print(F("Your choice:")); -} - -void TestMenu::tick() -{ - if (millis() > _lastTick + 250) - { - _lastTick = millis(); - if (_internalState != testMenuInternalState::IDLE) - { - if (_internalState & DISPLAY_RA) - { - Serial.print(F("RA : ")); - Serial.print(mount.getCurrentStepperPosition(RA_STEPS)); - Serial.print(" ("); - Serial.print(String(100.0 * (mount.getCurrentStepperPosition(RA_STEPS) - TestMenu::_startRA) - / (TestMenu::_targetRA - TestMenu::_startRA), - 0)); - Serial.print(F("%) ")); - if (!mount.isAxisRunning(RA_STEPS)) - { - _internalState = static_cast(static_cast(_internalState) & ~static_cast(DISPLAY_RA)); - } - } - - if (_internalState & DISPLAY_DEC) - { - Serial.print(F("DEC: ")); - Serial.print(mount.getCurrentStepperPosition(DEC_STEPS)); - Serial.print(" ("); - Serial.print(String(100.0 * (mount.getCurrentStepperPosition(DEC_STEPS) - TestMenu::_startDEC) - / (TestMenu::_targetDEC - TestMenu::_startDEC), - 0)); - Serial.print(F("%) ")); - if (!mount.isAxisRunning(DEC_STEPS)) - { - _internalState = static_cast(static_cast(_internalState) & ~static_cast(DISPLAY_DEC)); - } - } - - #if AZ_STEPPER_TYPE != STEPPER_TYPE_NONE - if (_internalState & DISPLAY_AZ) - { - Serial.print(F("AZ: ")); - Serial.print(mount.getCurrentStepperPosition(AZIMUTH_STEPS)); - Serial.print(" ("); - Serial.print(String(100.0 * (mount.getCurrentStepperPosition(AZIMUTH_STEPS) - TestMenu::_startAZ) - / (TestMenu::_targetAZ - TestMenu::_startAZ), - 0)); - Serial.print(F("%) ")); - if (!mount.isAxisRunning(AZIMUTH_STEPS)) - { - _internalState = static_cast(static_cast(_internalState) & ~static_cast(DISPLAY_AZ)); - } - } - #endif - - #if ALT_STEPPER_TYPE != STEPPER_TYPE_NONE - if (_internalState & DISPLAY_ALT) - { - Serial.print(F("ALT: ")); - Serial.print(mount.getCurrentStepperPosition(ALTITUDE_STEPS)); - Serial.print(" ("); - Serial.print(String(100.0 * (mount.getCurrentStepperPosition(ALTITUDE_STEPS) - TestMenu::_startALT) - / (TestMenu::_targetALT - TestMenu::_startALT), - 0)); - Serial.print(F("%) ")); - if (!mount.isAxisRunning(ALTITUDE_STEPS)) - { - _internalState = static_cast(static_cast(_internalState) & ~static_cast(DISPLAY_ALT)); - } - } - #endif - - Serial.println(); - - if (_internalState == testMenuInternalState::IDLE) - { - _currentMenu->display(); - } - } - } -} - -testMenuState_t TestMenu::getMenuState() -{ - return TestMenu::_menuState; -} - -void TestMenu::setMenuState(testMenuState_t state) -{ - TestMenu::_menuState = state; -} - -TestMenu *TestMenu::getCurrentMenu() -{ - return TestMenu::_currentMenu; -} - -#endif // TEST_VERIFY_MODE \ No newline at end of file diff --git a/src/testmenu.hpp b/src/testmenu.hpp deleted file mode 100644 index ead525cc..00000000 --- a/src/testmenu.hpp +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once -#include - -#if TEST_VERIFY_MODE == 1 - -enum menuText_t -{ - MENU_BACK, - MENU_CONNECT_RA, - MENU_CONNECT_DEC, - MENU_CONNECT_ALT, - MENU_CONNECT_AZ, - MENU_CONNECT_FOC, - MENU_PRIMARY_RA_CW, - MENU_PRIMARY_RA_CCW, - MENU_PRIMARY_DEC_UP, - MENU_PRIMARY_DEC_DOWN, - MENU_PRIMARY_SET_HOME, - MENU_PRIMARY_GO_HOME, - MENU_TOGGLE_TRK, - MENU_SECONDARY_RATE_1, - MENU_SECONDARY_RATE_2, - MENU_SECONDARY_RATE_3, - MENU_SECONDARY_RATE_4, - MENU_SECONDARY_RATE_5, - MENU_SECONDARY_ALT_UP, - MENU_SECONDARY_ALT_DOWN, - MENU_SECONDARY_AZ_LEFT, - MENU_SECONDARY_AZ_RIGHT, - MENU_FACTORY_RESET, - MENU_PASSTHROUGH_COMMAND, - MENU_MAIN_LIST_HARDWARE, - MENU_MAIN_CONNECT_DRIVERS, - MENU_MAIN_PRIMARY_AXIS_MOVES, - MENU_MAIN_SECONDARY_AXIS_MOVES, -}; - -enum testMenuState_t -{ - CLEAR, - WAITING_ON_INPUT, - WAITING_ON_COMMAND, -}; - -// Flag as to what to display to terminal -enum testMenuInternalState -{ - IDLE = 0, - DISPLAY_RA = 1 << 0, - DISPLAY_DEC = 1 << 1, - DISPLAY_AZ = 1 << 2, - DISPLAY_ALT = 1 << 3, -}; - -class TestMenu; - -class TestMenuItem -{ - int _key; - String _label; - String _action; - TestMenu *_subMenu; - bool _isSubMenu; - - public: - TestMenuItem(menuText_t labelId, TestMenu *subMenu = nullptr); - void display() const; - int getKey() const; - void setKey(int key); - String getAction() const; - TestMenu *getSubMenu() const; -}; - -class TestMenu -{ - int _level; - unsigned long _lastTick; - String _name; - String _parent; - TestMenuItem *_choices; - int _numChoices; - TestMenu *_parentMenu; - float _secondaryDistance; - - static long _targetRA; - static long _startRA; - static long _targetDEC; - static long _startDEC; - static long _startAZ; - static long _targetAZ; - static long _startALT; - static long _targetALT; - - static testMenuState_t _menuState; - static testMenuInternalState _internalState; - static TestMenu *_currentMenu; - static TestMenuItem *_backItem; - - public: - TestMenu(int level, String name, String parent, TestMenuItem *choices, int numChoices, TestMenu *parentMenu = nullptr); - void onKeyPressed(int key); - void onCommandReceived(String s); - void display() const; - void displayStepperPos() const; - void setParentMenu(TestMenu *parentMenu); - static TestMenu *getCurrentMenu(); - static testMenuState_t getMenuState(); - static void setMenuState(testMenuState_t state); - - void listHardware() const; - void connectDriver(String axisStr); - void tick(); -}; -#endif diff --git a/src/testmenudef.hpp b/src/testmenudef.hpp deleted file mode 100644 index cbf18526..00000000 --- a/src/testmenudef.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#if TEST_VERIFY_MODE == 1 - #include "testmenu.hpp" - -TestMenuItem connectMenuItems[] = { - #if RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - TestMenuItem(MENU_CONNECT_RA), - #endif - #if DEC_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - TestMenuItem(MENU_CONNECT_DEC), - #endif - #if ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - TestMenuItem(MENU_CONNECT_ALT), - #endif - #if AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - TestMenuItem(MENU_CONNECT_AZ), - #endif - #if FOCUS_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - TestMenuItem(MENU_CONNECT_FOC), - #endif -}; -TestMenu connectDriversMenu(1, "ConnectDrivers", "Main menu", connectMenuItems, sizeof(connectMenuItems) / sizeof(connectMenuItems[0])); - -TestMenuItem primaryAxisMenuItems[] = { - TestMenuItem(MENU_PRIMARY_RA_CW), - TestMenuItem(MENU_PRIMARY_RA_CCW), - TestMenuItem(MENU_PRIMARY_DEC_UP), - TestMenuItem(MENU_PRIMARY_DEC_DOWN), - TestMenuItem(MENU_PRIMARY_SET_HOME), - TestMenuItem(MENU_PRIMARY_GO_HOME), - TestMenuItem(MENU_TOGGLE_TRK), -}; -TestMenu primaryAxisMenu( - 1, "PrimaryAxisMoves", "Move Primary Axes", primaryAxisMenuItems, sizeof(primaryAxisMenuItems) / sizeof(primaryAxisMenuItems[0])); - -TestMenuItem secondaryAxisMenuItems[] = { - TestMenuItem(MENU_SECONDARY_RATE_1), - TestMenuItem(MENU_SECONDARY_RATE_2), - TestMenuItem(MENU_SECONDARY_RATE_3), - TestMenuItem(MENU_SECONDARY_RATE_4), - TestMenuItem(MENU_SECONDARY_RATE_5), - #if ALT_STEPPER_TYPE != STEPPER_TYPE_NONE - TestMenuItem(MENU_SECONDARY_ALT_UP), - TestMenuItem(MENU_SECONDARY_ALT_DOWN), - #endif - #if AZ_STEPPER_TYPE != STEPPER_TYPE_NONE - TestMenuItem(MENU_SECONDARY_AZ_LEFT), - TestMenuItem(MENU_SECONDARY_AZ_RIGHT), - #endif -}; -TestMenu secondaryAxisMenu(1, - "SecondaryAxisMoves", - "Move Secondary Axes", - secondaryAxisMenuItems, - sizeof(secondaryAxisMenuItems) / sizeof(secondaryAxisMenuItems[0])); - -TestMenuItem menuItems[] = { - TestMenuItem(MENU_MAIN_LIST_HARDWARE), - #if RA_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART || DEC_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART \ - || AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART || ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART \ - || FOCUS_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - TestMenuItem(MENU_MAIN_CONNECT_DRIVERS, &connectDriversMenu), - #endif - TestMenuItem(MENU_MAIN_PRIMARY_AXIS_MOVES, &primaryAxisMenu), - #if (AZ_STEPPER_TYPE != STEPPER_TYPE_NONE) || (ALT_STEPPER_TYPE != STEPPER_TYPE_NONE) - TestMenuItem(MENU_MAIN_SECONDARY_AXIS_MOVES, &secondaryAxisMenu), - #endif - TestMenuItem(MENU_PASSTHROUGH_COMMAND), - TestMenuItem(MENU_FACTORY_RESET), -}; - -TestMenu mainTestMenu(0, "OAT/OAM/OAE Testing menu", "", menuItems, sizeof(menuItems) / sizeof(menuItems[0])); -#endif \ No newline at end of file diff --git a/version_check.py b/version_check.py old mode 100755 new mode 100644