🔥 Drop STM L64** drivers, STEVAL_3DP001V1 (#24427)
This commit is contained in:
		@@ -1,151 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | 
			
		||||
 *
 | 
			
		||||
 * Based on Sprinter and grbl.
 | 
			
		||||
 * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_L64XX
 | 
			
		||||
 | 
			
		||||
#include "../../gcode.h"
 | 
			
		||||
#include "../../../libs/L64XX/L64XX_Marlin.h"
 | 
			
		||||
#include "../../../module/stepper/indirection.h"
 | 
			
		||||
 | 
			
		||||
void echo_yes_no(const bool yes);
 | 
			
		||||
 | 
			
		||||
inline void L6470_say_status(const L64XX_axis_t axis) {
 | 
			
		||||
  if (L64xxManager.spi_abort) return;
 | 
			
		||||
  const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
 | 
			
		||||
  L64xxManager.get_status(axis);
 | 
			
		||||
  L64xxManager.say_axis(axis);
 | 
			
		||||
  #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
    char temp_buf[20];
 | 
			
		||||
    sprintf_P(temp_buf, PSTR("   status: %4x   "), sh.STATUS_AXIS_RAW);
 | 
			
		||||
    SERIAL_ECHO(temp_buf);
 | 
			
		||||
    print_bin(sh.STATUS_AXIS_RAW);
 | 
			
		||||
    switch (sh.STATUS_AXIS_LAYOUT) {
 | 
			
		||||
      case L6470_STATUS_LAYOUT: SERIAL_ECHOPGM("   L6470"); break;
 | 
			
		||||
      case L6474_STATUS_LAYOUT: SERIAL_ECHOPGM("   L6474"); break;
 | 
			
		||||
      case L6480_STATUS_LAYOUT: SERIAL_ECHOPGM("   L6480/powerSTEP01"); break;
 | 
			
		||||
    }
 | 
			
		||||
  #endif
 | 
			
		||||
  SERIAL_ECHOPGM("\n...OUTPUT: ");
 | 
			
		||||
  SERIAL_ECHOF(sh.STATUS_AXIS & STATUS_HIZ ? F("OFF") : F("ON "));
 | 
			
		||||
  SERIAL_ECHOPGM("   BUSY: "); echo_yes_no((sh.STATUS_AXIS & STATUS_BUSY) == 0);
 | 
			
		||||
  SERIAL_ECHOPGM("   DIR: ");
 | 
			
		||||
  SERIAL_ECHOF((((sh.STATUS_AXIS & STATUS_DIR) >> 4) ^ L64xxManager.index_to_dir[axis]) ? F("FORWARD") : F("REVERSE"));
 | 
			
		||||
  if (sh.STATUS_AXIS_LAYOUT == L6480_STATUS_LAYOUT) {
 | 
			
		||||
    SERIAL_ECHOPGM("   Last Command: ");
 | 
			
		||||
    if (sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD) SERIAL_ECHOPGM("VALID");
 | 
			
		||||
    else                                           SERIAL_ECHOPGM("ERROR");
 | 
			
		||||
    SERIAL_ECHOPGM("\n...THERMAL: ");
 | 
			
		||||
    switch ((sh.STATUS_AXIS & (sh.STATUS_AXIS_TH_SD | sh.STATUS_AXIS_TH_WRN)) >> 11) {
 | 
			
		||||
      case 0: SERIAL_ECHOPGM("DEVICE SHUTDOWN"); break;
 | 
			
		||||
      case 1: SERIAL_ECHOPGM("BRIDGE SHUTDOWN"); break;
 | 
			
		||||
      case 2: SERIAL_ECHOPGM("WARNING        "); break;
 | 
			
		||||
      case 3: SERIAL_ECHOPGM("OK             "); break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    SERIAL_ECHOPGM("   Last Command: ");
 | 
			
		||||
    if (!(sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD)) SERIAL_ECHOPGM("IN");
 | 
			
		||||
    SERIAL_ECHOPGM("VALID    ");
 | 
			
		||||
    SERIAL_ECHOF(sh.STATUS_AXIS & sh.STATUS_AXIS_NOTPERF_CMD ?  F("COMPLETED    ") : F("Not PERFORMED"));
 | 
			
		||||
    SERIAL_ECHOPGM("\n...THERMAL: ", !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_SD) ? "SHUTDOWN       " : !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_WRN) ? "WARNING        " : "OK             ");
 | 
			
		||||
  }
 | 
			
		||||
  SERIAL_ECHOPGM("   OVERCURRENT:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_OCD) == 0);
 | 
			
		||||
  if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) {
 | 
			
		||||
    SERIAL_ECHOPGM("   STALL:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_STEP_LOSS_A) == 0 || (sh.STATUS_AXIS & sh.STATUS_AXIS_STEP_LOSS_B) == 0);
 | 
			
		||||
    SERIAL_ECHOPGM("   STEP-CLOCK MODE:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_SCK_MOD) != 0);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    SERIAL_ECHOPGM("   STALL: NA "
 | 
			
		||||
                   "   STEP-CLOCK MODE: NA"
 | 
			
		||||
                   "   UNDER VOLTAGE LOCKOUT: "); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_UVLO) == 0);
 | 
			
		||||
  }
 | 
			
		||||
  SERIAL_EOL();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * M122: Debug L6470 drivers
 | 
			
		||||
 */
 | 
			
		||||
void GcodeSuite::M122() {
 | 
			
		||||
  L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
 | 
			
		||||
  L64xxManager.spi_active = true;   // Tell set_directions() a series of SPI transfers is underway
 | 
			
		||||
 | 
			
		||||
  //if (parser.seen('S'))
 | 
			
		||||
  //  tmc_set_report_interval(parser.value_bool());
 | 
			
		||||
  //else
 | 
			
		||||
 | 
			
		||||
  #if AXIS_IS_L64XX(X)
 | 
			
		||||
    L6470_say_status(X);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(X2)
 | 
			
		||||
    L6470_say_status(X2);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(Y)
 | 
			
		||||
    L6470_say_status(Y);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(Y2)
 | 
			
		||||
    L6470_say_status(Y2);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(Z)
 | 
			
		||||
    L6470_say_status(Z);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(Z2)
 | 
			
		||||
    L6470_say_status(Z2);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(Z3)
 | 
			
		||||
    L6470_say_status(Z3);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(Z4)
 | 
			
		||||
    L6470_say_status(Z4);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E0)
 | 
			
		||||
    L6470_say_status(E0);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E1)
 | 
			
		||||
    L6470_say_status(E1);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E2)
 | 
			
		||||
    L6470_say_status(E2);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E3)
 | 
			
		||||
    L6470_say_status(E3);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E4)
 | 
			
		||||
    L6470_say_status(E4);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E5)
 | 
			
		||||
    L6470_say_status(E5);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E6)
 | 
			
		||||
    L6470_say_status(E6);
 | 
			
		||||
  #endif
 | 
			
		||||
  #if AXIS_IS_L64XX(E7)
 | 
			
		||||
    L6470_say_status(E7);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  L64xxManager.spi_active = false;   // done with all SPI transfers - clear handshake flags
 | 
			
		||||
  L64xxManager.spi_abort = false;
 | 
			
		||||
  L64xxManager.pause_monitor(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // HAS_L64XX
 | 
			
		||||
@@ -1,417 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | 
			
		||||
 *
 | 
			
		||||
 * Based on Sprinter and grbl.
 | 
			
		||||
 * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_L64XX
 | 
			
		||||
 | 
			
		||||
#if AXIS_COLLISION('I')
 | 
			
		||||
  #error "M906 parameter 'I' collision with axis name."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "../../gcode.h"
 | 
			
		||||
#include "../../../libs/L64XX/L64XX_Marlin.h"
 | 
			
		||||
#include "../../../module/stepper/indirection.h"
 | 
			
		||||
#include "../../../module/planner.h"
 | 
			
		||||
 | 
			
		||||
#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
 | 
			
		||||
#include "../../../core/debug_out.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MACRO to fetch information on the items associated with current limiting
 | 
			
		||||
 * and maximum voltage output.
 | 
			
		||||
 *
 | 
			
		||||
 * L6470 can be setup to shutdown if either current threshold is exceeded.
 | 
			
		||||
 *
 | 
			
		||||
 * L6470 output current can not be set directly.  It is set indirectly by
 | 
			
		||||
 * setting the maximum effective output voltage.
 | 
			
		||||
 *
 | 
			
		||||
 *  Effective output voltage is set by PWM duty cycle.
 | 
			
		||||
 *
 | 
			
		||||
 *  Maximum effective output voltage is affected by MANY variables.  The main ones are:
 | 
			
		||||
 *    KVAL_HOLD
 | 
			
		||||
 *    KVAL_RUN
 | 
			
		||||
 *    KVAL_ACC
 | 
			
		||||
 *    KVAL_DEC
 | 
			
		||||
 *    Vs compensation (if enabled)
 | 
			
		||||
 */
 | 
			
		||||
void L64XX_report_current(L64XX &motor, const L64XX_axis_t axis) {
 | 
			
		||||
 | 
			
		||||
  if (L64xxManager.spi_abort) return;  // don't do anything if set_directions() has occurred
 | 
			
		||||
 | 
			
		||||
  const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
 | 
			
		||||
  const uint16_t status = L64xxManager.get_status(axis);    //also populates shadow structure
 | 
			
		||||
  const uint8_t OverCurrent_Threshold = uint8_t(motor.GetParam(L6470_OCD_TH));
 | 
			
		||||
 | 
			
		||||
  auto say_axis_status = [](const L64XX_axis_t axis, const uint16_t status) {
 | 
			
		||||
    L64xxManager.say_axis(axis);
 | 
			
		||||
    #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
      char tmp[10];
 | 
			
		||||
      sprintf_P(tmp, PSTR("%4x   "), status);
 | 
			
		||||
      DEBUG_ECHOPGM("   status: ", tmp);
 | 
			
		||||
      print_bin(status);
 | 
			
		||||
    #else
 | 
			
		||||
      UNUSED(status);
 | 
			
		||||
    #endif
 | 
			
		||||
    SERIAL_EOL();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  char temp_buf[10];
 | 
			
		||||
 | 
			
		||||
  switch (sh.STATUS_AXIS_LAYOUT) {
 | 
			
		||||
    case L6470_STATUS_LAYOUT:       // L6470
 | 
			
		||||
    case L6480_STATUS_LAYOUT: {     // L6480 & powerstep01
 | 
			
		||||
      const uint16_t Stall_Threshold = (uint8_t)motor.GetParam(L6470_STALL_TH),
 | 
			
		||||
                     motor_status = (status & (STATUS_MOT_STATUS)) >> 5,
 | 
			
		||||
                     L6470_ADC_out = motor.GetParam(L6470_ADC_OUT),
 | 
			
		||||
                     L6470_ADC_out_limited = constrain(L6470_ADC_out, 8, 24);
 | 
			
		||||
      const float comp_coef = 1600.0f / L6470_ADC_out_limited;
 | 
			
		||||
      const uint16_t MicroSteps = _BV(motor.GetParam(L6470_STEP_MODE) & 0x07);
 | 
			
		||||
 | 
			
		||||
      say_axis_status(axis, sh.STATUS_AXIS_RAW);
 | 
			
		||||
 | 
			
		||||
      SERIAL_ECHOPGM("...OverCurrent Threshold: ");
 | 
			
		||||
      sprintf_P(temp_buf, PSTR("%2d ("), OverCurrent_Threshold);
 | 
			
		||||
      SERIAL_ECHO(temp_buf);
 | 
			
		||||
      SERIAL_ECHO((OverCurrent_Threshold + 1) * motor.OCD_CURRENT_CONSTANT_INV);
 | 
			
		||||
      SERIAL_ECHOPGM(" mA)");
 | 
			
		||||
      SERIAL_ECHOPGM("   Stall Threshold: ");
 | 
			
		||||
      sprintf_P(temp_buf, PSTR("%2d ("), Stall_Threshold);
 | 
			
		||||
      SERIAL_ECHO(temp_buf);
 | 
			
		||||
      SERIAL_ECHO((Stall_Threshold + 1) * motor.STALL_CURRENT_CONSTANT_INV);
 | 
			
		||||
      SERIAL_ECHOPGM(" mA)");
 | 
			
		||||
      SERIAL_ECHOPGM("   Motor Status: ");
 | 
			
		||||
      switch (motor_status) {
 | 
			
		||||
        case 0: SERIAL_ECHOPGM("stopped"); break;
 | 
			
		||||
        case 1: SERIAL_ECHOPGM("accelerating"); break;
 | 
			
		||||
        case 2: SERIAL_ECHOPGM("decelerating"); break;
 | 
			
		||||
        case 3: SERIAL_ECHOPGM("at constant speed"); break;
 | 
			
		||||
      }
 | 
			
		||||
      SERIAL_EOL();
 | 
			
		||||
 | 
			
		||||
      SERIAL_ECHOPGM("...MicroSteps: ", MicroSteps,
 | 
			
		||||
                      "   ADC_OUT: ", L6470_ADC_out);
 | 
			
		||||
      SERIAL_ECHOPGM("   Vs_compensation: ");
 | 
			
		||||
      SERIAL_ECHOF((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_EN_VSCOMP) ? F("ENABLED ") : F("DISABLED"));
 | 
			
		||||
      SERIAL_ECHOLNPGM("   Compensation coefficient: ~", comp_coef * 0.01f);
 | 
			
		||||
 | 
			
		||||
      SERIAL_ECHOPGM("...KVAL_HOLD: ", motor.GetParam(L6470_KVAL_HOLD),
 | 
			
		||||
                      "   KVAL_RUN : ", motor.GetParam(L6470_KVAL_RUN),
 | 
			
		||||
                      "   KVAL_ACC: ", motor.GetParam(L6470_KVAL_ACC),
 | 
			
		||||
                      "   KVAL_DEC: ", motor.GetParam(L6470_KVAL_DEC),
 | 
			
		||||
                      "   V motor max = ");
 | 
			
		||||
      switch (motor_status) {
 | 
			
		||||
        case 0: SERIAL_ECHO(motor.GetParam(L6470_KVAL_HOLD) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_HOLD)"); break;
 | 
			
		||||
        case 1: SERIAL_ECHO(motor.GetParam(L6470_KVAL_RUN)  * 100 / 256); SERIAL_ECHOPGM("% (KVAL_RUN)"); break;
 | 
			
		||||
        case 2: SERIAL_ECHO(motor.GetParam(L6470_KVAL_ACC)  * 100 / 256); SERIAL_ECHOPGM("% (KVAL_ACC)"); break;
 | 
			
		||||
        case 3: SERIAL_ECHO(motor.GetParam(L6470_KVAL_DEC)  * 100 / 256); SERIAL_ECHOPGM("% (KVAL_HOLD)"); break;
 | 
			
		||||
      }
 | 
			
		||||
      SERIAL_EOL();
 | 
			
		||||
 | 
			
		||||
      #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
        DEBUG_ECHOPGM("...SLEW RATE: ");
 | 
			
		||||
        switch (sh.STATUS_AXIS_LAYOUT) {
 | 
			
		||||
          case L6470_STATUS_LAYOUT: {
 | 
			
		||||
            switch ((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT) {
 | 
			
		||||
              case 0: { DEBUG_ECHOLNPGM("320V/uS") ; break; }
 | 
			
		||||
              case 1: { DEBUG_ECHOLNPGM("75V/uS")  ; break; }
 | 
			
		||||
              case 2: { DEBUG_ECHOLNPGM("110V/uS") ; break; }
 | 
			
		||||
              case 3: { DEBUG_ECHOLNPGM("260V/uS") ; break; }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        case L6480_STATUS_LAYOUT: {
 | 
			
		||||
            switch (motor.GetParam(L6470_GATECFG1) & CONFIG1_SR ) {
 | 
			
		||||
              case CONFIG1_SR_220V_us: { DEBUG_ECHOLNPGM("220V/uS") ; break; }
 | 
			
		||||
              case CONFIG1_SR_400V_us: { DEBUG_ECHOLNPGM("400V/uS") ; break; }
 | 
			
		||||
              case CONFIG1_SR_520V_us: { DEBUG_ECHOLNPGM("520V/uS") ; break; }
 | 
			
		||||
              case CONFIG1_SR_980V_us: { DEBUG_ECHOLNPGM("980V/uS") ; break; }
 | 
			
		||||
              default: { DEBUG_ECHOLNPGM("unknown") ; break; }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      #endif
 | 
			
		||||
      SERIAL_EOL();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case L6474_STATUS_LAYOUT: {  // L6474
 | 
			
		||||
      const uint16_t L6470_ADC_out = motor.GetParam(L6470_ADC_OUT) & 0x1F,
 | 
			
		||||
                     L6474_TVAL_val = motor.GetParam(L6474_TVAL) & 0x7F;
 | 
			
		||||
 | 
			
		||||
      say_axis_status(axis, sh.STATUS_AXIS_RAW);
 | 
			
		||||
 | 
			
		||||
      SERIAL_ECHOPGM("...OverCurrent Threshold: ");
 | 
			
		||||
      sprintf_P(temp_buf, PSTR("%2d ("), OverCurrent_Threshold);
 | 
			
		||||
      SERIAL_ECHO(temp_buf);
 | 
			
		||||
      SERIAL_ECHO((OverCurrent_Threshold + 1) * motor.OCD_CURRENT_CONSTANT_INV);
 | 
			
		||||
      SERIAL_ECHOPGM(" mA)");
 | 
			
		||||
      SERIAL_ECHOPGM("   TVAL: ");
 | 
			
		||||
      sprintf_P(temp_buf, PSTR("%2d ("), L6474_TVAL_val);
 | 
			
		||||
      SERIAL_ECHO(temp_buf);
 | 
			
		||||
      SERIAL_ECHO((L6474_TVAL_val + 1) * motor.STALL_CURRENT_CONSTANT_INV);
 | 
			
		||||
      SERIAL_ECHOLNPGM(" mA)   Motor Status: NA");
 | 
			
		||||
 | 
			
		||||
      const uint16_t MicroSteps = _BV(motor.GetParam(L6470_STEP_MODE) & 0x07); //NOMORE(MicroSteps, 16);
 | 
			
		||||
      SERIAL_ECHOPGM("...MicroSteps: ", MicroSteps,
 | 
			
		||||
                      "   ADC_OUT: ", L6470_ADC_out);
 | 
			
		||||
 | 
			
		||||
      SERIAL_ECHOLNPGM("   Vs_compensation: NA\n");
 | 
			
		||||
      SERIAL_ECHOLNPGM("...KVAL_HOLD: NA"
 | 
			
		||||
                       "   KVAL_RUN : NA"
 | 
			
		||||
                       "   KVAL_ACC: NA"
 | 
			
		||||
                       "   KVAL_DEC: NA"
 | 
			
		||||
                       "   V motor max =  NA");
 | 
			
		||||
 | 
			
		||||
      #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
        DEBUG_ECHOPGM("...SLEW RATE: ");
 | 
			
		||||
        switch ((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT) {
 | 
			
		||||
          case 0:  DEBUG_ECHOLNPGM("320V/uS") ; break;
 | 
			
		||||
          case 1:  DEBUG_ECHOLNPGM("75V/uS")  ; break;
 | 
			
		||||
          case 2:  DEBUG_ECHOLNPGM("110V/uS") ; break;
 | 
			
		||||
          case 3:  DEBUG_ECHOLNPGM("260V/uS") ; break;
 | 
			
		||||
          default: DEBUG_ECHOLNPGM("slew rate: ", (motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT); break;
 | 
			
		||||
        }
 | 
			
		||||
      #endif
 | 
			
		||||
      SERIAL_EOL();
 | 
			
		||||
      SERIAL_EOL();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * M906: report or set KVAL_HOLD which sets the maximum effective voltage provided by the
 | 
			
		||||
 *       PWMs to the steppers
 | 
			
		||||
 *
 | 
			
		||||
 * On L6474 this sets the TVAL register (same address).
 | 
			
		||||
 *
 | 
			
		||||
 * I - select which driver(s) to change on multi-driver axis
 | 
			
		||||
 *         (default) all drivers on the axis
 | 
			
		||||
 *     0 - monitor only the first XYZ... driver
 | 
			
		||||
 *     1 - monitor only X2, Y2, Z2
 | 
			
		||||
 *     2 - monitor only Z3
 | 
			
		||||
 *     3 - monitor only Z4
 | 
			
		||||
 * Xxxx, Yxxx, Zxxx, Axxx, Bxxx, Cxxx, Uxxx, Vxxx, Wxxx, Exxx - axis to change (optional)
 | 
			
		||||
 *     L6474 - current in mA (4A max)
 | 
			
		||||
 *     All others - 0-255
 | 
			
		||||
 *
 | 
			
		||||
 * Sets KVAL_HOLD which affects the current being driven through the stepper.
 | 
			
		||||
 *
 | 
			
		||||
 * L6470 is used in the STEP-CLOCK mode.  KVAL_HOLD is the only KVAL_xxx
 | 
			
		||||
 * that affects the effective voltage seen by the stepper.
 | 
			
		||||
 */
 | 
			
		||||
void GcodeSuite::M906() {
 | 
			
		||||
 | 
			
		||||
  L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
 | 
			
		||||
 | 
			
		||||
  #define L6470_SET_KVAL_HOLD(Q) (AXIS_IS_L64XX(Q) ? stepper##Q.setTVALCurrent(value) : stepper##Q.SetParam(L6470_KVAL_HOLD, uint8_t(value)))
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM("M906");
 | 
			
		||||
 | 
			
		||||
  uint8_t report_current = true;
 | 
			
		||||
 | 
			
		||||
  #if AXIS_IS_L64XX(X2) || AXIS_IS_L64XX(Y2) || AXIS_IS_L64XX(Z2) || AXIS_IS_L64XX(Z3) || AXIS_IS_L64XX(Z4)
 | 
			
		||||
    const int8_t index = parser.byteval('I', -1);
 | 
			
		||||
  #else
 | 
			
		||||
    constexpr int8_t index = -1;
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(AXIS_CHAR(i))) {
 | 
			
		||||
 | 
			
		||||
    report_current = false;
 | 
			
		||||
 | 
			
		||||
    if (planner.has_blocks_queued() || planner.cleaning_buffer_counter) {
 | 
			
		||||
      SERIAL_ECHOLNPGM("Test aborted. Can't set KVAL_HOLD while steppers are moving.");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (i) {
 | 
			
		||||
      #if AXIS_IS_L64XX(X) || AXIS_IS_L64XX(X2)
 | 
			
		||||
        case X_AXIS:
 | 
			
		||||
          #if AXIS_IS_L64XX(X)
 | 
			
		||||
            if (index < 0 || index == 0) L6470_SET_KVAL_HOLD(X);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(X2)
 | 
			
		||||
            if (index < 0 || index == 1) L6470_SET_KVAL_HOLD(X2);
 | 
			
		||||
          #endif
 | 
			
		||||
          break;
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #if AXIS_IS_L64XX(Y) || AXIS_IS_L64XX(Y2)
 | 
			
		||||
        case Y_AXIS:
 | 
			
		||||
          #if AXIS_IS_L64XX(Y)
 | 
			
		||||
            if (index < 0 || index == 0) L6470_SET_KVAL_HOLD(Y);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(Y2)
 | 
			
		||||
            if (index < 0 || index == 1) L6470_SET_KVAL_HOLD(Y2);
 | 
			
		||||
          #endif
 | 
			
		||||
          break;
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #if AXIS_IS_L64XX(Z) || AXIS_IS_L64XX(Z2) || AXIS_IS_L64XX(Z3) || AXIS_IS_L64XX(Z4)
 | 
			
		||||
        case Z_AXIS:
 | 
			
		||||
          #if AXIS_IS_L64XX(Z)
 | 
			
		||||
            if (index < 0 || index == 0) L6470_SET_KVAL_HOLD(Z);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(Z2)
 | 
			
		||||
            if (index < 0 || index == 1) L6470_SET_KVAL_HOLD(Z2);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(Z3)
 | 
			
		||||
            if (index < 0 || index == 2) L6470_SET_KVAL_HOLD(Z3);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(Z4)
 | 
			
		||||
            if (index < 0 || index == 3) L6470_SET_KVAL_HOLD(Z4);
 | 
			
		||||
          #endif
 | 
			
		||||
          break;
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #if AXIS_IS_L64XX(I)
 | 
			
		||||
        case I_AXIS: L6470_SET_KVAL_HOLD(I); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #if AXIS_IS_L64XX(J)
 | 
			
		||||
        case J_AXIS: L6470_SET_KVAL_HOLD(J); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #if AXIS_IS_L64XX(K)
 | 
			
		||||
        case K_AXIS: L6470_SET_KVAL_HOLD(K); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #if AXIS_IS_L64XX(U)
 | 
			
		||||
        case U_AXIS: L6470_SET_KVAL_HOLD(U); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #if AXIS_IS_L64XX(V)
 | 
			
		||||
        case V_AXIS: L6470_SET_KVAL_HOLD(V); break;
 | 
			
		||||
      #endif
 | 
			
		||||
      #if AXIS_IS_L64XX(W)
 | 
			
		||||
        case W_AXIS: L6470_SET_KVAL_HOLD(W); break;
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #if AXIS_IS_L64XX(E0) || AXIS_IS_L64XX(E1) || AXIS_IS_L64XX(E2) || AXIS_IS_L64XX(E3) || AXIS_IS_L64XX(E4) || AXIS_IS_L64XX(E5) || AXIS_IS_L64XX(E6) || AXIS_IS_L64XX(E7)
 | 
			
		||||
        case E_AXIS: {
 | 
			
		||||
          const int8_t eindex = get_target_e_stepper_from_command(-2);
 | 
			
		||||
          #if AXIS_IS_L64XX(E0)
 | 
			
		||||
            if (eindex < 0 || eindex == 0) L6470_SET_KVAL_HOLD(E0);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(E1)
 | 
			
		||||
            if (eindex < 0 || eindex == 1) L6470_SET_KVAL_HOLD(E1);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(E2)
 | 
			
		||||
            if (eindex < 0 || eindex == 2) L6470_SET_KVAL_HOLD(E2);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(E3)
 | 
			
		||||
            if (eindex < 0 || eindex == 3) L6470_SET_KVAL_HOLD(E3);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(E4)
 | 
			
		||||
            if (eindex < 0 || eindex == 4) L6470_SET_KVAL_HOLD(E4);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(E5)
 | 
			
		||||
            if (eindex < 0 || eindex == 5) L6470_SET_KVAL_HOLD(E5);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(E6)
 | 
			
		||||
            if (eindex < 0 || eindex == 6) L6470_SET_KVAL_HOLD(E6);
 | 
			
		||||
          #endif
 | 
			
		||||
          #if AXIS_IS_L64XX(E7)
 | 
			
		||||
            if (eindex < 0 || eindex == 7) L6470_SET_KVAL_HOLD(E7);
 | 
			
		||||
          #endif
 | 
			
		||||
        } break;
 | 
			
		||||
      #endif
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (report_current) {
 | 
			
		||||
    #define L64XX_REPORT_CURRENT(Q) L64XX_report_current(stepper##Q, Q)
 | 
			
		||||
 | 
			
		||||
    L64xxManager.spi_active = true; // Tell set_directions() a series of SPI transfers is underway
 | 
			
		||||
 | 
			
		||||
    #if AXIS_IS_L64XX(X)
 | 
			
		||||
      L64XX_REPORT_CURRENT(X);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(X2)
 | 
			
		||||
      L64XX_REPORT_CURRENT(X2);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(Y)
 | 
			
		||||
      L64XX_REPORT_CURRENT(Y);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(Y2)
 | 
			
		||||
      L64XX_REPORT_CURRENT(Y2);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(Z)
 | 
			
		||||
      L64XX_REPORT_CURRENT(Z);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(Z2)
 | 
			
		||||
      L64XX_REPORT_CURRENT(Z2);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(Z3)
 | 
			
		||||
      L64XX_REPORT_CURRENT(Z3);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(Z4)
 | 
			
		||||
      L64XX_REPORT_CURRENT(Z4);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(I)
 | 
			
		||||
      L64XX_REPORT_CURRENT(I);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(J)
 | 
			
		||||
      L64XX_REPORT_CURRENT(J);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(K)
 | 
			
		||||
      L64XX_REPORT_CURRENT(K);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(U)
 | 
			
		||||
      L64XX_REPORT_CURRENT(U);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(V)
 | 
			
		||||
      L64XX_REPORT_CURRENT(V);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(W)
 | 
			
		||||
      L64XX_REPORT_CURRENT(W);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E0)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E0);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E1)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E1);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E2)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E2);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E3)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E3);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E4)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E4);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E5)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E5);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E6)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E6);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if AXIS_IS_L64XX(E7)
 | 
			
		||||
      L64XX_REPORT_CURRENT(E7);
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    L64xxManager.spi_active = false;   // done with all SPI transfers - clear handshake flags
 | 
			
		||||
    L64xxManager.spi_abort = false;
 | 
			
		||||
    L64xxManager.pause_monitor(false);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // HAS_L64XX
 | 
			
		||||
@@ -1,650 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | 
			
		||||
 *
 | 
			
		||||
 * Based on Sprinter and grbl.
 | 
			
		||||
 * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// NOTE: All tests assume each axis uses matching driver chips.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_L64XX
 | 
			
		||||
 | 
			
		||||
#include "../../gcode.h"
 | 
			
		||||
#include "../../../module/stepper/indirection.h"
 | 
			
		||||
#include "../../../module/planner.h"
 | 
			
		||||
#include "../../../libs/L64XX/L64XX_Marlin.h"
 | 
			
		||||
 | 
			
		||||
#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
 | 
			
		||||
#include "../../../core/debug_out.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * M916: increase KVAL_HOLD until get thermal warning
 | 
			
		||||
 *       NOTE - on L6474 it is TVAL that is used
 | 
			
		||||
 *
 | 
			
		||||
 * J - select which driver(s) to monitor on multi-driver axis
 | 
			
		||||
 *     0 - (default) monitor all drivers on the axis or E0
 | 
			
		||||
 *     1 - monitor only X, Y, Z, E1
 | 
			
		||||
 *     2 - monitor only X2, Y2, Z2, E2
 | 
			
		||||
 *     3 - monitor only Z3, E3
 | 
			
		||||
 *     4 - monitor only Z4, E4
 | 
			
		||||
 *
 | 
			
		||||
 * Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement
 | 
			
		||||
 *     xxx (1-255) is distance moved on either side of current position
 | 
			
		||||
 *
 | 
			
		||||
 * F - feedrate
 | 
			
		||||
 *     optional - will use default max feedrate from configuration.h if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * K - value for KVAL_HOLD (0 - 255) (ignored for L6474)
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * D - time (in seconds) to run each setting of KVAL_HOLD/TVAL
 | 
			
		||||
 *     optional - defaults to zero (runs each setting once)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This routine is also useful for determining the approximate KVAL_HOLD
 | 
			
		||||
 * where the stepper stops losing steps. The sound will get noticeably quieter
 | 
			
		||||
 * as it stops losing steps.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void GcodeSuite::M916() {
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM("M916");
 | 
			
		||||
 | 
			
		||||
  L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
 | 
			
		||||
 | 
			
		||||
  // Variables used by L64xxManager.get_user_input function - some may not be used
 | 
			
		||||
  char axis_mon[3][3] = { {"  "}, {"  "}, {"  "} };   // list of Axes to be monitored
 | 
			
		||||
  L64XX_axis_t axis_index[3];
 | 
			
		||||
  uint16_t axis_status[3];
 | 
			
		||||
  uint8_t driver_count = 1;
 | 
			
		||||
  float position_max;
 | 
			
		||||
  float position_min;
 | 
			
		||||
  float final_feedrate;
 | 
			
		||||
  uint8_t kval_hold;
 | 
			
		||||
  uint8_t OCD_TH_val = 0;
 | 
			
		||||
  uint8_t STALL_TH_val = 0;
 | 
			
		||||
  uint16_t over_current_threshold;
 | 
			
		||||
  constexpr uint8_t over_current_flag = false;  // M916 doesn't play with the overcurrent thresholds
 | 
			
		||||
 | 
			
		||||
  #define DRIVER_TYPE_L6474(Q) AXIS_DRIVER_TYPE_##Q(L6474)
 | 
			
		||||
 | 
			
		||||
  uint8_t j;   // general purpose counter
 | 
			
		||||
 | 
			
		||||
  if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold))
 | 
			
		||||
    return;  // quit if invalid user input
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM("feedrate = ", final_feedrate);
 | 
			
		||||
 | 
			
		||||
  planner.synchronize();                             // wait for all current movement commands to complete
 | 
			
		||||
 | 
			
		||||
  const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
 | 
			
		||||
  for (j = 0; j < driver_count; j++)
 | 
			
		||||
    L64xxManager.get_status(axis_index[j]);  // clear out any pre-existing error flags
 | 
			
		||||
 | 
			
		||||
  char temp_axis_string[] = " ";
 | 
			
		||||
  temp_axis_string[0] = axis_mon[0][0];  // need to have a string for use within sprintf format section
 | 
			
		||||
  char gcode_string[80];
 | 
			
		||||
  uint16_t status_composite = 0;
 | 
			
		||||
 | 
			
		||||
  uint16_t M91x_counter = kval_hold;
 | 
			
		||||
  uint16_t M91x_counter_max;
 | 
			
		||||
  if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) {
 | 
			
		||||
    M91x_counter_max = 128;  // TVAL is 7 bits
 | 
			
		||||
    LIMIT(M91x_counter, 0U, 127U);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    M91x_counter_max = 256;  // KVAL_HOLD is 8 bits
 | 
			
		||||
 | 
			
		||||
  uint8_t M91x_delay_s = parser.byteval('D');   // get delay in seconds
 | 
			
		||||
  millis_t M91x_delay_ms = SEC_TO_MS(M91x_delay_s * 60);
 | 
			
		||||
  millis_t M91x_delay_end;
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM(".\n.");
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
 | 
			
		||||
    if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT)
 | 
			
		||||
      DEBUG_ECHOLNPGM("TVAL current (mA) = ", (M91x_counter + 1) * sh.AXIS_STALL_CURRENT_CONSTANT_INV);        // report TVAL current for this run
 | 
			
		||||
    else
 | 
			
		||||
      DEBUG_ECHOLNPGM("kval_hold = ", M91x_counter);                                   // report KVAL_HOLD for this run
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j < driver_count; j++)
 | 
			
		||||
      L64xxManager.set_param(axis_index[j], L6470_KVAL_HOLD, M91x_counter);  //set KVAL_HOLD or TVAL (same register address)
 | 
			
		||||
 | 
			
		||||
    M91x_delay_end = millis() + M91x_delay_ms;
 | 
			
		||||
    do {
 | 
			
		||||
      // turn the motor(s) both directions
 | 
			
		||||
      sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate));
 | 
			
		||||
      process_subcommands_now(gcode_string);
 | 
			
		||||
 | 
			
		||||
      sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate));
 | 
			
		||||
      process_subcommands_now(gcode_string);
 | 
			
		||||
 | 
			
		||||
      // get the status after the motors have stopped
 | 
			
		||||
      planner.synchronize();
 | 
			
		||||
 | 
			
		||||
      status_composite = 0;    // clear out the old bits
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < driver_count; j++) {
 | 
			
		||||
        axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK;    // bits of interest are all active low
 | 
			
		||||
        status_composite |= axis_status[j] ;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (status_composite) break;
 | 
			
		||||
    } while (millis() < M91x_delay_end);
 | 
			
		||||
 | 
			
		||||
    if (status_composite) break;
 | 
			
		||||
 | 
			
		||||
    M91x_counter++;
 | 
			
		||||
 | 
			
		||||
  } while (!(status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)) && (M91x_counter < M91x_counter_max));
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM(".");
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
    if (status_composite) {
 | 
			
		||||
      L64xxManager.error_status_decode(status_composite, axis_index[0],
 | 
			
		||||
        sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
 | 
			
		||||
        sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
 | 
			
		||||
        sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
 | 
			
		||||
      DEBUG_ECHOLNPGM(".");
 | 
			
		||||
    }
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  if ((status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)))
 | 
			
		||||
    DEBUG_ECHOLNPGM(".\n.\nTest completed normally - Thermal warning/shutdown has occurred");
 | 
			
		||||
  else if (status_composite)
 | 
			
		||||
    DEBUG_ECHOLNPGM(".\n.\nTest completed abnormally - non-thermal error has occurred");
 | 
			
		||||
  else
 | 
			
		||||
    DEBUG_ECHOLNPGM(".\n.\nTest completed normally - Unable to get to thermal warning/shutdown");
 | 
			
		||||
 | 
			
		||||
  L64xxManager.pause_monitor(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * M917: Find minimum current thresholds
 | 
			
		||||
 *
 | 
			
		||||
 *   Decrease OCD current until overcurrent error
 | 
			
		||||
 *   Increase OCD until overcurrent error goes away
 | 
			
		||||
 *   Decrease stall threshold until stall (not done on L6474)
 | 
			
		||||
 *   Increase stall until stall error goes away (not done on L6474)
 | 
			
		||||
 *
 | 
			
		||||
 * J - select which driver(s) to monitor on multi-driver axis
 | 
			
		||||
 *     0 - (default) monitor all drivers on the axis or E0
 | 
			
		||||
 *     1 - monitor only X, Y, Z, E1
 | 
			
		||||
 *     2 - monitor only X2, Y2, Z2, E2
 | 
			
		||||
 * Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement
 | 
			
		||||
 *     xxx (1-255) is distance moved on either side of current position
 | 
			
		||||
 *
 | 
			
		||||
 * F - feedrate
 | 
			
		||||
 *     optional - will use default max feedrate from Configuration.h if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * I - starting over-current threshold
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 *     if there are multiple drivers on the axis then all will be set the same
 | 
			
		||||
 *
 | 
			
		||||
 * T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * K - value for KVAL_HOLD (0 - 255) (ignored for L6474)
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 */
 | 
			
		||||
void GcodeSuite::M917() {
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM("M917");
 | 
			
		||||
 | 
			
		||||
  L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
 | 
			
		||||
 | 
			
		||||
  char axis_mon[3][3] = { {"  "}, {"  "}, {"  "} };   // list of Axes to be monitored
 | 
			
		||||
  L64XX_axis_t axis_index[3];
 | 
			
		||||
  uint16_t axis_status[3];
 | 
			
		||||
  uint8_t driver_count = 1;
 | 
			
		||||
  float position_max;
 | 
			
		||||
  float position_min;
 | 
			
		||||
  float final_feedrate;
 | 
			
		||||
  uint8_t kval_hold;
 | 
			
		||||
  uint8_t OCD_TH_val = 0;
 | 
			
		||||
  uint8_t STALL_TH_val = 0;
 | 
			
		||||
  uint16_t over_current_threshold;
 | 
			
		||||
  constexpr uint8_t over_current_flag = true;
 | 
			
		||||
 | 
			
		||||
  uint8_t j;   // general purpose counter
 | 
			
		||||
 | 
			
		||||
  if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold))
 | 
			
		||||
    return;  // quit if invalid user input
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM("feedrate = ", final_feedrate);
 | 
			
		||||
 | 
			
		||||
  planner.synchronize();                             // wait for all current movement commands to complete
 | 
			
		||||
 | 
			
		||||
  const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
 | 
			
		||||
  for (j = 0; j < driver_count; j++)
 | 
			
		||||
    L64xxManager.get_status(axis_index[j]);  // clear error flags
 | 
			
		||||
  char temp_axis_string[] = " ";
 | 
			
		||||
  temp_axis_string[0] = axis_mon[0][0];   // need a sprintf format string
 | 
			
		||||
  char gcode_string[80];
 | 
			
		||||
  uint16_t status_composite = 0;
 | 
			
		||||
  uint8_t test_phase = 0;                 // 0 - decreasing OCD - exit when OCD warning occurs (ignore STALL)
 | 
			
		||||
                                          // 1 - increasing OCD - exit when OCD warning stops (ignore STALL)
 | 
			
		||||
                                          // 2 - OCD finalized - decreasing STALL - exit when STALL warning happens
 | 
			
		||||
                                          // 3 - OCD finalized - increasing STALL - exit when STALL warning stop
 | 
			
		||||
                                          // 4 - all testing completed
 | 
			
		||||
  DEBUG_ECHOPGM(".\n.\n.\nover_current threshold : ", (OCD_TH_val + 1) * 375);   // first status display
 | 
			
		||||
  DEBUG_ECHOPGM("  (OCD_TH:  : ", OCD_TH_val);
 | 
			
		||||
  if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) {
 | 
			
		||||
    DEBUG_ECHOPGM(")   Stall threshold: ", (STALL_TH_val + 1) * 31.25);
 | 
			
		||||
    DEBUG_ECHOPGM("  (STALL_TH: ", STALL_TH_val);
 | 
			
		||||
  }
 | 
			
		||||
  DEBUG_ECHOLNPGM(")");
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
 | 
			
		||||
    if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) DEBUG_ECHOPGM("STALL threshold : ", (STALL_TH_val + 1) * 31.25);
 | 
			
		||||
    DEBUG_ECHOLNPGM("   OCD threshold : ", (OCD_TH_val + 1) * 375);
 | 
			
		||||
 | 
			
		||||
    sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate));
 | 
			
		||||
    process_subcommands_now(gcode_string);
 | 
			
		||||
 | 
			
		||||
    sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate));
 | 
			
		||||
    process_subcommands_now(gcode_string);
 | 
			
		||||
 | 
			
		||||
    planner.synchronize();
 | 
			
		||||
 | 
			
		||||
    status_composite = 0;    // clear out the old bits
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j < driver_count; j++) {
 | 
			
		||||
      axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK;    // bits of interest are all active low
 | 
			
		||||
      status_composite |= axis_status[j];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (status_composite && (status_composite & sh.STATUS_AXIS_UVLO)) {
 | 
			
		||||
      DEBUG_ECHOLNPGM("Test aborted (Undervoltage lockout active)");
 | 
			
		||||
      #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
        for (j = 0; j < driver_count; j++) {
 | 
			
		||||
          if (j) DEBUG_ECHOPGM("...");
 | 
			
		||||
          L64xxManager.error_status_decode(axis_status[j], axis_index[j],
 | 
			
		||||
            sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
 | 
			
		||||
            sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
 | 
			
		||||
            sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
 | 
			
		||||
        }
 | 
			
		||||
      #endif
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)) {
 | 
			
		||||
      DEBUG_ECHOLNPGM("thermal problem - waiting for chip(s) to cool down ");
 | 
			
		||||
      uint16_t status_composite_temp = 0;
 | 
			
		||||
      uint8_t k = 0;
 | 
			
		||||
      do {
 | 
			
		||||
        k++;
 | 
			
		||||
        if (!(k % 4)) {
 | 
			
		||||
          kval_hold *= 0.95;
 | 
			
		||||
          DEBUG_EOL();
 | 
			
		||||
          DEBUG_ECHOLNPGM("Lowering KVAL_HOLD by about 5% to ", kval_hold);
 | 
			
		||||
          for (j = 0; j < driver_count; j++)
 | 
			
		||||
            L64xxManager.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
 | 
			
		||||
        }
 | 
			
		||||
        DEBUG_ECHOLNPGM(".");
 | 
			
		||||
        reset_stepper_timeout(); // keep steppers powered
 | 
			
		||||
        safe_delay(5000);
 | 
			
		||||
        status_composite_temp = 0;
 | 
			
		||||
        for (j = 0; j < driver_count; j++) {
 | 
			
		||||
          axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK;    // bits of interest are all active low
 | 
			
		||||
          status_composite_temp |= axis_status[j];
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      while (status_composite_temp & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD));
 | 
			
		||||
      DEBUG_EOL();
 | 
			
		||||
    }
 | 
			
		||||
    if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B | sh.STATUS_AXIS_OCD)) {
 | 
			
		||||
      switch (test_phase) {
 | 
			
		||||
 | 
			
		||||
        case 0: {
 | 
			
		||||
          if (status_composite & sh.STATUS_AXIS_OCD) {
 | 
			
		||||
            // phase 0 with OCD warning - time to go to next phase
 | 
			
		||||
            if (OCD_TH_val >= sh.AXIS_OCD_TH_MAX) {
 | 
			
		||||
              OCD_TH_val = sh.AXIS_OCD_TH_MAX;           // limit to max
 | 
			
		||||
              test_phase = 2;            // at highest value so skip phase 1
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E0A OCD at highest - skip to 2");
 | 
			
		||||
              DEBUG_ECHOLNPGM("OCD at highest - OCD finalized");
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
              OCD_TH_val++;              // normal exit to next phase
 | 
			
		||||
              test_phase = 1;            // setup for first pass of phase 1
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E0B - inc OCD  & go to 1");
 | 
			
		||||
              DEBUG_ECHOLNPGM("inc OCD");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else {  // phase 0 without OCD warning - keep on decrementing if can
 | 
			
		||||
            if (OCD_TH_val) {
 | 
			
		||||
              OCD_TH_val--;              // try lower value
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E0C - dec OCD");
 | 
			
		||||
              DEBUG_ECHOLNPGM("dec OCD");
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
              test_phase = 2;            // at lowest value without warning so skip phase 1
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E0D - OCD at latest - go to 2");
 | 
			
		||||
              DEBUG_ECHOLNPGM("OCD finalized");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case 1: {
 | 
			
		||||
          if (status_composite & sh.STATUS_AXIS_OCD) {
 | 
			
		||||
            // phase 1 with OCD warning - increment if can
 | 
			
		||||
            if (OCD_TH_val >= sh.AXIS_OCD_TH_MAX) {
 | 
			
		||||
              OCD_TH_val = sh.AXIS_OCD_TH_MAX;           // limit to max
 | 
			
		||||
              test_phase = 2;            // at highest value so go to next phase
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E1A - OCD at max - go to 2");
 | 
			
		||||
              DEBUG_ECHOLNPGM("OCD finalized");
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
              OCD_TH_val++;              // try a higher value
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E1B - inc OCD");
 | 
			
		||||
              DEBUG_ECHOLNPGM("inc OCD");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else { // phase 1 without OCD warning - normal exit to phase 2
 | 
			
		||||
            test_phase = 2;
 | 
			
		||||
            //DEBUG_ECHOLNPGM("LOGIC E1C - no OCD warning - go to 1");
 | 
			
		||||
            DEBUG_ECHOLNPGM("OCD finalized");
 | 
			
		||||
          }
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case 2: {
 | 
			
		||||
          if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) {  // skip all STALL_TH steps if L6474
 | 
			
		||||
            test_phase = 4;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
          if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B)) {
 | 
			
		||||
            // phase 2 with stall warning - time to go to next phase
 | 
			
		||||
            if (STALL_TH_val >= 127) {
 | 
			
		||||
              STALL_TH_val = 127;  // limit to max
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E2A - STALL warning, STALL at max, quit");
 | 
			
		||||
              DEBUG_ECHOLNPGM("finished - STALL at maximum value but still have stall warning");
 | 
			
		||||
              test_phase = 4;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
              test_phase = 3;              // normal exit to next phase (found failing value of STALL)
 | 
			
		||||
              STALL_TH_val++;              // setup for first pass of phase 3
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E2B - INC - STALL warning, inc Stall, go to 3");
 | 
			
		||||
              DEBUG_ECHOLNPGM("inc Stall");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else {  // phase 2 without stall warning - decrement if can
 | 
			
		||||
            if (STALL_TH_val) {
 | 
			
		||||
              STALL_TH_val--;              // try a lower value
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E2C - no STALL, dec STALL");
 | 
			
		||||
              DEBUG_ECHOLNPGM("dec STALL");
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
              DEBUG_ECHOLNPGM("finished - STALL at lowest value but still do NOT have stall warning");
 | 
			
		||||
              test_phase = 4;
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E2D - no STALL, at lowest so quit");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case 3: {
 | 
			
		||||
          if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) {  // skip all STALL_TH steps if L6474
 | 
			
		||||
            test_phase = 4;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
          if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B)) {
 | 
			
		||||
            // phase 3 with stall warning - increment if can
 | 
			
		||||
            if (STALL_TH_val >= 127) {
 | 
			
		||||
              STALL_TH_val = 127; // limit to max
 | 
			
		||||
              DEBUG_ECHOLNPGM("finished - STALL at maximum value but still have stall warning");
 | 
			
		||||
              test_phase = 4;
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E3A - STALL, at max so quit");
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
              STALL_TH_val++;              // still looking for passing value
 | 
			
		||||
              //DEBUG_ECHOLNPGM("LOGIC E3B - STALL, inc stall");
 | 
			
		||||
              DEBUG_ECHOLNPGM("inc stall");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else {  //phase 3 without stall warning  but have OCD warning
 | 
			
		||||
            DEBUG_ECHOLNPGM("Hardware problem - OCD warning without STALL warning");
 | 
			
		||||
            test_phase = 4;
 | 
			
		||||
            //DEBUG_ECHOLNPGM("LOGIC E3C - not STALLED, hardware problem (quit)");
 | 
			
		||||
          }
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      switch (test_phase) {
 | 
			
		||||
        case 0: { // phase 0 without OCD warning - keep on decrementing if can
 | 
			
		||||
          if (OCD_TH_val) {
 | 
			
		||||
            OCD_TH_val--;             // try lower value
 | 
			
		||||
            //DEBUG_ECHOLNPGM("LOGIC N0A - DEC OCD");
 | 
			
		||||
            DEBUG_ECHOLNPGM("DEC OCD");
 | 
			
		||||
          }
 | 
			
		||||
          else {
 | 
			
		||||
            test_phase = 2;           // at lowest value without warning so skip phase 1
 | 
			
		||||
            //DEBUG_ECHOLNPGM("LOGIC N0B - OCD at lowest (go to phase 2)");
 | 
			
		||||
            DEBUG_ECHOLNPGM("OCD finalized");
 | 
			
		||||
          }
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case 1: //DEBUG_ECHOLNPGM("LOGIC N1 (go directly to 2)"); // phase 1 without OCD warning - drop directly to phase 2
 | 
			
		||||
                DEBUG_ECHOLNPGM("OCD finalized");
 | 
			
		||||
 | 
			
		||||
        case 2: { // phase 2 without stall warning - keep on decrementing if can
 | 
			
		||||
          if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) {  // skip all STALL_TH steps if L6474
 | 
			
		||||
            test_phase = 4;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
          if (STALL_TH_val) {
 | 
			
		||||
            STALL_TH_val--;              // try a lower value (stay in phase 2)
 | 
			
		||||
            //DEBUG_ECHOLNPGM("LOGIC N2B - dec STALL");
 | 
			
		||||
            DEBUG_ECHOLNPGM("dec STALL");
 | 
			
		||||
          }
 | 
			
		||||
          else {
 | 
			
		||||
            DEBUG_ECHOLNPGM("finished - STALL at lowest value but still no stall warning");
 | 
			
		||||
            test_phase = 4;
 | 
			
		||||
            //DEBUG_ECHOLNPGM("LOGIC N2C - STALL at lowest (quit)");
 | 
			
		||||
          }
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case 3: {
 | 
			
		||||
          if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) {  // skip all STALL_TH steps if L6474
 | 
			
		||||
            test_phase = 4;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
          test_phase = 4;
 | 
			
		||||
           //DEBUG_ECHOLNPGM("LOGIC N3 - finished!");
 | 
			
		||||
           DEBUG_ECHOLNPGM("finished!");
 | 
			
		||||
        } break;  // phase 3 without any warnings - desired exit
 | 
			
		||||
      }  //
 | 
			
		||||
    }  // end of status checks
 | 
			
		||||
 | 
			
		||||
    if (test_phase != 4) {
 | 
			
		||||
      for (j = 0; j < driver_count; j++) {                       // update threshold(s)
 | 
			
		||||
        L64xxManager.set_param(axis_index[j], L6470_OCD_TH, OCD_TH_val);
 | 
			
		||||
        if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) L64xxManager.set_param(axis_index[j], L6470_STALL_TH, STALL_TH_val);
 | 
			
		||||
        if (L64xxManager.get_param(axis_index[j], L6470_OCD_TH) != OCD_TH_val) DEBUG_ECHOLNPGM("OCD mismatch");
 | 
			
		||||
        if ((L64xxManager.get_param(axis_index[j], L6470_STALL_TH) != STALL_TH_val) && (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT)) DEBUG_ECHOLNPGM("STALL mismatch");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  } while (test_phase != 4);
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM(".");
 | 
			
		||||
  if (status_composite) {
 | 
			
		||||
    #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
      for (j = 0; j < driver_count; j++) {
 | 
			
		||||
        if (j) DEBUG_ECHOPGM("...");
 | 
			
		||||
        L64xxManager.error_status_decode(axis_status[j], axis_index[j],
 | 
			
		||||
          sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
 | 
			
		||||
          sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
 | 
			
		||||
          sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
 | 
			
		||||
      }
 | 
			
		||||
      DEBUG_ECHOLNPGM(".");
 | 
			
		||||
    #endif
 | 
			
		||||
    DEBUG_ECHOLNPGM("Completed with errors");
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    DEBUG_ECHOLNPGM("Completed with no errors");
 | 
			
		||||
  DEBUG_ECHOLNPGM(".");
 | 
			
		||||
 | 
			
		||||
  L64xxManager.pause_monitor(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * M918: increase speed until error or max feedrate achieved (as shown in configuration.h))
 | 
			
		||||
 *
 | 
			
		||||
 * J - select which driver(s) to monitor on multi-driver axis
 | 
			
		||||
 *     0 - (default) monitor all drivers on the axis or E0
 | 
			
		||||
 *     1 - monitor only X, Y, Z, E1
 | 
			
		||||
 *     2 - monitor only X2, Y2, Z2, E2
 | 
			
		||||
 * Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement
 | 
			
		||||
 *     xxx (1-255) is distance moved on either side of current position
 | 
			
		||||
 *
 | 
			
		||||
 * I - over current threshold
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * K - value for KVAL_HOLD (0 - 255) (ignored for L6474)
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 *
 | 
			
		||||
 * M - value for microsteps (1 - 128) (optional)
 | 
			
		||||
 *     optional - will report current value from driver if not specified
 | 
			
		||||
 */
 | 
			
		||||
void GcodeSuite::M918() {
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM("M918");
 | 
			
		||||
 | 
			
		||||
  L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status
 | 
			
		||||
 | 
			
		||||
  char axis_mon[3][3] = { {"  "}, {"  "}, {"  "} };   // list of Axes to be monitored
 | 
			
		||||
  L64XX_axis_t axis_index[3];
 | 
			
		||||
  uint16_t axis_status[3];
 | 
			
		||||
  uint8_t driver_count = 1;
 | 
			
		||||
  float position_max, position_min;
 | 
			
		||||
  float final_feedrate;
 | 
			
		||||
  uint8_t kval_hold;
 | 
			
		||||
  uint8_t OCD_TH_val = 0;
 | 
			
		||||
  uint8_t STALL_TH_val = 0;
 | 
			
		||||
  uint16_t over_current_threshold;
 | 
			
		||||
  constexpr uint8_t over_current_flag = true;
 | 
			
		||||
 | 
			
		||||
  const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow;
 | 
			
		||||
 | 
			
		||||
  uint8_t j;   // general purpose counter
 | 
			
		||||
 | 
			
		||||
  if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold))
 | 
			
		||||
    return;  // quit if invalid user input
 | 
			
		||||
 | 
			
		||||
  L64xxManager.get_status(axis_index[0]); // populate shadow array
 | 
			
		||||
 | 
			
		||||
  uint8_t m_steps = parser.byteval('M');
 | 
			
		||||
 | 
			
		||||
  if (m_steps != 0) {
 | 
			
		||||
    LIMIT(m_steps, 1, sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT ? 16 : 128);  // L6474
 | 
			
		||||
 | 
			
		||||
    uint8_t stepVal;
 | 
			
		||||
    for (stepVal = 0; stepVal < 8; stepVal++) {  // convert to L64xx register value
 | 
			
		||||
      if (m_steps == 1) break;
 | 
			
		||||
      m_steps >>= 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT)
 | 
			
		||||
      stepVal |= 0x98;  // NO SYNC
 | 
			
		||||
    else
 | 
			
		||||
      stepVal |= (!SYNC_EN) | SYNC_SEL_1 | stepVal;
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j < driver_count; j++) {
 | 
			
		||||
      L64xxManager.set_param(axis_index[j], dSPIN_HARD_HIZ, 0);          // can't write STEP register if stepper being powered
 | 
			
		||||
                                                                         //   results in an extra NOOP being sent (data 00)
 | 
			
		||||
      L64xxManager.set_param(axis_index[j], L6470_STEP_MODE, stepVal);   // set microsteps
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  m_steps = L64xxManager.get_param(axis_index[0], L6470_STEP_MODE) & 0x07;   // get microsteps
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOLNPGM("Microsteps = ", _BV(m_steps));
 | 
			
		||||
  DEBUG_ECHOLNPGM("target (maximum) feedrate = ", final_feedrate);
 | 
			
		||||
 | 
			
		||||
  const float feedrate_inc = final_feedrate / 10,   // Start at 1/10 of max & go up by 1/10 per step
 | 
			
		||||
              fr_limit = final_feedrate * 0.99f;    // Rounding-safe comparison value
 | 
			
		||||
  float current_feedrate = 0;
 | 
			
		||||
 | 
			
		||||
  planner.synchronize();                            // Wait for moves to complete
 | 
			
		||||
 | 
			
		||||
  for (j = 0; j < driver_count; j++)
 | 
			
		||||
    L64xxManager.get_status(axis_index[j]);         // Clear error flags
 | 
			
		||||
 | 
			
		||||
  char temp_axis_string[2] = " ";
 | 
			
		||||
  temp_axis_string[0] = axis_mon[0][0];             // Need a sprintf format string
 | 
			
		||||
  //temp_axis_string[1] = '\n';
 | 
			
		||||
 | 
			
		||||
  char gcode_string[80];
 | 
			
		||||
  uint16_t status_composite = 0;
 | 
			
		||||
  DEBUG_ECHOLNPGM(".\n.\n.");                       // Make feedrate outputs easier to read
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
    current_feedrate += feedrate_inc;
 | 
			
		||||
    DEBUG_ECHOLNPGM("...feedrate = ", current_feedrate);
 | 
			
		||||
 | 
			
		||||
    sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(current_feedrate));
 | 
			
		||||
    process_subcommands_now(gcode_string);
 | 
			
		||||
 | 
			
		||||
    sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(current_feedrate));
 | 
			
		||||
    process_subcommands_now(gcode_string);
 | 
			
		||||
 | 
			
		||||
    planner.synchronize();
 | 
			
		||||
 | 
			
		||||
    for (j = 0; j < driver_count; j++) {
 | 
			
		||||
      axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & 0x0800;  // Bits of interest are all active LOW
 | 
			
		||||
      status_composite |= axis_status[j];
 | 
			
		||||
    }
 | 
			
		||||
    if (status_composite) break;              // Break on any error
 | 
			
		||||
  } while (current_feedrate < fr_limit);
 | 
			
		||||
 | 
			
		||||
  DEBUG_ECHOPGM("Completed with ");
 | 
			
		||||
  if (status_composite) {
 | 
			
		||||
    DEBUG_ECHOLNPGM("errors");
 | 
			
		||||
    #if ENABLED(L6470_CHITCHAT)
 | 
			
		||||
      for (j = 0; j < driver_count; j++) {
 | 
			
		||||
        if (j) DEBUG_ECHOPGM("...");
 | 
			
		||||
        L64xxManager.error_status_decode(axis_status[j], axis_index[j],
 | 
			
		||||
          sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN,
 | 
			
		||||
          sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B,
 | 
			
		||||
          sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT);
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    DEBUG_ECHOLNPGM("no errors");
 | 
			
		||||
 | 
			
		||||
  L64xxManager.pause_monitor(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // HAS_L64XX
 | 
			
		||||
		Reference in New Issue
	
	Block a user