diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ecdc833024..1ff8b6db2f 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -181,15 +181,14 @@ #define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? #define SD_FINISHED_RELEASECOMMAND "M84 X Y Z E" // no z because of layer shift. -// The hardware watchdog should halt the Microcontroller, in case the firmware gets stuck somewhere. However: -// the Watchdog is not working well, so please only enable this for testing -// this enables the watchdog interrupt. -//#define USE_WATCHDOG -//#ifdef USE_WATCHDOG - // you cannot reboot on a mega2560 due to a bug in he bootloader. Hence, you have to reset manually, and this is done hereby: +// The hardware watchdog should reset the Microcontroller disabling all outputs, in case the firmware gets stuck and doesn't do temperature regulation. +#define USE_WATCHDOG + +#ifdef USE_WATCHDOG +// you cannot watchdog reboot on Arduino mega2560 due to a bug in he bootloader. Hence we need to ask the user to reset. +// THIS FEATURE IS UNSAFE!, as it will only work if interrupts are disabled. And the code could hang in an interrupt routine with interrupts disabled. //#define RESET_MANUAL -//#define WATCHDOG_TIMEOUT 4 //seconds -//#endif +#endif // extruder advance constant (s2/mm3) // @@ -214,7 +213,7 @@ #define MM_PER_ARC_SEGMENT 1 #define N_ARC_CORRECTION 25 -const int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement +const unsigned int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement // If you are using a RAMPS board or cheap E-bay purchased boards that do not detect when an SD card is inserted // You can get round this by connecting a push button or single throw switch to the pin defined as SDCARDCARDDETECT diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 12674ef000..b833d71e63 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -6,14 +6,6 @@ #include "temperature.h" //#include -int plaPreheatHotendTemp; -int plaPreheatHPBTemp; -int plaPreheatFanSpeed; - -int absPreheatHotendTemp; -int absPreheatHPBTemp; -int absPreheatFanSpeed; - template int EEPROM_writeAnything(int &ee, const T& value) { const byte* p = (const byte*)(const void*)&value; diff --git a/Marlin/LiquidCrystalRus.cpp b/Marlin/LiquidCrystalRus.cpp index 9f3f5c055b..4bd8de781d 100644 --- a/Marlin/LiquidCrystalRus.cpp +++ b/Marlin/LiquidCrystalRus.cpp @@ -1,4 +1,3 @@ -#define __PROG_TYPES_COMPAT__ #include "LiquidCrystalRus.h" #include @@ -14,7 +13,7 @@ // it is a russian alphabet translation // except 0401 --> 0xa2 = ╗, 0451 --> 0xb5 -const PROGMEM prog_uchar utf_recode[] = +const PROGMEM uint8_t utf_recode[] = { 0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4,0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f, 0xa8,0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab,0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1, 0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f, diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 5b59885cd3..bec9dfe91b 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -17,8 +17,8 @@ #include #include #include -#include -#include +#include +#include #include "fastio.h" @@ -52,22 +52,11 @@ #define MYSERIAL MSerial #endif -//this is a unfinsihed attemp to removes a lot of warning messages, see: -// http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=57011 -//typedef char prog_char PROGMEM; -// //#define PSTR (s ) ((const PROGMEM char *)(s)) -// //# define MYPGM(s) (__extension__({static prog_char __c[] = (s); &__c[0];})) -// //#define MYPGM(s) ((const prog_char *g PROGMEM=s)) -#define MYPGM(s) PSTR(s) -//#define MYPGM(s) (__extension__({static char __c[] __attribute__((__progmem__)) = (s); &__c[0];})) //This is the normal behaviour -//#define MYPGM(s) (__extension__({static prog_char __c[] = (s); &__c[0];})) //this does not work but hides the warnings - - #define SERIAL_PROTOCOL(x) MYSERIAL.print(x); #define SERIAL_PROTOCOL_F(x,y) MYSERIAL.print(x,y); -#define SERIAL_PROTOCOLPGM(x) serialprintPGM(MYPGM(x)); +#define SERIAL_PROTOCOLPGM(x) serialprintPGM(PSTR(x)); #define SERIAL_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');} -#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(MYPGM(x));MYSERIAL.write('\n');} +#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(PSTR(x));MYSERIAL.write('\n');} const char errormagic[] PROGMEM ="Error:"; @@ -92,7 +81,6 @@ void serial_echopair_P(const char *s_P, unsigned long v); //things to write to serial from Programmemory. saves 400 to 2k of RAM. -#define SerialprintPGM(x) serialprintPGM(MYPGM(x)) FORCE_INLINE void serialprintPGM(const char *str) { char ch=pgm_read_byte(str); @@ -197,6 +185,9 @@ extern float min_pos[3]; extern float max_pos[3]; extern unsigned char FanSpeed; +extern unsigned long starttime; +extern unsigned long stoptime; + // Handling multiple extruders pins extern uint8_t active_extruder; diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index bda479e3ca..5d91345868 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -27,1839 +27,10 @@ http://reprap.org/pipermail/reprap-dev/2011-May/003323.html */ -#include "Marlin.h" +/* All the implementation is done in *.cpp files to get better compatibility with avr-gcc without the Arduino IDE */ +/* Use this file to help the Arduino IDE find which Arduino libraries are needed and to keep documentation on GCode */ -#include "ultralcd.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" -#include "motion_control.h" -#include "cardreader.h" -#include "watchdog.h" -#include "EEPROMwrite.h" -#include "language.h" -#include "pins_arduino.h" - -#define VERSION_STRING "1.0.0" - -// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html -// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes - -//Implemented Codes -//------------------- -// G0 -> G1 -// G1 - Coordinated Movement X Y Z E -// G2 - CW ARC -// G3 - CCW ARC -// G4 - Dwell S or P -// G10 - retract filament according to settings of M207 -// G11 - retract recover filament according to settings of M208 -// G28 - Home all Axis -// G90 - Use Absolute Coordinates -// G91 - Use Relative Coordinates -// G92 - Set current position to cordinates given - -//RepRap M Codes -// M0 - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled) -// M1 - Same as M0 -// M104 - Set extruder target temp -// M105 - Read current temp -// M106 - Fan on -// M107 - Fan off -// M109 - Wait for extruder current temp to reach target temp. -// M114 - Display current position - -//Custom M Codes -// M17 - Enable/Power all stepper motors -// M18 - Disable all stepper motors; same as M84 -// M20 - List SD card -// M21 - Init SD card -// M22 - Release SD card -// M23 - Select SD file (M23 filename.g) -// M24 - Start/resume SD print -// M25 - Pause SD print -// M26 - Set SD position in bytes (M26 S12345) -// M27 - Report SD print status -// M28 - Start SD write (M28 filename.g) -// M29 - Stop SD write -// M30 - Delete file from SD (M30 filename.g) -// M31 - Output time since last M109 or SD card start to serial -// M42 - Change pin status via gcode -// M80 - Turn on Power Supply -// M81 - Turn off Power Supply -// M82 - Set E codes absolute (default) -// M83 - Set E codes relative while in Absolute Coordinates (G90) mode -// M84 - Disable steppers until next move, -// or use S to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. -// M85 - Set inactivity shutdown timer with parameter S. To disable set zero (default) -// M92 - Set axis_steps_per_unit - same syntax as G92 -// M114 - Output current position to serial port -// M115 - Capabilities string -// M117 - display message -// M119 - Output Endstop status to serial port -// M140 - Set bed target temp -// M190 - Wait for bed current temp to reach target temp. -// M200 - Set filament diameter -// M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) -// M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!! -// M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec -// M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate -// M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk, E=maximum E jerk -// M206 - set additional homeing offset -// M207 - set retract length S[positive mm] F[feedrate mm/sec] Z[additional zlift/hop] -// M208 - set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/sec] -// M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction. -// M220 S- set speed factor override percentage -// M221 S- set extrude factor override percentage -// M240 - Trigger a camera to take a photograph -// M301 - Set PID parameters P I and D -// M302 - Allow cold extrudes -// M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) -// M304 - Set bed PID parameters P I and D -// M400 - Finish all moves -// M500 - stores paramters in EEPROM -// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). -// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. -// M503 - print the current settings (from memory not from eeprom) -// M999 - Restart after being stopped by error - -//Stepper Movement Variables - -//=========================================================================== -//=============================imported variables============================ -//=========================================================================== - - -//=========================================================================== -//=============================public variables============================= -//=========================================================================== -#ifdef SDSUPPORT -CardReader card; -#endif -float homing_feedrate[] = HOMING_FEEDRATE; -bool axis_relative_modes[] = AXIS_RELATIVE_MODES; -volatile int feedmultiply=100; //100->1 200->2 -int saved_feedmultiply; -volatile bool feedmultiplychanged=false; -volatile int extrudemultiply=100; //100->1 200->2 -float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 }; -float add_homeing[3]={0,0,0}; -float min_pos[3] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS }; -float max_pos[3] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS }; -uint8_t active_extruder = 0; -unsigned char FanSpeed=0; - -#ifdef FWRETRACT - bool autoretract_enabled=true; - bool retracted=false; - float retract_length=3, retract_feedrate=17*60, retract_zlift=0.8; - float retract_recover_length=0, retract_recover_feedrate=8*60; -#endif - -//=========================================================================== -//=============================private variables============================= -//=========================================================================== -const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; -static float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; -static float offset[3] = {0.0, 0.0, 0.0}; -static bool home_all_axis = true; -static float feedrate = 1500.0, next_feedrate, saved_feedrate; -static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0; - -static bool relative_mode = false; //Determines Absolute or Relative Coordinates -static bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. - -static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; -static bool fromsd[BUFSIZE]; -static int bufindr = 0; -static int bufindw = 0; -static int buflen = 0; -//static int i = 0; -static char serial_char; -static int serial_count = 0; -static boolean comment_mode = false; -static char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc - -const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 - -//static float tt = 0; -//static float bt = 0; - -//Inactivity shutdown variables -static unsigned long previous_millis_cmd = 0; -static unsigned long max_inactive_time = 0; -static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l; - -static unsigned long starttime=0; -static unsigned long stoptime=0; - -static uint8_t tmp_extruder; - - -bool Stopped=false; - -//=========================================================================== -//=============================ROUTINES============================= -//=========================================================================== - -void get_arc_coordinates(); -bool setTargetedHotend(int code); - -void serial_echopair_P(const char *s_P, float v) - { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_P(const char *s_P, double v) - { serialprintPGM(s_P); SERIAL_ECHO(v); } -void serial_echopair_P(const char *s_P, unsigned long v) - { serialprintPGM(s_P); SERIAL_ECHO(v); } - -extern "C"{ - extern unsigned int __bss_end; - extern unsigned int __heap_start; - extern void *__brkval; - - int freeMemory() { - int free_memory; - - if((int)__brkval == 0) - free_memory = ((int)&free_memory) - ((int)&__bss_end); - else - free_memory = ((int)&free_memory) - ((int)__brkval); - - return free_memory; - } -} - -//adds an command to the main command buffer -//thats really done in a non-safe way. -//needs overworking someday -void enquecommand(const char *cmd) -{ - if(buflen < BUFSIZE) - { - //this is dangerous if a mixing of serial and this happsens - strcpy(&(cmdbuffer[bufindw][0]),cmd); - SERIAL_ECHO_START; - SERIAL_ECHOPGM("enqueing \""); - SERIAL_ECHO(cmdbuffer[bufindw]); - SERIAL_ECHOLNPGM("\""); - bufindw= (bufindw + 1)%BUFSIZE; - buflen += 1; - } -} - -void setup_killpin() -{ - #if( KILL_PIN>-1 ) - pinMode(KILL_PIN,INPUT); - WRITE(KILL_PIN,HIGH); - #endif -} - -void setup_photpin() -{ - #ifdef PHOTOGRAPH_PIN - #if (PHOTOGRAPH_PIN > -1) - SET_OUTPUT(PHOTOGRAPH_PIN); - WRITE(PHOTOGRAPH_PIN, LOW); - #endif - #endif -} - -void setup_powerhold() -{ - #ifdef SUICIDE_PIN - #if (SUICIDE_PIN> -1) - SET_OUTPUT(SUICIDE_PIN); - WRITE(SUICIDE_PIN, HIGH); - #endif - #endif -} - -void suicide() -{ - #ifdef SUICIDE_PIN - #if (SUICIDE_PIN> -1) - SET_OUTPUT(SUICIDE_PIN); - WRITE(SUICIDE_PIN, LOW); - #endif - #endif -} - -void setup() -{ - setup_killpin(); - setup_powerhold(); - 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(VERSION_STRING); - #ifdef STRING_VERSION_CONFIG_H - #ifdef STRING_CONFIG_H_AUTHOR - SERIAL_ECHO_START; - SERIAL_ECHOPGM(MSG_CONFIGURATION_VER); - SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); - SERIAL_ECHOPGM(MSG_AUTHOR); - SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); - #endif - #endif - 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); - for(int8_t i = 0; i < BUFSIZE; i++) - { - fromsd[i] = false; - } - - EEPROM_RetrieveSettings(); // loads data from EEPROM if available - - for(int8_t i=0; i < NUM_AXIS; i++) - { - axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; - } - - - tp_init(); // Initialize temperature loop - plan_init(); // Initialize planner; - st_init(); // Initialize stepper; - wd_init(); - setup_photpin(); - - LCD_INIT; -} - - -void loop() -{ - if(buflen < (BUFSIZE-1)) - get_command(); - #ifdef SDSUPPORT - card.checkautostart(false); - #endif - if(buflen) - { - #ifdef SDSUPPORT - if(card.saving) - { - if(strstr(cmdbuffer[bufindr],"M29") == NULL) - { - card.write_command(cmdbuffer[bufindr]); - SERIAL_PROTOCOLLNPGM(MSG_OK); - } - else - { - card.closefile(); - SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED); - } - } - else - { - process_commands(); - } - #else - process_commands(); - #endif //SDSUPPORT - buflen = (buflen-1); - bufindr = (bufindr + 1)%BUFSIZE; - } - //check heater every n milliseconds - manage_heater(); - manage_inactivity(); - checkHitEndstops(); - LCD_STATUS; -} - -void get_command() -{ - while( MYSERIAL.available() > 0 && buflen < BUFSIZE) { - serial_char = MYSERIAL.read(); - if(serial_char == '\n' || - serial_char == '\r' || - (serial_char == ':' && comment_mode == false) || - serial_count >= (MAX_CMD_SIZE - 1) ) - { - if(!serial_count) { //if empty line - comment_mode = false; //for new command - return; - } - cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ - comment_mode = false; //for new command - fromsd[bufindw] = false; - if(strstr(cmdbuffer[bufindw], "N") != NULL) - { - strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); - gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10)); - if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) { - SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_LINE_NO); - SERIAL_ERRORLN(gcode_LastN); - //Serial.println(gcode_N); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - - if(strstr(cmdbuffer[bufindw], "*") != NULL) - { - byte checksum = 0; - byte count = 0; - while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; - strchr_pointer = strchr(cmdbuffer[bufindw], '*'); - - if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) { - SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH); - SERIAL_ERRORLN(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { - SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM); - SERIAL_ERRORLN(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - - gcode_LastN = gcode_N; - //if no errors, continue parsing - } - else // if we don't receive 'N' but still see '*' - { - if((strstr(cmdbuffer[bufindw], "*") != NULL)) - { - SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM); - SERIAL_ERRORLN(gcode_LastN); - serial_count = 0; - return; - } - } - if((strstr(cmdbuffer[bufindw], "G") != NULL)){ - strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); - switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){ - case 0: - case 1: - case 2: - case 3: - if(Stopped == false) { // If printer is stopped by an error the G[0-3] codes are ignored. - #ifdef SDSUPPORT - if(card.saving) - break; - #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM(MSG_OK); - } - else { - SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); - LCD_MESSAGEPGM(MSG_STOPPED); - } - break; - default: - break; - } - - } - bufindw = (bufindw + 1)%BUFSIZE; - buflen += 1; - } - serial_count = 0; //clear buffer - } - else - { - if(serial_char == ';') comment_mode = true; - if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; - } - } - #ifdef SDSUPPORT - if(!card.sdprinting || serial_count!=0){ - return; - } - while( !card.eof() && buflen < BUFSIZE) { - int16_t n=card.get(); - serial_char = (char)n; - if(serial_char == '\n' || - serial_char == '\r' || - (serial_char == ':' && comment_mode == false) || - serial_count >= (MAX_CMD_SIZE - 1)||n==-1) - { - if(card.eof()){ - SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED); - stoptime=millis(); - char time[30]; - unsigned long t=(stoptime-starttime)/1000; - int sec,min; - min=t/60; - sec=t%60; - sprintf(time,"%i min, %i sec",min,sec); - SERIAL_ECHO_START; - SERIAL_ECHOLN(time); - LCD_MESSAGE(time); - card.printingHasFinished(); - card.checkautostart(true); - - } - if(!serial_count) - { - comment_mode = false; //for new command - return; //if empty line - } - cmdbuffer[bufindw][serial_count] = 0; //terminate string -// if(!comment_mode){ - fromsd[bufindw] = true; - buflen += 1; - bufindw = (bufindw + 1)%BUFSIZE; -// } - comment_mode = false; //for new command - serial_count = 0; //clear buffer - } - else - { - if(serial_char == ';') comment_mode = true; - if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; - } - } - - #endif //SDSUPPORT - -} - - -float code_value() -{ - return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); -} - -long code_value_long() -{ - return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); -} - -bool code_seen(char code_string[]) //Return True if the string was found -{ - return (strstr(cmdbuffer[bufindr], code_string) != NULL); -} - -bool code_seen(char code) -{ - strchr_pointer = strchr(cmdbuffer[bufindr], code); - return (strchr_pointer != NULL); //Return True if a character was found -} - -#define DEFINE_PGM_READ_ANY(type, reader) \ - static inline type pgm_read_any(const type *p) \ - { return pgm_read_##reader##_near(p); } - -DEFINE_PGM_READ_ANY(float, float); -DEFINE_PGM_READ_ANY(signed char, byte); - -#define XYZ_CONSTS_FROM_CONFIG(type, array, CONFIG) \ -static const PROGMEM type array##_P[3] = \ - { X_##CONFIG, Y_##CONFIG, Z_##CONFIG }; \ -static inline type array(int axis) \ - { return pgm_read_any(&array##_P[axis]); } - -XYZ_CONSTS_FROM_CONFIG(float, base_min_pos, MIN_POS); -XYZ_CONSTS_FROM_CONFIG(float, base_max_pos, MAX_POS); -XYZ_CONSTS_FROM_CONFIG(float, base_home_pos, HOME_POS); -XYZ_CONSTS_FROM_CONFIG(float, max_length, MAX_LENGTH); -XYZ_CONSTS_FROM_CONFIG(float, home_retract_mm, HOME_RETRACT_MM); -XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR); - -static void axis_is_at_home(int axis) { - current_position[axis] = base_home_pos(axis) + add_homeing[axis]; - min_pos[axis] = base_min_pos(axis) + add_homeing[axis]; - max_pos[axis] = base_max_pos(axis) + add_homeing[axis]; -} - -static void homeaxis(int axis) { -#define HOMEAXIS_DO(LETTER) \ - ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1)) - - if (axis==X_AXIS ? HOMEAXIS_DO(X) : - axis==Y_AXIS ? HOMEAXIS_DO(Y) : - axis==Z_AXIS ? HOMEAXIS_DO(Z) : - 0) { - current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[axis] = 1.5 * max_length(axis) * home_dir(axis); - feedrate = homing_feedrate[axis]; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - st_synchronize(); - - current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[axis] = -home_retract_mm(axis) * home_dir(axis); - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - st_synchronize(); - - destination[axis] = 2*home_retract_mm(axis) * home_dir(axis); - feedrate = homing_feedrate[axis]/2 ; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - st_synchronize(); - - axis_is_at_home(axis); - destination[axis] = current_position[axis]; - feedrate = 0.0; - endstops_hit_on_purpose(); - } -} -#define HOMEAXIS(LETTER) homeaxis(LETTER##_AXIS) - -void process_commands() -{ - unsigned long codenum; //throw away variable - char *starpos = NULL; - - if(code_seen('G')) - { - switch((int)code_value()) - { - case 0: // G0 -> G1 - case 1: // G1 - if(Stopped == false) { - get_coordinates(); // For X Y Z E F - prepare_move(); - //ClearToSend(); - return; - } - //break; - case 2: // G2 - CW ARC - if(Stopped == false) { - get_arc_coordinates(); - prepare_arc_move(true); - return; - } - case 3: // G3 - CCW ARC - if(Stopped == false) { - get_arc_coordinates(); - prepare_arc_move(false); - return; - } - case 4: // G4 dwell - LCD_MESSAGEPGM(MSG_DWELL); - codenum = 0; - if(code_seen('P')) codenum = code_value(); // milliseconds to wait - if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait - - st_synchronize(); - codenum += millis(); // keep track of when we started waiting - previous_millis_cmd = millis(); - while(millis() < codenum ){ - manage_heater(); - manage_inactivity(); - LCD_STATUS; - } - break; - #ifdef FWRETRACT - case 10: // G10 retract - if(!retracted) - { - destination[X_AXIS]=current_position[X_AXIS]; - destination[Y_AXIS]=current_position[Y_AXIS]; - destination[Z_AXIS]=current_position[Z_AXIS]; - current_position[Z_AXIS]+=-retract_zlift; - destination[E_AXIS]=current_position[E_AXIS]-retract_length; - feedrate=retract_feedrate; - retracted=true; - prepare_move(); - } - - break; - case 11: // G10 retract_recover - if(!retracted) - { - destination[X_AXIS]=current_position[X_AXIS]; - destination[Y_AXIS]=current_position[Y_AXIS]; - destination[Z_AXIS]=current_position[Z_AXIS]; - - current_position[Z_AXIS]+=retract_zlift; - current_position[E_AXIS]+=-retract_recover_length; - feedrate=retract_recover_feedrate; - retracted=false; - prepare_move(); - } - break; - #endif //FWRETRACT - case 28: //G28 Home all Axis one at a time - saved_feedrate = feedrate; - saved_feedmultiply = feedmultiply; - feedmultiply = 100; - previous_millis_cmd = millis(); - - enable_endstops(true); - - for(int8_t i=0; i < NUM_AXIS; i++) { - destination[i] = current_position[i]; - } - feedrate = 0.0; - home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); - - #if Z_HOME_DIR > 0 // If homing away from BED do Z first - if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { - HOMEAXIS(Z); - } - #endif - - #ifdef QUICK_HOME - if((home_all_axis)||( code_seen(axis_codes[X_AXIS]) && code_seen(axis_codes[Y_AXIS])) ) //first diagonal move - { - current_position[X_AXIS] = 0;current_position[Y_AXIS] = 0; - - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]; - if(homing_feedrate[Y_AXIS] 0){ - codenum += millis(); // keep track of when we started waiting - while(millis() < codenum && !CLICKED){ - manage_heater(); - manage_inactivity(); - LCD_STATUS; - } - }else{ - while(!CLICKED){ - manage_heater(); - manage_inactivity(); - LCD_STATUS; - } - } - } - break; -#endif - case 17: - LCD_MESSAGEPGM(MSG_NO_MOVE); - enable_x(); - enable_y(); - enable_z(); - enable_e0(); - enable_e1(); - enable_e2(); - break; - -#ifdef SDSUPPORT - case 20: // M20 - list SD card - SERIAL_PROTOCOLLNPGM(MSG_BEGIN_FILE_LIST); - card.ls(); - SERIAL_PROTOCOLLNPGM(MSG_END_FILE_LIST); - break; - case 21: // M21 - init SD card - - card.initsd(); - - break; - case 22: //M22 - release SD card - card.release(); - - break; - case 23: //M23 - Select file - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos!=NULL) - *(starpos-1)='\0'; - card.openFile(strchr_pointer + 4,true); - break; - case 24: //M24 - Start SD print - card.startFileprint(); - starttime=millis(); - break; - case 25: //M25 - Pause SD print - card.pauseSDPrint(); - break; - case 26: //M26 - Set SD index - if(card.cardOK && code_seen('S')) { - card.setIndex(code_value_long()); - } - break; - case 27: //M27 - Get SD status - card.getStatus(); - break; - case 28: //M28 - Start SD write - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos != NULL){ - char* npos = strchr(cmdbuffer[bufindr], 'N'); - strchr_pointer = strchr(npos,' ') + 1; - *(starpos-1) = '\0'; - } - card.openFile(strchr_pointer+4,false); - break; - case 29: //M29 - Stop SD write - //processed in write to file routine above - //card,saving = false; - break; - case 30: //M30 Delete File - if (card.cardOK){ - card.closefile(); - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos != NULL){ - char* npos = strchr(cmdbuffer[bufindr], 'N'); - strchr_pointer = strchr(npos,' ') + 1; - *(starpos-1) = '\0'; - } - card.removeFile(strchr_pointer + 4); - } - break; - -#endif //SDSUPPORT - - case 31: //M31 take time since the start of the SD print or an M109 command - { - stoptime=millis(); - char time[30]; - unsigned long t=(stoptime-starttime)/1000; - int sec,min; - min=t/60; - sec=t%60; - sprintf(time,"%i min, %i sec",min,sec); - SERIAL_ECHO_START; - SERIAL_ECHOLN(time); - LCD_MESSAGE(time); - autotempShutdown(); - } - break; - case 42: //M42 -Change pin status via gcode - if (code_seen('S')) - { - int pin_status = code_value(); - if (code_seen('P') && pin_status >= 0 && pin_status <= 255) - { - int pin_number = code_value(); - for(int8_t i = 0; i < (int8_t)sizeof(sensitive_pins); i++) - { - if (sensitive_pins[i] == pin_number) - { - pin_number = -1; - break; - } - } - - if (pin_number > -1) - { - pinMode(pin_number, OUTPUT); - digitalWrite(pin_number, pin_status); - analogWrite(pin_number, pin_status); - } - } - } - break; - case 104: // M104 - if(setTargetedHotend(104)){ - break; - } - if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder); - setWatch(); - break; - case 140: // M140 set bed temp - if (code_seen('S')) setTargetBed(code_value()); - break; - case 105 : // M105 - if(setTargetedHotend(105)){ - break; - } - #if (TEMP_0_PIN > -1) - SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); - SERIAL_PROTOCOLPGM(" /"); - SERIAL_PROTOCOL_F(degTargetHotend(tmp_extruder),1); - #if TEMP_BED_PIN > -1 - SERIAL_PROTOCOLPGM(" B:"); - SERIAL_PROTOCOL_F(degBed(),1); - SERIAL_PROTOCOLPGM(" /"); - SERIAL_PROTOCOL_F(degTargetBed(),1); - #endif //TEMP_BED_PIN - #else - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS); - #endif - - SERIAL_PROTOCOLPGM(" @:"); - SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); - - SERIAL_PROTOCOLPGM(" B@:"); - SERIAL_PROTOCOL(getHeaterPower(-1)); - - SERIAL_PROTOCOLLN(""); - return; - break; - case 109: - {// M109 - Wait for extruder heater to reach target. - if(setTargetedHotend(109)){ - break; - } - LCD_MESSAGEPGM(MSG_HEATING); - #ifdef AUTOTEMP - autotemp_enabled=false; - #endif - if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder); - #ifdef AUTOTEMP - if (code_seen('S')) autotemp_min=code_value(); - if (code_seen('B')) autotemp_max=code_value(); - if (code_seen('F')) - { - autotemp_factor=code_value(); - autotemp_enabled=true; - } - #endif - - setWatch(); - codenum = millis(); - - /* See if we are heating up or cooling down */ - bool target_direction = isHeatingHotend(tmp_extruder); // true if heating, false if cooling - - #ifdef TEMP_RESIDENCY_TIME - long residencyStart; - residencyStart = -1; - /* continue to loop until we have reached the target temp - _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */ - while((residencyStart == -1) || - (residencyStart >= 0 && (((unsigned int) (millis() - residencyStart)) < (TEMP_RESIDENCY_TIME * 1000UL))) ) { - #else - while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { - #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000UL ) - { //Print Temp Reading and remaining time every 1 second while heating up/cooling down - SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); - SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOL((int)tmp_extruder); - #ifdef TEMP_RESIDENCY_TIME - SERIAL_PROTOCOLPGM(" W:"); - if(residencyStart > -1) - { - codenum = ((TEMP_RESIDENCY_TIME * 1000UL) - (millis() - residencyStart)) / 1000UL; - SERIAL_PROTOCOLLN( codenum ); - } - else - { - SERIAL_PROTOCOLLN( "?" ); - } - #else - SERIAL_PROTOCOLLN(""); - #endif - codenum = millis(); - } - manage_heater(); - manage_inactivity(); - LCD_STATUS; - #ifdef TEMP_RESIDENCY_TIME - /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time - or when current temp falls outside the hysteresis after target temp was reached */ - if ((residencyStart == -1 && target_direction && (degHotend(tmp_extruder) >= (degTargetHotend(tmp_extruder)-TEMP_WINDOW))) || - (residencyStart == -1 && !target_direction && (degHotend(tmp_extruder) <= (degTargetHotend(tmp_extruder)+TEMP_WINDOW))) || - (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) ) - { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGEPGM(MSG_HEATING_COMPLETE); - starttime=millis(); - previous_millis_cmd = millis(); - } - break; - case 190: // M190 - Wait for bed heater to reach target. - #if TEMP_BED_PIN > -1 - LCD_MESSAGEPGM(MSG_BED_HEATING); - if (code_seen('S')) setTargetBed(code_value()); - codenum = millis(); - while(isHeatingBed()) - { - if(( millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. - { - float tt=degHotend(active_extruder); - SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOL(tt); - SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOL((int)active_extruder); - SERIAL_PROTOCOLPGM(" B:"); - SERIAL_PROTOCOL_F(degBed(),1); - SERIAL_PROTOCOLLN(""); - codenum = millis(); - } - manage_heater(); - manage_inactivity(); - LCD_STATUS; - } - LCD_MESSAGEPGM(MSG_BED_DONE); - previous_millis_cmd = millis(); - #endif - break; - - #if FAN_PIN > -1 - case 106: //M106 Fan On - if (code_seen('S')){ - FanSpeed=constrain(code_value(),0,255); - } - else { - FanSpeed=255; - } - break; - case 107: //M107 Fan Off - FanSpeed = 0; - break; - #endif //FAN_PIN - - #if (PS_ON_PIN > -1) - case 80: // M80 - ATX Power On - SET_OUTPUT(PS_ON_PIN); //GND - WRITE(PS_ON_PIN, LOW); - break; - #endif - - case 81: // M81 - ATX Power Off - - #if defined SUICIDE_PIN && SUICIDE_PIN > -1 - st_synchronize(); - suicide(); - #elif (PS_ON_PIN > -1) - SET_OUTPUT(PS_ON_PIN); - WRITE(PS_ON_PIN, HIGH); - #endif - break; - - case 82: - axis_relative_modes[3] = false; - break; - case 83: - axis_relative_modes[3] = true; - break; - case 18: //compatibility - case 84: // M84 - if(code_seen('S')){ - stepper_inactive_time = code_value() * 1000; - } - else - { - bool all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))|| (code_seen(axis_codes[3]))); - if(all_axis) - { - st_synchronize(); - disable_e0(); - disable_e1(); - disable_e2(); - finishAndDisableSteppers(); - } - else - { - st_synchronize(); - if(code_seen('X')) disable_x(); - if(code_seen('Y')) disable_y(); - if(code_seen('Z')) disable_z(); - #if ((E0_ENABLE_PIN != X_ENABLE_PIN) && (E1_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS - if(code_seen('E')) { - disable_e0(); - disable_e1(); - disable_e2(); - } - #endif - LCD_MESSAGEPGM(MSG_PART_RELEASE); - } - } - break; - case 85: // M85 - code_seen('S'); - max_inactive_time = code_value() * 1000; - break; - case 92: // M92 - for(int8_t i=0; i < NUM_AXIS; i++) - { - if(code_seen(axis_codes[i])) - - if(i == 3) { // E - float value = code_value(); - if(value < 20.0) { - float factor = axis_steps_per_unit[i] / value; // increase e constants if M92 E14 is given for netfab. - max_e_jerk *= factor; - max_feedrate[i] *= factor; - axis_steps_per_sqr_second[i] *= factor; - } - axis_steps_per_unit[i] = value; - } - else { - axis_steps_per_unit[i] = code_value(); - } - } - break; - case 115: // M115 - SerialprintPGM(MSG_M115_REPORT); - break; - case 117: // M117 display message - LCD_MESSAGE(cmdbuffer[bufindr]+5); - break; - case 114: // M114 - SERIAL_PROTOCOLPGM("X:"); - SERIAL_PROTOCOL(current_position[X_AXIS]); - SERIAL_PROTOCOLPGM("Y:"); - SERIAL_PROTOCOL(current_position[Y_AXIS]); - SERIAL_PROTOCOLPGM("Z:"); - SERIAL_PROTOCOL(current_position[Z_AXIS]); - SERIAL_PROTOCOLPGM("E:"); - SERIAL_PROTOCOL(current_position[E_AXIS]); - - SERIAL_PROTOCOLPGM(MSG_COUNT_X); - SERIAL_PROTOCOL(float(st_get_position(X_AXIS))/axis_steps_per_unit[X_AXIS]); - SERIAL_PROTOCOLPGM("Y:"); - SERIAL_PROTOCOL(float(st_get_position(Y_AXIS))/axis_steps_per_unit[Y_AXIS]); - SERIAL_PROTOCOLPGM("Z:"); - SERIAL_PROTOCOL(float(st_get_position(Z_AXIS))/axis_steps_per_unit[Z_AXIS]); - - SERIAL_PROTOCOLLN(""); - break; - case 120: // M120 - enable_endstops(false) ; - break; - case 121: // M121 - enable_endstops(true) ; - break; - case 119: // M119 - SERIAL_PROTOCOLLN(MSG_M119_REPORT); - #if (X_MIN_PIN > -1) - SERIAL_PROTOCOLPGM(MSG_X_MIN); - SERIAL_PROTOCOLLN(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); - #endif - #if (X_MAX_PIN > -1) - SERIAL_PROTOCOLPGM(MSG_X_MAX); - SERIAL_PROTOCOLLN(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); - #endif - #if (Y_MIN_PIN > -1) - SERIAL_PROTOCOLPGM(MSG_Y_MIN); - SERIAL_PROTOCOLLN(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); - #endif - #if (Y_MAX_PIN > -1) - SERIAL_PROTOCOLPGM(MSG_Y_MAX); - SERIAL_PROTOCOLLN(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); - #endif - #if (Z_MIN_PIN > -1) - SERIAL_PROTOCOLPGM(MSG_Z_MIN); - SERIAL_PROTOCOLLN(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); - #endif - #if (Z_MAX_PIN > -1) - SERIAL_PROTOCOLPGM(MSG_Z_MAX); - SERIAL_PROTOCOLLN(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); - #endif - break; - //TODO: update for all axis, use for loop - case 201: // M201 - for(int8_t i=0; i < NUM_AXIS; i++) - { - if(code_seen(axis_codes[i])) - { - max_acceleration_units_per_sq_second[i] = code_value(); - axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; - } - } - break; - #if 0 // Not used for Sprinter/grbl gen6 - case 202: // M202 - for(int8_t i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; - } - break; - #endif - case 203: // M203 max feedrate mm/sec - for(int8_t i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) max_feedrate[i] = code_value(); - } - break; - case 204: // M204 acclereration S normal moves T filmanent only moves - { - if(code_seen('S')) acceleration = code_value() ; - if(code_seen('T')) retract_acceleration = code_value() ; - } - break; - case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk - { - if(code_seen('S')) minimumfeedrate = code_value(); - if(code_seen('T')) mintravelfeedrate = code_value(); - if(code_seen('B')) minsegmenttime = code_value() ; - if(code_seen('X')) max_xy_jerk = code_value() ; - if(code_seen('Z')) max_z_jerk = code_value() ; - if(code_seen('E')) max_e_jerk = code_value() ; - } - break; - case 206: // M206 additional homeing offset - for(int8_t i=0; i < 3; i++) - { - if(code_seen(axis_codes[i])) add_homeing[i] = code_value(); - } - break; - #ifdef FWRETRACT - case 207: //M207 - set retract length S[positive mm] F[feedrate mm/sec] Z[additional zlift/hop] - { - if(code_seen('S')) - { - retract_length = code_value() ; - } - if(code_seen('F')) - { - retract_feedrate = code_value() ; - } - if(code_seen('Z')) - { - retract_zlift = code_value() ; - } - }break; - case 208: // M208 - set retract recover length S[positive mm surplus to the M207 S*] F[feedrate mm/sec] - { - if(code_seen('S')) - { - retract_recover_length = code_value() ; - } - if(code_seen('F')) - { - retract_recover_feedrate = code_value() ; - } - }break; - - case 209: // M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction. - { - if(code_seen('S')) - { - int t= code_value() ; - switch(t) - { - case 0: autoretract_enabled=false;retracted=false;break; - case 1: autoretract_enabled=true;retracted=false;break; - default: - SERIAL_ECHO_START; - SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND); - SERIAL_ECHO(cmdbuffer[bufindr]); - SERIAL_ECHOLNPGM("\""); - } - } - - }break; - #endif - case 220: // M220 S- set speed factor override percentage - { - if(code_seen('S')) - { - feedmultiply = code_value() ; - feedmultiplychanged=true; - } - } - break; - case 221: // M221 S- set extrude factor override percentage - { - if(code_seen('S')) - { - extrudemultiply = code_value() ; - } - } - break; - - #ifdef PIDTEMP - case 301: // M301 - { - if(code_seen('P')) Kp = code_value(); - if(code_seen('I')) Ki = code_value()*PID_dT; - if(code_seen('D')) Kd = code_value()/PID_dT; - #ifdef PID_ADD_EXTRUSION_RATE - if(code_seen('C')) Kc = code_value(); - #endif - updatePID(); - SERIAL_PROTOCOL(MSG_OK); - SERIAL_PROTOCOL(" p:"); - SERIAL_PROTOCOL(Kp); - SERIAL_PROTOCOL(" i:"); - SERIAL_PROTOCOL(Ki/PID_dT); - SERIAL_PROTOCOL(" d:"); - SERIAL_PROTOCOL(Kd*PID_dT); - #ifdef PID_ADD_EXTRUSION_RATE - SERIAL_PROTOCOL(" c:"); - SERIAL_PROTOCOL(Kc*PID_dT); - #endif - SERIAL_PROTOCOLLN(""); - } - break; - #endif //PIDTEMP - #ifdef PIDTEMPBED - case 304: // M304 - { - if(code_seen('P')) bedKp = code_value(); - if(code_seen('I')) bedKi = code_value()*PID_dT; - if(code_seen('D')) bedKd = code_value()/PID_dT; - updatePID(); - SERIAL_PROTOCOL(MSG_OK); - SERIAL_PROTOCOL(" p:"); - SERIAL_PROTOCOL(bedKp); - SERIAL_PROTOCOL(" i:"); - SERIAL_PROTOCOL(bedKi/PID_dT); - SERIAL_PROTOCOL(" d:"); - SERIAL_PROTOCOL(bedKd*PID_dT); - SERIAL_PROTOCOLLN(""); - } - break; - #endif //PIDTEMP - case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/ - { - #ifdef PHOTOGRAPH_PIN - #if (PHOTOGRAPH_PIN > -1) - const uint8_t NUM_PULSES=16; - const float PULSE_LENGTH=0.01524; - for(int i=0; i < NUM_PULSES; i++) { - WRITE(PHOTOGRAPH_PIN, HIGH); - _delay_ms(PULSE_LENGTH); - WRITE(PHOTOGRAPH_PIN, LOW); - _delay_ms(PULSE_LENGTH); - } - delay(7.33); - for(int i=0; i < NUM_PULSES; i++) { - WRITE(PHOTOGRAPH_PIN, HIGH); - _delay_ms(PULSE_LENGTH); - WRITE(PHOTOGRAPH_PIN, LOW); - _delay_ms(PULSE_LENGTH); - } - #endif - #endif - } - break; - - case 302: // allow cold extrudes - { - allow_cold_extrudes(true); - } - break; - case 303: // M303 PID autotune - { - float temp = 150.0; - int e=0; - int c=5; - if (code_seen('E')) e=code_value(); - if (e<0) - temp=70; - if (code_seen('S')) temp=code_value(); - if (code_seen('C')) c=code_value(); - PID_autotune(temp, e, c); - } - break; - case 400: // M400 finish all moves - { - st_synchronize(); - } - break; - case 500: // Store settings in EEPROM - { - EEPROM_StoreSettings(); - } - break; - case 501: // Read settings from EEPROM - { - EEPROM_RetrieveSettings(); - } - break; - case 502: // Revert to default settings - { - EEPROM_RetrieveSettings(true); - } - break; - case 503: // print settings currently in memory - { - EEPROM_printSettings(); - } - break; - case 999: // Restart after being stopped - Stopped = false; - gcode_LastN = Stopped_gcode_LastN; - FlushSerialRequestResend(); - break; - } - } - - else if(code_seen('T')) - { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHO("T"); - SERIAL_ECHO(tmp_extruder); - SERIAL_ECHOLN(MSG_INVALID_EXTRUDER); - } - else { - active_extruder = tmp_extruder; - SERIAL_ECHO_START; - SERIAL_ECHO(MSG_ACTIVE_EXTRUDER); - SERIAL_PROTOCOLLN((int)active_extruder); - } - } - - else - { - SERIAL_ECHO_START; - SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND); - SERIAL_ECHO(cmdbuffer[bufindr]); - SERIAL_ECHOLNPGM("\""); - } - - ClearToSend(); -} - -void FlushSerialRequestResend() -{ - //char cmdbuffer[bufindr][100]="Resend:"; - MYSERIAL.flush(); - SERIAL_PROTOCOLPGM(MSG_RESEND); - SERIAL_PROTOCOLLN(gcode_LastN + 1); - ClearToSend(); -} - -void ClearToSend() -{ - previous_millis_cmd = millis(); - #ifdef SDSUPPORT - if(fromsd[bufindr]) - return; - #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM(MSG_OK); -} - -void get_coordinates() -{ - bool seen[4]={false,false,false,false}; - for(int8_t i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) - { - destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i]; - seen[i]=true; - } - else destination[i] = current_position[i]; //Are these else lines really needed? - } - if(code_seen('F')) { - next_feedrate = code_value(); - if(next_feedrate > 0.0) feedrate = next_feedrate; - } - #ifdef FWRETRACT - if(autoretract_enabled) - if( !(seen[X_AXIS] || seen[Y_AXIS] || seen[Z_AXIS]) && seen[E_AXIS]) - { - float echange=destination[E_AXIS]-current_position[E_AXIS]; - if(echange<-MIN_RETRACT) //retract - { - if(!retracted) - { - - destination[Z_AXIS]+=retract_zlift; //not sure why chaninging current_position negatively does not work. - //if slicer retracted by echange=-1mm and you want to retract 3mm, corrrectede=-2mm additionally - float correctede=-echange-retract_length; - //to generate the additional steps, not the destination is changed, but inversely the current position - current_position[E_AXIS]+=-correctede; - feedrate=retract_feedrate; - retracted=true; - } - - } - else - if(echange>MIN_RETRACT) //retract_recover - { - if(retracted) - { - //current_position[Z_AXIS]+=-retract_zlift; - //if slicer retracted_recovered by echange=+1mm and you want to retract_recover 3mm, corrrectede=2mm additionally - float correctede=-echange+1*retract_length+retract_recover_length; //total unretract=retract_length+retract_recover_length[surplus] - current_position[E_AXIS]+=correctede; //to generate the additional steps, not the destination is changed, but inversely the current position - feedrate=retract_recover_feedrate; - retracted=false; - } - } - - } - #endif //FWRETRACT -} - -void get_arc_coordinates() -{ -#ifdef SF_ARC_FIX - bool relative_mode_backup = relative_mode; - relative_mode = true; -#endif - get_coordinates(); -#ifdef SF_ARC_FIX - relative_mode=relative_mode_backup; -#endif - - if(code_seen('I')) { - offset[0] = code_value(); - } - else { - offset[0] = 0.0; - } - if(code_seen('J')) { - offset[1] = code_value(); - } - else { - offset[1] = 0.0; - } -} - -void clamp_to_software_endstops(float target[3]) -{ - if (min_software_endstops) { - if (target[X_AXIS] < min_pos[X_AXIS]) target[X_AXIS] = min_pos[X_AXIS]; - if (target[Y_AXIS] < min_pos[Y_AXIS]) target[Y_AXIS] = min_pos[Y_AXIS]; - if (target[Z_AXIS] < min_pos[Z_AXIS]) target[Z_AXIS] = min_pos[Z_AXIS]; - } - - if (max_software_endstops) { - if (target[X_AXIS] > max_pos[X_AXIS]) target[X_AXIS] = max_pos[X_AXIS]; - if (target[Y_AXIS] > max_pos[Y_AXIS]) target[Y_AXIS] = max_pos[Y_AXIS]; - if (target[Z_AXIS] > max_pos[Z_AXIS]) target[Z_AXIS] = max_pos[Z_AXIS]; - } -} - -void prepare_move() -{ - clamp_to_software_endstops(destination); - - previous_millis_cmd = millis(); - // Do not use feedmultiply for E or Z only moves - if( (current_position[X_AXIS] == destination [X_AXIS]) && (current_position[Y_AXIS] == destination [Y_AXIS])) { - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - } - else { - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder); - } - for(int8_t i=0; i < NUM_AXIS; i++) { - current_position[i] = destination[i]; - } -} - -void prepare_arc_move(char isclockwise) { - float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc - - // Trace the arc - mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise, active_extruder); - - // As far as the parser is concerned, the position is now == target. In reality the - // motion control system might still be processing the action and the real tool position - // in any intermediate location. - for(int8_t i=0; i < NUM_AXIS; i++) { - current_position[i] = destination[i]; - } - previous_millis_cmd = millis(); -} - -#ifdef CONTROLLERFAN_PIN -unsigned long lastMotor = 0; //Save the time for when a motor was turned on last -unsigned long lastMotorCheck = 0; - -void controllerFan() -{ - if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms - { - lastMotorCheck = millis(); - - if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) - #if EXTRUDERS > 2 - || !READ(E2_ENABLE_PIN) - #endif - #if EXTRUDER > 1 - || !READ(E2_ENABLE_PIN) - #endif - || !READ(E0_ENABLE_PIN)) //If any of the drivers are enabled... - { - lastMotor = millis(); //... set time to NOW so the fan will turn on - } - - if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC... - { - WRITE(CONTROLLERFAN_PIN, LOW); //... turn the fan off - } - else - { - WRITE(CONTROLLERFAN_PIN, HIGH); //... turn the fan on - } - } -} -#endif - -void manage_inactivity() -{ - if( (millis() - previous_millis_cmd) > max_inactive_time ) - if(max_inactive_time) - kill(); - if(stepper_inactive_time) { - if( (millis() - previous_millis_cmd) > stepper_inactive_time ) - { - if(blocks_queued() == false) { - disable_x(); - disable_y(); - disable_z(); - disable_e0(); - disable_e1(); - disable_e2(); - } - } - } - #if( KILL_PIN>-1 ) - if( 0 == READ(KILL_PIN) ) - kill(); - #endif - #ifdef CONTROLLERFAN_PIN - controllerFan(); //Check if fan should be turned on to cool stepper drivers down - #endif - #ifdef EXTRUDER_RUNOUT_PREVENT - if( (millis() - previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) - if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) - { - bool oldstatus=READ(E0_ENABLE_PIN); - enable_e0(); - float oldepos=current_position[E_AXIS]; - float oldedes=destination[E_AXIS]; - plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], - current_position[E_AXIS]+EXTRUDER_RUNOUT_EXTRUDE*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], - EXTRUDER_RUNOUT_SPEED/60.*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], active_extruder); - current_position[E_AXIS]=oldepos; - destination[E_AXIS]=oldedes; - plan_set_e_position(oldepos); - previous_millis_cmd=millis(); - st_synchronize(); - WRITE(E0_ENABLE_PIN,oldstatus); - } - #endif - check_axes_activity(); -} - -void kill() -{ - cli(); // Stop interrupts - disable_heater(); - - disable_x(); - disable_y(); - disable_z(); - disable_e0(); - disable_e1(); - disable_e2(); - - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM(MSG_ERR_KILLED); - LCD_ALERTMESSAGEPGM(MSG_KILLED); - suicide(); - while(1); // Wait for reset -} - -void Stop() -{ - disable_heater(); - if(Stopped == false) { - Stopped = true; - Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); - LCD_MESSAGEPGM(MSG_STOPPED); - } -} - -bool IsStopped() { return Stopped; }; - -#ifdef FAST_PWM_FAN -void setPwmFrequency(uint8_t pin, int val) -{ - val &= 0x07; - switch(digitalPinToTimer(pin)) - { - - #if defined(TCCR0A) - case TIMER0A: - case TIMER0B: -// TCCR0B &= ~(CS00 | CS01 | CS02); -// TCCR0B |= val; - break; - #endif - - #if defined(TCCR1A) - case TIMER1A: - case TIMER1B: -// TCCR1B &= ~(CS10 | CS11 | CS12); -// TCCR1B |= val; - break; - #endif - - #if defined(TCCR2) - case TIMER2: - case TIMER2: - TCCR2 &= ~(CS10 | CS11 | CS12); - TCCR2 |= val; - break; - #endif - - #if defined(TCCR2A) - case TIMER2A: - case TIMER2B: - TCCR2B &= ~(CS20 | CS21 | CS22); - TCCR2B |= val; - break; - #endif - - #if defined(TCCR3A) - case TIMER3A: - case TIMER3B: - case TIMER3C: - TCCR3B &= ~(CS30 | CS31 | CS32); - TCCR3B |= val; - break; - #endif - - #if defined(TCCR4A) - case TIMER4A: - case TIMER4B: - case TIMER4C: - TCCR4B &= ~(CS40 | CS41 | CS42); - TCCR4B |= val; - break; - #endif - - #if defined(TCCR5A) - case TIMER5A: - case TIMER5B: - case TIMER5C: - TCCR5B &= ~(CS50 | CS51 | CS52); - TCCR5B |= val; - break; - #endif - - } -} -#endif //FAST_PWM_FAN - -bool setTargetedHotend(int code){ - tmp_extruder = active_extruder; - if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - switch(code){ - case 104: - SERIAL_ECHO(MSG_M104_INVALID_EXTRUDER); - break; - case 105: - SERIAL_ECHO(MSG_M105_INVALID_EXTRUDER); - break; - case 109: - SERIAL_ECHO(MSG_M109_INVALID_EXTRUDER); - break; - } - SERIAL_ECHOLN(tmp_extruder); - return true; - } - } - return false; -} +#include +#endif diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp new file mode 100644 index 0000000000..ed222b8cf1 --- /dev/null +++ b/Marlin/Marlin_main.cpp @@ -0,0 +1,1865 @@ +/* -*- c++ -*- */ + +/* + Reprap firmware 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 . + */ + +/* + This firmware is a mashup between Sprinter and grbl. + (https://github.com/kliment/Sprinter) + (https://github.com/simen/grbl/tree) + + It has preliminary support for Matthew Roberts advance algorithm + http://reprap.org/pipermail/reprap-dev/2011-May/003323.html + */ + +#include "Marlin.h" + +#include "ultralcd.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" +#include "motion_control.h" +#include "cardreader.h" +#include "watchdog.h" +#include "EEPROMwrite.h" +#include "language.h" +#include "pins_arduino.h" + +#define VERSION_STRING "1.0.0" + +// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html +// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes + +//Implemented Codes +//------------------- +// G0 -> G1 +// G1 - Coordinated Movement X Y Z E +// G2 - CW ARC +// G3 - CCW ARC +// G4 - Dwell S or P +// G10 - retract filament according to settings of M207 +// G11 - retract recover filament according to settings of M208 +// G28 - Home all Axis +// G90 - Use Absolute Coordinates +// G91 - Use Relative Coordinates +// G92 - Set current position to cordinates given + +//RepRap M Codes +// M0 - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled) +// M1 - Same as M0 +// M104 - Set extruder target temp +// M105 - Read current temp +// M106 - Fan on +// M107 - Fan off +// M109 - Wait for extruder current temp to reach target temp. +// M114 - Display current position + +//Custom M Codes +// M17 - Enable/Power all stepper motors +// M18 - Disable all stepper motors; same as M84 +// M20 - List SD card +// M21 - Init SD card +// M22 - Release SD card +// M23 - Select SD file (M23 filename.g) +// M24 - Start/resume SD print +// M25 - Pause SD print +// M26 - Set SD position in bytes (M26 S12345) +// M27 - Report SD print status +// M28 - Start SD write (M28 filename.g) +// M29 - Stop SD write +// M30 - Delete file from SD (M30 filename.g) +// M31 - Output time since last M109 or SD card start to serial +// M42 - Change pin status via gcode +// M80 - Turn on Power Supply +// M81 - Turn off Power Supply +// M82 - Set E codes absolute (default) +// M83 - Set E codes relative while in Absolute Coordinates (G90) mode +// M84 - Disable steppers until next move, +// or use S to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. +// M85 - Set inactivity shutdown timer with parameter S. To disable set zero (default) +// M92 - Set axis_steps_per_unit - same syntax as G92 +// M114 - Output current position to serial port +// M115 - Capabilities string +// M117 - display message +// M119 - Output Endstop status to serial port +// M140 - Set bed target temp +// M190 - Wait for bed current temp to reach target temp. +// M200 - Set filament diameter +// M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) +// M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!! +// M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec +// M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate +// M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk, E=maximum E jerk +// M206 - set additional homeing offset +// M207 - set retract length S[positive mm] F[feedrate mm/sec] Z[additional zlift/hop] +// M208 - set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/sec] +// M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction. +// M220 S- set speed factor override percentage +// M221 S- set extrude factor override percentage +// M240 - Trigger a camera to take a photograph +// M301 - Set PID parameters P I and D +// M302 - Allow cold extrudes +// M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) +// M304 - Set bed PID parameters P I and D +// M400 - Finish all moves +// M500 - stores paramters in EEPROM +// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). +// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. +// M503 - print the current settings (from memory not from eeprom) +// M999 - Restart after being stopped by error + +//Stepper Movement Variables + +//=========================================================================== +//=============================imported variables============================ +//=========================================================================== + + +//=========================================================================== +//=============================public variables============================= +//=========================================================================== +#ifdef SDSUPPORT +CardReader card; +#endif +float homing_feedrate[] = HOMING_FEEDRATE; +bool axis_relative_modes[] = AXIS_RELATIVE_MODES; +volatile int feedmultiply=100; //100->1 200->2 +int saved_feedmultiply; +volatile bool feedmultiplychanged=false; +volatile int extrudemultiply=100; //100->1 200->2 +float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 }; +float add_homeing[3]={0,0,0}; +float min_pos[3] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS }; +float max_pos[3] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS }; +uint8_t active_extruder = 0; +unsigned char FanSpeed=0; + +#ifdef FWRETRACT + bool autoretract_enabled=true; + bool retracted=false; + float retract_length=3, retract_feedrate=17*60, retract_zlift=0.8; + float retract_recover_length=0, retract_recover_feedrate=8*60; +#endif + +//=========================================================================== +//=============================private variables============================= +//=========================================================================== +const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; +static float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; +static float offset[3] = {0.0, 0.0, 0.0}; +static bool home_all_axis = true; +static float feedrate = 1500.0, next_feedrate, saved_feedrate; +static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0; + +static bool relative_mode = false; //Determines Absolute or Relative Coordinates + +static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; +static bool fromsd[BUFSIZE]; +static int bufindr = 0; +static int bufindw = 0; +static int buflen = 0; +//static int i = 0; +static char serial_char; +static int serial_count = 0; +static boolean comment_mode = false; +static char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc + +const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 + +//static float tt = 0; +//static float bt = 0; + +//Inactivity shutdown variables +static unsigned long previous_millis_cmd = 0; +static unsigned long max_inactive_time = 0; +static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l; + +unsigned long starttime=0; +unsigned long stoptime=0; + +static uint8_t tmp_extruder; + + +bool Stopped=false; + +//=========================================================================== +//=============================ROUTINES============================= +//=========================================================================== + +void get_arc_coordinates(); +bool setTargetedHotend(int code); + +void serial_echopair_P(const char *s_P, float v) + { serialprintPGM(s_P); SERIAL_ECHO(v); } +void serial_echopair_P(const char *s_P, double v) + { serialprintPGM(s_P); SERIAL_ECHO(v); } +void serial_echopair_P(const char *s_P, unsigned long v) + { serialprintPGM(s_P); SERIAL_ECHO(v); } + +extern "C"{ + extern unsigned int __bss_end; + extern unsigned int __heap_start; + extern void *__brkval; + + int freeMemory() { + int free_memory; + + if((int)__brkval == 0) + free_memory = ((int)&free_memory) - ((int)&__bss_end); + else + free_memory = ((int)&free_memory) - ((int)__brkval); + + return free_memory; + } +} + +//adds an command to the main command buffer +//thats really done in a non-safe way. +//needs overworking someday +void enquecommand(const char *cmd) +{ + if(buflen < BUFSIZE) + { + //this is dangerous if a mixing of serial and this happsens + strcpy(&(cmdbuffer[bufindw][0]),cmd); + SERIAL_ECHO_START; + SERIAL_ECHOPGM("enqueing \""); + SERIAL_ECHO(cmdbuffer[bufindw]); + SERIAL_ECHOLNPGM("\""); + bufindw= (bufindw + 1)%BUFSIZE; + buflen += 1; + } +} + +void setup_killpin() +{ + #if( KILL_PIN>-1 ) + pinMode(KILL_PIN,INPUT); + WRITE(KILL_PIN,HIGH); + #endif +} + +void setup_photpin() +{ + #ifdef PHOTOGRAPH_PIN + #if (PHOTOGRAPH_PIN > -1) + SET_OUTPUT(PHOTOGRAPH_PIN); + WRITE(PHOTOGRAPH_PIN, LOW); + #endif + #endif +} + +void setup_powerhold() +{ + #ifdef SUICIDE_PIN + #if (SUICIDE_PIN> -1) + SET_OUTPUT(SUICIDE_PIN); + WRITE(SUICIDE_PIN, HIGH); + #endif + #endif +} + +void suicide() +{ + #ifdef SUICIDE_PIN + #if (SUICIDE_PIN> -1) + SET_OUTPUT(SUICIDE_PIN); + WRITE(SUICIDE_PIN, LOW); + #endif + #endif +} + +void setup() +{ + setup_killpin(); + setup_powerhold(); + 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(VERSION_STRING); + #ifdef STRING_VERSION_CONFIG_H + #ifdef STRING_CONFIG_H_AUTHOR + SERIAL_ECHO_START; + SERIAL_ECHOPGM(MSG_CONFIGURATION_VER); + SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); + SERIAL_ECHOPGM(MSG_AUTHOR); + SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); + #endif + #endif + 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); + for(int8_t i = 0; i < BUFSIZE; i++) + { + fromsd[i] = false; + } + + EEPROM_RetrieveSettings(); // loads data from EEPROM if available + + for(int8_t i=0; i < NUM_AXIS; i++) + { + axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; + } + + + tp_init(); // Initialize temperature loop + plan_init(); // Initialize planner; + watchdog_init(); + st_init(); // Initialize stepper, this enables interrupts! + setup_photpin(); + + LCD_INIT; +} + + +void loop() +{ + if(buflen < (BUFSIZE-1)) + get_command(); + #ifdef SDSUPPORT + card.checkautostart(false); + #endif + if(buflen) + { + #ifdef SDSUPPORT + if(card.saving) + { + if(strstr(cmdbuffer[bufindr],"M29") == NULL) + { + card.write_command(cmdbuffer[bufindr]); + SERIAL_PROTOCOLLNPGM(MSG_OK); + } + else + { + card.closefile(); + SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED); + } + } + else + { + process_commands(); + } + #else + process_commands(); + #endif //SDSUPPORT + buflen = (buflen-1); + bufindr = (bufindr + 1)%BUFSIZE; + } + //check heater every n milliseconds + manage_heater(); + manage_inactivity(); + checkHitEndstops(); + LCD_STATUS; +} + +void get_command() +{ + while( MYSERIAL.available() > 0 && buflen < BUFSIZE) { + serial_char = MYSERIAL.read(); + if(serial_char == '\n' || + serial_char == '\r' || + (serial_char == ':' && comment_mode == false) || + serial_count >= (MAX_CMD_SIZE - 1) ) + { + if(!serial_count) { //if empty line + comment_mode = false; //for new command + return; + } + cmdbuffer[bufindw][serial_count] = 0; //terminate string + if(!comment_mode){ + comment_mode = false; //for new command + fromsd[bufindw] = false; + if(strstr(cmdbuffer[bufindw], "N") != NULL) + { + strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); + gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10)); + if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) { + SERIAL_ERROR_START; + SERIAL_ERRORPGM(MSG_ERR_LINE_NO); + SERIAL_ERRORLN(gcode_LastN); + //Serial.println(gcode_N); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + + if(strstr(cmdbuffer[bufindw], "*") != NULL) + { + byte checksum = 0; + byte count = 0; + while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; + strchr_pointer = strchr(cmdbuffer[bufindw], '*'); + + if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) { + SERIAL_ERROR_START; + SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH); + SERIAL_ERRORLN(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + //if no errors, continue parsing + } + else + { + SERIAL_ERROR_START; + SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM); + SERIAL_ERRORLN(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + + gcode_LastN = gcode_N; + //if no errors, continue parsing + } + else // if we don't receive 'N' but still see '*' + { + if((strstr(cmdbuffer[bufindw], "*") != NULL)) + { + SERIAL_ERROR_START; + SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM); + SERIAL_ERRORLN(gcode_LastN); + serial_count = 0; + return; + } + } + if((strstr(cmdbuffer[bufindw], "G") != NULL)){ + strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); + switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){ + case 0: + case 1: + case 2: + case 3: + if(Stopped == false) { // If printer is stopped by an error the G[0-3] codes are ignored. + #ifdef SDSUPPORT + if(card.saving) + break; + #endif //SDSUPPORT + SERIAL_PROTOCOLLNPGM(MSG_OK); + } + else { + SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); + LCD_MESSAGEPGM(MSG_STOPPED); + } + break; + default: + break; + } + + } + bufindw = (bufindw + 1)%BUFSIZE; + buflen += 1; + } + serial_count = 0; //clear buffer + } + else + { + if(serial_char == ';') comment_mode = true; + if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; + } + } + #ifdef SDSUPPORT + if(!card.sdprinting || serial_count!=0){ + return; + } + while( !card.eof() && buflen < BUFSIZE) { + int16_t n=card.get(); + serial_char = (char)n; + if(serial_char == '\n' || + serial_char == '\r' || + (serial_char == ':' && comment_mode == false) || + serial_count >= (MAX_CMD_SIZE - 1)||n==-1) + { + if(card.eof()){ + SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED); + stoptime=millis(); + char time[30]; + unsigned long t=(stoptime-starttime)/1000; + int sec,min; + min=t/60; + sec=t%60; + sprintf(time,"%i min, %i sec",min,sec); + SERIAL_ECHO_START; + SERIAL_ECHOLN(time); + LCD_MESSAGE(time); + card.printingHasFinished(); + card.checkautostart(true); + + } + if(!serial_count) + { + comment_mode = false; //for new command + return; //if empty line + } + cmdbuffer[bufindw][serial_count] = 0; //terminate string +// if(!comment_mode){ + fromsd[bufindw] = true; + buflen += 1; + bufindw = (bufindw + 1)%BUFSIZE; +// } + comment_mode = false; //for new command + serial_count = 0; //clear buffer + } + else + { + if(serial_char == ';') comment_mode = true; + if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; + } + } + + #endif //SDSUPPORT + +} + + +float code_value() +{ + return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); +} + +long code_value_long() +{ + return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); +} + +bool code_seen(char code_string[]) //Return True if the string was found +{ + return (strstr(cmdbuffer[bufindr], code_string) != NULL); +} + +bool code_seen(char code) +{ + strchr_pointer = strchr(cmdbuffer[bufindr], code); + return (strchr_pointer != NULL); //Return True if a character was found +} + +#define DEFINE_PGM_READ_ANY(type, reader) \ + static inline type pgm_read_any(const type *p) \ + { return pgm_read_##reader##_near(p); } + +DEFINE_PGM_READ_ANY(float, float); +DEFINE_PGM_READ_ANY(signed char, byte); + +#define XYZ_CONSTS_FROM_CONFIG(type, array, CONFIG) \ +static const PROGMEM type array##_P[3] = \ + { X_##CONFIG, Y_##CONFIG, Z_##CONFIG }; \ +static inline type array(int axis) \ + { return pgm_read_any(&array##_P[axis]); } + +XYZ_CONSTS_FROM_CONFIG(float, base_min_pos, MIN_POS); +XYZ_CONSTS_FROM_CONFIG(float, base_max_pos, MAX_POS); +XYZ_CONSTS_FROM_CONFIG(float, base_home_pos, HOME_POS); +XYZ_CONSTS_FROM_CONFIG(float, max_length, MAX_LENGTH); +XYZ_CONSTS_FROM_CONFIG(float, home_retract_mm, HOME_RETRACT_MM); +XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR); + +static void axis_is_at_home(int axis) { + current_position[axis] = base_home_pos(axis) + add_homeing[axis]; + min_pos[axis] = base_min_pos(axis) + add_homeing[axis]; + max_pos[axis] = base_max_pos(axis) + add_homeing[axis]; +} + +static void homeaxis(int axis) { +#define HOMEAXIS_DO(LETTER) \ + ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1)) + + if (axis==X_AXIS ? HOMEAXIS_DO(X) : + axis==Y_AXIS ? HOMEAXIS_DO(Y) : + axis==Z_AXIS ? HOMEAXIS_DO(Z) : + 0) { + current_position[axis] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[axis] = 1.5 * max_length(axis) * home_dir(axis); + feedrate = homing_feedrate[axis]; + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + + current_position[axis] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[axis] = -home_retract_mm(axis) * home_dir(axis); + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + + destination[axis] = 2*home_retract_mm(axis) * home_dir(axis); + feedrate = homing_feedrate[axis]/2 ; + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + + axis_is_at_home(axis); + destination[axis] = current_position[axis]; + feedrate = 0.0; + endstops_hit_on_purpose(); + } +} +#define HOMEAXIS(LETTER) homeaxis(LETTER##_AXIS) + +void process_commands() +{ + unsigned long codenum; //throw away variable + char *starpos = NULL; + + if(code_seen('G')) + { + switch((int)code_value()) + { + case 0: // G0 -> G1 + case 1: // G1 + if(Stopped == false) { + get_coordinates(); // For X Y Z E F + prepare_move(); + //ClearToSend(); + return; + } + //break; + case 2: // G2 - CW ARC + if(Stopped == false) { + get_arc_coordinates(); + prepare_arc_move(true); + return; + } + case 3: // G3 - CCW ARC + if(Stopped == false) { + get_arc_coordinates(); + prepare_arc_move(false); + return; + } + case 4: // G4 dwell + LCD_MESSAGEPGM(MSG_DWELL); + codenum = 0; + if(code_seen('P')) codenum = code_value(); // milliseconds to wait + if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait + + st_synchronize(); + codenum += millis(); // keep track of when we started waiting + previous_millis_cmd = millis(); + while(millis() < codenum ){ + manage_heater(); + manage_inactivity(); + LCD_STATUS; + } + break; + #ifdef FWRETRACT + case 10: // G10 retract + if(!retracted) + { + destination[X_AXIS]=current_position[X_AXIS]; + destination[Y_AXIS]=current_position[Y_AXIS]; + destination[Z_AXIS]=current_position[Z_AXIS]; + current_position[Z_AXIS]+=-retract_zlift; + destination[E_AXIS]=current_position[E_AXIS]-retract_length; + feedrate=retract_feedrate; + retracted=true; + prepare_move(); + } + + break; + case 11: // G10 retract_recover + if(!retracted) + { + destination[X_AXIS]=current_position[X_AXIS]; + destination[Y_AXIS]=current_position[Y_AXIS]; + destination[Z_AXIS]=current_position[Z_AXIS]; + + current_position[Z_AXIS]+=retract_zlift; + current_position[E_AXIS]+=-retract_recover_length; + feedrate=retract_recover_feedrate; + retracted=false; + prepare_move(); + } + break; + #endif //FWRETRACT + case 28: //G28 Home all Axis one at a time + saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + previous_millis_cmd = millis(); + + enable_endstops(true); + + for(int8_t i=0; i < NUM_AXIS; i++) { + destination[i] = current_position[i]; + } + feedrate = 0.0; + home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); + + #if Z_HOME_DIR > 0 // If homing away from BED do Z first + if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { + HOMEAXIS(Z); + } + #endif + + #ifdef QUICK_HOME + if((home_all_axis)||( code_seen(axis_codes[X_AXIS]) && code_seen(axis_codes[Y_AXIS])) ) //first diagonal move + { + current_position[X_AXIS] = 0;current_position[Y_AXIS] = 0; + + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; + feedrate = homing_feedrate[X_AXIS]; + if(homing_feedrate[Y_AXIS] 0){ + codenum += millis(); // keep track of when we started waiting + while(millis() < codenum && !CLICKED){ + manage_heater(); + manage_inactivity(); + LCD_STATUS; + } + }else{ + while(!CLICKED){ + manage_heater(); + manage_inactivity(); + LCD_STATUS; + } + } + } + break; +#endif + case 17: + LCD_MESSAGEPGM(MSG_NO_MOVE); + enable_x(); + enable_y(); + enable_z(); + enable_e0(); + enable_e1(); + enable_e2(); + break; + +#ifdef SDSUPPORT + case 20: // M20 - list SD card + SERIAL_PROTOCOLLNPGM(MSG_BEGIN_FILE_LIST); + card.ls(); + SERIAL_PROTOCOLLNPGM(MSG_END_FILE_LIST); + break; + case 21: // M21 - init SD card + + card.initsd(); + + break; + case 22: //M22 - release SD card + card.release(); + + break; + case 23: //M23 - Select file + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos!=NULL) + *(starpos-1)='\0'; + card.openFile(strchr_pointer + 4,true); + break; + case 24: //M24 - Start SD print + card.startFileprint(); + starttime=millis(); + break; + case 25: //M25 - Pause SD print + card.pauseSDPrint(); + break; + case 26: //M26 - Set SD index + if(card.cardOK && code_seen('S')) { + card.setIndex(code_value_long()); + } + break; + case 27: //M27 - Get SD status + card.getStatus(); + break; + case 28: //M28 - Start SD write + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos != NULL){ + char* npos = strchr(cmdbuffer[bufindr], 'N'); + strchr_pointer = strchr(npos,' ') + 1; + *(starpos-1) = '\0'; + } + card.openFile(strchr_pointer+4,false); + break; + case 29: //M29 - Stop SD write + //processed in write to file routine above + //card,saving = false; + break; + case 30: //M30 Delete File + if (card.cardOK){ + card.closefile(); + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos != NULL){ + char* npos = strchr(cmdbuffer[bufindr], 'N'); + strchr_pointer = strchr(npos,' ') + 1; + *(starpos-1) = '\0'; + } + card.removeFile(strchr_pointer + 4); + } + break; + +#endif //SDSUPPORT + + case 31: //M31 take time since the start of the SD print or an M109 command + { + stoptime=millis(); + char time[30]; + unsigned long t=(stoptime-starttime)/1000; + int sec,min; + min=t/60; + sec=t%60; + sprintf(time,"%i min, %i sec",min,sec); + SERIAL_ECHO_START; + SERIAL_ECHOLN(time); + LCD_MESSAGE(time); + autotempShutdown(); + } + break; + case 42: //M42 -Change pin status via gcode + if (code_seen('S')) + { + int pin_status = code_value(); + if (code_seen('P') && pin_status >= 0 && pin_status <= 255) + { + int pin_number = code_value(); + for(int8_t i = 0; i < (int8_t)sizeof(sensitive_pins); i++) + { + if (sensitive_pins[i] == pin_number) + { + pin_number = -1; + break; + } + } + + if (pin_number > -1) + { + pinMode(pin_number, OUTPUT); + digitalWrite(pin_number, pin_status); + analogWrite(pin_number, pin_status); + } + } + } + break; + case 104: // M104 + if(setTargetedHotend(104)){ + break; + } + if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder); + setWatch(); + break; + case 140: // M140 set bed temp + if (code_seen('S')) setTargetBed(code_value()); + break; + case 105 : // M105 + if(setTargetedHotend(105)){ + break; + } + #if (TEMP_0_PIN > -1) + SERIAL_PROTOCOLPGM("ok T:"); + SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); + SERIAL_PROTOCOLPGM(" /"); + SERIAL_PROTOCOL_F(degTargetHotend(tmp_extruder),1); + #if TEMP_BED_PIN > -1 + SERIAL_PROTOCOLPGM(" B:"); + SERIAL_PROTOCOL_F(degBed(),1); + SERIAL_PROTOCOLPGM(" /"); + SERIAL_PROTOCOL_F(degTargetBed(),1); + #endif //TEMP_BED_PIN + #else + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS); + #endif + + SERIAL_PROTOCOLPGM(" @:"); + SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); + + SERIAL_PROTOCOLPGM(" B@:"); + SERIAL_PROTOCOL(getHeaterPower(-1)); + + SERIAL_PROTOCOLLN(""); + return; + break; + case 109: + {// M109 - Wait for extruder heater to reach target. + if(setTargetedHotend(109)){ + break; + } + LCD_MESSAGEPGM(MSG_HEATING); + #ifdef AUTOTEMP + autotemp_enabled=false; + #endif + if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder); + #ifdef AUTOTEMP + if (code_seen('S')) autotemp_min=code_value(); + if (code_seen('B')) autotemp_max=code_value(); + if (code_seen('F')) + { + autotemp_factor=code_value(); + autotemp_enabled=true; + } + #endif + + setWatch(); + codenum = millis(); + + /* See if we are heating up or cooling down */ + bool target_direction = isHeatingHotend(tmp_extruder); // true if heating, false if cooling + + #ifdef TEMP_RESIDENCY_TIME + long residencyStart; + residencyStart = -1; + /* continue to loop until we have reached the target temp + _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */ + while((residencyStart == -1) || + (residencyStart >= 0 && (((unsigned int) (millis() - residencyStart)) < (TEMP_RESIDENCY_TIME * 1000UL))) ) { + #else + while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { + #endif //TEMP_RESIDENCY_TIME + if( (millis() - codenum) > 1000UL ) + { //Print Temp Reading and remaining time every 1 second while heating up/cooling down + SERIAL_PROTOCOLPGM("T:"); + SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); + SERIAL_PROTOCOLPGM(" E:"); + SERIAL_PROTOCOL((int)tmp_extruder); + #ifdef TEMP_RESIDENCY_TIME + SERIAL_PROTOCOLPGM(" W:"); + if(residencyStart > -1) + { + codenum = ((TEMP_RESIDENCY_TIME * 1000UL) - (millis() - residencyStart)) / 1000UL; + SERIAL_PROTOCOLLN( codenum ); + } + else + { + SERIAL_PROTOCOLLN( "?" ); + } + #else + SERIAL_PROTOCOLLN(""); + #endif + codenum = millis(); + } + manage_heater(); + manage_inactivity(); + LCD_STATUS; + #ifdef TEMP_RESIDENCY_TIME + /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time + or when current temp falls outside the hysteresis after target temp was reached */ + if ((residencyStart == -1 && target_direction && (degHotend(tmp_extruder) >= (degTargetHotend(tmp_extruder)-TEMP_WINDOW))) || + (residencyStart == -1 && !target_direction && (degHotend(tmp_extruder) <= (degTargetHotend(tmp_extruder)+TEMP_WINDOW))) || + (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) ) + { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGEPGM(MSG_HEATING_COMPLETE); + starttime=millis(); + previous_millis_cmd = millis(); + } + break; + case 190: // M190 - Wait for bed heater to reach target. + #if TEMP_BED_PIN > -1 + LCD_MESSAGEPGM(MSG_BED_HEATING); + if (code_seen('S')) setTargetBed(code_value()); + codenum = millis(); + while(isHeatingBed()) + { + if(( millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + { + float tt=degHotend(active_extruder); + SERIAL_PROTOCOLPGM("T:"); + SERIAL_PROTOCOL(tt); + SERIAL_PROTOCOLPGM(" E:"); + SERIAL_PROTOCOL((int)active_extruder); + SERIAL_PROTOCOLPGM(" B:"); + SERIAL_PROTOCOL_F(degBed(),1); + SERIAL_PROTOCOLLN(""); + codenum = millis(); + } + manage_heater(); + manage_inactivity(); + LCD_STATUS; + } + LCD_MESSAGEPGM(MSG_BED_DONE); + previous_millis_cmd = millis(); + #endif + break; + + #if FAN_PIN > -1 + case 106: //M106 Fan On + if (code_seen('S')){ + FanSpeed=constrain(code_value(),0,255); + } + else { + FanSpeed=255; + } + break; + case 107: //M107 Fan Off + FanSpeed = 0; + break; + #endif //FAN_PIN + + #if (PS_ON_PIN > -1) + case 80: // M80 - ATX Power On + SET_OUTPUT(PS_ON_PIN); //GND + WRITE(PS_ON_PIN, LOW); + break; + #endif + + case 81: // M81 - ATX Power Off + + #if defined SUICIDE_PIN && SUICIDE_PIN > -1 + st_synchronize(); + suicide(); + #elif (PS_ON_PIN > -1) + SET_OUTPUT(PS_ON_PIN); + WRITE(PS_ON_PIN, HIGH); + #endif + break; + + case 82: + axis_relative_modes[3] = false; + break; + case 83: + axis_relative_modes[3] = true; + break; + case 18: //compatibility + case 84: // M84 + if(code_seen('S')){ + stepper_inactive_time = code_value() * 1000; + } + else + { + bool all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))|| (code_seen(axis_codes[3]))); + if(all_axis) + { + st_synchronize(); + disable_e0(); + disable_e1(); + disable_e2(); + finishAndDisableSteppers(); + } + else + { + st_synchronize(); + if(code_seen('X')) disable_x(); + if(code_seen('Y')) disable_y(); + if(code_seen('Z')) disable_z(); + #if ((E0_ENABLE_PIN != X_ENABLE_PIN) && (E1_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS + if(code_seen('E')) { + disable_e0(); + disable_e1(); + disable_e2(); + } + #endif + LCD_MESSAGEPGM(MSG_PART_RELEASE); + } + } + break; + case 85: // M85 + code_seen('S'); + max_inactive_time = code_value() * 1000; + break; + case 92: // M92 + for(int8_t i=0; i < NUM_AXIS; i++) + { + if(code_seen(axis_codes[i])) + { + if(i == 3) { // E + float value = code_value(); + if(value < 20.0) { + float factor = axis_steps_per_unit[i] / value; // increase e constants if M92 E14 is given for netfab. + max_e_jerk *= factor; + max_feedrate[i] *= factor; + axis_steps_per_sqr_second[i] *= factor; + } + axis_steps_per_unit[i] = value; + } + else { + axis_steps_per_unit[i] = code_value(); + } + } + } + break; + case 115: // M115 + SERIAL_PROTOCOLPGM(MSG_M115_REPORT); + break; + case 117: // M117 display message + LCD_MESSAGE(cmdbuffer[bufindr]+5); + break; + case 114: // M114 + SERIAL_PROTOCOLPGM("X:"); + SERIAL_PROTOCOL(current_position[X_AXIS]); + SERIAL_PROTOCOLPGM("Y:"); + SERIAL_PROTOCOL(current_position[Y_AXIS]); + SERIAL_PROTOCOLPGM("Z:"); + SERIAL_PROTOCOL(current_position[Z_AXIS]); + SERIAL_PROTOCOLPGM("E:"); + SERIAL_PROTOCOL(current_position[E_AXIS]); + + SERIAL_PROTOCOLPGM(MSG_COUNT_X); + SERIAL_PROTOCOL(float(st_get_position(X_AXIS))/axis_steps_per_unit[X_AXIS]); + SERIAL_PROTOCOLPGM("Y:"); + SERIAL_PROTOCOL(float(st_get_position(Y_AXIS))/axis_steps_per_unit[Y_AXIS]); + SERIAL_PROTOCOLPGM("Z:"); + SERIAL_PROTOCOL(float(st_get_position(Z_AXIS))/axis_steps_per_unit[Z_AXIS]); + + SERIAL_PROTOCOLLN(""); + break; + case 120: // M120 + enable_endstops(false) ; + break; + case 121: // M121 + enable_endstops(true) ; + break; + case 119: // M119 + SERIAL_PROTOCOLLN(MSG_M119_REPORT); + #if (X_MIN_PIN > -1) + SERIAL_PROTOCOLPGM(MSG_X_MIN); + SERIAL_PROTOCOLLN(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif + #if (X_MAX_PIN > -1) + SERIAL_PROTOCOLPGM(MSG_X_MAX); + SERIAL_PROTOCOLLN(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif + #if (Y_MIN_PIN > -1) + SERIAL_PROTOCOLPGM(MSG_Y_MIN); + SERIAL_PROTOCOLLN(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif + #if (Y_MAX_PIN > -1) + SERIAL_PROTOCOLPGM(MSG_Y_MAX); + SERIAL_PROTOCOLLN(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif + #if (Z_MIN_PIN > -1) + SERIAL_PROTOCOLPGM(MSG_Z_MIN); + SERIAL_PROTOCOLLN(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif + #if (Z_MAX_PIN > -1) + SERIAL_PROTOCOLPGM(MSG_Z_MAX); + SERIAL_PROTOCOLLN(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif + break; + //TODO: update for all axis, use for loop + case 201: // M201 + for(int8_t i=0; i < NUM_AXIS; i++) + { + if(code_seen(axis_codes[i])) + { + max_acceleration_units_per_sq_second[i] = code_value(); + axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; + } + } + break; + #if 0 // Not used for Sprinter/grbl gen6 + case 202: // M202 + for(int8_t i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; + } + break; + #endif + case 203: // M203 max feedrate mm/sec + for(int8_t i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) max_feedrate[i] = code_value(); + } + break; + case 204: // M204 acclereration S normal moves T filmanent only moves + { + if(code_seen('S')) acceleration = code_value() ; + if(code_seen('T')) retract_acceleration = code_value() ; + } + break; + case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk + { + if(code_seen('S')) minimumfeedrate = code_value(); + if(code_seen('T')) mintravelfeedrate = code_value(); + if(code_seen('B')) minsegmenttime = code_value() ; + if(code_seen('X')) max_xy_jerk = code_value() ; + if(code_seen('Z')) max_z_jerk = code_value() ; + if(code_seen('E')) max_e_jerk = code_value() ; + } + break; + case 206: // M206 additional homeing offset + for(int8_t i=0; i < 3; i++) + { + if(code_seen(axis_codes[i])) add_homeing[i] = code_value(); + } + break; + #ifdef FWRETRACT + case 207: //M207 - set retract length S[positive mm] F[feedrate mm/sec] Z[additional zlift/hop] + { + if(code_seen('S')) + { + retract_length = code_value() ; + } + if(code_seen('F')) + { + retract_feedrate = code_value() ; + } + if(code_seen('Z')) + { + retract_zlift = code_value() ; + } + }break; + case 208: // M208 - set retract recover length S[positive mm surplus to the M207 S*] F[feedrate mm/sec] + { + if(code_seen('S')) + { + retract_recover_length = code_value() ; + } + if(code_seen('F')) + { + retract_recover_feedrate = code_value() ; + } + }break; + + case 209: // M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction. + { + if(code_seen('S')) + { + int t= code_value() ; + switch(t) + { + case 0: autoretract_enabled=false;retracted=false;break; + case 1: autoretract_enabled=true;retracted=false;break; + default: + SERIAL_ECHO_START; + SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND); + SERIAL_ECHO(cmdbuffer[bufindr]); + SERIAL_ECHOLNPGM("\""); + } + } + + }break; + #endif + case 220: // M220 S- set speed factor override percentage + { + if(code_seen('S')) + { + feedmultiply = code_value() ; + feedmultiplychanged=true; + } + } + break; + case 221: // M221 S- set extrude factor override percentage + { + if(code_seen('S')) + { + extrudemultiply = code_value() ; + } + } + break; + + #ifdef PIDTEMP + case 301: // M301 + { + if(code_seen('P')) Kp = code_value(); + if(code_seen('I')) Ki = code_value()*PID_dT; + if(code_seen('D')) Kd = code_value()/PID_dT; + #ifdef PID_ADD_EXTRUSION_RATE + if(code_seen('C')) Kc = code_value(); + #endif + updatePID(); + SERIAL_PROTOCOL(MSG_OK); + SERIAL_PROTOCOL(" p:"); + SERIAL_PROTOCOL(Kp); + SERIAL_PROTOCOL(" i:"); + SERIAL_PROTOCOL(Ki/PID_dT); + SERIAL_PROTOCOL(" d:"); + SERIAL_PROTOCOL(Kd*PID_dT); + #ifdef PID_ADD_EXTRUSION_RATE + SERIAL_PROTOCOL(" c:"); + SERIAL_PROTOCOL(Kc*PID_dT); + #endif + SERIAL_PROTOCOLLN(""); + } + break; + #endif //PIDTEMP + #ifdef PIDTEMPBED + case 304: // M304 + { + if(code_seen('P')) bedKp = code_value(); + if(code_seen('I')) bedKi = code_value()*PID_dT; + if(code_seen('D')) bedKd = code_value()/PID_dT; + updatePID(); + SERIAL_PROTOCOL(MSG_OK); + SERIAL_PROTOCOL(" p:"); + SERIAL_PROTOCOL(bedKp); + SERIAL_PROTOCOL(" i:"); + SERIAL_PROTOCOL(bedKi/PID_dT); + SERIAL_PROTOCOL(" d:"); + SERIAL_PROTOCOL(bedKd*PID_dT); + SERIAL_PROTOCOLLN(""); + } + break; + #endif //PIDTEMP + case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/ + { + #ifdef PHOTOGRAPH_PIN + #if (PHOTOGRAPH_PIN > -1) + const uint8_t NUM_PULSES=16; + const float PULSE_LENGTH=0.01524; + for(int i=0; i < NUM_PULSES; i++) { + WRITE(PHOTOGRAPH_PIN, HIGH); + _delay_ms(PULSE_LENGTH); + WRITE(PHOTOGRAPH_PIN, LOW); + _delay_ms(PULSE_LENGTH); + } + delay(7.33); + for(int i=0; i < NUM_PULSES; i++) { + WRITE(PHOTOGRAPH_PIN, HIGH); + _delay_ms(PULSE_LENGTH); + WRITE(PHOTOGRAPH_PIN, LOW); + _delay_ms(PULSE_LENGTH); + } + #endif + #endif + } + break; + + case 302: // allow cold extrudes + { + allow_cold_extrudes(true); + } + break; + case 303: // M303 PID autotune + { + float temp = 150.0; + int e=0; + int c=5; + if (code_seen('E')) e=code_value(); + if (e<0) + temp=70; + if (code_seen('S')) temp=code_value(); + if (code_seen('C')) c=code_value(); + PID_autotune(temp, e, c); + } + break; + case 400: // M400 finish all moves + { + st_synchronize(); + } + break; + case 500: // Store settings in EEPROM + { + EEPROM_StoreSettings(); + } + break; + case 501: // Read settings from EEPROM + { + EEPROM_RetrieveSettings(); + } + break; + case 502: // Revert to default settings + { + EEPROM_RetrieveSettings(true); + } + break; + case 503: // print settings currently in memory + { + EEPROM_printSettings(); + } + break; + case 999: // Restart after being stopped + Stopped = false; + gcode_LastN = Stopped_gcode_LastN; + FlushSerialRequestResend(); + break; + } + } + + else if(code_seen('T')) + { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHO("T"); + SERIAL_ECHO(tmp_extruder); + SERIAL_ECHOLN(MSG_INVALID_EXTRUDER); + } + else { + active_extruder = tmp_extruder; + SERIAL_ECHO_START; + SERIAL_ECHO(MSG_ACTIVE_EXTRUDER); + SERIAL_PROTOCOLLN((int)active_extruder); + } + } + + else + { + SERIAL_ECHO_START; + SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND); + SERIAL_ECHO(cmdbuffer[bufindr]); + SERIAL_ECHOLNPGM("\""); + } + + ClearToSend(); +} + +void FlushSerialRequestResend() +{ + //char cmdbuffer[bufindr][100]="Resend:"; + MYSERIAL.flush(); + SERIAL_PROTOCOLPGM(MSG_RESEND); + SERIAL_PROTOCOLLN(gcode_LastN + 1); + ClearToSend(); +} + +void ClearToSend() +{ + previous_millis_cmd = millis(); + #ifdef SDSUPPORT + if(fromsd[bufindr]) + return; + #endif //SDSUPPORT + SERIAL_PROTOCOLLNPGM(MSG_OK); +} + +void get_coordinates() +{ + bool seen[4]={false,false,false,false}; + for(int8_t i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) + { + destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i]; + seen[i]=true; + } + else destination[i] = current_position[i]; //Are these else lines really needed? + } + if(code_seen('F')) { + next_feedrate = code_value(); + if(next_feedrate > 0.0) feedrate = next_feedrate; + } + #ifdef FWRETRACT + if(autoretract_enabled) + if( !(seen[X_AXIS] || seen[Y_AXIS] || seen[Z_AXIS]) && seen[E_AXIS]) + { + float echange=destination[E_AXIS]-current_position[E_AXIS]; + if(echange<-MIN_RETRACT) //retract + { + if(!retracted) + { + + destination[Z_AXIS]+=retract_zlift; //not sure why chaninging current_position negatively does not work. + //if slicer retracted by echange=-1mm and you want to retract 3mm, corrrectede=-2mm additionally + float correctede=-echange-retract_length; + //to generate the additional steps, not the destination is changed, but inversely the current position + current_position[E_AXIS]+=-correctede; + feedrate=retract_feedrate; + retracted=true; + } + + } + else + if(echange>MIN_RETRACT) //retract_recover + { + if(retracted) + { + //current_position[Z_AXIS]+=-retract_zlift; + //if slicer retracted_recovered by echange=+1mm and you want to retract_recover 3mm, corrrectede=2mm additionally + float correctede=-echange+1*retract_length+retract_recover_length; //total unretract=retract_length+retract_recover_length[surplus] + current_position[E_AXIS]+=correctede; //to generate the additional steps, not the destination is changed, but inversely the current position + feedrate=retract_recover_feedrate; + retracted=false; + } + } + + } + #endif //FWRETRACT +} + +void get_arc_coordinates() +{ +#ifdef SF_ARC_FIX + bool relative_mode_backup = relative_mode; + relative_mode = true; +#endif + get_coordinates(); +#ifdef SF_ARC_FIX + relative_mode=relative_mode_backup; +#endif + + if(code_seen('I')) { + offset[0] = code_value(); + } + else { + offset[0] = 0.0; + } + if(code_seen('J')) { + offset[1] = code_value(); + } + else { + offset[1] = 0.0; + } +} + +void clamp_to_software_endstops(float target[3]) +{ + if (min_software_endstops) { + if (target[X_AXIS] < min_pos[X_AXIS]) target[X_AXIS] = min_pos[X_AXIS]; + if (target[Y_AXIS] < min_pos[Y_AXIS]) target[Y_AXIS] = min_pos[Y_AXIS]; + if (target[Z_AXIS] < min_pos[Z_AXIS]) target[Z_AXIS] = min_pos[Z_AXIS]; + } + + if (max_software_endstops) { + if (target[X_AXIS] > max_pos[X_AXIS]) target[X_AXIS] = max_pos[X_AXIS]; + if (target[Y_AXIS] > max_pos[Y_AXIS]) target[Y_AXIS] = max_pos[Y_AXIS]; + if (target[Z_AXIS] > max_pos[Z_AXIS]) target[Z_AXIS] = max_pos[Z_AXIS]; + } +} + +void prepare_move() +{ + clamp_to_software_endstops(destination); + + previous_millis_cmd = millis(); + // Do not use feedmultiply for E or Z only moves + if( (current_position[X_AXIS] == destination [X_AXIS]) && (current_position[Y_AXIS] == destination [Y_AXIS])) { + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + } + else { + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder); + } + for(int8_t i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; + } +} + +void prepare_arc_move(char isclockwise) { + float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc + + // Trace the arc + mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise, active_extruder); + + // As far as the parser is concerned, the position is now == target. In reality the + // motion control system might still be processing the action and the real tool position + // in any intermediate location. + for(int8_t i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; + } + previous_millis_cmd = millis(); +} + +#ifdef CONTROLLERFAN_PIN +unsigned long lastMotor = 0; //Save the time for when a motor was turned on last +unsigned long lastMotorCheck = 0; + +void controllerFan() +{ + if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms + { + lastMotorCheck = millis(); + + if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) + #if EXTRUDERS > 2 + || !READ(E2_ENABLE_PIN) + #endif + #if EXTRUDER > 1 + || !READ(E2_ENABLE_PIN) + #endif + || !READ(E0_ENABLE_PIN)) //If any of the drivers are enabled... + { + lastMotor = millis(); //... set time to NOW so the fan will turn on + } + + if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC... + { + WRITE(CONTROLLERFAN_PIN, LOW); //... turn the fan off + } + else + { + WRITE(CONTROLLERFAN_PIN, HIGH); //... turn the fan on + } + } +} +#endif + +void manage_inactivity() +{ + if( (millis() - previous_millis_cmd) > max_inactive_time ) + if(max_inactive_time) + kill(); + if(stepper_inactive_time) { + if( (millis() - previous_millis_cmd) > stepper_inactive_time ) + { + if(blocks_queued() == false) { + disable_x(); + disable_y(); + disable_z(); + disable_e0(); + disable_e1(); + disable_e2(); + } + } + } + #if( KILL_PIN>-1 ) + if( 0 == READ(KILL_PIN) ) + kill(); + #endif + #ifdef CONTROLLERFAN_PIN + controllerFan(); //Check if fan should be turned on to cool stepper drivers down + #endif + #ifdef EXTRUDER_RUNOUT_PREVENT + if( (millis() - previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) + if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) + { + bool oldstatus=READ(E0_ENABLE_PIN); + enable_e0(); + float oldepos=current_position[E_AXIS]; + float oldedes=destination[E_AXIS]; + plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], + current_position[E_AXIS]+EXTRUDER_RUNOUT_EXTRUDE*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], + EXTRUDER_RUNOUT_SPEED/60.*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], active_extruder); + current_position[E_AXIS]=oldepos; + destination[E_AXIS]=oldedes; + plan_set_e_position(oldepos); + previous_millis_cmd=millis(); + st_synchronize(); + WRITE(E0_ENABLE_PIN,oldstatus); + } + #endif + check_axes_activity(); +} + +void kill() +{ + cli(); // Stop interrupts + disable_heater(); + + disable_x(); + disable_y(); + disable_z(); + disable_e0(); + disable_e1(); + disable_e2(); + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_KILLED); + LCD_ALERTMESSAGEPGM(MSG_KILLED); + suicide(); + while(1); // Wait for reset +} + +void Stop() +{ + disable_heater(); + if(Stopped == false) { + Stopped = true; + Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); + LCD_MESSAGEPGM(MSG_STOPPED); + } +} + +bool IsStopped() { return Stopped; }; + +#ifdef FAST_PWM_FAN +void setPwmFrequency(uint8_t pin, int val) +{ + val &= 0x07; + switch(digitalPinToTimer(pin)) + { + + #if defined(TCCR0A) + case TIMER0A: + case TIMER0B: +// TCCR0B &= ~(CS00 | CS01 | CS02); +// TCCR0B |= val; + break; + #endif + + #if defined(TCCR1A) + case TIMER1A: + case TIMER1B: +// TCCR1B &= ~(CS10 | CS11 | CS12); +// TCCR1B |= val; + break; + #endif + + #if defined(TCCR2) + case TIMER2: + case TIMER2: + TCCR2 &= ~(CS10 | CS11 | CS12); + TCCR2 |= val; + break; + #endif + + #if defined(TCCR2A) + case TIMER2A: + case TIMER2B: + TCCR2B &= ~(CS20 | CS21 | CS22); + TCCR2B |= val; + break; + #endif + + #if defined(TCCR3A) + case TIMER3A: + case TIMER3B: + case TIMER3C: + TCCR3B &= ~(CS30 | CS31 | CS32); + TCCR3B |= val; + break; + #endif + + #if defined(TCCR4A) + case TIMER4A: + case TIMER4B: + case TIMER4C: + TCCR4B &= ~(CS40 | CS41 | CS42); + TCCR4B |= val; + break; + #endif + + #if defined(TCCR5A) + case TIMER5A: + case TIMER5B: + case TIMER5C: + TCCR5B &= ~(CS50 | CS51 | CS52); + TCCR5B |= val; + break; + #endif + + } +} +#endif //FAST_PWM_FAN + +bool setTargetedHotend(int code){ + tmp_extruder = active_extruder; + if(code_seen('T')) { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + switch(code){ + case 104: + SERIAL_ECHO(MSG_M104_INVALID_EXTRUDER); + break; + case 105: + SERIAL_ECHO(MSG_M105_INVALID_EXTRUDER); + break; + case 109: + SERIAL_ECHO(MSG_M109_INVALID_EXTRUDER); + break; + } + SERIAL_ECHOLN(tmp_extruder); + return true; + } + } + return false; +} diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index e9439e3b50..29f5efadc1 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -55,13 +55,16 @@ int16_t SdFile::write(const void* buf, uint16_t nbyte) { * Use writeError to check for errors. */ #if ARDUINO >= 100 - size_t SdFile::write(uint8_t b) +size_t SdFile::write(uint8_t b) +{ + return SdBaseFile::write(&b, 1); +} #else - void SdFile::write(uint8_t b) -#endif +void SdFile::write(uint8_t b) { - SdBaseFile::write(&b, 1); + SdBaseFile::write(&b, 1); } +#endif //------------------------------------------------------------------------------ /** Write a string to a file. Used by the Arduino Print class. * \param[in] str Pointer to the string. @@ -89,4 +92,4 @@ void SdFile::writeln_P(PGM_P str) { } -#endif \ No newline at end of file +#endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 6c47e298d5..caee9915be 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -191,8 +191,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exi // have to use intersection_distance() to calculate when to abort acceleration and start braking // in order to reach the final_rate exactly at the end of this block. if (plateau_steps < 0) { - accelerate_steps = ceil( - intersection_distance(block->initial_rate, block->final_rate, acceleration, block->step_event_count)); + accelerate_steps = ceil(intersection_distance(block->initial_rate, block->final_rate, acceleration, block->step_event_count)); accelerate_steps = max(accelerate_steps,0); // Check limits due to numerical round-off accelerate_steps = min(accelerate_steps,block->step_event_count); plateau_steps = 0; diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 66293c7f59..9bc0953609 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -145,20 +145,20 @@ static volatile bool temp_meas_ready = false; void PID_autotune(float temp, int extruder, int ncycles) { - float input; + float input = 0.0; int cycles=0; bool heating = true; unsigned long temp_millis = millis(); unsigned long t1=temp_millis; unsigned long t2=temp_millis; - long t_high; - long t_low; + long t_high = 0; + long t_low = 0; long bias, d; float Ku, Tu; float Kp, Ki, Kd; - float max, min; + float max = 0, min = 10000; if ((extruder > EXTRUDERS) #if (TEMP_BED_PIN <= -1) @@ -315,17 +315,15 @@ int getHeaterPower(int heater) { void manage_heater() { - - #ifdef USE_WATCHDOG - wd_reset(); - #endif - float pid_input; float pid_output; if(temp_meas_ready != true) //better readability return; + //Reset the watchdog after we know we have a temperature measurement. + watchdog_reset(); + CRITICAL_SECTION_START; temp_meas_ready = false; CRITICAL_SECTION_END; @@ -548,7 +546,6 @@ int temp2analogBed(int celsius) { #elif defined BED_USES_AD595 return lround(((celsius-TEMP_SENSOR_AD595_OFFSET)/TEMP_SENSOR_AD595_GAIN) * (1024.0 * OVERSAMPLENR/ (5.0 * 100.0) ) ); #else - #warning No heater-type defined for the bed. return 0; #endif } @@ -625,7 +622,6 @@ float analog2tempBed(int raw) { #elif defined BED_USES_AD595 return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET; #else - #warning No heater-type defined for the bed. return 0; #endif } diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.cpp similarity index 88% rename from Marlin/ultralcd.pde rename to Marlin/ultralcd.cpp index 8a6b8463ff..6245e728dd 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.cpp @@ -6,11 +6,7 @@ #include "language.h" #include "temperature.h" #include "EEPROMwrite.h" -#if LANGUAGE_CHOICE == 6 -#include "LiquidCrystalRus.h" -#else -#include -#endif + //=========================================================================== //=============================imported variables============================ //=========================================================================== @@ -33,6 +29,14 @@ volatile char buttons=0; //the last checked buttons in a bit array. long encoderpos=0; short lastenc=0; +//TODO: This should be in a preferences file. +int plaPreheatHotendTemp; +int plaPreheatHPBTemp; +int plaPreheatFanSpeed; + +int absPreheatHotendTemp; +int absPreheatHPBTemp; +int absPreheatFanSpeed; //=========================================================================== //=============================private variables============================ @@ -42,11 +46,7 @@ static char messagetext[LCD_WIDTH]=""; //return for string conversion routines static char conv[8]; -#if LANGUAGE_CHOICE == 6 -LiquidCrystalRus lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 -#else -LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 -#endif +LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 static unsigned long previous_millis_lcd=0; //static long previous_millis_buttons=0; @@ -70,7 +70,7 @@ void lcdProgMemprint(const char *str) ch=pgm_read_byte(++str); } } -#define lcdprintPGM(x) lcdProgMemprint(MYPGM(x)) +#define LCD_PRINT_PGM(x) lcdProgMemprint(PSTR(x)) //=========================================================================== @@ -366,11 +366,11 @@ void MainMenu::showStatus() { encoderpos=feedmultiply; clear(); - lcd.setCursor(0,0);lcdprintPGM("\002000/000\001 "); + lcd.setCursor(0,0);LCD_PRINT_PGM("\002000/000\001 "); #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcdprintPGM("B000/000\001 "); + lcd.setCursor(10,0);LCD_PRINT_PGM("B000/000\001 "); #elif EXTRUDERS > 1 - lcd.setCursor(10,0);lcdprintPGM("\002000/000\001 "); + lcd.setCursor(10,0);LCD_PRINT_PGM("\002000/000\001 "); #endif } @@ -432,7 +432,7 @@ void MainMenu::showStatus() if(starttime!=oldtime) { - lcd.print(itostr2(time/60));lcdprintPGM("h ");lcd.print(itostr2(time%60));lcdprintPGM("m"); + lcd.print(itostr2(time/60));LCD_PRINT_PGM("h ");lcd.print(itostr2(time%60));LCD_PRINT_PGM("m"); oldtime=time; } } @@ -441,7 +441,7 @@ void MainMenu::showStatus() if((currentz!=oldzpos)||force_lcd_update) { lcd.setCursor(10,1); - lcdprintPGM("Z:");lcd.print(ftostr52(current_position[2])); + LCD_PRINT_PGM("Z:");lcd.print(ftostr52(current_position[2])); oldzpos=currentz; } @@ -468,7 +468,7 @@ void MainMenu::showStatus() { oldfeedmultiply=curfeedmultiply; lcd.setCursor(0,2); - lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% "); + lcd.print(itostr3(curfeedmultiply));LCD_PRINT_PGM("% "); } if(messagetext[0]!='\0') @@ -487,7 +487,7 @@ void MainMenu::showStatus() { lcd.setCursor(10,2); lcd.print(itostr3((int)percent)); - lcdprintPGM("%SD"); + LCD_PRINT_PGM("%SD"); } #endif #else //smaller LCDS---------------------------------- @@ -496,7 +496,7 @@ void MainMenu::showStatus() if(force_lcd_update) //initial display of content { encoderpos=feedmultiply; - lcd.setCursor(0,0);lcdprintPGM("\002---/---\001 "); + lcd.setCursor(0,0);LCD_PRINT_PGM("\002---/---\001 "); } int tHotEnd0=intround(degHotend0()); @@ -550,26 +550,26 @@ void MainMenu::showPrepare() switch(i) { case ItemP_exit: - MENUITEM( lcdprintPGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemP_autostart: - MENUITEM( lcdprintPGM(MSG_AUTOSTART) , BLOCK; + MENUITEM( LCD_PRINT_PGM(MSG_AUTOSTART) , BLOCK; #ifdef SDSUPPORT card.lastnr=0;card.setroot();card.checkautostart(true); #endif beepshort(); ) ; break; case ItemP_disstep: - MENUITEM( lcdprintPGM(MSG_DISABLE_STEPPERS) , BLOCK;enquecommand("M84");beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_DISABLE_STEPPERS) , BLOCK;enquecommand("M84");beepshort(); ) ; break; case ItemP_home: - MENUITEM( lcdprintPGM(MSG_AUTO_HOME) , BLOCK;enquecommand("G28");beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_AUTO_HOME) , BLOCK;enquecommand("G28");beepshort(); ) ; break; case ItemP_origin: - MENUITEM( lcdprintPGM(MSG_SET_ORIGIN) , BLOCK;enquecommand("G92 X0 Y0 Z0");beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_SET_ORIGIN) , BLOCK;enquecommand("G92 X0 Y0 Z0");beepshort(); ) ; break; case ItemP_preheat_pla: - MENUITEM( lcdprintPGM(MSG_PREHEAT_PLA) , BLOCK;setTargetHotend0(plaPreheatHotendTemp);setTargetBed(plaPreheatHPBTemp); + MENUITEM( LCD_PRINT_PGM(MSG_PREHEAT_PLA) , BLOCK;setTargetHotend0(plaPreheatHotendTemp);setTargetBed(plaPreheatHPBTemp); #if FAN_PIN > -1 FanSpeed = plaPreheatFanSpeed; analogWrite(FAN_PIN, FanSpeed); @@ -577,7 +577,7 @@ void MainMenu::showPrepare() beepshort(); ); break; case ItemP_preheat_abs: - MENUITEM( lcdprintPGM(MSG_PREHEAT_ABS) , BLOCK;setTargetHotend0(absPreheatHotendTemp);setTargetBed(absPreheatHPBTemp); + MENUITEM( LCD_PRINT_PGM(MSG_PREHEAT_ABS) , BLOCK;setTargetHotend0(absPreheatHotendTemp);setTargetBed(absPreheatHPBTemp); #if FAN_PIN > -1 FanSpeed = absPreheatFanSpeed; analogWrite(FAN_PIN, FanSpeed); @@ -585,13 +585,13 @@ void MainMenu::showPrepare() beepshort(); ); break; case ItemP_cooldown: - MENUITEM( lcdprintPGM(MSG_COOLDOWN) , BLOCK;setTargetHotend0(0);setTargetHotend1(0);setTargetHotend2(0);setTargetBed(0);beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_COOLDOWN) , BLOCK;setTargetHotend0(0);setTargetHotend1(0);setTargetHotend2(0);setTargetBed(0);beepshort(); ) ; break; // case ItemP_extrude: - // MENUITEM( lcdprintPGM(" Extrude") , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ; + // MENUITEM( LCD_PRINT_PGM(" Extrude") , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ; // break; case ItemP_move: - MENUITEM( lcdprintPGM(MSG_MOVE_AXIS) , BLOCK;status=Sub_PrepareMove;beepshort(); ); + MENUITEM( LCD_PRINT_PGM(MSG_MOVE_AXIS) , BLOCK;status=Sub_PrepareMove;beepshort(); ); break; default: break; @@ -617,14 +617,14 @@ void MainMenu::showAxisMove() switch(i) { case ItemAM_exit: - MENUITEM( lcdprintPGM(MSG_PREPARE_ALT) , BLOCK;status=Main_Prepare;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_PREPARE_ALT) , BLOCK;status=Main_Prepare;beepshort(); ) ; break; case ItemAM_X: { //oldencoderpos=0; if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" X:"); + lcd.setCursor(0,line);LCD_PRINT_PGM(" X:"); lcd.setCursor(11,line);lcd.print(ftostr52(current_position[X_AXIS])); } @@ -669,7 +669,7 @@ void MainMenu::showAxisMove() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Y:"); + lcd.setCursor(0,line);LCD_PRINT_PGM(" Y:"); lcd.setCursor(11,line);lcd.print(ftostr52(current_position[Y_AXIS])); } @@ -714,7 +714,7 @@ void MainMenu::showAxisMove() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Z:"); + lcd.setCursor(0,line);LCD_PRINT_PGM(" Z:"); lcd.setCursor(11,line);lcd.print(ftostr52(current_position[Z_AXIS])); } @@ -757,11 +757,11 @@ void MainMenu::showAxisMove() break; case ItemAM_E: // ErikDB: TODO: this length should be changed for volumetric. - MENUITEM( lcdprintPGM(MSG_EXTRUDE) , BLOCK;enquecommand("G92 E0");enquecommand("G1 F70 E1");beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_EXTRUDE) , BLOCK;enquecommand("G92 E0");enquecommand("G1 F70 E1");beepshort(); ) ; break; case ItemAM_ERetract: // ErikDB: TODO: this length should be changed for volumetric. - MENUITEM( lcdprintPGM(MSG_RETRACT) , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E-1");beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_RETRACT) , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E-1");beepshort(); ) ; break; default: break; @@ -787,13 +787,13 @@ void MainMenu::showTune() switch(i) { case ItemT_exit: - MENUITEM( lcdprintPGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemT_speed: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_SPEED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_SPEED); lcd.setCursor(13,line);lcd.print(ftostr3(feedmultiply)); } @@ -828,7 +828,7 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_NOZZLE); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); } @@ -862,7 +862,7 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_BED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_BED); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetBed()))); } @@ -898,7 +898,7 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_FAN_SPEED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_FAN_SPEED); lcd.setCursor(13,line);lcd.print(ftostr3(FanSpeed)); } @@ -933,7 +933,7 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_FLOW); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_FLOW); lcd.setCursor(13,line);lcd.print(ftostr52(axis_steps_per_unit[E_AXIS])); } @@ -975,22 +975,22 @@ void MainMenu::showTune() updateActiveLines(ItemT_fan,encoderpos); } -//does not work -// #define MENUCHANGEITEM(repaint_action, enter_action, accept_action, change_action) \ -// {\ -// if(force_lcd_update) { lcd.setCursor(0,line); repaint_action; } \ -// if(activeline==line) \ -// { \ -// if(CLICKED) \ -// { \ -// linechanging=!linechanging; \ -// if(linechanging) {enter_action;} \ -// else {accept_action;} \ -// } \ -// else \ -// if(linechanging) {change_action};}\ -// } -// +/*does not work +#define MENUCHANGEITEM(repaint_action, enter_action, accept_action, change_action) \ + {\ + if(force_lcd_update) { lcd.setCursor(0,line); repaint_action; } \ + if(activeline==line) \ + { \ + if(CLICKED) \ + { \ + linechanging=!linechanging; \ + if(linechanging) {enter_action;} \ + else {accept_action;} \ + } \ + else \ + if(linechanging) {change_action};}\ + } +*/ enum { ItemCT_exit,ItemCT_nozzle0, @@ -1022,13 +1022,13 @@ void MainMenu::showControlTemp() switch(i) { case ItemCT_exit: - MENUITEM( lcdprintPGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; break; case ItemCT_nozzle0: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_NOZZLE); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); } @@ -1063,7 +1063,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE1); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_NOZZLE1); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend1()))); } @@ -1099,7 +1099,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE2); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_NOZZLE2); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend2()))); } @@ -1135,7 +1135,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_MIN); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_MIN); lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_min)); } @@ -1169,7 +1169,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_MAX); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_MAX); lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); } @@ -1203,7 +1203,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_FACTOR); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_FACTOR); lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor)); } @@ -1237,12 +1237,12 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_AUTOTEMP); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_AUTOTEMP); lcd.setCursor(13,line); if(autotemp_enabled) - lcdprintPGM(MSG_ON); + LCD_PRINT_PGM(MSG_ON); else - lcdprintPGM(MSG_OFF); + LCD_PRINT_PGM(MSG_OFF); } if((activeline!=line) ) @@ -1253,9 +1253,9 @@ void MainMenu::showControlTemp() autotemp_enabled=!autotemp_enabled; lcd.setCursor(13,line); if(autotemp_enabled) - lcdprintPGM(MSG_ON); + LCD_PRINT_PGM(MSG_ON); else - lcdprintPGM(MSG_OFF); + LCD_PRINT_PGM(MSG_OFF); BLOCK; } @@ -1266,7 +1266,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_BED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_BED); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetBed()))); } @@ -1300,7 +1300,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_FAN_SPEED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_FAN_SPEED); lcd.setCursor(13,line);lcd.print(ftostr3(FanSpeed)); } @@ -1336,7 +1336,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" PID-P: "); + lcd.setCursor(0,line);LCD_PRINT_PGM(" PID-P: "); lcd.setCursor(13,line);lcd.print(itostr4(Kp)); } @@ -1371,7 +1371,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_PID_I); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_PID_I); lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT)); } @@ -1406,7 +1406,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_PID_D); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_PID_D); lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT)); } @@ -1443,7 +1443,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_PID_C); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_PID_C); lcd.setCursor(13,line);lcd.print(itostr3(Kc)); } @@ -1478,10 +1478,10 @@ void MainMenu::showControlTemp() #endif break; case ItemCT_PLA_PreHeat_Setting: - MENUITEM( lcdprintPGM(MSG_PREHEAT_PLA_SETTINGS) , BLOCK;status=Sub_PreheatPLASettings;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_PREHEAT_PLA_SETTINGS) , BLOCK;status=Sub_PreheatPLASettings;beepshort(); ) ; break; case ItemCT_ABS_PreHeat_Setting: - MENUITEM( lcdprintPGM(MSG_PREHEAT_ABS_SETTINGS) , BLOCK;status=Sub_PreheatABSSettings;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_PREHEAT_ABS_SETTINGS) , BLOCK;status=Sub_PreheatABSSettings;beepshort(); ) ; break; default: break; @@ -1513,14 +1513,14 @@ void MainMenu::showControlMotion() switch(i) { case ItemCM_exit: - MENUITEM( lcdprintPGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; break; case ItemCM_acc: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_ACC); - lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcdprintPGM("00"); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_ACC); + lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));LCD_PRINT_PGM("00"); } if((activeline!=line) ) @@ -1545,7 +1545,7 @@ void MainMenu::showControlMotion() { if(encoderpos<5) encoderpos=5; if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));LCD_PRINT_PGM("00"); } }break; @@ -1553,7 +1553,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_VXY_JERK); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_VXY_JERK); lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk)); } @@ -1592,11 +1592,11 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_VMAX); - if(i==ItemCM_vmaxx)lcdprintPGM(MSG_X); - if(i==ItemCM_vmaxy)lcdprintPGM(MSG_Y); - if(i==ItemCM_vmaxz)lcdprintPGM(MSG_Z); - if(i==ItemCM_vmaxe)lcdprintPGM(MSG_E); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_VMAX); + if(i==ItemCM_vmaxx)LCD_PRINT_PGM(MSG_X); + if(i==ItemCM_vmaxy)LCD_PRINT_PGM(MSG_Y); + if(i==ItemCM_vmaxz)LCD_PRINT_PGM(MSG_Z); + if(i==ItemCM_vmaxe)LCD_PRINT_PGM(MSG_E); lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx])); } @@ -1632,7 +1632,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_VMIN); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_VMIN); lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate)); } @@ -1667,7 +1667,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_VTRAV_MIN); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_VTRAV_MIN); lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate)); } @@ -1706,12 +1706,12 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Amax "); - if(i==ItemCM_amaxx)lcdprintPGM(MSG_X); - if(i==ItemCM_amaxy)lcdprintPGM(MSG_Y); - if(i==ItemCM_amaxz)lcdprintPGM(MSG_Z); - if(i==ItemCM_amaxe)lcdprintPGM(MSG_E); - lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));lcdprintPGM("00"); + lcd.setCursor(0,line);LCD_PRINT_PGM(" Amax "); + if(i==ItemCM_amaxx)LCD_PRINT_PGM(MSG_X); + if(i==ItemCM_amaxy)LCD_PRINT_PGM(MSG_Y); + if(i==ItemCM_amaxz)LCD_PRINT_PGM(MSG_Z); + if(i==ItemCM_amaxe)LCD_PRINT_PGM(MSG_E); + lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));LCD_PRINT_PGM("00"); } if((activeline!=line) ) @@ -1736,7 +1736,7 @@ void MainMenu::showControlMotion() { if(encoderpos<1) encoderpos=1; if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));LCD_PRINT_PGM("00"); } }break; @@ -1746,8 +1746,8 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_A_RETRACT); - lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00"); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_A_RETRACT); + lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));LCD_PRINT_PGM("00"); } if((activeline!=line) ) @@ -1773,7 +1773,7 @@ void MainMenu::showControlMotion() { if(encoderpos<10) encoderpos=10; if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));LCD_PRINT_PGM("00"); } }break; @@ -1781,7 +1781,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_XSTEPS); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_XSTEPS); lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[X_AXIS])); } @@ -1818,7 +1818,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_YSTEPS); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_YSTEPS); lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[Y_AXIS])); } @@ -1856,7 +1856,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_ZSTEPS); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_ZSTEPS); lcd.setCursor(11,line);lcd.print(ftostr51(axis_steps_per_unit[Z_AXIS])); } @@ -1895,7 +1895,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_ESTEPS); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_ESTEPS); lcd.setCursor(11,line);lcd.print(ftostr51(axis_steps_per_unit[E_AXIS])); } @@ -1958,7 +1958,7 @@ void MainMenu::showControlRetract() switch(i) { case ItemR_exit: - MENUITEM( lcdprintPGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; break; //float retract_length=2, retract_feedrate=1200, retract_zlift=0.4; @@ -1967,12 +1967,12 @@ void MainMenu::showControlRetract() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_AUTORETRACT); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_AUTORETRACT); lcd.setCursor(13,line); if(autoretract_enabled) - lcdprintPGM(MSG_ON); + LCD_PRINT_PGM(MSG_ON); else - lcdprintPGM(MSG_OFF); + LCD_PRINT_PGM(MSG_OFF); } if((activeline!=line) ) @@ -1983,9 +1983,9 @@ void MainMenu::showControlRetract() autoretract_enabled=!autoretract_enabled; lcd.setCursor(13,line); if(autoretract_enabled) - lcdprintPGM(MSG_ON); + LCD_PRINT_PGM(MSG_ON); else - lcdprintPGM(MSG_OFF); + LCD_PRINT_PGM(MSG_OFF); BLOCK; } @@ -1995,7 +1995,7 @@ void MainMenu::showControlRetract() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACT); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_CONTROL_RETRACT); lcd.setCursor(13,line);lcd.print(ftostr52(retract_length)); } @@ -2030,7 +2030,7 @@ void MainMenu::showControlRetract() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACTF); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_CONTROL_RETRACTF); lcd.setCursor(13,line);lcd.print(itostr4(retract_feedrate)); } @@ -2065,7 +2065,7 @@ void MainMenu::showControlRetract() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACT_ZLIFT); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_CONTROL_RETRACT_ZLIFT); lcd.setCursor(13,line);lcd.print(ftostr52(retract_zlift));; } @@ -2100,7 +2100,7 @@ void MainMenu::showControlRetract() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACT_RECOVER); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_CONTROL_RETRACT_RECOVER); lcd.setCursor(13,line);lcd.print(ftostr52(retract_recover_length));; } @@ -2136,7 +2136,7 @@ void MainMenu::showControlRetract() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACT_RECOVERF); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_CONTROL_RETRACT_RECOVERF); lcd.setCursor(13,line);lcd.print(itostr4(retract_recover_feedrate)); } @@ -2196,24 +2196,24 @@ void MainMenu::showControl() switch(i) { case ItemC_exit: - MENUITEM( lcdprintPGM(MSG_MAIN_WIDE) , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_MAIN_WIDE) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemC_temp: - MENUITEM( lcdprintPGM(MSG_TEMPERATURE_WIDE) , BLOCK;status=Sub_TempControl;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_TEMPERATURE_WIDE) , BLOCK;status=Sub_TempControl;beepshort(); ) ; break; case ItemC_move: - MENUITEM( lcdprintPGM(MSG_MOTION_WIDE) , BLOCK;status=Sub_MotionControl;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_MOTION_WIDE) , BLOCK;status=Sub_MotionControl;beepshort(); ) ; break; #ifdef FWRETRACT case ItemC_rectract: - MENUITEM( lcdprintPGM(MSG_RECTRACT_WIDE) , BLOCK;status=Sub_RetractControl;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_RECTRACT_WIDE) , BLOCK;status=Sub_RetractControl;beepshort(); ) ; break; #endif case ItemC_store: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_STORE_EPROM); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_STORE_EPROM); } if((activeline==line) && CLICKED) { @@ -2227,7 +2227,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_LOAD_EPROM); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_LOAD_EPROM); } if((activeline==line) && CLICKED) { @@ -2241,7 +2241,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_RESTORE_FAILSAFE); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_RESTORE_FAILSAFE); } if((activeline==line) && CLICKED) { @@ -2288,7 +2288,7 @@ void MainMenu::showSD() switch(i) { case 0: - MENUITEM( lcdprintPGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; break; // case 1: // { @@ -2301,11 +2301,11 @@ void MainMenu::showSD() // if(true) // #endif // { -// lcdprintPGM(" \004Refresh"); +// LCD_PRINT_PGM(" \004Refresh"); // } // else // { -// lcdprintPGM(" \004Insert Card"); +// LCD_PRINT_PGM(" \004Insert Card"); // } // // } @@ -2320,7 +2320,7 @@ void MainMenu::showSD() // }break; case 1: MENUITEM( lcd.print(" ");card.getWorkDirName(); - if(card.filename[0]=='/') lcdprintPGM(MSG_REFRESH); + if(card.filename[0]=='/') LCD_PRINT_PGM(MSG_REFRESH); else { lcd.print("\005"); lcd.print(card.filename); @@ -2343,8 +2343,12 @@ void MainMenu::showSD() { card.getfilename(i-FIRSTITEM); //Serial.print("Filenr:");Serial.println(i-2); - lcd.setCursor(0,line);lcdprintPGM(" "); - if(card.filenameIsDir) lcd.print("\005"); + lcd.setCursor(0,line);LCD_PRINT_PGM(" "); + if(card.filenameIsDir) + { + lcd.print("\005"); + card.longFilename[LCD_WIDTH-2] = '\0'; + } if (card.longFilename[0]) { card.longFilename[LCD_WIDTH-1] = '\0'; @@ -2436,14 +2440,14 @@ void MainMenu::showMainMenu() switch(i) { case ItemM_watch: - MENUITEM( lcdprintPGM(MSG_WATCH) , BLOCK;status=Main_Status;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_WATCH) , BLOCK;status=Main_Status;beepshort(); ) ; break; case ItemM_prepare: - MENUITEM( if(!tune) lcdprintPGM(MSG_PREPARE);else lcdprintPGM(MSG_TUNE); , BLOCK;status=Main_Prepare;beepshort(); ) ; + MENUITEM( if(!tune) LCD_PRINT_PGM(MSG_PREPARE);else LCD_PRINT_PGM(MSG_TUNE); , BLOCK;status=Main_Prepare;beepshort(); ) ; break; case ItemM_control: - MENUITEM( lcdprintPGM(MSG_CONTROL_ARROW) , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_CONTROL_ARROW) , BLOCK;status=Main_Control;beepshort(); ) ; break; #ifdef SDSUPPORT case ItemM_file: @@ -2458,13 +2462,13 @@ void MainMenu::showMainMenu() #endif { if(card.sdprinting) - lcdprintPGM(MSG_STOP_PRINT); + LCD_PRINT_PGM(MSG_STOP_PRINT); else - lcdprintPGM(MSG_CARD_MENU); + LCD_PRINT_PGM(MSG_CARD_MENU); } else { - lcdprintPGM(MSG_NO_CARD); + LCD_PRINT_PGM(MSG_NO_CARD); } } #ifdef CARDINSERTED @@ -2490,13 +2494,13 @@ void MainMenu::showMainMenu() #endif { if(card.sdprinting) - lcdprintPGM(MSG_PAUSE_PRINT); + LCD_PRINT_PGM(MSG_PAUSE_PRINT); else - lcdprintPGM(MSG_RESUME_PRINT); + LCD_PRINT_PGM(MSG_RESUME_PRINT); } else { - //lcdprintPGM(MSG_NO_CARD); + //LCD_PRINT_PGM(MSG_NO_CARD); } } #ifdef CARDINSERTED @@ -2666,14 +2670,14 @@ void MainMenu::showPLAsettings() { case ItemPLAPreHeat_Exit: - MENUITEM( lcdprintPGM(MSG_TEMPERATURE_RTN) , BLOCK;status=Sub_TempControl;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_TEMPERATURE_RTN) , BLOCK;status=Sub_TempControl;beepshort(); ) ; break; case ItemPLAPreHeat_set_PLA_FanSpeed: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_FAN_SPEED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_FAN_SPEED); lcd.setCursor(13,line);lcd.print(ftostr3(plaPreheatFanSpeed)); } @@ -2707,7 +2711,7 @@ void MainMenu::showPLAsettings() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_NOZZLE); lcd.setCursor(13,line);lcd.print(ftostr3(plaPreheatHotendTemp)); } @@ -2741,7 +2745,7 @@ void MainMenu::showPLAsettings() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_BED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_BED); lcd.setCursor(13,line);lcd.print(ftostr3(plaPreheatHPBTemp)); } @@ -2774,7 +2778,7 @@ void MainMenu::showPLAsettings() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_STORE_EPROM); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_STORE_EPROM); } if((activeline==line) && CLICKED) { @@ -2812,14 +2816,14 @@ void MainMenu::showABSsettings() { case ItemABSPreHeat_Exit: - MENUITEM( lcdprintPGM(MSG_TEMPERATURE_RTN) , BLOCK;status=Sub_TempControl;beepshort(); ) ; + MENUITEM( LCD_PRINT_PGM(MSG_TEMPERATURE_RTN) , BLOCK;status=Sub_TempControl;beepshort(); ) ; break; case ItemABSPreHeat_set_FanSpeed: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_FAN_SPEED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_FAN_SPEED); lcd.setCursor(13,line);lcd.print(ftostr3(absPreheatFanSpeed)); } @@ -2853,7 +2857,7 @@ void MainMenu::showABSsettings() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_NOZZLE); lcd.setCursor(13,line);lcd.print(ftostr3(absPreheatHotendTemp)); } @@ -2887,7 +2891,7 @@ void MainMenu::showABSsettings() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_BED); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_BED); lcd.setCursor(13,line);lcd.print(ftostr3(absPreheatHPBTemp)); } @@ -2920,7 +2924,7 @@ void MainMenu::showABSsettings() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(MSG_STORE_EPROM); + lcd.setCursor(0,line);LCD_PRINT_PGM(MSG_STORE_EPROM); } if((activeline==line) && CLICKED) { diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index fbc12e987f..8b9feeacbc 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -1,46 +1,41 @@ #ifndef ULTRALCD_H #define ULTRALCD_H + #include "Marlin.h" + #ifdef ULTRA_LCD #include "language.h" + #if LANGUAGE_CHOICE == 6 #include "LiquidCrystalRus.h" +#define LCD_CLASS LiquidCrystalRus #else #include +#define LCD_CLASS LiquidCrystal #endif - void lcd_status(); - void lcd_init(); - void lcd_status(const char* message); - void beep(); - void buttons_init(); - void buttons_check(); - - #define LCD_UPDATE_INTERVAL 100 - #define STATUSTIMEOUT 15000 -#if LANGUAGE_CHOICE == 6 - extern LiquidCrystalRus lcd; -#else - extern LiquidCrystal lcd; -#endif - extern volatile char buttons; //the last checked buttons in a bit array. + +void lcd_status(); +void lcd_init(); +void lcd_status(const char* message); +void beep(); +void buttons_init(); +void buttons_check(); + +#define LCD_UPDATE_INTERVAL 100 +#define STATUSTIMEOUT 15000 + +extern LCD_CLASS lcd; + +extern volatile char buttons; //the last checked buttons in a bit array. - #ifdef NEWPANEL +#ifdef NEWPANEL #define EN_C (1< -1) - #ifdef SDCARDDETECTINVERTED - #define CARDINSERTED (READ(SDCARDDETECT)!=0) - #else - #define CARDINSERTED (READ(SDCARDDETECT)==0) - #endif - #endif //SDCARDTETECTINVERTED - - #else - +#else //atomatic, do not change #define B_LE (1< -1) +#ifdef SDCARDDETECTINVERTED +#define CARDINSERTED (READ(SDCARDDETECT)!=0) +#else +#define CARDINSERTED (READ(SDCARDDETECT)==0) +#endif //SDCARDTETECTINVERTED +#else +//If we don't have a card detect line, aways asume the card is inserted +#define CARDINSERTED true +#endif // blocking time for recognizing a new keypress of one key, ms @@ -152,8 +156,8 @@ #define LCD_INIT lcd_init(); #define LCD_MESSAGE(x) lcd_status(x); - #define LCD_MESSAGEPGM(x) lcd_statuspgm(MYPGM(x)); - #define LCD_ALERTMESSAGEPGM(x) lcd_alertstatuspgm(MYPGM(x)); + #define LCD_MESSAGEPGM(x) lcd_statuspgm(PSTR(x)); + #define LCD_ALERTMESSAGEPGM(x) lcd_alertstatuspgm(PSTR(x)); #define LCD_STATUS lcd_status() #else //no lcd #define LCD_INIT @@ -178,4 +182,14 @@ char *itostr31(const int &xx); char *itostr3(const int &xx); char *itostr4(const int &xx); char *ftostr51(const float &x); + +//TODO: These do not belong here. +extern int plaPreheatHotendTemp; +extern int plaPreheatHPBTemp; +extern int plaPreheatFanSpeed; + +extern int absPreheatHotendTemp; +extern int absPreheatHPBTemp; +extern int absPreheatFanSpeed; + #endif //ULTRALCD diff --git a/Marlin/watchdog.cpp b/Marlin/watchdog.cpp new file mode 100644 index 0000000000..19e6c54d49 --- /dev/null +++ b/Marlin/watchdog.cpp @@ -0,0 +1,54 @@ +#include "Marlin.h" + +#ifdef USE_WATCHDOG +#include "watchdog.h" +#include "ultralcd.h" + +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== + +//=========================================================================== +//=============================functinos ============================ +//=========================================================================== + + +/// intialise watch dog with a 1 sec interrupt time +void watchdog_init() +{ +#ifdef RESET_MANUAL + //We enable the watchdog timer, but only for the interrupt. + //Take care, as this requires the correct order of operation, with interrupts disabled. See the datasheet of any AVR chip for details. + wdt_reset(); + _WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE); + _WD_CONTROL_REG = _BV(WDIE) | WDTO_1S; +#else + wdt_enable(WDTO_1S); +#endif +} + +/// reset watchdog. MUST be called every 1s after init or avr will reset. +void watchdog_reset() +{ + wdt_reset(); +} + +//=========================================================================== +//=============================ISR ============================ +//=========================================================================== + +//Watchdog timer interrupt, called if main program blocks >1sec and manual reset is enabled. +#ifdef RESET_MANUAL +ISR(WDT_vect) +{ + LCD_MESSAGEPGM("ERR:Please Reset");//16 characters so it fits on a 16x2 display + LCD_STATUS; + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Something is wrong, please turn off the printer."); + + kill(); //kill blocks + while(1); //wait for user or serial reset +} +#endif//RESET_MANUAL + +#endif//USE_WATCHDOG diff --git a/Marlin/watchdog.h b/Marlin/watchdog.h index 937379b696..7f78453530 100644 --- a/Marlin/watchdog.h +++ b/Marlin/watchdog.h @@ -1,16 +1,17 @@ #ifndef WATCHDOG_H #define WATCHDOG_H + #include "Marlin.h" -#ifdef USE_WATCHDOG +#ifdef USE_WATCHDOG // intialise watch dog with a 1 sec interrupt time - void wd_init(); - // pad the dog/reset watchdog. MUST be called at least every second after the first wd_init or avr will go into emergency procedures.. - void wd_reset(); - + void watchdog_init(); + // pad the dog/reset watchdog. MUST be called at least every second after the first watchdog_init or avr will go into emergency procedures.. + void watchdog_reset(); #else - FORCE_INLINE void wd_init() {}; - FORCE_INLINE void wd_reset() {}; + //If we do not have a watchdog, then we can have empty functions which are optimized away. + FORCE_INLINE void watchdog_init() {}; + FORCE_INLINE void watchdog_reset() {}; #endif #endif diff --git a/Marlin/watchdog.pde b/Marlin/watchdog.pde deleted file mode 100644 index 356e374738..0000000000 --- a/Marlin/watchdog.pde +++ /dev/null @@ -1,63 +0,0 @@ -#ifdef USE_WATCHDOG -#include "Marlin.h" -#include "watchdog.h" - -//=========================================================================== -//=============================private variables ============================ -//=========================================================================== - -static volatile uint8_t timeout_seconds=0; - -void(* ctrlaltdelete) (void) = 0; //does not work on my atmega2560 - -//=========================================================================== -//=============================functinos ============================ -//=========================================================================== - - -/// intialise watch dog with a 1 sec interrupt time -void wd_init() -{ - WDTCSR |= (1<1sec -ISR(WDT_vect) -{ - if(timeout_seconds++ >= WATCHDOG_TIMEOUT) - { - - #ifdef RESET_MANUAL - LCD_MESSAGEPGM("Please Reset!"); - LCD_STATUS; - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Something is wrong, please turn off the printer."); - #else - LCD_MESSAGEPGM("Timeout, resetting!"); - LCD_STATUS; - #endif - //disable watchdog, it will survife reboot. - WDTCSR |= (1<