/**
   * M100 D
   *  Dump the free memory block from __brkval to the stack pointer.
   *  malloc() eats memory from the start of the block and the stack grows
   *  up from the bottom of the block. Solid test bytes indicate nothing has
   *  used that memory yet. There should not be anything but test bytes within
   *  the block. If so, it may indicate memory corruption due to a bad pointer.
   *  Unexpected bytes are flagged in the right column.
   */
  void dump_free_memory(const char *ptr, const char *sp) {
    //
    // Start and end the dump on a nice 16 byte boundary
    // (even though the values are not 16-byte aligned).
    //
    ptr = (char *)((uint16_t)ptr & 0xFFF0); // Align to 16-byte boundary
    sp  = (char *)((uint16_t)sp  | 0x000F); // Align sp to the 15th byte (at or above sp)

    // Dump command main loop
    while (ptr < sp) {
      print_hex_word((uint16_t)ptr);      // Print the address
      SERIAL_CHAR(':');
      for (uint8_t i = 0; i < 16; i++) {  // and 16 data bytes
        if (i == 8) SERIAL_CHAR('-');
        print_hex_byte(ptr[i]);
        SERIAL_CHAR(' ');
      }
      safe_delay(25);
      SERIAL_CHAR('|');                   // Point out non test bytes
      for (uint8_t i = 0; i < 16; i++) {
        char ccc = (char)ptr[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken
        if (&ptr[i] >= (const char*)command_queue && &ptr[i] < (const char*)(command_queue + sizeof(command_queue))) { // Print out ASCII in the command buffer area
          if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' ';
        }
        else { // If not in the command buffer area, flag bytes that don't match the test byte
          ccc = (ccc == TEST_BYTE) ? ' ' : '?';
        }
        SERIAL_CHAR(ccc);
      }
      SERIAL_EOL();
      ptr += 16;
      safe_delay(25);
      idle();
    }
  }
Beispiel #2
0
/**
 * M81: Turn off Power, including Power Supply, if there is one.
 *
 *      This code should ALWAYS be available for EMERGENCY SHUTDOWN!
 */
void GcodeSuite::M81() {
  thermalManager.disable_all_heaters();
  print_job_timer.stop();
  planner.finish_and_disable();

  #if FAN_COUNT > 0
    thermalManager.zero_fan_speeds();
    #if ENABLED(PROBING_FANS_OFF)
      thermalManager.fans_paused = false;
      ZERO(thermalManager.paused_fan_speed);
    #endif
  #endif

  safe_delay(1000); // Wait 1 second before switching off

  #if HAS_SUICIDE
    suicide();
  #elif HAS_POWER_SWITCH
    PSU_OFF();
  #endif

  #if HAS_LCD_MENU
    LCD_MESSAGEPGM(MACHINE_NAME " " MSG_OFF ".");
  #endif
}
Beispiel #3
0
 void unified_bed_leveling::report_state() {
   echo_name();
   SERIAL_PROTOCOLPGM(" System v" UBL_VERSION " ");
   if (!planner.leveling_active) SERIAL_PROTOCOLPGM("in");
   SERIAL_PROTOCOLLNPGM("active.");
   safe_delay(50);
 }
Beispiel #4
0
 inline void _move_nozzle_servo(const uint8_t e, const uint8_t angle_index) {
   constexpr int8_t  sns_index[2] = { SWITCHING_NOZZLE_SERVO_NR, SWITCHING_NOZZLE_E1_SERVO_NR };
   constexpr int16_t sns_angles[2] = SWITCHING_NOZZLE_SERVO_ANGLES;
   planner.synchronize();
   MOVE_SERVO(sns_index[e], sns_angles[angle_index]);
   safe_delay(500);
 }
Beispiel #5
0
  bool set_bltouch_deployed(const bool deploy) {
    if (deploy && TEST_BLTOUCH()) {      // If BL-Touch says it's triggered
      bltouch_command(BLTOUCH_RESET);    //  try to reset it.
      bltouch_command(BLTOUCH_DEPLOY);   // Also needs to deploy and stow to
      bltouch_command(BLTOUCH_STOW);     //  clear the triggered condition.
      safe_delay(1500);                  // Wait for internal self-test to complete.
                                         //  (Measured completion time was 0.65 seconds
                                         //   after reset, deploy, and stow sequence)
      if (TEST_BLTOUCH()) {              // If it still claims to be triggered...
        SERIAL_ERROR_START();
        SERIAL_ERRORLNPGM(MSG_STOP_BLTOUCH);
        stop();                          // punt!
        return true;
      }
    }

    bltouch_command(deploy ? BLTOUCH_DEPLOY : BLTOUCH_STOW);

    #if ENABLED(DEBUG_LEVELING_FEATURE)
      if (DEBUGGING(LEVELING)) {
        SERIAL_ECHOPAIR("set_bltouch_deployed(", deploy);
        SERIAL_CHAR(')');
        SERIAL_EOL();
      }
    #endif

    return false;
  }
int check_for_free_memory_corruption(const char * const title) {
  SERIAL_ECHO(title);

  char *ptr = END_OF_HEAP(), *sp = top_of_stack();
  int n = sp - ptr;

  SERIAL_ECHOPAIR("\nfmc() n=", n);
  SERIAL_ECHOPAIR("\n&__brkval: ", hex_address(&__brkval));
  SERIAL_ECHOPAIR("=",             hex_address(__brkval));
  SERIAL_ECHOPAIR("\n__bss_end: ", hex_address(&__bss_end));
  SERIAL_ECHOPAIR(" sp=",          hex_address(sp));

  if (sp < ptr)  {
    SERIAL_ECHOPGM(" sp < Heap ");
    // SET_INPUT_PULLUP(63);           // if the developer has a switch wired up to their controller board
    // safe_delay(5);                  // this code can be enabled to pause the display as soon as the
    // while ( READ(63))               // malfunction is detected.   It is currently defaulting to a switch
    //   idle();                       // being on pin-63 which is unassigend and available on most controller
    // safe_delay(20);                 // boards.
    // while ( !READ(63))
    //   idle();
    safe_delay(20);
    #ifdef M100_FREE_MEMORY_DUMPER
      M100_dump_routine("   Memory corruption detected with sp<Heap\n", (char*)0x1B80, (char*)0x21FF);
    #endif
  }

  // Scan through the range looking for the biggest block of 0xE5's we can find
  int block_cnt = 0;
  for (int i = 0; i < n; i++) {
    if (ptr[i] == TEST_BYTE) {
      int16_t j = count_test_bytes(ptr + i);
      if (j > 8) {
        // SERIAL_ECHOPAIR("Found ", j);
        // SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(ptr + i));
        i += j;
        block_cnt++;
        SERIAL_ECHOPAIR(" (", block_cnt);
        SERIAL_ECHOPAIR(") found=", j);
        SERIAL_ECHOPGM("   ");
      }
    }
  }
  SERIAL_ECHOPAIR("  block_found=", block_cnt);

  if (block_cnt != 1 || __brkval != 0x0000)
    SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");

  if (block_cnt == 0)       // Make sure the special case of no free blocks shows up as an
    block_cnt = -1;         // error to the calling code!

  SERIAL_ECHOPGM(" return=");
  if (block_cnt == 1) {
    SERIAL_CHAR('0');       // if the block_cnt is 1, nothing has broken up the free memory
    SERIAL_EOL();             // area and it is appropriate to say 'no corruption'.
    return 0;
  }
  SERIAL_ECHOLNPGM("true");
  return block_cnt;
}
Beispiel #7
0
void setup_neopixel() {
  SET_OUTPUT(NEOPIXEL_PIN);
  pixels.setBrightness(NEOPIXEL_BRIGHTNESS); // 0 - 255 range
  pixels.begin();
  pixels.show(); // initialize to all off

  #if ENABLED(NEOPIXEL_STARTUP_TEST)
    safe_delay(1000);
    set_neopixel_color(pixels.Color(255, 0, 0, 0));  // red
    safe_delay(1000);
    set_neopixel_color(pixels.Color(0, 255, 0, 0));  // green
    safe_delay(1000);
    set_neopixel_color(pixels.Color(0, 0, 255, 0));  // blue
    safe_delay(1000);
  #endif
  set_neopixel_color(pixels.Color(NEO_WHITE));       // white
}
Beispiel #8
0
 static void serial_echo_xy(const int16_t x, const int16_t y) {
   SERIAL_CHAR('(');
   SERIAL_ECHO(x);
   SERIAL_CHAR(',');
   SERIAL_ECHO(y);
   SERIAL_CHAR(')');
   safe_delay(10);
 }
Beispiel #9
0
 void move_extruder_servo(const uint8_t e) {
   planner.synchronize();
   #if EXTRUDERS & 1
     if (e < EXTRUDERS - 1)
   #endif
   {
     MOVE_SERVO(_SERVO_NR(e), servo_angles[_SERVO_NR(e)][e]);
     safe_delay(500);
   }
 }
Beispiel #10
0
  inline void home_z_safely() {

    // Disallow Z homing if X or Y are unknown
    if (!TEST(axis_known_position, X_AXIS) || !TEST(axis_known_position, Y_AXIS)) {
      LCD_MESSAGEPGM(MSG_ERR_Z_HOMING);
      SERIAL_ECHO_MSG(MSG_ERR_Z_HOMING);
      return;
    }

    #if ENABLED(DEBUG_LEVELING_FEATURE)
      if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("Z_SAFE_HOMING >>>");
    #endif

    sync_plan_position();

    /**
     * Move the Z probe (or just the nozzle) to the safe homing point
     */
    destination[X_AXIS] = Z_SAFE_HOMING_X_POINT;
    destination[Y_AXIS] = Z_SAFE_HOMING_Y_POINT;
    destination[Z_AXIS] = current_position[Z_AXIS]; // Z is already at the right height

    #if HOMING_Z_WITH_PROBE
      destination[X_AXIS] -= X_PROBE_OFFSET_FROM_EXTRUDER;
      destination[Y_AXIS] -= Y_PROBE_OFFSET_FROM_EXTRUDER;
    #endif

    if (position_is_reachable(destination[X_AXIS], destination[Y_AXIS])) {

      #if ENABLED(DEBUG_LEVELING_FEATURE)
        if (DEBUGGING(LEVELING)) DEBUG_POS("Z_SAFE_HOMING", destination);
      #endif

      // This causes the carriage on Dual X to unpark
      #if ENABLED(DUAL_X_CARRIAGE)
        active_extruder_parked = false;
      #endif

      #if ENABLED(SENSORLESS_HOMING)
        safe_delay(500); // Short delay needed to settle
      #endif

      do_blocking_move_to_xy(destination[X_AXIS], destination[Y_AXIS]);
      homeaxis(Z_AXIS);
    }
    else {
      LCD_MESSAGEPGM(MSG_ZPROBE_OUT);
      SERIAL_ECHO_MSG(MSG_ZPROBE_OUT);
    }

    #if ENABLED(DEBUG_LEVELING_FEATURE)
      if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< Z_SAFE_HOMING");
    #endif
  }
Beispiel #11
0
void Servo::move(const int value) {
  constexpr uint16_t servo_delay[] = SERVO_DELAY;
  static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");
  if (this->attach(0) >= 0) {
    this->write(value);
    safe_delay(servo_delay[this->servoIndex]);
    #if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
      this->detach();
    #endif
  }
}
Beispiel #12
0
 void probing_pause(const bool p) {
   #if ENABLED(PROBING_HEATERS_OFF)
     thermalManager.pause(p);
   #endif
   #if ENABLED(PROBING_FANS_OFF)
     fans_pause(p);
   #endif
   if (p) safe_delay(
     #if DELAY_BEFORE_PROBING > 25
       DELAY_BEFORE_PROBING
     #else
       25
     #endif
   );
 }
    /**
     * Detect ubl_lcd_clicked, debounce it, and return true for cancel
     */
    bool user_canceled() {
      if (!ubl_lcd_clicked()) return false;
      safe_delay(10);                       // Wait for click to settle

      #if ENABLED(ULTRA_LCD)
        lcd_setstatusPGM(PSTR("Mesh Validation Stopped."), 99);
        lcd_quick_feedback();
      #endif

      while (!ubl_lcd_clicked()) idle();    // Wait for button release

      // If the button is suddenly pressed again,
      // ask the user to resolve the issue
      lcd_setstatusPGM(PSTR("Release button"), 99); // will never appear...
      while (ubl_lcd_clicked()) idle();             // unless this loop happens
      lcd_reset_status();

      return true;
    }
Beispiel #14
0
 LOOP_L_N(f, COUNT(custom_bootscreen_animation)) {
   if (f) safe_delay(CUSTOM_BOOTSCREEN_FRAME_TIME);
   draw_custom_bootscreen((u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[f]), f == 0);
 }
Beispiel #15
0
 void bltouch_command(const int angle) {
   MOVE_SERVO(Z_ENDSTOP_SERVO_NR, angle);  // Give the BL-Touch the command and wait
   safe_delay(BLTOUCH_DELAY);
 }
Beispiel #16
0
  inline void switching_toolhead_tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool no_move/*=false*/) {
    if (no_move) return;

    constexpr uint16_t angles[2] = SWITCHING_TOOLHEAD_SERVO_ANGLES;

    const float toolheadposx[] = SWITCHING_TOOLHEAD_X_POS,
                placexpos = toolheadposx[active_extruder],
                grabxpos = toolheadposx[tmp_extruder];

    /**
     * 1. Raise Z to give enough clearance
     * 2. Move to switch position of current toolhead
     * 3. Unlock tool and drop it in the dock
     * 4. Move to the new toolhead
     * 5. Grab and lock the new toolhead
     */

    // 1. Raise Z to give enough clearance

    if (DEBUGGING(LEVELING)) DEBUG_POS("Starting Toolhead change", current_position);

    current_position[Z_AXIS] += toolchange_settings.z_raise;

    if (DEBUGGING(LEVELING)) DEBUG_POS("(1) Raise Z-Axis", current_position);

    fast_line_to_current(Z_AXIS);
    planner.synchronize();

    // 2. Move to switch position of current toolhead

    current_position[X_AXIS] = placexpos;

    if (DEBUGGING(LEVELING)) {
      DEBUG_ECHOLNPAIR("(2) Place old tool ", int(active_extruder));
      DEBUG_POS("Move X SwitchPos", current_position);
    }

    fast_line_to_current(X_AXIS);
    planner.synchronize();

    current_position[Y_AXIS] = SWITCHING_TOOLHEAD_Y_POS - SWITCHING_TOOLHEAD_Y_SECURITY;

    if (DEBUGGING(LEVELING)) DEBUG_POS("Move Y SwitchPos + Security", current_position);

    fast_line_to_current(Y_AXIS);
    planner.synchronize();

    // 3. Unlock tool and drop it in the dock

    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("(3) Unlock and Place Toolhead");

    MOVE_SERVO(SWITCHING_TOOLHEAD_SERVO_NR, angles[1]);
    safe_delay(500);

    current_position[Y_AXIS] = SWITCHING_TOOLHEAD_Y_POS;

    if (DEBUGGING(LEVELING)) DEBUG_POS("Move Y SwitchPos", current_position);

    planner.buffer_line(current_position,(planner.settings.max_feedrate_mm_s[Y_AXIS] * 0.5), active_extruder);
    planner.synchronize();
    safe_delay(200);
    current_position[Y_AXIS] -= SWITCHING_TOOLHEAD_Y_CLEAR;

    if (DEBUGGING(LEVELING)) DEBUG_POS("Move back Y clear", current_position);

    fast_line_to_current(Y_AXIS); // move away from docked toolhead
    planner.synchronize();

    // 4. Move to the new toolhead

    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("(4) Move to new toolhead position");

    current_position[X_AXIS] = grabxpos;

    if (DEBUGGING(LEVELING)) DEBUG_POS("Move to new toolhead X", current_position);

    fast_line_to_current(X_AXIS);
    planner.synchronize();
    current_position[Y_AXIS] = SWITCHING_TOOLHEAD_Y_POS - SWITCHING_TOOLHEAD_Y_SECURITY;

    if (DEBUGGING(LEVELING)) DEBUG_POS("Move Y SwitchPos + Security", current_position);

    fast_line_to_current(Y_AXIS);
    planner.synchronize();

    // 5. Grab and lock the new toolhead

    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("(5) Grab and lock new toolhead ");

    current_position[Y_AXIS] = SWITCHING_TOOLHEAD_Y_POS;

    if (DEBUGGING(LEVELING)) DEBUG_POS("Move Y SwitchPos", current_position);

    planner.buffer_line(current_position, planner.settings.max_feedrate_mm_s[Y_AXIS] * 0.5, active_extruder);
    planner.synchronize();

    safe_delay(200);
    MOVE_SERVO(SWITCHING_TOOLHEAD_SERVO_NR, angles[0]);
    safe_delay(500);

    current_position[Y_AXIS] -= SWITCHING_TOOLHEAD_Y_CLEAR;

    if (DEBUGGING(LEVELING)) DEBUG_POS("Move back Y clear", current_position);

    fast_line_to_current(Y_AXIS); // move away from docked toolhead
    planner.synchronize();

    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Toolhead change done.");
  }
Beispiel #17
0
 void move_nozzle_servo(const uint8_t angle_index) {
   planner.synchronize();
   MOVE_SERVO(SWITCHING_NOZZLE_SERVO_NR, servo_angles[SWITCHING_NOZZLE_SERVO_NR][e]);
   safe_delay(500);
 }
Beispiel #18
0
  void unified_bed_leveling::display_map(const int map_type) {
    constexpr uint8_t spaces = 8 * (GRID_MAX_POINTS_X - 2);

    SERIAL_PROTOCOLPGM("\nBed Topography Report");
    if (map_type == 0) {
      SERIAL_PROTOCOLPGM(":\n\n");
      serial_echo_xy(0, GRID_MAX_POINTS_Y - 1);
      SERIAL_ECHO_SP(spaces + 3);
      serial_echo_xy(GRID_MAX_POINTS_X - 1, GRID_MAX_POINTS_Y - 1);
      SERIAL_EOL();
      serial_echo_xy(MESH_MIN_X, MESH_MAX_Y);
      SERIAL_ECHO_SP(spaces);
      serial_echo_xy(MESH_MAX_X, MESH_MAX_Y);
      SERIAL_EOL();
    }
    else {
      SERIAL_PROTOCOLPGM(" for ");
      serialprintPGM(map_type == 1 ? PSTR("CSV:\n\n") : PSTR("LCD:\n\n"));
    }

    const float current_xi = get_cell_index_x(current_position[X_AXIS] + (MESH_X_DIST) / 2.0),
                current_yi = get_cell_index_y(current_position[Y_AXIS] + (MESH_Y_DIST) / 2.0);

    for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) {
      for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
        const bool is_current = i == current_xi && j == current_yi;

        // is the nozzle here? then mark the number
        if (map_type == 0) SERIAL_CHAR(is_current ? '[' : ' ');

        const float f = z_values[i][j];
        if (isnan(f)) {
          serialprintPGM(map_type == 0 ? PSTR("    .   ") : PSTR("NAN"));
        }
        else if (map_type <= 1) {
          // if we don't do this, the columns won't line up nicely
          if (map_type == 0 && f >= 0.0) SERIAL_CHAR(' ');
          SERIAL_PROTOCOL_F(f, 3);
        }
        idle();
        if (map_type == 1 && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR(',');

        #if TX_BUFFER_SIZE > 0
          MYSERIAL.flushTX();
        #endif
        safe_delay(15);
        if (map_type == 0) {
          SERIAL_CHAR(is_current ? ']' : ' ');
          SERIAL_CHAR(' ');
        }
      }
      SERIAL_EOL();
      if (j && map_type == 0) { // we want the (0,0) up tight against the block of numbers
        SERIAL_CHAR(' ');
        SERIAL_EOL();
      }
    }

    if (map_type == 0) {
      serial_echo_xy(MESH_MIN_X, MESH_MIN_Y);
      SERIAL_ECHO_SP(spaces + 4);
      serial_echo_xy(MESH_MAX_X, MESH_MIN_Y);
      SERIAL_EOL();
      serial_echo_xy(0, 0);
      SERIAL_ECHO_SP(spaces + 5);
      serial_echo_xy(GRID_MAX_POINTS_X - 1, 0);
      SERIAL_EOL();
    }
  }
Beispiel #19
0
// Output the contents of a file, first parameter is the filename, second is the limit ( in number of lines to output )
void SimpleShell::cat_command( string parameters, StreamOutput *stream )
{
    // Get parameters ( filename and line limit )
    string filename          = absolute_from_relative(shift_parameter( parameters ));
    string limit_parameter   = shift_parameter( parameters );
    int limit = -1;
    int delay= 0;
    bool send_eof= false;
    if ( limit_parameter == "-d" ) {
        string d= shift_parameter( parameters );
        char *e = NULL;
        delay = strtol(d.c_str(), &e, 10);
        if (e <= d.c_str()) {
            delay = 0;

        } else {
            send_eof= true; // we need to terminate file send with an eof
        }

    }else if ( limit_parameter != "" ) {
        char *e = NULL;
        limit = strtol(limit_parameter.c_str(), &e, 10);
        if (e <= limit_parameter.c_str())
            limit = -1;
    }

    // we have been asked to delay before cat, probably to allow time to issue upload command
    if(delay > 0) {
        safe_delay(delay*1000);
    }

    // Open file
    FILE *lp = fopen(filename.c_str(), "r");
    if (lp == NULL) {
        stream->printf("File not found: %s\r\n", filename.c_str());
        return;
    }
    string buffer;
    int c;
    int newlines = 0;
    int linecnt = 0;
    // Print each line of the file
    while ((c = fgetc (lp)) != EOF) {
        buffer.append((char *)&c, 1);
        if ( c == '\n' || ++linecnt > 80) {
            if(c == '\n') newlines++;
            stream->puts(buffer.c_str());
            buffer.clear();
            if(linecnt > 80) linecnt = 0;
            // we need to kick things or they die
            THEKERNEL->call_event(ON_IDLE);
        }
        if ( newlines == limit ) {
            break;
        }
    };
    fclose(lp);

    if(send_eof) {
        stream->puts("\032"); // ^Z terminates the upload
    }
}