|
@ -850,10 +850,6 @@ void servo_init() { |
|
|
*/ |
|
|
*/ |
|
|
STOW_Z_SERVO(); |
|
|
STOW_Z_SERVO(); |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#if HAS_BED_PROBE |
|
|
|
|
|
endstops.enable_z_probe(false); |
|
|
|
|
|
#endif |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/**
|
|
|
/**
|
|
@ -879,216 +875,6 @@ void servo_init() { |
|
|
|
|
|
|
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Marlin entry-point: Set up before the program loop |
|
|
|
|
|
* - Set up the kill pin, filament runout, power hold |
|
|
|
|
|
* - Start the serial port |
|
|
|
|
|
* - Print startup messages and diagnostics |
|
|
|
|
|
* - Get EEPROM or default settings |
|
|
|
|
|
* - Initialize managers for: |
|
|
|
|
|
* • temperature |
|
|
|
|
|
* • planner |
|
|
|
|
|
* • watchdog |
|
|
|
|
|
* • stepper |
|
|
|
|
|
* • photo pin |
|
|
|
|
|
* • servos |
|
|
|
|
|
* • LCD controller |
|
|
|
|
|
* • Digipot I2C |
|
|
|
|
|
* • Z probe sled |
|
|
|
|
|
* • status LEDs |
|
|
|
|
|
*/ |
|
|
|
|
|
void setup() { |
|
|
|
|
|
|
|
|
|
|
|
#ifdef DISABLE_JTAG |
|
|
|
|
|
// Disable JTAG on AT90USB chips to free up pins for IO
|
|
|
|
|
|
MCUCR = 0x80; |
|
|
|
|
|
MCUCR = 0x80; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(FILAMENT_RUNOUT_SENSOR) |
|
|
|
|
|
setup_filrunoutpin(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
setup_killpin(); |
|
|
|
|
|
|
|
|
|
|
|
setup_powerhold(); |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_STEPPER_RESET |
|
|
|
|
|
disableStepperDrivers(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
MYSERIAL.begin(BAUDRATE); |
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("start"); |
|
|
|
|
|
SERIAL_ECHO_START; |
|
|
|
|
|
|
|
|
|
|
|
// Check startup - does nothing if bootloader sets MCUSR to 0
|
|
|
|
|
|
byte mcu = MCUSR; |
|
|
|
|
|
if (mcu & 1) SERIAL_ECHOLNPGM(MSG_POWERUP); |
|
|
|
|
|
if (mcu & 2) SERIAL_ECHOLNPGM(MSG_EXTERNAL_RESET); |
|
|
|
|
|
if (mcu & 4) SERIAL_ECHOLNPGM(MSG_BROWNOUT_RESET); |
|
|
|
|
|
if (mcu & 8) SERIAL_ECHOLNPGM(MSG_WATCHDOG_RESET); |
|
|
|
|
|
if (mcu & 32) SERIAL_ECHOLNPGM(MSG_SOFTWARE_RESET); |
|
|
|
|
|
MCUSR = 0; |
|
|
|
|
|
|
|
|
|
|
|
SERIAL_ECHOPGM(MSG_MARLIN); |
|
|
|
|
|
SERIAL_ECHOLNPGM(" " SHORT_BUILD_VERSION); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef STRING_DISTRIBUTION_DATE |
|
|
|
|
|
#ifdef STRING_CONFIG_H_AUTHOR |
|
|
|
|
|
SERIAL_ECHO_START; |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_CONFIGURATION_VER); |
|
|
|
|
|
SERIAL_ECHOPGM(STRING_DISTRIBUTION_DATE); |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_AUTHOR); |
|
|
|
|
|
SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); |
|
|
|
|
|
SERIAL_ECHOPGM("Compiled: "); |
|
|
|
|
|
SERIAL_ECHOLNPGM(__DATE__); |
|
|
|
|
|
#endif // STRING_CONFIG_H_AUTHOR
|
|
|
|
|
|
#endif // STRING_DISTRIBUTION_DATE
|
|
|
|
|
|
|
|
|
|
|
|
SERIAL_ECHO_START; |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_FREE_MEMORY); |
|
|
|
|
|
SERIAL_ECHO(freeMemory()); |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES); |
|
|
|
|
|
SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE); |
|
|
|
|
|
|
|
|
|
|
|
// Send "ok" after commands by default
|
|
|
|
|
|
for (int8_t i = 0; i < BUFSIZE; i++) send_ok[i] = true; |
|
|
|
|
|
|
|
|
|
|
|
// Load data from EEPROM if available (or use defaults)
|
|
|
|
|
|
// This also updates variables in the planner, elsewhere
|
|
|
|
|
|
Config_RetrieveSettings(); |
|
|
|
|
|
|
|
|
|
|
|
// Initialize current position based on home_offset
|
|
|
|
|
|
memcpy(current_position, home_offset, sizeof(home_offset)); |
|
|
|
|
|
|
|
|
|
|
|
// Vital to init stepper/planner equivalent for current_position
|
|
|
|
|
|
SYNC_PLAN_POSITION_KINEMATIC(); |
|
|
|
|
|
|
|
|
|
|
|
thermalManager.init(); // Initialize temperature loop
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(USE_WATCHDOG) |
|
|
|
|
|
watchdog_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
stepper.init(); // Initialize stepper, this enables interrupts!
|
|
|
|
|
|
setup_photpin(); |
|
|
|
|
|
servo_init(); |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_CONTROLLERFAN |
|
|
|
|
|
SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_STEPPER_RESET |
|
|
|
|
|
enableStepperDrivers(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DIGIPOT_I2C) |
|
|
|
|
|
digipot_i2c_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DAC_STEPPER_CURRENT) |
|
|
|
|
|
dac_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(Z_PROBE_SLED) && PIN_EXISTS(SLED) |
|
|
|
|
|
pinMode(SLED_PIN, OUTPUT); |
|
|
|
|
|
digitalWrite(SLED_PIN, LOW); // turn it off
|
|
|
|
|
|
#endif // Z_PROBE_SLED
|
|
|
|
|
|
|
|
|
|
|
|
setup_homepin(); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef STAT_LED_RED |
|
|
|
|
|
pinMode(STAT_LED_RED, OUTPUT); |
|
|
|
|
|
digitalWrite(STAT_LED_RED, LOW); // turn it off
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef STAT_LED_BLUE |
|
|
|
|
|
pinMode(STAT_LED_BLUE, OUTPUT); |
|
|
|
|
|
digitalWrite(STAT_LED_BLUE, LOW); // turn it off
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
lcd_init(); |
|
|
|
|
|
#if ENABLED(SHOW_BOOTSCREEN) |
|
|
|
|
|
#if ENABLED(DOGLCD) |
|
|
|
|
|
safe_delay(BOOTSCREEN_TIMEOUT); |
|
|
|
|
|
#elif ENABLED(ULTRA_LCD) |
|
|
|
|
|
bootscreen(); |
|
|
|
|
|
lcd_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1 |
|
|
|
|
|
// Initialize mixing to 100% color 1
|
|
|
|
|
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++) |
|
|
|
|
|
mixing_factor[i] = (i == 0) ? 1 : 0; |
|
|
|
|
|
for (uint8_t t = 0; t < MIXING_VIRTUAL_TOOLS; t++) |
|
|
|
|
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++) |
|
|
|
|
|
mixing_virtual_tool_mix[t][i] = mixing_factor[i]; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0 |
|
|
|
|
|
i2c.onReceive(i2c_on_receive); |
|
|
|
|
|
i2c.onRequest(i2c_on_request); |
|
|
|
|
|
#endif |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* The main Marlin program loop |
|
|
|
|
|
* |
|
|
|
|
|
* - Save or log commands to SD |
|
|
|
|
|
* - Process available commands (if not saving) |
|
|
|
|
|
* - Call heater manager |
|
|
|
|
|
* - Call inactivity manager |
|
|
|
|
|
* - Call endstop manager |
|
|
|
|
|
* - Call LCD update |
|
|
|
|
|
*/ |
|
|
|
|
|
void loop() { |
|
|
|
|
|
if (commands_in_queue < BUFSIZE) get_available_commands(); |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(SDSUPPORT) |
|
|
|
|
|
card.checkautostart(false); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if (commands_in_queue) { |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(SDSUPPORT) |
|
|
|
|
|
|
|
|
|
|
|
if (card.saving) { |
|
|
|
|
|
char* command = command_queue[cmd_queue_index_r]; |
|
|
|
|
|
if (strstr_P(command, PSTR("M29"))) { |
|
|
|
|
|
// M29 closes the file
|
|
|
|
|
|
card.closefile(); |
|
|
|
|
|
SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED); |
|
|
|
|
|
ok_to_send(); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
// Write the string from the read buffer to SD
|
|
|
|
|
|
card.write_command(command); |
|
|
|
|
|
if (card.logging) |
|
|
|
|
|
process_next_command(); // The card is saving because it's logging
|
|
|
|
|
|
else |
|
|
|
|
|
ok_to_send(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
process_next_command(); |
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
process_next_command(); |
|
|
|
|
|
|
|
|
|
|
|
#endif // SDSUPPORT
|
|
|
|
|
|
|
|
|
|
|
|
// The queue may be reset by a command handler or by code invoked by idle() within a handler
|
|
|
|
|
|
if (commands_in_queue) { |
|
|
|
|
|
--commands_in_queue; |
|
|
|
|
|
cmd_queue_index_r = (cmd_queue_index_r + 1) % BUFSIZE; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
endstops.report_state(); |
|
|
|
|
|
idle(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void gcode_line_error(const char* err, bool doFlush = true) { |
|
|
void gcode_line_error(const char* err, bool doFlush = true) { |
|
|
SERIAL_ERROR_START; |
|
|
SERIAL_ERROR_START; |
|
|
serialprintPGM(err); |
|
|
serialprintPGM(err); |
|
@ -8889,3 +8675,217 @@ void calculate_volumetric_multipliers() { |
|
|
for (uint8_t i = 0; i < COUNT(filament_size); i++) |
|
|
for (uint8_t i = 0; i < COUNT(filament_size); i++) |
|
|
volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]); |
|
|
volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Marlin entry-point: Set up before the program loop |
|
|
|
|
|
* - Set up the kill pin, filament runout, power hold |
|
|
|
|
|
* - Start the serial port |
|
|
|
|
|
* - Print startup messages and diagnostics |
|
|
|
|
|
* - Get EEPROM or default settings |
|
|
|
|
|
* - Initialize managers for: |
|
|
|
|
|
* • temperature |
|
|
|
|
|
* • planner |
|
|
|
|
|
* • watchdog |
|
|
|
|
|
* • stepper |
|
|
|
|
|
* • photo pin |
|
|
|
|
|
* • servos |
|
|
|
|
|
* • LCD controller |
|
|
|
|
|
* • Digipot I2C |
|
|
|
|
|
* • Z probe sled |
|
|
|
|
|
* • status LEDs |
|
|
|
|
|
*/ |
|
|
|
|
|
void setup() { |
|
|
|
|
|
|
|
|
|
|
|
#ifdef DISABLE_JTAG |
|
|
|
|
|
// Disable JTAG on AT90USB chips to free up pins for IO
|
|
|
|
|
|
MCUCR = 0x80; |
|
|
|
|
|
MCUCR = 0x80; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(FILAMENT_RUNOUT_SENSOR) |
|
|
|
|
|
setup_filrunoutpin(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
setup_killpin(); |
|
|
|
|
|
|
|
|
|
|
|
setup_powerhold(); |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_STEPPER_RESET |
|
|
|
|
|
disableStepperDrivers(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
MYSERIAL.begin(BAUDRATE); |
|
|
|
|
|
SERIAL_PROTOCOLLNPGM("start"); |
|
|
|
|
|
SERIAL_ECHO_START; |
|
|
|
|
|
|
|
|
|
|
|
// Check startup - does nothing if bootloader sets MCUSR to 0
|
|
|
|
|
|
byte mcu = MCUSR; |
|
|
|
|
|
if (mcu & 1) SERIAL_ECHOLNPGM(MSG_POWERUP); |
|
|
|
|
|
if (mcu & 2) SERIAL_ECHOLNPGM(MSG_EXTERNAL_RESET); |
|
|
|
|
|
if (mcu & 4) SERIAL_ECHOLNPGM(MSG_BROWNOUT_RESET); |
|
|
|
|
|
if (mcu & 8) SERIAL_ECHOLNPGM(MSG_WATCHDOG_RESET); |
|
|
|
|
|
if (mcu & 32) SERIAL_ECHOLNPGM(MSG_SOFTWARE_RESET); |
|
|
|
|
|
MCUSR = 0; |
|
|
|
|
|
|
|
|
|
|
|
SERIAL_ECHOPGM(MSG_MARLIN); |
|
|
|
|
|
SERIAL_ECHOLNPGM(" " SHORT_BUILD_VERSION); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef STRING_DISTRIBUTION_DATE |
|
|
|
|
|
#ifdef STRING_CONFIG_H_AUTHOR |
|
|
|
|
|
SERIAL_ECHO_START; |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_CONFIGURATION_VER); |
|
|
|
|
|
SERIAL_ECHOPGM(STRING_DISTRIBUTION_DATE); |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_AUTHOR); |
|
|
|
|
|
SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); |
|
|
|
|
|
SERIAL_ECHOPGM("Compiled: "); |
|
|
|
|
|
SERIAL_ECHOLNPGM(__DATE__); |
|
|
|
|
|
#endif // STRING_CONFIG_H_AUTHOR
|
|
|
|
|
|
#endif // STRING_DISTRIBUTION_DATE
|
|
|
|
|
|
|
|
|
|
|
|
SERIAL_ECHO_START; |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_FREE_MEMORY); |
|
|
|
|
|
SERIAL_ECHO(freeMemory()); |
|
|
|
|
|
SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES); |
|
|
|
|
|
SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE); |
|
|
|
|
|
|
|
|
|
|
|
// Send "ok" after commands by default
|
|
|
|
|
|
for (int8_t i = 0; i < BUFSIZE; i++) send_ok[i] = true; |
|
|
|
|
|
|
|
|
|
|
|
// Load data from EEPROM if available (or use defaults)
|
|
|
|
|
|
// This also updates variables in the planner, elsewhere
|
|
|
|
|
|
Config_RetrieveSettings(); |
|
|
|
|
|
|
|
|
|
|
|
// Initialize current position based on home_offset
|
|
|
|
|
|
memcpy(current_position, home_offset, sizeof(home_offset)); |
|
|
|
|
|
|
|
|
|
|
|
// Vital to init stepper/planner equivalent for current_position
|
|
|
|
|
|
SYNC_PLAN_POSITION_KINEMATIC(); |
|
|
|
|
|
|
|
|
|
|
|
thermalManager.init(); // Initialize temperature loop
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(USE_WATCHDOG) |
|
|
|
|
|
watchdog_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
stepper.init(); // Initialize stepper, this enables interrupts!
|
|
|
|
|
|
setup_photpin(); |
|
|
|
|
|
servo_init(); |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_BED_PROBE |
|
|
|
|
|
endstops.enable_z_probe(false); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_CONTROLLERFAN |
|
|
|
|
|
SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_STEPPER_RESET |
|
|
|
|
|
enableStepperDrivers(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DIGIPOT_I2C) |
|
|
|
|
|
digipot_i2c_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DAC_STEPPER_CURRENT) |
|
|
|
|
|
dac_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(Z_PROBE_SLED) && PIN_EXISTS(SLED) |
|
|
|
|
|
pinMode(SLED_PIN, OUTPUT); |
|
|
|
|
|
digitalWrite(SLED_PIN, LOW); // turn it off
|
|
|
|
|
|
#endif // Z_PROBE_SLED
|
|
|
|
|
|
|
|
|
|
|
|
setup_homepin(); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef STAT_LED_RED |
|
|
|
|
|
pinMode(STAT_LED_RED, OUTPUT); |
|
|
|
|
|
digitalWrite(STAT_LED_RED, LOW); // turn it off
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef STAT_LED_BLUE |
|
|
|
|
|
pinMode(STAT_LED_BLUE, OUTPUT); |
|
|
|
|
|
digitalWrite(STAT_LED_BLUE, LOW); // turn it off
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
lcd_init(); |
|
|
|
|
|
#if ENABLED(SHOW_BOOTSCREEN) |
|
|
|
|
|
#if ENABLED(DOGLCD) |
|
|
|
|
|
safe_delay(BOOTSCREEN_TIMEOUT); |
|
|
|
|
|
#elif ENABLED(ULTRA_LCD) |
|
|
|
|
|
bootscreen(); |
|
|
|
|
|
lcd_init(); |
|
|
|
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1 |
|
|
|
|
|
// Initialize mixing to 100% color 1
|
|
|
|
|
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++) |
|
|
|
|
|
mixing_factor[i] = (i == 0) ? 1 : 0; |
|
|
|
|
|
for (uint8_t t = 0; t < MIXING_VIRTUAL_TOOLS; t++) |
|
|
|
|
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++) |
|
|
|
|
|
mixing_virtual_tool_mix[t][i] = mixing_factor[i]; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0 |
|
|
|
|
|
i2c.onReceive(i2c_on_receive); |
|
|
|
|
|
i2c.onRequest(i2c_on_request); |
|
|
|
|
|
#endif |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* The main Marlin program loop |
|
|
|
|
|
* |
|
|
|
|
|
* - Save or log commands to SD |
|
|
|
|
|
* - Process available commands (if not saving) |
|
|
|
|
|
* - Call heater manager |
|
|
|
|
|
* - Call inactivity manager |
|
|
|
|
|
* - Call endstop manager |
|
|
|
|
|
* - Call LCD update |
|
|
|
|
|
*/ |
|
|
|
|
|
void loop() { |
|
|
|
|
|
if (commands_in_queue < BUFSIZE) get_available_commands(); |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(SDSUPPORT) |
|
|
|
|
|
card.checkautostart(false); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if (commands_in_queue) { |
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(SDSUPPORT) |
|
|
|
|
|
|
|
|
|
|
|
if (card.saving) { |
|
|
|
|
|
char* command = command_queue[cmd_queue_index_r]; |
|
|
|
|
|
if (strstr_P(command, PSTR("M29"))) { |
|
|
|
|
|
// M29 closes the file
|
|
|
|
|
|
card.closefile(); |
|
|
|
|
|
SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED); |
|
|
|
|
|
ok_to_send(); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
// Write the string from the read buffer to SD
|
|
|
|
|
|
card.write_command(command); |
|
|
|
|
|
if (card.logging) |
|
|
|
|
|
process_next_command(); // The card is saving because it's logging
|
|
|
|
|
|
else |
|
|
|
|
|
ok_to_send(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
process_next_command(); |
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
process_next_command(); |
|
|
|
|
|
|
|
|
|
|
|
#endif // SDSUPPORT
|
|
|
|
|
|
|
|
|
|
|
|
// The queue may be reset by a command handler or by code invoked by idle() within a handler
|
|
|
|
|
|
if (commands_in_queue) { |
|
|
|
|
|
--commands_in_queue; |
|
|
|
|
|
cmd_queue_index_r = (cmd_queue_index_r + 1) % BUFSIZE; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
endstops.report_state(); |
|
|
|
|
|
idle(); |
|
|
|
|
|
} |
|
|