From 094afe7c1065d5663628b389f27687a5f465abb8 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 4 Nov 2011 18:02:56 +0100 Subject: [PATCH 001/228] Merged Marlin, Marlin non gen6 and Ultimaker changes --- Marlin/Configuration.h | 147 ++- Marlin/EEPROM.h | 123 +++ Marlin/Makefile | 451 +++++----- Marlin/Marlin.h | 86 +- Marlin/Marlin.pde | 1718 +++++++++--------------------------- Marlin/fastio.h | 1 + Marlin/lcd.h | 10 + Marlin/lcd.pde | 1 + Marlin/pins.h | 96 +- Marlin/planner.cpp | 584 ++++++++++++ Marlin/planner.h | 90 ++ Marlin/speed_lookuptable.h | 8 +- Marlin/stepper.cpp | 592 +++++++++++++ Marlin/stepper.h | 40 + Marlin/streaming.h | 84 ++ Marlin/temperature.cpp | 476 ++++++++++ Marlin/temperature.h | 55 ++ Marlin/thermistortables.h | 221 ++--- Marlin/ultralcd.h | 156 ++++ Marlin/ultralcd.pde | 1593 +++++++++++++++++++++++++++++++++ Marlin/wiring.c | 176 ---- Marlin/wiring_serial.c | 139 --- 22 files changed, 4803 insertions(+), 2044 deletions(-) create mode 100644 Marlin/EEPROM.h create mode 100644 Marlin/lcd.h create mode 100644 Marlin/lcd.pde create mode 100644 Marlin/planner.cpp create mode 100644 Marlin/planner.h create mode 100644 Marlin/stepper.cpp create mode 100644 Marlin/stepper.h create mode 100644 Marlin/streaming.h create mode 100644 Marlin/temperature.cpp create mode 100644 Marlin/temperature.h create mode 100644 Marlin/ultralcd.h create mode 100644 Marlin/ultralcd.pde delete mode 100644 Marlin/wiring.c delete mode 100644 Marlin/wiring_serial.c diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 39480939d7..2cef365b09 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,38 +1,70 @@ #ifndef CONFIGURATION_H #define CONFIGURATION_H +//#define DEBUG_STEPS + // BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration //// The following define selects which electronics board you have. Please choose the one that matches your setup -// Gen6 = 5, -#define MOTHERBOARD 5 +// MEGA/RAMPS up to 1.2 = 3, +// RAMPS 1.3 = 33 +// Gen6 = 5, +// Sanguinololu 1.2 and above = 62 +// Ultimaker = 7, +#define MOTHERBOARD 7 +//#define MOTHERBOARD 5 //// Thermistor settings: // 1 is 100k thermistor // 2 is 200k thermistor // 3 is mendel-parts thermistor #define THERMISTORHEATER 3 +// Select one of these only to define how the nozzle temp is read. +//#define HEATER_USES_THERMISTOR +#define HEATER_USES_AD595 +// Select one of these only to define how the bed temp is read. +//#define BED_USES_THERMISTOR +//#define BED_USES_AD595 + +#define HEATER_CHECK_INTERVAL 50 +#define BED_CHECK_INTERVAL 5000 +#define BNUMTEMPS NUMTEMPS +#define bedtemptable temptable -//// Calibration variables -// X, Y, Z, E steps per unit - Metric Mendel / Orca with V9 extruder: -float axis_steps_per_unit[] = {40, 40, 3333.92, 67}; -// For E steps per unit = 67 for v9 with direct drive (needs finetuning) for other extruders this needs to be changed -// Metric Prusa Mendel with Makergear geared stepper extruder: -//float axis_steps_per_unit[] = {80,80,3200/1.25,1380}; //// Endstop Settings #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false // This determines the communication speed of the printer -#define BAUDRATE 250000 +//#define BAUDRATE 250000 +#define BAUDRATE 115200 +//#define BAUDRATE 230400 // Comment out (using // at the start of the line) to disable SD support: -//#define SDSUPPORT +// #define ULTRA_LCD //any lcd +#define LCD_WIDTH 16 +#define LCD_HEIGHT 2 + +#define ULTIPANEL +#ifdef ULTIPANEL + //#define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 +#define LCD_HEIGHT 4 +#endif + + +//#define SDSUPPORT // Enable SD Card Support in Hardware Console + + + +const int dropsegments=5; //everything with this number of steps will be ignored as move //// ADVANCED SETTINGS - to tweak parameters @@ -47,14 +79,14 @@ const bool ENDSTOPS_INVERTING = false; // set to true to invert the logic of the // Disables axis when it's not being used. #define DISABLE_X false #define DISABLE_Y false -#define DISABLE_Z true +#define DISABLE_Z false #define DISABLE_E false // Inverting axis direction #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false #define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false //// ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -63,51 +95,81 @@ const bool ENDSTOPS_INVERTING = false; // set to true to invert the logic of the #define Z_HOME_DIR -1 #define min_software_endstops false //If true, axis won't move to coordinates less than zero. -#define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 200 -#define Y_MAX_LENGTH 200 -#define Z_MAX_LENGTH 100 +#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. +#define X_MAX_LENGTH 210 +#define Y_MAX_LENGTH 210 +#define Z_MAX_LENGTH 210 //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -float max_feedrate[] = {60000, 60000, 100, 500000}; // set the max speeds -float homing_feedrate[] = {2400, 2400, 80, 0}; // set the homing speeds -bool axis_relative_modes[] = {false, false, false, false}; +//note: on bernhards ultimaker 200 200 12 are working well. +#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds +//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. +//!!!!!!Use only if you know that your printer works at the maximum declared speeds. +// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze +#define TRAVELING_AT_MAXSPEED +#define AXIS_RELATIVE_MODES {false, false, false, false} + +#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker +#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} +#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts + +#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 10 + +// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. +#define DEFAULT_MINSEGMENTTIME 20000 +#define DEFAULT_XYJERK 30.0*60 +#define DEFAULT_ZJERK 10.0*60 -//// Acceleration settings -// X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. -float acceleration = 2000; // Normal acceleration mm/s^2 -float retract_acceleration = 7000; // Normal acceleration mm/s^2 -float max_xy_jerk = 20.0*60; -float max_z_jerk = 0.4*60; -long max_acceleration_units_per_sq_second[] = {7000,7000,100,10000}; // X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +//this enables the watchdog interrupt. +#define 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: +#define RESET_MANUAL + +#define WATCHDOG_TIMEOUT 4 + + // If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 //#define WATCHPERIOD 5000 //5 seconds //// The minimal temperature defines the temperature below which the heater will not be enabled #define MINTEMP 5 +#define BED_MINTEMP 5 // When temperature exceeds max temp, your heater will be switched off. // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. #define MAXTEMP 275 - +#define BED_MAXTEMP 150 /// PID settings: // Uncomment the following line to enable PID support. -//#define PIDTEMP +//#define SMOOTHING +//#define SMOOTHFACTOR 5.0 +//float current_raw_average=0; + +#define PIDTEMP #ifdef PIDTEMP -//#define PID_DEBUG 1 // Sends debug data to the serial port. +//#define PID_DEBUG // Sends debug data to the serial port. //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % -#define PID_MAX 156 // limits current to nozzle -#define PID_INTEGRAL_DRIVE_MAX 156.0 -#define PID_dT 0.16 -double Kp = 20.0; -double Ki = 1.5*PID_dT; -double Kd = 80/PID_dT; +#define PID_MAX 255 // limits current to nozzle +#define PID_INTEGRAL_DRIVE_MAX 255 +#define PID_dT 0.10 // 100ms sample time +#define DEFAULT_Kp 20.0 +#define DEFAULT_Ki 1.5*PID_dT +#define DEFAULT_Kd 80/PID_dT +#define DEFAULT_Kc 0 #endif // PIDTEMP @@ -121,7 +183,7 @@ double Kd = 80/PID_dT; //#define ADVANCE #ifdef ADVANCE -#define EXTRUDER_ADVANCE_K 0.02 +#define EXTRUDER_ADVANCE_K .3 #define D_FILAMENT 1.7 #define STEPS_MM_E 65 @@ -130,4 +192,15 @@ double Kd = 80/PID_dT; #endif // ADVANCE +#if defined SDSUPPORT +// The number of linear motions that can be in the plan at any give time. + #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller +#else + #define BLOCK_BUFFER_SIZE 16 // maximize block buffer +#endif + +#ifdef SIMPLE_LCD + #define BLOCK_BUFFER_SIZE 16 // A little less buffer for just a simple LCD +#endif + #endif diff --git a/Marlin/EEPROM.h b/Marlin/EEPROM.h new file mode 100644 index 0000000000..0390d94e46 --- /dev/null +++ b/Marlin/EEPROM.h @@ -0,0 +1,123 @@ + +#include "planner.h" +#include "temperature.h" + +//====================================================================================== +template int EEPROM_writeAnything(int &ee, const T& value) +{ + const byte* p = (const byte*)(const void*)&value; + int i; + for (i = 0; i < sizeof(value); i++) + EEPROM.write(ee++, *p++); + return i; +} +//====================================================================================== +template int EEPROM_readAnything(int &ee, T& value) +{ + byte* p = (byte*)(void*)&value; + int i; + for (i = 0; i < sizeof(value); i++) + *p++ = EEPROM.read(ee++); + return i; +} +//====================================================================================== + +#define EEPROM_OFFSET 100 + +#define EEPROM_VERSION "V04" // IMPORTANT: Whenever there are changes made to the variables stored in EEPROM + // in the functions below, also increment the version number. This makes sure that + // the default values are used whenever there is a change to the data, to prevent + // wrong data being written to the variables. + // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. +void StoreSettings() { + char ver[4]= "000"; + int i=EEPROM_OFFSET; + EEPROM_writeAnything(i,ver); // invalidate data first + EEPROM_writeAnything(i,axis_steps_per_unit); + EEPROM_writeAnything(i,max_feedrate); + EEPROM_writeAnything(i,max_acceleration_units_per_sq_second); + EEPROM_writeAnything(i,acceleration); + EEPROM_writeAnything(i,retract_acceleration); + EEPROM_writeAnything(i,minimumfeedrate); + EEPROM_writeAnything(i,mintravelfeedrate); + EEPROM_writeAnything(i,minsegmenttime); + EEPROM_writeAnything(i,max_xy_jerk); + EEPROM_writeAnything(i,max_z_jerk); + #ifdef PIDTEMP + EEPROM_writeAnything(i,Kp); + EEPROM_writeAnything(i,Ki); + EEPROM_writeAnything(i,Kd); +#else + EEPROM_writeAnything(i,3000); + EEPROM_writeAnything(i,0); + EEPROM_writeAnything(i,0); +#endif + char ver2[4]=EEPROM_VERSION; + i=EEPROM_OFFSET; + EEPROM_writeAnything(i,ver2); // validate data + ECHOLN("Settings Stored"); + +} + +void RetrieveSettings(bool def=false){ // if def=true, the default values will be used + int i=EEPROM_OFFSET; + char stored_ver[4]; + char ver[4]=EEPROM_VERSION; + EEPROM_readAnything(i,stored_ver); //read stored version +// ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); + if ((!def)&&(strncmp(ver,stored_ver,3)==0)) { // version number match + EEPROM_readAnything(i,axis_steps_per_unit); + EEPROM_readAnything(i,max_feedrate); + EEPROM_readAnything(i,max_acceleration_units_per_sq_second); + EEPROM_readAnything(i,acceleration); + EEPROM_readAnything(i,retract_acceleration); + EEPROM_readAnything(i,minimumfeedrate); + EEPROM_readAnything(i,mintravelfeedrate); + EEPROM_readAnything(i,minsegmenttime); + EEPROM_readAnything(i,max_xy_jerk); + EEPROM_readAnything(i,max_z_jerk); +#ifndef PIDTEMP + float Kp,Ki,Kd; +#endif + EEPROM_readAnything(i,Kp); + EEPROM_readAnything(i,Ki); + EEPROM_readAnything(i,Kd); + + ECHOLN("Stored settings retreived:"); + } + else { + float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; + float tmp2[]=DEFAULT_MAX_FEEDRATE; + long tmp3[]=DEFAULT_MAX_ACCELERATION; + for (int i=0;i<4;i++) { + axis_steps_per_unit[i]=tmp1[i]; + max_feedrate[i]=tmp2[i]; + max_acceleration_units_per_sq_second[i]=tmp3[i]; + } + acceleration=DEFAULT_ACCELERATION; + retract_acceleration=DEFAULT_RETRACT_ACCELERATION; + minimumfeedrate=DEFAULT_MINIMUMFEEDRATE; + minsegmenttime=DEFAULT_MINSEGMENTTIME; + mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; + max_xy_jerk=DEFAULT_XYJERK; + max_z_jerk=DEFAULT_ZJERK; + ECHOLN("Using Default settings:"); + } + ECHOLN("Steps per unit:"); + ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); + ECHOLN("Maximum feedrates (mm/s):"); + ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); + ECHOLN("Maximum Acceleration (mm/s2):"); + ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); + ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); + ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); + ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); + ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); +#ifdef PIDTEMP + ECHOLN("PID settings:"); + ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); +#endif + +} + + diff --git a/Marlin/Makefile b/Marlin/Makefile index 06e643d4aa..6fafba13b0 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -1,247 +1,274 @@ -# Marlin Arduino Project Makefile -# -# Makefile Based on: -# Arduino 0011 Makefile -# Arduino adaptation by mellis, eighthave, oli.keller # -# This has been tested with Arduino 0022. -# -# This makefile allows you to build sketches from the command line -# without the Arduino environment (or Java). +# Arduino 0022 Makefile +# Uno with DOGS102 Shield # -# Detailed instructions for using the makefile: +# written by olikraus@gmail.com # -# 1. Modify the line containg "INSTALL_DIR" to point to the directory that -# contains the Arduino installation (for example, under Mac OS X, this -# might be /Applications/arduino-0012). +# Features: +# - boards.txt is used to derive parameters +# - All intermediate files are put into a separate directory (TMPDIRNAME) +# - Simple use: Copy Makefile into the same directory of the .pde file # -# 2. Modify the line containing "PORT" to refer to the filename -# representing the USB or serial connection to your Arduino board -# (e.g. PORT = /dev/tty.USB0). If the exact name of this file -# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.usb*). +# Limitations: +# - requires UNIX environment +# - TMPDIRNAME must be subdirectory of the current directory. # -# 3. Set the line containing "MCU" to match your board's processor. -# Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth -# or Diecimila have the atmega168. If you're using a LilyPad Arduino, -# change F_CPU to 8000000. +# Targets +# all build everything +# upload build and upload to arduino +# clean remove all temporary files (includes final hex file) # -# 4. Type "make" and press enter to compile/verify your program. +# History +# 001 28 Apr 2010 first release +# 002 05 Oct 2010 added 'uno' # -# 5. Type "make upload", reset your Arduino board, and press enter to -# upload your program to the Arduino board. -# -# $Id$ -TARGET = Marlin -INSTALL_DIR = ../../Desktop/arduino-0018/ -UPLOAD_RATE = 38400 -AVRDUDE_PROGRAMMER = stk500v1 -PORT = /dev/ttyUSB0 -#MCU = atmega2560 -#For "old" Arduino Mega -#MCU = atmega1280 -#For Sanguinololu -MCU = atmega644p -F_CPU = 16000000 +#=== user configuration === +# All ...PATH variables must have a '/' at the end + +# Board (and prozessor) information: see $(ARDUINO_PATH)hardware/arduino/boards.txt +# Some examples: +# BOARD DESCRIPTION +# uno Arduino Uno +# atmega328 Arduino Duemilanove or Nano w/ ATmega328 +# diecimila Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 +# mega Arduino Mega +# mini Arduino Mini +# lilypad328 LilyPad Arduino w/ ATmega328 +BOARD:=mega + +# additional (comma separated) defines +# -DDOGM128_HW board is connected to DOGM128 display +# -DDOGM132_HW board is connected to DOGM132 display +# -DDOGS102_HW board is connected to DOGS102 display +# -DDOG_REVERSE 180 degree rotation +# -DDOG_SPI_SW_ARDUINO force SW shiftOut +DEFS=-DDOGS102_HW -DDOG_DOUBLE_MEMORY -DDOG_SPI_SW_ARDUINO + +# The location where the avr tools (e.g. avr-gcc) are located. Requires a '/' at the end. +# Can be empty if all tools are accessable through the search path +AVR_TOOLS_PATH:=/usr/bin/ + +# Install path of the arduino software. Requires a '/' at the end. +ARDUINO_PATH:=/home/bkubicek/software/arduino-0022/ + +# Install path for avrdude. Requires a '/' at the end. Can be empty if avrdude is in the search path. +AVRDUDE_PATH:= + +# The unix device where we can reach the arduino board +# Uno: /dev/ttyACM0 +# Duemilanove: /dev/ttyUSB0 +AVRDUDE_PORT:=/dev/ttyACM0 + +# List of all libaries which should be included. +#EXTRA_DIRS=$(ARDUINO_PATH)libraries/LiquidCrystal/ +#EXTRA_DIRS+=$(ARDUINO_PATH)libraries/Dogm/ +#EXTRA_DIRS+=/home/kraus/src/arduino/dogm128/hg/libraries/Dogm/ + +#=== fetch parameter from boards.txt processor parameter === +# the basic idea is to get most of the information from boards.txt + +BOARDS_TXT:=$(ARDUINO_PATH)hardware/arduino/boards.txt + +# get the MCU value from the $(BOARD).build.mcu variable. For the atmega328 board this is atmega328p +MCU:=$(shell sed -n -e "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the F_CPU value from the $(BOARD).build.f_cpu variable. For the atmega328 board this is 16000000 +F_CPU:=$(shell sed -n -e "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_TXT)) + +# avrdude +# get the AVRDUDE_UPLOAD_RATE value from the $(BOARD).upload.speed variable. For the atmega328 board this is 57600 +AVRDUDE_UPLOAD_RATE:=$(shell sed -n -e "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the AVRDUDE_PROGRAMMER value from the $(BOARD).upload.protocol variable. For the atmega328 board this is stk500 +# AVRDUDE_PROGRAMMER:=$(shell sed -n -e "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_TXT)) +# use stk500v1, because stk500 will default to stk500v2 +AVRDUDE_PROGRAMMER:=stk500v1 + +#=== identify user files === +PDESRC:=$(shell ls *.pde) +TARGETNAME=$(basename $(PDESRC)) + +CDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CDIRS:=*.c utility/*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +CSRC:=$(shell ls $(CDIRS) 2>/dev/null) + +CCSRC:=$(shell ls *.cc 2>/dev/null) + +CPPDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CPPDIRS:=*.cpp utility/*.cpp $(addsuffix *.cpp,$(CPPDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.cpp +CPPSRC:=$(shell ls $(CPPDIRS) 2>/dev/null) + +#=== build internal variables === + +# the name of the subdirectory where everything is stored +TMPDIRNAME:=tmp +TMPDIRPATH:=$(TMPDIRNAME)/ + +AVRTOOLSPATH:=$(AVR_TOOLS_PATH) + +OBJCOPY:=$(AVRTOOLSPATH)avr-objcopy +OBJDUMP:=$(AVRTOOLSPATH)avr-objdump +SIZE:=$(AVRTOOLSPATH)avr-size + +CPPSRC:=$(addprefix $(TMPDIRPATH),$(PDESRC:.pde=.cpp)) $(CPPSRC) + +COBJ:=$(CSRC:.c=.o) +CCOBJ:=$(CCSRC:.cc=.o) +CPPOBJ:=$(CPPSRC:.cpp=.o) + +OBJFILES:=$(COBJ) $(CCOBJ) $(CPPOBJ) +DIRS:= $(dir $(OBJFILES)) + +DEPFILES:=$(OBJFILES:.o=.d) +# assembler files from avr-gcc -S +ASSFILES:=$(OBJFILES:.o=.s) +# disassembled object files with avr-objdump -S +DISFILES:=$(OBJFILES:.o=.dis) -############################################################################ -# Below here nothing should be changed... +LIBNAME:=$(TMPDIRPATH)$(TARGETNAME).a +ELFNAME:=$(TMPDIRPATH)$(TARGETNAME).elf +HEXNAME:=$(TMPDIRPATH)$(TARGETNAME).hex -ARDUINO = $(INSTALL_DIR)/hardware/Sanguino/cores/arduino -AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin -SRC = $(ARDUINO)/pins_arduino.c wiring.c wiring_serial.c \ -$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ -$(ARDUINO)/wiring_pulse.c \ -$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c -CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp \ -$(ARDUINO)/Print.cpp ./SdFile.cpp ./SdVolume.cpp ./Sd2Card.cpp -FORMAT = ihex +AVRDUDE_FLAGS = -V -F +AVRDUDE_FLAGS += -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf +AVRDUDE_FLAGS += -p $(MCU) +AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) +AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += -b $(AVRDUDE_UPLOAD_RATE) +AVRDUDE_FLAGS += -U flash:w:$(HEXNAME) + +AVRDUDE = avrdude + +#=== predefined variable override === +# use "make -p -f/dev/null" to see the default rules and definitions + +# Build C and C++ flags. Include path information must be placed here +COMMON_FLAGS = -DF_CPU=$(F_CPU) -mmcu=$(MCU) $(DEFS) +# COMMON_FLAGS += -gdwarf-2 +COMMON_FLAGS += -Os +COMMON_FLAGS += -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +COMMON_FLAGS += -I. +COMMON_FLAGS += -I$(ARDUINO_PATH)hardware/arduino/cores/arduino +COMMON_FLAGS += $(addprefix -I,$(EXTRA_DIRS)) +COMMON_FLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections +COMMON_FLAGS += -Wl,--relax +COMMON_FLAGS += -mcall-prologues + +CFLAGS = $(COMMON_FLAGS) -std=gnu99 -Wstrict-prototypes +CXXFLAGS = $(COMMON_FLAGS) + +# Replace standard build tools by avr tools +CC = $(AVRTOOLSPATH)avr-gcc +CXX = $(AVRTOOLSPATH)avr-g++ +AR = @$(AVRTOOLSPATH)avr-ar -# Name of this Makefile (used for "make depend"). -MAKEFILE = Makefile +# "rm" must be able to delete a directory tree +RM = rm -rf -# Debugging format. -# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. -# AVR (extended) COFF requires stabs, plus an avr-objcopy run. -DEBUG = stabs +#=== rules === -OPT = s +# add rules for the C/C++ files where the .o file is placed in the TMPDIRPATH +# reuse existing variables as far as possible -# Place -D or -U options here -CDEFS = -DF_CPU=$(F_CPU) -CXXDEFS = -DF_CPU=$(F_CPU) +$(TMPDIRPATH)%.o: %.c + @echo compile $< + @$(COMPILE.c) $(OUTPUT_OPTION) $< -# Place -I options here -CINCS = -I$(ARDUINO) -CXXINCS = -I$(ARDUINO) +$(TMPDIRPATH)%.o: %.cc + @echo compile $< + @$(COMPILE.cc) $(OUTPUT_OPTION) $< -# Compiler flag to set the C Standard level. -# c89 - "ANSI" C -# gnu89 - c89 plus GCC extensions -# c99 - ISO C99 standard (not yet fully implemented) -# gnu99 - c99 plus GCC extensions -#CSTANDARD = -std=gnu99 -CDEBUG = -g$(DEBUG) -CWARN = -Wall -Wunused-variable -CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -w -ffunction-sections -fdata-sections -DARDUINO=22 -#CEXTRA = -Wa,-adhlns=$(<:.c=.lst) +$(TMPDIRPATH)%.o: %.cpp + @echo compile $< + @$(COMPILE.cpp) $(OUTPUT_OPTION) $< -CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) -CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) -#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs -LDFLAGS = -lm +$(TMPDIRPATH)%.s: %.c + @$(COMPILE.c) $(OUTPUT_OPTION) -S $< +$(TMPDIRPATH)%.s: %.cc + @$(COMPILE.cc) $(OUTPUT_OPTION) -S $< -# Programming support using avrdude. Settings and variables. -AVRDUDE_PORT = $(PORT) -AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex:i -AVRDUDE_FLAGS = -D -C $(INSTALL_DIR)/hardware/tools/avrdude.conf \ --p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \ --b $(UPLOAD_RATE) +$(TMPDIRPATH)%.s: %.cpp + @$(COMPILE.cpp) $(OUTPUT_OPTION) -S $< -# Program settings -CC = $(AVR_TOOLS_PATH)/avr-gcc -CXX = $(AVR_TOOLS_PATH)/avr-g++ -OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy -OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump -AR = $(AVR_TOOLS_PATH)/avr-ar -SIZE = $(AVR_TOOLS_PATH)/avr-size -NM = $(AVR_TOOLS_PATH)/avr-nm -AVRDUDE = $(INSTALL_DIR)/hardware/tools/avrdude -REMOVE = rm -f -MV = mv -f +$(TMPDIRPATH)%.dis: $(TMPDIRPATH)%.o + @$(OBJDUMP) -S $< > $@ -# Define all object files. -OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) - -# Define all listing files. -LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst) - -# Combine all necessary flags and optional flags. -# Add target processor to flags. -ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) -ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS) -ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) - - -# Default target. -all: applet_files_ez build sizeafter - -build: elf hex - -applet_files_ez: $(TARGET).pde - # Here is the "preprocessing". - # It creates a .cpp file based with the same name as the .pde file. - # On top of the new .cpp file comes the WProgram.h header. - # At the end there is a generic main() function attached. - # Then the .cpp file will be compiled. Errors during compile will - # refer to this new, automatically generated, file. - # Not the original .pde file you actually edit... - test -d applet || mkdir applet - echo '#include "WProgram.h"' > applet/$(TARGET).cpp - cat $(TARGET).pde >> applet/$(TARGET).cpp - cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp - -elf: applet/$(TARGET).elf -hex: applet/$(TARGET).hex -eep: applet/$(TARGET).eep -lss: applet/$(TARGET).lss -sym: applet/$(TARGET).sym - -# Program the device. -upload: applet/$(TARGET).hex - $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) - - - # Display size of file. -HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex -ELFSIZE = $(SIZE) applet/$(TARGET).elf -sizebefore: - @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi - -sizeafter: - @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi - - -# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. -COFFCONVERT=$(OBJCOPY) --debugging \ ---change-section-address .data-0x800000 \ ---change-section-address .bss-0x800000 \ ---change-section-address .noinit-0x800000 \ ---change-section-address .eeprom-0x810000 - - -coff: applet/$(TARGET).elf - $(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof - - -extcoff: $(TARGET).elf - $(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof - - -.SUFFIXES: .elf .hex .eep .lss .sym +.SUFFIXES: .elf .hex .pde .elf.hex: - $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ - -.elf.eep: - -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ - -# Create extended listing file from ELF output file. -.elf.lss: - $(OBJDUMP) -h -S $< > $@ - -# Create a symbol table from ELF output file. -.elf.sym: - $(NM) -n $< > $@ - - # Link: create ELF output file from library. -applet/$(TARGET).elf: $(TARGET).pde applet/core.a - $(CC) $(ALL_CFLAGS) -Wl,--gc-sections -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) - -applet/core.a: $(OBJ) - @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done + @$(OBJCOPY) -O ihex -R .eeprom $< $@ + +$(TMPDIRPATH)%.cpp: %.pde + @cat $(ARDUINO_PATH)hardware/arduino/cores/arduino/main.cpp > $@ + @cat $< >> $@ + @echo >> $@ + @echo 'extern "C" void __cxa_pure_virtual() { while (1); }' >> $@ +.PHONY: all +all: tmpdir $(HEXNAME) assemblersource showsize + ls -al $(HEXNAME) $(ELFNAME) -# Compile: create object files from C++ source files. -.cpp.o: - $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ +$(ELFNAME): $(LIBNAME)($(addprefix $(TMPDIRPATH),$(OBJFILES))) + $(LINK.o) $(COMMON_FLAGS) $(LIBNAME) $(LOADLIBES) $(LDLIBS) -o $@ -# Compile: create object files from C source files. -.c.o: - $(CC) -c $(ALL_CFLAGS) $< -o $@ +$(LIBNAME)(): $(addprefix $(TMPDIRPATH),$(OBJFILES)) + +#=== create temp directory === +# not really required, because it will be also created during the dependency handling +.PHONY: tmpdir +tmpdir: + @test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH) + +#=== create assembler files for each C/C++ file === +.PHONY: assemblersource +assemblersource: $(addprefix $(TMPDIRPATH),$(ASSFILES)) $(addprefix $(TMPDIRPATH),$(DISFILES)) -# Compile: create assembler files from C source files. -.c.s: - $(CC) -S $(ALL_CFLAGS) $< -o $@ +#=== show the section sizes of the ELF file === +.PHONY: showsize +showsize: $(ELFNAME) + $(SIZE) $< - -# Assemble: create object files from assembler source files. -.S.o: - $(CC) -c $(ALL_ASFLAGS) $< -o $@ - - - -# Target: clean project. +#=== clean up target === +# this is simple: the TMPDIRPATH is removed +.PHONY: clean clean: - $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ - applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ - $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) + $(RM) $(TMPDIRPATH) + +# Program the device. +# step 1: reset the arduino board with the stty command +# step 2: user avrdude to upload the software +.PHONY: upload +upload: $(HEXNAME) + stty -F $(AVRDUDE_PORT) hupcl + $(AVRDUDE) $(AVRDUDE_FLAGS) + + +# === dependency handling === +# From the gnu make manual (section 4.14, Generating Prerequisites Automatically) +# Additionally (because this will be the first executed rule) TMPDIRPATH is created here. +# Instead of "sed" the "echo" command is used +# cd $(TMPDIRPATH); mkdir -p $(DIRS) 2> /dev/null; cd .. +DEPACTION=test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH);\ +mkdir -p $(addprefix $(TMPDIRPATH),$(DIRS));\ +set -e; echo -n $@ $(dir $@) > $@; $(CC) -MM $(COMMON_FLAGS) $< >> $@ + + +$(TMPDIRPATH)%.d: %.c + @$(DEPACTION) + +$(TMPDIRPATH)%.d: %.cc + @$(DEPACTION) + + +$(TMPDIRPATH)%.d: %.cpp + @$(DEPACTION) + +# Include dependency files. If a .d file is missing, a warning is created and the .d file is created +# This warning is not a problem (gnu make manual, section 3.3 Including Other Makefiles) +-include $(addprefix $(TMPDIRPATH),$(DEPFILES)) -depend: - if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \ - then \ - sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \ - $(MAKEFILE).$$$$ && \ - $(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \ - fi - echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \ - >> $(MAKEFILE); \ - $(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE) -.PHONY: all build elf hex eep lss sym program coff extcoff clean depend applet_files sizebefore sizeafter diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 56d716542d..cc43f00b2d 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -1,27 +1,20 @@ +#ifndef __MARLINH +#define __MARLINH + // Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. // Licence: GPL #include #include "fastio.h" -extern "C" void __cxa_pure_virtual(); -void __cxa_pure_virtual(){}; + + +#define ECHO(x) Serial << "echo: " << x; +#define ECHOLN(x) Serial << "echo: "< -1 #define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) @@ -43,9 +36,12 @@ float analog2tempu(int raw, const short table[][2], int numtemps); #define enable_z() ; #define disable_z() ; #endif + #if E_ENABLE_PIN > -1 -#define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) -#define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) + + #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) + #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) + #else #define enable_e() ; #define disable_e() ; @@ -61,47 +57,27 @@ void ClearToSend(); void get_coordinates(); void prepare_move(); -void linear_move(unsigned long steps_remaining[]); -void do_step(int axis); void kill(byte debug); -// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in -// the source g-code and may never actually be reached if acceleration management is active. -typedef struct { - // Fields used by the bresenham algorithm for tracing the line - long steps_x, steps_y, steps_z, steps_e; // Step count along each axis - long step_event_count; // The number of step events required to complete this block - volatile long accelerate_until; // The index of the step event on which to stop acceleration - volatile long decelerate_after; // The index of the step event on which to start decelerating - volatile long acceleration_rate; // The acceleration rate used for acceleration calculation - unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) +//void check_axes_activity(); +//void plan_init(); +//void st_init(); +//void tp_init(); +//void plan_buffer_line(float x, float y, float z, float e, float feed_rate); +//void plan_set_position(float x, float y, float z, float e); +//void st_wake_up(); +//void st_synchronize(); +void enquecommand(const char *cmd); +void wd_reset(); - long advance_rate; - volatile long initial_advance; - volatile long final_advance; - float advance; +#ifndef CRITICAL_SECTION_START +#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); +#define CRITICAL_SECTION_END SREG = _sreg; +#endif //CRITICAL_SECTION_START - // Fields used by the motion planner to manage acceleration - float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis - float nominal_speed; // The nominal speed for this block in mm/min - float millimeters; // The total travel of this block in mm - float entry_speed; - float acceleration; // acceleration mm/sec^2 +extern float homing_feedrate[]; +extern bool axis_relative_modes[]; - // Settings for the trapezoid generator - long nominal_rate; // The nominal step rate for this block in step_events/sec - volatile long initial_rate; // The jerk-adjusted step rate at start of block - volatile long final_rate; // The minimal rate at exit - long acceleration_st; // acceleration steps/sec^2 - volatile char busy; -} block_t; - -void check_axes_activity(); -void plan_init(); -void st_init(); -void tp_init(); -void plan_buffer_line(float x, float y, float z, float e, float feed_rate); -void plan_set_position(float x, float y, float z, float e); -void st_wake_up(); -void st_synchronize(); +void manage_inactivity(byte debug); +#endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index c1ece44cbc..6922b8a1fe 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -23,26 +23,29 @@ It has preliminary support for Matthew Roberts advance algorithm http://reprap.org/pipermail/reprap-dev/2011-May/003323.html - - This firmware is optimized for gen6 electronics. */ +#include #include "fastio.h" #include "Configuration.h" #include "pins.h" #include "Marlin.h" -#include "speed_lookuptable.h" +#include "ultralcd.h" +#include "streaming.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" -char version_string[] = "0.9.10"; +#ifdef SIMPLE_LCD + #include "Simplelcd.h" +#endif + +char version_string[] = "1.0.0 Alpha 1"; #ifdef SDSUPPORT #include "SdFat.h" #endif //SDSUPPORT -#ifndef CRITICAL_SECTION_START -#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli() -#define CRITICAL_SECTION_END SREG = _sreg -#endif //CRITICAL_SECTION_START // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html // http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes @@ -87,9 +90,17 @@ char version_string[] = "0.9.10"; // M115 - Capabilities string // 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) +// 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 +// M220 - set speed factor override percentage S:factor in percent // M301 - Set PID parameters P I and D +// M500 - stores paramters in EEPROM +// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D +// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. //Stepper Movement Variables @@ -100,15 +111,23 @@ float destination[NUM_AXIS] = { float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; bool home_all_axis = true; -long feedrate = 1500, next_feedrate, saved_feedrate; +float feedrate = 1500.0, next_feedrate, saved_feedrate; long gcode_N, gcode_LastN; + +float homing_feedrate[] = HOMING_FEEDRATE; +bool axis_relative_modes[] = AXIS_RELATIVE_MODES; + bool relative_mode = false; //Determines Absolute or Relative Coordinates bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. -unsigned long axis_steps_per_sqr_second[NUM_AXIS]; +uint8_t fanpwm=0; + +volatile int feedmultiply=100; //100->1 200->2 +int saved_feedmultiply; +volatile bool feedmultiplychanged=false; // comm variables #define MAX_CMD_SIZE 96 -#define BUFSIZE 8 +#define BUFSIZE 4 char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; bool fromsd[BUFSIZE]; int bufindr = 0; @@ -119,45 +138,23 @@ char serial_char; int serial_count = 0; boolean comment_mode = false; char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc +extern float HeaterPower; -// Manage heater variables. - -int target_raw = 0; -int current_raw = 0; -unsigned char temp_meas_ready = false; - -#ifdef PIDTEMP - double temp_iState = 0; - double temp_dState = 0; - double pTerm; - double iTerm; - double dTerm; - //int output; - double pid_error; - double temp_iState_min; - double temp_iState_max; - double pid_setpoint = 0.0; - double pid_input; - double pid_output; - bool pid_reset; -#endif //PIDTEMP +#include "EEPROM.h" +float tt = 0, bt = 0; #ifdef WATCHPERIOD int watch_raw = -1000; unsigned long watchmillis = 0; #endif //WATCHPERIOD -#ifdef MINTEMP -int minttemp = temp2analogh(MINTEMP); -#endif //MINTEMP -#ifdef MAXTEMP -int maxttemp = temp2analogh(MAXTEMP); -#endif //MAXTEMP //Inactivity shutdown variables unsigned long previous_millis_cmd = 0; unsigned long max_inactive_time = 0; unsigned long stepper_inactive_time = 0; +unsigned long starttime=0; +unsigned long stoptime=0; #ifdef SDSUPPORT Sd2Card card; SdVolume volume; @@ -169,6 +166,7 @@ bool sdmode = false; bool sdactive = false; bool savetosd = false; int16_t n; +long autostart_atmillis=0; void initsd(){ sdactive = false; @@ -184,10 +182,18 @@ void initsd(){ else if (!root.openRoot(&volume)) Serial.println("openRoot failed"); else + { sdactive = true; + Serial.println("SD card ok"); + } #endif //SDSS } +void quickinitsd(){ + sdactive=false; + autostart_atmillis=millis()+5000; +} + inline void write_command(char *buf){ char* begin = buf; char* npos = 0; @@ -210,147 +216,131 @@ inline void write_command(char *buf){ #endif //SDSUPPORT +///adds an command to the main command buffer +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.print("en:");Serial.println(cmdbuffer[bufindw]); + bufindw= (bufindw + 1)%BUFSIZE; + buflen += 1; + } +} + void setup() { + Serial.begin(BAUDRATE); - Serial.print("Marlin "); - Serial.println(version_string); + ECHOLN("Marlin "< -1 - SET_OUTPUT(X_DIR_PIN); -#endif -#if Y_DIR_PIN > -1 - SET_OUTPUT(Y_DIR_PIN); -#endif -#if Z_DIR_PIN > -1 - SET_OUTPUT(Z_DIR_PIN); -#endif -#if E_DIR_PIN > -1 - SET_OUTPUT(E_DIR_PIN); -#endif - //Initialize Enable Pins - steppers default to disabled. - -#if (X_ENABLE_PIN > -1) - SET_OUTPUT(X_ENABLE_PIN); - if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); -#endif -#if (Y_ENABLE_PIN > -1) - SET_OUTPUT(Y_ENABLE_PIN); - if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); -#endif -#if (Z_ENABLE_PIN > -1) - SET_OUTPUT(Z_ENABLE_PIN); - if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); -#endif -#if (E_ENABLE_PIN > -1) - SET_OUTPUT(E_ENABLE_PIN); - if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); -#endif - - //endstops and pullups -#ifdef ENDSTOPPULLUPS -#if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); - WRITE(X_MIN_PIN,HIGH); -#endif -#if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); - WRITE(X_MAX_PIN,HIGH); -#endif -#if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); - WRITE(Y_MIN_PIN,HIGH); -#endif -#if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); - WRITE(Y_MAX_PIN,HIGH); -#endif -#if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); - WRITE(Z_MIN_PIN,HIGH); -#endif -#if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); - WRITE(Z_MAX_PIN,HIGH); -#endif -#else //ENDSTOPPULLUPS -#if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); -#endif -#if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); -#endif -#if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); -#endif -#if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); -#endif -#if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); -#endif -#if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); -#endif -#endif //ENDSTOPPULLUPS - -#if (HEATER_0_PIN > -1) - SET_OUTPUT(HEATER_0_PIN); -#endif -#if (HEATER_1_PIN > -1) - SET_OUTPUT(HEATER_1_PIN); -#endif - - //Initialize Step Pins -#if (X_STEP_PIN > -1) - SET_OUTPUT(X_STEP_PIN); -#endif -#if (Y_STEP_PIN > -1) - SET_OUTPUT(Y_STEP_PIN); -#endif -#if (Z_STEP_PIN > -1) - SET_OUTPUT(Z_STEP_PIN); -#endif -#if (E_STEP_PIN > -1) - SET_OUTPUT(E_STEP_PIN); -#endif for(int i=0; i < NUM_AXIS; i++){ axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; } -#ifdef PIDTEMP - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; -#endif //PIDTEMP - #ifdef SDSUPPORT //power to SD reader #if SDPOWER > -1 SET_OUTPUT(SDPOWER); WRITE(SDPOWER,HIGH); #endif //SDPOWER - initsd(); + quickinitsd(); #endif //SDSUPPORT plan_init(); // Initialize planner; st_init(); // Initialize stepper; tp_init(); // Initialize temperature loop + //checkautostart(); } +#ifdef SDSUPPORT +bool autostart_stilltocheck=true; + + +void checkautostart(bool force) +{ + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int i=0;i= filesize){ sdmode = false; Serial.println("Done printing file"); + 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.println(time); + LCD_MESSAGE(time); + checkautostart(true); } if(!serial_count) return; //if empty line cmdbuffer[bufindw][serial_count] = 0; //terminate string @@ -548,38 +549,41 @@ inline void process_commands() break; case 28: //G28 Home all Axis one at a time saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + for(int i=0; i < NUM_AXIS; i++) { destination[i] = current_position[i]; } - feedrate = 0; + feedrate = 0.0; home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ - st_synchronize(); +// st_synchronize(); current_position[X_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; feedrate = homing_feedrate[X_AXIS]; prepare_move(); - - st_synchronize(); + +// st_synchronize(); current_position[X_AXIS] = 0; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[X_AXIS] = -5 * X_HOME_DIR; prepare_move(); - - st_synchronize(); + +// st_synchronize(); destination[X_AXIS] = 10 * X_HOME_DIR; feedrate = homing_feedrate[X_AXIS]/2 ; prepare_move(); - st_synchronize(); - + +// st_synchronize(); current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[X_AXIS] = current_position[X_AXIS]; - feedrate = 0; + feedrate = 0.0; } } @@ -590,23 +594,23 @@ inline void process_commands() destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; feedrate = homing_feedrate[Y_AXIS]; prepare_move(); - st_synchronize(); +// st_synchronize(); 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[Y_AXIS] = -5 * Y_HOME_DIR; prepare_move(); - st_synchronize(); +// st_synchronize(); destination[Y_AXIS] = 10 * Y_HOME_DIR; feedrate = homing_feedrate[Y_AXIS]/2; prepare_move(); - st_synchronize(); +// st_synchronize(); current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[Y_AXIS] = current_position[Y_AXIS]; - feedrate = 0; + feedrate = 0.0; } } @@ -617,26 +621,27 @@ inline void process_commands() destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; feedrate = homing_feedrate[Z_AXIS]; prepare_move(); - st_synchronize(); +// st_synchronize(); current_position[Z_AXIS] = 0; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[Z_AXIS] = -2 * Z_HOME_DIR; prepare_move(); - st_synchronize(); +// st_synchronize(); destination[Z_AXIS] = 3 * Z_HOME_DIR; feedrate = homing_feedrate[Z_AXIS]/2; prepare_move(); - st_synchronize(); +// st_synchronize(); current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0; + feedrate = 0.0; } } feedrate = saved_feedrate; + feedmultiply = saved_feedmultiply; previous_millis_cmd = millis(); break; case 90: // G90 @@ -653,7 +658,6 @@ inline void process_commands() } plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); break; - } } @@ -701,6 +705,7 @@ inline void process_commands() case 24: //M24 - Start SD print if(sdactive){ sdmode = true; + starttime=millis(); } break; case 25: //M25 - Pause SD print @@ -753,70 +758,141 @@ inline void process_commands() //processed in write to file routine above //savetosd = false; break; + case 30: + { + 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.println(time); + LCD_MESSAGE(time); + } + break; #endif //SDSUPPORT - case 104: // M104 -#ifdef PID_OPENLOOP - if (code_seen('S')) PidTemp_Output = code_value() * (PID_MAX/100.0); - if(pid_output > PID_MAX) pid_output = PID_MAX; - if(pid_output < 0) pid_output = 0; -#else //PID_OPENLOOP - if (code_seen('S')) { - target_raw = temp2analogh(code_value()); + case 104: // M104 + if (code_seen('S')) target_raw[0] = temp2analog(code_value()); #ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEMP - } -#ifdef WATCHPERIOD - if(target_raw > current_raw){ - watchmillis = max(1,millis()); - watch_raw = current_raw; - } - else{ - watchmillis = 0; - } -#endif //WATCHPERIOD -#endif //PID_OPENLOOP - break; - case 105: // M105 - Serial.print("ok T:"); - Serial.println(analog2temp(current_raw)); - return; - //break; - case 109: // M109 - Wait for extruder heater to reach target. - if (code_seen('S')) { - target_raw = temp2analogh(code_value()); + pid_setpoint = code_value(); +#endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[0] > current_raw[0]){ + watchmillis = max(1,millis()); + watch_raw[0] = current_raw[0]; + }else{ + watchmillis = 0; + } + #endif + break; + case 140: // M140 set bed temp + if (code_seen('S')) target_raw[1] = temp2analogBed(code_value()); + break; + case 105: // M105 + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + tt = analog2temp(current_raw[0]); + #endif + #if TEMP_1_PIN > -1 + bt = analog2tempBed(current_raw[1]); + #endif + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + Serial.print("ok T:"); + Serial.print(tt); +// Serial.print(", raw:"); +// Serial.print(current_raw); + #if TEMP_1_PIN > -1 #ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEMP - } -#ifdef WATCHPERIOD - if(target_raw>current_raw){ - watchmillis = max(1,millis()); - watch_raw = current_raw; - } - else{ - watchmillis = 0; - } -#endif //WATCHERPERIOD - codenum = millis(); - while(current_raw < target_raw) { - if( (millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. - { - Serial.print("T:"); - Serial.println( analog2temp(current_raw)); + Serial.print(" B:"); + #if TEMP_1_PIN > -1 + Serial.println(bt); + #else + Serial.println(HeaterPower); + #endif +#else + Serial.println(); +#endif + #else + Serial.println(); + #endif + #else + Serial.println("No thermistors - no temp"); + #endif + return; + //break; + case 109: // M109 - Wait for extruder heater to reach target. + LCD_MESSAGE("Heating..."); + if (code_seen('S')) target_raw[0] = temp2analog(code_value()); +#ifdef PIDTEMP + pid_setpoint = code_value(); +#endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[0]>current_raw[0]){ + watchmillis = max(1,millis()); + watch_raw[0] = current_raw[0]; + }else{ + watchmillis = 0; + } + #endif codenum = millis(); + starttime=millis(); + while(current_raw[0] < target_raw[0]) { + if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up. + Serial.print("T:"); + Serial.println( analog2temp(current_raw[0]) ); + codenum = millis(); + } + LCD_STATUS; + manage_heater(); + } + LCD_MESSAGE("UltiMarlin ready."); + break; + case 190: // M190 - Wait bed for heater to reach target. + #if TEMP_1_PIN > -1 + if (code_seen('S')) target_raw[1] = temp2analog(code_value()); + codenum = millis(); + while(current_raw[1] < target_raw[1]) + { + if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + { + float tt=analog2temp(current_raw[0]); + Serial.print("T:"); + Serial.println( tt ); + Serial.print("ok T:"); + Serial.print( tt ); + Serial.print(" B:"); + Serial.println( analog2temp(current_raw[1]) ); + codenum = millis(); + } + manage_heater(); } - manage_heater(); - } - break; - case 190: + #endif break; +#if FAN_PIN > -1 + case 106: //M106 Fan On + if (code_seen('S')){ + WRITE(FAN_PIN,HIGH); + fanpwm=constrain(code_value(),0,255); + analogWrite(FAN_PIN, fanpwm); + } + else { + WRITE(FAN_PIN,HIGH); + fanpwm=255; + analogWrite(FAN_PIN, fanpwm); + } + break; + case 107: //M107 Fan Off + WRITE(FAN_PIN,LOW); + analogWrite(FAN_PIN, 0); + break; +#endif case 82: axis_relative_modes[3] = false; break; case 83: axis_relative_modes[3] = true; break; + case 18: case 84: if(code_seen('S')){ stepper_inactive_time = code_value() * 1000; @@ -849,8 +925,17 @@ inline void process_commands() Serial.print(current_position[Y_AXIS]); Serial.print("Z:"); Serial.print(current_position[Z_AXIS]); - Serial.print("E:"); - Serial.println(current_position[E_AXIS]); + Serial.print("E:"); + Serial.print(current_position[E_AXIS]); + #ifdef DEBUG_STEPS + Serial.print(" Count X:"); + Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); + Serial.print("Y:"); + Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); + Serial.print("Z:"); + Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); + #endif + Serial.println(""); break; case 119: // M119 #if (X_MIN_PIN > -1) @@ -892,18 +977,67 @@ inline void process_commands() } break; #endif + case 203: // M203 max feedrate mm/sec + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; + } + 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()*60 ; + if(code_seen('T')) mintravelfeedrate = code_value()*60 ; + if(code_seen('B')) minsegmenttime = code_value() ; + if(code_seen('X')) max_xy_jerk = code_value()*60 ; + if(code_seen('Z')) max_z_jerk = code_value()*60 ; + } + break; + case 220: // M220 S- set speed factor override percentage + { + if(code_seen('S')) + { + feedmultiply = code_value() ; + feedmultiplychanged=true; + } + } + 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; - Serial.print("Kp ");Serial.println(Kp); - Serial.print("Ki ");Serial.println(Ki/PID_dT); - Serial.print("Kd ");Serial.println(Kd*PID_dT); - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; +// ECHOLN("Kp "<<_FLOAT(Kp,2)); +// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); +// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); + +// temp_iState_min = 0.0; +// if (Ki!=0) { +// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); +// } +// else temp_iState_max = 1.0e10; break; #endif //PIDTEMP + case 500: // Store settings in EEPROM + { + StoreSettings(); + } + break; + case 501: // Read settings from EEPROM + { + RetrieveSettings(); + } + break; + case 502: // Revert to default settings + { + RetrieveSettings(true); + } + break; + } } else{ @@ -947,141 +1081,89 @@ inline void get_coordinates() void prepare_move() { - if (min_software_endstops) { - if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0; - if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0; - if (destination[Z_AXIS] < 0) destination[Z_AXIS] = 0.0; - } - - if (max_software_endstops) { - if (destination[X_AXIS] > X_MAX_LENGTH) destination[X_AXIS] = X_MAX_LENGTH; - if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH; - if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; - } - - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60.0); + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); for(int i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } } -void manage_heater() -{ - float pid_input; - float pid_output; - if(temp_meas_ready != true) - return; -CRITICAL_SECTION_START; - temp_meas_ready = false; -CRITICAL_SECTION_END; -#ifdef PIDTEMP - pid_input = analog2temp(current_raw); +#ifdef USE_WATCHDOG -#ifndef PID_OPENLOOP - pid_error = pid_setpoint - pid_input; - if(pid_error > 10){ - pid_output = PID_MAX; - pid_reset = true; +#include +#include + +volatile uint8_t timeout_seconds=0; + +void(* ctrlaltdelete) (void) = 0; + +ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec + if(timeout_seconds++ >= WATCHDOG_TIMEOUT) + { + kill(); +#ifdef RESET_MANUAL + LCD_MESSAGE("Please Reset!"); + ECHOLN("echo_: Something is wrong, please turn off the printer."); +#else + LCD_MESSAGE("Timeout, resetting!"); +#endif + //disable watchdog, it will survife reboot. + WDTCSR |= (1< raw) { - celsius = (float)table[i-1][1] + - (float)(raw - table[i-1][0]) * - (float)(table[i][1] - table[i-1][1]) / - (float)(table[i][0] - table[i-1][0]); - - break; - } - } - // Overflow: Set to last value in the table - if (i == numtemps) celsius = table[i-1][1]; - - return celsius; +/// reset watchdog. MUST be called every 1s after init or avr will reset. +void wd_reset() { + wdt_reset(); + timeout_seconds=0; //reset counter for resets } +#endif /* USE_WATCHDOG */ inline void kill() { - target_raw=0; -#ifdef PIDTEMP - pid_setpoint = 0.0; -#endif //PIDTEMP - OCR2B = 0; - WRITE(HEATER_0_PIN,LOW); - + #if TEMP_0_PIN > -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif disable_x(); disable_y(); disable_z(); disable_e(); - + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + Serial.println("!! Printer halted. kill() called!!"); + while(1); // Wait for reset } -inline void manage_inactivity(byte debug) { +void manage_inactivity(byte debug) { if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { disable_x(); @@ -1091,965 +1173,3 @@ inline void manage_inactivity(byte debug) { } check_axes_activity(); } - -// Planner - -/* - Reasoning behind the mathematics in this module (in the key of 'Mathematica'): - - s == speed, a == acceleration, t == time, d == distance - - Basic definitions: - - Speed[s_, a_, t_] := s + (a*t) - Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] - - Distance to reach a specific speed with a constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] - d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() - - Speed after a given distance of travel with constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] - m -> Sqrt[2 a d + s^2] - - DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] - - When to start braking (di) to reach a specified destionation speed (s2) after accelerating - from initial speed s1 without ever stopping at a plateau: - - Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] - di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() - - IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) - */ - - -// The number of linear motions that can be in the plan at any give time -#define BLOCK_BUFFER_SIZE 16 -#define BLOCK_BUFFER_MASK 0x0f - -static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instructions -static volatile unsigned char block_buffer_head; // Index of the next block to be pushed -static volatile unsigned char block_buffer_tail; // Index of the block to process now - -// The current position of the tool in absolute steps -static long position[4]; - -#define ONE_MINUTE_OF_MICROSECONDS 60000000.0 - -// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the -// given acceleration: -inline long estimate_acceleration_distance(long initial_rate, long target_rate, long acceleration) { - return( - (target_rate*target_rate-initial_rate*initial_rate)/ - (2L*acceleration) - ); -} - -// This function gives you the point at which you must start braking (at the rate of -acceleration) if -// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after -// a total travel of distance. This can be used to compute the intersection point between acceleration and -// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) - -inline long intersection_distance(long initial_rate, long final_rate, long acceleration, long distance) { - return( - (2*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ - (4*acceleration) - ); -} - -// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. - -void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit_speed) { - if(block->busy == true) return; // If block is busy then bail out. - float entry_factor = entry_speed / block->nominal_speed; - float exit_factor = exit_speed / block->nominal_speed; - long initial_rate = ceil(block->nominal_rate*entry_factor); - long final_rate = ceil(block->nominal_rate*exit_factor); - -#ifdef ADVANCE - long initial_advance = block->advance*entry_factor*entry_factor; - long final_advance = block->advance*exit_factor*exit_factor; -#endif // ADVANCE - - // Limit minimal step rate (Otherwise the timer will overflow.) - if(initial_rate <120) initial_rate=120; - if(final_rate < 120) final_rate=120; - - // Calculate the acceleration steps - long acceleration = block->acceleration_st; - long accelerate_steps = estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration); - long decelerate_steps = estimate_acceleration_distance(final_rate, block->nominal_rate, acceleration); - // Calculate the size of Plateau of Nominal Rate. - long plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; - - // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will - // 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 = intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count); - plateau_steps = 0; - } - - long decelerate_after = accelerate_steps+plateau_steps; - long acceleration_rate = (long)((float)acceleration * 8.388608); - - CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section - if(block->busy == false) { // Don't update variables if block is busy. - block->accelerate_until = accelerate_steps; - block->decelerate_after = decelerate_after; - block->acceleration_rate = acceleration_rate; - block->initial_rate = initial_rate; - block->final_rate = final_rate; -#ifdef ADVANCE - block->initial_advance = initial_advance; - block->final_advance = final_advance; -#endif ADVANCE - } - CRITICAL_SECTION_END; -} - -// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the -// acceleration within the allotted distance. -inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { - return( - sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance) - ); -} - -// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. -// This method will calculate the junction jerk as the euclidean distance between the nominal -// velocities of the respective blocks. -inline float junction_jerk(block_t *before, block_t *after) { - return(sqrt( - pow((before->speed_x-after->speed_x), 2)+ - pow((before->speed_y-after->speed_y), 2))); -} - -// Return the safe speed which is max_jerk/2, e.g. the -// speed under which you cannot exceed max_jerk no matter what you do. -float safe_speed(block_t *block) { - float safe_speed; - safe_speed = max_xy_jerk/2; - if(abs(block->speed_z) > max_z_jerk/2) safe_speed = max_z_jerk/2; - if (safe_speed > block->nominal_speed) safe_speed = block->nominal_speed; - return safe_speed; -} - -// The kernel called by planner_recalculate() when scanning the plan from last to first entry. -void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - - float entry_speed = current->nominal_speed; - float exit_factor; - float exit_speed; - if (next) { - exit_speed = next->entry_speed; - } - else { - exit_speed = safe_speed(current); - } - - // Calculate the entry_factor for the current block. - if (previous) { - // Reduce speed so that junction_jerk is within the maximum allowed - float jerk = junction_jerk(previous, current); - if((previous->steps_x == 0) && (previous->steps_y == 0)) { - entry_speed = safe_speed(current); - } - else if (jerk > max_xy_jerk) { - entry_speed = (max_xy_jerk/jerk) * entry_speed; - } - if(abs(previous->speed_z - current->speed_z) > max_z_jerk) { - entry_speed = (max_z_jerk/abs(previous->speed_z - current->speed_z)) * entry_speed; - } - // If the required deceleration across the block is too rapid, reduce the entry_factor accordingly. - if (entry_speed > exit_speed) { - float max_entry_speed = max_allowable_speed(-current->acceleration,exit_speed, current->millimeters); - if (max_entry_speed < entry_speed) { - entry_speed = max_entry_speed; - } - } - } - else { - entry_speed = safe_speed(current); - } - // Store result - current->entry_speed = entry_speed; -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the reverse pass. -void planner_reverse_pass() { - char block_index = block_buffer_head; - block_index--; - block_t *block[3] = { NULL, NULL, NULL }; - while(block_index != block_buffer_tail) { - block_index--; - if(block_index < 0) block_index = BLOCK_BUFFER_SIZE-1; - block[2]= block[1]; - block[1]= block[0]; - block[0] = &block_buffer[block_index]; - planner_reverse_pass_kernel(block[0], block[1], block[2]); - } - planner_reverse_pass_kernel(NULL, block[0], block[1]); -} - -// The kernel called by planner_recalculate() when scanning the plan from first to last entry. -void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - if(previous) { - // If the previous block is an acceleration block, but it is not long enough to - // complete the full speed change within the block, we need to adjust out entry - // speed accordingly. Remember current->entry_factor equals the exit factor of - // the previous block. - if(previous->entry_speed < current->entry_speed) { - float max_entry_speed = max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters); - if (max_entry_speed < current->entry_speed) { - current->entry_speed = max_entry_speed; - } - } - } -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the forward pass. -void planner_forward_pass() { - char block_index = block_buffer_tail; - block_t *block[3] = { - NULL, NULL, NULL }; - - while(block_index != block_buffer_head) { - block[0] = block[1]; - block[1] = block[2]; - block[2] = &block_buffer[block_index]; - planner_forward_pass_kernel(block[0],block[1],block[2]); - block_index = (block_index+1) & BLOCK_BUFFER_MASK; - } - planner_forward_pass_kernel(block[1], block[2], NULL); -} - -// Recalculates the trapezoid speed profiles for all blocks in the plan according to the -// entry_factor for each junction. Must be called by planner_recalculate() after -// updating the blocks. -void planner_recalculate_trapezoids() { - char block_index = block_buffer_tail; - block_t *current; - block_t *next = NULL; - while(block_index != block_buffer_head) { - current = next; - next = &block_buffer[block_index]; - if (current) { - calculate_trapezoid_for_block(current, current->entry_speed, next->entry_speed); - } - block_index = (block_index+1) & BLOCK_BUFFER_MASK; - } - calculate_trapezoid_for_block(next, next->entry_speed, safe_speed(next)); -} - -// Recalculates the motion plan according to the following algorithm: -// -// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) -// so that: -// a. The junction jerk is within the set limit -// b. No speed reduction within one block requires faster deceleration than the one, true constant -// acceleration. -// 2. Go over every block in chronological order and dial down junction speed reduction values if -// a. The speed increase within one block would require faster accelleration than the one, true -// constant acceleration. -// -// When these stages are complete all blocks have an entry_factor that will allow all speed changes to -// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than -// the set limit. Finally it will: -// -// 3. Recalculate trapezoids for all blocks. - -void planner_recalculate() { - planner_reverse_pass(); - planner_forward_pass(); - planner_recalculate_trapezoids(); -} - -void plan_init() { - block_buffer_head = 0; - block_buffer_tail = 0; - memset(position, 0, sizeof(position)); // clear position -} - - -inline void plan_discard_current_block() { - if (block_buffer_head != block_buffer_tail) { - block_buffer_tail = (block_buffer_tail + 1) & BLOCK_BUFFER_MASK; - } -} - -inline block_t *plan_get_current_block() { - if (block_buffer_head == block_buffer_tail) { - return(NULL); - } - block_t *block = &block_buffer[block_buffer_tail]; - block->busy = true; - return(block); -} - -void check_axes_activity() { - unsigned char x_active = 0; - unsigned char y_active = 0; - unsigned char z_active = 0; - unsigned char e_active = 0; - block_t *block; - - if(block_buffer_tail != block_buffer_head) { - char block_index = block_buffer_tail; - while(block_index != block_buffer_head) { - block = &block_buffer[block_index]; - if(block->steps_x != 0) x_active++; - if(block->steps_y != 0) y_active++; - if(block->steps_z != 0) z_active++; - if(block->steps_e != 0) e_active++; - block_index = (block_index+1) & BLOCK_BUFFER_MASK; - } - } - if((DISABLE_X) && (x_active == 0)) disable_x(); - if((DISABLE_Y) && (y_active == 0)) disable_y(); - if((DISABLE_Z) && (z_active == 0)) disable_z(); - if((DISABLE_E) && (e_active == 0)) disable_e(); -} - -// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in -// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration -// calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { - // The target position of the tool in absolute steps - // Calculate target position in absolute steps - long target[4]; - target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - - // Calculate the buffer head after we push this byte - int next_buffer_head = (block_buffer_head + 1) & BLOCK_BUFFER_MASK; - - // If the buffer is full: good! That means we are well ahead of the robot. - // Rest here until there is room in the buffer. - while(block_buffer_tail == next_buffer_head) { - manage_heater(); - manage_inactivity(1); - } - - // Prepare to set up new block - block_t *block = &block_buffer[block_buffer_head]; - - // Mark block as not busy (Not executed by the stepper interrupt) - block->busy = false; - - // Number of steps for each axis - block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); - block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); - block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); - block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); - block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); - - // Bail if this is a zero-length block - if (block->step_event_count == 0) { - return; - }; - - //enable active axes - if(block->steps_x != 0) enable_x(); - if(block->steps_y != 0) enable_y(); - if(block->steps_z != 0) enable_z(); - if(block->steps_e != 0) enable_e(); - - float delta_x_mm = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; - float delta_y_mm = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; - float delta_z_mm = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; - float delta_e_mm = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; - block->millimeters = sqrt(square(delta_x_mm) + square(delta_y_mm) + square(delta_z_mm) + square(delta_e_mm)); - - unsigned long microseconds; - microseconds = lround((block->millimeters/feed_rate)*1000000); - - // Calculate speed in mm/minute for each axis - float multiplier = 60.0*1000000.0/microseconds; - block->speed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - - // Limit speed per axis - float speed_factor = 1; - float tmp_speed_factor; - if(abs(block->speed_x) > max_feedrate[X_AXIS]) { - speed_factor = max_feedrate[X_AXIS] / abs(block->speed_x); - } - if(abs(block->speed_y) > max_feedrate[Y_AXIS]){ - tmp_speed_factor = max_feedrate[Y_AXIS] / abs(block->speed_y); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_z) > max_feedrate[Z_AXIS]){ - tmp_speed_factor = max_feedrate[Z_AXIS] / abs(block->speed_z); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_e) > max_feedrate[E_AXIS]){ - tmp_speed_factor = max_feedrate[E_AXIS] / abs(block->speed_e); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - multiplier = multiplier * speed_factor; - block->speed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - block->nominal_speed = block->millimeters * multiplier; - block->nominal_rate = ceil(block->step_event_count * multiplier / 60); - - if(block->nominal_rate < 120) block->nominal_rate = 120; - block->entry_speed = safe_speed(block); - - // Compute the acceleration rate for the trapezoid generator. - float travel_per_step = block->millimeters/block->step_event_count; - if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { - block->acceleration_st = ceil( (retract_acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - } - else { - block->acceleration_st = ceil( (acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - // Limit acceleration per axis - if((block->acceleration_st * block->steps_x / block->step_event_count) > axis_steps_per_sqr_second[X_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; - if((block->acceleration_st * block->steps_y / block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; - if((block->acceleration_st * block->steps_e / block->step_event_count) > axis_steps_per_sqr_second[E_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; - if(((block->acceleration_st / block->step_event_count) * block->steps_z ) > axis_steps_per_sqr_second[Z_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; - } - block->acceleration = block->acceleration_st * travel_per_step; - -#ifdef ADVANCE - // Calculate advance rate - if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { - block->advance_rate = 0; - block->advance = 0; - } - else { - long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); - float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; - block->advance = advance; - if(acc_dist == 0) { - block->advance_rate = 0; - } - else { - block->advance_rate = advance / (float)acc_dist; - } - } - -#endif // ADVANCE - - // compute a preliminary conservative acceleration trapezoid - float safespeed = safe_speed(block); - calculate_trapezoid_for_block(block, safespeed, safespeed); - - // Compute direction bits for this block - block->direction_bits = 0; - if (target[X_AXIS] < position[X_AXIS]) { - block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<> 16 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 24 bit result -#define MultiU16X8toH16(intRes, charIn1, intIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %A1, %A2 \n\t" \ -"add %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r0 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (charIn1), \ -"d" (intIn2) \ -: \ -"r26" \ -) - -// intRes = longIn1 * longIn2 >> 24 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 48bit result -#define MultiU24X24toH16(intRes, longIn1, longIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"mov r27, r1 \n\t" \ -"mul %B1, %C2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %C1, %C2 \n\t" \ -"add %B0, r0 \n\t" \ -"mul %C1, %B2 \n\t" \ -"add %A0, r0 \n\t" \ -"adc %B0, r1 \n\t" \ -"mul %A1, %C2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %B2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %C1, %A2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %A2 \n\t" \ -"add r27, r1 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r27 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (longIn1), \ -"d" (longIn2) \ -: \ -"r26" , "r27" \ -) - -// Some useful constants - -#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< -// -// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates -// first block->accelerate_until step_events_completed, then keeps going at constant speed until -// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. -// The slope of acceleration is calculated with the leib ramp alghorithm. - -void st_wake_up() { - // TCNT1 = 0; - ENABLE_STEPPER_DRIVER_INTERRUPT(); -} - -inline unsigned short calc_timer(unsigned short step_rate) { - unsigned short timer; - if(step_rate < 32) step_rate = 32; - step_rate -= 32; // Correct for minimal speed - if(step_rate >= (8*256)){ // higher step rate - unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; - unsigned char tmp_step_rate = (step_rate & 0x00ff); - unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); - MultiU16X8toH16(timer, tmp_step_rate, gain); - timer = (unsigned short)pgm_read_word_near(table_address) - timer; - } - else { // lower step rates - unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; - table_address += ((step_rate)>>1) & 0xfffc; - timer = (unsigned short)pgm_read_word_near(table_address); - timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); - } - if(timer < 100) timer = 100; - return timer; -} - -// Initializes the trapezoid generator from the current block. Called whenever a new -// block begins. -inline void trapezoid_generator_reset() { - accelerate_until = current_block->accelerate_until; - decelerate_after = current_block->decelerate_after; - acceleration_rate = current_block->acceleration_rate; - initial_rate = current_block->initial_rate; - final_rate = current_block->final_rate; - nominal_rate = current_block->nominal_rate; - advance = current_block->initial_advance; - final_advance = current_block->final_advance; - deceleration_time = 0; - advance_rate = current_block->advance_rate; - - // step_rate to timer interval - acc_step_rate = initial_rate; - acceleration_time = calc_timer(acc_step_rate); - OCR1A = acceleration_time; -} - -// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. -// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. -ISR(TIMER1_COMPA_vect) -{ - if(busy){ /*Serial.println("BUSY")*/; - return; - } // The busy-flag is used to avoid reentering this interrupt - - busy = true; - sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) - - // If there is no current block, attempt to pop one from the buffer - if (current_block == NULL) { - // Anything in the buffer? - current_block = plan_get_current_block(); - if (current_block != NULL) { - trapezoid_generator_reset(); - counter_x = -(current_block->step_event_count >> 1); - counter_y = counter_x; - counter_z = counter_x; - counter_e = counter_x; - step_events_completed = 0; - e_steps = 0; - } - else { - DISABLE_STEPPER_DRIVER_INTERRUPT(); - } - } - - if (current_block != NULL) { - // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt - out_bits = current_block->direction_bits; - -#ifdef ADVANCE - // Calculate E early. - counter_e += current_block->steps_e; - if (counter_e > 0) { - counter_e -= current_block->step_event_count; - if ((out_bits & (1<> 16) - old_advance); - CRITICAL_SECTION_END; - old_advance = advance >> 16; -#endif //ADVANCE - - // Set direction en check limit switches - if ((out_bits & (1<step_event_count; - } - } - else // +direction - WRITE(X_DIR_PIN,!INVERT_X_DIR); - - if ((out_bits & (1<step_event_count; - } - } - else // +direction - WRITE(Y_DIR_PIN,!INVERT_Y_DIR); - - if ((out_bits & (1<step_event_count; - } - } - else // +direction - WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - -#ifndef ADVANCE - if ((out_bits & (1<steps_x; - if (counter_x > 0) { - WRITE(X_STEP_PIN, HIGH); - counter_x -= current_block->step_event_count; - WRITE(X_STEP_PIN, LOW); - } - - counter_y += current_block->steps_y; - if (counter_y > 0) { - WRITE(Y_STEP_PIN, HIGH); - counter_y -= current_block->step_event_count; - WRITE(Y_STEP_PIN, LOW); - } - - counter_z += current_block->steps_z; - if (counter_z > 0) { - WRITE(Z_STEP_PIN, HIGH); - counter_z -= current_block->step_event_count; - WRITE(Z_STEP_PIN, LOW); - } - -#ifndef ADVANCE - counter_e += current_block->steps_e; - if (counter_e > 0) { - WRITE(E_STEP_PIN, HIGH); - counter_e -= current_block->step_event_count; - WRITE(E_STEP_PIN, LOW); - } -#endif //!ADVANCE - - // Calculare new timer value - unsigned short timer; - unsigned short step_rate; - if (step_events_completed < accelerate_until) { - MultiU24X24toH16(acc_step_rate, acceleration_time, acceleration_rate); - acc_step_rate += initial_rate; - - // upper limit - if(acc_step_rate > nominal_rate) - acc_step_rate = nominal_rate; - - // step_rate to timer interval - timer = calc_timer(acc_step_rate); - advance += advance_rate; - acceleration_time += timer; - OCR1A = timer; - } - else if (step_events_completed >= decelerate_after) { - MultiU24X24toH16(step_rate, deceleration_time, acceleration_rate); - - if(step_rate > acc_step_rate) { // Check step_rate stays positive - step_rate = final_rate; - } - else { - step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. - } - - // lower limit - if(step_rate < final_rate) - step_rate = final_rate; - - // step_rate to timer interval - timer = calc_timer(step_rate); -#ifdef ADVANCE - advance -= advance_rate; - if(advance < final_advance) - advance = final_advance; -#endif //ADVANCE - deceleration_time += timer; - OCR1A = timer; - } - // If current block is finished, reset pointer - step_events_completed += 1; - if (step_events_completed >= current_block->step_event_count) { - current_block = NULL; - plan_discard_current_block(); - } - } - busy=false; -} - -#ifdef ADVANCE - -unsigned char old_OCR0A; -// Timer interrupt for E. e_steps is set in the main routine; -// Timer 0 is shared with millies -ISR(TIMER0_COMPA_vect) -{ - // Critical section needed because Timer 1 interrupt has higher priority. - // The pin set functions are placed on trategic position to comply with the stepper driver timing. - WRITE(E_STEP_PIN, LOW); - // Set E direction (Depends on E direction + advance) - if (e_steps < 0) { - WRITE(E_DIR_PIN,INVERT_E_DIR); - e_steps++; - WRITE(E_STEP_PIN, HIGH); - } - if (e_steps > 0) { - WRITE(E_DIR_PIN,!INVERT_E_DIR); - e_steps--; - WRITE(E_STEP_PIN, HIGH); - } - old_OCR0A += 25; // 10kHz interrupt - OCR0A = old_OCR0A; -} -#endif // ADVANCE - -void st_init() -{ - // waveform generation = 0100 = CTC - TCCR1B &= ~(1<= 16) - { - current_raw = 16383 - raw_temp_value; - temp_meas_ready = true; - temp_count = 0; - raw_temp_value = 0; -#ifdef MAXTEMP - if(current_raw >= maxttemp) { - target_raw = 0; -#ifdef PIDTEMP - OCR2B = 0; -#else - WRITE(HEATER_0_PIN,LOW); -#endif //PIDTEMP - } -#endif //MAXTEMP -#ifdef MINTEMP - if(current_raw <= minttemp) { - target_raw = 0; -#ifdef PIDTEMP - OCR2B = 0; -#else - WRITE(HEATER_0_PIN,LOW); -#endif //PIDTEMP - } -#endif //MAXTEMP -#ifndef PIDTEMP - if(current_raw >= target_raw) - { - WRITE(HEATER_0_PIN,LOW); - } - else - { - WRITE(HEATER_0_PIN,HIGH); - } -#endif //PIDTEMP - } -} - - diff --git a/Marlin/fastio.h b/Marlin/fastio.h index 1d28d0582f..c1671ddef9 100644 --- a/Marlin/fastio.h +++ b/Marlin/fastio.h @@ -27,6 +27,7 @@ #define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) /// write to a pin #define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) +//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) /// toggle a pin #define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) diff --git a/Marlin/lcd.h b/Marlin/lcd.h new file mode 100644 index 0000000000..74057ddde1 --- /dev/null +++ b/Marlin/lcd.h @@ -0,0 +1,10 @@ +#ifndef __LCDH +#define __LCDH + + + + + + + +#endif diff --git a/Marlin/lcd.pde b/Marlin/lcd.pde new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Marlin/lcd.pde @@ -0,0 +1 @@ + diff --git a/Marlin/pins.h b/Marlin/pins.h index 1bd670266c..795d8bdbb5 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -60,8 +60,8 @@ #define HEATER_0_PIN 6 #define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! - - +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 #endif @@ -133,7 +133,8 @@ #define HEATER_0_PIN 14 #define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! - +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 /* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ @@ -194,7 +195,8 @@ #define HEATER_0_PIN -1 #define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! - +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 @@ -255,8 +257,10 @@ #define HEATER_0_PIN 10 #define HEATER_1_PIN 8 +#define HEATER_2_PIN -1 #define TEMP_0_PIN 13 // ANALOG NUMBERING #define TEMP_1_PIN 14 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING #else // RAMPS_V_1_1 or RAMPS_V_1_2 as default @@ -301,9 +305,10 @@ #define HEATER_1_PIN 8 // RAMPS 1.1 #define FAN_PIN 9 // RAMPS 1.1 #endif - +#define HEATER_2_PIN -1 #define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! #define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! #endif // SPI for Max6675 Thermocouple @@ -361,7 +366,8 @@ #define HEATER_0_PIN 6 #define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! - +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 #endif @@ -404,12 +410,13 @@ #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 - + #define HEATER_2_PIN -1 #define SDPOWER -1 #define SDSS 17 #define LED_PIN -1 //changed @ rkoeppl 20110410 #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 #define FAN_PIN -1 //changed @ rkoeppl 20110410 #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 //our pin for debugging. @@ -421,6 +428,7 @@ #define RX_ENABLE_PIN 13 #endif + /**************************************************************************************** * Sanguinololu pin assignment * @@ -482,13 +490,77 @@ #define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) #define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define SDPOWER -1 -#define SDSS 31 +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 31 +#define HEATER_2_PIN -1 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_1_PIN 4 +#define TEMP_1_PIN 11 + +#define EXTRUDER_0_STEP_PIN 43 +#define EXTRUDER_0_DIR_PIN 45 +#define EXTRUDER_0_ENABLE_PIN 41 +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define EXTRUDER_1_STEP_PIN 49 +#define EXTRUDER_1_DIR_PIN 47 +#define EXTRUDER_1_ENABLE_PIN 51 +#define EXTRUDER_1_HEATER_PIN 3 +#define EXTRUDER_1_TEMPERATURE_PIN 10 +#define HEATER_2_PIN 51 +#define TEMP_2_PIN 3 + + + +#define E_STEP_PIN EXTRUDER_0_STEP_PIN +#define E_DIR_PIN EXTRUDER_0_DIR_PIN +#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 +#endif + #ifndef KNOWN_BOARD #error Unknown MOTHERBOARD value in configuration.h #endif - -#endif - #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp new file mode 100644 index 0000000000..645384e6d8 --- /dev/null +++ b/Marlin/planner.cpp @@ -0,0 +1,584 @@ +/* + planner.c - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ + +/* + Reasoning behind the mathematics in this module (in the key of 'Mathematica'): + + s == speed, a == acceleration, t == time, d == distance + + Basic definitions: + + Speed[s_, a_, t_] := s + (a*t) + Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] + + Distance to reach a specific speed with a constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] + d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() + + Speed after a given distance of travel with constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] + m -> Sqrt[2 a d + s^2] + + DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] + + When to start braking (di) to reach a specified destionation speed (s2) after accelerating + from initial speed s1 without ever stopping at a plateau: + + Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] + di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() + + IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) +*/ + + +//#include +//#include +//#include + +#include "Marlin.h" +#include "Configuration.h" +#include "pins.h" +#include "fastio.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" +#include "ultralcd.h" + +unsigned long minsegmenttime; +float max_feedrate[4]; // set the max speeds +float axis_steps_per_unit[4]; +long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +float minimumfeedrate; +float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +float max_z_jerk; +float mintravelfeedrate; +unsigned long axis_steps_per_sqr_second[NUM_AXIS]; +// Manage heater variables. + +static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +static volatile unsigned char block_buffer_head; // Index of the next block to be pushed +static volatile unsigned char block_buffer_tail; // Index of the block to process now + +// The current position of the tool in absolute steps + long position[4]; + +#define ONE_MINUTE_OF_MICROSECONDS 60000000.0 + +// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the +// given acceleration: +inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { + if (acceleration!=0) { + return((target_rate*target_rate-initial_rate*initial_rate)/ + (2.0*acceleration)); + } + else { + return 0.0; // acceleration was 0, set acceleration distance to 0 + } +} + +// This function gives you the point at which you must start braking (at the rate of -acceleration) if +// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after +// a total travel of distance. This can be used to compute the intersection point between acceleration and +// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) + +inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { + if (acceleration!=0) { + return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ + (4.0*acceleration) ); + } + else { + return 0.0; // acceleration was 0, set intersection distance to 0 + } +} + +// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. + +void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit_speed) { + if(block->busy == true) return; // If block is busy then bail out. + float entry_factor = entry_speed / block->nominal_speed; + float exit_factor = exit_speed / block->nominal_speed; + long initial_rate = ceil(block->nominal_rate*entry_factor); + long final_rate = ceil(block->nominal_rate*exit_factor); + +#ifdef ADVANCE + long initial_advance = block->advance*entry_factor*entry_factor; + long final_advance = block->advance*exit_factor*exit_factor; +#endif // ADVANCE + + // Limit minimal step rate (Otherwise the timer will overflow.) + if(initial_rate <120) initial_rate=120; + if(final_rate < 120) final_rate=120; + + // Calculate the acceleration steps + long acceleration = block->acceleration_st; + long accelerate_steps = estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration); + long decelerate_steps = estimate_acceleration_distance(final_rate, block->nominal_rate, acceleration); + // Calculate the size of Plateau of Nominal Rate. + long plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; + + // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will + // 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 = intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count); + plateau_steps = 0; + } + + long decelerate_after = accelerate_steps+plateau_steps; + + CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section + if(block->busy == false) { // Don't update variables if block is busy. + block->accelerate_until = accelerate_steps; + block->decelerate_after = decelerate_after; + block->initial_rate = initial_rate; + block->final_rate = final_rate; +#ifdef ADVANCE + block->initial_advance = initial_advance; + block->final_advance = final_advance; +#endif //ADVANCE + } + CRITICAL_SECTION_END; +} + +// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the +// acceleration within the allotted distance. +inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { + return( + sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance) + ); +} + +// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. +// This method will calculate the junction jerk as the euclidean distance between the nominal +// velocities of the respective blocks. +inline float junction_jerk(block_t *before, block_t *after) { + return(sqrt( + pow((before->speed_x-after->speed_x), 2)+ + pow((before->speed_y-after->speed_y), 2))); +} + +// Return the safe speed which is max_jerk/2, e.g. the +// speed under which you cannot exceed max_jerk no matter what you do. +float safe_speed(block_t *block) { + float safe_speed; + safe_speed = max_xy_jerk/2; + if(abs(block->speed_z) > max_z_jerk/2) safe_speed = max_z_jerk/2; + if (safe_speed > block->nominal_speed) safe_speed = block->nominal_speed; + return safe_speed; +} + +// The kernel called by planner_recalculate() when scanning the plan from last to first entry. +void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!current) { + return; + } + + float entry_speed = current->nominal_speed; + float exit_factor; + float exit_speed; + if (next) { + exit_speed = next->entry_speed; + } + else { + exit_speed = safe_speed(current); + } + + // Calculate the entry_factor for the current block. + if (previous) { + // Reduce speed so that junction_jerk is within the maximum allowed + float jerk = junction_jerk(previous, current); + if((previous->steps_x == 0) && (previous->steps_y == 0)) { + entry_speed = safe_speed(current); + } + else if (jerk > max_xy_jerk) { + entry_speed = (max_xy_jerk/jerk) * entry_speed; + } + if(abs(previous->speed_z - current->speed_z) > max_z_jerk) { + entry_speed = (max_z_jerk/abs(previous->speed_z - current->speed_z)) * entry_speed; + } + // If the required deceleration across the block is too rapid, reduce the entry_factor accordingly. + if (entry_speed > exit_speed) { + float max_entry_speed = max_allowable_speed(-current->acceleration,exit_speed, current->millimeters); + if (max_entry_speed < entry_speed) { + entry_speed = max_entry_speed; + } + } + } + else { + entry_speed = safe_speed(current); + } + // Store result + current->entry_speed = entry_speed; +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the reverse pass. +void planner_reverse_pass() { + char block_index = block_buffer_head; + if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { + block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); + block_t *block[5] = { + NULL, NULL, NULL, NULL, NULL }; + while(block_index != block_buffer_tail) { + block_index = (block_index-1) & (BLOCK_BUFFER_SIZE -1); + block[2]= block[1]; + block[1]= block[0]; + block[0] = &block_buffer[block_index]; + planner_reverse_pass_kernel(block[0], block[1], block[2]); + } + planner_reverse_pass_kernel(NULL, block[0], block[1]); + } +} + +// The kernel called by planner_recalculate() when scanning the plan from first to last entry. +void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!current) { + return; + } + if(previous) { + // If the previous block is an acceleration block, but it is not long enough to + // complete the full speed change within the block, we need to adjust out entry + // speed accordingly. Remember current->entry_factor equals the exit factor of + // the previous block. + if(previous->entry_speed < current->entry_speed) { + float max_entry_speed = max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters); + if (max_entry_speed < current->entry_speed) { + current->entry_speed = max_entry_speed; + } + } + } +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the forward pass. +void planner_forward_pass() { + char block_index = block_buffer_tail; + block_t *block[3] = { + NULL, NULL, NULL }; + + while(block_index != block_buffer_head) { + block[0] = block[1]; + block[1] = block[2]; + block[2] = &block_buffer[block_index]; + planner_forward_pass_kernel(block[0],block[1],block[2]); + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + planner_forward_pass_kernel(block[1], block[2], NULL); +} + +// Recalculates the trapezoid speed profiles for all blocks in the plan according to the +// entry_factor for each junction. Must be called by planner_recalculate() after +// updating the blocks. +void planner_recalculate_trapezoids() { + char block_index = block_buffer_tail; + block_t *current; + block_t *next = NULL; + while(block_index != block_buffer_head) { + current = next; + next = &block_buffer[block_index]; + if (current) { + calculate_trapezoid_for_block(current, current->entry_speed, next->entry_speed); + } + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + calculate_trapezoid_for_block(next, next->entry_speed, safe_speed(next)); +} + +// Recalculates the motion plan according to the following algorithm: +// +// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) +// so that: +// a. The junction jerk is within the set limit +// b. No speed reduction within one block requires faster deceleration than the one, true constant +// acceleration. +// 2. Go over every block in chronological order and dial down junction speed reduction values if +// a. The speed increase within one block would require faster accelleration than the one, true +// constant acceleration. +// +// When these stages are complete all blocks have an entry_factor that will allow all speed changes to +// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than +// the set limit. Finally it will: +// +// 3. Recalculate trapezoids for all blocks. + +void planner_recalculate() { + planner_reverse_pass(); + planner_forward_pass(); + planner_recalculate_trapezoids(); +} + +void plan_init() { + block_buffer_head = 0; + block_buffer_tail = 0; + memset(position, 0, sizeof(position)); // clear position +} + + +void plan_discard_current_block() { + if (block_buffer_head != block_buffer_tail) { + block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); + } +} + +block_t *plan_get_current_block() { + if (block_buffer_head == block_buffer_tail) { + return(NULL); + } + block_t *block = &block_buffer[block_buffer_tail]; + block->busy = true; + return(block); +} + +void check_axes_activity() { + unsigned char x_active = 0; + unsigned char y_active = 0; + unsigned char z_active = 0; + unsigned char e_active = 0; + block_t *block; + + if(block_buffer_tail != block_buffer_head) { + char block_index = block_buffer_tail; + while(block_index != block_buffer_head) { + block = &block_buffer[block_index]; + if(block->steps_x != 0) x_active++; + if(block->steps_y != 0) y_active++; + if(block->steps_z != 0) z_active++; + if(block->steps_e != 0) e_active++; + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + } + if((DISABLE_X) && (x_active == 0)) disable_x(); + if((DISABLE_Y) && (y_active == 0)) disable_y(); + if((DISABLE_Z) && (z_active == 0)) disable_z(); + if((DISABLE_E) && (e_active == 0)) disable_e(); +} + +// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in +// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration +// calculation the caller must also provide the physical length of the line in millimeters. +void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { + + // The target position of the tool in absolute steps + // Calculate target position in absolute steps + long target[4]; + target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + + // Calculate the buffer head after we push this byte + int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); + + // If the buffer is full: good! That means we are well ahead of the robot. + // Rest here until there is room in the buffer. + while(block_buffer_tail == next_buffer_head) { + manage_heater(); + manage_inactivity(1); + LCD_STATUS; + } + + // Prepare to set up new block + block_t *block = &block_buffer[block_buffer_head]; + + // Mark block as not busy (Not executed by the stepper interrupt) + block->busy = false; + + // Number of steps for each axis + block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); + block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); + block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); + block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); + block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); + + // Bail if this is a zero-length block + if (block->step_event_count <=dropsegments) { + return; + }; + + //enable active axes + if(block->steps_x != 0) enable_x(); + if(block->steps_y != 0) enable_y(); + if(block->steps_z != 0) enable_z(); + if(block->steps_e != 0) enable_e(); + + float delta_x_mm = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; + float delta_y_mm = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; + float delta_z_mm = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; + float delta_e_mm = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; + block->millimeters = sqrt(square(delta_x_mm) + square(delta_y_mm) + square(delta_z_mm) + square(delta_e_mm)); + + unsigned long microseconds; + + if (block->steps_e == 0) { + if(feed_ratemillimeters/feed_rate)*1000000); + + // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill + // reduces/removes corner blobs as the machine won't come to a full stop. + int blockcount=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + + if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { + if (microsecondsspeed_z = delta_z_mm * multiplier; + block->speed_x = delta_x_mm * multiplier; + block->speed_y = delta_y_mm * multiplier; + block->speed_e = delta_e_mm * multiplier; + + + // Limit speed per axis + float speed_factor = 1; //factor <=1 do decrease speed + if(abs(block->speed_x) > max_feedrate[X_AXIS]) { + //// [ErikDeBruijn] IS THIS THE BUG WE'RE LOOING FOR???? + //// [bernhard] No its not, according to Zalm. + //// the if would always be true, since tmp_speedfactor <=0 due the inial if, so its safe to set. the next lines actually compare. + speed_factor = max_feedrate[X_AXIS] / abs(block->speed_x); + //if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + if(abs(block->speed_y) > max_feedrate[Y_AXIS]){ + float tmp_speed_factor = max_feedrate[Y_AXIS] / abs(block->speed_y); + if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + if(abs(block->speed_z) > max_feedrate[Z_AXIS]){ + float tmp_speed_factor = max_feedrate[Z_AXIS] / abs(block->speed_z); + if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + if(abs(block->speed_e) > max_feedrate[E_AXIS]){ + float tmp_speed_factor = max_feedrate[E_AXIS] / abs(block->speed_e); + if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + multiplier = multiplier * speed_factor; + block->speed_z = delta_z_mm * multiplier; + block->speed_x = delta_x_mm * multiplier; + block->speed_y = delta_y_mm * multiplier; + block->speed_e = delta_e_mm * multiplier; + block->nominal_speed = block->millimeters * multiplier; + block->nominal_rate = ceil(block->step_event_count * multiplier / 60); + + if(block->nominal_rate < 120) block->nominal_rate = 120; + block->entry_speed = safe_speed(block); + + // Compute the acceleration rate for the trapezoid generator. + float travel_per_step = block->millimeters/block->step_event_count; + if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { + block->acceleration_st = ceil( (retract_acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 + } + else { + block->acceleration_st = ceil( (acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 + float tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + // Limit acceleration per axis + if((tmp_acceleration * block->steps_x) > axis_steps_per_sqr_second[X_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + if((tmp_acceleration * block->steps_y) > axis_steps_per_sqr_second[Y_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + if((tmp_acceleration * block->steps_e) > axis_steps_per_sqr_second[E_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + if((tmp_acceleration * block->steps_z) > axis_steps_per_sqr_second[Z_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + } + block->acceleration = block->acceleration_st * travel_per_step; + block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); + +#ifdef ADVANCE + // Calculate advance rate + if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { + block->advance_rate = 0; + block->advance = 0; + } + else { + long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); + float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * + (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; + block->advance = advance; + if(acc_dist == 0) { + block->advance_rate = 0; + } + else { + block->advance_rate = advance / (float)acc_dist; + } + } +#endif // ADVANCE + + // compute a preliminary conservative acceleration trapezoid + float safespeed = safe_speed(block); + calculate_trapezoid_for_block(block, safespeed, safespeed); + + // Compute direction bits for this block + block->direction_bits = 0; + if (target[X_AXIS] < position[X_AXIS]) { + block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<. +*/ + +// This module is to be considered a sub-module of stepper.c. Please don't include +// this file from any other module. + +#ifndef planner_h +#define planner_h + +// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in +// the source g-code and may never actually be reached if acceleration management is active. +typedef struct { + // Fields used by the bresenham algorithm for tracing the line + long steps_x, steps_y, steps_z, steps_e; // Step count along each axis + long step_event_count; // The number of step events required to complete this block + volatile long accelerate_until; // The index of the step event on which to stop acceleration + volatile long decelerate_after; // The index of the step event on which to start decelerating + volatile long acceleration_rate; // The acceleration rate used for acceleration calculation + unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) +#ifdef ADVANCE + long advance_rate; + volatile long initial_advance; + volatile long final_advance; + float advance; +#endif + + // Fields used by the motion planner to manage acceleration + float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis + float nominal_speed; // The nominal speed for this block in mm/min + float millimeters; // The total travel of this block in mm + float entry_speed; + float acceleration; // acceleration mm/sec^2 + + // Settings for the trapezoid generator + long nominal_rate; // The nominal step rate for this block in step_events/sec + volatile long initial_rate; // The jerk-adjusted step rate at start of block + volatile long final_rate; // The minimal rate at exit + long acceleration_st; // acceleration steps/sec^2 + volatile char busy; +} block_t; + +// Initialize the motion plan subsystem +void plan_init(); + +// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in +// millimaters. Feed rate specifies the speed of the motion. +void plan_buffer_line(float x, float y, float z, float e, float feed_rate); + +// Set position. Used for G92 instructions. +void plan_set_position(float x, float y, float z, float e); + +// Called when the current block is no longer needed. Discards the block and makes the memory +// availible for new blocks. +void plan_discard_current_block(); + +// Gets the current block. Returns NULL if buffer empty +block_t *plan_get_current_block(); + +void check_axes_activity(); + +extern unsigned long minsegmenttime; +extern float max_feedrate[4]; // set the max speeds +extern float axis_steps_per_unit[4]; +extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +extern float minimumfeedrate; +extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +extern float max_z_jerk; +extern float mintravelfeedrate; +extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + +#endif diff --git a/Marlin/speed_lookuptable.h b/Marlin/speed_lookuptable.h index 5c54a08d1c..43ef89980d 100644 --- a/Marlin/speed_lookuptable.h +++ b/Marlin/speed_lookuptable.h @@ -3,7 +3,7 @@ #include -uint16_t speed_lookuptable_fast[256][2] PROGMEM = { +uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ { 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, { 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, { 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, @@ -35,9 +35,9 @@ uint16_t speed_lookuptable_fast[256][2] PROGMEM = { { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, -{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0}, +{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0} }; -uint16_t speed_lookuptable_slow[256][2] PROGMEM = { +uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ { 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, { 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, { 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, @@ -69,7 +69,7 @@ uint16_t speed_lookuptable_slow[256][2] PROGMEM = { { 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4}, { 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4}, { 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4}, -{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3}, +{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3} }; #endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp new file mode 100644 index 0000000000..cd68bae0d5 --- /dev/null +++ b/Marlin/stepper.cpp @@ -0,0 +1,592 @@ +/* + stepper.c - stepper motor driver: executes motion plans using stepper motors + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith + and Philipp Tiefenbacher. */ + +#include "stepper.h" +#include "Configuration.h" +#include "Marlin.h" +#include "planner.h" +#include "pins.h" +#include "fastio.h" +#include "temperature.h" +#include "ultralcd.h" + +#include "speed_lookuptable.h" + +// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. +// for debugging purposes only, should be disabled by default +#ifdef DEBUG_STEPS +volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; +volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; +#endif + + +// intRes = intIn1 * intIn2 >> 16 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 24 bit result +#define MultiU16X8toH16(intRes, charIn1, intIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %A1, %A2 \n\t" \ +"add %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r0 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (charIn1), \ +"d" (intIn2) \ +: \ +"r26" \ +) + +// intRes = longIn1 * longIn2 >> 24 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 48bit result +#define MultiU24X24toH16(intRes, longIn1, longIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"mov r27, r1 \n\t" \ +"mul %B1, %C2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %C1, %C2 \n\t" \ +"add %B0, r0 \n\t" \ +"mul %C1, %B2 \n\t" \ +"add %A0, r0 \n\t" \ +"adc %B0, r1 \n\t" \ +"mul %A1, %C2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %B2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %C1, %A2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %A2 \n\t" \ +"add r27, r1 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r27 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (longIn1), \ +"d" (longIn2) \ +: \ +"r26" , "r27" \ +) + +// Some useful constants + +#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< +// +// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates +// first block->accelerate_until step_events_completed, then keeps going at constant speed until +// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. +// The slope of acceleration is calculated with the leib ramp alghorithm. + +void st_wake_up() { + // TCNT1 = 0; + ENABLE_STEPPER_DRIVER_INTERRUPT(); +} + +inline unsigned short calc_timer(unsigned short step_rate) { + unsigned short timer; + if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; + + if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times + step_rate = step_rate >> 2; + step_loops = 4; + } + else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times + step_rate = step_rate >> 1; + step_loops = 2; + } + else { + step_loops = 1; + } + + if(step_rate < 32) step_rate = 32; + step_rate -= 32; // Correct for minimal speed + if(step_rate >= (8*256)){ // higher step rate + unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; + unsigned char tmp_step_rate = (step_rate & 0x00ff); + unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); + MultiU16X8toH16(timer, tmp_step_rate, gain); + timer = (unsigned short)pgm_read_word_near(table_address) - timer; + } + else { // lower step rates + unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; + table_address += ((step_rate)>>1) & 0xfffc; + timer = (unsigned short)pgm_read_word_near(table_address); + timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); + } + if(timer < 100) timer = 100; + return timer; +} + +// Initializes the trapezoid generator from the current block. Called whenever a new +// block begins. +inline void trapezoid_generator_reset() { +#ifdef ADVANCE + advance = current_block->initial_advance; + final_advance = current_block->final_advance; +#endif + deceleration_time = 0; + // advance_rate = current_block->advance_rate; + // step_rate to timer interval + acc_step_rate = current_block->initial_rate; + acceleration_time = calc_timer(acc_step_rate); + OCR1A = acceleration_time; +} + +// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. +// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. +ISR(TIMER1_COMPA_vect) +{ + if(busy){ Serial.print(*(unsigned short *)OCR1A); Serial.println(" BUSY"); + return; + } // The busy-flag is used to avoid reentering this interrupt + + busy = true; + sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) + + // If there is no current block, attempt to pop one from the buffer + if (current_block == NULL) { + // Anything in the buffer? + current_block = plan_get_current_block(); + if (current_block != NULL) { + trapezoid_generator_reset(); + counter_x = -(current_block->step_event_count >> 1); + counter_y = counter_x; + counter_z = counter_x; + counter_e = counter_x; + step_events_completed = 0; + #ifdef ADVANCE + e_steps = 0; + #endif + } + else { +// DISABLE_STEPPER_DRIVER_INTERRUPT(); + } + } + + if (current_block != NULL) { + // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt + out_bits = current_block->direction_bits; + +#ifdef ADVANCE + // Calculate E early. + counter_e += current_block->steps_e; + if (counter_e > 0) { + counter_e -= current_block->step_event_count; + if ((out_bits & (1<> 16) - old_advance); + CRITICAL_SECTION_END; + old_advance = advance >> 16; +#endif //ADVANCE + + // Set direction en check limit switches +if ((out_bits & (1< -1 + if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } +#endif + } + else { // +direction + WRITE(X_DIR_PIN,!INVERT_X_DIR); + #ifdef DEBUG_STEPS + count_direction[X_AXIS]=1; + #endif +#if X_MAX_PIN > -1 + if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ + step_events_completed = current_block->step_event_count; + } +#endif + } + + if ((out_bits & (1< -1 + if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } +#endif + } + else { // +direction + WRITE(Y_DIR_PIN,!INVERT_Y_DIR); + #ifdef DEBUG_STEPS + count_direction[Y_AXIS]=1; + #endif +#if Y_MAX_PIN > -1 + if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ + step_events_completed = current_block->step_event_count; + } +#endif + } + + if ((out_bits & (1< -1 + if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } +#endif + } + else { // +direction + WRITE(Z_DIR_PIN,!INVERT_Z_DIR); + #ifdef DEBUG_STEPS + count_direction[Z_AXIS]=1; + #endif +#if Z_MAX_PIN > -1 + if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ + step_events_completed = current_block->step_event_count; + } +#endif + } + +#ifndef ADVANCE + if ((out_bits & (1<steps_x; + if (counter_x > 0) { + WRITE(X_STEP_PIN, HIGH); + counter_x -= current_block->step_event_count; + WRITE(X_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[X_AXIS]+=count_direction[X_AXIS]; + #endif + } + + counter_y += current_block->steps_y; + if (counter_y > 0) { + WRITE(Y_STEP_PIN, HIGH); + counter_y -= current_block->step_event_count; + WRITE(Y_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Y_AXIS]+=count_direction[Y_AXIS]; + #endif + } + + counter_z += current_block->steps_z; + if (counter_z > 0) { + WRITE(Z_STEP_PIN, HIGH); + counter_z -= current_block->step_event_count; + WRITE(Z_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Z_AXIS]+=count_direction[Z_AXIS]; + #endif + } + +#ifndef ADVANCE + counter_e += current_block->steps_e; + if (counter_e > 0) { + WRITE(E_STEP_PIN, HIGH); + counter_e -= current_block->step_event_count; + WRITE(E_STEP_PIN, LOW); + } +#endif //!ADVANCE + step_events_completed += 1; + if(step_events_completed >= current_block->step_event_count) break; + } + // Calculare new timer value + unsigned short timer; + unsigned short step_rate; + if (step_events_completed <= current_block->accelerate_until) { + MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); + acc_step_rate += current_block->initial_rate; + + // upper limit + if(acc_step_rate > current_block->nominal_rate) + acc_step_rate = current_block->nominal_rate; + + // step_rate to timer interval + timer = calc_timer(acc_step_rate); +#ifdef ADVANCE + advance += advance_rate; +#endif + acceleration_time += timer; + OCR1A = timer; + } + else if (step_events_completed > current_block->decelerate_after) { + MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); + + if(step_rate > acc_step_rate) { // Check step_rate stays positive + step_rate = current_block->final_rate; + } + else { + step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. + } + + // lower limit + if(step_rate < current_block->final_rate) + step_rate = current_block->final_rate; + + // step_rate to timer interval + timer = calc_timer(step_rate); +#ifdef ADVANCE + advance -= advance_rate; + if(advance < final_advance) + advance = final_advance; +#endif //ADVANCE + deceleration_time += timer; + OCR1A = timer; + } + // If current block is finished, reset pointer + if (step_events_completed >= current_block->step_event_count) { + current_block = NULL; + plan_discard_current_block(); + } + } + cli(); // disable interrupts + busy=false; +} + +#ifdef ADVANCE + +unsigned char old_OCR0A; +// Timer interrupt for E. e_steps is set in the main routine; +// Timer 0 is shared with millies +ISR(TIMER0_COMPA_vect) +{ + // Critical section needed because Timer 1 interrupt has higher priority. + // The pin set functions are placed on trategic position to comply with the stepper driver timing. + WRITE(E_STEP_PIN, LOW); + // Set E direction (Depends on E direction + advance) + if (e_steps < 0) { + WRITE(E_DIR_PIN,INVERT_E_DIR); + e_steps++; + WRITE(E_STEP_PIN, HIGH); + } + if (e_steps > 0) { + WRITE(E_DIR_PIN,!INVERT_E_DIR); + e_steps--; + WRITE(E_STEP_PIN, HIGH); + } + old_OCR0A += 25; // 10kHz interrupt + OCR0A = old_OCR0A; +} +#endif // ADVANCE + +void st_init() +{ + //Initialize Dir Pins +#if X_DIR_PIN > -1 + SET_OUTPUT(X_DIR_PIN); +#endif +#if Y_DIR_PIN > -1 + SET_OUTPUT(Y_DIR_PIN); +#endif +#if Z_DIR_PIN > -1 + SET_OUTPUT(Z_DIR_PIN); +#endif +#if E_DIR_PIN > -1 + SET_OUTPUT(E_DIR_PIN); +#endif + + //Initialize Enable Pins - steppers default to disabled. + +#if (X_ENABLE_PIN > -1) + SET_OUTPUT(X_ENABLE_PIN); + if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); +#endif +#if (Y_ENABLE_PIN > -1) + SET_OUTPUT(Y_ENABLE_PIN); + if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); +#endif +#if (Z_ENABLE_PIN > -1) + SET_OUTPUT(Z_ENABLE_PIN); + if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); +#endif +#if (E_ENABLE_PIN > -1) + SET_OUTPUT(E_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); +#endif + + //endstops and pullups +#ifdef ENDSTOPPULLUPS +#if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + WRITE(X_MIN_PIN,HIGH); +#endif +#if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + WRITE(X_MAX_PIN,HIGH); +#endif +#if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + WRITE(Y_MIN_PIN,HIGH); +#endif +#if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + WRITE(Y_MAX_PIN,HIGH); +#endif +#if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + WRITE(Z_MIN_PIN,HIGH); +#endif +#if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + WRITE(Z_MAX_PIN,HIGH); +#endif +#else //ENDSTOPPULLUPS +#if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); +#endif +#if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); +#endif +#if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); +#endif +#if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); +#endif +#if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); +#endif +#if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); +#endif +#endif //ENDSTOPPULLUPS + + + //Initialize Step Pins +#if (X_STEP_PIN > -1) + SET_OUTPUT(X_STEP_PIN); +#endif +#if (Y_STEP_PIN > -1) + SET_OUTPUT(Y_STEP_PIN); +#endif +#if (Z_STEP_PIN > -1) + SET_OUTPUT(Z_STEP_PIN); +#endif +#if (E_STEP_PIN > -1) + SET_OUTPUT(E_STEP_PIN); +#endif + + // waveform generation = 0100 = CTC + TCCR1B &= ~(1<. +*/ + +#ifndef stepper_h +#define stepper_h +// Initialize and start the stepper motor subsystem +void st_init(); + +// Block until all buffered steps are executed +void st_synchronize(); + +// The stepper subsystem goes to sleep when it runs out of things to execute. Call this +// to notify the subsystem that it is time to go to work. +void st_wake_up(); + +// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. +// for debugging purposes only, should be disabled by default +#ifdef DEBUG_STEPS +extern volatile long count_position[NUM_AXIS]; +extern volatile int count_direction[NUM_AXIS]; +#endif + +#endif diff --git a/Marlin/streaming.h b/Marlin/streaming.h new file mode 100644 index 0000000000..2abf64f149 --- /dev/null +++ b/Marlin/streaming.h @@ -0,0 +1,84 @@ +/* +Streaming.h - Arduino library for supporting the << streaming operator +Copyright (c) 2010 Mikal Hart. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ARDUINO_STREAMING +#define ARDUINO_STREAMING + +//#include + +#define STREAMING_LIBRARY_VERSION 4 + +// Generic template +template +inline Print &operator <<(Print &stream, T arg) +{ stream.print(arg); return stream; } + +struct _BASED +{ + long val; + int base; + _BASED(long v, int b): val(v), base(b) + {} +}; + +#define _HEX(a) _BASED(a, HEX) +#define _DEC(a) _BASED(a, DEC) +#define _OCT(a) _BASED(a, OCT) +#define _BIN(a) _BASED(a, BIN) +#define _BYTE(a) _BASED(a, BYTE) + +// Specialization for class _BASED +// Thanks to Arduino forum user Ben Combee who suggested this +// clever technique to allow for expressions like +// Serial << _HEX(a); + +inline Print &operator <<(Print &obj, const _BASED &arg) +{ obj.print(arg.val, arg.base); return obj; } + +#if ARDUINO >= 18 +// Specialization for class _FLOAT +// Thanks to Michael Margolis for suggesting a way +// to accommodate Arduino 0018's floating point precision +// feature like this: +// Serial << _FLOAT(gps_latitude, 6); // 6 digits of precision + +struct _FLOAT +{ + float val; + int digits; + _FLOAT(double v, int d): val(v), digits(d) + {} +}; + +inline Print &operator <<(Print &obj, const _FLOAT &arg) +{ obj.print(arg.val, arg.digits); return obj; } +#endif + +// Specialization for enum _EndLineCode +// Thanks to Arduino forum user Paul V. who suggested this +// clever technique to allow for expressions like +// Serial << "Hello!" << endl; + +enum _EndLineCode { endl }; + +inline Print &operator <<(Print &obj, _EndLineCode arg) +{ obj.println(); return obj; } + +#endif + diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp new file mode 100644 index 0000000000..248b807fd4 --- /dev/null +++ b/Marlin/temperature.cpp @@ -0,0 +1,476 @@ +/* + temperature.c - temperature control + Part of Marlin + + 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 + + This firmware is optimized for gen6 electronics. + */ + +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "temperature.h" + +int target_bed_raw = 0; +int current_bed_raw = 0; + +int target_raw[3] = {0, 0, 0}; +int current_raw[3] = {0, 0, 0}; +unsigned char temp_meas_ready = false; + +unsigned long previous_millis_heater, previous_millis_bed_heater; + +#ifdef PIDTEMP + double temp_iState = 0; + double temp_dState = 0; + double pTerm; + double iTerm; + double dTerm; + //int output; + double pid_error; + double temp_iState_min; + double temp_iState_max; + double pid_setpoint = 0.0; + double pid_input; + double pid_output; + bool pid_reset; + float HeaterPower; + + float Kp=DEFAULT_Kp; + float Ki=DEFAULT_Ki; + float Kd=DEFAULT_Kd; + float Kc=DEFAULT_Kc; +#endif //PIDTEMP + +#ifdef MINTEMP +int minttemp = temp2analog(MINTEMP); +#endif //MINTEMP +#ifdef MAXTEMP +int maxttemp = temp2analog(MAXTEMP); +#endif //MAXTEMP + +#ifdef BED_MINTEMP +int bed_minttemp = temp2analog(BED_MINTEMP); +#endif //BED_MINTEMP +#ifdef BED_MAXTEMP +int bed_maxttemp = temp2analog(BED_MAXTEMP); +#endif //BED_MAXTEMP + +void manage_heater() +{ +#ifdef USE_WATCHDOG + wd_reset(); +#endif + + float pid_input; + float pid_output; + if(temp_meas_ready == true) { + +CRITICAL_SECTION_START; + temp_meas_ready = false; +CRITICAL_SECTION_END; + +#ifdef PIDTEMP + pid_input = analog2temp(current_raw[0]); + +#ifndef PID_OPENLOOP + pid_error = pid_setpoint - pid_input; + if(pid_error > 10){ + pid_output = PID_MAX; + pid_reset = true; + } + else if(pid_error < -10) { + pid_output = 0; + pid_reset = true; + } + else { + if(pid_reset == true) { + temp_iState = 0.0; + pid_reset = false; + } + pTerm = Kp * pid_error; + temp_iState += pid_error; + temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); + iTerm = Ki * temp_iState; + #define K1 0.95 + #define K2 (1.0-K1) + dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); + temp_dState = pid_input; + pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); + } +#endif //PID_OPENLOOP +#ifdef PID_DEBUG + Serial.print(" Input "); + Serial.print(pid_input); + Serial.print(" Output "); + Serial.print(pid_output); + Serial.print(" pTerm "); + Serial.print(pTerm); + Serial.print(" iTerm "); + Serial.print(iTerm); + Serial.print(" dTerm "); + Serial.print(dTerm); + Serial.println(); +#endif //PID_DEBUG + analogWrite(HEATER_0_PIN, pid_output); +#endif //PIDTEMP + +#ifndef PIDTEMP + if(current_raw[0] >= target_raw[0]) + { + WRITE(HEATER_0_PIN,LOW); + } + else + { + WRITE(HEATER_0_PIN,HIGH); + } +#endif + + if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) + return; + previous_millis_bed_heater = millis(); + + #if TEMP_1_PIN > -1 + if(current_raw[1] >= target_raw[1]) + { + WRITE(HEATER_1_PIN,LOW); + } + else + { + WRITE(HEATER_1_PIN,HIGH); + } + #endif + } +} + +// Takes hot end temperature value as input and returns corresponding raw value. +// For a thermistor, it uses the RepRap thermistor temp table. +// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. +// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. +float temp2analog(int celsius) { + #ifdef HEATER_USES_THERMISTOR + int raw = 0; + byte i; + + for (i=1; i raw) + { + celsius = temptable[i-1][1] + + (raw - temptable[i-1][0]) * + (temptable[i][1] - temptable[i-1][1]) / + (temptable[i][0] - temptable[i-1][0]); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == NUMTEMPS) celsius = temptable[i-1][1]; + + return celsius; + #elif defined HEATER_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +// Derived from RepRap FiveD extruder::getTemperature() +// For bed temperature measurement. +float analog2tempBed(int raw) { + #ifdef BED_USES_THERMISTOR + int celsius = 0; + byte i; + + raw = (1023 * OVERSAMPLENR) - raw; + + for (i=1; i raw) + { + celsius = bedtemptable[i-1][1] + + (raw - bedtemptable[i-1][0]) * + (bedtemptable[i][1] - bedtemptable[i-1][1]) / + (bedtemptable[i][0] - bedtemptable[i-1][0]); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == NUMTEMPS) celsius = bedtemptable[i-1][1]; + + return celsius; + + #elif defined BED_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +void tp_init() +{ +#if (HEATER_0_PIN > -1) + SET_OUTPUT(HEATER_0_PIN); +#endif +#if (HEATER_1_PIN > -1) + SET_OUTPUT(HEATER_1_PIN); +#endif +#if (HEATER_2_PIN > -1) + SET_OUTPUT(HEATER_2_PIN); +#endif + +#ifdef PIDTEMP + temp_iState_min = 0.0; + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; +#endif //PIDTEMP + +// Set analog inputs + ADCSRA = 1< -1) + #if TEMP_0_PIN < 8 + DIDR0 = 1 << TEMP_0_PIN; + #else + DIDR2 = 1<<(TEMP_0_PIN - 8); + ADCSRB = 1< -1) + raw_temp_0_value += ADC; + #endif + temp_state = 2; + break; + case 2: // Prepare TEMP_1 + #if (TEMP_1_PIN > -1) + #if TEMP_1_PIN < 7 + DIDR0 = 1< -1) + raw_temp_1_value += ADC; + #endif + temp_state = 4; + break; + case 4: // Prepare TEMP_2 + #if (TEMP_2_PIN > -1) + #if TEMP_2_PIN < 7 + DIDR0 = 1 << TEMP_2_PIN; + #else + DIDR2 = 1<<(TEMP_2_PIN - 8); + ADCSRB = 1< -1) + raw_temp_2_value += ADC; + #endif + temp_state = 0; + temp_count++; + break; + default: + Serial.println("!! Temp measurement error !!"); + break; + } + + if(temp_count >= 16) // 6 ms * 16 = 96ms. + { + #ifdef HEATER_USES_AD595 + current_raw[0] = raw_temp_0_value; + current_raw[2] = raw_temp_2_value; + #else + current_raw[0] = 16383 - raw_temp_0_value; + current_raw[2] = 16383 - raw_temp_2_value; + #endif + + #ifdef BED_USES_AD595 + current_raw[1] = raw_temp_1_value; + #else + current_raw[1] = 16383 - raw_temp_1_value; + #endif + + temp_meas_ready = true; + temp_count = 0; + raw_temp_0_value = 0; + raw_temp_1_value = 0; + raw_temp_2_value = 0; +#ifdef MAXTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[0] >= maxttemp) { + target_raw[0] = 0; + analogWrite(HEATER_0_PIN, 0); + Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); + } + #endif + #if (HEATER_2_PIN > -1) + if(current_raw[2] >= maxttemp) { + target_raw[2] = 0; + analogWrite(HEATER_2_PIN, 0); + Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); + } + #endif +#endif //MAXTEMP +#ifdef MINTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[0] <= minttemp) { + target_raw[0] = 0; + analogWrite(HEATER_0_PIN, 0); + Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); + } + #endif + #if (HEATER_2_PIN > -1) + if(current_raw[2] <= minttemp) { + target_raw[2] = 0; + analogWrite(HEATER_2_PIN, 0); + Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); + } + #endif +#endif //MAXTEMP +#ifdef BED_MINTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] <= bed_minttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); + } + #endif +#endif +#ifdef BED_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] >= bed_maxttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); + } + #endif +#endif + } +} diff --git a/Marlin/temperature.h b/Marlin/temperature.h new file mode 100644 index 0000000000..986aca9998 --- /dev/null +++ b/Marlin/temperature.h @@ -0,0 +1,55 @@ +/* + temperature.h - temperature controller + Part of Marlin + + Copyright (c) 2011 Erik van der Zalm + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +#ifndef temperature_h +#define temperature_h + +void manage_inactivity(byte debug); + +void tp_init(); +void manage_heater(); +//int temp2analogu(int celsius, const short table[][2], int numtemps); +//float analog2tempu(int raw, const short table[][2], int numtemps); +float temp2analog(int celsius); +float temp2analogBed(int celsius); +float analog2temp(int raw); +float analog2tempBed(int raw); + +#ifdef HEATER_USES_THERMISTOR + #define HEATERSOURCE 1 +#endif +#ifdef BED_USES_THERMISTOR + #define BEDSOURCE 1 +#endif + +//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) +//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS + + +extern float Kp; +extern float Ki; +extern float Kd; +extern float Kc; + +extern int target_raw[3]; +extern int current_raw[3]; +extern double pid_setpoint; + +#endif diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 1c780020b0..725e972fa1 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -1,132 +1,133 @@ #ifndef THERMISTORTABLES_H_ #define THERMISTORTABLES_H_ +#define OVERSAMPLENR 16 #if (THERMISTORHEATER == 1) || (THERMISTORBED == 1) //100k bed thermistor #define NUMTEMPS_1 61 const short temptable_1[NUMTEMPS_1][2] = { -{ (23*16) , 300 }, -{ (25*16) , 295 }, -{ (27*16) , 290 }, -{ (28*16) , 285 }, -{ (31*16) , 280 }, -{ (33*16) , 275 }, -{ (35*16) , 270 }, -{ (38*16) , 265 }, -{ (41*16) , 260 }, -{ (44*16) , 255 }, -{ (48*16) , 250 }, -{ (52*16) , 245 }, -{ (56*16) , 240 }, -{ (61*16) , 235 }, -{ (66*16) , 230 }, -{ (71*16) , 225 }, -{ (78*16) , 220 }, -{ (84*16) , 215 }, -{ (92*16) , 210 }, -{ (100*16), 205 }, -{ (109*16), 200 }, -{ (120*16), 195 }, -{ (131*16), 190 }, -{ (143*16), 185 }, -{ (156*16), 180 }, -{ (171*16), 175 }, -{ (187*16), 170 }, -{ (205*16), 165 }, -{ (224*16), 160 }, -{ (245*16), 155 }, -{ (268*16), 150 }, -{ (293*16), 145 }, -{ (320*16), 140 }, -{ (348*16), 135 }, -{ (379*16), 130 }, -{ (411*16), 125 }, -{ (445*16), 120 }, -{ (480*16), 115 }, -{ (516*16), 110 }, -{ (553*16), 105 }, -{ (591*16), 100 }, -{ (628*16), 95 }, -{ (665*16), 90 }, -{ (702*16), 85 }, -{ (737*16), 80 }, -{ (770*16), 75 }, -{ (801*16), 70 }, -{ (830*16), 65 }, -{ (857*16), 60 }, -{ (881*16), 55 }, -{ (903*16), 50 }, -{ (922*16), 45 }, -{ (939*16), 40 }, -{ (954*16), 35 }, -{ (966*16), 30 }, -{ (977*16), 25 }, -{ (985*16), 20 }, -{ (993*16), 15 }, -{ (999*16), 10 }, -{ (1004*16), 5 }, -{ (1008*16), 0 } //safety +{ (23*OVERSAMPLENR) , 300 }, +{ (25*OVERSAMPLENR) , 295 }, +{ (27*OVERSAMPLENR) , 290 }, +{ (28*OVERSAMPLENR) , 285 }, +{ (31*OVERSAMPLENR) , 280 }, +{ (33*OVERSAMPLENR) , 275 }, +{ (35*OVERSAMPLENR) , 270 }, +{ (38*OVERSAMPLENR) , 265 }, +{ (41*OVERSAMPLENR) , 260 }, +{ (44*OVERSAMPLENR) , 255 }, +{ (48*OVERSAMPLENR) , 250 }, +{ (52*OVERSAMPLENR) , 245 }, +{ (56*OVERSAMPLENR) , 240 }, +{ (61*OVERSAMPLENR) , 235 }, +{ (66*OVERSAMPLENR) , 230 }, +{ (71*OVERSAMPLENR) , 225 }, +{ (78*OVERSAMPLENR) , 220 }, +{ (84*OVERSAMPLENR) , 215 }, +{ (92*OVERSAMPLENR) , 210 }, +{ (100*OVERSAMPLENR), 205 }, +{ (109*OVERSAMPLENR), 200 }, +{ (120*OVERSAMPLENR), 195 }, +{ (131*OVERSAMPLENR), 190 }, +{ (143*OVERSAMPLENR), 185 }, +{ (156*OVERSAMPLENR), 180 }, +{ (171*OVERSAMPLENR), 175 }, +{ (187*OVERSAMPLENR), 170 }, +{ (205*OVERSAMPLENR), 165 }, +{ (224*OVERSAMPLENR), 160 }, +{ (245*OVERSAMPLENR), 155 }, +{ (268*OVERSAMPLENR), 150 }, +{ (293*OVERSAMPLENR), 145 }, +{ (320*OVERSAMPLENR), 140 }, +{ (348*OVERSAMPLENR), 135 }, +{ (379*OVERSAMPLENR), 130 }, +{ (411*OVERSAMPLENR), 125 }, +{ (445*OVERSAMPLENR), 120 }, +{ (480*OVERSAMPLENR), 115 }, +{ (516*OVERSAMPLENR), 110 }, +{ (553*OVERSAMPLENR), 105 }, +{ (591*OVERSAMPLENR), 100 }, +{ (628*OVERSAMPLENR), 95 }, +{ (665*OVERSAMPLENR), 90 }, +{ (702*OVERSAMPLENR), 85 }, +{ (737*OVERSAMPLENR), 80 }, +{ (770*OVERSAMPLENR), 75 }, +{ (801*OVERSAMPLENR), 70 }, +{ (830*OVERSAMPLENR), 65 }, +{ (857*OVERSAMPLENR), 60 }, +{ (881*OVERSAMPLENR), 55 }, +{ (903*OVERSAMPLENR), 50 }, +{ (922*OVERSAMPLENR), 45 }, +{ (939*OVERSAMPLENR), 40 }, +{ (954*OVERSAMPLENR), 35 }, +{ (966*OVERSAMPLENR), 30 }, +{ (977*OVERSAMPLENR), 25 }, +{ (985*OVERSAMPLENR), 20 }, +{ (993*OVERSAMPLENR), 15 }, +{ (999*OVERSAMPLENR), 10 }, +{ (1004*OVERSAMPLENR), 5 }, +{ (1008*OVERSAMPLENR), 0 } //safety }; #endif #if (THERMISTORHEATER == 2) || (THERMISTORBED == 2) //200k bed thermistor #define NUMTEMPS_2 21 const short temptable_2[NUMTEMPS_2][2] = { - {(1*16), 848}, - {(54*16), 275}, - {(107*16), 228}, - {(160*16), 202}, - {(213*16), 185}, - {(266*16), 171}, - {(319*16), 160}, - {(372*16), 150}, - {(425*16), 141}, - {(478*16), 133}, - {(531*16), 125}, - {(584*16), 118}, - {(637*16), 110}, - {(690*16), 103}, - {(743*16), 95}, - {(796*16), 86}, - {(849*16), 77}, - {(902*16), 65}, - {(955*16), 49}, - {(1008*16), 17}, - {(1020*16), 0} //safety + {(1*OVERSAMPLENR), 848}, + {(54*OVERSAMPLENR), 275}, + {(107*OVERSAMPLENR), 228}, + {(160*OVERSAMPLENR), 202}, + {(213*OVERSAMPLENR), 185}, + {(266*OVERSAMPLENR), 171}, + {(319*OVERSAMPLENR), 160}, + {(372*OVERSAMPLENR), 150}, + {(425*OVERSAMPLENR), 141}, + {(478*OVERSAMPLENR), 133}, + {(531*OVERSAMPLENR), 125}, + {(584*OVERSAMPLENR), 118}, + {(637*OVERSAMPLENR), 110}, + {(690*OVERSAMPLENR), 103}, + {(743*OVERSAMPLENR), 95}, + {(796*OVERSAMPLENR), 86}, + {(849*OVERSAMPLENR), 77}, + {(902*OVERSAMPLENR), 65}, + {(955*OVERSAMPLENR), 49}, + {(1008*OVERSAMPLENR), 17}, + {(1020*OVERSAMPLENR), 0} //safety }; #endif #if (THERMISTORHEATER == 3) || (THERMISTORBED == 3) //mendel-parts #define NUMTEMPS_3 28 const short temptable_3[NUMTEMPS_3][2] = { - {(1*16),864}, - {(21*16),300}, - {(25*16),290}, - {(29*16),280}, - {(33*16),270}, - {(39*16),260}, - {(46*16),250}, - {(54*16),240}, - {(64*16),230}, - {(75*16),220}, - {(90*16),210}, - {(107*16),200}, - {(128*16),190}, - {(154*16),180}, - {(184*16),170}, - {(221*16),160}, - {(265*16),150}, - {(316*16),140}, - {(375*16),130}, - {(441*16),120}, - {(513*16),110}, - {(588*16),100}, - {(734*16),80}, - {(856*16),60}, - {(938*16),40}, - {(986*16),20}, - {(1008*16),0}, - {(1018*16),-20} + {(1*OVERSAMPLENR),864}, + {(21*OVERSAMPLENR),300}, + {(25*OVERSAMPLENR),290}, + {(29*OVERSAMPLENR),280}, + {(33*OVERSAMPLENR),270}, + {(39*OVERSAMPLENR),260}, + {(46*OVERSAMPLENR),250}, + {(54*OVERSAMPLENR),240}, + {(64*OVERSAMPLENR),230}, + {(75*OVERSAMPLENR),220}, + {(90*OVERSAMPLENR),210}, + {(107*OVERSAMPLENR),200}, + {(128*OVERSAMPLENR),190}, + {(154*OVERSAMPLENR),180}, + {(184*OVERSAMPLENR),170}, + {(221*OVERSAMPLENR),160}, + {(265*OVERSAMPLENR),150}, + {(316*OVERSAMPLENR),140}, + {(375*OVERSAMPLENR),130}, + {(441*OVERSAMPLENR),120}, + {(513*OVERSAMPLENR),110}, + {(588*OVERSAMPLENR),100}, + {(734*OVERSAMPLENR),80}, + {(856*OVERSAMPLENR),60}, + {(938*OVERSAMPLENR),40}, + {(986*OVERSAMPLENR),20}, + {(1008*OVERSAMPLENR),0}, + {(1018*OVERSAMPLENR),-20} }; #endif diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h new file mode 100644 index 0000000000..5f0196fa5a --- /dev/null +++ b/Marlin/ultralcd.h @@ -0,0 +1,156 @@ +#ifndef __ULTRALCDH +#define __ULTRALCDH +#include "Configuration.h" + +#ifdef ULTRA_LCD + + void lcd_status(); + void lcd_init(); + void lcd_status(const char* message); + void beep(); + void buttons_check(); + #define LCDSTATUSRIGHT + + #define LCD_UPDATE_INTERVAL 100 + #define STATUSTIMEOUT 15000 + + #include "Configuration.h" + + #include + extern LiquidCrystal lcd; + + //lcd display size + +#ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + #define EN_C (1< +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 + +unsigned long previous_millis_lcd=0; + + + +volatile char buttons=0; //the last checked buttons in a bit array. +int encoderpos=0; +short lastenc=0; +#ifdef NEWPANEL + long blocking=0; +#else + long blocking[8]={0,0,0,0,0,0,0,0}; +#endif +MainMenu menu; + +void lcd_status(const char* message) +{ + strncpy(messagetext,message,LCD_WIDTH); +} + +void clear() +{ + //lcd.setCursor(0,0); + lcd.clear(); + //delay(1); + // lcd.begin(LCD_WIDTH,LCD_HEIGHT); + //lcd_init(); +} +long previous_millis_buttons=0; + +void lcd_init() +{ + //beep(); + byte Degree[8] = + { + B01100, + B10010, + B10010, + B01100, + B00000, + B00000, + B00000, + B00000 + }; + byte Thermometer[8] = + { + B00100, + B01010, + B01010, + B01010, + B01010, + B10001, + B10001, + B01110 + }; + byte uplevel[8]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris + byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + lcd.createChar(1,Degree); + lcd.createChar(2,Thermometer); + lcd.createChar(3,uplevel); + lcd.createChar(4,refresh); + LCD_MESSAGE(fillto(LCD_WIDTH,"UltiMarlin ready.")); +} + + +void beep() +{ + //return; +#ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<20;i++){ + WRITE(BEEPER,HIGH); + delay(5); + WRITE(BEEPER,LOW); + delay(5); + } +#endif +} + +void beepshort() +{ + //return; +#ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<10;i++){ + WRITE(BEEPER,HIGH); + delay(3); + WRITE(BEEPER,LOW); + delay(3); + } +#endif +} +void lcd_status() +{ +#ifdef ULTIPANEL + static uint8_t oldbuttons=0; + static long previous_millis_buttons=0; + static long previous_lcdinit=0; +// buttons_check(); // Done in temperature interrupt + //previous_millis_buttons=millis(); + + if((buttons==oldbuttons) && ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; + oldbuttons=buttons; +#else + + if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; +#endif + + previous_millis_lcd=millis(); + menu.update(); +} +#ifdef ULTIPANEL +void buttons_init() +{ +#ifdef NEWPANEL + pinMode(BTN_EN1,INPUT); + pinMode(BTN_EN2,INPUT); + pinMode(BTN_ENC,INPUT); + pinMode(SDCARDDETECT,INPUT); + WRITE(BTN_EN1,HIGH); + WRITE(BTN_EN2,HIGH); + WRITE(BTN_ENC,HIGH); + WRITE(SDCARDDETECT,HIGH); +#else + pinMode(SHIFT_CLK,OUTPUT); + pinMode(SHIFT_LD,OUTPUT); + pinMode(SHIFT_EN,OUTPUT); + pinMode(SHIFT_OUT,INPUT); + WRITE(SHIFT_OUT,HIGH); + WRITE(SHIFT_LD,HIGH); + WRITE(SHIFT_EN,LOW); +#endif +} + + +void buttons_check() +{ +// volatile static bool busy=false; +// if(busy) +// return; +// busy=true; + +#ifdef NEWPANEL + uint8_t newbutton=0; + if(READ(BTN_EN1)==0) newbutton|=EN_A; + if(READ(BTN_EN2)==0) newbutton|=EN_B; + if((blocking>1; + if(READ(SHIFT_OUT)) + newbutton|=(1<<7); + WRITE(SHIFT_CLK,HIGH); + WRITE(SHIFT_CLK,LOW); + } + buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 +#endif + char enc=0; + if(buttons&EN_A) + enc|=(1<<0); + if(buttons&EN_B) + enc|=(1<<1); + if(enc!=lastenc) + { + switch(enc) + { + case encrot0: + if(lastenc==encrot3) + encoderpos++; + else if(lastenc==encrot1) + encoderpos--; + break; + case encrot1: + if(lastenc==encrot0) + encoderpos++; + else if(lastenc==encrot2) + encoderpos--; + break; + case encrot2: + if(lastenc==encrot1) + encoderpos++; + else if(lastenc==encrot3) + encoderpos--; + break; + case encrot3: + if(lastenc==encrot2) + encoderpos++; + else if(lastenc==encrot0) + encoderpos--; + break; + default: + ; + } + } + lastenc=enc; +// busy=false; +} + +#endif + +MainMenu::MainMenu() +{ + status=Main_Status; + displayStartingRow=0; + activeline=0; + force_lcd_update=true; +#ifdef ULTIPANEL + buttons_init(); +#endif + lcd_init(); + linechanging=false; +} + +extern volatile bool feedmultiplychanged; + +void MainMenu::showStatus() +{ +#if LCD_HEIGHT==4 + static int oldcurrentraw=-1; + static int oldtargetraw=-1; + //force_lcd_update=true; + if(force_lcd_update||feedmultiplychanged) //initial display of content + { + feedmultiplychanged=false; + encoderpos=feedmultiply; + clear(); + lcd.setCursor(0,0);lcd.print("\002123/567\001 "); +#if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + lcd.setCursor(10,0);lcd.print("B123/567\001 "); +#endif + } + + + if((abs(current_raw[0]-oldcurrentraw)>3)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_raw[0]))); + oldcurrentraw=current_raw[0]; + } + if((target_raw[0]!=oldtargetraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_raw[0]))); + oldtargetraw=target_raw[0]; + } + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + static int oldcurrentbedraw=-1; + static int oldtargetbedraw=-1; + if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_bed_raw))); + oldcurrentraw=current_raw[1]; + } + if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_bed_raw))); + oldtargetraw=target_bed_raw; + } + #endif + //starttime=2; + static uint16_t oldtime=0; + if(starttime!=0) + { + lcd.setCursor(0,1); + uint16_t time=millis()/60000-starttime/60000; + + if(starttime!=oldtime) + { + lcd.print(itostr2(time/60));lcd.print("h ");lcd.print(itostr2(time%60));lcd.print("m"); + oldtime=time; + } + } + static int oldzpos=0; + int currentz=current_position[2]*10; + if((currentz!=oldzpos)||force_lcd_update) + { + lcd.setCursor(10,1); + lcd.print("Z:");lcd.print(itostr31(currentz)); + oldzpos=currentz; + } + static int oldfeedmultiply=0; + int curfeedmultiply=feedmultiply; + if(encoderpos!=curfeedmultiply||force_lcd_update) + { + curfeedmultiply=encoderpos; + if(curfeedmultiply<10) + curfeedmultiply=10; + if(curfeedmultiply>999) + curfeedmultiply=999; + feedmultiply=curfeedmultiply; + encoderpos=curfeedmultiply; + } + if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) + { + oldfeedmultiply=curfeedmultiply; + lcd.setCursor(0,2); + lcd.print(itostr3(curfeedmultiply));lcd.print("% "); + } + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(fillto(LCD_WIDTH,messagetext)); + messagetext[0]='\0'; + } +#else //smaller LCDS---------------------------------- + static int oldcurrentraw=-1; + static int oldtargetraw=-1; + if(force_lcd_update) //initial display of content + { + encoderpos=feedmultiply; + lcd.setCursor(0,0);lcd.print("\002123/567\001 "); + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + lcd.setCursor(10,0);lcd.print("B123/567\001 "); + #endif + } + + + if((abs(current_raw[0]-oldcurrentraw)>3)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_raw[0]))); + oldcurrentraw=current_raw[0]; + } + if((target_raw[0]!=oldtargetraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_raw[0]))); + oldtargetraw=target_raw[0]; + } + + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(fillto(LCD_WIDTH,messagetext)); + messagetext[0]='\0'; + } + +#endif +} + +enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; + +void MainMenu::showPrepare() +{ + uint8_t line=0; + if(lastlineoffset!=lineoffset) + { + force_lcd_update=true; + clear(); + } + for(uint8_t i=lineoffset;i3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(ItemP_disstep+1-LCD_HEIGHT)) + lineoffset=ItemP_disstep+1-LCD_HEIGHT; + force_lcd_update=true; + } + //encoderpos=encoderpos%LCD_HEIGHT; + lastencoderpos=encoderpos; + activeline=encoderpos/lcdslow; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + } +} +enum { + ItemC_exit, ItemC_nozzle, + ItemC_PID_P,ItemC_PID_I,ItemC_PID_D,ItemC_PID_C, + ItemC_fan, + ItemC_acc, ItemC_xyjerk, + ItemC_vmaxx, ItemC_vmaxy, ItemC_vmaxz, ItemC_vmaxe, + ItemC_vtravmin,ItemC_vmin, + ItemC_amaxx, ItemC_amaxy, ItemC_amaxz, ItemC_amaxe, + ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe +}; + +void MainMenu::showControl() +{ + uint8_t line=0; + if((lastlineoffset!=lineoffset)||force_lcd_update) + { + force_lcd_update=true; + clear(); + } + for(uint8_t i=lineoffset;i260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_fan: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Fan speed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + } + + if((activeline==line) ) + { + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=fanpwm; + } + else + { + fanpwm = constrain(encoderpos,0,255); + encoderpos=fanpwm; + analogWrite(FAN_PIN, fanpwm); + + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_acc: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Acc:"); + lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)acceleration/100; + } + else + { + acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_xyjerk: //max_xy_jerk + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vxy-jerk: "); + lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_xy_jerk/60; + } + else + { + max_xy_jerk= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_PID_P: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-P: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kp)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kp/5; + } + else + { + Kp= encoderpos*5; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>9990/5) encoderpos=9990/5; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + } + }break; + case ItemC_PID_I: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-I: "); + lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(Ki*10); + } + else + { + Ki= encoderpos/10.; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); + } + } + }break; + case ItemC_PID_D: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-D: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kd)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kd/5; + } + else + { + Kd= encoderpos*5; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990/5) encoderpos=9990/5; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + } + }break; + + + + case ItemC_PID_C: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-C: "); + lcd.setCursor(13,line);lcd.print(itostr3(Kc)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kc; + } + else + { + Kc= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_vmaxx: + case ItemC_vmaxy: + case ItemC_vmaxz: + case ItemC_vmaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vmax "); + if(i==ItemC_vmaxx)lcd.print("x:"); + if(i==ItemC_vmaxy)lcd.print("y:"); + if(i==ItemC_vmaxz)lcd.print("z:"); + if(i==ItemC_vmaxe)lcd.print("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemC_vmaxx]/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_feedrate[i-ItemC_vmaxx]/60; + } + else + { + max_feedrate[i-ItemC_vmaxx]= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_vmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vmin:"); + lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(minimumfeedrate/60.); + } + else + { + minimumfeedrate= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_vtravmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" VTrav min:"); + lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)mintravelfeedrate/60; + } + else + { + mintravelfeedrate= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_amaxx: + case ItemC_amaxy: + case ItemC_amaxz: + case ItemC_amaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Amax "); + if(i==ItemC_amaxx)lcd.print("x:"); + if(i==ItemC_amaxy)lcd.print("y:"); + if(i==ItemC_amaxz)lcd.print("z:"); + if(i==ItemC_amaxe)lcd.print("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100; + } + else + { + max_acceleration_units_per_sq_second[i-ItemC_amaxx]= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_aret://float retract_acceleration = 7000; + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" A-retract:"); + lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)retract_acceleration/100; + } + else + { + retract_acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<10) encoderpos=10; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_esteps://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Esteps/mm:"); + lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)axis_steps_per_unit[3]; + } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + } + }break; + case ItemC_store: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Store EPROM"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + StoreSettings(); + } + }break; + case ItemC_load: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Load EPROM"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + RetrieveSettings(); + } + }break; + case ItemC_failsafe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Restore Failsafe"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + RetrieveSettings(true); + } + }break; + default: + break; + } + line++; + } + lastlineoffset=lineoffset; + + if(!linechanging && ((encoderpos/lcdslow!=lastencoderpos/lcdslow)||force_lcd_update)) + { + + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?' ':' '); + + if(encoderpos<0) + { + lineoffset--; + if(lineoffset<0) + lineoffset=0; + encoderpos=0; + force_lcd_update=true; + } + if(encoderpos/lcdslow>3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(ItemC_failsafe+1-LCD_HEIGHT)) + lineoffset=ItemC_failsafe+1-LCD_HEIGHT; + force_lcd_update=true; + } + //encoderpos=encoderpos%LCD_HEIGHT; + lastencoderpos=encoderpos; + activeline=encoderpos/lcdslow; + if(activeline>3) activeline=3; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + } +} + +#include "SdFat.h" + +void MainMenu::getfilename(const uint8_t nr) +{ +#ifdef SDSUPPORT + dir_t p; + root.rewind(); + uint8_t cnt=0; + filename[0]='\0'; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + if(cnt++!=nr) continue; + //Serial.println((char*)p.name); + uint8_t writepos=0; + for (uint8_t i = 0; i < 11; i++) + { + if (p.name[i] == ' ') continue; + if (i == 8) { + filename[writepos++]='.'; + } + filename[writepos++]=p.name[i]; + } + filename[writepos++]=0; + } +#endif +} + +uint8_t getnrfilenames() +{ +#ifdef SDSUPPORT + dir_t p; + root.rewind(); + uint8_t cnt=0; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + cnt++; + } + return cnt; +#endif +} + +void MainMenu::showSD() +{ + +#ifdef SDSUPPORT + uint8_t line=0; + + if(lastlineoffset!=lineoffset) + { + force_lcd_update=true; + } + static uint8_t nrfiles=0; + if(force_lcd_update) + { + clear(); + if(sdactive) + { + nrfiles=getnrfilenames(); + } + else + { + nrfiles=0; + lineoffset=0; + } + //Serial.print("Nr files:"); Serial.println((int)nrfiles); + } + + for(int8_t i=lineoffset;i3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(1+nrfiles+1-LCD_HEIGHT)) + lineoffset=1+nrfiles+1-LCD_HEIGHT; + force_lcd_update=true; + + } + lastencoderpos=encoderpos; + activeline=encoderpos; + if(activeline>3) + { + activeline=3; + } + if(activeline<0) + { + activeline=0; + } + if(activeline>1+nrfiles) activeline=1+nrfiles; + if(lineoffset>1+nrfiles) lineoffset=1+nrfiles; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + + } +#endif +} + +enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file }; +void MainMenu::showMainMenu() +{ + //if(int(encoderpos/lcdslow)!=int(lastencoderpos/lcdslow)) + // force_lcd_update=true; +#ifndef ULTIPANEL + force_lcd_update=false; +#endif + //Serial.println((int)activeline); + if(force_lcd_update) + clear(); + for(short line=0;line=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + if((encoderpos!=lastencoderpos)||force_lcd_update) + { + lcd.setCursor(0,activeline);lcd.print(activeline?' ':' '); + if(encoderpos<0) encoderpos=0; + if(encoderpos>3*lcdslow) encoderpos=3*lcdslow; + activeline=abs(encoderpos/lcdslow)%LCD_HEIGHT; + if(activeline<0) activeline=0; + if(activeline>=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + lastencoderpos=encoderpos; + lcd.setCursor(0,activeline);lcd.print(activeline?'>':'\003'); + } + + + +} + +void MainMenu::update() +{ + static MainStatus oldstatus=Main_Menu; //init automatically causes foce_lcd_update=true + static long timeoutToStatus=0; + static bool oldcardstatus=false; +#ifdef CARDINSERTED + if((CARDINSERTED != oldcardstatus)) + { + force_lcd_update=true; + oldcardstatus=CARDINSERTED; + //Serial.println("SD CHANGE"); + if(CARDINSERTED) + { + initsd(); + lcd_status("Card inserted"); + } + else + { + sdactive=false; + lcd_status("Card removed"); + + } + } +#endif + + if(status!=oldstatus) + { + //Serial.println(status); + //clear(); + force_lcd_update=true; + encoderpos=0; + lineoffset=0; + + oldstatus=status; + } + if( (encoderpos!=lastencoderpos) || CLICKED) + timeoutToStatus=millis()+STATUSTIMEOUT; + + switch(status) + { + case Main_Status: + { + showStatus(); + if(CLICKED) + { + linechanging=false; + BLOCK + status=Main_Menu; + timeoutToStatus=millis()+STATUSTIMEOUT; + } + }break; + case Main_Menu: + { + showMainMenu(); + linechanging=false; + }break; + case Main_Prepare: + { + showPrepare(); + }break; + case Main_Control: + { + showControl(); + }break; + case Main_SD: + { + showSD(); + }break; + } + + if(timeoutToStatus=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} + +char *itostr31(const int &xx) +{ + //sprintf(conv,"%5.1f",x); + conv[0]=(xx>=0)?'+':'-'; + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} +char *itostr3(const int &xx) +{ + conv[0]=(xx/100)%10+'0'; + conv[1]=(xx/10)%10+'0'; + conv[2]=(xx)%10+'0'; + conv[3]=0; + return conv; +} + +char *itostr4(const int &xx) +{ + conv[0]=(xx/1000)%10+'0'; + conv[1]=(xx/100)%10+'0'; + conv[2]=(xx/10)%10+'0'; + conv[3]=(xx)%10+'0'; + conv[4]=0; + return conv; +} + +/// convert float to string with +1234.5 format +char *ftostr51(const float &x) +{ + int xx=x*10; + conv[0]=(xx>=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/10000)%10+'0'; + conv[2]=(xx/1000)%10+'0'; + conv[3]=(xx/100)%10+'0'; + conv[4]=(xx/10)%10+'0'; + conv[5]='.'; + conv[6]=(xx)%10+'0'; + conv[7]=0; + return conv; +} + +char *fillto(int8_t n,char *c) +{ + static char ret[25]; + bool endfound=false; + for(int8_t i=0;i= 16000000L - // for the 16 MHz clock on most Arduino boards - - // for a one-microsecond delay, simply return. the overhead - // of the function call yields a delay of approximately 1 1/8 us. - if (--us == 0) - return; - - // the following loop takes a quarter of a microsecond (4 cycles) - // per iteration, so execute it four times for each microsecond of - // delay requested. - us <<= 2; - - // account for the time taken in the preceeding commands. - us -= 2; -#else - // for the 8 MHz internal clock on the ATmega168 - - // for a one- or two-microsecond delay, simply return. the overhead of - // the function calls takes more than two microseconds. can't just - // subtract two, since us is unsigned; we'd overflow. - if (--us == 0) - return; - if (--us == 0) - return; - - // the following loop takes half of a microsecond (4 cycles) - // per iteration, so execute it twice for each microsecond of - // delay requested. - us <<= 1; - - // partially compensate for the time taken by the preceeding commands. - // we can't subtract any more than this or we'd overflow w/ small delays. - us--; -#endif - - // disable interrupts, otherwise the timer 0 overflow interrupt that - // tracks milliseconds will make us delay longer than we want. - oldSREG = SREG; - cli(); - - // busy wait - __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles - "brne 1b" : "=w" (us) : "0" (us) // 2 cycles - ); - - // reenable interrupts. - SREG = oldSREG; -} - -void init() -{ - // this needs to be called before setup() or some functions won't - // work there - sei(); - - // on the ATmega168, timer 0 is also used for fast hardware pwm - // (using phase-correct PWM would mean that timer 0 overflowed half as often - // resulting in different millis() behavior on the ATmega8 and ATmega168) - sbi(TCCR0A, WGM01); - sbi(TCCR0A, WGM00); - - // set timer 0 prescale factor to 64 - sbi(TCCR0B, CS01); - sbi(TCCR0B, CS00); - - // enable timer 0 overflow interrupt - sbi(TIMSK0, TOIE0); - - // timers 1 and 2 are used for phase-correct hardware pwm - // this is better for motors as it ensures an even waveform - // note, however, that fast pwm mode can achieve a frequency of up - // 8 MHz (with a 16 MHz clock) at 50% duty cycle -#if 0 - // set timer 1 prescale factor to 64 - sbi(TCCR1B, CS11); - sbi(TCCR1B, CS10); - - // put timer 1 in 8-bit phase correct pwm mode - sbi(TCCR1A, WGM10); - - // set timer 2 prescale factor to 64 - sbi(TCCR2B, CS22); - - // configure timer 2 for phase correct pwm (8-bit) - sbi(TCCR2A, WGM20); - - // set a2d prescale factor to 128 - // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. - // XXX: this will not work properly for other clock speeds, and - // this code should use F_CPU to determine the prescale factor. - sbi(ADCSRA, ADPS2); - sbi(ADCSRA, ADPS1); - sbi(ADCSRA, ADPS0); - - // enable a2d conversions - sbi(ADCSRA, ADEN); - - // the bootloader connects pins 0 and 1 to the USART; disconnect them - // here so they can be used as normal digital i/o; they will be - // reconnected in Serial.begin() - UCSR0B = 0; - #if defined(__AVR_ATmega644P__) - //TODO: test to see if disabling this helps? - //UCSR1B = 0; - #endif -#endif -} diff --git a/Marlin/wiring_serial.c b/Marlin/wiring_serial.c deleted file mode 100644 index c027944c90..0000000000 --- a/Marlin/wiring_serial.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - wiring_serial.c - serial functions. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - Modified 29 January 2009, Marius Kintel for Sanguino - http://www.sanguino.cc/ - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - - -#include "wiring_private.h" - -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which rx_buffer_head is the index of the -// location to which to write the next incoming character and rx_buffer_tail -// is the index of the location from which to read. -#define RX_BUFFER_SIZE 128 -#define RX_BUFFER_MASK 0x7f - -#if defined(__AVR_ATmega644P__) -unsigned char rx_buffer[2][RX_BUFFER_SIZE]; -int rx_buffer_head[2] = {0, 0}; -int rx_buffer_tail[2] = {0, 0}; -#else -unsigned char rx_buffer[1][RX_BUFFER_SIZE]; -int rx_buffer_head[1] = {0}; -int rx_buffer_tail[1] = {0}; -#endif - - -#define BEGIN_SERIAL(uart_, baud_) \ -{ \ - UBRR##uart_##H = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8; \ - UBRR##uart_##L = ((F_CPU / 16 + baud / 2) / baud - 1); \ - \ - /* reset config for UART */ \ - UCSR##uart_##A = 0; \ - UCSR##uart_##B = 0; \ - UCSR##uart_##C = 0; \ - \ - /* enable rx and tx */ \ - sbi(UCSR##uart_##B, RXEN##uart_);\ - sbi(UCSR##uart_##B, TXEN##uart_);\ - \ - /* enable interrupt on complete reception of a byte */ \ - sbi(UCSR##uart_##B, RXCIE##uart_); \ - UCSR##uart_##C = _BV(UCSZ##uart_##1)|_BV(UCSZ##uart_##0); \ - /* defaults to 8-bit, no parity, 1 stop bit */ \ -} - -void beginSerial(uint8_t uart, long baud) -{ - if (uart == 0) BEGIN_SERIAL(0, baud) -#if defined(__AVR_ATmega644P__) - else BEGIN_SERIAL(1, baud) -#endif -} - -#define SERIAL_WRITE(uart_, c_) \ - while (!(UCSR##uart_##A & (1 << UDRE##uart_))) \ - ; \ - UDR##uart_ = c - -void serialWrite(uint8_t uart, unsigned char c) -{ - if (uart == 0) { - SERIAL_WRITE(0, c); - } -#if defined(__AVR_ATmega644P__) - else { - SERIAL_WRITE(1, c); - } -#endif -} - -int serialAvailable(uint8_t uart) -{ - return (RX_BUFFER_SIZE + rx_buffer_head[uart] - rx_buffer_tail[uart]) & RX_BUFFER_MASK; -} - -int serialRead(uint8_t uart) -{ - // if the head isn't ahead of the tail, we don't have any characters - if (rx_buffer_head[uart] == rx_buffer_tail[uart]) { - return -1; - } else { - unsigned char c = rx_buffer[uart][rx_buffer_tail[uart]]; - rx_buffer_tail[uart] = (rx_buffer_tail[uart] + 1) & RX_BUFFER_MASK; - return c; - } -} - -void serialFlush(uint8_t uart) -{ - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // were full, not empty. - rx_buffer_head[uart] = rx_buffer_tail[uart]; -} - -#define UART_ISR(uart_) \ -ISR(USART##uart_##_RX_vect) \ -{ \ - unsigned char c = UDR##uart_; \ - \ - int i = (rx_buffer_head[uart_] + 1) & RX_BUFFER_MASK; \ - \ - /* if we should be storing the received character into the location \ - just before the tail (meaning that the head would advance to the \ - current location of the tail), we're about to overflow the buffer \ - and so we don't write the character or advance the head. */ \ - if (i != rx_buffer_tail[uart_]) { \ - rx_buffer[uart_][rx_buffer_head[uart_]] = c; \ - rx_buffer_head[uart_] = i; \ - } \ -} - -UART_ISR(0) -#if defined(__AVR_ATmega644P__) -UART_ISR(1) -#endif From bf879ceaa9685648adba645cadc6ce5aaa5fac85 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 4 Nov 2011 22:51:14 +0100 Subject: [PATCH 002/228] Added thermistor tables --- Marlin/Configuration.h | 21 +- Marlin/temperature.cpp | 48 ++-- Marlin/thermistortables.h | 509 ++++++++++++++++++++++++++++---------- 3 files changed, 425 insertions(+), 153 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 2cef365b09..36b5f7b67b 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -14,14 +14,23 @@ #define MOTHERBOARD 7 //#define MOTHERBOARD 5 + //// Thermistor settings: // 1 is 100k thermistor // 2 is 200k thermistor // 3 is mendel-parts thermistor -#define THERMISTORHEATER 3 -// Select one of these only to define how the nozzle temp is read. -//#define HEATER_USES_THERMISTOR -#define HEATER_USES_AD595 +// 4 is 10k thermistor +// 5 is ParCan supplied 104GT-2 100K +// 6 is EPCOS 100k +// 7 is 100k Honeywell thermistor 135-104LAG-J01 +#define THERMISTORHEATER_1 3 +#define THERMISTORHEATER_2 3 +#define THERMISTORBED 3 + +//#define HEATER_1_USES_THERMISTOR +//#define HEATER_2_USES_THERMISTOR +#define HEATER_1_USES_AD595 +//#define HEATER_2_USES_AD595 // Select one of these only to define how the bed temp is read. //#define BED_USES_THERMISTOR @@ -29,8 +38,6 @@ #define HEATER_CHECK_INTERVAL 50 #define BED_CHECK_INTERVAL 5000 -#define BNUMTEMPS NUMTEMPS -#define bedtemptable temptable //// Endstop Settings @@ -50,7 +57,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define LCD_WIDTH 16 #define LCD_HEIGHT 2 -#define ULTIPANEL +//#define ULTIPANEL #ifdef ULTIPANEL //#define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 248b807fd4..7a9c56e10b 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -174,28 +174,28 @@ CRITICAL_SECTION_END; // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. float temp2analog(int celsius) { - #ifdef HEATER_USES_THERMISTOR + #ifdef HEATER_USES_THERMISTOR_1 int raw = 0; byte i; - for (i=1; i raw) + if (temptable_1[i][0] > raw) { - celsius = temptable[i-1][1] + - (raw - temptable[i-1][0]) * - (temptable[i][1] - temptable[i-1][1]) / - (temptable[i][0] - temptable[i-1][0]); + celsius = temptable_1[i-1][1] + + (raw - temptable_1[i-1][0]) * + (temptable_1[i][1] - temptable_1[i-1][1]) / + (temptable_1[i][0] - temptable_1[i-1][0]); break; } } // Overflow: Set to last value in the table - if (i == NUMTEMPS) celsius = temptable[i-1][1]; + if (i == NUMTEMPS_HEATER_1) celsius = temptable_1[i-1][1]; return celsius; - #elif defined HEATER_USES_AD595 + #elif defined HEATER_1_USES_AD595 return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; #endif } @@ -270,7 +270,7 @@ float analog2tempBed(int raw) { raw = (1023 * OVERSAMPLENR) - raw; - for (i=1; i raw) { @@ -284,7 +284,7 @@ float analog2tempBed(int raw) { } // Overflow: Set to last value in the table - if (i == NUMTEMPS) celsius = bedtemptable[i-1][1]; + if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; return celsius; @@ -403,11 +403,15 @@ ISR(TIMER0_COMPB_vect) if(temp_count >= 16) // 6 ms * 16 = 96ms. { - #ifdef HEATER_USES_AD595 + #ifdef HEATER_1_USES_AD595 current_raw[0] = raw_temp_0_value; - current_raw[2] = raw_temp_2_value; #else current_raw[0] = 16383 - raw_temp_0_value; + #endif + + #ifdef HEATER_2_USES_AD595 + current_raw[2] = raw_temp_2_value; + #else current_raw[2] = 16383 - raw_temp_2_value; #endif diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 725e972fa1..0ea1991dce 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -2,148 +2,409 @@ #define THERMISTORTABLES_H_ #define OVERSAMPLENR 16 -#if (THERMISTORHEATER == 1) || (THERMISTORBED == 1) //100k bed thermistor +#if (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor #define NUMTEMPS_1 61 const short temptable_1[NUMTEMPS_1][2] = { -{ (23*OVERSAMPLENR) , 300 }, -{ (25*OVERSAMPLENR) , 295 }, -{ (27*OVERSAMPLENR) , 290 }, -{ (28*OVERSAMPLENR) , 285 }, -{ (31*OVERSAMPLENR) , 280 }, -{ (33*OVERSAMPLENR) , 275 }, -{ (35*OVERSAMPLENR) , 270 }, -{ (38*OVERSAMPLENR) , 265 }, -{ (41*OVERSAMPLENR) , 260 }, -{ (44*OVERSAMPLENR) , 255 }, -{ (48*OVERSAMPLENR) , 250 }, -{ (52*OVERSAMPLENR) , 245 }, -{ (56*OVERSAMPLENR) , 240 }, -{ (61*OVERSAMPLENR) , 235 }, -{ (66*OVERSAMPLENR) , 230 }, -{ (71*OVERSAMPLENR) , 225 }, -{ (78*OVERSAMPLENR) , 220 }, -{ (84*OVERSAMPLENR) , 215 }, -{ (92*OVERSAMPLENR) , 210 }, -{ (100*OVERSAMPLENR), 205 }, -{ (109*OVERSAMPLENR), 200 }, -{ (120*OVERSAMPLENR), 195 }, -{ (131*OVERSAMPLENR), 190 }, -{ (143*OVERSAMPLENR), 185 }, -{ (156*OVERSAMPLENR), 180 }, -{ (171*OVERSAMPLENR), 175 }, -{ (187*OVERSAMPLENR), 170 }, -{ (205*OVERSAMPLENR), 165 }, -{ (224*OVERSAMPLENR), 160 }, -{ (245*OVERSAMPLENR), 155 }, -{ (268*OVERSAMPLENR), 150 }, -{ (293*OVERSAMPLENR), 145 }, -{ (320*OVERSAMPLENR), 140 }, -{ (348*OVERSAMPLENR), 135 }, -{ (379*OVERSAMPLENR), 130 }, -{ (411*OVERSAMPLENR), 125 }, -{ (445*OVERSAMPLENR), 120 }, -{ (480*OVERSAMPLENR), 115 }, -{ (516*OVERSAMPLENR), 110 }, -{ (553*OVERSAMPLENR), 105 }, -{ (591*OVERSAMPLENR), 100 }, -{ (628*OVERSAMPLENR), 95 }, -{ (665*OVERSAMPLENR), 90 }, -{ (702*OVERSAMPLENR), 85 }, -{ (737*OVERSAMPLENR), 80 }, -{ (770*OVERSAMPLENR), 75 }, -{ (801*OVERSAMPLENR), 70 }, -{ (830*OVERSAMPLENR), 65 }, -{ (857*OVERSAMPLENR), 60 }, -{ (881*OVERSAMPLENR), 55 }, -{ (903*OVERSAMPLENR), 50 }, -{ (922*OVERSAMPLENR), 45 }, -{ (939*OVERSAMPLENR), 40 }, -{ (954*OVERSAMPLENR), 35 }, -{ (966*OVERSAMPLENR), 30 }, -{ (977*OVERSAMPLENR), 25 }, -{ (985*OVERSAMPLENR), 20 }, -{ (993*OVERSAMPLENR), 15 }, -{ (999*OVERSAMPLENR), 10 }, -{ (1004*OVERSAMPLENR), 5 }, -{ (1008*OVERSAMPLENR), 0 } //safety +{ 23*OVERSAMPLENR , 300 }, +{ 25*OVERSAMPLENR , 295 }, +{ 27*OVERSAMPLENR , 290 }, +{ 28*OVERSAMPLENR , 285 }, +{ 31*OVERSAMPLENR , 280 }, +{ 33*OVERSAMPLENR , 275 }, +{ 35*OVERSAMPLENR , 270 }, +{ 38*OVERSAMPLENR , 265 }, +{ 41*OVERSAMPLENR , 260 }, +{ 44*OVERSAMPLENR , 255 }, +{ 48*OVERSAMPLENR , 250 }, +{ 52*OVERSAMPLENR , 245 }, +{ 56*OVERSAMPLENR , 240 }, +{ 61*OVERSAMPLENR , 235 }, +{ 66*OVERSAMPLENR , 230 }, +{ 71*OVERSAMPLENR , 225 }, +{ 78*OVERSAMPLENR , 220 }, +{ 84*OVERSAMPLENR , 215 }, +{ 92*OVERSAMPLENR , 210 }, +{ 100*OVERSAMPLENR , 205 }, +{ 109*OVERSAMPLENR , 200 }, +{ 120*OVERSAMPLENR , 195 }, +{ 131*OVERSAMPLENR , 190 }, +{ 143*OVERSAMPLENR , 185 }, +{ 156*OVERSAMPLENR , 180 }, +{ 171*OVERSAMPLENR , 175 }, +{ 187*OVERSAMPLENR , 170 }, +{ 205*OVERSAMPLENR , 165 }, +{ 224*OVERSAMPLENR , 160 }, +{ 245*OVERSAMPLENR , 155 }, +{ 268*OVERSAMPLENR , 150 }, +{ 293*OVERSAMPLENR , 145 }, +{ 320*OVERSAMPLENR , 140 }, +{ 348*OVERSAMPLENR , 135 }, +{ 379*OVERSAMPLENR , 130 }, +{ 411*OVERSAMPLENR , 125 }, +{ 445*OVERSAMPLENR , 120 }, +{ 480*OVERSAMPLENR , 115 }, +{ 516*OVERSAMPLENR , 110 }, +{ 553*OVERSAMPLENR , 105 }, +{ 591*OVERSAMPLENR , 100 }, +{ 628*OVERSAMPLENR , 95 }, +{ 665*OVERSAMPLENR , 90 }, +{ 702*OVERSAMPLENR , 85 }, +{ 737*OVERSAMPLENR , 80 }, +{ 770*OVERSAMPLENR , 75 }, +{ 801*OVERSAMPLENR , 70 }, +{ 830*OVERSAMPLENR , 65 }, +{ 857*OVERSAMPLENR , 60 }, +{ 881*OVERSAMPLENR , 55 }, +{ 903*OVERSAMPLENR , 50 }, +{ 922*OVERSAMPLENR , 45 }, +{ 939*OVERSAMPLENR , 40 }, +{ 954*OVERSAMPLENR , 35 }, +{ 966*OVERSAMPLENR , 30 }, +{ 977*OVERSAMPLENR , 25 }, +{ 985*OVERSAMPLENR , 20 }, +{ 993*OVERSAMPLENR , 15 }, +{ 999*OVERSAMPLENR , 10 }, +{ 1004*OVERSAMPLENR , 5 }, +{ 1008*OVERSAMPLENR , 0 } //safety }; #endif -#if (THERMISTORHEATER == 2) || (THERMISTORBED == 2) //200k bed thermistor +#if (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor #define NUMTEMPS_2 21 const short temptable_2[NUMTEMPS_2][2] = { - {(1*OVERSAMPLENR), 848}, - {(54*OVERSAMPLENR), 275}, - {(107*OVERSAMPLENR), 228}, - {(160*OVERSAMPLENR), 202}, - {(213*OVERSAMPLENR), 185}, - {(266*OVERSAMPLENR), 171}, - {(319*OVERSAMPLENR), 160}, - {(372*OVERSAMPLENR), 150}, - {(425*OVERSAMPLENR), 141}, - {(478*OVERSAMPLENR), 133}, - {(531*OVERSAMPLENR), 125}, - {(584*OVERSAMPLENR), 118}, - {(637*OVERSAMPLENR), 110}, - {(690*OVERSAMPLENR), 103}, - {(743*OVERSAMPLENR), 95}, - {(796*OVERSAMPLENR), 86}, - {(849*OVERSAMPLENR), 77}, - {(902*OVERSAMPLENR), 65}, - {(955*OVERSAMPLENR), 49}, - {(1008*OVERSAMPLENR), 17}, - {(1020*OVERSAMPLENR), 0} //safety + {1*OVERSAMPLENR, 848}, + {54*OVERSAMPLENR, 275}, + {107*OVERSAMPLENR, 228}, + {160*OVERSAMPLENR, 202}, + {213*OVERSAMPLENR, 185}, + {266*OVERSAMPLENR, 171}, + {319*OVERSAMPLENR, 160}, + {372*OVERSAMPLENR, 150}, + {425*OVERSAMPLENR, 141}, + {478*OVERSAMPLENR, 133}, + {531*OVERSAMPLENR, 125}, + {584*OVERSAMPLENR, 118}, + {637*OVERSAMPLENR, 110}, + {690*OVERSAMPLENR, 103}, + {743*OVERSAMPLENR, 95}, + {796*OVERSAMPLENR, 86}, + {849*OVERSAMPLENR, 77}, + {902*OVERSAMPLENR, 65}, + {955*OVERSAMPLENR, 49}, + {1008*OVERSAMPLENR, 17}, + {1020*OVERSAMPLENR, 0} //safety }; #endif -#if (THERMISTORHEATER == 3) || (THERMISTORBED == 3) //mendel-parts +#if (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts #define NUMTEMPS_3 28 const short temptable_3[NUMTEMPS_3][2] = { - {(1*OVERSAMPLENR),864}, - {(21*OVERSAMPLENR),300}, - {(25*OVERSAMPLENR),290}, - {(29*OVERSAMPLENR),280}, - {(33*OVERSAMPLENR),270}, - {(39*OVERSAMPLENR),260}, - {(46*OVERSAMPLENR),250}, - {(54*OVERSAMPLENR),240}, - {(64*OVERSAMPLENR),230}, - {(75*OVERSAMPLENR),220}, - {(90*OVERSAMPLENR),210}, - {(107*OVERSAMPLENR),200}, - {(128*OVERSAMPLENR),190}, - {(154*OVERSAMPLENR),180}, - {(184*OVERSAMPLENR),170}, - {(221*OVERSAMPLENR),160}, - {(265*OVERSAMPLENR),150}, - {(316*OVERSAMPLENR),140}, - {(375*OVERSAMPLENR),130}, - {(441*OVERSAMPLENR),120}, - {(513*OVERSAMPLENR),110}, - {(588*OVERSAMPLENR),100}, - {(734*OVERSAMPLENR),80}, - {(856*OVERSAMPLENR),60}, - {(938*OVERSAMPLENR),40}, - {(986*OVERSAMPLENR),20}, - {(1008*OVERSAMPLENR),0}, - {(1018*OVERSAMPLENR),-20} + {1*OVERSAMPLENR,864}, + {21*OVERSAMPLENR,300}, + {25*OVERSAMPLENR,290}, + {29*OVERSAMPLENR,280}, + {33*OVERSAMPLENR,270}, + {39*OVERSAMPLENR,260}, + {46*OVERSAMPLENR,250}, + {54*OVERSAMPLENR,240}, + {64*OVERSAMPLENR,230}, + {75*OVERSAMPLENR,220}, + {90*OVERSAMPLENR,210}, + {107*OVERSAMPLENR,200}, + {128*OVERSAMPLENR,190}, + {154*OVERSAMPLENR,180}, + {184*OVERSAMPLENR,170}, + {221*OVERSAMPLENR,160}, + {265*OVERSAMPLENR,150}, + {316*OVERSAMPLENR,140}, + {375*OVERSAMPLENR,130}, + {441*OVERSAMPLENR,120}, + {513*OVERSAMPLENR,110}, + {588*OVERSAMPLENR,100}, + {734*OVERSAMPLENR,80}, + {856*OVERSAMPLENR,60}, + {938*OVERSAMPLENR,40}, + {986*OVERSAMPLENR,20}, + {1008*OVERSAMPLENR,0}, + {1018*OVERSAMPLENR,-20} }; #endif +#if (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor -#if THERMISTORHEATER == 1 -#define NUMTEMPS NUMTEMPS_1 -#define temptable temptable_1 -#elif THERMISTORHEATER == 2 -#define NUMTEMPS NUMTEMPS_2 -#define temptable temptable_2 -#elif THERMISTORHEATER == 3 -#define NUMTEMPS NUMTEMPS_3 -#define temptable temptable_3 -#else -#error No heater thermistor table specified +#define NUMTEMPS_4 20 +short temptable_4[NUMTEMPS_4][2] = { + {1*OVERSAMPLENR, 430}, + {54*OVERSAMPLENR, 137}, + {107*OVERSAMPLENR, 107}, + {160*OVERSAMPLENR, 91}, + {213*OVERSAMPLENR, 80}, + {266*OVERSAMPLENR, 71}, + {319*OVERSAMPLENR, 64}, + {372*OVERSAMPLENR, 57}, + {425*OVERSAMPLENR, 51}, + {478*OVERSAMPLENR, 46}, + {531*OVERSAMPLENR, 41}, + {584*OVERSAMPLENR, 35}, + {637*OVERSAMPLENR, 30}, + {690*OVERSAMPLENR, 25}, + {743*OVERSAMPLENR, 20}, + {796*OVERSAMPLENR, 14}, + {849*OVERSAMPLENR, 7}, + {902*OVERSAMPLENR, 0}, + {955*OVERSAMPLENR, -11}, + {1008*OVERSAMPLENR, -35} +}; +#endif + +#if (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) + +#define NUMTEMPS_5 61 +const short temptable_5[NUMTEMPS_5][2] = { +{1*OVERSAMPLENR, 713}, +{18*OVERSAMPLENR, 316}, +{35*OVERSAMPLENR, 266}, +{52*OVERSAMPLENR, 239}, +{69*OVERSAMPLENR, 221}, +{86*OVERSAMPLENR, 208}, +{103*OVERSAMPLENR, 197}, +{120*OVERSAMPLENR, 188}, +{137*OVERSAMPLENR, 181}, +{154*OVERSAMPLENR, 174}, +{171*OVERSAMPLENR, 169}, +{188*OVERSAMPLENR, 163}, +{205*OVERSAMPLENR, 159}, +{222*OVERSAMPLENR, 154}, +{239*OVERSAMPLENR, 150}, +{256*OVERSAMPLENR, 147}, +{273*OVERSAMPLENR, 143}, +{290*OVERSAMPLENR, 140}, +{307*OVERSAMPLENR, 136}, +{324*OVERSAMPLENR, 133}, +{341*OVERSAMPLENR, 130}, +{358*OVERSAMPLENR, 128}, +{375*OVERSAMPLENR, 125}, +{392*OVERSAMPLENR, 122}, +{409*OVERSAMPLENR, 120}, +{426*OVERSAMPLENR, 117}, +{443*OVERSAMPLENR, 115}, +{460*OVERSAMPLENR, 112}, +{477*OVERSAMPLENR, 110}, +{494*OVERSAMPLENR, 108}, +{511*OVERSAMPLENR, 106}, +{528*OVERSAMPLENR, 103}, +{545*OVERSAMPLENR, 101}, +{562*OVERSAMPLENR, 99}, +{579*OVERSAMPLENR, 97}, +{596*OVERSAMPLENR, 95}, +{613*OVERSAMPLENR, 92}, +{630*OVERSAMPLENR, 90}, +{647*OVERSAMPLENR, 88}, +{664*OVERSAMPLENR, 86}, +{681*OVERSAMPLENR, 84}, +{698*OVERSAMPLENR, 81}, +{715*OVERSAMPLENR, 79}, +{732*OVERSAMPLENR, 77}, +{749*OVERSAMPLENR, 75}, +{766*OVERSAMPLENR, 72}, +{783*OVERSAMPLENR, 70}, +{800*OVERSAMPLENR, 67}, +{817*OVERSAMPLENR, 64}, +{834*OVERSAMPLENR, 61}, +{851*OVERSAMPLENR, 58}, +{868*OVERSAMPLENR, 55}, +{885*OVERSAMPLENR, 52}, +{902*OVERSAMPLENR, 48}, +{919*OVERSAMPLENR, 44}, +{936*OVERSAMPLENR, 40}, +{953*OVERSAMPLENR, 34}, +{970*OVERSAMPLENR, 28}, +{987*OVERSAMPLENR, 20}, +{1004*OVERSAMPLENR, 8}, +{1021*OVERSAMPLENR, 0} +}; +#endif + +#if (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor +#define NUMTEMPS_6 36 +const short temptable_6[NUMTEMPS_6][2] = { + {28*OVERSAMPLENR, 250}, + {31*OVERSAMPLENR, 245}, + {35*OVERSAMPLENR, 240}, + {39*OVERSAMPLENR, 235}, + {42*OVERSAMPLENR, 230}, + {44*OVERSAMPLENR, 225}, + {49*OVERSAMPLENR, 220}, + {53*OVERSAMPLENR, 215}, + {62*OVERSAMPLENR, 210}, + {73*OVERSAMPLENR, 205}, + {72*OVERSAMPLENR, 200}, + {94*OVERSAMPLENR, 190}, + {102*OVERSAMPLENR, 185}, + {116*OVERSAMPLENR, 170}, + {143*OVERSAMPLENR, 160}, + {183*OVERSAMPLENR, 150}, + {223*OVERSAMPLENR, 140}, + {270*OVERSAMPLENR, 130}, + {318*OVERSAMPLENR, 120}, + {383*OVERSAMPLENR, 110}, + {413*OVERSAMPLENR, 105}, + {439*OVERSAMPLENR, 100}, + {484*OVERSAMPLENR, 95}, + {513*OVERSAMPLENR, 90}, + {607*OVERSAMPLENR, 80}, + {664*OVERSAMPLENR, 70}, + {781*OVERSAMPLENR, 60}, + {810*OVERSAMPLENR, 55}, + {849*OVERSAMPLENR, 50}, + {914*OVERSAMPLENR, 45}, + {914*OVERSAMPLENR, 40}, + {935*OVERSAMPLENR, 35}, + {954*OVERSAMPLENR, 30}, + {970*OVERSAMPLENR, 25}, + {978*OVERSAMPLENR, 22}, + {1008*OVERSAMPLENR, 3} +}; +#endif + +#if (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 +#define NUMTEMPS_7 54 +const short temptable_7[NUMTEMPS_7][2] = { + {46*OVERSAMPLENR, 270}, + {50*OVERSAMPLENR, 265}, + {54*OVERSAMPLENR, 260}, + {58*OVERSAMPLENR, 255}, + {62*OVERSAMPLENR, 250}, + {67*OVERSAMPLENR, 245}, + {72*OVERSAMPLENR, 240}, + {79*OVERSAMPLENR, 235}, + {85*OVERSAMPLENR, 230}, + {91*OVERSAMPLENR, 225}, + {99*OVERSAMPLENR, 220}, + {107*OVERSAMPLENR, 215}, + {116*OVERSAMPLENR, 210}, + {126*OVERSAMPLENR, 205}, + {136*OVERSAMPLENR, 200}, + {149*OVERSAMPLENR, 195}, + {160*OVERSAMPLENR, 190}, + {175*OVERSAMPLENR, 185}, + {191*OVERSAMPLENR, 180}, + {209*OVERSAMPLENR, 175}, + {224*OVERSAMPLENR, 170}, + {246*OVERSAMPLENR, 165}, + {267*OVERSAMPLENR, 160}, + {293*OVERSAMPLENR, 155}, + {316*OVERSAMPLENR, 150}, + {340*OVERSAMPLENR, 145}, + {364*OVERSAMPLENR, 140}, + {396*OVERSAMPLENR, 135}, + {425*OVERSAMPLENR, 130}, + {460*OVERSAMPLENR, 125}, + {489*OVERSAMPLENR, 120}, + {526*OVERSAMPLENR, 115}, + {558*OVERSAMPLENR, 110}, + {591*OVERSAMPLENR, 105}, + {628*OVERSAMPLENR, 100}, + {660*OVERSAMPLENR, 95}, + {696*OVERSAMPLENR, 90}, + {733*OVERSAMPLENR, 85}, + {761*OVERSAMPLENR, 80}, + {794*OVERSAMPLENR, 75}, + {819*OVERSAMPLENR, 70}, + {847*OVERSAMPLENR, 65}, + {870*OVERSAMPLENR, 60}, + {892*OVERSAMPLENR, 55}, + {911*OVERSAMPLENR, 50}, + {929*OVERSAMPLENR, 45}, + {944*OVERSAMPLENR, 40}, + {959*OVERSAMPLENR, 35}, + {971*OVERSAMPLENR, 30}, + {981*OVERSAMPLENR, 25}, + {989*OVERSAMPLENR, 20}, + {994*OVERSAMPLENR, 15}, + {1001*OVERSAMPLENR, 10}, + {1005*OVERSAMPLENR, 5} +}; #endif + +#if THERMISTORHEATER_1 == 1 +#define NUMTEMPS_HEATER_1 NUMTEMPS_1 +#define temptable_1 temptable_1 +#elif THERMISTORHEATER_1 == 2 +#define NUMTEMPS_HEATER_1 NUMTEMPS_2 +#define temptable_1 temptable_2 +#elif THERMISTORHEATER_1 == 3 +#define NUMTEMPS_HEATER_1 NUMTEMPS_3 +#define temptable_1 temptable_3 +#elif THERMISTORHEATER_1 == 4 +#define NUMTEMPS_HEATER_1 NUMTEMPS_4 +#define temptable_1 temptable_4 +#elif THERMISTORHEATER_1 == 5 +#define NUMTEMPS_HEATER_1 NUMTEMPS_5 +#define temptable_1 temptable_5 +#elif THERMISTORHEATER_1 == 6 +#define NUMTEMPS_HEATER_1 NUMTEMPS_6 +#define temptable_1 temptable_6 +#elif THERMISTORHEATER_1 == 7 +#define NUMTEMPS_HEATER_1 NUMTEMPS_7 +#define temptable_1 temptable_7 +#elif defined HEATER_1_USES_THERMISTOR +#error No heater 1 thermistor table specified +#endif + +#if THERMISTORHEATER_2 == 1 +#define NUMTEMPS_HEATER_2 NUMTEMPS_1 +#define temptable_2 temptable_1 +#elif THERMISTORHEATER_2 == 2 +#define NUMTEMPS_HEATER_2 NUMTEMPS_2 +#define temptable_2 temptable_2 +#elif THERMISTORHEATER_2 == 3 +#define NUMTEMPS_HEATER_2 NUMTEMPS_3 +#define temptable_2 temptable_3 +#elif THERMISTORHEATER_2 == 4 +#define NUMTEMPS_HEATER_2 NUMTEMPS_4 +#define temptable_2 temptable_4 +#elif THERMISTORHEATER_2 == 5 +#define NUMTEMPS_HEATER_2 NUMTEMPS_5 +#define temptable_2 temptable_5 +#elif THERMISTORHEATER_2 == 6 +#define NUMTEMPS_HEATER_2 NUMTEMPS_6 +#define temptable_2 temptable_6 +#elif THERMISTORHEATER_2 == 7 +#define NUMTEMPS_HEATER22 NUMTEMPS_7 +#define temptable_2 temptable_7 +#elif defined HEATER_2_USES_THERMISTOR +#error No heater 2 thermistor table specified +#endif + + +#if THERMISTORBED == 1 +#define BNUMTEMPS NUMTEMPS_1 +#define bedtemptable temptable_1 +#elif THERMISTORBED == 2 +#define BNUMTEMPS NUMTEMPS_2 +#define bedtemptable temptable_2 +#elif THERMISTORBED == 3 +#define BNUMTEMPS NUMTEMPS_3 +#define bedtemptable temptable_3 +#elif THERMISTORBED == 4 +#define BNUMTEMPS NUMTEMPS_4 +#define bedtemptable temptable_4 +#elif THERMISTORBED == 5 +#define BNUMTEMPS NUMTEMPS_5 +#define bedtemptable temptable_5 +#elif THERMISTORBED == 6 +#define BNUMTEMPS NUMTEMPS_6 +#define bedtemptable temptable_6 +#elif THERMISTORBED == 7 +#define BNUMTEMPS NUMTEMPS_7 +#define bedtemptable temptable_7 +#elif defined BED_USES_THERMISTOR +#error No bed thermistor table specified +#endif + #endif //THERMISTORTABLES_H_ + From 95d3d9847c4d78c068f622c7d24dc716263d9b73 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 4 Nov 2011 23:38:25 +0100 Subject: [PATCH 003/228] M109 now equal to sprinter --- Marlin/Configuration.h | 7 +++++ Marlin/Marlin.pde | 68 ++++++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 36b5f7b67b..b8c41301c9 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -146,9 +146,16 @@ const int dropsegments=5; //everything with this number of steps will be ignore #define WATCHDOG_TIMEOUT 4 + +//// Experimental watchdog and minimal temp +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 //#define WATCHPERIOD 5000 //5 seconds +// Actual temperature must be close to target for this long before M109 returns success +//#define TEMP_RESIDENCY_TIME 20 // (seconds) +//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one + //// The minimal temperature defines the temperature below which the heater will not be enabled #define MINTEMP 5 #define BED_MINTEMP 5 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 6922b8a1fe..8c8fe4bc25 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -780,7 +780,7 @@ inline void process_commands() #ifdef WATCHPERIOD if(target_raw[0] > current_raw[0]){ watchmillis = max(1,millis()); - watch_raw[0] = current_raw[0]; + watch_raw = current_raw[0]; }else{ watchmillis = 0; } @@ -820,32 +820,54 @@ inline void process_commands() #endif return; //break; - case 109: // M109 - Wait for extruder heater to reach target. - LCD_MESSAGE("Heating..."); - if (code_seen('S')) target_raw[0] = temp2analog(code_value()); -#ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[0]>current_raw[0]){ + case 109: {// M109 - Wait for extruder heater to reach target. + LCD_MESSAGE("Heating..."); + if (code_seen('S')) target_raw[0] = temp2analog(code_value()); + #ifdef PIDTEMP + pid_setpoint = code_value(); + #endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[0]>current_raw[0]) { watchmillis = max(1,millis()); - watch_raw[0] = current_raw[0]; - }else{ + watch_raw = current_raw[0]; + } else { watchmillis = 0; - } - #endif - codenum = millis(); - starttime=millis(); - while(current_raw[0] < target_raw[0]) { - if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up. - Serial.print("T:"); - Serial.println( analog2temp(current_raw[0]) ); - codenum = millis(); } - LCD_STATUS; - manage_heater(); + #endif //WATCHPERIOD + codenum = millis(); + + /* See if we are heating up or cooling down */ + bool target_direction = (current_raw[0] < target_raw[0]); // 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((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + #else + while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { + #endif //TEMP_RESIDENCY_TIME + if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down + Serial.print("T:"); + Serial.println( analog2temp(current_raw[0]) ); + codenum = millis(); + } + manage_heater(); + 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 && current_raw[0] >= target_raw[0]) || + (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || + (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGE("Marlin ready."); } - LCD_MESSAGE("UltiMarlin ready."); break; case 190: // M190 - Wait bed for heater to reach target. #if TEMP_1_PIN > -1 From d7c4f0780b41507ae6a40cc46efb59c526e58437 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 5 Nov 2011 11:18:52 +0100 Subject: [PATCH 004/228] Added M42, M80 and M81 --- Marlin/Marlin.pde | 38 +++++++++++++++++++++++++++++++++++++- Marlin/pins.h | 4 ++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 8c8fe4bc25..cb55131df3 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -69,7 +69,6 @@ char version_string[] = "1.0.0 Alpha 1"; // M114 - Display current position //Custom M Codes -// M80 - Turn on Power Supply // M20 - List SD card // M21 - Init SD card // M22 - Release SD card @@ -80,6 +79,8 @@ char version_string[] = "1.0.0 Alpha 1"; // M27 - Report SD print status // M28 - Start SD write (M28 filename.g) // M29 - Stop SD write +// 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 @@ -142,6 +143,8 @@ extern float HeaterPower; #include "EEPROM.h" +const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 + float tt = 0, bt = 0; #ifdef WATCHPERIOD int watch_raw = -1000; @@ -772,6 +775,31 @@ inline void process_commands() } break; #endif //SDSUPPORT + 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(int i = 0; i < 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 (code_seen('S')) target_raw[0] = temp2analog(code_value()); #ifdef PIDTEMP @@ -907,6 +935,14 @@ inline void process_commands() WRITE(FAN_PIN,LOW); analogWrite(FAN_PIN, 0); break; +#endif +#if (PS_ON_PIN > -1) + case 80: // M80 - ATX Power On + SET_OUTPUT(PS_ON_PIN); //GND + break; + case 81: // M81 - ATX Power Off + SET_INPUT(PS_ON_PIN); //Floating + break; #endif case 82: axis_relative_modes[3] = false; diff --git a/Marlin/pins.h b/Marlin/pins.h index 795d8bdbb5..1e2fd65fd2 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -563,4 +563,8 @@ #ifndef KNOWN_BOARD #error Unknown MOTHERBOARD value in configuration.h #endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} + #endif From 00674af3a82e6b6b517a12ae3e77803df4f4892d Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 5 Nov 2011 14:13:20 +0100 Subject: [PATCH 005/228] merge from the branch bkubicek/Marlin/zalmmerge --- Marlin/Configuration.h | 463 ++-- Marlin/{EEPROM.h => EEPROMwrite.h} | 252 +-- Marlin/Makefile | 508 +++-- Marlin/Marlin.h | 165 +- Marlin/Marlin.pde | 2466 ++++++++++----------- Marlin/fastio.h | 10 +- Marlin/lcd.h | 10 - Marlin/lcd.pde | 1 - Marlin/planner.cpp | 18 +- Marlin/planner.h | 182 +- Marlin/stepper.cpp | 2 +- Marlin/stepper.h | 84 +- Marlin/temperature.cpp | 29 +- Marlin/temperature.h | 113 +- Marlin/thermistortables.h | 180 +- Marlin/ultralcd.h | 2 +- Marlin/ultralcd.pde | 3186 ++++++++++++++-------------- README | 64 +- README.md | 69 + merging still needs.txt | 58 + 20 files changed, 4030 insertions(+), 3832 deletions(-) rename Marlin/{EEPROM.h => EEPROMwrite.h} (94%) delete mode 100644 Marlin/lcd.h delete mode 100644 Marlin/lcd.pde create mode 100644 README.md create mode 100644 merging still needs.txt diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index b8c41301c9..0df1ba6fe1 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,220 +1,243 @@ -#ifndef CONFIGURATION_H -#define CONFIGURATION_H - -//#define DEBUG_STEPS - -// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration - -//// The following define selects which electronics board you have. Please choose the one that matches your setup -// MEGA/RAMPS up to 1.2 = 3, -// RAMPS 1.3 = 33 -// Gen6 = 5, -// Sanguinololu 1.2 and above = 62 -// Ultimaker = 7, -#define MOTHERBOARD 7 -//#define MOTHERBOARD 5 - - -//// Thermistor settings: -// 1 is 100k thermistor -// 2 is 200k thermistor -// 3 is mendel-parts thermistor -// 4 is 10k thermistor -// 5 is ParCan supplied 104GT-2 100K -// 6 is EPCOS 100k -// 7 is 100k Honeywell thermistor 135-104LAG-J01 -#define THERMISTORHEATER_1 3 -#define THERMISTORHEATER_2 3 -#define THERMISTORBED 3 - -//#define HEATER_1_USES_THERMISTOR -//#define HEATER_2_USES_THERMISTOR -#define HEATER_1_USES_AD595 -//#define HEATER_2_USES_AD595 - -// Select one of these only to define how the bed temp is read. -//#define BED_USES_THERMISTOR -//#define BED_USES_AD595 - -#define HEATER_CHECK_INTERVAL 50 -#define BED_CHECK_INTERVAL 5000 - - -//// Endstop Settings -#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors -// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false - -// This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 -//#define BAUDRATE 230400 - -// Comment out (using // at the start of the line) to disable SD support: - -// #define ULTRA_LCD //any lcd -#define LCD_WIDTH 16 -#define LCD_HEIGHT 2 - -//#define ULTIPANEL -#ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 -#define LCD_HEIGHT 4 -#endif - - -//#define SDSUPPORT // Enable SD Card Support in Hardware Console - - - -const int dropsegments=5; //everything with this number of steps will be ignored as move - -//// ADVANCED SETTINGS - to tweak parameters - -#include "thermistortables.h" - -// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 -#define X_ENABLE_ON 0 -#define Y_ENABLE_ON 0 -#define Z_ENABLE_ON 0 -#define E_ENABLE_ON 0 - -// Disables axis when it's not being used. -#define DISABLE_X false -#define DISABLE_Y false -#define DISABLE_Z false -#define DISABLE_E false - -// Inverting axis direction -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false - -//// ENDSTOP SETTINGS: -// Sets direction of endstops when homing; 1=MAX, -1=MIN -#define X_HOME_DIR -1 -#define Y_HOME_DIR -1 -#define Z_HOME_DIR -1 - -#define min_software_endstops false //If true, axis won't move to coordinates less than zero. -#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 210 -#define Y_MAX_LENGTH 210 -#define Z_MAX_LENGTH 210 - -//// MOVEMENT SETTINGS -#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -//note: on bernhards ultimaker 200 200 12 are working well. -#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds -//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. -//!!!!!!Use only if you know that your printer works at the maximum declared speeds. -// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze -#define TRAVELING_AT_MAXSPEED -#define AXIS_RELATIVE_MODES {false, false, false, false} - -#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) - -// default settings - -#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker -#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} -#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. - -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts - -#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 10 - -// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. -#define DEFAULT_MINSEGMENTTIME 20000 -#define DEFAULT_XYJERK 30.0*60 -#define DEFAULT_ZJERK 10.0*60 - - -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -//this enables the watchdog interrupt. -#define 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: -#define RESET_MANUAL - -#define WATCHDOG_TIMEOUT 4 - - - -//// Experimental watchdog and minimal temp -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 -//#define WATCHPERIOD 5000 //5 seconds - -// Actual temperature must be close to target for this long before M109 returns success -//#define TEMP_RESIDENCY_TIME 20 // (seconds) -//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one - -//// The minimal temperature defines the temperature below which the heater will not be enabled -#define MINTEMP 5 -#define BED_MINTEMP 5 - - -// When temperature exceeds max temp, your heater will be switched off. -// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! -// You should use MINTEMP for thermistor short/failure protection. -#define MAXTEMP 275 -#define BED_MAXTEMP 150 - -/// PID settings: -// Uncomment the following line to enable PID support. -//#define SMOOTHING -//#define SMOOTHFACTOR 5.0 -//float current_raw_average=0; - -#define PIDTEMP -#ifdef PIDTEMP -//#define PID_DEBUG // Sends debug data to the serial port. -//#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % -#define PID_MAX 255 // limits current to nozzle -#define PID_INTEGRAL_DRIVE_MAX 255 -#define PID_dT 0.10 // 100ms sample time -#define DEFAULT_Kp 20.0 -#define DEFAULT_Ki 1.5*PID_dT -#define DEFAULT_Kd 80/PID_dT -#define DEFAULT_Kc 0 -#endif // PIDTEMP - - -// extruder advance constant (s2/mm3) -// -// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 -// -// hooke's law says: force = k * distance -// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant -// so: v ^ 2 is proportional to number of steps we advance the extruder -//#define ADVANCE - -#ifdef ADVANCE -#define EXTRUDER_ADVANCE_K .3 - -#define D_FILAMENT 1.7 -#define STEPS_MM_E 65 -#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) -#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) - -#endif // ADVANCE - -#if defined SDSUPPORT -// The number of linear motions that can be in the plan at any give time. - #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller -#else - #define BLOCK_BUFFER_SIZE 16 // maximize block buffer -#endif - -#ifdef SIMPLE_LCD - #define BLOCK_BUFFER_SIZE 16 // A little less buffer for just a simple LCD -#endif - -#endif +#ifndef CONFIGURATION_H +#define CONFIGURATION_H + +//#define DEBUG_STEPS + +// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration + +//// The following define selects which electronics board you have. Please choose the one that matches your setup +// MEGA/RAMPS up to 1.2 = 3, +// RAMPS 1.3 = 33 +// Gen6 = 5, +// Sanguinololu 1.2 and above = 62 +// Ultimaker = 7, +#define MOTHERBOARD 7 +//#define MOTHERBOARD 5 + + +//// Thermistor settings: +// 1 is 100k thermistor +// 2 is 200k thermistor +// 3 is mendel-parts thermistor +// 4 is 10k thermistor +// 5 is ParCan supplied 104GT-2 100K +// 6 is EPCOS 100k +// 7 is 100k Honeywell thermistor 135-104LAG-J01 +#define THERMISTORHEATER_1 3 +#define THERMISTORHEATER_2 3 +#define THERMISTORBED 3 + +//#define HEATER_1_USES_THERMISTOR +//#define HEATER_2_USES_THERMISTOR +#define HEATER_1_USES_AD595 +//#define HEATER_2_USES_AD595 + +// Select one of these only to define how the bed temp is read. +//#define BED_USES_THERMISTOR +//#define BED_USES_AD595 + +#define HEATER_CHECK_INTERVAL 50 +#define BED_CHECK_INTERVAL 5000 + + +//// Endstop Settings +#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors +// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. +const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false + +// This determines the communication speed of the printer +//#define BAUDRATE 250000 +#define BAUDRATE 115200 +//#define BAUDRATE 230400 + +// Comment out (using // at the start of the line) to disable SD support: + +// #define ULTRA_LCD //any lcd + + +#define ULTIPANEL +#ifdef ULTIPANEL + //#define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 +#define LCD_HEIGHT 4 +#else //no panel but just lcd + #ifdef ULTRA_LCD + #define LCD_WIDTH 16 + #define LCD_HEIGHT 2 + #endif +#endif + + +//#define SDSUPPORT // Enable SD Card Support in Hardware Console + + + +const int dropsegments=5; //everything with this number of steps will be ignored as move + +//// ADVANCED SETTINGS - to tweak parameters + +#include "thermistortables.h" + +// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 +#define X_ENABLE_ON 0 +#define Y_ENABLE_ON 0 +#define Z_ENABLE_ON 0 +#define E_ENABLE_ON 0 + +// Disables axis when it's not being used. +#define DISABLE_X false +#define DISABLE_Y false +#define DISABLE_Z false +#define DISABLE_E false + +// Inverting axis direction +#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false +#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false + +//// ENDSTOP SETTINGS: +// Sets direction of endstops when homing; 1=MAX, -1=MIN +#define X_HOME_DIR -1 +#define Y_HOME_DIR -1 +#define Z_HOME_DIR -1 + +#define min_software_endstops false //If true, axis won't move to coordinates less than zero. +#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. +#define X_MAX_LENGTH 210 +#define Y_MAX_LENGTH 210 +#define Z_MAX_LENGTH 210 + +//// MOVEMENT SETTINGS +#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E +//note: on bernhards ultimaker 200 200 12 are working well. +#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds +//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. +//!!!!!!Use only if you know that your printer works at the maximum declared speeds. +// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze +#define TRAVELING_AT_MAXSPEED +#define AXIS_RELATIVE_MODES {false, false, false, false} + +#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker +#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} +#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts + +#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 10 + +// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. +#define DEFAULT_MINSEGMENTTIME 20000 +#define DEFAULT_XYJERK 30.0*60 +#define DEFAULT_ZJERK 10.0*60 + + +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +//this enables the watchdog interrupt. +#define 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: +#define RESET_MANUAL + +#define WATCHDOG_TIMEOUT 4 + + + +//// Experimental watchdog and minimal temp +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 +//#define WATCHPERIOD 5000 //5 seconds + +// Actual temperature must be close to target for this long before M109 returns success +//#define TEMP_RESIDENCY_TIME 20 // (seconds) +//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one + +//// The minimal temperature defines the temperature below which the heater will not be enabled +#define MINTEMP 5 +#define BED_MINTEMP 5 + + +// When temperature exceeds max temp, your heater will be switched off. +// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! +// You should use MINTEMP for thermistor short/failure protection. +#define MAXTEMP 275 +#define BED_MAXTEMP 150 + + + + + + + +#define PIDTEMP +#ifdef PIDTEMP + /// PID settings: + // Uncomment the following line to enable PID support. + //#define SMOOTHING + //#define SMOOTHFACTOR 5.0 + //float current_raw_average=0; + #define K1 0.95 //smoothing of the PID + //#define PID_DEBUG // Sends debug data to the serial port. + //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % + #define PID_MAX 255 // limits current to nozzle + #define PID_INTEGRAL_DRIVE_MAX 255 + #define PID_dT 0.1 + //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 + + #define PID_CRITIAL_GAIN 3000 + #define PID_SWING_AT_CRITIAL 45 //seconds + #define PIDIADD 5 + /* + //PID according to Ziegler-Nichols method + float Kp = 0.6*PID_CRITIAL_GAIN; + float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; + float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; + */ + //PI according to Ziegler-Nichols method + #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) + #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (0) + + #define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) + #endif +#endif // PIDTEMP + +// extruder advance constant (s2/mm3) +// +// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 +// +// hooke's law says: force = k * distance +// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant +// so: v ^ 2 is proportional to number of steps we advance the extruder +//#define ADVANCE + +#ifdef ADVANCE +#define EXTRUDER_ADVANCE_K .3 + +#define D_FILAMENT 1.7 +#define STEPS_MM_E 65 +#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) +#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) + +#endif // ADVANCE + +// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 +#if defined SDSUPPORT +// The number of linear motions that can be in the plan at any give time. + #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller +#else + #define BLOCK_BUFFER_SIZE 16 // maximize block buffer +#endif + + +#endif diff --git a/Marlin/EEPROM.h b/Marlin/EEPROMwrite.h similarity index 94% rename from Marlin/EEPROM.h rename to Marlin/EEPROMwrite.h index 0390d94e46..2247e2f52d 100644 --- a/Marlin/EEPROM.h +++ b/Marlin/EEPROMwrite.h @@ -1,123 +1,129 @@ - -#include "planner.h" -#include "temperature.h" - -//====================================================================================== -template int EEPROM_writeAnything(int &ee, const T& value) -{ - const byte* p = (const byte*)(const void*)&value; - int i; - for (i = 0; i < sizeof(value); i++) - EEPROM.write(ee++, *p++); - return i; -} -//====================================================================================== -template int EEPROM_readAnything(int &ee, T& value) -{ - byte* p = (byte*)(void*)&value; - int i; - for (i = 0; i < sizeof(value); i++) - *p++ = EEPROM.read(ee++); - return i; -} -//====================================================================================== - -#define EEPROM_OFFSET 100 - -#define EEPROM_VERSION "V04" // IMPORTANT: Whenever there are changes made to the variables stored in EEPROM - // in the functions below, also increment the version number. This makes sure that - // the default values are used whenever there is a change to the data, to prevent - // wrong data being written to the variables. - // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. -void StoreSettings() { - char ver[4]= "000"; - int i=EEPROM_OFFSET; - EEPROM_writeAnything(i,ver); // invalidate data first - EEPROM_writeAnything(i,axis_steps_per_unit); - EEPROM_writeAnything(i,max_feedrate); - EEPROM_writeAnything(i,max_acceleration_units_per_sq_second); - EEPROM_writeAnything(i,acceleration); - EEPROM_writeAnything(i,retract_acceleration); - EEPROM_writeAnything(i,minimumfeedrate); - EEPROM_writeAnything(i,mintravelfeedrate); - EEPROM_writeAnything(i,minsegmenttime); - EEPROM_writeAnything(i,max_xy_jerk); - EEPROM_writeAnything(i,max_z_jerk); - #ifdef PIDTEMP - EEPROM_writeAnything(i,Kp); - EEPROM_writeAnything(i,Ki); - EEPROM_writeAnything(i,Kd); -#else - EEPROM_writeAnything(i,3000); - EEPROM_writeAnything(i,0); - EEPROM_writeAnything(i,0); -#endif - char ver2[4]=EEPROM_VERSION; - i=EEPROM_OFFSET; - EEPROM_writeAnything(i,ver2); // validate data - ECHOLN("Settings Stored"); - -} - -void RetrieveSettings(bool def=false){ // if def=true, the default values will be used - int i=EEPROM_OFFSET; - char stored_ver[4]; - char ver[4]=EEPROM_VERSION; - EEPROM_readAnything(i,stored_ver); //read stored version -// ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); - if ((!def)&&(strncmp(ver,stored_ver,3)==0)) { // version number match - EEPROM_readAnything(i,axis_steps_per_unit); - EEPROM_readAnything(i,max_feedrate); - EEPROM_readAnything(i,max_acceleration_units_per_sq_second); - EEPROM_readAnything(i,acceleration); - EEPROM_readAnything(i,retract_acceleration); - EEPROM_readAnything(i,minimumfeedrate); - EEPROM_readAnything(i,mintravelfeedrate); - EEPROM_readAnything(i,minsegmenttime); - EEPROM_readAnything(i,max_xy_jerk); - EEPROM_readAnything(i,max_z_jerk); -#ifndef PIDTEMP - float Kp,Ki,Kd; -#endif - EEPROM_readAnything(i,Kp); - EEPROM_readAnything(i,Ki); - EEPROM_readAnything(i,Kd); - - ECHOLN("Stored settings retreived:"); - } - else { - float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; - float tmp2[]=DEFAULT_MAX_FEEDRATE; - long tmp3[]=DEFAULT_MAX_ACCELERATION; - for (int i=0;i<4;i++) { - axis_steps_per_unit[i]=tmp1[i]; - max_feedrate[i]=tmp2[i]; - max_acceleration_units_per_sq_second[i]=tmp3[i]; - } - acceleration=DEFAULT_ACCELERATION; - retract_acceleration=DEFAULT_RETRACT_ACCELERATION; - minimumfeedrate=DEFAULT_MINIMUMFEEDRATE; - minsegmenttime=DEFAULT_MINSEGMENTTIME; - mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; - max_xy_jerk=DEFAULT_XYJERK; - max_z_jerk=DEFAULT_ZJERK; - ECHOLN("Using Default settings:"); - } - ECHOLN("Steps per unit:"); - ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); - ECHOLN("Maximum feedrates (mm/s):"); - ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); - ECHOLN("Maximum Acceleration (mm/s2):"); - ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); - ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); - ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); - ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); - ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); -#ifdef PIDTEMP - ECHOLN("PID settings:"); - ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); -#endif - -} - - +#ifndef __EEPROMH +#define __EEPROMH +#include "planner.h" +#include "temperature.h" +#include +#include "Marlin.h" +#include "streaming.h" + +//====================================================================================== +template int EEPROM_writeAnything(int &ee, const T& value) +{ + const byte* p = (const byte*)(const void*)&value; + int i; + for (i = 0; i < (int)sizeof(value); i++) + EEPROM.write(ee++, *p++); + return i; +} +//====================================================================================== +template int EEPROM_readAnything(int &ee, T& value) +{ + byte* p = (byte*)(void*)&value; + int i; + for (i = 0; i < (int)sizeof(value); i++) + *p++ = EEPROM.read(ee++); + return i; +} +//====================================================================================== + +#define EEPROM_OFFSET 100 + +#define EEPROM_VERSION "V04" // IMPORTANT: Whenever there are changes made to the variables stored in EEPROM + // in the functions below, also increment the version number. This makes sure that + // the default values are used whenever there is a change to the data, to prevent + // wrong data being written to the variables. + // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. +void StoreSettings() { + char ver[4]= "000"; + int i=EEPROM_OFFSET; + EEPROM_writeAnything(i,ver); // invalidate data first + EEPROM_writeAnything(i,axis_steps_per_unit); + EEPROM_writeAnything(i,max_feedrate); + EEPROM_writeAnything(i,max_acceleration_units_per_sq_second); + EEPROM_writeAnything(i,acceleration); + EEPROM_writeAnything(i,retract_acceleration); + EEPROM_writeAnything(i,minimumfeedrate); + EEPROM_writeAnything(i,mintravelfeedrate); + EEPROM_writeAnything(i,minsegmenttime); + EEPROM_writeAnything(i,max_xy_jerk); + EEPROM_writeAnything(i,max_z_jerk); + #ifdef PIDTEMP + EEPROM_writeAnything(i,Kp); + EEPROM_writeAnything(i,Ki); + EEPROM_writeAnything(i,Kd); +#else + EEPROM_writeAnything(i,3000); + EEPROM_writeAnything(i,0); + EEPROM_writeAnything(i,0); +#endif + char ver2[4]=EEPROM_VERSION; + i=EEPROM_OFFSET; + EEPROM_writeAnything(i,ver2); // validate data + ECHOLN("Settings Stored"); + +} + +void RetrieveSettings(bool def=false){ // if def=true, the default values will be used + int i=EEPROM_OFFSET; + char stored_ver[4]; + char ver[4]=EEPROM_VERSION; + EEPROM_readAnything(i,stored_ver); //read stored version +// ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); + if ((!def)&&(strncmp(ver,stored_ver,3)==0)) { // version number match + EEPROM_readAnything(i,axis_steps_per_unit); + EEPROM_readAnything(i,max_feedrate); + EEPROM_readAnything(i,max_acceleration_units_per_sq_second); + EEPROM_readAnything(i,acceleration); + EEPROM_readAnything(i,retract_acceleration); + EEPROM_readAnything(i,minimumfeedrate); + EEPROM_readAnything(i,mintravelfeedrate); + EEPROM_readAnything(i,minsegmenttime); + EEPROM_readAnything(i,max_xy_jerk); + EEPROM_readAnything(i,max_z_jerk); +#ifndef PIDTEMP + float Kp,Ki,Kd; +#endif + EEPROM_readAnything(i,Kp); + EEPROM_readAnything(i,Ki); + EEPROM_readAnything(i,Kd); + + ECHOLN("Stored settings retreived:"); + } + else { + float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; + float tmp2[]=DEFAULT_MAX_FEEDRATE; + long tmp3[]=DEFAULT_MAX_ACCELERATION; + for (int i=0;i<4;i++) { + axis_steps_per_unit[i]=tmp1[i]; + max_feedrate[i]=tmp2[i]; + max_acceleration_units_per_sq_second[i]=tmp3[i]; + } + acceleration=DEFAULT_ACCELERATION; + retract_acceleration=DEFAULT_RETRACT_ACCELERATION; + minimumfeedrate=DEFAULT_MINIMUMFEEDRATE; + minsegmenttime=DEFAULT_MINSEGMENTTIME; + mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; + max_xy_jerk=DEFAULT_XYJERK; + max_z_jerk=DEFAULT_ZJERK; + ECHOLN("Using Default settings:"); + } + ECHOLN("Steps per unit:"); + ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); + ECHOLN("Maximum feedrates (mm/s):"); + ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); + ECHOLN("Maximum Acceleration (mm/s2):"); + ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); + ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); + ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); + ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); + ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); +#ifdef PIDTEMP + ECHOLN("PID settings:"); + ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); +#endif + +} + +#endif + + diff --git a/Marlin/Makefile b/Marlin/Makefile index 6fafba13b0..f456e3cbd4 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -1,274 +1,320 @@ +TARGET = $(notdir $(CURDIR)) +# CHANGE BELOW: +#~ INSTALL_DIR = /Applications/Arduino.app/Contents/Resources/Java +INSTALL_DIR = /home/bkubicek/software/arduino-0022 +#~ PORT = /dev/cu.usbserial* +PORT = /dev/ttyACM0 + +# Get these values from: +# $(INSTALL_DIR)/hardware/boards.txt +# (arduino-0022/hardware/arduino/boards.txt) +# The values below are for the "Arduino Duemilanove or Nano w/ ATmega328" +# now for "Arduino Mega 2560" +UPLOAD_SPEED = 115200 +UPLOAD_PROTOCOL = stk500v2 +BUILD_MCU = atmega2560 +BUILD_F_CPU = 16000000L + +# getting undefined reference to `__cxa_pure_virtual' +#~ [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254180518 Arduino Forum - Makefile] +#~ http://www.arduino.cc/playground/OpenBSD/CLI +#~ [http://arduino.cc/forum/index.php?topic=52041.0 A "simple" makefile for Arduino] +#~ [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1275488191 Arduino Forum - Configuring avr-gcc options in arduino IDE] +# found in /usr/lib/gcc/avr/4.3.5/cc1plus; fixed with -Wl,--gc-section + +############################################################################ +# Below here nothing should be changed... + +ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino # -# Arduino 0022 Makefile -# Uno with DOGS102 Shield -# -# written by olikraus@gmail.com -# -# Features: -# - boards.txt is used to derive parameters -# - All intermediate files are put into a separate directory (TMPDIRNAME) -# - Simple use: Copy Makefile into the same directory of the .pde file -# -# Limitations: -# - requires UNIX environment -# - TMPDIRNAME must be subdirectory of the current directory. -# -# Targets -# all build everything -# upload build and upload to arduino -# clean remove all temporary files (includes final hex file) -# -# History -# 001 28 Apr 2010 first release -# 002 05 Oct 2010 added 'uno' +#~ AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin +# in Ubuntu, avr-gcc is installed separate; +# only avrdude comes with the IDE +AVR_TOOLS_PATH = /usr/bin +AVR_DUDE_PATH = $(INSTALL_DIR)/hardware/tools # +SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ + $(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ + $(ARDUINO)/wiring_pulse.c \ + $(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c +# added applet/$(TARGET).cpp as in IDE 0022 +CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp \ + $(ARDUINO)/Print.cpp \ + $(ARDUINO)/main.cpp +# applet/$(TARGET).cpp # no need, having a rule now for applet/$(TARGET).cpp.o +# added main.cpp, as in 0022 +FORMAT = ihex -#=== user configuration === -# All ...PATH variables must have a '/' at the end +# Name of this Makefile (used for "make depend"). +MAKEFILE = Makefile -# Board (and prozessor) information: see $(ARDUINO_PATH)hardware/arduino/boards.txt -# Some examples: -# BOARD DESCRIPTION -# uno Arduino Uno -# atmega328 Arduino Duemilanove or Nano w/ ATmega328 -# diecimila Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 -# mega Arduino Mega -# mini Arduino Mini -# lilypad328 LilyPad Arduino w/ ATmega328 -BOARD:=mega +# Debugging format. +# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. +# AVR (extended) COFF requires stabs, plus an avr-objcopy run. +DEBUG = stabs -# additional (comma separated) defines -# -DDOGM128_HW board is connected to DOGM128 display -# -DDOGM132_HW board is connected to DOGM132 display -# -DDOGS102_HW board is connected to DOGS102 display -# -DDOG_REVERSE 180 degree rotation -# -DDOG_SPI_SW_ARDUINO force SW shiftOut -DEFS=-DDOGS102_HW -DDOG_DOUBLE_MEMORY -DDOG_SPI_SW_ARDUINO +OPT = 2 -# The location where the avr tools (e.g. avr-gcc) are located. Requires a '/' at the end. -# Can be empty if all tools are accessable through the search path -AVR_TOOLS_PATH:=/usr/bin/ +# Place -D or -U options here +#~ CDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) +#~ CXXDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) +# now called DF_CPU +CDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=22 +CXXDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=22 -# Install path of the arduino software. Requires a '/' at the end. -ARDUINO_PATH:=/home/bkubicek/software/arduino-0022/ +# Place -I options here +CINCS = -I$(ARDUINO) -I$(INSTALL_DIR)/libraries/LiquidCrystal/ -I$(INSTALL_DIR)/libraries/EEPROM/ +CXXINCS = -I$(ARDUINO) -# Install path for avrdude. Requires a '/' at the end. Can be empty if avrdude is in the search path. -AVRDUDE_PATH:= +# Compiler flag to set the C Standard level. +# c89 - "ANSI" C +# gnu89 - c89 plus GCC extensions +# c99 - ISO C99 standard (not yet fully implemented) +# gnu99 - c99 plus GCC extensions +CSTANDARD = -std=gnu99 +CDEBUG = -g$(DEBUG) +# note that typically, IDE 0022 uses -w to suppress warnings (both in cpp and c)! +CWARN = -Wall +#~ CWARN = -w +# "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++: +CCWARN = -Wstrict-prototypes +CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +#CEXTRA = -Wa,-adhlns=$(<:.c=.lst) -# The unix device where we can reach the arduino board -# Uno: /dev/ttyACM0 -# Duemilanove: /dev/ttyUSB0 -AVRDUDE_PORT:=/dev/ttyACM0 +# to eliminate pins_ardiuno warnings: +# http://arduino.cc/pipermail/developers_arduino.cc/2010-December/004005.html -# List of all libaries which should be included. -#EXTRA_DIRS=$(ARDUINO_PATH)libraries/LiquidCrystal/ -#EXTRA_DIRS+=$(ARDUINO_PATH)libraries/Dogm/ -#EXTRA_DIRS+=/home/kraus/src/arduino/dogm128/hg/libraries/Dogm/ +# [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254180518 Arduino Forum - Makefile] +#~ For building the objects files "-ffunction-sections -fdata-sections" was missing +#~ and the final avr-gcc call needs "-Wl,--gc-section". +CXSECTF = -fno-exceptions -ffunction-sections -fdata-sections +CFINALF = -Wl,--gc-section -#=== fetch parameter from boards.txt processor parameter === -# the basic idea is to get most of the information from boards.txt +CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CCWARN) $(CSTANDARD) $(CEXTRA) +# added CWARN also to .cpp +CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CXSECTF) +#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs +LDFLAGS = -lm -BOARDS_TXT:=$(ARDUINO_PATH)hardware/arduino/boards.txt +# Programming support using avrdude. Settings and variables. +AVRDUDE_PORT = $(PORT) +AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex +AVRDUDE_FLAGS = -V -F \ + -p $(BUILD_MCU) -P $(AVRDUDE_PORT) -c $(UPLOAD_PROTOCOL) \ + -b $(UPLOAD_SPEED) -C $(INSTALL_DIR)/hardware/tools/avrdude.conf +# -b $(UPLOAD_SPEED) -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf -# get the MCU value from the $(BOARD).build.mcu variable. For the atmega328 board this is atmega328p -MCU:=$(shell sed -n -e "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_TXT)) -# get the F_CPU value from the $(BOARD).build.f_cpu variable. For the atmega328 board this is 16000000 -F_CPU:=$(shell sed -n -e "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_TXT)) +# Program settings +CC = $(AVR_TOOLS_PATH)/avr-gcc +CXX = $(AVR_TOOLS_PATH)/avr-g++ +OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy +OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump +AR = $(AVR_TOOLS_PATH)/avr-ar +SIZE = $(AVR_TOOLS_PATH)/avr-size +NM = $(AVR_TOOLS_PATH)/avr-nm +#~ AVRDUDE = $(AVR_TOOLS_PATH)/avrdude +AVRDUDE = $(AVR_DUDE_PATH)/avrdude +REMOVE = rm -f +MV = mv -f -# avrdude -# get the AVRDUDE_UPLOAD_RATE value from the $(BOARD).upload.speed variable. For the atmega328 board this is 57600 -AVRDUDE_UPLOAD_RATE:=$(shell sed -n -e "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_TXT)) -# get the AVRDUDE_PROGRAMMER value from the $(BOARD).upload.protocol variable. For the atmega328 board this is stk500 -# AVRDUDE_PROGRAMMER:=$(shell sed -n -e "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_TXT)) -# use stk500v1, because stk500 will default to stk500v2 -AVRDUDE_PROGRAMMER:=stk500v1 +# Define all object files. +# NOTE: obj files will be created in respective src directories (libraries or $(INSTALL_DIR)); +# make clean deletes them fine +# note that srcs are in libraries or other directories; +# $(CXXSRC:.cpp=.o) will cause obj files to be in same loc as src files +#~ OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) +# to change the output directory for object files; +# must change the obj list here! +# and then, match to corresponding rule somehow? +# or leave this - and parse in rule (auth automatic variable $(@F))? +# "Suffix Replacement" +OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) -#=== identify user files === -PDESRC:=$(shell ls *.pde) -TARGETNAME=$(basename $(PDESRC)) +# added - OBJ list, transformed into applet/ +OBJT = $(addprefix applet/,$(notdir $(OBJ))) +ALLSRC = $(SRC) $(CXXSRC) $(ASRC) -CDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) -CDIRS:=*.c utility/*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c -CSRC:=$(shell ls $(CDIRS) 2>/dev/null) +# Define all listing files. +LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst) -CCSRC:=$(shell ls *.cc 2>/dev/null) +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(BUILD_MCU) -I. $(CFLAGS) +ALL_CXXFLAGS = -mmcu=$(BUILD_MCU) -I. $(CXXFLAGS) +ALL_ASFLAGS = -mmcu=$(BUILD_MCU) -I. -x assembler-with-cpp $(ASFLAGS) -CPPDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) -CPPDIRS:=*.cpp utility/*.cpp $(addsuffix *.cpp,$(CPPDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.cpp -CPPSRC:=$(shell ls $(CPPDIRS) 2>/dev/null) +# depended libraries of .pde need to be added from +# $(INSTALL_DIR)/libraries (TODO: and/or ~/sketchbook/libraries) +# grep for 'include', test if exists, add... +# note: prefix "a real tab character" http://www.delorie.com/djgpp/doc/ug/larger/makefiles.html +# $$ to escape $ for shell; +# note: must NOT put comments # inside bash execution; +# those would get removed by make; making shell see "EOF in backquote substitution" +# echo $$ix ; \ +# 'shell' twice - for each subprocess! Backtick doesn't get expanded? +GREPRES:=$(shell for ix in $(shell grep include $(TARGET).pde | sed 's/.*[<"]\(.*\).h[>"].*/\1/'); do \ + if [ -d $(INSTALL_DIR)/libraries/$$ix ] ; then \ + LINCS="$$LINCS -I$(INSTALL_DIR)/libraries/$$ix" ;\ + fi; \ + done; \ + echo $$LINCS) +# append includes: +CINCS += $(GREPRES) +CXXINCS += $(GREPRES) +# append library source .cpp files too (CXXSRC) +GREPRESB:=$(shell for ix in $(shell grep include $(TARGET).pde | sed 's/.*[<"]\(.*\).h[>"].*/\1/'); do \ + if [ -d $(INSTALL_DIR)/libraries/$$ix ] ; then \ + CPPSRCS="$$CPPSRCS $(INSTALL_DIR)/libraries/$$ix/*.cpp" ;\ + fi; \ + done; \ + echo $$CPPSRCS) +CXXSRC += $(GREPRESB) +# added - only CXX obj from libraries: +CXXLIBOBJ = $(GREPRESB:.cpp=.o) -#=== build internal variables === +# Default target. +all: applet_files build sizeafter -# the name of the subdirectory where everything is stored -TMPDIRNAME:=tmp -TMPDIRPATH:=$(TMPDIRNAME)/ +build: elf hex -AVRTOOLSPATH:=$(AVR_TOOLS_PATH) - -OBJCOPY:=$(AVRTOOLSPATH)avr-objcopy -OBJDUMP:=$(AVRTOOLSPATH)avr-objdump -SIZE:=$(AVRTOOLSPATH)avr-size - -CPPSRC:=$(addprefix $(TMPDIRPATH),$(PDESRC:.pde=.cpp)) $(CPPSRC) - -COBJ:=$(CSRC:.c=.o) -CCOBJ:=$(CCSRC:.cc=.o) -CPPOBJ:=$(CPPSRC:.cpp=.o) - -OBJFILES:=$(COBJ) $(CCOBJ) $(CPPOBJ) -DIRS:= $(dir $(OBJFILES)) - -DEPFILES:=$(OBJFILES:.o=.d) -# assembler files from avr-gcc -S -ASSFILES:=$(OBJFILES:.o=.s) -# disassembled object files with avr-objdump -S -DISFILES:=$(OBJFILES:.o=.dis) +applet_files: $(TARGET).pde + # Here is the "preprocessing". + # It creates a .cpp file based with the same name as the .pde file. + # On top of the new .cpp file comes the WProgram.h header. + # At the end there is a generic main() function attached. + # Then the .cpp file will be compiled. Errors during compile will + # refer to this new, automatically generated, file. + # Not the original .pde file you actually edit... + test -d applet || mkdir applet + # @ supresses printout of the cmdline itself; so only the out of echo is printed + @echo ALL OBJT: $(OBJT) + @echo ALL CXXLIBOBJ: $(CXXLIBOBJ) +# echo '#include "WProgram.h"' > applet/$(TARGET).cpp + @echo "#include \"WProgram.h\"\nvoid setup();\nvoid loop();\n" > applet/$(TARGET).cpp + cat $(TARGET).pde >> applet/$(TARGET).cpp + # no more need to cat main.cpp (v0022) - now it is compiled in +# cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp -LIBNAME:=$(TMPDIRPATH)$(TARGETNAME).a -ELFNAME:=$(TMPDIRPATH)$(TARGETNAME).elf -HEXNAME:=$(TMPDIRPATH)$(TARGETNAME).hex +elf: applet/$(TARGET).elf +hex: applet/$(TARGET).hex +eep: applet/$(TARGET).eep +lss: applet/$(TARGET).lss +sym: applet/$(TARGET).sym -AVRDUDE_FLAGS = -V -F -AVRDUDE_FLAGS += -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf -AVRDUDE_FLAGS += -p $(MCU) -AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) -AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) -AVRDUDE_FLAGS += -b $(AVRDUDE_UPLOAD_RATE) -AVRDUDE_FLAGS += -U flash:w:$(HEXNAME) +# Program the device. +upload: applet/$(TARGET).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) -AVRDUDE = avrdude +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex +ELFSIZE = $(SIZE) applet/$(TARGET).elf +sizebefore: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi -#=== predefined variable override === -# use "make -p -f/dev/null" to see the default rules and definitions +sizeafter: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi -# Build C and C++ flags. Include path information must be placed here -COMMON_FLAGS = -DF_CPU=$(F_CPU) -mmcu=$(MCU) $(DEFS) -# COMMON_FLAGS += -gdwarf-2 -COMMON_FLAGS += -Os -COMMON_FLAGS += -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -COMMON_FLAGS += -I. -COMMON_FLAGS += -I$(ARDUINO_PATH)hardware/arduino/cores/arduino -COMMON_FLAGS += $(addprefix -I,$(EXTRA_DIRS)) -COMMON_FLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -COMMON_FLAGS += -Wl,--relax -COMMON_FLAGS += -mcall-prologues +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ + --change-section-address .data-0x800000 \ + --change-section-address .bss-0x800000 \ + --change-section-address .noinit-0x800000 \ + --change-section-address .eeprom-0x810000 -CFLAGS = $(COMMON_FLAGS) -std=gnu99 -Wstrict-prototypes -CXXFLAGS = $(COMMON_FLAGS) +coff: applet/$(TARGET).elf + $(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof -# Replace standard build tools by avr tools -CC = $(AVRTOOLSPATH)avr-gcc -CXX = $(AVRTOOLSPATH)avr-g++ -AR = @$(AVRTOOLSPATH)avr-ar +extcoff: $(TARGET).elf + $(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof - -# "rm" must be able to delete a directory tree -RM = rm -rf - -#=== rules === - -# add rules for the C/C++ files where the .o file is placed in the TMPDIRPATH -# reuse existing variables as far as possible - -$(TMPDIRPATH)%.o: %.c - @echo compile $< - @$(COMPILE.c) $(OUTPUT_OPTION) $< - -$(TMPDIRPATH)%.o: %.cc - @echo compile $< - @$(COMPILE.cc) $(OUTPUT_OPTION) $< - -$(TMPDIRPATH)%.o: %.cpp - @echo compile $< - @$(COMPILE.cpp) $(OUTPUT_OPTION) $< - -$(TMPDIRPATH)%.s: %.c - @$(COMPILE.c) $(OUTPUT_OPTION) -S $< - -$(TMPDIRPATH)%.s: %.cc - @$(COMPILE.cc) $(OUTPUT_OPTION) -S $< - -$(TMPDIRPATH)%.s: %.cpp - @$(COMPILE.cpp) $(OUTPUT_OPTION) -S $< - -$(TMPDIRPATH)%.dis: $(TMPDIRPATH)%.o - @$(OBJDUMP) -S $< > $@ - -.SUFFIXES: .elf .hex .pde +.SUFFIXES: .elf .hex .eep .lss .sym .elf.hex: - @$(OBJCOPY) -O ihex -R .eeprom $< $@ - -$(TMPDIRPATH)%.cpp: %.pde - @cat $(ARDUINO_PATH)hardware/arduino/cores/arduino/main.cpp > $@ - @cat $< >> $@ - @echo >> $@ - @echo 'extern "C" void __cxa_pure_virtual() { while (1); }' >> $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ +.elf.eep: + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ -.PHONY: all -all: tmpdir $(HEXNAME) assemblersource showsize - ls -al $(HEXNAME) $(ELFNAME) +# Create extended listing file from ELF output file. +.elf.lss: + $(OBJDUMP) -h -S $< > $@ -$(ELFNAME): $(LIBNAME)($(addprefix $(TMPDIRPATH),$(OBJFILES))) - $(LINK.o) $(COMMON_FLAGS) $(LIBNAME) $(LOADLIBES) $(LDLIBS) -o $@ +# Create a symbol table from ELF output file. +.elf.sym: + $(NM) -n $< > $@ -$(LIBNAME)(): $(addprefix $(TMPDIRPATH),$(OBJFILES)) +# Link: create ELF output file from library. +# NOTE: applet/$(TARGET).cpp.o MUST BE BEFORE applet/core.a +# in the dependency list, so its rule runs first! +applet/$(TARGET).elf: $(TARGET).pde applet/$(TARGET).cpp.o applet/core.a +# $(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) +# changed as in IDE v0022: link cpp obj files + @echo $$(tput bold)$$(tput setaf 2) $(CC) $$(tput sgr0) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) + @$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) -#=== create temp directory === -# not really required, because it will be also created during the dependency handling -.PHONY: tmpdir -tmpdir: - @test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH) +# added: cpp.o depends on cpp (and .pde which generates it) +# $< "first item in the dependencies list"; $@ "left side of the :"; $^ "right side of the :" +# http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ +applet/$(TARGET).cpp.o: applet/$(TARGET).cpp + @echo $$(tput bold) $(CXX) $$(tput sgr0) -c $(ALL_CXXFLAGS) $< -o $@ + @$(CXX) -c $(ALL_CXXFLAGS) $< -o $@ -#=== create assembler files for each C/C++ file === -.PHONY: assemblersource -assemblersource: $(addprefix $(TMPDIRPATH),$(ASSFILES)) $(addprefix $(TMPDIRPATH),$(DISFILES)) +#~ applet/core.a: $(OBJ) +#~ @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done +applet/core.a: $(OBJT) + @for i in $(OBJT); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done -#=== show the section sizes of the ELF file === -.PHONY: showsize -showsize: $(ELFNAME) - $(SIZE) $< +# iterate through OBJ to find the original location; then build depending on source extension +# TODO: add handling of assembler files +applet/%.o: + @for iob in $(OBJ); do \ + if [ "`basename $$iob`" = "`basename $@`" ]; then \ + for ios in $(ALLSRC); do \ + if [ "$${iob%%.*}" = "$${ios%%.*}" ]; then \ + case $${ios##*.} in \ + "cpp") \ + echo "$$(tput bold)$$(tput setaf 1) $(CXX) $$(tput sgr0) -c $(ALL_CXXFLAGS) $$ios -o $@"; \ + $(CXX) -c $(ALL_CXXFLAGS) $$ios -o $@;; \ + "c") \ + echo "$$(tput bold)$$(tput setaf 1) $(CC) $$(tput sgr0) -c $(ALL_CFLAGS) $$ios -o $@"; \ + $(CC) -c $(ALL_CFLAGS) $$ios -o $@;; \ + esac; \ + fi; \ + done; \ + fi; \ + done; -#=== clean up target === -# this is simple: the TMPDIRPATH is removed -.PHONY: clean +#~ # Compile: create object files from C++ source files. +#~ .cpp.o: +#~ $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ + +#~ # Compile: create object files from C source files. +#~ .c.o: +#~ $(CC) -c $(ALL_CFLAGS) $< -o $@ + +#~ # Compile: create assembler files from C source files. +#~ .c.s: +#~ $(CC) -S $(ALL_CFLAGS) $< -o $@ + +#~ # Assemble: create object files from assembler source files. +#~ .S.o: +#~ $(CC) -c $(ALL_ASFLAGS) $< -o $@ + +#~ # Automatic dependencies +#~ %.d: %.c +#~ $(CC) -M $(ALL_CFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ + +#~ %.d: %.cpp +#~ $(CXX) -M $(ALL_CXXFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ + +# Target: clean project. clean: - $(RM) $(TMPDIRPATH) - -# Program the device. -# step 1: reset the arduino board with the stty command -# step 2: user avrdude to upload the software -.PHONY: upload -upload: $(HEXNAME) - stty -F $(AVRDUDE_PORT) hupcl - $(AVRDUDE) $(AVRDUDE_FLAGS) - - -# === dependency handling === -# From the gnu make manual (section 4.14, Generating Prerequisites Automatically) -# Additionally (because this will be the first executed rule) TMPDIRPATH is created here. -# Instead of "sed" the "echo" command is used -# cd $(TMPDIRPATH); mkdir -p $(DIRS) 2> /dev/null; cd .. -DEPACTION=test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH);\ -mkdir -p $(addprefix $(TMPDIRPATH),$(DIRS));\ -set -e; echo -n $@ $(dir $@) > $@; $(CC) -MM $(COMMON_FLAGS) $< >> $@ - - -$(TMPDIRPATH)%.d: %.c - @$(DEPACTION) - -$(TMPDIRPATH)%.d: %.cc - @$(DEPACTION) - - -$(TMPDIRPATH)%.d: %.cpp - @$(DEPACTION) - -# Include dependency files. If a .d file is missing, a warning is created and the .d file is created -# This warning is not a problem (gnu make manual, section 3.3 Including Other Makefiles) --include $(addprefix $(TMPDIRPATH),$(DEPFILES)) - + $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ + applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ + $(OBJT) applet/$(TARGET).cpp.o \ + $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) +.PHONY: all build elf hex eep lss sym program coff extcoff clean applet_files sizebefore sizeafter diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index cc43f00b2d..f85dad3576 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -1,83 +1,82 @@ -#ifndef __MARLINH -#define __MARLINH - -// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. -// Licence: GPL -#include -#include "fastio.h" - - -#define ECHO(x) Serial << "echo: " << x; -#define ECHOLN(x) Serial << "echo: "< -1 -#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) -#define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) -#else -#define enable_x() ; -#define disable_x() ; -#endif -#if Y_ENABLE_PIN > -1 -#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) -#define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) -#else -#define enable_y() ; -#define disable_y() ; -#endif -#if Z_ENABLE_PIN > -1 -#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON) -#define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON) -#else -#define enable_z() ; -#define disable_z() ; -#endif - -#if E_ENABLE_PIN > -1 - - #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) - #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) - -#else -#define enable_e() ; -#define disable_e() ; -#endif - -#define X_AXIS 0 -#define Y_AXIS 1 -#define Z_AXIS 2 -#define E_AXIS 3 - -void FlushSerialRequestResend(); -void ClearToSend(); - -void get_coordinates(); -void prepare_move(); -void kill(byte debug); - -//void check_axes_activity(); -//void plan_init(); -//void st_init(); -//void tp_init(); -//void plan_buffer_line(float x, float y, float z, float e, float feed_rate); -//void plan_set_position(float x, float y, float z, float e); -//void st_wake_up(); -//void st_synchronize(); -void enquecommand(const char *cmd); -void wd_reset(); - -#ifndef CRITICAL_SECTION_START -#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); -#define CRITICAL_SECTION_END SREG = _sreg; -#endif //CRITICAL_SECTION_START - -extern float homing_feedrate[]; -extern bool axis_relative_modes[]; - -void manage_inactivity(byte debug); - -#endif +#ifndef __MARLINH +#define __MARLINH + +// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. +// Licence: GPL +#include +#include "fastio.h" + + +#define ECHO(x) Serial << "echo: " << x; +#define ECHOLN(x) Serial << "echo: "< -1 +#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) +#define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) +#else +#define enable_x() ; +#define disable_x() ; +#endif +#if Y_ENABLE_PIN > -1 +#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) +#define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) +#else +#define enable_y() ; +#define disable_y() ; +#endif +#if Z_ENABLE_PIN > -1 +#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON) +#define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON) +#else +#define enable_z() ; +#define disable_z() ; +#endif + +#if E_ENABLE_PIN > -1 + + #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) + #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) + +#else +#define enable_e() ; +#define disable_e() ; +#endif + +#define X_AXIS 0 +#define Y_AXIS 1 +#define Z_AXIS 2 +#define E_AXIS 3 + +void FlushSerialRequestResend(); +void ClearToSend(); + +void get_coordinates(); +void prepare_move(); +void kill(); + +//void check_axes_activity(); +//void plan_init(); +//void st_init(); +//void tp_init(); +//void plan_buffer_line(float x, float y, float z, float e, float feed_rate); +//void plan_set_position(float x, float y, float z, float e); +//void st_wake_up(); +//void st_synchronize(); +void enquecommand(const char *cmd); + + +#ifndef CRITICAL_SECTION_START +#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); +#define CRITICAL_SECTION_END SREG = _sreg; +#endif //CRITICAL_SECTION_START + +extern float homing_feedrate[]; +extern bool axis_relative_modes[]; + +void wd_reset() ; +#endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index cb55131df3..3cf8d3bdf0 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1,1233 +1,1233 @@ -/* - 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 -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "streaming.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" - -#ifdef SIMPLE_LCD - #include "Simplelcd.h" -#endif - -char version_string[] = "1.0.0 Alpha 1"; - -#ifdef SDSUPPORT -#include "SdFat.h" -#endif //SDSUPPORT - - -// 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 -// G4 - Dwell S or P -// G28 - Home all Axis -// G90 - Use Absolute Coordinates -// G91 - Use Relative Coordinates -// G92 - Set current position to cordinates given - -//RepRap M Codes -// 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 -// 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 -// 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 -// M115 - Capabilities string -// 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 -// M220 - set speed factor override percentage S:factor in percent -// M301 - Set PID parameters P I and D -// M500 - stores paramters in EEPROM -// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D -// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. - -//Stepper Movement Variables - -char axis_codes[NUM_AXIS] = { - 'X', 'Y', 'Z', 'E'}; -float destination[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -float current_position[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -bool home_all_axis = true; -float feedrate = 1500.0, next_feedrate, saved_feedrate; -long gcode_N, gcode_LastN; - -float homing_feedrate[] = HOMING_FEEDRATE; -bool axis_relative_modes[] = AXIS_RELATIVE_MODES; - -bool relative_mode = false; //Determines Absolute or Relative Coordinates -bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. - -uint8_t fanpwm=0; - -volatile int feedmultiply=100; //100->1 200->2 -int saved_feedmultiply; -volatile bool feedmultiplychanged=false; -// comm variables -#define MAX_CMD_SIZE 96 -#define BUFSIZE 4 -char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; -bool fromsd[BUFSIZE]; -int bufindr = 0; -int bufindw = 0; -int buflen = 0; -int i = 0; -char serial_char; -int serial_count = 0; -boolean comment_mode = false; -char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc -extern float HeaterPower; - -#include "EEPROM.h" - -const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 - -float tt = 0, bt = 0; -#ifdef WATCHPERIOD -int watch_raw = -1000; -unsigned long watchmillis = 0; -#endif //WATCHPERIOD - -//Inactivity shutdown variables -unsigned long previous_millis_cmd = 0; -unsigned long max_inactive_time = 0; -unsigned long stepper_inactive_time = 0; - -unsigned long starttime=0; -unsigned long stoptime=0; -#ifdef SDSUPPORT -Sd2Card card; -SdVolume volume; -SdFile root; -SdFile file; -uint32_t filesize = 0; -uint32_t sdpos = 0; -bool sdmode = false; -bool sdactive = false; -bool savetosd = false; -int16_t n; -long autostart_atmillis=0; - -void initsd(){ - sdactive = false; -#if SDSS >- 1 - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)){ - //if (!card.init(SPI_HALF_SPEED,SDSS)) - Serial.println("SD init fail"); - } - else if (!volume.init(&card)) - Serial.println("volume.init failed"); - else if (!root.openRoot(&volume)) - Serial.println("openRoot failed"); - else - { - sdactive = true; - Serial.println("SD card ok"); - } -#endif //SDSS -} - -void quickinitsd(){ - sdactive=false; - autostart_atmillis=millis()+5000; -} - -inline void write_command(char *buf){ - char* begin = buf; - char* npos = 0; - char* end = buf + strlen(buf) - 1; - - file.writeError = false; - if((npos = strchr(buf, 'N')) != NULL){ - begin = strchr(npos, ' ') + 1; - end = strchr(npos, '*') - 1; - } - end[1] = '\r'; - end[2] = '\n'; - end[3] = '\0'; - //Serial.println(begin); - file.write(begin); - if (file.writeError){ - Serial.println("error writing to file"); - } -} -#endif //SDSUPPORT - - -///adds an command to the main command buffer -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.print("en:");Serial.println(cmdbuffer[bufindw]); - bufindw= (bufindw + 1)%BUFSIZE; - buflen += 1; - } -} - -void setup() -{ - - Serial.begin(BAUDRATE); - ECHOLN("Marlin "< -1 - SET_OUTPUT(SDPOWER); - WRITE(SDPOWER,HIGH); -#endif //SDPOWER - quickinitsd(); - -#endif //SDSUPPORT - plan_init(); // Initialize planner; - st_init(); // Initialize stepper; - tp_init(); // Initialize temperature loop - //checkautostart(); -} - -#ifdef SDSUPPORT -bool autostart_stilltocheck=true; - - -void checkautostart(bool force) -{ - //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) - { - for(int i=0;i 0 && buflen < BUFSIZE) { - serial_char = Serial.read(); - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) - { - if(!serial_count) return; //if empty line - cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ - 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.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); - Serial.println(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.print("Error: checksum mismatch, Last Line:"); - Serial.println(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { - Serial.print("Error: No Checksum with line number, Last Line:"); - Serial.println(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.print("Error: No Line Number with checksum, Last Line:"); - Serial.println(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: -#ifdef SDSUPPORT - if(savetosd) - break; -#endif //SDSUPPORT - Serial.println("ok"); - break; - default: - break; - } - - } - bufindw = (bufindw + 1)%BUFSIZE; - buflen += 1; - - } - 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; - } - } -#ifdef SDSUPPORT - if(!sdmode || serial_count!=0){ - return; - } - while( filesize > sdpos && buflen < BUFSIZE) { - n = file.read(); - serial_char = (char)n; - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) - { - sdpos = file.curPosition(); - if(sdpos >= filesize){ - sdmode = false; - Serial.println("Done printing file"); - 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.println(time); - LCD_MESSAGE(time); - checkautostart(true); - } - if(!serial_count) 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 - -} - - -inline float code_value() { - return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); -} -inline long code_value_long() { - return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); -} -inline bool code_seen(char code_string[]) { - return (strstr(cmdbuffer[bufindr], code_string) != NULL); -} //Return True if the string was found - -inline bool code_seen(char code) -{ - strchr_pointer = strchr(cmdbuffer[bufindr], code); - return (strchr_pointer != NULL); //Return True if a character was found -} - -inline 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 - get_coordinates(); // For X Y Z E F - prepare_move(); - previous_millis_cmd = millis(); - //ClearToSend(); - return; - //break; - case 4: // G4 dwell - codenum = 0; - if(code_seen('P')) codenum = code_value(); // milliseconds to wait - if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait - codenum += millis(); // keep track of when we started waiting - while(millis() < codenum ){ - manage_heater(); - } - break; - case 28: //G28 Home all Axis one at a time - saved_feedrate = feedrate; - saved_feedmultiply = feedmultiply; - feedmultiply = 100; - - for(int 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((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { - if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ -// st_synchronize(); - current_position[X_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; - feedrate = homing_feedrate[X_AXIS]; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = -5 * X_HOME_DIR; - prepare_move(); - -// st_synchronize(); - destination[X_AXIS] = 10 * X_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]/2 ; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = current_position[X_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { - if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ - 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[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]; - prepare_move(); -// st_synchronize(); - - 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[Y_AXIS] = -5 * Y_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Y_AXIS] = 10 * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = current_position[Y_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { - if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = -2 * Z_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Z_AXIS] = 3 * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0.0; - } - } - feedrate = saved_feedrate; - feedmultiply = saved_feedmultiply; - previous_millis_cmd = millis(); - break; - case 90: // G90 - relative_mode = false; - break; - case 91: // G91 - relative_mode = true; - break; - case 92: // G92 - if(!code_seen(axis_codes[E_AXIS])) - st_synchronize(); - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) current_position[i] = code_value(); - } - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - break; - } - } - - else if(code_seen('M')) - { - - switch( (int)code_value() ) - { -#ifdef SDSUPPORT - - case 20: // M20 - list SD card - Serial.println("Begin file list"); - root.ls(); - Serial.println("End file list"); - break; - case 21: // M21 - init SD card - sdmode = false; - initsd(); - break; - case 22: //M22 - release SD card - sdmode = false; - sdactive = false; - break; - case 23: //M23 - Select file - if(sdactive){ - sdmode = false; - file.close(); - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos!=NULL) - *(starpos-1)='\0'; - if (file.open(&root, strchr_pointer + 4, O_READ)) { - Serial.print("File opened:"); - Serial.print(strchr_pointer + 4); - Serial.print(" Size:"); - Serial.println(file.fileSize()); - sdpos = 0; - filesize = file.fileSize(); - Serial.println("File selected"); - } - else{ - Serial.println("file.open failed"); - } - } - break; - case 24: //M24 - Start SD print - if(sdactive){ - sdmode = true; - starttime=millis(); - } - break; - case 25: //M25 - Pause SD print - if(sdmode){ - sdmode = false; - } - break; - case 26: //M26 - Set SD index - if(sdactive && code_seen('S')){ - sdpos = code_value_long(); - file.seekSet(sdpos); - } - break; - case 27: //M27 - Get SD status - if(sdactive){ - Serial.print("SD printing byte "); - Serial.print(sdpos); - Serial.print("/"); - Serial.println(filesize); - } - else{ - Serial.println("Not SD printing"); - } - break; - case 28: //M28 - Start SD write - if(sdactive){ - char* npos = 0; - file.close(); - sdmode = false; - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos != NULL){ - npos = strchr(cmdbuffer[bufindr], 'N'); - strchr_pointer = strchr(npos,' ') + 1; - *(starpos-1) = '\0'; - } - if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) - { - Serial.print("open failed, File: "); - Serial.print(strchr_pointer + 4); - Serial.print("."); - } - else{ - savetosd = true; - Serial.print("Writing to file: "); - Serial.println(strchr_pointer + 4); - } - } - break; - case 29: //M29 - Stop SD write - //processed in write to file routine above - //savetosd = false; - break; - case 30: - { - 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.println(time); - LCD_MESSAGE(time); - } - break; -#endif //SDSUPPORT - 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(int i = 0; i < 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 (code_seen('S')) target_raw[0] = temp2analog(code_value()); -#ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[0] > current_raw[0]){ - watchmillis = max(1,millis()); - watch_raw = current_raw[0]; - }else{ - watchmillis = 0; - } - #endif - break; - case 140: // M140 set bed temp - if (code_seen('S')) target_raw[1] = temp2analogBed(code_value()); - break; - case 105: // M105 - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = analog2temp(current_raw[0]); - #endif - #if TEMP_1_PIN > -1 - bt = analog2tempBed(current_raw[1]); - #endif - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - Serial.print("ok T:"); - Serial.print(tt); -// Serial.print(", raw:"); -// Serial.print(current_raw); - #if TEMP_1_PIN > -1 -#ifdef PIDTEMP - Serial.print(" B:"); - #if TEMP_1_PIN > -1 - Serial.println(bt); - #else - Serial.println(HeaterPower); - #endif -#else - Serial.println(); -#endif - #else - Serial.println(); - #endif - #else - Serial.println("No thermistors - no temp"); - #endif - return; - //break; - case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGE("Heating..."); - if (code_seen('S')) target_raw[0] = temp2analog(code_value()); - #ifdef PIDTEMP - pid_setpoint = code_value(); - #endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[0]>current_raw[0]) { - watchmillis = max(1,millis()); - watch_raw = current_raw[0]; - } else { - watchmillis = 0; - } - #endif //WATCHPERIOD - codenum = millis(); - - /* See if we are heating up or cooling down */ - bool target_direction = (current_raw[0] < target_raw[0]); // 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((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || - (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { - #else - while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { - #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down - Serial.print("T:"); - Serial.println( analog2temp(current_raw[0]) ); - codenum = millis(); - } - manage_heater(); - 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 && current_raw[0] >= target_raw[0]) || - (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || - (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGE("Marlin ready."); - } - break; - case 190: // M190 - Wait bed for heater to reach target. - #if TEMP_1_PIN > -1 - if (code_seen('S')) target_raw[1] = temp2analog(code_value()); - codenum = millis(); - while(current_raw[1] < target_raw[1]) - { - if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. - { - float tt=analog2temp(current_raw[0]); - Serial.print("T:"); - Serial.println( tt ); - Serial.print("ok T:"); - Serial.print( tt ); - Serial.print(" B:"); - Serial.println( analog2temp(current_raw[1]) ); - codenum = millis(); - } - manage_heater(); - } - #endif - break; -#if FAN_PIN > -1 - case 106: //M106 Fan On - if (code_seen('S')){ - WRITE(FAN_PIN,HIGH); - fanpwm=constrain(code_value(),0,255); - analogWrite(FAN_PIN, fanpwm); - } - else { - WRITE(FAN_PIN,HIGH); - fanpwm=255; - analogWrite(FAN_PIN, fanpwm); - } - break; - case 107: //M107 Fan Off - WRITE(FAN_PIN,LOW); - analogWrite(FAN_PIN, 0); - break; -#endif -#if (PS_ON_PIN > -1) - case 80: // M80 - ATX Power On - SET_OUTPUT(PS_ON_PIN); //GND - break; - case 81: // M81 - ATX Power Off - SET_INPUT(PS_ON_PIN); //Floating - break; -#endif - case 82: - axis_relative_modes[3] = false; - break; - case 83: - axis_relative_modes[3] = true; - break; - case 18: - case 84: - if(code_seen('S')){ - stepper_inactive_time = code_value() * 1000; - } - else{ - st_synchronize(); - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - break; - case 85: // M85 - code_seen('S'); - max_inactive_time = code_value() * 1000; - break; - case 92: // M92 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); - } - - break; - case 115: // M115 - Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); - break; - case 114: // M114 - Serial.print("X:"); - Serial.print(current_position[X_AXIS]); - Serial.print("Y:"); - Serial.print(current_position[Y_AXIS]); - Serial.print("Z:"); - Serial.print(current_position[Z_AXIS]); - Serial.print("E:"); - Serial.print(current_position[E_AXIS]); - #ifdef DEBUG_STEPS - Serial.print(" Count X:"); - Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); - Serial.print("Y:"); - Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); - Serial.print("Z:"); - Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); - #endif - Serial.println(""); - break; - case 119: // M119 -#if (X_MIN_PIN > -1) - Serial.print("x_min:"); - Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (X_MAX_PIN > -1) - Serial.print("x_max:"); - Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MIN_PIN > -1) - Serial.print("y_min:"); - Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MAX_PIN > -1) - Serial.print("y_max:"); - Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MIN_PIN > -1) - Serial.print("z_min:"); - Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MAX_PIN > -1) - Serial.print("z_max:"); - Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif - Serial.println(""); - break; - //TODO: update for all axis, use for loop - case 201: // M201 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) 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(int 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(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; - } - 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()*60 ; - if(code_seen('T')) mintravelfeedrate = code_value()*60 ; - if(code_seen('B')) minsegmenttime = code_value() ; - if(code_seen('X')) max_xy_jerk = code_value()*60 ; - if(code_seen('Z')) max_z_jerk = code_value()*60 ; - } - break; - case 220: // M220 S- set speed factor override percentage - { - if(code_seen('S')) - { - feedmultiply = code_value() ; - feedmultiplychanged=true; - } - } - 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; -// ECHOLN("Kp "<<_FLOAT(Kp,2)); -// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); -// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); - -// temp_iState_min = 0.0; -// if (Ki!=0) { -// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); -// } -// else temp_iState_max = 1.0e10; - break; -#endif //PIDTEMP - case 500: // Store settings in EEPROM - { - StoreSettings(); - } - break; - case 501: // Read settings from EEPROM - { - RetrieveSettings(); - } - break; - case 502: // Revert to default settings - { - RetrieveSettings(true); - } - break; - - } - } - else{ - Serial.println("Unknown command:"); - Serial.println(cmdbuffer[bufindr]); - } - - ClearToSend(); -} - -void FlushSerialRequestResend() -{ - //char cmdbuffer[bufindr][100]="Resend:"; - Serial.flush(); - Serial.print("Resend:"); - Serial.println(gcode_LastN + 1); - ClearToSend(); -} - -void ClearToSend() -{ - previous_millis_cmd = millis(); -#ifdef SDSUPPORT - if(fromsd[bufindr]) - return; -#endif //SDSUPPORT - Serial.println("ok"); -} - -inline void get_coordinates() -{ - for(int 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]; - 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; - } -} - -void prepare_move() -{ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); - for(int i=0; i < NUM_AXIS; i++) { - current_position[i] = destination[i]; - } -} - - - -#ifdef USE_WATCHDOG - -#include -#include - -volatile uint8_t timeout_seconds=0; - -void(* ctrlaltdelete) (void) = 0; - -ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec - if(timeout_seconds++ >= WATCHDOG_TIMEOUT) - { - kill(); -#ifdef RESET_MANUAL - LCD_MESSAGE("Please Reset!"); - ECHOLN("echo_: Something is wrong, please turn off the printer."); -#else - LCD_MESSAGE("Timeout, resetting!"); -#endif - //disable watchdog, it will survife reboot. - WDTCSR |= (1< -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif - disable_x(); - disable_y(); - disable_z(); - disable_e(); - - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); - Serial.println("!! Printer halted. kill() called!!"); - while(1); // Wait for reset -} - -void manage_inactivity(byte debug) { - if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); - if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - check_axes_activity(); -} +/* + 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 "EEPROMwrite.h" +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" + +#ifdef SIMPLE_LCD + #include "Simplelcd.h" +#endif + +char version_string[] = "1.0.0 Alpha 1"; + +#ifdef SDSUPPORT +#include "SdFat.h" +#endif //SDSUPPORT + + +// 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 +// G4 - Dwell S or P +// G28 - Home all Axis +// G90 - Use Absolute Coordinates +// G91 - Use Relative Coordinates +// G92 - Set current position to cordinates given + +//RepRap M Codes +// 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 +// 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 +// 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 +// M115 - Capabilities string +// 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 +// M220 - set speed factor override percentage S:factor in percent +// M301 - Set PID parameters P I and D +// M500 - stores paramters in EEPROM +// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D +// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. + +//Stepper Movement Variables + +char axis_codes[NUM_AXIS] = { + 'X', 'Y', 'Z', 'E'}; +float destination[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +float current_position[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +bool home_all_axis = true; +float feedrate = 1500.0, next_feedrate, saved_feedrate; +long gcode_N, gcode_LastN; + +float homing_feedrate[] = HOMING_FEEDRATE; +bool axis_relative_modes[] = AXIS_RELATIVE_MODES; + +bool relative_mode = false; //Determines Absolute or Relative Coordinates +bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. + +uint8_t fanpwm=0; + +volatile int feedmultiply=100; //100->1 200->2 +int saved_feedmultiply; +volatile bool feedmultiplychanged=false; +// comm variables +#define MAX_CMD_SIZE 96 +#define BUFSIZE 4 +char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; +bool fromsd[BUFSIZE]; +int bufindr = 0; +int bufindw = 0; +int buflen = 0; +int i = 0; +char serial_char; +int serial_count = 0; +boolean comment_mode = false; +char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc +extern float HeaterPower; + +#include "EEPROM.h" + +const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 + +float tt = 0, bt = 0; +#ifdef WATCHPERIOD +int watch_raw = -1000; +unsigned long watchmillis = 0; +#endif //WATCHPERIOD + +//Inactivity shutdown variables +unsigned long previous_millis_cmd = 0; +unsigned long max_inactive_time = 0; +unsigned long stepper_inactive_time = 0; + +unsigned long starttime=0; +unsigned long stoptime=0; +#ifdef SDSUPPORT +Sd2Card card; +SdVolume volume; +SdFile root; +SdFile file; +uint32_t filesize = 0; +uint32_t sdpos = 0; +bool sdmode = false; +bool sdactive = false; +bool savetosd = false; +int16_t n; +unsigned long autostart_atmillis=0; + +void initsd(){ + sdactive = false; +#if SDSS >- 1 + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)){ + //if (!card.init(SPI_HALF_SPEED,SDSS)) + Serial.println("SD init fail"); + } + else if (!volume.init(&card)) + Serial.println("volume.init failed"); + else if (!root.openRoot(&volume)) + Serial.println("openRoot failed"); + else + { + sdactive = true; + Serial.println("SD card ok"); + } +#endif //SDSS +} + +void quickinitsd(){ + sdactive=false; + autostart_atmillis=millis()+5000; +} + +inline void write_command(char *buf){ + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL){ + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + //Serial.println(begin); + file.write(begin); + if (file.writeError){ + Serial.println("error writing to file"); + } +} +#endif //SDSUPPORT + + +///adds an command to the main command buffer +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.print("en:");Serial.println(cmdbuffer[bufindw]); + bufindw= (bufindw + 1)%BUFSIZE; + buflen += 1; + } +} + +void setup() +{ + + Serial.begin(BAUDRATE); + ECHOLN("Marlin "< -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); +#endif //SDPOWER + quickinitsd(); + +#endif //SDSUPPORT + plan_init(); // Initialize planner; + st_init(); // Initialize stepper; + tp_init(); // Initialize temperature loop + //checkautostart(); +} + +#ifdef SDSUPPORT +bool autostart_stilltocheck=true; + + +void checkautostart(bool force) +{ + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + //sprintf(cmd,"M115"); + //enquecommand("G92 Z0"); + //enquecommand("G1 Z10 F2000"); + //enquecommand("G28 X-105 Y-105"); + enquecommand(cmd); + enquecommand("M24"); + found=true; + + } + } + if(!found) + lastnr=-1; + else + lastnr++; + +} +#else + +inline void checkautostart(bool x) +{ +} +#endif + + +void loop() +{ + if(buflen<3) + get_command(); + checkautostart(false); + if(buflen) + { +#ifdef SDSUPPORT + if(savetosd){ + if(strstr(cmdbuffer[bufindr],"M29") == NULL){ + write_command(cmdbuffer[bufindr]); + Serial.println("ok"); + } + else{ + file.sync(); + file.close(); + savetosd = false; + Serial.println("Done saving file."); + } + } + else{ + process_commands(); + } +#else + process_commands(); +#endif //SDSUPPORT + buflen = (buflen-1); + bufindr = (bufindr + 1)%BUFSIZE; + } + //check heater every n milliseconds + manage_heater(); + manage_inactivity(1); + LCD_STATUS; +} + + +inline void get_command() +{ + while( Serial.available() > 0 && buflen < BUFSIZE) { + serial_char = Serial.read(); + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) + { + if(!serial_count) return; //if empty line + cmdbuffer[bufindw][serial_count] = 0; //terminate string + if(!comment_mode){ + 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.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); + Serial.println(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.print("Error: checksum mismatch, Last Line:"); + Serial.println(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + //if no errors, continue parsing + } + else + { + Serial.print("Error: No Checksum with line number, Last Line:"); + Serial.println(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.print("Error: No Line Number with checksum, Last Line:"); + Serial.println(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: +#ifdef SDSUPPORT + if(savetosd) + break; +#endif //SDSUPPORT + Serial.println("ok"); + break; + default: + break; + } + + } + bufindw = (bufindw + 1)%BUFSIZE; + buflen += 1; + + } + 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; + } + } +#ifdef SDSUPPORT + if(!sdmode || serial_count!=0){ + return; + } + while( filesize > sdpos && buflen < BUFSIZE) { + n = file.read(); + serial_char = (char)n; + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) + { + sdpos = file.curPosition(); + if(sdpos >= filesize){ + sdmode = false; + Serial.println("Done printing file"); + 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.println(time); + LCD_MESSAGE(time); + checkautostart(true); + } + if(!serial_count) 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 + +} + + +inline float code_value() { + return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); +} +inline long code_value_long() { + return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); +} +inline bool code_seen(char code_string[]) { + return (strstr(cmdbuffer[bufindr], code_string) != NULL); +} //Return True if the string was found + +inline bool code_seen(char code) +{ + strchr_pointer = strchr(cmdbuffer[bufindr], code); + return (strchr_pointer != NULL); //Return True if a character was found +} + +inline 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 + get_coordinates(); // For X Y Z E F + prepare_move(); + previous_millis_cmd = millis(); + //ClearToSend(); + return; + //break; + case 4: // G4 dwell + codenum = 0; + if(code_seen('P')) codenum = code_value(); // milliseconds to wait + if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait + codenum += millis(); // keep track of when we started waiting + while(millis() < codenum ){ + manage_heater(); + } + break; + case 28: //G28 Home all Axis one at a time + saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + + for(int 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((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { + if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ +// st_synchronize(); + current_position[X_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; + feedrate = homing_feedrate[X_AXIS]; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = -5 * X_HOME_DIR; + prepare_move(); + +// st_synchronize(); + destination[X_AXIS] = 10 * X_HOME_DIR; + feedrate = homing_feedrate[X_AXIS]/2 ; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = current_position[X_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { + if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ + 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[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]; + prepare_move(); +// st_synchronize(); + + 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[Y_AXIS] = -5 * Y_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Y_AXIS] = 10 * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Y_AXIS] = current_position[Y_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { + if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = -2 * Z_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Z_AXIS] = 3 * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = current_position[Z_AXIS]; + feedrate = 0.0; + } + } + feedrate = saved_feedrate; + feedmultiply = saved_feedmultiply; + previous_millis_cmd = millis(); + break; + case 90: // G90 + relative_mode = false; + break; + case 91: // G91 + relative_mode = true; + break; + case 92: // G92 + if(!code_seen(axis_codes[E_AXIS])) + st_synchronize(); + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) current_position[i] = code_value(); + } + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + break; + } + } + + else if(code_seen('M')) + { + + switch( (int)code_value() ) + { +#ifdef SDSUPPORT + + case 20: // M20 - list SD card + Serial.println("Begin file list"); + root.ls(); + Serial.println("End file list"); + break; + case 21: // M21 - init SD card + sdmode = false; + initsd(); + break; + case 22: //M22 - release SD card + sdmode = false; + sdactive = false; + break; + case 23: //M23 - Select file + if(sdactive){ + sdmode = false; + file.close(); + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos!=NULL) + *(starpos-1)='\0'; + if (file.open(&root, strchr_pointer + 4, O_READ)) { + Serial.print("File opened:"); + Serial.print(strchr_pointer + 4); + Serial.print(" Size:"); + Serial.println(file.fileSize()); + sdpos = 0; + filesize = file.fileSize(); + Serial.println("File selected"); + } + else{ + Serial.println("file.open failed"); + } + } + break; + case 24: //M24 - Start SD print + if(sdactive){ + sdmode = true; + starttime=millis(); + } + break; + case 25: //M25 - Pause SD print + if(sdmode){ + sdmode = false; + } + break; + case 26: //M26 - Set SD index + if(sdactive && code_seen('S')){ + sdpos = code_value_long(); + file.seekSet(sdpos); + } + break; + case 27: //M27 - Get SD status + if(sdactive){ + Serial.print("SD printing byte "); + Serial.print(sdpos); + Serial.print("/"); + Serial.println(filesize); + } + else{ + Serial.println("Not SD printing"); + } + break; + case 28: //M28 - Start SD write + if(sdactive){ + char* npos = 0; + file.close(); + sdmode = false; + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos != NULL){ + npos = strchr(cmdbuffer[bufindr], 'N'); + strchr_pointer = strchr(npos,' ') + 1; + *(starpos-1) = '\0'; + } + if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + Serial.print("open failed, File: "); + Serial.print(strchr_pointer + 4); + Serial.print("."); + } + else{ + savetosd = true; + Serial.print("Writing to file: "); + Serial.println(strchr_pointer + 4); + } + } + break; + case 29: //M29 - Stop SD write + //processed in write to file routine above + //savetosd = false; + break; + case 30: + { + 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.println(time); + LCD_MESSAGE(time); + } + break; +#endif //SDSUPPORT + 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(int i = 0; i < (int)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 (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); +#ifdef PIDTEMP + pid_setpoint = code_value(); +#endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND] > current_raw[TEMPSENSOR_HOTEND]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; + }else{ + watchmillis = 0; + } + #endif + break; + case 140: // M140 set bed temp + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); + break; + case 105: // M105 + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + tt = analog2temp(current_raw[TEMPSENSOR_HOTEND]); + #endif + #if TEMP_1_PIN > -1 + bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); + #endif + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + Serial.print("ok T:"); + Serial.print(tt); +// Serial.print(", raw:"); +// Serial.print(current_raw); + #if TEMP_1_PIN > -1 +#ifdef PIDTEMP + Serial.print(" B:"); + #if TEMP_1_PIN > -1 + Serial.println(bt); + #else + Serial.println(HeaterPower); + #endif +#else + Serial.println(); +#endif + #else + Serial.println(); + #endif + #else + Serial.println("No thermistors - no temp"); + #endif + return; + //break; + case 109: {// M109 - Wait for extruder heater to reach target. + LCD_MESSAGE("Heating..."); + if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); + #ifdef PIDTEMP + pid_setpoint = code_value(); + #endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND]>current_raw[TEMPSENSOR_HOTEND]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; + } else { + watchmillis = 0; + } + #endif //WATCHPERIOD + codenum = millis(); + + /* See if we are heating up or cooling down */ + bool target_direction = (current_raw[0] < target_raw[0]); // 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((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + #else + while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { + #endif //TEMP_RESIDENCY_TIME + if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down + Serial.print("T:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND]) ); + codenum = millis(); + } + manage_heater(); + 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 && current_raw[0] >= target_raw[0]) || + (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || + (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGE("Marlin ready."); + } + break; + case 190: // M190 - Wait bed for heater to reach target. + #if TEMP_1_PIN > -1 + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); + codenum = millis(); + while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) + { + if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + { + float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND]); + Serial.print("T:"); + Serial.println( tt ); + Serial.print("ok T:"); + Serial.print( tt ); + Serial.print(" B:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); + codenum = millis(); + } + manage_heater(); + } + #endif + break; +#if FAN_PIN > -1 + case 106: //M106 Fan On + if (code_seen('S')){ + WRITE(FAN_PIN,HIGH); + fanpwm=constrain(code_value(),0,255); + analogWrite(FAN_PIN, fanpwm); + } + else { + WRITE(FAN_PIN,HIGH); + fanpwm=255; + analogWrite(FAN_PIN, fanpwm); + } + break; + case 107: //M107 Fan Off + WRITE(FAN_PIN,LOW); + analogWrite(FAN_PIN, 0); + break; +#endif +#if (PS_ON_PIN > -1) + case 80: // M80 - ATX Power On + SET_OUTPUT(PS_ON_PIN); //GND + break; + case 81: // M81 - ATX Power Off + SET_INPUT(PS_ON_PIN); //Floating + break; +#endif + case 82: + axis_relative_modes[3] = false; + break; + case 83: + axis_relative_modes[3] = true; + break; + case 18: + case 84: + if(code_seen('S')){ + stepper_inactive_time = code_value() * 1000; + } + else{ + st_synchronize(); + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + break; + case 85: // M85 + code_seen('S'); + max_inactive_time = code_value() * 1000; + break; + case 92: // M92 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); + } + + break; + case 115: // M115 + Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); + break; + case 114: // M114 + Serial.print("X:"); + Serial.print(current_position[X_AXIS]); + Serial.print("Y:"); + Serial.print(current_position[Y_AXIS]); + Serial.print("Z:"); + Serial.print(current_position[Z_AXIS]); + Serial.print("E:"); + Serial.print(current_position[E_AXIS]); + #ifdef DEBUG_STEPS + Serial.print(" Count X:"); + Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); + Serial.print("Y:"); + Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); + Serial.print("Z:"); + Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); + #endif + Serial.println(""); + break; + case 119: // M119 +#if (X_MIN_PIN > -1) + Serial.print("x_min:"); + Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (X_MAX_PIN > -1) + Serial.print("x_max:"); + Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MIN_PIN > -1) + Serial.print("y_min:"); + Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MAX_PIN > -1) + Serial.print("y_max:"); + Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MIN_PIN > -1) + Serial.print("z_min:"); + Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MAX_PIN > -1) + Serial.print("z_max:"); + Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif + Serial.println(""); + break; + //TODO: update for all axis, use for loop + case 201: // M201 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) 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(int 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(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; + } + 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()*60 ; + if(code_seen('T')) mintravelfeedrate = code_value()*60 ; + if(code_seen('B')) minsegmenttime = code_value() ; + if(code_seen('X')) max_xy_jerk = code_value()*60 ; + if(code_seen('Z')) max_z_jerk = code_value()*60 ; + } + break; + case 220: // M220 S- set speed factor override percentage + { + if(code_seen('S')) + { + feedmultiply = code_value() ; + feedmultiplychanged=true; + } + } + 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; +// ECHOLN("Kp "<<_FLOAT(Kp,2)); +// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); +// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); + +// temp_iState_min = 0.0; +// if (Ki!=0) { +// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); +// } +// else temp_iState_max = 1.0e10; + break; +#endif //PIDTEMP + case 500: // Store settings in EEPROM + { + StoreSettings(); + } + break; + case 501: // Read settings from EEPROM + { + RetrieveSettings(); + } + break; + case 502: // Revert to default settings + { + RetrieveSettings(true); + } + break; + + } + } + else{ + Serial.println("Unknown command:"); + Serial.println(cmdbuffer[bufindr]); + } + + ClearToSend(); +} + +void FlushSerialRequestResend() +{ + //char cmdbuffer[bufindr][100]="Resend:"; + Serial.flush(); + Serial.print("Resend:"); + Serial.println(gcode_LastN + 1); + ClearToSend(); +} + +void ClearToSend() +{ + previous_millis_cmd = millis(); +#ifdef SDSUPPORT + if(fromsd[bufindr]) + return; +#endif //SDSUPPORT + Serial.println("ok"); +} + +inline void get_coordinates() +{ + for(int 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]; + 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; + } +} + +void prepare_move() +{ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); + for(int i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; + } +} + + + +#ifdef USE_WATCHDOG + +#include +#include + +volatile uint8_t timeout_seconds=0; + +void(* ctrlaltdelete) (void) = 0; + +ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec + if(timeout_seconds++ >= WATCHDOG_TIMEOUT) + { + kill(); +#ifdef RESET_MANUAL + LCD_MESSAGE("Please Reset!"); + ECHOLN("echo_: Something is wrong, please turn off the printer."); +#else + LCD_MESSAGE("Timeout, resetting!"); +#endif + //disable watchdog, it will survife reboot. + WDTCSR |= (1< -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif + disable_x(); + disable_y(); + disable_z(); + disable_e(); + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + Serial.println("!! Printer halted. kill() called!!"); + while(1); // Wait for reset +} + +void manage_inactivity(byte debug) { + if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); + if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + check_axes_activity(); +} diff --git a/Marlin/fastio.h b/Marlin/fastio.h index c1671ddef9..2d13962523 100644 --- a/Marlin/fastio.h +++ b/Marlin/fastio.h @@ -24,12 +24,12 @@ */ /// Read a pin -#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) +#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) /// write to a pin -#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) -//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) +#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) +//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) /// toggle a pin -#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) +#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) /// set pin as input #define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0) @@ -2556,4 +2556,4 @@ pins #error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request #endif -#endif /* _ARDUINO_H */ +#endif /* _ARDUINO_H */ diff --git a/Marlin/lcd.h b/Marlin/lcd.h deleted file mode 100644 index 74057ddde1..0000000000 --- a/Marlin/lcd.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __LCDH -#define __LCDH - - - - - - - -#endif diff --git a/Marlin/lcd.pde b/Marlin/lcd.pde deleted file mode 100644 index 8b13789179..0000000000 --- a/Marlin/lcd.pde +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 645384e6d8..f0ca298214 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -381,13 +381,6 @@ void check_axes_activity() { // calculation the caller must also provide the physical length of the line in millimeters. void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { - // The target position of the tool in absolute steps - // Calculate target position in absolute steps - long target[4]; - target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); // Calculate the buffer head after we push this byte int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); @@ -400,6 +393,15 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { LCD_STATUS; } + // The target position of the tool in absolute steps + // Calculate target position in absolute steps + //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow + long target[4]; + target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + // Prepare to set up new block block_t *block = &block_buffer[block_buffer_head]; @@ -433,7 +435,7 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { unsigned long microseconds; if (block->steps_e == 0) { - if(feed_rate. -*/ - -// This module is to be considered a sub-module of stepper.c. Please don't include -// this file from any other module. - -#ifndef planner_h -#define planner_h - -// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in -// the source g-code and may never actually be reached if acceleration management is active. -typedef struct { - // Fields used by the bresenham algorithm for tracing the line - long steps_x, steps_y, steps_z, steps_e; // Step count along each axis - long step_event_count; // The number of step events required to complete this block - volatile long accelerate_until; // The index of the step event on which to stop acceleration - volatile long decelerate_after; // The index of the step event on which to start decelerating - volatile long acceleration_rate; // The acceleration rate used for acceleration calculation - unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) -#ifdef ADVANCE - long advance_rate; - volatile long initial_advance; - volatile long final_advance; - float advance; -#endif - - // Fields used by the motion planner to manage acceleration - float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis - float nominal_speed; // The nominal speed for this block in mm/min - float millimeters; // The total travel of this block in mm - float entry_speed; - float acceleration; // acceleration mm/sec^2 - - // Settings for the trapezoid generator - long nominal_rate; // The nominal step rate for this block in step_events/sec - volatile long initial_rate; // The jerk-adjusted step rate at start of block - volatile long final_rate; // The minimal rate at exit - long acceleration_st; // acceleration steps/sec^2 - volatile char busy; -} block_t; - -// Initialize the motion plan subsystem -void plan_init(); - -// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in -// millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(float x, float y, float z, float e, float feed_rate); - -// Set position. Used for G92 instructions. -void plan_set_position(float x, float y, float z, float e); - -// Called when the current block is no longer needed. Discards the block and makes the memory -// availible for new blocks. -void plan_discard_current_block(); - -// Gets the current block. Returns NULL if buffer empty -block_t *plan_get_current_block(); - -void check_axes_activity(); - -extern unsigned long minsegmenttime; -extern float max_feedrate[4]; // set the max speeds -extern float axis_steps_per_unit[4]; -extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -extern float minimumfeedrate; -extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -extern float max_z_jerk; -extern float mintravelfeedrate; -extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - -#endif +/* + planner.h - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +// This module is to be considered a sub-module of stepper.c. Please don't include +// this file from any other module. + +#ifndef planner_h +#define planner_h + +#include "Configuration.h" + +// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in +// the source g-code and may never actually be reached if acceleration management is active. +typedef struct { + // Fields used by the bresenham algorithm for tracing the line + long steps_x, steps_y, steps_z, steps_e; // Step count along each axis + long step_event_count; // The number of step events required to complete this block + volatile long accelerate_until; // The index of the step event on which to stop acceleration + volatile long decelerate_after; // The index of the step event on which to start decelerating + volatile long acceleration_rate; // The acceleration rate used for acceleration calculation + unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) +#ifdef ADVANCE + long advance_rate; + volatile long initial_advance; + volatile long final_advance; + float advance; +#endif + + // Fields used by the motion planner to manage acceleration + float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis + float nominal_speed; // The nominal speed for this block in mm/min + float millimeters; // The total travel of this block in mm + float entry_speed; + float acceleration; // acceleration mm/sec^2 + + // Settings for the trapezoid generator + long nominal_rate; // The nominal step rate for this block in step_events/sec + volatile long initial_rate; // The jerk-adjusted step rate at start of block + volatile long final_rate; // The minimal rate at exit + long acceleration_st; // acceleration steps/sec^2 + volatile char busy; +} block_t; + +// Initialize the motion plan subsystem +void plan_init(); + +// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in +// millimaters. Feed rate specifies the speed of the motion. +void plan_buffer_line(float x, float y, float z, float e, float feed_rate); + +// Set position. Used for G92 instructions. +void plan_set_position(float x, float y, float z, float e); + +// Called when the current block is no longer needed. Discards the block and makes the memory +// availible for new blocks. +void plan_discard_current_block(); + +// Gets the current block. Returns NULL if buffer empty +block_t *plan_get_current_block(); + +void check_axes_activity(); + +extern unsigned long minsegmenttime; +extern float max_feedrate[4]; // set the max speeds +extern float axis_steps_per_unit[4]; +extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +extern float minimumfeedrate; +extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +extern float max_z_jerk; +extern float mintravelfeedrate; +extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + +#endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index cd68bae0d5..15f1433497 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -115,7 +115,7 @@ asm volatile ( \ #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<. -*/ - -#ifndef stepper_h -#define stepper_h -// Initialize and start the stepper motor subsystem -void st_init(); - -// Block until all buffered steps are executed -void st_synchronize(); - -// The stepper subsystem goes to sleep when it runs out of things to execute. Call this -// to notify the subsystem that it is time to go to work. -void st_wake_up(); - -// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. -// for debugging purposes only, should be disabled by default -#ifdef DEBUG_STEPS -extern volatile long count_position[NUM_AXIS]; -extern volatile int count_direction[NUM_AXIS]; -#endif - -#endif +/* + stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +#ifndef stepper_h +#define stepper_h + +#include "planner.h" + +// Initialize and start the stepper motor subsystem +void st_init(); + +// Block until all buffered steps are executed +void st_synchronize(); + +// The stepper subsystem goes to sleep when it runs out of things to execute. Call this +// to notify the subsystem that it is time to go to work. +void st_wake_up(); + +// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. +// for debugging purposes only, should be disabled by default +#ifdef DEBUG_STEPS +extern volatile long count_position[NUM_AXIS]; +extern volatile int count_direction[NUM_AXIS]; +#endif + +extern block_t *current_block; // A pointer to the block currently being traced +#endif diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 7a9c56e10b..5aaf6fd975 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -90,14 +90,15 @@ void manage_heater() float pid_input; float pid_output; - if(temp_meas_ready == true) { + if(temp_meas_ready != true) //better readability + return; CRITICAL_SECTION_START; temp_meas_ready = false; CRITICAL_SECTION_END; #ifdef PIDTEMP - pid_input = analog2temp(current_raw[0]); + pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND]); #ifndef PID_OPENLOOP pid_error = pid_setpoint - pid_input; @@ -118,10 +119,13 @@ CRITICAL_SECTION_END; temp_iState += pid_error; temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); iTerm = Ki * temp_iState; - #define K1 0.95 + //K1 defined in Configuration.h in the PID settings #define K2 (1.0-K1) dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); temp_dState = pid_input; + #ifdef PID_ADD_EXTRUSION_RATE + pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high + #endif pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); } #endif //PID_OPENLOOP @@ -157,7 +161,7 @@ CRITICAL_SECTION_END; previous_millis_bed_heater = millis(); #if TEMP_1_PIN > -1 - if(current_raw[1] >= target_raw[1]) + if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) { WRITE(HEATER_1_PIN,LOW); } @@ -167,7 +171,6 @@ CRITICAL_SECTION_END; } #endif } -} // Takes hot end temperature value as input and returns corresponding raw value. // For a thermistor, it uses the RepRap thermistor temp table. @@ -428,15 +431,15 @@ ISR(TIMER0_COMPB_vect) raw_temp_2_value = 0; #ifdef MAXTEMP #if (HEATER_0_PIN > -1) - if(current_raw[0] >= maxttemp) { - target_raw[0] = 0; + if(current_raw[TEMPSENSOR_HOTEND] >= maxttemp) { + target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(current_raw[2] >= maxttemp) { - target_raw[2] = 0; + if(current_raw[TEMPSENSOR_AUX] >= maxttemp) { + target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); } @@ -444,15 +447,15 @@ ISR(TIMER0_COMPB_vect) #endif //MAXTEMP #ifdef MINTEMP #if (HEATER_0_PIN > -1) - if(current_raw[0] <= minttemp) { - target_raw[0] = 0; + if(current_raw[TEMPSENSOR_HOTEND] <= minttemp) { + target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(current_raw[2] <= minttemp) { - target_raw[2] = 0; + if(current_raw[TEMPSENSOR_AUX] <= minttemp) { + target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); } diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 986aca9998..e2e6c459c6 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -1,55 +1,58 @@ -/* - temperature.h - temperature controller - Part of Marlin - - Copyright (c) 2011 Erik van der Zalm - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -#ifndef temperature_h -#define temperature_h - -void manage_inactivity(byte debug); - -void tp_init(); -void manage_heater(); -//int temp2analogu(int celsius, const short table[][2], int numtemps); -//float analog2tempu(int raw, const short table[][2], int numtemps); -float temp2analog(int celsius); -float temp2analogBed(int celsius); -float analog2temp(int raw); -float analog2tempBed(int raw); - -#ifdef HEATER_USES_THERMISTOR - #define HEATERSOURCE 1 -#endif -#ifdef BED_USES_THERMISTOR - #define BEDSOURCE 1 -#endif - -//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) -//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS - - -extern float Kp; -extern float Ki; -extern float Kd; -extern float Kc; - -extern int target_raw[3]; -extern int current_raw[3]; -extern double pid_setpoint; - -#endif +/* + temperature.h - temperature controller + Part of Marlin + + Copyright (c) 2011 Erik van der Zalm + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +#ifndef temperature_h +#define temperature_h + +#include "Marlin.h" +#ifdef PID_ADD_EXTRUSION_RATE + #include "stepper.h" +#endif +void tp_init(); +void manage_heater(); +//int temp2analogu(int celsius, const short table[][2], int numtemps); +//float analog2tempu(int raw, const short table[][2], int numtemps); +float temp2analog(int celsius); +float temp2analogBed(int celsius); +float analog2temp(int raw); +float analog2tempBed(int raw); + +#ifdef HEATER_USES_THERMISTOR + #define HEATERSOURCE 1 +#endif +#ifdef BED_USES_THERMISTOR + #define BEDSOURCE 1 +#endif + +//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) +//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS + + +extern float Kp; +extern float Ki; +extern float Kd; +extern float Kc; + +enum {TEMPSENSOR_HOTEND=0,TEMPSENSOR_BED=1, TEMPSENSOR_AUX=2}; +extern int target_raw[3]; +extern int current_raw[3]; +extern double pid_setpoint; + +#endif diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 0ea1991dce..6d43d72735 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -7,67 +7,67 @@ #define NUMTEMPS_1 61 const short temptable_1[NUMTEMPS_1][2] = { -{ 23*OVERSAMPLENR , 300 }, -{ 25*OVERSAMPLENR , 295 }, -{ 27*OVERSAMPLENR , 290 }, -{ 28*OVERSAMPLENR , 285 }, -{ 31*OVERSAMPLENR , 280 }, -{ 33*OVERSAMPLENR , 275 }, -{ 35*OVERSAMPLENR , 270 }, -{ 38*OVERSAMPLENR , 265 }, -{ 41*OVERSAMPLENR , 260 }, -{ 44*OVERSAMPLENR , 255 }, -{ 48*OVERSAMPLENR , 250 }, -{ 52*OVERSAMPLENR , 245 }, -{ 56*OVERSAMPLENR , 240 }, -{ 61*OVERSAMPLENR , 235 }, -{ 66*OVERSAMPLENR , 230 }, -{ 71*OVERSAMPLENR , 225 }, -{ 78*OVERSAMPLENR , 220 }, -{ 84*OVERSAMPLENR , 215 }, -{ 92*OVERSAMPLENR , 210 }, -{ 100*OVERSAMPLENR , 205 }, -{ 109*OVERSAMPLENR , 200 }, -{ 120*OVERSAMPLENR , 195 }, -{ 131*OVERSAMPLENR , 190 }, -{ 143*OVERSAMPLENR , 185 }, -{ 156*OVERSAMPLENR , 180 }, -{ 171*OVERSAMPLENR , 175 }, -{ 187*OVERSAMPLENR , 170 }, -{ 205*OVERSAMPLENR , 165 }, -{ 224*OVERSAMPLENR , 160 }, -{ 245*OVERSAMPLENR , 155 }, -{ 268*OVERSAMPLENR , 150 }, -{ 293*OVERSAMPLENR , 145 }, -{ 320*OVERSAMPLENR , 140 }, -{ 348*OVERSAMPLENR , 135 }, -{ 379*OVERSAMPLENR , 130 }, -{ 411*OVERSAMPLENR , 125 }, -{ 445*OVERSAMPLENR , 120 }, -{ 480*OVERSAMPLENR , 115 }, -{ 516*OVERSAMPLENR , 110 }, -{ 553*OVERSAMPLENR , 105 }, -{ 591*OVERSAMPLENR , 100 }, -{ 628*OVERSAMPLENR , 95 }, -{ 665*OVERSAMPLENR , 90 }, -{ 702*OVERSAMPLENR , 85 }, -{ 737*OVERSAMPLENR , 80 }, -{ 770*OVERSAMPLENR , 75 }, -{ 801*OVERSAMPLENR , 70 }, -{ 830*OVERSAMPLENR , 65 }, -{ 857*OVERSAMPLENR , 60 }, -{ 881*OVERSAMPLENR , 55 }, -{ 903*OVERSAMPLENR , 50 }, -{ 922*OVERSAMPLENR , 45 }, -{ 939*OVERSAMPLENR , 40 }, -{ 954*OVERSAMPLENR , 35 }, -{ 966*OVERSAMPLENR , 30 }, -{ 977*OVERSAMPLENR , 25 }, -{ 985*OVERSAMPLENR , 20 }, -{ 993*OVERSAMPLENR , 15 }, -{ 999*OVERSAMPLENR , 10 }, -{ 1004*OVERSAMPLENR , 5 }, -{ 1008*OVERSAMPLENR , 0 } //safety +{ 23*OVERSAMPLENR , 300 }, +{ 25*OVERSAMPLENR , 295 }, +{ 27*OVERSAMPLENR , 290 }, +{ 28*OVERSAMPLENR , 285 }, +{ 31*OVERSAMPLENR , 280 }, +{ 33*OVERSAMPLENR , 275 }, +{ 35*OVERSAMPLENR , 270 }, +{ 38*OVERSAMPLENR , 265 }, +{ 41*OVERSAMPLENR , 260 }, +{ 44*OVERSAMPLENR , 255 }, +{ 48*OVERSAMPLENR , 250 }, +{ 52*OVERSAMPLENR , 245 }, +{ 56*OVERSAMPLENR , 240 }, +{ 61*OVERSAMPLENR , 235 }, +{ 66*OVERSAMPLENR , 230 }, +{ 71*OVERSAMPLENR , 225 }, +{ 78*OVERSAMPLENR , 220 }, +{ 84*OVERSAMPLENR , 215 }, +{ 92*OVERSAMPLENR , 210 }, +{ 100*OVERSAMPLENR , 205 }, +{ 109*OVERSAMPLENR , 200 }, +{ 120*OVERSAMPLENR , 195 }, +{ 131*OVERSAMPLENR , 190 }, +{ 143*OVERSAMPLENR , 185 }, +{ 156*OVERSAMPLENR , 180 }, +{ 171*OVERSAMPLENR , 175 }, +{ 187*OVERSAMPLENR , 170 }, +{ 205*OVERSAMPLENR , 165 }, +{ 224*OVERSAMPLENR , 160 }, +{ 245*OVERSAMPLENR , 155 }, +{ 268*OVERSAMPLENR , 150 }, +{ 293*OVERSAMPLENR , 145 }, +{ 320*OVERSAMPLENR , 140 }, +{ 348*OVERSAMPLENR , 135 }, +{ 379*OVERSAMPLENR , 130 }, +{ 411*OVERSAMPLENR , 125 }, +{ 445*OVERSAMPLENR , 120 }, +{ 480*OVERSAMPLENR , 115 }, +{ 516*OVERSAMPLENR , 110 }, +{ 553*OVERSAMPLENR , 105 }, +{ 591*OVERSAMPLENR , 100 }, +{ 628*OVERSAMPLENR , 95 }, +{ 665*OVERSAMPLENR , 90 }, +{ 702*OVERSAMPLENR , 85 }, +{ 737*OVERSAMPLENR , 80 }, +{ 770*OVERSAMPLENR , 75 }, +{ 801*OVERSAMPLENR , 70 }, +{ 830*OVERSAMPLENR , 65 }, +{ 857*OVERSAMPLENR , 60 }, +{ 881*OVERSAMPLENR , 55 }, +{ 903*OVERSAMPLENR , 50 }, +{ 922*OVERSAMPLENR , 45 }, +{ 939*OVERSAMPLENR , 40 }, +{ 954*OVERSAMPLENR , 35 }, +{ 966*OVERSAMPLENR , 30 }, +{ 977*OVERSAMPLENR , 25 }, +{ 985*OVERSAMPLENR , 20 }, +{ 993*OVERSAMPLENR , 15 }, +{ 999*OVERSAMPLENR , 10 }, +{ 1004*OVERSAMPLENR , 5 }, +{ 1008*OVERSAMPLENR , 0 } //safety }; #endif #if (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor @@ -100,35 +100,35 @@ const short temptable_2[NUMTEMPS_2][2] = { #if (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts #define NUMTEMPS_3 28 const short temptable_3[NUMTEMPS_3][2] = { - {1*OVERSAMPLENR,864}, - {21*OVERSAMPLENR,300}, - {25*OVERSAMPLENR,290}, - {29*OVERSAMPLENR,280}, - {33*OVERSAMPLENR,270}, - {39*OVERSAMPLENR,260}, - {46*OVERSAMPLENR,250}, - {54*OVERSAMPLENR,240}, - {64*OVERSAMPLENR,230}, - {75*OVERSAMPLENR,220}, - {90*OVERSAMPLENR,210}, - {107*OVERSAMPLENR,200}, - {128*OVERSAMPLENR,190}, - {154*OVERSAMPLENR,180}, - {184*OVERSAMPLENR,170}, - {221*OVERSAMPLENR,160}, - {265*OVERSAMPLENR,150}, - {316*OVERSAMPLENR,140}, - {375*OVERSAMPLENR,130}, - {441*OVERSAMPLENR,120}, - {513*OVERSAMPLENR,110}, - {588*OVERSAMPLENR,100}, - {734*OVERSAMPLENR,80}, - {856*OVERSAMPLENR,60}, - {938*OVERSAMPLENR,40}, - {986*OVERSAMPLENR,20}, - {1008*OVERSAMPLENR,0}, - {1018*OVERSAMPLENR,-20} - }; + {1*OVERSAMPLENR,864}, + {21*OVERSAMPLENR,300}, + {25*OVERSAMPLENR,290}, + {29*OVERSAMPLENR,280}, + {33*OVERSAMPLENR,270}, + {39*OVERSAMPLENR,260}, + {46*OVERSAMPLENR,250}, + {54*OVERSAMPLENR,240}, + {64*OVERSAMPLENR,230}, + {75*OVERSAMPLENR,220}, + {90*OVERSAMPLENR,210}, + {107*OVERSAMPLENR,200}, + {128*OVERSAMPLENR,190}, + {154*OVERSAMPLENR,180}, + {184*OVERSAMPLENR,170}, + {221*OVERSAMPLENR,160}, + {265*OVERSAMPLENR,150}, + {316*OVERSAMPLENR,140}, + {375*OVERSAMPLENR,130}, + {441*OVERSAMPLENR,120}, + {513*OVERSAMPLENR,110}, + {588*OVERSAMPLENR,100}, + {734*OVERSAMPLENR,80}, + {856*OVERSAMPLENR,60}, + {938*OVERSAMPLENR,40}, + {986*OVERSAMPLENR,20}, + {1008*OVERSAMPLENR,0}, + {1018*OVERSAMPLENR,-20} + }; #endif #if (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 5f0196fa5a..39cca278ee 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -153,4 +153,4 @@ #define BLOCK ; #endif #endif //ULTRALCD - + diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 2702af854a..a6c75e0fc2 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1,1593 +1,1593 @@ -#include "ultralcd.h" - - -#ifdef ULTRA_LCD -extern volatile int feedmultiply; -extern long position[4]; - -char messagetext[LCD_WIDTH]=""; - -#include -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 - -unsigned long previous_millis_lcd=0; - - - -volatile char buttons=0; //the last checked buttons in a bit array. -int encoderpos=0; -short lastenc=0; -#ifdef NEWPANEL - long blocking=0; -#else - long blocking[8]={0,0,0,0,0,0,0,0}; -#endif -MainMenu menu; - -void lcd_status(const char* message) -{ - strncpy(messagetext,message,LCD_WIDTH); -} - -void clear() -{ - //lcd.setCursor(0,0); - lcd.clear(); - //delay(1); - // lcd.begin(LCD_WIDTH,LCD_HEIGHT); - //lcd_init(); -} -long previous_millis_buttons=0; - -void lcd_init() -{ - //beep(); - byte Degree[8] = - { - B01100, - B10010, - B10010, - B01100, - B00000, - B00000, - B00000, - B00000 - }; - byte Thermometer[8] = - { - B00100, - B01010, - B01010, - B01010, - B01010, - B10001, - B10001, - B01110 - }; - byte uplevel[8]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris - byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - lcd.createChar(1,Degree); - lcd.createChar(2,Thermometer); - lcd.createChar(3,uplevel); - lcd.createChar(4,refresh); - LCD_MESSAGE(fillto(LCD_WIDTH,"UltiMarlin ready.")); -} - - -void beep() -{ - //return; -#ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int i=0;i<20;i++){ - WRITE(BEEPER,HIGH); - delay(5); - WRITE(BEEPER,LOW); - delay(5); - } -#endif -} - -void beepshort() -{ - //return; -#ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int i=0;i<10;i++){ - WRITE(BEEPER,HIGH); - delay(3); - WRITE(BEEPER,LOW); - delay(3); - } -#endif -} -void lcd_status() -{ -#ifdef ULTIPANEL - static uint8_t oldbuttons=0; - static long previous_millis_buttons=0; - static long previous_lcdinit=0; -// buttons_check(); // Done in temperature interrupt - //previous_millis_buttons=millis(); - - if((buttons==oldbuttons) && ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) - return; - oldbuttons=buttons; -#else - - if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) - return; -#endif - - previous_millis_lcd=millis(); - menu.update(); -} -#ifdef ULTIPANEL -void buttons_init() -{ -#ifdef NEWPANEL - pinMode(BTN_EN1,INPUT); - pinMode(BTN_EN2,INPUT); - pinMode(BTN_ENC,INPUT); - pinMode(SDCARDDETECT,INPUT); - WRITE(BTN_EN1,HIGH); - WRITE(BTN_EN2,HIGH); - WRITE(BTN_ENC,HIGH); - WRITE(SDCARDDETECT,HIGH); -#else - pinMode(SHIFT_CLK,OUTPUT); - pinMode(SHIFT_LD,OUTPUT); - pinMode(SHIFT_EN,OUTPUT); - pinMode(SHIFT_OUT,INPUT); - WRITE(SHIFT_OUT,HIGH); - WRITE(SHIFT_LD,HIGH); - WRITE(SHIFT_EN,LOW); -#endif -} - - -void buttons_check() -{ -// volatile static bool busy=false; -// if(busy) -// return; -// busy=true; - -#ifdef NEWPANEL - uint8_t newbutton=0; - if(READ(BTN_EN1)==0) newbutton|=EN_A; - if(READ(BTN_EN2)==0) newbutton|=EN_B; - if((blocking>1; - if(READ(SHIFT_OUT)) - newbutton|=(1<<7); - WRITE(SHIFT_CLK,HIGH); - WRITE(SHIFT_CLK,LOW); - } - buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 -#endif - char enc=0; - if(buttons&EN_A) - enc|=(1<<0); - if(buttons&EN_B) - enc|=(1<<1); - if(enc!=lastenc) - { - switch(enc) - { - case encrot0: - if(lastenc==encrot3) - encoderpos++; - else if(lastenc==encrot1) - encoderpos--; - break; - case encrot1: - if(lastenc==encrot0) - encoderpos++; - else if(lastenc==encrot2) - encoderpos--; - break; - case encrot2: - if(lastenc==encrot1) - encoderpos++; - else if(lastenc==encrot3) - encoderpos--; - break; - case encrot3: - if(lastenc==encrot2) - encoderpos++; - else if(lastenc==encrot0) - encoderpos--; - break; - default: - ; - } - } - lastenc=enc; -// busy=false; -} - -#endif - -MainMenu::MainMenu() -{ - status=Main_Status; - displayStartingRow=0; - activeline=0; - force_lcd_update=true; -#ifdef ULTIPANEL - buttons_init(); -#endif - lcd_init(); - linechanging=false; -} - -extern volatile bool feedmultiplychanged; - -void MainMenu::showStatus() -{ -#if LCD_HEIGHT==4 - static int oldcurrentraw=-1; - static int oldtargetraw=-1; - //force_lcd_update=true; - if(force_lcd_update||feedmultiplychanged) //initial display of content - { - feedmultiplychanged=false; - encoderpos=feedmultiply; - clear(); - lcd.setCursor(0,0);lcd.print("\002123/567\001 "); -#if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcd.print("B123/567\001 "); -#endif - } - - - if((abs(current_raw[0]-oldcurrentraw)>3)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[0]))); - oldcurrentraw=current_raw[0]; - } - if((target_raw[0]!=oldtargetraw)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[0]))); - oldtargetraw=target_raw[0]; - } - #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - static int oldcurrentbedraw=-1; - static int oldtargetbedraw=-1; - if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_bed_raw))); - oldcurrentraw=current_raw[1]; - } - if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_bed_raw))); - oldtargetraw=target_bed_raw; - } - #endif - //starttime=2; - static uint16_t oldtime=0; - if(starttime!=0) - { - lcd.setCursor(0,1); - uint16_t time=millis()/60000-starttime/60000; - - if(starttime!=oldtime) - { - lcd.print(itostr2(time/60));lcd.print("h ");lcd.print(itostr2(time%60));lcd.print("m"); - oldtime=time; - } - } - static int oldzpos=0; - int currentz=current_position[2]*10; - if((currentz!=oldzpos)||force_lcd_update) - { - lcd.setCursor(10,1); - lcd.print("Z:");lcd.print(itostr31(currentz)); - oldzpos=currentz; - } - static int oldfeedmultiply=0; - int curfeedmultiply=feedmultiply; - if(encoderpos!=curfeedmultiply||force_lcd_update) - { - curfeedmultiply=encoderpos; - if(curfeedmultiply<10) - curfeedmultiply=10; - if(curfeedmultiply>999) - curfeedmultiply=999; - feedmultiply=curfeedmultiply; - encoderpos=curfeedmultiply; - } - if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) - { - oldfeedmultiply=curfeedmultiply; - lcd.setCursor(0,2); - lcd.print(itostr3(curfeedmultiply));lcd.print("% "); - } - if(messagetext[0]!='\0') - { - lcd.setCursor(0,LCD_HEIGHT-1); - lcd.print(fillto(LCD_WIDTH,messagetext)); - messagetext[0]='\0'; - } -#else //smaller LCDS---------------------------------- - static int oldcurrentraw=-1; - static int oldtargetraw=-1; - if(force_lcd_update) //initial display of content - { - encoderpos=feedmultiply; - lcd.setCursor(0,0);lcd.print("\002123/567\001 "); - #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcd.print("B123/567\001 "); - #endif - } - - - if((abs(current_raw[0]-oldcurrentraw)>3)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[0]))); - oldcurrentraw=current_raw[0]; - } - if((target_raw[0]!=oldtargetraw)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[0]))); - oldtargetraw=target_raw[0]; - } - - if(messagetext[0]!='\0') - { - lcd.setCursor(0,LCD_HEIGHT-1); - lcd.print(fillto(LCD_WIDTH,messagetext)); - messagetext[0]='\0'; - } - -#endif -} - -enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; - -void MainMenu::showPrepare() -{ - uint8_t line=0; - if(lastlineoffset!=lineoffset) - { - force_lcd_update=true; - clear(); - } - for(uint8_t i=lineoffset;i3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(ItemP_disstep+1-LCD_HEIGHT)) - lineoffset=ItemP_disstep+1-LCD_HEIGHT; - force_lcd_update=true; - } - //encoderpos=encoderpos%LCD_HEIGHT; - lastencoderpos=encoderpos; - activeline=encoderpos/lcdslow; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - } -} -enum { - ItemC_exit, ItemC_nozzle, - ItemC_PID_P,ItemC_PID_I,ItemC_PID_D,ItemC_PID_C, - ItemC_fan, - ItemC_acc, ItemC_xyjerk, - ItemC_vmaxx, ItemC_vmaxy, ItemC_vmaxz, ItemC_vmaxe, - ItemC_vtravmin,ItemC_vmin, - ItemC_amaxx, ItemC_amaxy, ItemC_amaxz, ItemC_amaxe, - ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe -}; - -void MainMenu::showControl() -{ - uint8_t line=0; - if((lastlineoffset!=lineoffset)||force_lcd_update) - { - force_lcd_update=true; - clear(); - } - for(uint8_t i=lineoffset;i260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - - case ItemC_fan: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Fan speed:"); - lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); - } - - if((activeline==line) ) - { - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=fanpwm; - } - else - { - fanpwm = constrain(encoderpos,0,255); - encoderpos=fanpwm; - analogWrite(FAN_PIN, fanpwm); - - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_acc: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Acc:"); - lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcd.print("00"); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)acceleration/100; - } - else - { - acceleration= encoderpos*100; - encoderpos=activeline*lcdslow; - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<5) encoderpos=5; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); - } - } - }break; - case ItemC_xyjerk: //max_xy_jerk - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Vxy-jerk: "); - lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_xy_jerk/60; - } - else - { - max_xy_jerk= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_PID_P: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-P: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kp)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kp/5; - } - else - { - Kp= encoderpos*5; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>9990/5) encoderpos=9990/5; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); - } - } - }break; - case ItemC_PID_I: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-I: "); - lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(Ki*10); - } - else - { - Ki= encoderpos/10.; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); - } - } - }break; - case ItemC_PID_D: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-D: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kd)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kd/5; - } - else - { - Kd= encoderpos*5; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990/5) encoderpos=9990/5; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); - } - } - }break; - - - - case ItemC_PID_C: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-C: "); - lcd.setCursor(13,line);lcd.print(itostr3(Kc)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kc; - } - else - { - Kc= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_vmaxx: - case ItemC_vmaxy: - case ItemC_vmaxz: - case ItemC_vmaxe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Vmax "); - if(i==ItemC_vmaxx)lcd.print("x:"); - if(i==ItemC_vmaxy)lcd.print("y:"); - if(i==ItemC_vmaxz)lcd.print("z:"); - if(i==ItemC_vmaxe)lcd.print("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemC_vmaxx]/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_feedrate[i-ItemC_vmaxx]/60; - } - else - { - max_feedrate[i-ItemC_vmaxx]= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - - case ItemC_vmin: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Vmin:"); - lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(minimumfeedrate/60.); - } - else - { - minimumfeedrate= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_vtravmin: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" VTrav min:"); - lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)mintravelfeedrate/60; - } - else - { - mintravelfeedrate= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - - case ItemC_amaxx: - case ItemC_amaxy: - case ItemC_amaxz: - case ItemC_amaxe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Amax "); - if(i==ItemC_amaxx)lcd.print("x:"); - if(i==ItemC_amaxy)lcd.print("y:"); - if(i==ItemC_amaxz)lcd.print("z:"); - if(i==ItemC_amaxe)lcd.print("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcd.print("00"); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100; - } - else - { - max_acceleration_units_per_sq_second[i-ItemC_amaxx]= encoderpos*100; - encoderpos=activeline*lcdslow; - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); - } - } - }break; - case ItemC_aret://float retract_acceleration = 7000; - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" A-retract:"); - lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcd.print("00"); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)retract_acceleration/100; - } - else - { - retract_acceleration= encoderpos*100; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<10) encoderpos=10; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); - } - } - }break; - case ItemC_esteps://axis_steps_per_unit[i] = code_value(); - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Esteps/mm:"); - lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)axis_steps_per_unit[3]; - } - else - { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); - position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); - } - } - }break; - case ItemC_store: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Store EPROM"); - } - if((activeline==line) && CLICKED) - { - //enquecommand("M84"); - beepshort(); - BLOCK; - StoreSettings(); - } - }break; - case ItemC_load: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Load EPROM"); - } - if((activeline==line) && CLICKED) - { - //enquecommand("M84"); - beepshort(); - BLOCK; - RetrieveSettings(); - } - }break; - case ItemC_failsafe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Restore Failsafe"); - } - if((activeline==line) && CLICKED) - { - //enquecommand("M84"); - beepshort(); - BLOCK; - RetrieveSettings(true); - } - }break; - default: - break; - } - line++; - } - lastlineoffset=lineoffset; - - if(!linechanging && ((encoderpos/lcdslow!=lastencoderpos/lcdslow)||force_lcd_update)) - { - - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?' ':' '); - - if(encoderpos<0) - { - lineoffset--; - if(lineoffset<0) - lineoffset=0; - encoderpos=0; - force_lcd_update=true; - } - if(encoderpos/lcdslow>3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(ItemC_failsafe+1-LCD_HEIGHT)) - lineoffset=ItemC_failsafe+1-LCD_HEIGHT; - force_lcd_update=true; - } - //encoderpos=encoderpos%LCD_HEIGHT; - lastencoderpos=encoderpos; - activeline=encoderpos/lcdslow; - if(activeline>3) activeline=3; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - } -} - -#include "SdFat.h" - -void MainMenu::getfilename(const uint8_t nr) -{ -#ifdef SDSUPPORT - dir_t p; - root.rewind(); - uint8_t cnt=0; - filename[0]='\0'; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - if(cnt++!=nr) continue; - //Serial.println((char*)p.name); - uint8_t writepos=0; - for (uint8_t i = 0; i < 11; i++) - { - if (p.name[i] == ' ') continue; - if (i == 8) { - filename[writepos++]='.'; - } - filename[writepos++]=p.name[i]; - } - filename[writepos++]=0; - } -#endif -} - -uint8_t getnrfilenames() -{ -#ifdef SDSUPPORT - dir_t p; - root.rewind(); - uint8_t cnt=0; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - cnt++; - } - return cnt; -#endif -} - -void MainMenu::showSD() -{ - -#ifdef SDSUPPORT - uint8_t line=0; - - if(lastlineoffset!=lineoffset) - { - force_lcd_update=true; - } - static uint8_t nrfiles=0; - if(force_lcd_update) - { - clear(); - if(sdactive) - { - nrfiles=getnrfilenames(); - } - else - { - nrfiles=0; - lineoffset=0; - } - //Serial.print("Nr files:"); Serial.println((int)nrfiles); - } - - for(int8_t i=lineoffset;i3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(1+nrfiles+1-LCD_HEIGHT)) - lineoffset=1+nrfiles+1-LCD_HEIGHT; - force_lcd_update=true; - - } - lastencoderpos=encoderpos; - activeline=encoderpos; - if(activeline>3) - { - activeline=3; - } - if(activeline<0) - { - activeline=0; - } - if(activeline>1+nrfiles) activeline=1+nrfiles; - if(lineoffset>1+nrfiles) lineoffset=1+nrfiles; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - - } -#endif -} - -enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file }; -void MainMenu::showMainMenu() -{ - //if(int(encoderpos/lcdslow)!=int(lastencoderpos/lcdslow)) - // force_lcd_update=true; -#ifndef ULTIPANEL - force_lcd_update=false; -#endif - //Serial.println((int)activeline); - if(force_lcd_update) - clear(); - for(short line=0;line=LCD_HEIGHT) activeline=LCD_HEIGHT-1; - if((encoderpos!=lastencoderpos)||force_lcd_update) - { - lcd.setCursor(0,activeline);lcd.print(activeline?' ':' '); - if(encoderpos<0) encoderpos=0; - if(encoderpos>3*lcdslow) encoderpos=3*lcdslow; - activeline=abs(encoderpos/lcdslow)%LCD_HEIGHT; - if(activeline<0) activeline=0; - if(activeline>=LCD_HEIGHT) activeline=LCD_HEIGHT-1; - lastencoderpos=encoderpos; - lcd.setCursor(0,activeline);lcd.print(activeline?'>':'\003'); - } - - - -} - -void MainMenu::update() -{ - static MainStatus oldstatus=Main_Menu; //init automatically causes foce_lcd_update=true - static long timeoutToStatus=0; - static bool oldcardstatus=false; -#ifdef CARDINSERTED - if((CARDINSERTED != oldcardstatus)) - { - force_lcd_update=true; - oldcardstatus=CARDINSERTED; - //Serial.println("SD CHANGE"); - if(CARDINSERTED) - { - initsd(); - lcd_status("Card inserted"); - } - else - { - sdactive=false; - lcd_status("Card removed"); - - } - } -#endif - - if(status!=oldstatus) - { - //Serial.println(status); - //clear(); - force_lcd_update=true; - encoderpos=0; - lineoffset=0; - - oldstatus=status; - } - if( (encoderpos!=lastencoderpos) || CLICKED) - timeoutToStatus=millis()+STATUSTIMEOUT; - - switch(status) - { - case Main_Status: - { - showStatus(); - if(CLICKED) - { - linechanging=false; - BLOCK - status=Main_Menu; - timeoutToStatus=millis()+STATUSTIMEOUT; - } - }break; - case Main_Menu: - { - showMainMenu(); - linechanging=false; - }break; - case Main_Prepare: - { - showPrepare(); - }break; - case Main_Control: - { - showControl(); - }break; - case Main_SD: - { - showSD(); - }break; - } - - if(timeoutToStatus=0)?'+':'-'; - xx=abs(xx); - conv[1]=(xx/1000)%10+'0'; - conv[2]=(xx/100)%10+'0'; - conv[3]=(xx/10)%10+'0'; - conv[4]='.'; - conv[5]=(xx)%10+'0'; - conv[6]=0; - return conv; -} - -char *itostr31(const int &xx) -{ - //sprintf(conv,"%5.1f",x); - conv[0]=(xx>=0)?'+':'-'; - conv[1]=(xx/1000)%10+'0'; - conv[2]=(xx/100)%10+'0'; - conv[3]=(xx/10)%10+'0'; - conv[4]='.'; - conv[5]=(xx)%10+'0'; - conv[6]=0; - return conv; -} -char *itostr3(const int &xx) -{ - conv[0]=(xx/100)%10+'0'; - conv[1]=(xx/10)%10+'0'; - conv[2]=(xx)%10+'0'; - conv[3]=0; - return conv; -} - -char *itostr4(const int &xx) -{ - conv[0]=(xx/1000)%10+'0'; - conv[1]=(xx/100)%10+'0'; - conv[2]=(xx/10)%10+'0'; - conv[3]=(xx)%10+'0'; - conv[4]=0; - return conv; -} - -/// convert float to string with +1234.5 format -char *ftostr51(const float &x) -{ - int xx=x*10; - conv[0]=(xx>=0)?'+':'-'; - xx=abs(xx); - conv[1]=(xx/10000)%10+'0'; - conv[2]=(xx/1000)%10+'0'; - conv[3]=(xx/100)%10+'0'; - conv[4]=(xx/10)%10+'0'; - conv[5]='.'; - conv[6]=(xx)%10+'0'; - conv[7]=0; - return conv; -} - -char *fillto(int8_t n,char *c) -{ - static char ret[25]; - bool endfound=false; - for(int8_t i=0;i +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 + +unsigned long previous_millis_lcd=0; + + + +volatile char buttons=0; //the last checked buttons in a bit array. +int encoderpos=0; +short lastenc=0; +#ifdef NEWPANEL + long blocking=0; +#else + long blocking[8]={0,0,0,0,0,0,0,0}; +#endif +MainMenu menu; + +void lcd_status(const char* message) +{ + strncpy(messagetext,message,LCD_WIDTH); +} + +void clear() +{ + //lcd.setCursor(0,0); + lcd.clear(); + //delay(1); + // lcd.begin(LCD_WIDTH,LCD_HEIGHT); + //lcd_init(); +} +long previous_millis_buttons=0; + +void lcd_init() +{ + //beep(); + byte Degree[8] = + { + B01100, + B10010, + B10010, + B01100, + B00000, + B00000, + B00000, + B00000 + }; + byte Thermometer[8] = + { + B00100, + B01010, + B01010, + B01010, + B01010, + B10001, + B10001, + B01110 + }; + byte uplevel[8]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris + byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + lcd.createChar(1,Degree); + lcd.createChar(2,Thermometer); + lcd.createChar(3,uplevel); + lcd.createChar(4,refresh); + LCD_MESSAGE(fillto(LCD_WIDTH,"UltiMarlin ready.")); +} + + +void beep() +{ + //return; +#ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<20;i++){ + WRITE(BEEPER,HIGH); + delay(5); + WRITE(BEEPER,LOW); + delay(5); + } +#endif +} + +void beepshort() +{ + //return; +#ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<10;i++){ + WRITE(BEEPER,HIGH); + delay(3); + WRITE(BEEPER,LOW); + delay(3); + } +#endif +} +void lcd_status() +{ +#ifdef ULTIPANEL + static uint8_t oldbuttons=0; + static long previous_millis_buttons=0; + static long previous_lcdinit=0; +// buttons_check(); // Done in temperature interrupt + //previous_millis_buttons=millis(); + + if((buttons==oldbuttons) && ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; + oldbuttons=buttons; +#else + + if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; +#endif + + previous_millis_lcd=millis(); + menu.update(); +} +#ifdef ULTIPANEL +void buttons_init() +{ +#ifdef NEWPANEL + pinMode(BTN_EN1,INPUT); + pinMode(BTN_EN2,INPUT); + pinMode(BTN_ENC,INPUT); + pinMode(SDCARDDETECT,INPUT); + WRITE(BTN_EN1,HIGH); + WRITE(BTN_EN2,HIGH); + WRITE(BTN_ENC,HIGH); + WRITE(SDCARDDETECT,HIGH); +#else + pinMode(SHIFT_CLK,OUTPUT); + pinMode(SHIFT_LD,OUTPUT); + pinMode(SHIFT_EN,OUTPUT); + pinMode(SHIFT_OUT,INPUT); + WRITE(SHIFT_OUT,HIGH); + WRITE(SHIFT_LD,HIGH); + WRITE(SHIFT_EN,LOW); +#endif +} + + +void buttons_check() +{ +// volatile static bool busy=false; +// if(busy) +// return; +// busy=true; + +#ifdef NEWPANEL + uint8_t newbutton=0; + if(READ(BTN_EN1)==0) newbutton|=EN_A; + if(READ(BTN_EN2)==0) newbutton|=EN_B; + if((blocking>1; + if(READ(SHIFT_OUT)) + newbutton|=(1<<7); + WRITE(SHIFT_CLK,HIGH); + WRITE(SHIFT_CLK,LOW); + } + buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 +#endif + char enc=0; + if(buttons&EN_A) + enc|=(1<<0); + if(buttons&EN_B) + enc|=(1<<1); + if(enc!=lastenc) + { + switch(enc) + { + case encrot0: + if(lastenc==encrot3) + encoderpos++; + else if(lastenc==encrot1) + encoderpos--; + break; + case encrot1: + if(lastenc==encrot0) + encoderpos++; + else if(lastenc==encrot2) + encoderpos--; + break; + case encrot2: + if(lastenc==encrot1) + encoderpos++; + else if(lastenc==encrot3) + encoderpos--; + break; + case encrot3: + if(lastenc==encrot2) + encoderpos++; + else if(lastenc==encrot0) + encoderpos--; + break; + default: + ; + } + } + lastenc=enc; +// busy=false; +} + +#endif + +MainMenu::MainMenu() +{ + status=Main_Status; + displayStartingRow=0; + activeline=0; + force_lcd_update=true; +#ifdef ULTIPANEL + buttons_init(); +#endif + lcd_init(); + linechanging=false; +} + +extern volatile bool feedmultiplychanged; + +void MainMenu::showStatus() +{ +#if LCD_HEIGHT==4 + static int oldcurrentraw=-1; + static int oldtargetraw=-1; + //force_lcd_update=true; + if(force_lcd_update||feedmultiplychanged) //initial display of content + { + feedmultiplychanged=false; + encoderpos=feedmultiply; + clear(); + lcd.setCursor(0,0);lcd.print("\002123/567\001 "); +#if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + lcd.setCursor(10,0);lcd.print("B123/567\001 "); +#endif + } + + + if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); + oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + } + if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + } + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + static int oldcurrentbedraw=-1; + static int oldtargetbedraw=-1; + if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_bed_raw))); + oldcurrentraw=current_raw[TEMPSENSOR_BED]; + } + if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_bed_raw))); + oldtargetraw=target_bed_raw; + } + #endif + //starttime=2; + static uint16_t oldtime=0; + if(starttime!=0) + { + lcd.setCursor(0,1); + uint16_t time=millis()/60000-starttime/60000; + + if(starttime!=oldtime) + { + lcd.print(itostr2(time/60));lcd.print("h ");lcd.print(itostr2(time%60));lcd.print("m"); + oldtime=time; + } + } + static int oldzpos=0; + int currentz=current_position[2]*10; + if((currentz!=oldzpos)||force_lcd_update) + { + lcd.setCursor(10,1); + lcd.print("Z:");lcd.print(itostr31(currentz)); + oldzpos=currentz; + } + static int oldfeedmultiply=0; + int curfeedmultiply=feedmultiply; + if(encoderpos!=curfeedmultiply||force_lcd_update) + { + curfeedmultiply=encoderpos; + if(curfeedmultiply<10) + curfeedmultiply=10; + if(curfeedmultiply>999) + curfeedmultiply=999; + feedmultiply=curfeedmultiply; + encoderpos=curfeedmultiply; + } + if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) + { + oldfeedmultiply=curfeedmultiply; + lcd.setCursor(0,2); + lcd.print(itostr3(curfeedmultiply));lcd.print("% "); + } + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(fillto(LCD_WIDTH,messagetext)); + messagetext[0]='\0'; + } +#else //smaller LCDS---------------------------------- + static int oldcurrentraw=-1; + static int oldtargetraw=-1; + if(force_lcd_update) //initial display of content + { + encoderpos=feedmultiply; + lcd.setCursor(0,0);lcd.print("\002123/567\001 "); + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + lcd.setCursor(10,0);lcd.print("B123/567\001 "); + #endif + } + + + if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); + oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + } + if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + } + + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(fillto(LCD_WIDTH,messagetext)); + messagetext[0]='\0'; + } + +#endif +} + +enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; + +void MainMenu::showPrepare() +{ + uint8_t line=0; + if(lastlineoffset!=lineoffset) + { + force_lcd_update=true; + clear(); + } + for(uint8_t i=lineoffset;i3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(ItemP_disstep+1-LCD_HEIGHT)) + lineoffset=ItemP_disstep+1-LCD_HEIGHT; + force_lcd_update=true; + } + //encoderpos=encoderpos%LCD_HEIGHT; + lastencoderpos=encoderpos; + activeline=encoderpos/lcdslow; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + } +} +enum { + ItemC_exit, ItemC_nozzle, + ItemC_PID_P,ItemC_PID_I,ItemC_PID_D,ItemC_PID_C, + ItemC_fan, + ItemC_acc, ItemC_xyjerk, + ItemC_vmaxx, ItemC_vmaxy, ItemC_vmaxz, ItemC_vmaxe, + ItemC_vtravmin,ItemC_vmin, + ItemC_amaxx, ItemC_amaxy, ItemC_amaxz, ItemC_amaxe, + ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe +}; + +void MainMenu::showControl() +{ + uint8_t line=0; + if((lastlineoffset!=lineoffset)||force_lcd_update) + { + force_lcd_update=true; + clear(); + } + for(uint8_t i=lineoffset;i260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_fan: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Fan speed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + } + + if((activeline==line) ) + { + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=fanpwm; + } + else + { + fanpwm = constrain(encoderpos,0,255); + encoderpos=fanpwm; + analogWrite(FAN_PIN, fanpwm); + + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_acc: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Acc:"); + lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)acceleration/100; + } + else + { + acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_xyjerk: //max_xy_jerk + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vxy-jerk: "); + lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_xy_jerk/60; + } + else + { + max_xy_jerk= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_PID_P: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-P: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kp)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kp/5; + } + else + { + Kp= encoderpos*5; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>9990/5) encoderpos=9990/5; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + } + }break; + case ItemC_PID_I: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-I: "); + lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(Ki*10); + } + else + { + Ki= encoderpos/10.; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); + } + } + }break; + case ItemC_PID_D: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-D: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kd)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kd/5; + } + else + { + Kd= encoderpos*5; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990/5) encoderpos=9990/5; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + } + }break; + + + + case ItemC_PID_C: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-C: "); + lcd.setCursor(13,line);lcd.print(itostr3(Kc)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kc; + } + else + { + Kc= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_vmaxx: + case ItemC_vmaxy: + case ItemC_vmaxz: + case ItemC_vmaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vmax "); + if(i==ItemC_vmaxx)lcd.print("x:"); + if(i==ItemC_vmaxy)lcd.print("y:"); + if(i==ItemC_vmaxz)lcd.print("z:"); + if(i==ItemC_vmaxe)lcd.print("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemC_vmaxx]/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_feedrate[i-ItemC_vmaxx]/60; + } + else + { + max_feedrate[i-ItemC_vmaxx]= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_vmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vmin:"); + lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(minimumfeedrate/60.); + } + else + { + minimumfeedrate= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_vtravmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" VTrav min:"); + lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)mintravelfeedrate/60; + } + else + { + mintravelfeedrate= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_amaxx: + case ItemC_amaxy: + case ItemC_amaxz: + case ItemC_amaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Amax "); + if(i==ItemC_amaxx)lcd.print("x:"); + if(i==ItemC_amaxy)lcd.print("y:"); + if(i==ItemC_amaxz)lcd.print("z:"); + if(i==ItemC_amaxe)lcd.print("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100; + } + else + { + max_acceleration_units_per_sq_second[i-ItemC_amaxx]= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_aret://float retract_acceleration = 7000; + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" A-retract:"); + lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)retract_acceleration/100; + } + else + { + retract_acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<10) encoderpos=10; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_esteps://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Esteps/mm:"); + lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)axis_steps_per_unit[3]; + } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + } + }break; + case ItemC_store: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Store EPROM"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + StoreSettings(); + } + }break; + case ItemC_load: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Load EPROM"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + RetrieveSettings(); + } + }break; + case ItemC_failsafe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Restore Failsafe"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + RetrieveSettings(true); + } + }break; + default: + break; + } + line++; + } + lastlineoffset=lineoffset; + + if(!linechanging && ((encoderpos/lcdslow!=lastencoderpos/lcdslow)||force_lcd_update)) + { + + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?' ':' '); + + if(encoderpos<0) + { + lineoffset--; + if(lineoffset<0) + lineoffset=0; + encoderpos=0; + force_lcd_update=true; + } + if(encoderpos/lcdslow>3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(ItemC_failsafe+1-LCD_HEIGHT)) + lineoffset=ItemC_failsafe+1-LCD_HEIGHT; + force_lcd_update=true; + } + //encoderpos=encoderpos%LCD_HEIGHT; + lastencoderpos=encoderpos; + activeline=encoderpos/lcdslow; + if(activeline>3) activeline=3; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + } +} + +#include "SdFat.h" + +void MainMenu::getfilename(const uint8_t nr) +{ +#ifdef SDSUPPORT + dir_t p; + root.rewind(); + uint8_t cnt=0; + filename[0]='\0'; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + if(cnt++!=nr) continue; + //Serial.println((char*)p.name); + uint8_t writepos=0; + for (uint8_t i = 0; i < 11; i++) + { + if (p.name[i] == ' ') continue; + if (i == 8) { + filename[writepos++]='.'; + } + filename[writepos++]=p.name[i]; + } + filename[writepos++]=0; + } +#endif +} + +uint8_t getnrfilenames() +{ +#ifdef SDSUPPORT + dir_t p; + root.rewind(); + uint8_t cnt=0; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + cnt++; + } + return cnt; +#endif +} + +void MainMenu::showSD() +{ + +#ifdef SDSUPPORT + uint8_t line=0; + + if(lastlineoffset!=lineoffset) + { + force_lcd_update=true; + } + static uint8_t nrfiles=0; + if(force_lcd_update) + { + clear(); + if(sdactive) + { + nrfiles=getnrfilenames(); + } + else + { + nrfiles=0; + lineoffset=0; + } + //Serial.print("Nr files:"); Serial.println((int)nrfiles); + } + + for(int8_t i=lineoffset;i3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(1+nrfiles+1-LCD_HEIGHT)) + lineoffset=1+nrfiles+1-LCD_HEIGHT; + force_lcd_update=true; + + } + lastencoderpos=encoderpos; + activeline=encoderpos; + if(activeline>3) + { + activeline=3; + } + if(activeline<0) + { + activeline=0; + } + if(activeline>1+nrfiles) activeline=1+nrfiles; + if(lineoffset>1+nrfiles) lineoffset=1+nrfiles; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + + } +#endif +} + +enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file }; +void MainMenu::showMainMenu() +{ + //if(int(encoderpos/lcdslow)!=int(lastencoderpos/lcdslow)) + // force_lcd_update=true; +#ifndef ULTIPANEL + force_lcd_update=false; +#endif + //Serial.println((int)activeline); + if(force_lcd_update) + clear(); + for(short line=0;line=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + if((encoderpos!=lastencoderpos)||force_lcd_update) + { + lcd.setCursor(0,activeline);lcd.print(activeline?' ':' '); + if(encoderpos<0) encoderpos=0; + if(encoderpos>3*lcdslow) encoderpos=3*lcdslow; + activeline=abs(encoderpos/lcdslow)%LCD_HEIGHT; + if(activeline<0) activeline=0; + if(activeline>=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + lastencoderpos=encoderpos; + lcd.setCursor(0,activeline);lcd.print(activeline?'>':'\003'); + } + + + +} + +void MainMenu::update() +{ + static MainStatus oldstatus=Main_Menu; //init automatically causes foce_lcd_update=true + static long timeoutToStatus=0; + static bool oldcardstatus=false; +#ifdef CARDINSERTED + if((CARDINSERTED != oldcardstatus)) + { + force_lcd_update=true; + oldcardstatus=CARDINSERTED; + //Serial.println("SD CHANGE"); + if(CARDINSERTED) + { + initsd(); + lcd_status("Card inserted"); + } + else + { + sdactive=false; + lcd_status("Card removed"); + + } + } +#endif + + if(status!=oldstatus) + { + //Serial.println(status); + //clear(); + force_lcd_update=true; + encoderpos=0; + lineoffset=0; + + oldstatus=status; + } + if( (encoderpos!=lastencoderpos) || CLICKED) + timeoutToStatus=millis()+STATUSTIMEOUT; + + switch(status) + { + case Main_Status: + { + showStatus(); + if(CLICKED) + { + linechanging=false; + BLOCK + status=Main_Menu; + timeoutToStatus=millis()+STATUSTIMEOUT; + } + }break; + case Main_Menu: + { + showMainMenu(); + linechanging=false; + }break; + case Main_Prepare: + { + showPrepare(); + }break; + case Main_Control: + { + showControl(); + }break; + case Main_SD: + { + showSD(); + }break; + } + + if(timeoutToStatus=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} + +char *itostr31(const int &xx) +{ + //sprintf(conv,"%5.1f",x); + conv[0]=(xx>=0)?'+':'-'; + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} +char *itostr3(const int &xx) +{ + conv[0]=(xx/100)%10+'0'; + conv[1]=(xx/10)%10+'0'; + conv[2]=(xx)%10+'0'; + conv[3]=0; + return conv; +} + +char *itostr4(const int &xx) +{ + conv[0]=(xx/1000)%10+'0'; + conv[1]=(xx/100)%10+'0'; + conv[2]=(xx/10)%10+'0'; + conv[3]=(xx)%10+'0'; + conv[4]=0; + return conv; +} + +/// convert float to string with +1234.5 format +char *ftostr51(const float &x) +{ + int xx=x*10; + conv[0]=(xx>=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/10000)%10+'0'; + conv[2]=(xx/1000)%10+'0'; + conv[3]=(xx/100)%10+'0'; + conv[4]=(xx/10)%10+'0'; + conv[5]='.'; + conv[6]=(xx)%10+'0'; + conv[7]=0; + return conv; +} + +char *fillto(int8_t n,char *c) +{ + static char ret[25]; + bool endfound=false; + for(int8_t i=0;i Board -> Sanguino +Select Tools -> Board -> Arduino Mega 2560 Select the correct serial port in Tools ->Serial Port Open Marlin.pde -Change the printer specific setting in Configuration.h to the correct values. - -The following values are the most important: - - float axis_steps_per_unit[].... // Set the correct steps / mm in the corresponding field - - const bool ENDSTOPS_INVERTING = false; // Change if only positive moves are executed - - #define INVERT_x_DIR true // Change if the motor direction is wrong +Click the Verify/Compile button Click the Upload button If all goes well the firmware is uploading -Start pronterface - -Select the correct Serial Port. Type 250000 in the baudrate field. -Press the Connect button - -=============================================================================================== -Known issues - -On some systems we get compilation errors. - -This is caused by the "wiring_serial.c" and "wiring.c". -The simple fix is to delete these files but this may have a performance impact. - -The best workaround is to move these files to sanguino directory. -(".../arduino-0018/hardware/Sanguino/cores/arduino/" on windows systems) - +Start Ultimaker's Custom RepG 25 +Make sure Show Experimental Profiles is enabled in Preferences +Select Sprinter as the Driver +Press the Connect button. +KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z +That's ok. Enjoy Silky Smooth Printing. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..6cab9fa526 --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +WARNING: THIS IN A PROCESS OF HEAVY OVERWORKING. +DO NOT USE THIS ON YOUR MACHINE UNTIL FURTHER NOTICE!!! + +=========================================== + +This RepRap firmware is a mashup between Sprinter, grbl and many original parts. + +Derived from Sprinter and Grbl by Erik van der Zalm. +Sprinters lead developers are Kliment and caru. +Grbls lead developer is Simen Svale Skogsrud. +Some features have been added by and configuration has been added by: +Bernhard Kubicek, Matthijs Keuper, Bradley Feldman, and others... + + +Features: + - Interrupt based movement with real linear acceleration + - High steprate + - Look ahead (Keep the speed high when possible. High cornering speed) + - Interrupt based temperature protection + - preliminary support for Matthew Roberts advance algorithm + For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html + - Full endstop support + - Simple LCD support (16x2) + - SD Card support + - Provisions for Bernhard Kubicek's new hardware control console and 20x4 lcd + +This firmware is optimized for Ultimaker's gen6 electronics (including the Ultimaker 1.5.x daughterboard and Arduino Mega 2560). + +The default baudrate is 115200. + + +======================================================================================== + +Configuring and compilation + + +Install the latest arduino software IDE/toolset (currently 0022) + http://www.arduino.cc/en/Main/Software + +Install Ultimaker's RepG 25 build + http://software.ultimaker.com +(or alternatively install Kliment's printrun/pronterface https://github.com/kliment/Printrun_) + +Copy the Ultimaker Marlin firmware + https:/github.com/bkubicek/Marlin + (Use the download button) + +Start the arduino IDE. +Select Tools -> Board -> Arduino Mega 2560 +Select the correct serial port in Tools ->Serial Port +Open Marlin.pde + +Click the Verify/Compile button + +Click the Upload button +If all goes well the firmware is uploading + +Start Ultimaker's Custom RepG 25 +Make sure Show Experimental Profiles is enabled in Preferences +Select Sprinter as the Driver + +Press the Connect button. + +KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z + +That's ok. Enjoy Silky Smooth Printing. + + + diff --git a/merging still needs.txt b/merging still needs.txt new file mode 100644 index 0000000000..2d369c968a --- /dev/null +++ b/merging still needs.txt @@ -0,0 +1,58 @@ +files to compare manually: +planner.cpp +stepper.cpp +temperature.cpp + +--- +things that changed: +* planner.cpp +estimate_acc_distance now works with floats. +in calculate_trapezoid:for_block + long acceleration_rate=(long)((float)acceleration*8.388608) is gone + so is block_>acceleration_rate +void planner_reverse_pass: + some stuff I don't understand right now changed +in planner_forward_pass: + done: BLOCK_BUFFER_SIZE is now necessarily power of 2 (aka 8 16, 32). Inportant to document this somewhere. +no more inline in void plan_discard_current_block() +no more inline in plan_get_current_block() +in plan_buffer_line(...) + the long target[4]; and calculations of thoose should go after the while(block_buffer_tail==..). if the axis_steps_per_unit are changed from the gcode (M92) the calculation for the currently planned buffer move will be corrupt, because Target is calculated with one value, and the stuff afterwards with another. At least this solved the problem I had with the M92 E* changes in the code. Very sure about this, I took me 20min to find this as the solution for the bug I was hunting. +around if(feed_rate!true+return? +done #define K1 0.95 maybe in the configuration.h? +semi-done: PID-C checking needed. Untested but added. +---- + +still needed to finish the merge, before testin! + + manage_heater + ISR + movement planner + +TODO: + +remove traveling at maxpseed +remove Simplelcd + +remove DEBUG_STEPS? + +block_t +pid_dt ->0.1 whats the changes to the PID, checking needed + + +---- +second merge saturday morning: +done: PID_dt->0.1 \ No newline at end of file From 40e80816235739064fcc7fd74228c9c225387caf Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 5 Nov 2011 14:19:57 +0100 Subject: [PATCH 006/228] changed end of line to windows, which seems to be the majority of developers main platform. --- Marlin/FatStructs.h | 836 +++--- Marlin/Sd2Card.cpp | 1286 ++++----- Marlin/Sd2Card.h | 466 ++-- Marlin/Sd2PinMap.h | 706 ++--- Marlin/SdFat.h | 1094 ++++---- Marlin/SdFatUtil.h | 140 +- Marlin/SdFatmainpage.h | 404 +-- Marlin/SdFile.cpp | 2504 +++++++++--------- Marlin/SdInfo.h | 464 ++-- Marlin/SdVolume.cpp | 590 ++--- Marlin/fastio.h | 5116 ++++++++++++++++++------------------ Marlin/pins.h | 1140 ++++---- Marlin/planner.cpp | 1154 ++++---- Marlin/speed_lookuptable.h | 150 +- Marlin/stepper.cpp | 1184 ++++----- Marlin/streaming.h | 168 +- Marlin/temperature.cpp | 934 +++---- Marlin/thermistortables.h | 820 +++--- Marlin/ultralcd.h | 310 +-- README | 128 +- README.md | 138 +- merging still needs.txt | 114 +- 22 files changed, 9923 insertions(+), 9923 deletions(-) diff --git a/Marlin/FatStructs.h b/Marlin/FatStructs.h index 5713467cec..f5bdaa5946 100644 --- a/Marlin/FatStructs.h +++ b/Marlin/FatStructs.h @@ -1,418 +1,418 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#ifndef FatStructs_h -#define FatStructs_h -/** - * \file - * FAT file structures - */ -/* - * mostly from Microsoft document fatgen103.doc - * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx - */ -//------------------------------------------------------------------------------ -/** Value for byte 510 of boot block or MBR */ -uint8_t const BOOTSIG0 = 0X55; -/** Value for byte 511 of boot block or MBR */ -uint8_t const BOOTSIG1 = 0XAA; -//------------------------------------------------------------------------------ -/** - * \struct partitionTable - * \brief MBR partition table entry - * - * A partition table entry for a MBR formatted storage device. - * The MBR partition table has four entries. - */ -struct partitionTable { - /** - * Boot Indicator . Indicates whether the volume is the active - * partition. Legal values include: 0X00. Do not use for booting. - * 0X80 Active partition. - */ - uint8_t boot; - /** - * Head part of Cylinder-head-sector address of the first block in - * the partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t beginHead; - /** - * Sector part of Cylinder-head-sector address of the first block in - * the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned beginSector : 6; - /** High bits cylinder for first block in partition. */ - unsigned beginCylinderHigh : 2; - /** - * Combine beginCylinderLow with beginCylinderHigh. Legal values - * are 0-1023. Only used in old PC BIOS. - */ - uint8_t beginCylinderLow; - /** - * Partition type. See defines that begin with PART_TYPE_ for - * some Microsoft partition types. - */ - uint8_t type; - /** - * head part of cylinder-head-sector address of the last sector in the - * partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t endHead; - /** - * Sector part of cylinder-head-sector address of the last sector in - * the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned endSector : 6; - /** High bits of end cylinder */ - unsigned endCylinderHigh : 2; - /** - * Combine endCylinderLow with endCylinderHigh. Legal values - * are 0-1023. Only used in old PC BIOS. - */ - uint8_t endCylinderLow; - /** Logical block address of the first block in the partition. */ - uint32_t firstSector; - /** Length of the partition, in blocks. */ - uint32_t totalSectors; -}; -/** Type name for partitionTable */ -typedef struct partitionTable part_t; -//------------------------------------------------------------------------------ -/** - * \struct masterBootRecord - * - * \brief Master Boot Record - * - * The first block of a storage device that is formatted with a MBR. - */ -struct masterBootRecord { - /** Code Area for master boot program. */ - uint8_t codeArea[440]; - /** Optional WindowsNT disk signature. May contain more boot code. */ - uint32_t diskSignature; - /** Usually zero but may be more boot code. */ - uint16_t usuallyZero; - /** Partition tables. */ - part_t part[4]; - /** First MBR signature byte. Must be 0X55 */ - uint8_t mbrSig0; - /** Second MBR signature byte. Must be 0XAA */ - uint8_t mbrSig1; -}; -/** Type name for masterBootRecord */ -typedef struct masterBootRecord mbr_t; -//------------------------------------------------------------------------------ -/** - * \struct biosParmBlock - * - * \brief BIOS parameter block - * - * The BIOS parameter block describes the physical layout of a FAT volume. - */ -struct biosParmBlock { - /** - * Count of bytes per sector. This value may take on only the - * following values: 512, 1024, 2048 or 4096 - */ - uint16_t bytesPerSector; - /** - * Number of sectors per allocation unit. This value must be a - * power of 2 that is greater than 0. The legal values are - * 1, 2, 4, 8, 16, 32, 64, and 128. - */ - uint8_t sectorsPerCluster; - /** - * Number of sectors before the first FAT. - * This value must not be zero. - */ - uint16_t reservedSectorCount; - /** The count of FAT data structures on the volume. This field should - * always contain the value 2 for any FAT volume of any type. - */ - uint8_t fatCount; - /** - * For FAT12 and FAT16 volumes, this field contains the count of - * 32-byte directory entries in the root directory. For FAT32 volumes, - * this field must be set to 0. For FAT12 and FAT16 volumes, this - * value should always specify a count that when multiplied by 32 - * results in a multiple of bytesPerSector. FAT16 volumes should - * use the value 512. - */ - uint16_t rootDirEntryCount; - /** - * This field is the old 16-bit total count of sectors on the volume. - * This count includes the count of all sectors in all four regions - * of the volume. This field can be 0; if it is 0, then totalSectors32 - * must be non-zero. For FAT32 volumes, this field must be 0. For - * FAT12 and FAT16 volumes, this field contains the sector count, and - * totalSectors32 is 0 if the total sector count fits - * (is less than 0x10000). - */ - uint16_t totalSectors16; - /** - * This dates back to the old MS-DOS 1.x media determination and is - * no longer usually used for anything. 0xF8 is the standard value - * for fixed (non-removable) media. For removable media, 0xF0 is - * frequently used. Legal values are 0xF0 or 0xF8-0xFF. - */ - uint8_t mediaType; - /** - * Count of sectors occupied by one FAT on FAT12/FAT16 volumes. - * On FAT32 volumes this field must be 0, and sectorsPerFat32 - * contains the FAT size count. - */ - uint16_t sectorsPerFat16; - /** Sectors per track for interrupt 0x13. Not used otherwise. */ - uint16_t sectorsPerTrtack; - /** Number of heads for interrupt 0x13. Not used otherwise. */ - uint16_t headCount; - /** - * Count of hidden sectors preceding the partition that contains this - * FAT volume. This field is generally only relevant for media - * visible on interrupt 0x13. - */ - uint32_t hidddenSectors; - /** - * This field is the new 32-bit total count of sectors on the volume. - * This count includes the count of all sectors in all four regions - * of the volume. This field can be 0; if it is 0, then - * totalSectors16 must be non-zero. - */ - uint32_t totalSectors32; - /** - * Count of sectors occupied by one FAT on FAT32 volumes. - */ - uint32_t sectorsPerFat32; - /** - * This field is only defined for FAT32 media and does not exist on - * FAT12 and FAT16 media. - * Bits 0-3 -- Zero-based number of active FAT. - * Only valid if mirroring is disabled. - * Bits 4-6 -- Reserved. - * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. - * -- 1 means only one FAT is active; it is the one referenced in bits 0-3. - * Bits 8-15 -- Reserved. - */ - uint16_t fat32Flags; - /** - * FAT32 version. High byte is major revision number. - * Low byte is minor revision number. Only 0.0 define. - */ - uint16_t fat32Version; - /** - * Cluster number of the first cluster of the root directory for FAT32. - * This usually 2 but not required to be 2. - */ - uint32_t fat32RootCluster; - /** - * Sector number of FSINFO structure in the reserved area of the - * FAT32 volume. Usually 1. - */ - uint16_t fat32FSInfo; - /** - * If non-zero, indicates the sector number in the reserved area - * of the volume of a copy of the boot record. Usually 6. - * No value other than 6 is recommended. - */ - uint16_t fat32BackBootBlock; - /** - * Reserved for future expansion. Code that formats FAT32 volumes - * should always set all of the bytes of this field to 0. - */ - uint8_t fat32Reserved[12]; -}; -/** Type name for biosParmBlock */ -typedef struct biosParmBlock bpb_t; -//------------------------------------------------------------------------------ -/** - * \struct fat32BootSector - * - * \brief Boot sector for a FAT16 or FAT32 volume. - * - */ -struct fat32BootSector { - /** X86 jmp to boot program */ - uint8_t jmpToBootCode[3]; - /** informational only - don't depend on it */ - char oemName[8]; - /** BIOS Parameter Block */ - bpb_t bpb; - /** for int0x13 use value 0X80 for hard drive */ - uint8_t driveNumber; - /** used by Windows NT - should be zero for FAT */ - uint8_t reserved1; - /** 0X29 if next three fields are valid */ - uint8_t bootSignature; - /** usually generated by combining date and time */ - uint32_t volumeSerialNumber; - /** should match volume label in root dir */ - char volumeLabel[11]; - /** informational only - don't depend on it */ - char fileSystemType[8]; - /** X86 boot code */ - uint8_t bootCode[420]; - /** must be 0X55 */ - uint8_t bootSectorSig0; - /** must be 0XAA */ - uint8_t bootSectorSig1; -}; -//------------------------------------------------------------------------------ -// End Of Chain values for FAT entries -/** FAT16 end of chain value used by Microsoft. */ -uint16_t const FAT16EOC = 0XFFFF; -/** Minimum value for FAT16 EOC. Use to test for EOC. */ -uint16_t const FAT16EOC_MIN = 0XFFF8; -/** FAT32 end of chain value used by Microsoft. */ -uint32_t const FAT32EOC = 0X0FFFFFFF; -/** Minimum value for FAT32 EOC. Use to test for EOC. */ -uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; -/** Mask a for FAT32 entry. Entries are 28 bits. */ -uint32_t const FAT32MASK = 0X0FFFFFFF; - -/** Type name for fat32BootSector */ -typedef struct fat32BootSector fbs_t; -//------------------------------------------------------------------------------ -/** - * \struct directoryEntry - * \brief FAT short directory entry - * - * Short means short 8.3 name, not the entry size. - * - * Date Format. A FAT directory entry date stamp is a 16-bit field that is - * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the - * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the - * 16-bit word): - * - * Bits 9-15: Count of years from 1980, valid value range 0-127 - * inclusive (1980-2107). - * - * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. - * - * Bits 0-4: Day of month, valid value range 1-31 inclusive. - * - * Time Format. A FAT directory entry time stamp is a 16-bit field that has - * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the - * 16-bit word, bit 15 is the MSB of the 16-bit word). - * - * Bits 11-15: Hours, valid value range 0-23 inclusive. - * - * Bits 5-10: Minutes, valid value range 0-59 inclusive. - * - * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). - * - * The valid time range is from Midnight 00:00:00 to 23:59:58. - */ -struct directoryEntry { - /** - * Short 8.3 name. - * The first eight bytes contain the file name with blank fill. - * The last three bytes contain the file extension with blank fill. - */ - uint8_t name[11]; - /** Entry attributes. - * - * The upper two bits of the attribute byte are reserved and should - * always be set to 0 when a file is created and never modified or - * looked at after that. See defines that begin with DIR_ATT_. - */ - uint8_t attributes; - /** - * Reserved for use by Windows NT. Set value to 0 when a file is - * created and never modify or look at it after that. - */ - uint8_t reservedNT; - /** - * The granularity of the seconds part of creationTime is 2 seconds - * so this field is a count of tenths of a second and its valid - * value range is 0-199 inclusive. (WHG note - seems to be hundredths) - */ - uint8_t creationTimeTenths; - /** Time file was created. */ - uint16_t creationTime; - /** Date file was created. */ - uint16_t creationDate; - /** - * Last access date. Note that there is no last access time, only - * a date. This is the date of last read or write. In the case of - * a write, this should be set to the same date as lastWriteDate. - */ - uint16_t lastAccessDate; - /** - * High word of this entry's first cluster number (always 0 for a - * FAT12 or FAT16 volume). - */ - uint16_t firstClusterHigh; - /** Time of last write. File creation is considered a write. */ - uint16_t lastWriteTime; - /** Date of last write. File creation is considered a write. */ - uint16_t lastWriteDate; - /** Low word of this entry's first cluster number. */ - uint16_t firstClusterLow; - /** 32-bit unsigned holding this file's size in bytes. */ - uint32_t fileSize; -}; -//------------------------------------------------------------------------------ -// Definitions for directory entries -// -/** Type name for directoryEntry */ -typedef struct directoryEntry dir_t; -/** escape for name[0] = 0XE5 */ -uint8_t const DIR_NAME_0XE5 = 0X05; -/** name[0] value for entry that is free after being "deleted" */ -uint8_t const DIR_NAME_DELETED = 0XE5; -/** name[0] value for entry that is free and no allocated entries follow */ -uint8_t const DIR_NAME_FREE = 0X00; -/** file is read-only */ -uint8_t const DIR_ATT_READ_ONLY = 0X01; -/** File should hidden in directory listings */ -uint8_t const DIR_ATT_HIDDEN = 0X02; -/** Entry is for a system file */ -uint8_t const DIR_ATT_SYSTEM = 0X04; -/** Directory entry contains the volume label */ -uint8_t const DIR_ATT_VOLUME_ID = 0X08; -/** Entry is for a directory */ -uint8_t const DIR_ATT_DIRECTORY = 0X10; -/** Old DOS archive bit for backup support */ -uint8_t const DIR_ATT_ARCHIVE = 0X20; -/** Test value for long name entry. Test is - (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ -uint8_t const DIR_ATT_LONG_NAME = 0X0F; -/** Test mask for long name entry */ -uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; -/** defined attribute bits */ -uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; -/** Directory entry is part of a long name */ -static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { - return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; -} -/** Mask for file/subdirectory tests */ -uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); -/** Directory entry is for a file */ -static inline uint8_t DIR_IS_FILE(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; -} -/** Directory entry is for a subdirectory */ -static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; -} -/** Directory entry is for a file or subdirectory */ -static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; -} -#endif // FatStructs_h +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef FatStructs_h +#define FatStructs_h +/** + * \file + * FAT file structures + */ +/* + * mostly from Microsoft document fatgen103.doc + * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx + */ +//------------------------------------------------------------------------------ +/** Value for byte 510 of boot block or MBR */ +uint8_t const BOOTSIG0 = 0X55; +/** Value for byte 511 of boot block or MBR */ +uint8_t const BOOTSIG1 = 0XAA; +//------------------------------------------------------------------------------ +/** + * \struct partitionTable + * \brief MBR partition table entry + * + * A partition table entry for a MBR formatted storage device. + * The MBR partition table has four entries. + */ +struct partitionTable { + /** + * Boot Indicator . Indicates whether the volume is the active + * partition. Legal values include: 0X00. Do not use for booting. + * 0X80 Active partition. + */ + uint8_t boot; + /** + * Head part of Cylinder-head-sector address of the first block in + * the partition. Legal values are 0-255. Only used in old PC BIOS. + */ + uint8_t beginHead; + /** + * Sector part of Cylinder-head-sector address of the first block in + * the partition. Legal values are 1-63. Only used in old PC BIOS. + */ + unsigned beginSector : 6; + /** High bits cylinder for first block in partition. */ + unsigned beginCylinderHigh : 2; + /** + * Combine beginCylinderLow with beginCylinderHigh. Legal values + * are 0-1023. Only used in old PC BIOS. + */ + uint8_t beginCylinderLow; + /** + * Partition type. See defines that begin with PART_TYPE_ for + * some Microsoft partition types. + */ + uint8_t type; + /** + * head part of cylinder-head-sector address of the last sector in the + * partition. Legal values are 0-255. Only used in old PC BIOS. + */ + uint8_t endHead; + /** + * Sector part of cylinder-head-sector address of the last sector in + * the partition. Legal values are 1-63. Only used in old PC BIOS. + */ + unsigned endSector : 6; + /** High bits of end cylinder */ + unsigned endCylinderHigh : 2; + /** + * Combine endCylinderLow with endCylinderHigh. Legal values + * are 0-1023. Only used in old PC BIOS. + */ + uint8_t endCylinderLow; + /** Logical block address of the first block in the partition. */ + uint32_t firstSector; + /** Length of the partition, in blocks. */ + uint32_t totalSectors; +}; +/** Type name for partitionTable */ +typedef struct partitionTable part_t; +//------------------------------------------------------------------------------ +/** + * \struct masterBootRecord + * + * \brief Master Boot Record + * + * The first block of a storage device that is formatted with a MBR. + */ +struct masterBootRecord { + /** Code Area for master boot program. */ + uint8_t codeArea[440]; + /** Optional WindowsNT disk signature. May contain more boot code. */ + uint32_t diskSignature; + /** Usually zero but may be more boot code. */ + uint16_t usuallyZero; + /** Partition tables. */ + part_t part[4]; + /** First MBR signature byte. Must be 0X55 */ + uint8_t mbrSig0; + /** Second MBR signature byte. Must be 0XAA */ + uint8_t mbrSig1; +}; +/** Type name for masterBootRecord */ +typedef struct masterBootRecord mbr_t; +//------------------------------------------------------------------------------ +/** + * \struct biosParmBlock + * + * \brief BIOS parameter block + * + * The BIOS parameter block describes the physical layout of a FAT volume. + */ +struct biosParmBlock { + /** + * Count of bytes per sector. This value may take on only the + * following values: 512, 1024, 2048 or 4096 + */ + uint16_t bytesPerSector; + /** + * Number of sectors per allocation unit. This value must be a + * power of 2 that is greater than 0. The legal values are + * 1, 2, 4, 8, 16, 32, 64, and 128. + */ + uint8_t sectorsPerCluster; + /** + * Number of sectors before the first FAT. + * This value must not be zero. + */ + uint16_t reservedSectorCount; + /** The count of FAT data structures on the volume. This field should + * always contain the value 2 for any FAT volume of any type. + */ + uint8_t fatCount; + /** + * For FAT12 and FAT16 volumes, this field contains the count of + * 32-byte directory entries in the root directory. For FAT32 volumes, + * this field must be set to 0. For FAT12 and FAT16 volumes, this + * value should always specify a count that when multiplied by 32 + * results in a multiple of bytesPerSector. FAT16 volumes should + * use the value 512. + */ + uint16_t rootDirEntryCount; + /** + * This field is the old 16-bit total count of sectors on the volume. + * This count includes the count of all sectors in all four regions + * of the volume. This field can be 0; if it is 0, then totalSectors32 + * must be non-zero. For FAT32 volumes, this field must be 0. For + * FAT12 and FAT16 volumes, this field contains the sector count, and + * totalSectors32 is 0 if the total sector count fits + * (is less than 0x10000). + */ + uint16_t totalSectors16; + /** + * This dates back to the old MS-DOS 1.x media determination and is + * no longer usually used for anything. 0xF8 is the standard value + * for fixed (non-removable) media. For removable media, 0xF0 is + * frequently used. Legal values are 0xF0 or 0xF8-0xFF. + */ + uint8_t mediaType; + /** + * Count of sectors occupied by one FAT on FAT12/FAT16 volumes. + * On FAT32 volumes this field must be 0, and sectorsPerFat32 + * contains the FAT size count. + */ + uint16_t sectorsPerFat16; + /** Sectors per track for interrupt 0x13. Not used otherwise. */ + uint16_t sectorsPerTrtack; + /** Number of heads for interrupt 0x13. Not used otherwise. */ + uint16_t headCount; + /** + * Count of hidden sectors preceding the partition that contains this + * FAT volume. This field is generally only relevant for media + * visible on interrupt 0x13. + */ + uint32_t hidddenSectors; + /** + * This field is the new 32-bit total count of sectors on the volume. + * This count includes the count of all sectors in all four regions + * of the volume. This field can be 0; if it is 0, then + * totalSectors16 must be non-zero. + */ + uint32_t totalSectors32; + /** + * Count of sectors occupied by one FAT on FAT32 volumes. + */ + uint32_t sectorsPerFat32; + /** + * This field is only defined for FAT32 media and does not exist on + * FAT12 and FAT16 media. + * Bits 0-3 -- Zero-based number of active FAT. + * Only valid if mirroring is disabled. + * Bits 4-6 -- Reserved. + * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. + * -- 1 means only one FAT is active; it is the one referenced in bits 0-3. + * Bits 8-15 -- Reserved. + */ + uint16_t fat32Flags; + /** + * FAT32 version. High byte is major revision number. + * Low byte is minor revision number. Only 0.0 define. + */ + uint16_t fat32Version; + /** + * Cluster number of the first cluster of the root directory for FAT32. + * This usually 2 but not required to be 2. + */ + uint32_t fat32RootCluster; + /** + * Sector number of FSINFO structure in the reserved area of the + * FAT32 volume. Usually 1. + */ + uint16_t fat32FSInfo; + /** + * If non-zero, indicates the sector number in the reserved area + * of the volume of a copy of the boot record. Usually 6. + * No value other than 6 is recommended. + */ + uint16_t fat32BackBootBlock; + /** + * Reserved for future expansion. Code that formats FAT32 volumes + * should always set all of the bytes of this field to 0. + */ + uint8_t fat32Reserved[12]; +}; +/** Type name for biosParmBlock */ +typedef struct biosParmBlock bpb_t; +//------------------------------------------------------------------------------ +/** + * \struct fat32BootSector + * + * \brief Boot sector for a FAT16 or FAT32 volume. + * + */ +struct fat32BootSector { + /** X86 jmp to boot program */ + uint8_t jmpToBootCode[3]; + /** informational only - don't depend on it */ + char oemName[8]; + /** BIOS Parameter Block */ + bpb_t bpb; + /** for int0x13 use value 0X80 for hard drive */ + uint8_t driveNumber; + /** used by Windows NT - should be zero for FAT */ + uint8_t reserved1; + /** 0X29 if next three fields are valid */ + uint8_t bootSignature; + /** usually generated by combining date and time */ + uint32_t volumeSerialNumber; + /** should match volume label in root dir */ + char volumeLabel[11]; + /** informational only - don't depend on it */ + char fileSystemType[8]; + /** X86 boot code */ + uint8_t bootCode[420]; + /** must be 0X55 */ + uint8_t bootSectorSig0; + /** must be 0XAA */ + uint8_t bootSectorSig1; +}; +//------------------------------------------------------------------------------ +// End Of Chain values for FAT entries +/** FAT16 end of chain value used by Microsoft. */ +uint16_t const FAT16EOC = 0XFFFF; +/** Minimum value for FAT16 EOC. Use to test for EOC. */ +uint16_t const FAT16EOC_MIN = 0XFFF8; +/** FAT32 end of chain value used by Microsoft. */ +uint32_t const FAT32EOC = 0X0FFFFFFF; +/** Minimum value for FAT32 EOC. Use to test for EOC. */ +uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; +/** Mask a for FAT32 entry. Entries are 28 bits. */ +uint32_t const FAT32MASK = 0X0FFFFFFF; + +/** Type name for fat32BootSector */ +typedef struct fat32BootSector fbs_t; +//------------------------------------------------------------------------------ +/** + * \struct directoryEntry + * \brief FAT short directory entry + * + * Short means short 8.3 name, not the entry size. + * + * Date Format. A FAT directory entry date stamp is a 16-bit field that is + * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the + * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the + * 16-bit word): + * + * Bits 9-15: Count of years from 1980, valid value range 0-127 + * inclusive (1980-2107). + * + * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. + * + * Bits 0-4: Day of month, valid value range 1-31 inclusive. + * + * Time Format. A FAT directory entry time stamp is a 16-bit field that has + * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the + * 16-bit word, bit 15 is the MSB of the 16-bit word). + * + * Bits 11-15: Hours, valid value range 0-23 inclusive. + * + * Bits 5-10: Minutes, valid value range 0-59 inclusive. + * + * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). + * + * The valid time range is from Midnight 00:00:00 to 23:59:58. + */ +struct directoryEntry { + /** + * Short 8.3 name. + * The first eight bytes contain the file name with blank fill. + * The last three bytes contain the file extension with blank fill. + */ + uint8_t name[11]; + /** Entry attributes. + * + * The upper two bits of the attribute byte are reserved and should + * always be set to 0 when a file is created and never modified or + * looked at after that. See defines that begin with DIR_ATT_. + */ + uint8_t attributes; + /** + * Reserved for use by Windows NT. Set value to 0 when a file is + * created and never modify or look at it after that. + */ + uint8_t reservedNT; + /** + * The granularity of the seconds part of creationTime is 2 seconds + * so this field is a count of tenths of a second and its valid + * value range is 0-199 inclusive. (WHG note - seems to be hundredths) + */ + uint8_t creationTimeTenths; + /** Time file was created. */ + uint16_t creationTime; + /** Date file was created. */ + uint16_t creationDate; + /** + * Last access date. Note that there is no last access time, only + * a date. This is the date of last read or write. In the case of + * a write, this should be set to the same date as lastWriteDate. + */ + uint16_t lastAccessDate; + /** + * High word of this entry's first cluster number (always 0 for a + * FAT12 or FAT16 volume). + */ + uint16_t firstClusterHigh; + /** Time of last write. File creation is considered a write. */ + uint16_t lastWriteTime; + /** Date of last write. File creation is considered a write. */ + uint16_t lastWriteDate; + /** Low word of this entry's first cluster number. */ + uint16_t firstClusterLow; + /** 32-bit unsigned holding this file's size in bytes. */ + uint32_t fileSize; +}; +//------------------------------------------------------------------------------ +// Definitions for directory entries +// +/** Type name for directoryEntry */ +typedef struct directoryEntry dir_t; +/** escape for name[0] = 0XE5 */ +uint8_t const DIR_NAME_0XE5 = 0X05; +/** name[0] value for entry that is free after being "deleted" */ +uint8_t const DIR_NAME_DELETED = 0XE5; +/** name[0] value for entry that is free and no allocated entries follow */ +uint8_t const DIR_NAME_FREE = 0X00; +/** file is read-only */ +uint8_t const DIR_ATT_READ_ONLY = 0X01; +/** File should hidden in directory listings */ +uint8_t const DIR_ATT_HIDDEN = 0X02; +/** Entry is for a system file */ +uint8_t const DIR_ATT_SYSTEM = 0X04; +/** Directory entry contains the volume label */ +uint8_t const DIR_ATT_VOLUME_ID = 0X08; +/** Entry is for a directory */ +uint8_t const DIR_ATT_DIRECTORY = 0X10; +/** Old DOS archive bit for backup support */ +uint8_t const DIR_ATT_ARCHIVE = 0X20; +/** Test value for long name entry. Test is + (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ +uint8_t const DIR_ATT_LONG_NAME = 0X0F; +/** Test mask for long name entry */ +uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; +/** defined attribute bits */ +uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; +/** Directory entry is part of a long name */ +static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { + return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; +} +/** Mask for file/subdirectory tests */ +uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); +/** Directory entry is for a file */ +static inline uint8_t DIR_IS_FILE(const dir_t* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; +} +/** Directory entry is for a subdirectory */ +static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; +} +/** Directory entry is for a file or subdirectory */ +static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { + return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; +} +#endif // FatStructs_h diff --git a/Marlin/Sd2Card.cpp b/Marlin/Sd2Card.cpp index 62c1159174..8222cfd939 100644 --- a/Marlin/Sd2Card.cpp +++ b/Marlin/Sd2Card.cpp @@ -1,643 +1,643 @@ -/* Arduino Sd2Card Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino Sd2Card Library - * - * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see - * . - */ -#include -#include "Sd2Card.h" -//------------------------------------------------------------------------------ -#ifndef SOFTWARE_SPI -// functions for hardware SPI -/** Send a byte to the card */ -static void spiSend(uint8_t b) { - SPDR = b; - while (!(SPSR & (1 << SPIF))); -} -/** Receive a byte from the card */ -static uint8_t spiRec(void) { - spiSend(0XFF); - return SPDR; -} -#else // SOFTWARE_SPI -//------------------------------------------------------------------------------ -/** nop to tune soft SPI timing */ -#define nop asm volatile ("nop\n\t") -//------------------------------------------------------------------------------ -/** Soft SPI receive */ -uint8_t spiRec(void) { - uint8_t data = 0; - // no interrupts during byte receive - about 8 us - cli(); - // output pin high - like sending 0XFF - fastDigitalWrite(SPI_MOSI_PIN, HIGH); - - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, HIGH); - - // adjust so SCK is nice - nop; - nop; - - data <<= 1; - - if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; - - fastDigitalWrite(SPI_SCK_PIN, LOW); - } - // enable interrupts - sei(); - return data; -} -//------------------------------------------------------------------------------ -/** Soft SPI send */ -void spiSend(uint8_t data) { - // no interrupts during byte send - about 8 us - cli(); - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, LOW); - - fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); - - data <<= 1; - - fastDigitalWrite(SPI_SCK_PIN, HIGH); - } - // hold SCK high for a few ns - nop; - nop; - nop; - nop; - - fastDigitalWrite(SPI_SCK_PIN, LOW); - // enable interrupts - sei(); -} -#endif // SOFTWARE_SPI -//------------------------------------------------------------------------------ -// send command and return error code. Return zero for OK -uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { - // end read if in partialBlockRead mode - readEnd(); - - // select card - chipSelectLow(); - - // wait up to 300 ms if busy - waitNotBusy(300); - - // send command - spiSend(cmd | 0x40); - - // send argument - for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); - - // send CRC - uint8_t crc = 0XFF; - if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 - if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA - spiSend(crc); - - // wait for response - for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); - return status_; -} -//------------------------------------------------------------------------------ -/** - * Determine the size of an SD flash memory card. - * - * \return The number of 512 byte data blocks in the card - * or zero if an error occurs. - */ -uint32_t Sd2Card::cardSize(void) { - csd_t csd; - if (!readCSD(&csd)) return 0; - if (csd.v1.csd_ver == 0) { - uint8_t read_bl_len = csd.v1.read_bl_len; - uint16_t c_size = (csd.v1.c_size_high << 10) - | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; - uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) - | csd.v1.c_size_mult_low; - return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); - } else if (csd.v2.csd_ver == 1) { - uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) - | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; - return (c_size + 1) << 10; - } else { - error(SD_CARD_ERROR_BAD_CSD); - return 0; - } -} -//------------------------------------------------------------------------------ -void Sd2Card::chipSelectHigh(void) { - digitalWrite(chipSelectPin_, HIGH); -} -//------------------------------------------------------------------------------ -void Sd2Card::chipSelectLow(void) { - digitalWrite(chipSelectPin_, LOW); -} -//------------------------------------------------------------------------------ -/** Erase a range of blocks. - * - * \param[in] firstBlock The address of the first block in the range. - * \param[in] lastBlock The address of the last block in the range. - * - * \note This function requests the SD card to do a flash erase for a - * range of blocks. The data on the card after an erase operation is - * either 0 or 1, depends on the card vendor. The card must support - * single block erase. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { - if (!eraseSingleBlockEnable()) { - error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); - goto fail; - } - if (type_ != SD_CARD_TYPE_SDHC) { - firstBlock <<= 9; - lastBlock <<= 9; - } - if (cardCommand(CMD32, firstBlock) - || cardCommand(CMD33, lastBlock) - || cardCommand(CMD38, 0)) { - error(SD_CARD_ERROR_ERASE); - goto fail; - } - if (!waitNotBusy(SD_ERASE_TIMEOUT)) { - error(SD_CARD_ERROR_ERASE_TIMEOUT); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Determine if card supports single block erase. - * - * \return The value one, true, is returned if single block erase is supported. - * The value zero, false, is returned if single block erase is not supported. - */ -uint8_t Sd2Card::eraseSingleBlockEnable(void) { - csd_t csd; - return readCSD(&csd) ? csd.v1.erase_blk_en : 0; -} -//------------------------------------------------------------------------------ -/** - * Initialize an SD flash memory card. - * - * \param[in] sckRateID SPI clock rate selector. See setSckRate(). - * \param[in] chipSelectPin SD chip select pin number. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. The reason for failure - * can be determined by calling errorCode() and errorData(). - */ -uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { - errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0; - chipSelectPin_ = chipSelectPin; - // 16-bit init start time allows over a minute - uint16_t t0 = (uint16_t)millis(); - uint32_t arg; - - // set pin modes - pinMode(chipSelectPin_, OUTPUT); - chipSelectHigh(); - pinMode(SPI_MISO_PIN, INPUT); - pinMode(SPI_MOSI_PIN, OUTPUT); - pinMode(SPI_SCK_PIN, OUTPUT); - -#ifndef SOFTWARE_SPI - // SS must be in output mode even it is not chip select - pinMode(SS_PIN, OUTPUT); - // Enable SPI, Master, clock rate f_osc/128 - SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); - // clear double speed - SPSR &= ~(1 << SPI2X); -#endif // SOFTWARE_SPI - - // must supply min of 74 clock cycles with CS high. - for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); - - chipSelectLow(); - - // command to go idle in SPI mode - while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_CMD0); - goto fail; - } - } - // check SD version - if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { - type(SD_CARD_TYPE_SD1); - } else { - // only need last byte of r7 response - for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); - if (status_ != 0XAA) { - error(SD_CARD_ERROR_CMD8); - goto fail; - } - type(SD_CARD_TYPE_SD2); - } - // initialize card and send host supports SDHC if SD2 - arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; - - while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { - // check for timeout - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_ACMD41); - goto fail; - } - } - // if SD2 read OCR register to check for SDHC card - if (type() == SD_CARD_TYPE_SD2) { - if (cardCommand(CMD58, 0)) { - error(SD_CARD_ERROR_CMD58); - goto fail; - } - if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); - // discard rest of ocr - contains allowed voltage range - for (uint8_t i = 0; i < 3; i++) spiRec(); - } - chipSelectHigh(); - -#ifndef SOFTWARE_SPI - return setSckRate(sckRateID); -#else // SOFTWARE_SPI - return true; -#endif // SOFTWARE_SPI - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - * Enable or disable partial block reads. - * - * Enabling partial block reads improves performance by allowing a block - * to be read over the SPI bus as several sub-blocks. Errors may occur - * if the time between reads is too long since the SD card may timeout. - * The SPI SS line will be held low until the entire block is read or - * readEnd() is called. - * - * Use this for applications like the Adafruit Wave Shield. - * - * \param[in] value The value TRUE (non-zero) or FALSE (zero).) - */ -void Sd2Card::partialBlockRead(uint8_t value) { - readEnd(); - partialBlockRead_ = value; -} -//------------------------------------------------------------------------------ -/** - * Read a 512 byte block from an SD card device. - * - * \param[in] block Logical block to be read. - * \param[out] dst Pointer to the location that will receive the data. - - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { - return readData(block, 0, 512, dst); -} -//------------------------------------------------------------------------------ -/** - * Read part of a 512 byte block from an SD card. - * - * \param[in] block Logical block to be read. - * \param[in] offset Number of bytes to skip at start of block - * \param[out] dst Pointer to the location that will receive the data. - * \param[in] count Number of bytes to read - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t Sd2Card::readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst) { - uint16_t n; - if (count == 0) return true; - if ((count + offset) > 512) { - goto fail; - } - if (!inBlock_ || block != block_ || offset < offset_) { - block_ = block; - // use address if not SDHC card - if (type()!= SD_CARD_TYPE_SDHC) block <<= 9; - if (cardCommand(CMD17, block)) { - error(SD_CARD_ERROR_CMD17); - goto fail; - } - if (!waitStartBlock()) { - goto fail; - } - offset_ = 0; - inBlock_ = 1; - } - -#ifdef OPTIMIZE_HARDWARE_SPI - // start first spi transfer - SPDR = 0XFF; - - // skip data before offset - for (;offset_ < offset; offset_++) { - while (!(SPSR & (1 << SPIF))); - SPDR = 0XFF; - } - // transfer data - n = count - 1; - for (uint16_t i = 0; i < n; i++) { - while (!(SPSR & (1 << SPIF))); - dst[i] = SPDR; - SPDR = 0XFF; - } - // wait for last byte - while (!(SPSR & (1 << SPIF))); - dst[n] = SPDR; - -#else // OPTIMIZE_HARDWARE_SPI - - // skip data before offset - for (;offset_ < offset; offset_++) { - spiRec(); - } - // transfer data - for (uint16_t i = 0; i < count; i++) { - dst[i] = spiRec(); - } -#endif // OPTIMIZE_HARDWARE_SPI - - offset_ += count; - if (!partialBlockRead_ || offset_ >= 512) { - // read rest of data, checksum and set chip select high - readEnd(); - } - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Skip remaining data in a block when in partial block read mode. */ -void Sd2Card::readEnd(void) { - if (inBlock_) { - // skip data and crc -#ifdef OPTIMIZE_HARDWARE_SPI - // optimize skip for hardware - SPDR = 0XFF; - while (offset_++ < 513) { - while (!(SPSR & (1 << SPIF))); - SPDR = 0XFF; - } - // wait for last crc byte - while (!(SPSR & (1 << SPIF))); -#else // OPTIMIZE_HARDWARE_SPI - while (offset_++ < 514) spiRec(); -#endif // OPTIMIZE_HARDWARE_SPI - chipSelectHigh(); - inBlock_ = 0; - } -} -//------------------------------------------------------------------------------ -/** read CID or CSR register */ -uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { - uint8_t* dst = reinterpret_cast(buf); - if (cardCommand(cmd, 0)) { - error(SD_CARD_ERROR_READ_REG); - goto fail; - } - if (!waitStartBlock()) goto fail; - // transfer data - for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec(); - spiRec(); // get first crc byte - spiRec(); // get second crc byte - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - * Set the SPI clock rate. - * - * \param[in] sckRateID A value in the range [0, 6]. - * - * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum - * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 - * for \a scsRateID = 6. - * - * \return The value one, true, is returned for success and the value zero, - * false, is returned for an invalid value of \a sckRateID. - */ -uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { - if (sckRateID > 6) { - error(SD_CARD_ERROR_SCK_RATE); - return false; - } - // see avr processor datasheet for SPI register bit definitions - if ((sckRateID & 1) || sckRateID == 6) { - SPSR &= ~(1 << SPI2X); - } else { - SPSR |= (1 << SPI2X); - } - SPCR &= ~((1 < SD_READ_TIMEOUT) { - error(SD_CARD_ERROR_READ_TIMEOUT); - goto fail; - } - } - if (status_ != DATA_START_BLOCK) { - error(SD_CARD_ERROR_READ); - goto fail; - } - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - * Writes a 512 byte block to an SD card. - * - * \param[in] blockNumber Logical block to be written. - * \param[in] src Pointer to the location of the data to be written. - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { -#if SD_PROTECT_BLOCK_ZERO - // don't allow write to first block - if (blockNumber == 0) { - error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); - goto fail; - } -#endif // SD_PROTECT_BLOCK_ZERO - - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD24, blockNumber)) { - error(SD_CARD_ERROR_CMD24); - goto fail; - } - if (!writeData(DATA_START_BLOCK, src)) goto fail; - - // wait for flash programming to complete - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_TIMEOUT); - goto fail; - } - // response is r2 so get and check two bytes for nonzero - if (cardCommand(CMD13, 0) || spiRec()) { - error(SD_CARD_ERROR_WRITE_PROGRAMMING); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Write one data block in a multiple block write sequence */ -uint8_t Sd2Card::writeData(const uint8_t* src) { - // wait for previous write to finish - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_MULTIPLE); - chipSelectHigh(); - return false; - } - return writeData(WRITE_MULTIPLE_TOKEN, src); -} -//------------------------------------------------------------------------------ -// send one block of data for write block or write multiple blocks -uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { -#ifdef OPTIMIZE_HARDWARE_SPI - - // send data - optimized loop - SPDR = token; - - // send two byte per iteration - for (uint16_t i = 0; i < 512; i += 2) { - while (!(SPSR & (1 << SPIF))); - SPDR = src[i]; - while (!(SPSR & (1 << SPIF))); - SPDR = src[i+1]; - } - - // wait for last data byte - while (!(SPSR & (1 << SPIF))); - -#else // OPTIMIZE_HARDWARE_SPI - spiSend(token); - for (uint16_t i = 0; i < 512; i++) { - spiSend(src[i]); - } -#endif // OPTIMIZE_HARDWARE_SPI - spiSend(0xff); // dummy crc - spiSend(0xff); // dummy crc - - status_ = spiRec(); - if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { - error(SD_CARD_ERROR_WRITE); - chipSelectHigh(); - return false; - } - return true; -} -//------------------------------------------------------------------------------ -/** Start a write multiple blocks sequence. - * - * \param[in] blockNumber Address of first block in sequence. - * \param[in] eraseCount The number of blocks to be pre-erased. - * - * \note This function is used with writeData() and writeStop() - * for optimized multiple block writes. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { -#if SD_PROTECT_BLOCK_ZERO - // don't allow write to first block - if (blockNumber == 0) { - error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); - goto fail; - } -#endif // SD_PROTECT_BLOCK_ZERO - // send pre-erase count - if (cardAcmd(ACMD23, eraseCount)) { - error(SD_CARD_ERROR_ACMD23); - goto fail; - } - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD25, blockNumber)) { - error(SD_CARD_ERROR_CMD25); - goto fail; - } - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** End a write multiple blocks sequence. - * -* \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t Sd2Card::writeStop(void) { - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - spiSend(STOP_TRAN_TOKEN); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - chipSelectHigh(); - return true; - - fail: - error(SD_CARD_ERROR_STOP_TRAN); - chipSelectHigh(); - return false; -} +/* Arduino Sd2Card Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino Sd2Card Library + * + * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see + * . + */ +#include +#include "Sd2Card.h" +//------------------------------------------------------------------------------ +#ifndef SOFTWARE_SPI +// functions for hardware SPI +/** Send a byte to the card */ +static void spiSend(uint8_t b) { + SPDR = b; + while (!(SPSR & (1 << SPIF))); +} +/** Receive a byte from the card */ +static uint8_t spiRec(void) { + spiSend(0XFF); + return SPDR; +} +#else // SOFTWARE_SPI +//------------------------------------------------------------------------------ +/** nop to tune soft SPI timing */ +#define nop asm volatile ("nop\n\t") +//------------------------------------------------------------------------------ +/** Soft SPI receive */ +uint8_t spiRec(void) { + uint8_t data = 0; + // no interrupts during byte receive - about 8 us + cli(); + // output pin high - like sending 0XFF + fastDigitalWrite(SPI_MOSI_PIN, HIGH); + + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, HIGH); + + // adjust so SCK is nice + nop; + nop; + + data <<= 1; + + if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; + + fastDigitalWrite(SPI_SCK_PIN, LOW); + } + // enable interrupts + sei(); + return data; +} +//------------------------------------------------------------------------------ +/** Soft SPI send */ +void spiSend(uint8_t data) { + // no interrupts during byte send - about 8 us + cli(); + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, LOW); + + fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); + + data <<= 1; + + fastDigitalWrite(SPI_SCK_PIN, HIGH); + } + // hold SCK high for a few ns + nop; + nop; + nop; + nop; + + fastDigitalWrite(SPI_SCK_PIN, LOW); + // enable interrupts + sei(); +} +#endif // SOFTWARE_SPI +//------------------------------------------------------------------------------ +// send command and return error code. Return zero for OK +uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { + // end read if in partialBlockRead mode + readEnd(); + + // select card + chipSelectLow(); + + // wait up to 300 ms if busy + waitNotBusy(300); + + // send command + spiSend(cmd | 0x40); + + // send argument + for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); + + // send CRC + uint8_t crc = 0XFF; + if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 + if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA + spiSend(crc); + + // wait for response + for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); + return status_; +} +//------------------------------------------------------------------------------ +/** + * Determine the size of an SD flash memory card. + * + * \return The number of 512 byte data blocks in the card + * or zero if an error occurs. + */ +uint32_t Sd2Card::cardSize(void) { + csd_t csd; + if (!readCSD(&csd)) return 0; + if (csd.v1.csd_ver == 0) { + uint8_t read_bl_len = csd.v1.read_bl_len; + uint16_t c_size = (csd.v1.c_size_high << 10) + | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; + uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) + | csd.v1.c_size_mult_low; + return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); + } else if (csd.v2.csd_ver == 1) { + uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) + | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; + return (c_size + 1) << 10; + } else { + error(SD_CARD_ERROR_BAD_CSD); + return 0; + } +} +//------------------------------------------------------------------------------ +void Sd2Card::chipSelectHigh(void) { + digitalWrite(chipSelectPin_, HIGH); +} +//------------------------------------------------------------------------------ +void Sd2Card::chipSelectLow(void) { + digitalWrite(chipSelectPin_, LOW); +} +//------------------------------------------------------------------------------ +/** Erase a range of blocks. + * + * \param[in] firstBlock The address of the first block in the range. + * \param[in] lastBlock The address of the last block in the range. + * + * \note This function requests the SD card to do a flash erase for a + * range of blocks. The data on the card after an erase operation is + * either 0 or 1, depends on the card vendor. The card must support + * single block erase. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { + if (!eraseSingleBlockEnable()) { + error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); + goto fail; + } + if (type_ != SD_CARD_TYPE_SDHC) { + firstBlock <<= 9; + lastBlock <<= 9; + } + if (cardCommand(CMD32, firstBlock) + || cardCommand(CMD33, lastBlock) + || cardCommand(CMD38, 0)) { + error(SD_CARD_ERROR_ERASE); + goto fail; + } + if (!waitNotBusy(SD_ERASE_TIMEOUT)) { + error(SD_CARD_ERROR_ERASE_TIMEOUT); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Determine if card supports single block erase. + * + * \return The value one, true, is returned if single block erase is supported. + * The value zero, false, is returned if single block erase is not supported. + */ +uint8_t Sd2Card::eraseSingleBlockEnable(void) { + csd_t csd; + return readCSD(&csd) ? csd.v1.erase_blk_en : 0; +} +//------------------------------------------------------------------------------ +/** + * Initialize an SD flash memory card. + * + * \param[in] sckRateID SPI clock rate selector. See setSckRate(). + * \param[in] chipSelectPin SD chip select pin number. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. The reason for failure + * can be determined by calling errorCode() and errorData(). + */ +uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { + errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0; + chipSelectPin_ = chipSelectPin; + // 16-bit init start time allows over a minute + uint16_t t0 = (uint16_t)millis(); + uint32_t arg; + + // set pin modes + pinMode(chipSelectPin_, OUTPUT); + chipSelectHigh(); + pinMode(SPI_MISO_PIN, INPUT); + pinMode(SPI_MOSI_PIN, OUTPUT); + pinMode(SPI_SCK_PIN, OUTPUT); + +#ifndef SOFTWARE_SPI + // SS must be in output mode even it is not chip select + pinMode(SS_PIN, OUTPUT); + // Enable SPI, Master, clock rate f_osc/128 + SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); + // clear double speed + SPSR &= ~(1 << SPI2X); +#endif // SOFTWARE_SPI + + // must supply min of 74 clock cycles with CS high. + for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); + + chipSelectLow(); + + // command to go idle in SPI mode + while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { + if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_CMD0); + goto fail; + } + } + // check SD version + if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { + type(SD_CARD_TYPE_SD1); + } else { + // only need last byte of r7 response + for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); + if (status_ != 0XAA) { + error(SD_CARD_ERROR_CMD8); + goto fail; + } + type(SD_CARD_TYPE_SD2); + } + // initialize card and send host supports SDHC if SD2 + arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; + + while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { + // check for timeout + if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_ACMD41); + goto fail; + } + } + // if SD2 read OCR register to check for SDHC card + if (type() == SD_CARD_TYPE_SD2) { + if (cardCommand(CMD58, 0)) { + error(SD_CARD_ERROR_CMD58); + goto fail; + } + if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); + // discard rest of ocr - contains allowed voltage range + for (uint8_t i = 0; i < 3; i++) spiRec(); + } + chipSelectHigh(); + +#ifndef SOFTWARE_SPI + return setSckRate(sckRateID); +#else // SOFTWARE_SPI + return true; +#endif // SOFTWARE_SPI + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + * Enable or disable partial block reads. + * + * Enabling partial block reads improves performance by allowing a block + * to be read over the SPI bus as several sub-blocks. Errors may occur + * if the time between reads is too long since the SD card may timeout. + * The SPI SS line will be held low until the entire block is read or + * readEnd() is called. + * + * Use this for applications like the Adafruit Wave Shield. + * + * \param[in] value The value TRUE (non-zero) or FALSE (zero).) + */ +void Sd2Card::partialBlockRead(uint8_t value) { + readEnd(); + partialBlockRead_ = value; +} +//------------------------------------------------------------------------------ +/** + * Read a 512 byte block from an SD card device. + * + * \param[in] block Logical block to be read. + * \param[out] dst Pointer to the location that will receive the data. + + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { + return readData(block, 0, 512, dst); +} +//------------------------------------------------------------------------------ +/** + * Read part of a 512 byte block from an SD card. + * + * \param[in] block Logical block to be read. + * \param[in] offset Number of bytes to skip at start of block + * \param[out] dst Pointer to the location that will receive the data. + * \param[in] count Number of bytes to read + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t Sd2Card::readData(uint32_t block, + uint16_t offset, uint16_t count, uint8_t* dst) { + uint16_t n; + if (count == 0) return true; + if ((count + offset) > 512) { + goto fail; + } + if (!inBlock_ || block != block_ || offset < offset_) { + block_ = block; + // use address if not SDHC card + if (type()!= SD_CARD_TYPE_SDHC) block <<= 9; + if (cardCommand(CMD17, block)) { + error(SD_CARD_ERROR_CMD17); + goto fail; + } + if (!waitStartBlock()) { + goto fail; + } + offset_ = 0; + inBlock_ = 1; + } + +#ifdef OPTIMIZE_HARDWARE_SPI + // start first spi transfer + SPDR = 0XFF; + + // skip data before offset + for (;offset_ < offset; offset_++) { + while (!(SPSR & (1 << SPIF))); + SPDR = 0XFF; + } + // transfer data + n = count - 1; + for (uint16_t i = 0; i < n; i++) { + while (!(SPSR & (1 << SPIF))); + dst[i] = SPDR; + SPDR = 0XFF; + } + // wait for last byte + while (!(SPSR & (1 << SPIF))); + dst[n] = SPDR; + +#else // OPTIMIZE_HARDWARE_SPI + + // skip data before offset + for (;offset_ < offset; offset_++) { + spiRec(); + } + // transfer data + for (uint16_t i = 0; i < count; i++) { + dst[i] = spiRec(); + } +#endif // OPTIMIZE_HARDWARE_SPI + + offset_ += count; + if (!partialBlockRead_ || offset_ >= 512) { + // read rest of data, checksum and set chip select high + readEnd(); + } + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Skip remaining data in a block when in partial block read mode. */ +void Sd2Card::readEnd(void) { + if (inBlock_) { + // skip data and crc +#ifdef OPTIMIZE_HARDWARE_SPI + // optimize skip for hardware + SPDR = 0XFF; + while (offset_++ < 513) { + while (!(SPSR & (1 << SPIF))); + SPDR = 0XFF; + } + // wait for last crc byte + while (!(SPSR & (1 << SPIF))); +#else // OPTIMIZE_HARDWARE_SPI + while (offset_++ < 514) spiRec(); +#endif // OPTIMIZE_HARDWARE_SPI + chipSelectHigh(); + inBlock_ = 0; + } +} +//------------------------------------------------------------------------------ +/** read CID or CSR register */ +uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { + uint8_t* dst = reinterpret_cast(buf); + if (cardCommand(cmd, 0)) { + error(SD_CARD_ERROR_READ_REG); + goto fail; + } + if (!waitStartBlock()) goto fail; + // transfer data + for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec(); + spiRec(); // get first crc byte + spiRec(); // get second crc byte + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + * Set the SPI clock rate. + * + * \param[in] sckRateID A value in the range [0, 6]. + * + * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum + * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 + * for \a scsRateID = 6. + * + * \return The value one, true, is returned for success and the value zero, + * false, is returned for an invalid value of \a sckRateID. + */ +uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { + if (sckRateID > 6) { + error(SD_CARD_ERROR_SCK_RATE); + return false; + } + // see avr processor datasheet for SPI register bit definitions + if ((sckRateID & 1) || sckRateID == 6) { + SPSR &= ~(1 << SPI2X); + } else { + SPSR |= (1 << SPI2X); + } + SPCR &= ~((1 < SD_READ_TIMEOUT) { + error(SD_CARD_ERROR_READ_TIMEOUT); + goto fail; + } + } + if (status_ != DATA_START_BLOCK) { + error(SD_CARD_ERROR_READ); + goto fail; + } + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + * Writes a 512 byte block to an SD card. + * + * \param[in] blockNumber Logical block to be written. + * \param[in] src Pointer to the location of the data to be written. + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { +#if SD_PROTECT_BLOCK_ZERO + // don't allow write to first block + if (blockNumber == 0) { + error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); + goto fail; + } +#endif // SD_PROTECT_BLOCK_ZERO + + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD24, blockNumber)) { + error(SD_CARD_ERROR_CMD24); + goto fail; + } + if (!writeData(DATA_START_BLOCK, src)) goto fail; + + // wait for flash programming to complete + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + error(SD_CARD_ERROR_WRITE_TIMEOUT); + goto fail; + } + // response is r2 so get and check two bytes for nonzero + if (cardCommand(CMD13, 0) || spiRec()) { + error(SD_CARD_ERROR_WRITE_PROGRAMMING); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Write one data block in a multiple block write sequence */ +uint8_t Sd2Card::writeData(const uint8_t* src) { + // wait for previous write to finish + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + error(SD_CARD_ERROR_WRITE_MULTIPLE); + chipSelectHigh(); + return false; + } + return writeData(WRITE_MULTIPLE_TOKEN, src); +} +//------------------------------------------------------------------------------ +// send one block of data for write block or write multiple blocks +uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { +#ifdef OPTIMIZE_HARDWARE_SPI + + // send data - optimized loop + SPDR = token; + + // send two byte per iteration + for (uint16_t i = 0; i < 512; i += 2) { + while (!(SPSR & (1 << SPIF))); + SPDR = src[i]; + while (!(SPSR & (1 << SPIF))); + SPDR = src[i+1]; + } + + // wait for last data byte + while (!(SPSR & (1 << SPIF))); + +#else // OPTIMIZE_HARDWARE_SPI + spiSend(token); + for (uint16_t i = 0; i < 512; i++) { + spiSend(src[i]); + } +#endif // OPTIMIZE_HARDWARE_SPI + spiSend(0xff); // dummy crc + spiSend(0xff); // dummy crc + + status_ = spiRec(); + if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { + error(SD_CARD_ERROR_WRITE); + chipSelectHigh(); + return false; + } + return true; +} +//------------------------------------------------------------------------------ +/** Start a write multiple blocks sequence. + * + * \param[in] blockNumber Address of first block in sequence. + * \param[in] eraseCount The number of blocks to be pre-erased. + * + * \note This function is used with writeData() and writeStop() + * for optimized multiple block writes. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { +#if SD_PROTECT_BLOCK_ZERO + // don't allow write to first block + if (blockNumber == 0) { + error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); + goto fail; + } +#endif // SD_PROTECT_BLOCK_ZERO + // send pre-erase count + if (cardAcmd(ACMD23, eraseCount)) { + error(SD_CARD_ERROR_ACMD23); + goto fail; + } + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD25, blockNumber)) { + error(SD_CARD_ERROR_CMD25); + goto fail; + } + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** End a write multiple blocks sequence. + * +* \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t Sd2Card::writeStop(void) { + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + spiSend(STOP_TRAN_TOKEN); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + chipSelectHigh(); + return true; + + fail: + error(SD_CARD_ERROR_STOP_TRAN); + chipSelectHigh(); + return false; +} diff --git a/Marlin/Sd2Card.h b/Marlin/Sd2Card.h index 9160c3d7ad..73b46fb44b 100644 --- a/Marlin/Sd2Card.h +++ b/Marlin/Sd2Card.h @@ -1,233 +1,233 @@ -/* Arduino Sd2Card Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino Sd2Card Library - * - * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see - * . - */ -#ifndef Sd2Card_h -#define Sd2Card_h -/** - * \file - * Sd2Card class - */ -#include "Sd2PinMap.h" -#include "SdInfo.h" -/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */ -uint8_t const SPI_FULL_SPEED = 0; -/** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */ -uint8_t const SPI_HALF_SPEED = 1; -/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */ -uint8_t const SPI_QUARTER_SPEED = 2; -/** - * Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos. - * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. - * - * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used - * on Mega Arduinos. Software SPI works well with GPS Shield V1.1 - * but many SD cards will fail with GPS Shield V1.0. - */ -#define MEGA_SOFT_SPI 0 -//------------------------------------------------------------------------------ -#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) -#define SOFTWARE_SPI -#endif // MEGA_SOFT_SPI -//------------------------------------------------------------------------------ -// SPI pin definitions -// -#ifndef SOFTWARE_SPI -// hardware pin defs -/** - * SD Chip Select pin - * - * Warning if this pin is redefined the hardware SS will pin will be enabled - * as an output by init(). An avr processor will not function as an SPI - * master unless SS is set to output mode. - */ -/** The default chip select pin for the SD card is SS. */ -uint8_t const SD_CHIP_SELECT_PIN = SS_PIN; -// The following three pins must not be redefined for hardware SPI. -/** SPI Master Out Slave In pin */ -uint8_t const SPI_MOSI_PIN = MOSI_PIN; -/** SPI Master In Slave Out pin */ -uint8_t const SPI_MISO_PIN = MISO_PIN; -/** SPI Clock pin */ -uint8_t const SPI_SCK_PIN = SCK_PIN; -/** optimize loops for hardware SPI */ -#define OPTIMIZE_HARDWARE_SPI - -#else // SOFTWARE_SPI -// define software SPI pins so Mega can use unmodified GPS Shield -/** SPI chip select pin */ -uint8_t const SD_CHIP_SELECT_PIN = 10; -/** SPI Master Out Slave In pin */ -uint8_t const SPI_MOSI_PIN = 11; -/** SPI Master In Slave Out pin */ -uint8_t const SPI_MISO_PIN = 12; -/** SPI Clock pin */ -uint8_t const SPI_SCK_PIN = 13; -#endif // SOFTWARE_SPI -//------------------------------------------------------------------------------ -/** Protect block zero from write if nonzero */ -#define SD_PROTECT_BLOCK_ZERO 1 -/** init timeout ms */ -uint16_t const SD_INIT_TIMEOUT = 2000; -/** erase timeout ms */ -uint16_t const SD_ERASE_TIMEOUT = 10000; -/** read timeout ms */ -uint16_t const SD_READ_TIMEOUT = 300; -/** write time out ms */ -uint16_t const SD_WRITE_TIMEOUT = 600; -//------------------------------------------------------------------------------ -// SD card errors -/** timeout error for command CMD0 */ -uint8_t const SD_CARD_ERROR_CMD0 = 0X1; -/** CMD8 was not accepted - not a valid SD card*/ -uint8_t const SD_CARD_ERROR_CMD8 = 0X2; -/** card returned an error response for CMD17 (read block) */ -uint8_t const SD_CARD_ERROR_CMD17 = 0X3; -/** card returned an error response for CMD24 (write block) */ -uint8_t const SD_CARD_ERROR_CMD24 = 0X4; -/** WRITE_MULTIPLE_BLOCKS command failed */ -uint8_t const SD_CARD_ERROR_CMD25 = 0X05; -/** card returned an error response for CMD58 (read OCR) */ -uint8_t const SD_CARD_ERROR_CMD58 = 0X06; -/** SET_WR_BLK_ERASE_COUNT failed */ -uint8_t const SD_CARD_ERROR_ACMD23 = 0X07; -/** card's ACMD41 initialization process timeout */ -uint8_t const SD_CARD_ERROR_ACMD41 = 0X08; -/** card returned a bad CSR version field */ -uint8_t const SD_CARD_ERROR_BAD_CSD = 0X09; -/** erase block group command failed */ -uint8_t const SD_CARD_ERROR_ERASE = 0X0A; -/** card not capable of single block erase */ -uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B; -/** Erase sequence timed out */ -uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C; -/** card returned an error token instead of read data */ -uint8_t const SD_CARD_ERROR_READ = 0X0D; -/** read CID or CSD failed */ -uint8_t const SD_CARD_ERROR_READ_REG = 0X0E; -/** timeout while waiting for start of read data */ -uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F; -/** card did not accept STOP_TRAN_TOKEN */ -uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10; -/** card returned an error token as a response to a write operation */ -uint8_t const SD_CARD_ERROR_WRITE = 0X11; -/** attempt to write protected block zero */ -uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12; -/** card did not go ready for a multiple block write */ -uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13; -/** card returned an error to a CMD13 status check after a write */ -uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14; -/** timeout occurred during write programming */ -uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15; -/** incorrect rate selected */ -uint8_t const SD_CARD_ERROR_SCK_RATE = 0X16; -//------------------------------------------------------------------------------ -// card types -/** Standard capacity V1 SD card */ -uint8_t const SD_CARD_TYPE_SD1 = 1; -/** Standard capacity V2 SD card */ -uint8_t const SD_CARD_TYPE_SD2 = 2; -/** High Capacity SD card */ -uint8_t const SD_CARD_TYPE_SDHC = 3; -//------------------------------------------------------------------------------ -/** - * \class Sd2Card - * \brief Raw access to SD and SDHC flash memory cards. - */ -class Sd2Card { - public: - /** Construct an instance of Sd2Card. */ - Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} - uint32_t cardSize(void); - uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); - uint8_t eraseSingleBlockEnable(void); - /** - * \return error code for last error. See Sd2Card.h for a list of error codes. - */ - uint8_t errorCode(void) const {return errorCode_;} - /** \return error data for last error. */ - uint8_t errorData(void) const {return status_;} - /** - * Initialize an SD flash memory card with default clock rate and chip - * select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). - */ - uint8_t init(void) { - return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); - } - /** - * Initialize an SD flash memory card with the selected SPI clock rate - * and the default SD chip select pin. - * See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). - */ - uint8_t init(uint8_t sckRateID) { - return init(sckRateID, SD_CHIP_SELECT_PIN); - } - uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); - void partialBlockRead(uint8_t value); - /** Returns the current value, true or false, for partial block read. */ - uint8_t partialBlockRead(void) const {return partialBlockRead_;} - uint8_t readBlock(uint32_t block, uint8_t* dst); - uint8_t readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst); - /** - * Read a cards CID register. The CID contains card identification - * information such as Manufacturer ID, Product name, Product serial - * number and Manufacturing date. */ - uint8_t readCID(cid_t* cid) { - return readRegister(CMD10, cid); - } - /** - * Read a cards CSD register. The CSD contains Card-Specific Data that - * provides information regarding access to the card's contents. */ - uint8_t readCSD(csd_t* csd) { - return readRegister(CMD9, csd); - } - void readEnd(void); - uint8_t setSckRate(uint8_t sckRateID); - /** Return the card type: SD V1, SD V2 or SDHC */ - uint8_t type(void) const {return type_;} - uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src); - uint8_t writeData(const uint8_t* src); - uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); - uint8_t writeStop(void); - private: - uint32_t block_; - uint8_t chipSelectPin_; - uint8_t errorCode_; - uint8_t inBlock_; - uint16_t offset_; - uint8_t partialBlockRead_; - uint8_t status_; - uint8_t type_; - // private functions - uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { - cardCommand(CMD55, 0); - return cardCommand(cmd, arg); - } - uint8_t cardCommand(uint8_t cmd, uint32_t arg); - void error(uint8_t code) {errorCode_ = code;} - uint8_t readRegister(uint8_t cmd, void* buf); - uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); - void chipSelectHigh(void); - void chipSelectLow(void); - void type(uint8_t value) {type_ = value;} - uint8_t waitNotBusy(uint16_t timeoutMillis); - uint8_t writeData(uint8_t token, const uint8_t* src); - uint8_t waitStartBlock(void); -}; -#endif // Sd2Card_h +/* Arduino Sd2Card Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino Sd2Card Library + * + * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see + * . + */ +#ifndef Sd2Card_h +#define Sd2Card_h +/** + * \file + * Sd2Card class + */ +#include "Sd2PinMap.h" +#include "SdInfo.h" +/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */ +uint8_t const SPI_FULL_SPEED = 0; +/** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */ +uint8_t const SPI_HALF_SPEED = 1; +/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */ +uint8_t const SPI_QUARTER_SPEED = 2; +/** + * Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos. + * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. + * + * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used + * on Mega Arduinos. Software SPI works well with GPS Shield V1.1 + * but many SD cards will fail with GPS Shield V1.0. + */ +#define MEGA_SOFT_SPI 0 +//------------------------------------------------------------------------------ +#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) +#define SOFTWARE_SPI +#endif // MEGA_SOFT_SPI +//------------------------------------------------------------------------------ +// SPI pin definitions +// +#ifndef SOFTWARE_SPI +// hardware pin defs +/** + * SD Chip Select pin + * + * Warning if this pin is redefined the hardware SS will pin will be enabled + * as an output by init(). An avr processor will not function as an SPI + * master unless SS is set to output mode. + */ +/** The default chip select pin for the SD card is SS. */ +uint8_t const SD_CHIP_SELECT_PIN = SS_PIN; +// The following three pins must not be redefined for hardware SPI. +/** SPI Master Out Slave In pin */ +uint8_t const SPI_MOSI_PIN = MOSI_PIN; +/** SPI Master In Slave Out pin */ +uint8_t const SPI_MISO_PIN = MISO_PIN; +/** SPI Clock pin */ +uint8_t const SPI_SCK_PIN = SCK_PIN; +/** optimize loops for hardware SPI */ +#define OPTIMIZE_HARDWARE_SPI + +#else // SOFTWARE_SPI +// define software SPI pins so Mega can use unmodified GPS Shield +/** SPI chip select pin */ +uint8_t const SD_CHIP_SELECT_PIN = 10; +/** SPI Master Out Slave In pin */ +uint8_t const SPI_MOSI_PIN = 11; +/** SPI Master In Slave Out pin */ +uint8_t const SPI_MISO_PIN = 12; +/** SPI Clock pin */ +uint8_t const SPI_SCK_PIN = 13; +#endif // SOFTWARE_SPI +//------------------------------------------------------------------------------ +/** Protect block zero from write if nonzero */ +#define SD_PROTECT_BLOCK_ZERO 1 +/** init timeout ms */ +uint16_t const SD_INIT_TIMEOUT = 2000; +/** erase timeout ms */ +uint16_t const SD_ERASE_TIMEOUT = 10000; +/** read timeout ms */ +uint16_t const SD_READ_TIMEOUT = 300; +/** write time out ms */ +uint16_t const SD_WRITE_TIMEOUT = 600; +//------------------------------------------------------------------------------ +// SD card errors +/** timeout error for command CMD0 */ +uint8_t const SD_CARD_ERROR_CMD0 = 0X1; +/** CMD8 was not accepted - not a valid SD card*/ +uint8_t const SD_CARD_ERROR_CMD8 = 0X2; +/** card returned an error response for CMD17 (read block) */ +uint8_t const SD_CARD_ERROR_CMD17 = 0X3; +/** card returned an error response for CMD24 (write block) */ +uint8_t const SD_CARD_ERROR_CMD24 = 0X4; +/** WRITE_MULTIPLE_BLOCKS command failed */ +uint8_t const SD_CARD_ERROR_CMD25 = 0X05; +/** card returned an error response for CMD58 (read OCR) */ +uint8_t const SD_CARD_ERROR_CMD58 = 0X06; +/** SET_WR_BLK_ERASE_COUNT failed */ +uint8_t const SD_CARD_ERROR_ACMD23 = 0X07; +/** card's ACMD41 initialization process timeout */ +uint8_t const SD_CARD_ERROR_ACMD41 = 0X08; +/** card returned a bad CSR version field */ +uint8_t const SD_CARD_ERROR_BAD_CSD = 0X09; +/** erase block group command failed */ +uint8_t const SD_CARD_ERROR_ERASE = 0X0A; +/** card not capable of single block erase */ +uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B; +/** Erase sequence timed out */ +uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C; +/** card returned an error token instead of read data */ +uint8_t const SD_CARD_ERROR_READ = 0X0D; +/** read CID or CSD failed */ +uint8_t const SD_CARD_ERROR_READ_REG = 0X0E; +/** timeout while waiting for start of read data */ +uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F; +/** card did not accept STOP_TRAN_TOKEN */ +uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10; +/** card returned an error token as a response to a write operation */ +uint8_t const SD_CARD_ERROR_WRITE = 0X11; +/** attempt to write protected block zero */ +uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12; +/** card did not go ready for a multiple block write */ +uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13; +/** card returned an error to a CMD13 status check after a write */ +uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14; +/** timeout occurred during write programming */ +uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15; +/** incorrect rate selected */ +uint8_t const SD_CARD_ERROR_SCK_RATE = 0X16; +//------------------------------------------------------------------------------ +// card types +/** Standard capacity V1 SD card */ +uint8_t const SD_CARD_TYPE_SD1 = 1; +/** Standard capacity V2 SD card */ +uint8_t const SD_CARD_TYPE_SD2 = 2; +/** High Capacity SD card */ +uint8_t const SD_CARD_TYPE_SDHC = 3; +//------------------------------------------------------------------------------ +/** + * \class Sd2Card + * \brief Raw access to SD and SDHC flash memory cards. + */ +class Sd2Card { + public: + /** Construct an instance of Sd2Card. */ + Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} + uint32_t cardSize(void); + uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); + uint8_t eraseSingleBlockEnable(void); + /** + * \return error code for last error. See Sd2Card.h for a list of error codes. + */ + uint8_t errorCode(void) const {return errorCode_;} + /** \return error data for last error. */ + uint8_t errorData(void) const {return status_;} + /** + * Initialize an SD flash memory card with default clock rate and chip + * select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + */ + uint8_t init(void) { + return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); + } + /** + * Initialize an SD flash memory card with the selected SPI clock rate + * and the default SD chip select pin. + * See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + */ + uint8_t init(uint8_t sckRateID) { + return init(sckRateID, SD_CHIP_SELECT_PIN); + } + uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); + void partialBlockRead(uint8_t value); + /** Returns the current value, true or false, for partial block read. */ + uint8_t partialBlockRead(void) const {return partialBlockRead_;} + uint8_t readBlock(uint32_t block, uint8_t* dst); + uint8_t readData(uint32_t block, + uint16_t offset, uint16_t count, uint8_t* dst); + /** + * Read a cards CID register. The CID contains card identification + * information such as Manufacturer ID, Product name, Product serial + * number and Manufacturing date. */ + uint8_t readCID(cid_t* cid) { + return readRegister(CMD10, cid); + } + /** + * Read a cards CSD register. The CSD contains Card-Specific Data that + * provides information regarding access to the card's contents. */ + uint8_t readCSD(csd_t* csd) { + return readRegister(CMD9, csd); + } + void readEnd(void); + uint8_t setSckRate(uint8_t sckRateID); + /** Return the card type: SD V1, SD V2 or SDHC */ + uint8_t type(void) const {return type_;} + uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src); + uint8_t writeData(const uint8_t* src); + uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); + uint8_t writeStop(void); + private: + uint32_t block_; + uint8_t chipSelectPin_; + uint8_t errorCode_; + uint8_t inBlock_; + uint16_t offset_; + uint8_t partialBlockRead_; + uint8_t status_; + uint8_t type_; + // private functions + uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { + cardCommand(CMD55, 0); + return cardCommand(cmd, arg); + } + uint8_t cardCommand(uint8_t cmd, uint32_t arg); + void error(uint8_t code) {errorCode_ = code;} + uint8_t readRegister(uint8_t cmd, void* buf); + uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); + void chipSelectHigh(void); + void chipSelectLow(void); + void type(uint8_t value) {type_ = value;} + uint8_t waitNotBusy(uint16_t timeoutMillis); + uint8_t writeData(uint8_t token, const uint8_t* src); + uint8_t waitStartBlock(void); +}; +#endif // Sd2Card_h diff --git a/Marlin/Sd2PinMap.h b/Marlin/Sd2PinMap.h index bba0dd0278..4bd75a35db 100644 --- a/Marlin/Sd2PinMap.h +++ b/Marlin/Sd2PinMap.h @@ -1,353 +1,353 @@ -/* Arduino SdFat Library - * Copyright (C) 2010 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -// Warning this file was generated by a program. -#ifndef Sd2PinMap_h -#define Sd2PinMap_h -#include - -//------------------------------------------------------------------------------ -/** struct for mapping digital pins */ -struct pin_map_t { - volatile uint8_t* ddr; - volatile uint8_t* pin; - volatile uint8_t* port; - uint8_t bit; -}; -//------------------------------------------------------------------------------ -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -// Mega - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 20; -uint8_t const SCL_PIN = 21; - -// SPI port -uint8_t const SS_PIN = 53; -uint8_t const MOSI_PIN = 51; -uint8_t const MISO_PIN = 50; -uint8_t const SCK_PIN = 52; - -static const pin_map_t digitalPinMap[] = { - {&DDRE, &PINE, &PORTE, 0}, // E0 0 - {&DDRE, &PINE, &PORTE, 1}, // E1 1 - {&DDRE, &PINE, &PORTE, 4}, // E4 2 - {&DDRE, &PINE, &PORTE, 5}, // E5 3 - {&DDRG, &PING, &PORTG, 5}, // G5 4 - {&DDRE, &PINE, &PORTE, 3}, // E3 5 - {&DDRH, &PINH, &PORTH, 3}, // H3 6 - {&DDRH, &PINH, &PORTH, 4}, // H4 7 - {&DDRH, &PINH, &PORTH, 5}, // H5 8 - {&DDRH, &PINH, &PORTH, 6}, // H6 9 - {&DDRB, &PINB, &PORTB, 4}, // B4 10 - {&DDRB, &PINB, &PORTB, 5}, // B5 11 - {&DDRB, &PINB, &PORTB, 6}, // B6 12 - {&DDRB, &PINB, &PORTB, 7}, // B7 13 - {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 - {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 - {&DDRH, &PINH, &PORTH, 1}, // H1 16 - {&DDRH, &PINH, &PORTH, 0}, // H0 17 - {&DDRD, &PIND, &PORTD, 3}, // D3 18 - {&DDRD, &PIND, &PORTD, 2}, // D2 19 - {&DDRD, &PIND, &PORTD, 1}, // D1 20 - {&DDRD, &PIND, &PORTD, 0}, // D0 21 - {&DDRA, &PINA, &PORTA, 0}, // A0 22 - {&DDRA, &PINA, &PORTA, 1}, // A1 23 - {&DDRA, &PINA, &PORTA, 2}, // A2 24 - {&DDRA, &PINA, &PORTA, 3}, // A3 25 - {&DDRA, &PINA, &PORTA, 4}, // A4 26 - {&DDRA, &PINA, &PORTA, 5}, // A5 27 - {&DDRA, &PINA, &PORTA, 6}, // A6 28 - {&DDRA, &PINA, &PORTA, 7}, // A7 29 - {&DDRC, &PINC, &PORTC, 7}, // C7 30 - {&DDRC, &PINC, &PORTC, 6}, // C6 31 - {&DDRC, &PINC, &PORTC, 5}, // C5 32 - {&DDRC, &PINC, &PORTC, 4}, // C4 33 - {&DDRC, &PINC, &PORTC, 3}, // C3 34 - {&DDRC, &PINC, &PORTC, 2}, // C2 35 - {&DDRC, &PINC, &PORTC, 1}, // C1 36 - {&DDRC, &PINC, &PORTC, 0}, // C0 37 - {&DDRD, &PIND, &PORTD, 7}, // D7 38 - {&DDRG, &PING, &PORTG, 2}, // G2 39 - {&DDRG, &PING, &PORTG, 1}, // G1 40 - {&DDRG, &PING, &PORTG, 0}, // G0 41 - {&DDRL, &PINL, &PORTL, 7}, // L7 42 - {&DDRL, &PINL, &PORTL, 6}, // L6 43 - {&DDRL, &PINL, &PORTL, 5}, // L5 44 - {&DDRL, &PINL, &PORTL, 4}, // L4 45 - {&DDRL, &PINL, &PORTL, 3}, // L3 46 - {&DDRL, &PINL, &PORTL, 2}, // L2 47 - {&DDRL, &PINL, &PORTL, 1}, // L1 48 - {&DDRL, &PINL, &PORTL, 0}, // L0 49 - {&DDRB, &PINB, &PORTB, 3}, // B3 50 - {&DDRB, &PINB, &PORTB, 2}, // B2 51 - {&DDRB, &PINB, &PORTB, 1}, // B1 52 - {&DDRB, &PINB, &PORTB, 0}, // B0 53 - {&DDRF, &PINF, &PORTF, 0}, // F0 54 - {&DDRF, &PINF, &PORTF, 1}, // F1 55 - {&DDRF, &PINF, &PORTF, 2}, // F2 56 - {&DDRF, &PINF, &PORTF, 3}, // F3 57 - {&DDRF, &PINF, &PORTF, 4}, // F4 58 - {&DDRF, &PINF, &PORTF, 5}, // F5 59 - {&DDRF, &PINF, &PORTF, 6}, // F6 60 - {&DDRF, &PINF, &PORTF, 7}, // F7 61 - {&DDRK, &PINK, &PORTK, 0}, // K0 62 - {&DDRK, &PINK, &PORTK, 1}, // K1 63 - {&DDRK, &PINK, &PORTK, 2}, // K2 64 - {&DDRK, &PINK, &PORTK, 3}, // K3 65 - {&DDRK, &PINK, &PORTK, 4}, // K4 66 - {&DDRK, &PINK, &PORTK, 5}, // K5 67 - {&DDRK, &PINK, &PORTK, 6}, // K6 68 - {&DDRK, &PINK, &PORTK, 7} // K7 69 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) -// Sanguino - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 17; -uint8_t const SCL_PIN = 18; - -// SPI port -uint8_t const SS_PIN = 4; -uint8_t const MOSI_PIN = 5; -uint8_t const MISO_PIN = 6; -uint8_t const SCK_PIN = 7; - -static const pin_map_t digitalPinMap[] = { - {&DDRB, &PINB, &PORTB, 0}, // B0 0 - {&DDRB, &PINB, &PORTB, 1}, // B1 1 - {&DDRB, &PINB, &PORTB, 2}, // B2 2 - {&DDRB, &PINB, &PORTB, 3}, // B3 3 - {&DDRB, &PINB, &PORTB, 4}, // B4 4 - {&DDRB, &PINB, &PORTB, 5}, // B5 5 - {&DDRB, &PINB, &PORTB, 6}, // B6 6 - {&DDRB, &PINB, &PORTB, 7}, // B7 7 - {&DDRD, &PIND, &PORTD, 0}, // D0 8 - {&DDRD, &PIND, &PORTD, 1}, // D1 9 - {&DDRD, &PIND, &PORTD, 2}, // D2 10 - {&DDRD, &PIND, &PORTD, 3}, // D3 11 - {&DDRD, &PIND, &PORTD, 4}, // D4 12 - {&DDRD, &PIND, &PORTD, 5}, // D5 13 - {&DDRD, &PIND, &PORTD, 6}, // D6 14 - {&DDRD, &PIND, &PORTD, 7}, // D7 15 - {&DDRC, &PINC, &PORTC, 0}, // C0 16 - {&DDRC, &PINC, &PORTC, 1}, // C1 17 - {&DDRC, &PINC, &PORTC, 2}, // C2 18 - {&DDRC, &PINC, &PORTC, 3}, // C3 19 - {&DDRC, &PINC, &PORTC, 4}, // C4 20 - {&DDRC, &PINC, &PORTC, 5}, // C5 21 - {&DDRC, &PINC, &PORTC, 6}, // C6 22 - {&DDRC, &PINC, &PORTC, 7}, // C7 23 - {&DDRA, &PINA, &PORTA, 7}, // A7 24 - {&DDRA, &PINA, &PORTA, 6}, // A6 25 - {&DDRA, &PINA, &PORTA, 5}, // A5 26 - {&DDRA, &PINA, &PORTA, 4}, // A4 27 - {&DDRA, &PINA, &PORTA, 3}, // A3 28 - {&DDRA, &PINA, &PORTA, 2}, // A2 29 - {&DDRA, &PINA, &PORTA, 1}, // A1 30 - {&DDRA, &PINA, &PORTA, 0} // A0 31 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega32U4__) -// Teensy 2.0 - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 6; -uint8_t const SCL_PIN = 5; - -// SPI port -uint8_t const SS_PIN = 0; -uint8_t const MOSI_PIN = 2; -uint8_t const MISO_PIN = 3; -uint8_t const SCK_PIN = 1; - -static const pin_map_t digitalPinMap[] = { - {&DDRB, &PINB, &PORTB, 0}, // B0 0 - {&DDRB, &PINB, &PORTB, 1}, // B1 1 - {&DDRB, &PINB, &PORTB, 2}, // B2 2 - {&DDRB, &PINB, &PORTB, 3}, // B3 3 - {&DDRB, &PINB, &PORTB, 7}, // B7 4 - {&DDRD, &PIND, &PORTD, 0}, // D0 5 - {&DDRD, &PIND, &PORTD, 1}, // D1 6 - {&DDRD, &PIND, &PORTD, 2}, // D2 7 - {&DDRD, &PIND, &PORTD, 3}, // D3 8 - {&DDRC, &PINC, &PORTC, 6}, // C6 9 - {&DDRC, &PINC, &PORTC, 7}, // C7 10 - {&DDRD, &PIND, &PORTD, 6}, // D6 11 - {&DDRD, &PIND, &PORTD, 7}, // D7 12 - {&DDRB, &PINB, &PORTB, 4}, // B4 13 - {&DDRB, &PINB, &PORTB, 5}, // B5 14 - {&DDRB, &PINB, &PORTB, 6}, // B6 15 - {&DDRF, &PINF, &PORTF, 7}, // F7 16 - {&DDRF, &PINF, &PORTF, 6}, // F6 17 - {&DDRF, &PINF, &PORTF, 5}, // F5 18 - {&DDRF, &PINF, &PORTF, 4}, // F4 19 - {&DDRF, &PINF, &PORTF, 1}, // F1 20 - {&DDRF, &PINF, &PORTF, 0}, // F0 21 - {&DDRD, &PIND, &PORTD, 4}, // D4 22 - {&DDRD, &PIND, &PORTD, 5}, // D5 23 - {&DDRE, &PINE, &PORTE, 6} // E6 24 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -// Teensy++ 1.0 & 2.0 - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 1; -uint8_t const SCL_PIN = 0; - -// SPI port -uint8_t const SS_PIN = 20; -uint8_t const MOSI_PIN = 22; -uint8_t const MISO_PIN = 23; -uint8_t const SCK_PIN = 21; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRE, &PINE, &PORTE, 0}, // E0 8 - {&DDRE, &PINE, &PORTE, 1}, // E1 9 - {&DDRC, &PINC, &PORTC, 0}, // C0 10 - {&DDRC, &PINC, &PORTC, 1}, // C1 11 - {&DDRC, &PINC, &PORTC, 2}, // C2 12 - {&DDRC, &PINC, &PORTC, 3}, // C3 13 - {&DDRC, &PINC, &PORTC, 4}, // C4 14 - {&DDRC, &PINC, &PORTC, 5}, // C5 15 - {&DDRC, &PINC, &PORTC, 6}, // C6 16 - {&DDRC, &PINC, &PORTC, 7}, // C7 17 - {&DDRE, &PINE, &PORTE, 6}, // E6 18 - {&DDRE, &PINE, &PORTE, 7}, // E7 19 - {&DDRB, &PINB, &PORTB, 0}, // B0 20 - {&DDRB, &PINB, &PORTB, 1}, // B1 21 - {&DDRB, &PINB, &PORTB, 2}, // B2 22 - {&DDRB, &PINB, &PORTB, 3}, // B3 23 - {&DDRB, &PINB, &PORTB, 4}, // B4 24 - {&DDRB, &PINB, &PORTB, 5}, // B5 25 - {&DDRB, &PINB, &PORTB, 6}, // B6 26 - {&DDRB, &PINB, &PORTB, 7}, // B7 27 - {&DDRA, &PINA, &PORTA, 0}, // A0 28 - {&DDRA, &PINA, &PORTA, 1}, // A1 29 - {&DDRA, &PINA, &PORTA, 2}, // A2 30 - {&DDRA, &PINA, &PORTA, 3}, // A3 31 - {&DDRA, &PINA, &PORTA, 4}, // A4 32 - {&DDRA, &PINA, &PORTA, 5}, // A5 33 - {&DDRA, &PINA, &PORTA, 6}, // A6 34 - {&DDRA, &PINA, &PORTA, 7}, // A7 35 - {&DDRE, &PINE, &PORTE, 4}, // E4 36 - {&DDRE, &PINE, &PORTE, 5}, // E5 37 - {&DDRF, &PINF, &PORTF, 0}, // F0 38 - {&DDRF, &PINF, &PORTF, 1}, // F1 39 - {&DDRF, &PINF, &PORTF, 2}, // F2 40 - {&DDRF, &PINF, &PORTF, 3}, // F3 41 - {&DDRF, &PINF, &PORTF, 4}, // F4 42 - {&DDRF, &PINF, &PORTF, 5}, // F5 43 - {&DDRF, &PINF, &PORTF, 6}, // F6 44 - {&DDRF, &PINF, &PORTF, 7} // F7 45 -}; -//------------------------------------------------------------------------------ -#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -// 168 and 328 Arduinos - -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 18; -uint8_t const SCL_PIN = 19; - -// SPI port -uint8_t const SS_PIN = 10; -uint8_t const MOSI_PIN = 11; -uint8_t const MISO_PIN = 12; -uint8_t const SCK_PIN = 13; - -static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRB, &PINB, &PORTB, 0}, // B0 8 - {&DDRB, &PINB, &PORTB, 1}, // B1 9 - {&DDRB, &PINB, &PORTB, 2}, // B2 10 - {&DDRB, &PINB, &PORTB, 3}, // B3 11 - {&DDRB, &PINB, &PORTB, 4}, // B4 12 - {&DDRB, &PINB, &PORTB, 5}, // B5 13 - {&DDRC, &PINC, &PORTC, 0}, // C0 14 - {&DDRC, &PINC, &PORTC, 1}, // C1 15 - {&DDRC, &PINC, &PORTC, 2}, // C2 16 - {&DDRC, &PINC, &PORTC, 3}, // C3 17 - {&DDRC, &PINC, &PORTC, 4}, // C4 18 - {&DDRC, &PINC, &PORTC, 5} // C5 19 -}; -#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -//------------------------------------------------------------------------------ -static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t); - -uint8_t badPinNumber(void) - __attribute__((error("Pin number is too large or not a constant"))); - -static inline __attribute__((always_inline)) - uint8_t getPinMode(uint8_t pin) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1; - } else { - return badPinNumber(); - } -} -static inline __attribute__((always_inline)) - void setPinMode(uint8_t pin, uint8_t mode) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - if (mode) { - *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit; - } else { - *digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit); - } - } else { - badPinNumber(); - } -} -static inline __attribute__((always_inline)) - uint8_t fastDigitalRead(uint8_t pin) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1; - } else { - return badPinNumber(); - } -} -static inline __attribute__((always_inline)) - void fastDigitalWrite(uint8_t pin, uint8_t value) { - if (__builtin_constant_p(pin) && pin < digitalPinCount) { - if (value) { - *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit; - } else { - *digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit); - } - } else { - badPinNumber(); - } -} -#endif // Sd2PinMap_h +/* Arduino SdFat Library + * Copyright (C) 2010 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +// Warning this file was generated by a program. +#ifndef Sd2PinMap_h +#define Sd2PinMap_h +#include + +//------------------------------------------------------------------------------ +/** struct for mapping digital pins */ +struct pin_map_t { + volatile uint8_t* ddr; + volatile uint8_t* pin; + volatile uint8_t* port; + uint8_t bit; +}; +//------------------------------------------------------------------------------ +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +// Mega + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 20; +uint8_t const SCL_PIN = 21; + +// SPI port +uint8_t const SS_PIN = 53; +uint8_t const MOSI_PIN = 51; +uint8_t const MISO_PIN = 50; +uint8_t const SCK_PIN = 52; + +static const pin_map_t digitalPinMap[] = { + {&DDRE, &PINE, &PORTE, 0}, // E0 0 + {&DDRE, &PINE, &PORTE, 1}, // E1 1 + {&DDRE, &PINE, &PORTE, 4}, // E4 2 + {&DDRE, &PINE, &PORTE, 5}, // E5 3 + {&DDRG, &PING, &PORTG, 5}, // G5 4 + {&DDRE, &PINE, &PORTE, 3}, // E3 5 + {&DDRH, &PINH, &PORTH, 3}, // H3 6 + {&DDRH, &PINH, &PORTH, 4}, // H4 7 + {&DDRH, &PINH, &PORTH, 5}, // H5 8 + {&DDRH, &PINH, &PORTH, 6}, // H6 9 + {&DDRB, &PINB, &PORTB, 4}, // B4 10 + {&DDRB, &PINB, &PORTB, 5}, // B5 11 + {&DDRB, &PINB, &PORTB, 6}, // B6 12 + {&DDRB, &PINB, &PORTB, 7}, // B7 13 + {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 + {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 + {&DDRH, &PINH, &PORTH, 1}, // H1 16 + {&DDRH, &PINH, &PORTH, 0}, // H0 17 + {&DDRD, &PIND, &PORTD, 3}, // D3 18 + {&DDRD, &PIND, &PORTD, 2}, // D2 19 + {&DDRD, &PIND, &PORTD, 1}, // D1 20 + {&DDRD, &PIND, &PORTD, 0}, // D0 21 + {&DDRA, &PINA, &PORTA, 0}, // A0 22 + {&DDRA, &PINA, &PORTA, 1}, // A1 23 + {&DDRA, &PINA, &PORTA, 2}, // A2 24 + {&DDRA, &PINA, &PORTA, 3}, // A3 25 + {&DDRA, &PINA, &PORTA, 4}, // A4 26 + {&DDRA, &PINA, &PORTA, 5}, // A5 27 + {&DDRA, &PINA, &PORTA, 6}, // A6 28 + {&DDRA, &PINA, &PORTA, 7}, // A7 29 + {&DDRC, &PINC, &PORTC, 7}, // C7 30 + {&DDRC, &PINC, &PORTC, 6}, // C6 31 + {&DDRC, &PINC, &PORTC, 5}, // C5 32 + {&DDRC, &PINC, &PORTC, 4}, // C4 33 + {&DDRC, &PINC, &PORTC, 3}, // C3 34 + {&DDRC, &PINC, &PORTC, 2}, // C2 35 + {&DDRC, &PINC, &PORTC, 1}, // C1 36 + {&DDRC, &PINC, &PORTC, 0}, // C0 37 + {&DDRD, &PIND, &PORTD, 7}, // D7 38 + {&DDRG, &PING, &PORTG, 2}, // G2 39 + {&DDRG, &PING, &PORTG, 1}, // G1 40 + {&DDRG, &PING, &PORTG, 0}, // G0 41 + {&DDRL, &PINL, &PORTL, 7}, // L7 42 + {&DDRL, &PINL, &PORTL, 6}, // L6 43 + {&DDRL, &PINL, &PORTL, 5}, // L5 44 + {&DDRL, &PINL, &PORTL, 4}, // L4 45 + {&DDRL, &PINL, &PORTL, 3}, // L3 46 + {&DDRL, &PINL, &PORTL, 2}, // L2 47 + {&DDRL, &PINL, &PORTL, 1}, // L1 48 + {&DDRL, &PINL, &PORTL, 0}, // L0 49 + {&DDRB, &PINB, &PORTB, 3}, // B3 50 + {&DDRB, &PINB, &PORTB, 2}, // B2 51 + {&DDRB, &PINB, &PORTB, 1}, // B1 52 + {&DDRB, &PINB, &PORTB, 0}, // B0 53 + {&DDRF, &PINF, &PORTF, 0}, // F0 54 + {&DDRF, &PINF, &PORTF, 1}, // F1 55 + {&DDRF, &PINF, &PORTF, 2}, // F2 56 + {&DDRF, &PINF, &PORTF, 3}, // F3 57 + {&DDRF, &PINF, &PORTF, 4}, // F4 58 + {&DDRF, &PINF, &PORTF, 5}, // F5 59 + {&DDRF, &PINF, &PORTF, 6}, // F6 60 + {&DDRF, &PINF, &PORTF, 7}, // F7 61 + {&DDRK, &PINK, &PORTK, 0}, // K0 62 + {&DDRK, &PINK, &PORTK, 1}, // K1 63 + {&DDRK, &PINK, &PORTK, 2}, // K2 64 + {&DDRK, &PINK, &PORTK, 3}, // K3 65 + {&DDRK, &PINK, &PORTK, 4}, // K4 66 + {&DDRK, &PINK, &PORTK, 5}, // K5 67 + {&DDRK, &PINK, &PORTK, 6}, // K6 68 + {&DDRK, &PINK, &PORTK, 7} // K7 69 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) +// Sanguino + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 17; +uint8_t const SCL_PIN = 18; + +// SPI port +uint8_t const SS_PIN = 4; +uint8_t const MOSI_PIN = 5; +uint8_t const MISO_PIN = 6; +uint8_t const SCK_PIN = 7; + +static const pin_map_t digitalPinMap[] = { + {&DDRB, &PINB, &PORTB, 0}, // B0 0 + {&DDRB, &PINB, &PORTB, 1}, // B1 1 + {&DDRB, &PINB, &PORTB, 2}, // B2 2 + {&DDRB, &PINB, &PORTB, 3}, // B3 3 + {&DDRB, &PINB, &PORTB, 4}, // B4 4 + {&DDRB, &PINB, &PORTB, 5}, // B5 5 + {&DDRB, &PINB, &PORTB, 6}, // B6 6 + {&DDRB, &PINB, &PORTB, 7}, // B7 7 + {&DDRD, &PIND, &PORTD, 0}, // D0 8 + {&DDRD, &PIND, &PORTD, 1}, // D1 9 + {&DDRD, &PIND, &PORTD, 2}, // D2 10 + {&DDRD, &PIND, &PORTD, 3}, // D3 11 + {&DDRD, &PIND, &PORTD, 4}, // D4 12 + {&DDRD, &PIND, &PORTD, 5}, // D5 13 + {&DDRD, &PIND, &PORTD, 6}, // D6 14 + {&DDRD, &PIND, &PORTD, 7}, // D7 15 + {&DDRC, &PINC, &PORTC, 0}, // C0 16 + {&DDRC, &PINC, &PORTC, 1}, // C1 17 + {&DDRC, &PINC, &PORTC, 2}, // C2 18 + {&DDRC, &PINC, &PORTC, 3}, // C3 19 + {&DDRC, &PINC, &PORTC, 4}, // C4 20 + {&DDRC, &PINC, &PORTC, 5}, // C5 21 + {&DDRC, &PINC, &PORTC, 6}, // C6 22 + {&DDRC, &PINC, &PORTC, 7}, // C7 23 + {&DDRA, &PINA, &PORTA, 7}, // A7 24 + {&DDRA, &PINA, &PORTA, 6}, // A6 25 + {&DDRA, &PINA, &PORTA, 5}, // A5 26 + {&DDRA, &PINA, &PORTA, 4}, // A4 27 + {&DDRA, &PINA, &PORTA, 3}, // A3 28 + {&DDRA, &PINA, &PORTA, 2}, // A2 29 + {&DDRA, &PINA, &PORTA, 1}, // A1 30 + {&DDRA, &PINA, &PORTA, 0} // A0 31 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_ATmega32U4__) +// Teensy 2.0 + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 6; +uint8_t const SCL_PIN = 5; + +// SPI port +uint8_t const SS_PIN = 0; +uint8_t const MOSI_PIN = 2; +uint8_t const MISO_PIN = 3; +uint8_t const SCK_PIN = 1; + +static const pin_map_t digitalPinMap[] = { + {&DDRB, &PINB, &PORTB, 0}, // B0 0 + {&DDRB, &PINB, &PORTB, 1}, // B1 1 + {&DDRB, &PINB, &PORTB, 2}, // B2 2 + {&DDRB, &PINB, &PORTB, 3}, // B3 3 + {&DDRB, &PINB, &PORTB, 7}, // B7 4 + {&DDRD, &PIND, &PORTD, 0}, // D0 5 + {&DDRD, &PIND, &PORTD, 1}, // D1 6 + {&DDRD, &PIND, &PORTD, 2}, // D2 7 + {&DDRD, &PIND, &PORTD, 3}, // D3 8 + {&DDRC, &PINC, &PORTC, 6}, // C6 9 + {&DDRC, &PINC, &PORTC, 7}, // C7 10 + {&DDRD, &PIND, &PORTD, 6}, // D6 11 + {&DDRD, &PIND, &PORTD, 7}, // D7 12 + {&DDRB, &PINB, &PORTB, 4}, // B4 13 + {&DDRB, &PINB, &PORTB, 5}, // B5 14 + {&DDRB, &PINB, &PORTB, 6}, // B6 15 + {&DDRF, &PINF, &PORTF, 7}, // F7 16 + {&DDRF, &PINF, &PORTF, 6}, // F6 17 + {&DDRF, &PINF, &PORTF, 5}, // F5 18 + {&DDRF, &PINF, &PORTF, 4}, // F4 19 + {&DDRF, &PINF, &PORTF, 1}, // F1 20 + {&DDRF, &PINF, &PORTF, 0}, // F0 21 + {&DDRD, &PIND, &PORTD, 4}, // D4 22 + {&DDRD, &PIND, &PORTD, 5}, // D5 23 + {&DDRE, &PINE, &PORTE, 6} // E6 24 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +// Teensy++ 1.0 & 2.0 + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 1; +uint8_t const SCL_PIN = 0; + +// SPI port +uint8_t const SS_PIN = 20; +uint8_t const MOSI_PIN = 22; +uint8_t const MISO_PIN = 23; +uint8_t const SCK_PIN = 21; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PIND, &PORTD, 0}, // D0 0 + {&DDRD, &PIND, &PORTD, 1}, // D1 1 + {&DDRD, &PIND, &PORTD, 2}, // D2 2 + {&DDRD, &PIND, &PORTD, 3}, // D3 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRD, &PIND, &PORTD, 5}, // D5 5 + {&DDRD, &PIND, &PORTD, 6}, // D6 6 + {&DDRD, &PIND, &PORTD, 7}, // D7 7 + {&DDRE, &PINE, &PORTE, 0}, // E0 8 + {&DDRE, &PINE, &PORTE, 1}, // E1 9 + {&DDRC, &PINC, &PORTC, 0}, // C0 10 + {&DDRC, &PINC, &PORTC, 1}, // C1 11 + {&DDRC, &PINC, &PORTC, 2}, // C2 12 + {&DDRC, &PINC, &PORTC, 3}, // C3 13 + {&DDRC, &PINC, &PORTC, 4}, // C4 14 + {&DDRC, &PINC, &PORTC, 5}, // C5 15 + {&DDRC, &PINC, &PORTC, 6}, // C6 16 + {&DDRC, &PINC, &PORTC, 7}, // C7 17 + {&DDRE, &PINE, &PORTE, 6}, // E6 18 + {&DDRE, &PINE, &PORTE, 7}, // E7 19 + {&DDRB, &PINB, &PORTB, 0}, // B0 20 + {&DDRB, &PINB, &PORTB, 1}, // B1 21 + {&DDRB, &PINB, &PORTB, 2}, // B2 22 + {&DDRB, &PINB, &PORTB, 3}, // B3 23 + {&DDRB, &PINB, &PORTB, 4}, // B4 24 + {&DDRB, &PINB, &PORTB, 5}, // B5 25 + {&DDRB, &PINB, &PORTB, 6}, // B6 26 + {&DDRB, &PINB, &PORTB, 7}, // B7 27 + {&DDRA, &PINA, &PORTA, 0}, // A0 28 + {&DDRA, &PINA, &PORTA, 1}, // A1 29 + {&DDRA, &PINA, &PORTA, 2}, // A2 30 + {&DDRA, &PINA, &PORTA, 3}, // A3 31 + {&DDRA, &PINA, &PORTA, 4}, // A4 32 + {&DDRA, &PINA, &PORTA, 5}, // A5 33 + {&DDRA, &PINA, &PORTA, 6}, // A6 34 + {&DDRA, &PINA, &PORTA, 7}, // A7 35 + {&DDRE, &PINE, &PORTE, 4}, // E4 36 + {&DDRE, &PINE, &PORTE, 5}, // E5 37 + {&DDRF, &PINF, &PORTF, 0}, // F0 38 + {&DDRF, &PINF, &PORTF, 1}, // F1 39 + {&DDRF, &PINF, &PORTF, 2}, // F2 40 + {&DDRF, &PINF, &PORTF, 3}, // F3 41 + {&DDRF, &PINF, &PORTF, 4}, // F4 42 + {&DDRF, &PINF, &PORTF, 5}, // F5 43 + {&DDRF, &PINF, &PORTF, 6}, // F6 44 + {&DDRF, &PINF, &PORTF, 7} // F7 45 +}; +//------------------------------------------------------------------------------ +#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +// 168 and 328 Arduinos + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 18; +uint8_t const SCL_PIN = 19; + +// SPI port +uint8_t const SS_PIN = 10; +uint8_t const MOSI_PIN = 11; +uint8_t const MISO_PIN = 12; +uint8_t const SCK_PIN = 13; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PIND, &PORTD, 0}, // D0 0 + {&DDRD, &PIND, &PORTD, 1}, // D1 1 + {&DDRD, &PIND, &PORTD, 2}, // D2 2 + {&DDRD, &PIND, &PORTD, 3}, // D3 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRD, &PIND, &PORTD, 5}, // D5 5 + {&DDRD, &PIND, &PORTD, 6}, // D6 6 + {&DDRD, &PIND, &PORTD, 7}, // D7 7 + {&DDRB, &PINB, &PORTB, 0}, // B0 8 + {&DDRB, &PINB, &PORTB, 1}, // B1 9 + {&DDRB, &PINB, &PORTB, 2}, // B2 10 + {&DDRB, &PINB, &PORTB, 3}, // B3 11 + {&DDRB, &PINB, &PORTB, 4}, // B4 12 + {&DDRB, &PINB, &PORTB, 5}, // B5 13 + {&DDRC, &PINC, &PORTC, 0}, // C0 14 + {&DDRC, &PINC, &PORTC, 1}, // C1 15 + {&DDRC, &PINC, &PORTC, 2}, // C2 16 + {&DDRC, &PINC, &PORTC, 3}, // C3 17 + {&DDRC, &PINC, &PORTC, 4}, // C4 18 + {&DDRC, &PINC, &PORTC, 5} // C5 19 +}; +#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +//------------------------------------------------------------------------------ +static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t); + +uint8_t badPinNumber(void) + __attribute__((error("Pin number is too large or not a constant"))); + +static inline __attribute__((always_inline)) + uint8_t getPinMode(uint8_t pin) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1; + } else { + return badPinNumber(); + } +} +static inline __attribute__((always_inline)) + void setPinMode(uint8_t pin, uint8_t mode) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + if (mode) { + *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit; + } else { + *digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit); + } + } else { + badPinNumber(); + } +} +static inline __attribute__((always_inline)) + uint8_t fastDigitalRead(uint8_t pin) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1; + } else { + return badPinNumber(); + } +} +static inline __attribute__((always_inline)) + void fastDigitalWrite(uint8_t pin, uint8_t value) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + if (value) { + *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit; + } else { + *digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit); + } + } else { + badPinNumber(); + } +} +#endif // Sd2PinMap_h diff --git a/Marlin/SdFat.h b/Marlin/SdFat.h index aa018dd13e..048fa711ec 100644 --- a/Marlin/SdFat.h +++ b/Marlin/SdFat.h @@ -1,547 +1,547 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFat_h -#define SdFat_h -/** - * \file - * SdFile and SdVolume classes - */ -#include -#include "Sd2Card.h" -#include "FatStructs.h" -#include "Print.h" -//------------------------------------------------------------------------------ -/** - * Allow use of deprecated functions if non-zero - */ -#define ALLOW_DEPRECATED_FUNCTIONS 1 -//------------------------------------------------------------------------------ -// forward declaration since SdVolume is used in SdFile -class SdVolume; -//============================================================================== -// SdFile class - -// flags for ls() -/** ls() flag to print modify date */ -uint8_t const LS_DATE = 1; -/** ls() flag to print file size */ -uint8_t const LS_SIZE = 2; -/** ls() flag for recursive list of subdirectories */ -uint8_t const LS_R = 4; - -// use the gnu style oflag in open() -/** open() oflag for reading */ -uint8_t const O_READ = 0X01; -/** open() oflag - same as O_READ */ -uint8_t const O_RDONLY = O_READ; -/** open() oflag for write */ -uint8_t const O_WRITE = 0X02; -/** open() oflag - same as O_WRITE */ -uint8_t const O_WRONLY = O_WRITE; -/** open() oflag for reading and writing */ -uint8_t const O_RDWR = (O_READ | O_WRITE); -/** open() oflag mask for access modes */ -uint8_t const O_ACCMODE = (O_READ | O_WRITE); -/** The file offset shall be set to the end of the file prior to each write. */ -uint8_t const O_APPEND = 0X04; -/** synchronous writes - call sync() after each write */ -uint8_t const O_SYNC = 0X08; -/** create the file if nonexistent */ -uint8_t const O_CREAT = 0X10; -/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ -uint8_t const O_EXCL = 0X20; -/** truncate the file to zero length */ -uint8_t const O_TRUNC = 0X40; - -// flags for timestamp -/** set the file's last access date */ -uint8_t const T_ACCESS = 1; -/** set the file's creation date and time */ -uint8_t const T_CREATE = 2; -/** Set the file's write date and time */ -uint8_t const T_WRITE = 4; -// values for type_ -/** This SdFile has not been opened. */ -uint8_t const FAT_FILE_TYPE_CLOSED = 0; -/** SdFile for a file */ -uint8_t const FAT_FILE_TYPE_NORMAL = 1; -/** SdFile for a FAT16 root directory */ -uint8_t const FAT_FILE_TYPE_ROOT16 = 2; -/** SdFile for a FAT32 root directory */ -uint8_t const FAT_FILE_TYPE_ROOT32 = 3; -/** SdFile for a subdirectory */ -uint8_t const FAT_FILE_TYPE_SUBDIR = 4; -/** Test value for directory type */ -uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; - -/** date field for FAT directory entry */ -static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { - return (year - 1980) << 9 | month << 5 | day; -} -/** year part of FAT directory date field */ -static inline uint16_t FAT_YEAR(uint16_t fatDate) { - return 1980 + (fatDate >> 9); -} -/** month part of FAT directory date field */ -static inline uint8_t FAT_MONTH(uint16_t fatDate) { - return (fatDate >> 5) & 0XF; -} -/** day part of FAT directory date field */ -static inline uint8_t FAT_DAY(uint16_t fatDate) { - return fatDate & 0X1F; -} -/** time field for FAT directory entry */ -static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { - return hour << 11 | minute << 5 | second >> 1; -} -/** hour part of FAT directory time field */ -static inline uint8_t FAT_HOUR(uint16_t fatTime) { - return fatTime >> 11; -} -/** minute part of FAT directory time field */ -static inline uint8_t FAT_MINUTE(uint16_t fatTime) { - return(fatTime >> 5) & 0X3F; -} -/** second part of FAT directory time field */ -static inline uint8_t FAT_SECOND(uint16_t fatTime) { - return 2*(fatTime & 0X1F); -} -/** Default date for file timestamps is 1 Jan 2000 */ -uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; -/** Default time for file timestamp is 1 am */ -uint16_t const FAT_DEFAULT_TIME = (1 << 11); -//------------------------------------------------------------------------------ -/** - * \class SdFile - * \brief Access FAT16 and FAT32 files on SD and SDHC cards. - */ -class SdFile : public Print { - public: - /** Create an instance of SdFile. */ - SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} - /** - * writeError is set to true if an error occurs during a write(). - * Set writeError to false before calling print() and/or write() and check - * for true after calls to print() and/or write(). - */ - bool writeError; - /** - * Cancel unbuffered reads for this file. - * See setUnbufferedRead() - */ - void clearUnbufferedRead(void) { - flags_ &= ~F_FILE_UNBUFFERED_READ; - } - uint8_t close(void); - uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - uint8_t createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size); - /** \return The current cluster number for a file or directory. */ - uint32_t curCluster(void) const {return curCluster_;} - /** \return The current position for a file or directory. */ - uint32_t curPosition(void) const {return curPosition_;} - /** - * Set the date/time callback function - * - * \param[in] dateTime The user's call back function. The callback - * function is of the form: - * - * \code - * void dateTime(uint16_t* date, uint16_t* time) { - * uint16_t year; - * uint8_t month, day, hour, minute, second; - * - * // User gets date and time from GPS or real-time clock here - * - * // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); - * - * // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); - * } - * \endcode - * - * Sets the function that is called when a file is created or when - * a file's directory entry is modified by sync(). All timestamps, - * access, creation, and modify, are set when a file is created. - * sync() maintains the last access date and last modify date/time. - * - * See the timestamp() function. - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)) { - dateTime_ = dateTime; - } - /** - * Cancel the date/time callback function. - */ - static void dateTimeCallbackCancel(void) { - // use explicit zero since NULL is not defined for Sanguino - dateTime_ = 0; - } - /** \return Address of the block that contains this file's directory. */ - uint32_t dirBlock(void) const {return dirBlock_;} - uint8_t dirEntry(dir_t* dir); - /** \return Index of this file's directory in the block dirBlock. */ - uint8_t dirIndex(void) const {return dirIndex_;} - static void dirName(const dir_t& dir, char* name); - /** \return The total number of bytes in a file or directory. */ - uint32_t fileSize(void) const {return fileSize_;} - /** \return The first cluster number for a file or directory. */ - uint32_t firstCluster(void) const {return firstCluster_;} - /** \return True if this is a SdFile for a directory else false. */ - uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;} - /** \return True if this is a SdFile for a file else false. */ - uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;} - /** \return True if this is a SdFile for an open file/directory else false. */ - uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;} - /** \return True if this is a SdFile for a subdirectory else false. */ - uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;} - /** \return True if this is a SdFile for the root directory. */ - uint8_t isRoot(void) const { - return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; - } - void ls(uint8_t flags = 0, uint8_t indent = 0); - uint8_t makeDir(SdFile* dir, const char* dirName); - uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag); - uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag); - - uint8_t openRoot(SdVolume* vol); - static void printDirName(const dir_t& dir, uint8_t width); - static void printFatDate(uint16_t fatDate); - static void printFatTime(uint16_t fatTime); - static void printTwoDigits(uint8_t v); - /** - * Read the next byte from a file. - * - * \return For success read returns the next byte in the file as an int. - * If an error occurs or end of file is reached -1 is returned. - */ - int16_t read(void) { - uint8_t b; - return read(&b, 1) == 1 ? b : -1; - } - int16_t read(void* buf, uint16_t nbyte); - int8_t readDir(dir_t* dir); - static uint8_t remove(SdFile* dirFile, const char* fileName); - uint8_t remove(void); - /** Set the file's current position to zero. */ - void rewind(void) { - curPosition_ = curCluster_ = 0; - } - uint8_t rmDir(void); - uint8_t rmRfStar(void); - /** Set the files position to current position + \a pos. See seekSet(). */ - uint8_t seekCur(uint32_t pos) { - return seekSet(curPosition_ + pos); - } - /** - * Set the files current position to end of file. Useful to position - * a file for append. See seekSet(). - */ - uint8_t seekEnd(void) {return seekSet(fileSize_);} - uint8_t seekSet(uint32_t pos); - /** - * Use unbuffered reads to access this file. Used with Wave - * Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. - * - * Not recommended for normal applications. - */ - void setUnbufferedRead(void) { - if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ; - } - uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, - uint8_t hour, uint8_t minute, uint8_t second); - uint8_t sync(void); - /** Type of this SdFile. You should use isFile() or isDir() instead of type() - * if possible. - * - * \return The file or directory type. - */ - uint8_t type(void) const {return type_;} - uint8_t truncate(uint32_t size); - /** \return Unbuffered read flag. */ - uint8_t unbufferedRead(void) const { - return flags_ & F_FILE_UNBUFFERED_READ; - } - /** \return SdVolume that contains this file. */ - SdVolume* volume(void) const {return vol_;} - void write(uint8_t b); - int16_t write(const void* buf, uint16_t nbyte); - void write(const char* str); - void write_P(PGM_P str); - void writeln_P(PGM_P str); -//------------------------------------------------------------------------------ -#if ALLOW_DEPRECATED_FUNCTIONS -// Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: - * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - */ - uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT - return contiguousRange(&bgnBlock, &endBlock); - } - /** \deprecated Use: - * uint8_t SdFile::createContiguous(SdFile* dirFile, - * const char* fileName, uint32_t size) - */ - uint8_t createContiguous(SdFile& dirFile, // NOLINT - const char* fileName, uint32_t size) { - return createContiguous(&dirFile, fileName, size); - } - - /** - * \deprecated Use: - * static void SdFile::dateTimeCallback( - * void (*dateTime)(uint16_t* date, uint16_t* time)); - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT - oldDateTime_ = dateTime; - dateTime_ = dateTime ? oldToNew : 0; - } - /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ - uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT - /** \deprecated Use: - * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); - */ - uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT - return makeDir(&dir, dirName); - } - /** \deprecated Use: - * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, // NOLINT - const char* fileName, uint8_t oflag) { - return open(&dirFile, fileName, oflag); - } - /** \deprecated Do not use in new apps */ - uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT - return open(dirFile, fileName, O_RDWR); - } - /** \deprecated Use: - * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT - return open(&dirFile, index, oflag); - } - /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ - uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT - - /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ - int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT - /** \deprecated Use: - * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); - */ - static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT - return remove(&dirFile, fileName); - } -//------------------------------------------------------------------------------ -// rest are private - private: - static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT - static void oldToNew(uint16_t* date, uint16_t* time) { - uint16_t d; - uint16_t t; - oldDateTime_(d, t); - *date = d; - *time = t; - } -#endif // ALLOW_DEPRECATED_FUNCTIONS - private: - // bits defined in flags_ - // should be 0XF - static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); - // available bits - static uint8_t const F_UNUSED = 0X30; - // use unbuffered SD read - static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; - // sync of directory entry required - static uint8_t const F_FILE_DIR_DIRTY = 0X80; - -// make sure F_OFLAG is ok -#if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG) -#error flags_ bits conflict -#endif // flags_ bits - - // private data - uint8_t flags_; // See above for definition of flags_ bits - uint8_t type_; // type of file see above for values - uint32_t curCluster_; // cluster for current file position - uint32_t curPosition_; // current file position in bytes from beginning - uint32_t dirBlock_; // SD block that contains directory entry for file - uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF - uint32_t fileSize_; // file size in bytes - uint32_t firstCluster_; // first cluster of file - SdVolume* vol_; // volume where file is located - - // private functions - uint8_t addCluster(void); - uint8_t addDirCluster(void); - dir_t* cacheDirEntry(uint8_t action); - static void (*dateTime_)(uint16_t* date, uint16_t* time); - static uint8_t make83Name(const char* str, uint8_t* name); - uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); - dir_t* readDirCache(void); -}; -//============================================================================== -// SdVolume class -/** - * \brief Cache for an SD data block - */ -union cache_t { - /** Used to access cached file data blocks. */ - uint8_t data[512]; - /** Used to access cached FAT16 entries. */ - uint16_t fat16[256]; - /** Used to access cached FAT32 entries. */ - uint32_t fat32[128]; - /** Used to access cached directory entries. */ - dir_t dir[16]; - /** Used to access a cached MasterBoot Record. */ - mbr_t mbr; - /** Used to access to a cached FAT boot sector. */ - fbs_t fbs; -}; -//------------------------------------------------------------------------------ -/** - * \class SdVolume - * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. - */ -class SdVolume { - public: - /** Create an instance of SdVolume */ - SdVolume(void) :allocSearchStart_(2), fatType_(0) {} - /** Clear the cache and returns a pointer to the cache. Used by the WaveRP - * recorder to do raw write to the SD card. Not for normal apps. - */ - static uint8_t* cacheClear(void) { - cacheFlush(); - cacheBlockNumber_ = 0XFFFFFFFF; - return cacheBuffer_.data; - } - /** - * Initialize a FAT volume. Try partition one first then try super - * floppy format. - * - * \param[in] dev The Sd2Card where the volume is located. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. Reasons for - * failure include not finding a valid partition, not finding a valid - * FAT file system or an I/O error. - */ - uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);} - uint8_t init(Sd2Card* dev, uint8_t part); - - // inline functions that return volume info - /** \return The volume's cluster size in blocks. */ - uint8_t blocksPerCluster(void) const {return blocksPerCluster_;} - /** \return The number of blocks in one FAT. */ - uint32_t blocksPerFat(void) const {return blocksPerFat_;} - /** \return The total number of clusters in the volume. */ - uint32_t clusterCount(void) const {return clusterCount_;} - /** \return The shift count required to multiply by blocksPerCluster. */ - uint8_t clusterSizeShift(void) const {return clusterSizeShift_;} - /** \return The logical block number for the start of file data. */ - uint32_t dataStartBlock(void) const {return dataStartBlock_;} - /** \return The number of FAT structures on the volume. */ - uint8_t fatCount(void) const {return fatCount_;} - /** \return The logical block number for the start of the first FAT. */ - uint32_t fatStartBlock(void) const {return fatStartBlock_;} - /** \return The FAT type of the volume. Values are 12, 16 or 32. */ - uint8_t fatType(void) const {return fatType_;} - /** \return The number of entries in the root directory for FAT16 volumes. */ - uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;} - /** \return The logical block number for the start of the root directory - on FAT16 volumes or the first cluster number on FAT32 volumes. */ - uint32_t rootDirStart(void) const {return rootDirStart_;} - /** return a pointer to the Sd2Card object for this volume */ - static Sd2Card* sdCard(void) {return sdCard_;} -//------------------------------------------------------------------------------ -#if ALLOW_DEPRECATED_FUNCTIONS - // Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ - uint8_t init(Sd2Card& dev) {return init(&dev);} // NOLINT - - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ - uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT - return init(&dev, part); - } -#endif // ALLOW_DEPRECATED_FUNCTIONS -//------------------------------------------------------------------------------ - private: - // Allow SdFile access to SdVolume private data. - friend class SdFile; - - // value for action argument in cacheRawBlock to indicate read from cache - static uint8_t const CACHE_FOR_READ = 0; - // value for action argument in cacheRawBlock to indicate cache dirty - static uint8_t const CACHE_FOR_WRITE = 1; - - static cache_t cacheBuffer_; // 512 byte cache for device blocks - static uint32_t cacheBlockNumber_; // Logical number of block in the cache - static Sd2Card* sdCard_; // Sd2Card object for cache - static uint8_t cacheDirty_; // cacheFlush() will write block if true - static uint32_t cacheMirrorBlock_; // block number for mirror FAT -// - uint32_t allocSearchStart_; // start cluster for alloc search - uint8_t blocksPerCluster_; // cluster size in blocks - uint32_t blocksPerFat_; // FAT size in blocks - uint32_t clusterCount_; // clusters in one FAT - uint8_t clusterSizeShift_; // shift to convert cluster count to block count - uint32_t dataStartBlock_; // first data block number - uint8_t fatCount_; // number of FATs on volume - uint32_t fatStartBlock_; // start block for first FAT - uint8_t fatType_; // volume type (12, 16, OR 32) - uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir - uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 - //---------------------------------------------------------------------------- - uint8_t allocContiguous(uint32_t count, uint32_t* curCluster); - uint8_t blockOfCluster(uint32_t position) const { - return (position >> 9) & (blocksPerCluster_ - 1);} - uint32_t clusterStartBlock(uint32_t cluster) const { - return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} - uint32_t blockNumber(uint32_t cluster, uint32_t position) const { - return clusterStartBlock(cluster) + blockOfCluster(position);} - static uint8_t cacheFlush(void); - static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); - static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;} - static uint8_t cacheZeroBlock(uint32_t blockNumber); - uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const; - uint8_t fatGet(uint32_t cluster, uint32_t* value) const; - uint8_t fatPut(uint32_t cluster, uint32_t value); - uint8_t fatPutEOC(uint32_t cluster) { - return fatPut(cluster, 0x0FFFFFFF); - } - uint8_t freeChain(uint32_t cluster); - uint8_t isEOC(uint32_t cluster) const { - return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); - } - uint8_t readBlock(uint32_t block, uint8_t* dst) { - return sdCard_->readBlock(block, dst);} - uint8_t readData(uint32_t block, uint16_t offset, - uint16_t count, uint8_t* dst) { - return sdCard_->readData(block, offset, count, dst); - } - uint8_t writeBlock(uint32_t block, const uint8_t* dst) { - return sdCard_->writeBlock(block, dst); - } -}; -#endif // SdFat_h +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdFat_h +#define SdFat_h +/** + * \file + * SdFile and SdVolume classes + */ +#include +#include "Sd2Card.h" +#include "FatStructs.h" +#include "Print.h" +//------------------------------------------------------------------------------ +/** + * Allow use of deprecated functions if non-zero + */ +#define ALLOW_DEPRECATED_FUNCTIONS 1 +//------------------------------------------------------------------------------ +// forward declaration since SdVolume is used in SdFile +class SdVolume; +//============================================================================== +// SdFile class + +// flags for ls() +/** ls() flag to print modify date */ +uint8_t const LS_DATE = 1; +/** ls() flag to print file size */ +uint8_t const LS_SIZE = 2; +/** ls() flag for recursive list of subdirectories */ +uint8_t const LS_R = 4; + +// use the gnu style oflag in open() +/** open() oflag for reading */ +uint8_t const O_READ = 0X01; +/** open() oflag - same as O_READ */ +uint8_t const O_RDONLY = O_READ; +/** open() oflag for write */ +uint8_t const O_WRITE = 0X02; +/** open() oflag - same as O_WRITE */ +uint8_t const O_WRONLY = O_WRITE; +/** open() oflag for reading and writing */ +uint8_t const O_RDWR = (O_READ | O_WRITE); +/** open() oflag mask for access modes */ +uint8_t const O_ACCMODE = (O_READ | O_WRITE); +/** The file offset shall be set to the end of the file prior to each write. */ +uint8_t const O_APPEND = 0X04; +/** synchronous writes - call sync() after each write */ +uint8_t const O_SYNC = 0X08; +/** create the file if nonexistent */ +uint8_t const O_CREAT = 0X10; +/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ +uint8_t const O_EXCL = 0X20; +/** truncate the file to zero length */ +uint8_t const O_TRUNC = 0X40; + +// flags for timestamp +/** set the file's last access date */ +uint8_t const T_ACCESS = 1; +/** set the file's creation date and time */ +uint8_t const T_CREATE = 2; +/** Set the file's write date and time */ +uint8_t const T_WRITE = 4; +// values for type_ +/** This SdFile has not been opened. */ +uint8_t const FAT_FILE_TYPE_CLOSED = 0; +/** SdFile for a file */ +uint8_t const FAT_FILE_TYPE_NORMAL = 1; +/** SdFile for a FAT16 root directory */ +uint8_t const FAT_FILE_TYPE_ROOT16 = 2; +/** SdFile for a FAT32 root directory */ +uint8_t const FAT_FILE_TYPE_ROOT32 = 3; +/** SdFile for a subdirectory */ +uint8_t const FAT_FILE_TYPE_SUBDIR = 4; +/** Test value for directory type */ +uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; + +/** date field for FAT directory entry */ +static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { + return (year - 1980) << 9 | month << 5 | day; +} +/** year part of FAT directory date field */ +static inline uint16_t FAT_YEAR(uint16_t fatDate) { + return 1980 + (fatDate >> 9); +} +/** month part of FAT directory date field */ +static inline uint8_t FAT_MONTH(uint16_t fatDate) { + return (fatDate >> 5) & 0XF; +} +/** day part of FAT directory date field */ +static inline uint8_t FAT_DAY(uint16_t fatDate) { + return fatDate & 0X1F; +} +/** time field for FAT directory entry */ +static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { + return hour << 11 | minute << 5 | second >> 1; +} +/** hour part of FAT directory time field */ +static inline uint8_t FAT_HOUR(uint16_t fatTime) { + return fatTime >> 11; +} +/** minute part of FAT directory time field */ +static inline uint8_t FAT_MINUTE(uint16_t fatTime) { + return(fatTime >> 5) & 0X3F; +} +/** second part of FAT directory time field */ +static inline uint8_t FAT_SECOND(uint16_t fatTime) { + return 2*(fatTime & 0X1F); +} +/** Default date for file timestamps is 1 Jan 2000 */ +uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; +/** Default time for file timestamp is 1 am */ +uint16_t const FAT_DEFAULT_TIME = (1 << 11); +//------------------------------------------------------------------------------ +/** + * \class SdFile + * \brief Access FAT16 and FAT32 files on SD and SDHC cards. + */ +class SdFile : public Print { + public: + /** Create an instance of SdFile. */ + SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} + /** + * writeError is set to true if an error occurs during a write(). + * Set writeError to false before calling print() and/or write() and check + * for true after calls to print() and/or write(). + */ + bool writeError; + /** + * Cancel unbuffered reads for this file. + * See setUnbufferedRead() + */ + void clearUnbufferedRead(void) { + flags_ &= ~F_FILE_UNBUFFERED_READ; + } + uint8_t close(void); + uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); + uint8_t createContiguous(SdFile* dirFile, + const char* fileName, uint32_t size); + /** \return The current cluster number for a file or directory. */ + uint32_t curCluster(void) const {return curCluster_;} + /** \return The current position for a file or directory. */ + uint32_t curPosition(void) const {return curPosition_;} + /** + * Set the date/time callback function + * + * \param[in] dateTime The user's call back function. The callback + * function is of the form: + * + * \code + * void dateTime(uint16_t* date, uint16_t* time) { + * uint16_t year; + * uint8_t month, day, hour, minute, second; + * + * // User gets date and time from GPS or real-time clock here + * + * // return date using FAT_DATE macro to format fields + * *date = FAT_DATE(year, month, day); + * + * // return time using FAT_TIME macro to format fields + * *time = FAT_TIME(hour, minute, second); + * } + * \endcode + * + * Sets the function that is called when a file is created or when + * a file's directory entry is modified by sync(). All timestamps, + * access, creation, and modify, are set when a file is created. + * sync() maintains the last access date and last modify date/time. + * + * See the timestamp() function. + */ + static void dateTimeCallback( + void (*dateTime)(uint16_t* date, uint16_t* time)) { + dateTime_ = dateTime; + } + /** + * Cancel the date/time callback function. + */ + static void dateTimeCallbackCancel(void) { + // use explicit zero since NULL is not defined for Sanguino + dateTime_ = 0; + } + /** \return Address of the block that contains this file's directory. */ + uint32_t dirBlock(void) const {return dirBlock_;} + uint8_t dirEntry(dir_t* dir); + /** \return Index of this file's directory in the block dirBlock. */ + uint8_t dirIndex(void) const {return dirIndex_;} + static void dirName(const dir_t& dir, char* name); + /** \return The total number of bytes in a file or directory. */ + uint32_t fileSize(void) const {return fileSize_;} + /** \return The first cluster number for a file or directory. */ + uint32_t firstCluster(void) const {return firstCluster_;} + /** \return True if this is a SdFile for a directory else false. */ + uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;} + /** \return True if this is a SdFile for a file else false. */ + uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;} + /** \return True if this is a SdFile for an open file/directory else false. */ + uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;} + /** \return True if this is a SdFile for a subdirectory else false. */ + uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;} + /** \return True if this is a SdFile for the root directory. */ + uint8_t isRoot(void) const { + return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; + } + void ls(uint8_t flags = 0, uint8_t indent = 0); + uint8_t makeDir(SdFile* dir, const char* dirName); + uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag); + uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag); + + uint8_t openRoot(SdVolume* vol); + static void printDirName(const dir_t& dir, uint8_t width); + static void printFatDate(uint16_t fatDate); + static void printFatTime(uint16_t fatTime); + static void printTwoDigits(uint8_t v); + /** + * Read the next byte from a file. + * + * \return For success read returns the next byte in the file as an int. + * If an error occurs or end of file is reached -1 is returned. + */ + int16_t read(void) { + uint8_t b; + return read(&b, 1) == 1 ? b : -1; + } + int16_t read(void* buf, uint16_t nbyte); + int8_t readDir(dir_t* dir); + static uint8_t remove(SdFile* dirFile, const char* fileName); + uint8_t remove(void); + /** Set the file's current position to zero. */ + void rewind(void) { + curPosition_ = curCluster_ = 0; + } + uint8_t rmDir(void); + uint8_t rmRfStar(void); + /** Set the files position to current position + \a pos. See seekSet(). */ + uint8_t seekCur(uint32_t pos) { + return seekSet(curPosition_ + pos); + } + /** + * Set the files current position to end of file. Useful to position + * a file for append. See seekSet(). + */ + uint8_t seekEnd(void) {return seekSet(fileSize_);} + uint8_t seekSet(uint32_t pos); + /** + * Use unbuffered reads to access this file. Used with Wave + * Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. + * + * Not recommended for normal applications. + */ + void setUnbufferedRead(void) { + if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ; + } + uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, + uint8_t hour, uint8_t minute, uint8_t second); + uint8_t sync(void); + /** Type of this SdFile. You should use isFile() or isDir() instead of type() + * if possible. + * + * \return The file or directory type. + */ + uint8_t type(void) const {return type_;} + uint8_t truncate(uint32_t size); + /** \return Unbuffered read flag. */ + uint8_t unbufferedRead(void) const { + return flags_ & F_FILE_UNBUFFERED_READ; + } + /** \return SdVolume that contains this file. */ + SdVolume* volume(void) const {return vol_;} + void write(uint8_t b); + int16_t write(const void* buf, uint16_t nbyte); + void write(const char* str); + void write_P(PGM_P str); + void writeln_P(PGM_P str); +//------------------------------------------------------------------------------ +#if ALLOW_DEPRECATED_FUNCTIONS +// Deprecated functions - suppress cpplint warnings with NOLINT comment + /** \deprecated Use: + * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); + */ + uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT + return contiguousRange(&bgnBlock, &endBlock); + } + /** \deprecated Use: + * uint8_t SdFile::createContiguous(SdFile* dirFile, + * const char* fileName, uint32_t size) + */ + uint8_t createContiguous(SdFile& dirFile, // NOLINT + const char* fileName, uint32_t size) { + return createContiguous(&dirFile, fileName, size); + } + + /** + * \deprecated Use: + * static void SdFile::dateTimeCallback( + * void (*dateTime)(uint16_t* date, uint16_t* time)); + */ + static void dateTimeCallback( + void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT + oldDateTime_ = dateTime; + dateTime_ = dateTime ? oldToNew : 0; + } + /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ + uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT + /** \deprecated Use: + * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); + */ + uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT + return makeDir(&dir, dirName); + } + /** \deprecated Use: + * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); + */ + uint8_t open(SdFile& dirFile, // NOLINT + const char* fileName, uint8_t oflag) { + return open(&dirFile, fileName, oflag); + } + /** \deprecated Do not use in new apps */ + uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT + return open(dirFile, fileName, O_RDWR); + } + /** \deprecated Use: + * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); + */ + uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT + return open(&dirFile, index, oflag); + } + /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ + uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT + + /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ + int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT + /** \deprecated Use: + * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); + */ + static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT + return remove(&dirFile, fileName); + } +//------------------------------------------------------------------------------ +// rest are private + private: + static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT + static void oldToNew(uint16_t* date, uint16_t* time) { + uint16_t d; + uint16_t t; + oldDateTime_(d, t); + *date = d; + *time = t; + } +#endif // ALLOW_DEPRECATED_FUNCTIONS + private: + // bits defined in flags_ + // should be 0XF + static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); + // available bits + static uint8_t const F_UNUSED = 0X30; + // use unbuffered SD read + static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; + // sync of directory entry required + static uint8_t const F_FILE_DIR_DIRTY = 0X80; + +// make sure F_OFLAG is ok +#if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG) +#error flags_ bits conflict +#endif // flags_ bits + + // private data + uint8_t flags_; // See above for definition of flags_ bits + uint8_t type_; // type of file see above for values + uint32_t curCluster_; // cluster for current file position + uint32_t curPosition_; // current file position in bytes from beginning + uint32_t dirBlock_; // SD block that contains directory entry for file + uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF + uint32_t fileSize_; // file size in bytes + uint32_t firstCluster_; // first cluster of file + SdVolume* vol_; // volume where file is located + + // private functions + uint8_t addCluster(void); + uint8_t addDirCluster(void); + dir_t* cacheDirEntry(uint8_t action); + static void (*dateTime_)(uint16_t* date, uint16_t* time); + static uint8_t make83Name(const char* str, uint8_t* name); + uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); + dir_t* readDirCache(void); +}; +//============================================================================== +// SdVolume class +/** + * \brief Cache for an SD data block + */ +union cache_t { + /** Used to access cached file data blocks. */ + uint8_t data[512]; + /** Used to access cached FAT16 entries. */ + uint16_t fat16[256]; + /** Used to access cached FAT32 entries. */ + uint32_t fat32[128]; + /** Used to access cached directory entries. */ + dir_t dir[16]; + /** Used to access a cached MasterBoot Record. */ + mbr_t mbr; + /** Used to access to a cached FAT boot sector. */ + fbs_t fbs; +}; +//------------------------------------------------------------------------------ +/** + * \class SdVolume + * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. + */ +class SdVolume { + public: + /** Create an instance of SdVolume */ + SdVolume(void) :allocSearchStart_(2), fatType_(0) {} + /** Clear the cache and returns a pointer to the cache. Used by the WaveRP + * recorder to do raw write to the SD card. Not for normal apps. + */ + static uint8_t* cacheClear(void) { + cacheFlush(); + cacheBlockNumber_ = 0XFFFFFFFF; + return cacheBuffer_.data; + } + /** + * Initialize a FAT volume. Try partition one first then try super + * floppy format. + * + * \param[in] dev The Sd2Card where the volume is located. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. Reasons for + * failure include not finding a valid partition, not finding a valid + * FAT file system or an I/O error. + */ + uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);} + uint8_t init(Sd2Card* dev, uint8_t part); + + // inline functions that return volume info + /** \return The volume's cluster size in blocks. */ + uint8_t blocksPerCluster(void) const {return blocksPerCluster_;} + /** \return The number of blocks in one FAT. */ + uint32_t blocksPerFat(void) const {return blocksPerFat_;} + /** \return The total number of clusters in the volume. */ + uint32_t clusterCount(void) const {return clusterCount_;} + /** \return The shift count required to multiply by blocksPerCluster. */ + uint8_t clusterSizeShift(void) const {return clusterSizeShift_;} + /** \return The logical block number for the start of file data. */ + uint32_t dataStartBlock(void) const {return dataStartBlock_;} + /** \return The number of FAT structures on the volume. */ + uint8_t fatCount(void) const {return fatCount_;} + /** \return The logical block number for the start of the first FAT. */ + uint32_t fatStartBlock(void) const {return fatStartBlock_;} + /** \return The FAT type of the volume. Values are 12, 16 or 32. */ + uint8_t fatType(void) const {return fatType_;} + /** \return The number of entries in the root directory for FAT16 volumes. */ + uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;} + /** \return The logical block number for the start of the root directory + on FAT16 volumes or the first cluster number on FAT32 volumes. */ + uint32_t rootDirStart(void) const {return rootDirStart_;} + /** return a pointer to the Sd2Card object for this volume */ + static Sd2Card* sdCard(void) {return sdCard_;} +//------------------------------------------------------------------------------ +#if ALLOW_DEPRECATED_FUNCTIONS + // Deprecated functions - suppress cpplint warnings with NOLINT comment + /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ + uint8_t init(Sd2Card& dev) {return init(&dev);} // NOLINT + + /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ + uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT + return init(&dev, part); + } +#endif // ALLOW_DEPRECATED_FUNCTIONS +//------------------------------------------------------------------------------ + private: + // Allow SdFile access to SdVolume private data. + friend class SdFile; + + // value for action argument in cacheRawBlock to indicate read from cache + static uint8_t const CACHE_FOR_READ = 0; + // value for action argument in cacheRawBlock to indicate cache dirty + static uint8_t const CACHE_FOR_WRITE = 1; + + static cache_t cacheBuffer_; // 512 byte cache for device blocks + static uint32_t cacheBlockNumber_; // Logical number of block in the cache + static Sd2Card* sdCard_; // Sd2Card object for cache + static uint8_t cacheDirty_; // cacheFlush() will write block if true + static uint32_t cacheMirrorBlock_; // block number for mirror FAT +// + uint32_t allocSearchStart_; // start cluster for alloc search + uint8_t blocksPerCluster_; // cluster size in blocks + uint32_t blocksPerFat_; // FAT size in blocks + uint32_t clusterCount_; // clusters in one FAT + uint8_t clusterSizeShift_; // shift to convert cluster count to block count + uint32_t dataStartBlock_; // first data block number + uint8_t fatCount_; // number of FATs on volume + uint32_t fatStartBlock_; // start block for first FAT + uint8_t fatType_; // volume type (12, 16, OR 32) + uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir + uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 + //---------------------------------------------------------------------------- + uint8_t allocContiguous(uint32_t count, uint32_t* curCluster); + uint8_t blockOfCluster(uint32_t position) const { + return (position >> 9) & (blocksPerCluster_ - 1);} + uint32_t clusterStartBlock(uint32_t cluster) const { + return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} + uint32_t blockNumber(uint32_t cluster, uint32_t position) const { + return clusterStartBlock(cluster) + blockOfCluster(position);} + static uint8_t cacheFlush(void); + static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); + static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;} + static uint8_t cacheZeroBlock(uint32_t blockNumber); + uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const; + uint8_t fatGet(uint32_t cluster, uint32_t* value) const; + uint8_t fatPut(uint32_t cluster, uint32_t value); + uint8_t fatPutEOC(uint32_t cluster) { + return fatPut(cluster, 0x0FFFFFFF); + } + uint8_t freeChain(uint32_t cluster); + uint8_t isEOC(uint32_t cluster) const { + return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); + } + uint8_t readBlock(uint32_t block, uint8_t* dst) { + return sdCard_->readBlock(block, dst);} + uint8_t readData(uint32_t block, uint16_t offset, + uint16_t count, uint8_t* dst) { + return sdCard_->readData(block, offset, count, dst); + } + uint8_t writeBlock(uint32_t block, const uint8_t* dst) { + return sdCard_->writeBlock(block, dst); + } +}; +#endif // SdFat_h diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index 7992031f71..8bf90483d4 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -1,70 +1,70 @@ -/* Arduino SdFat Library - * Copyright (C) 2008 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFatUtil_h -#define SdFatUtil_h -/** - * \file - * Useful utility functions. - */ -#include -#include -/** Store and print a string in flash memory.*/ -#define PgmPrint(x) SerialPrint_P(PSTR(x)) -/** Store and print a string in flash memory followed by a CR/LF.*/ -#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) -/** Defined so doxygen works for function definitions. */ -#define NOINLINE __attribute__((noinline)) -//------------------------------------------------------------------------------ -/** Return the number of bytes currently free in RAM. */ -static int FreeRam(void) { - extern int __bss_end; - extern int* __brkval; - int free_memory; - if (reinterpret_cast(__brkval) == 0) { - // if no heap use from end of bss section - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(&__bss_end); - } else { - // use from top of stack to heap - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(__brkval); - } - return free_memory; -} -//------------------------------------------------------------------------------ -/** - * %Print a string in flash memory to the serial port. - * - * \param[in] str Pointer to string stored in flash memory. - */ -static NOINLINE void SerialPrint_P(PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.print(c); -} -//------------------------------------------------------------------------------ -/** - * %Print a string in flash memory followed by a CR/LF. - * - * \param[in] str Pointer to string stored in flash memory. - */ -static NOINLINE void SerialPrintln_P(PGM_P str) { - SerialPrint_P(str); - Serial.println(); -} -#endif // #define SdFatUtil_h +/* Arduino SdFat Library + * Copyright (C) 2008 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdFatUtil_h +#define SdFatUtil_h +/** + * \file + * Useful utility functions. + */ +#include +#include +/** Store and print a string in flash memory.*/ +#define PgmPrint(x) SerialPrint_P(PSTR(x)) +/** Store and print a string in flash memory followed by a CR/LF.*/ +#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) +/** Defined so doxygen works for function definitions. */ +#define NOINLINE __attribute__((noinline)) +//------------------------------------------------------------------------------ +/** Return the number of bytes currently free in RAM. */ +static int FreeRam(void) { + extern int __bss_end; + extern int* __brkval; + int free_memory; + if (reinterpret_cast(__brkval) == 0) { + // if no heap use from end of bss section + free_memory = reinterpret_cast(&free_memory) + - reinterpret_cast(&__bss_end); + } else { + // use from top of stack to heap + free_memory = reinterpret_cast(&free_memory) + - reinterpret_cast(__brkval); + } + return free_memory; +} +//------------------------------------------------------------------------------ +/** + * %Print a string in flash memory to the serial port. + * + * \param[in] str Pointer to string stored in flash memory. + */ +static NOINLINE void SerialPrint_P(PGM_P str) { + for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.print(c); +} +//------------------------------------------------------------------------------ +/** + * %Print a string in flash memory followed by a CR/LF. + * + * \param[in] str Pointer to string stored in flash memory. + */ +static NOINLINE void SerialPrintln_P(PGM_P str) { + SerialPrint_P(str); + Serial.println(); +} +#endif // #define SdFatUtil_h diff --git a/Marlin/SdFatmainpage.h b/Marlin/SdFatmainpage.h index d26cb854c6..73b3b63bd4 100644 --- a/Marlin/SdFatmainpage.h +++ b/Marlin/SdFatmainpage.h @@ -1,202 +1,202 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ - -/** -\mainpage Arduino SdFat Library -
Copyright © 2009 by William Greiman -
- -\section Intro Introduction -The Arduino SdFat Library is a minimal implementation of FAT16 and FAT32 -file systems on SD flash memory cards. Standard SD and high capacity -SDHC cards are supported. - -The SdFat only supports short 8.3 names. - -The main classes in SdFat are Sd2Card, SdVolume, and SdFile. - -The Sd2Card class supports access to standard SD cards and SDHC cards. Most -applications will only need to call the Sd2Card::init() member function. - -The SdVolume class supports FAT16 and FAT32 partitions. Most applications -will only need to call the SdVolume::init() member function. - -The SdFile class provides file access functions such as open(), read(), -remove(), write(), close() and sync(). This class supports access to the root -directory and subdirectories. - -A number of example are provided in the SdFat/examples folder. These were -developed to test SdFat and illustrate its use. - -SdFat was developed for high speed data recording. SdFat was used to implement -an audio record/play class, WaveRP, for the Adafruit Wave Shield. This -application uses special Sd2Card calls to write to contiguous files in raw mode. -These functions reduce write latency so that audio can be recorded with the -small amount of RAM in the Arduino. - -\section SDcard SD\SDHC Cards - -Arduinos access SD cards using the cards SPI protocol. PCs, Macs, and -most consumer devices use the 4-bit parallel SD protocol. A card that -functions well on A PC or Mac may not work well on the Arduino. - -Most cards have good SPI read performance but cards vary widely in SPI -write performance. Write performance is limited by how efficiently the -card manages internal erase/remapping operations. The Arduino cannot -optimize writes to reduce erase operations because of its limit RAM. - -SanDisk cards generally have good write performance. They seem to have -more internal RAM buffering than other cards and therefore can limit -the number of flash erase operations that the Arduino forces due to its -limited RAM. - -\section Hardware Hardware Configuration - -SdFat was developed using an - Adafruit Industries - Wave Shield. - -The hardware interface to the SD card should not use a resistor based level -shifter. SdFat sets the SPI bus frequency to 8 MHz which results in signal -rise times that are too slow for the edge detectors in many newer SD card -controllers when resistor voltage dividers are used. - -The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the -74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield -uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the -74LCX245. - -If you are using a resistor based level shifter and are having problems try -setting the SPI bus frequency to 4 MHz. This can be done by using -card.init(SPI_HALF_SPEED) to initialize the SD card. - -\section comment Bugs and Comments - -If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net. - -\section SdFatClass SdFat Usage - -SdFat uses a slightly restricted form of short names. -Only printable ASCII characters are supported. No characters with code point -values greater than 127 are allowed. Space is not allowed even though space -was allowed in the API of early versions of DOS. - -Short names are limited to 8 characters followed by an optional period (.) -and extension of up to 3 characters. The characters may be any combination -of letters and digits. The following special characters are also allowed: - -$ % ' - _ @ ~ ` ! ( ) { } ^ # & - -Short names are always converted to upper case and their original case -value is lost. - -\note - The Arduino Print class uses character -at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink -function to control when data is written to the SD card. - -\par -An application which writes to a file using \link Print::print() print()\endlink, -\link Print::println() println() \endlink -or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink -at the appropriate time to force data and directory information to be written -to the SD Card. Data and directory information are also written to the SD card -when \link SdFile::close() close() \endlink is called. - -\par -Applications must use care calling \link SdFile::sync() sync() \endlink -since 2048 bytes of I/O is required to update file and -directory information. This includes writing the current data block, reading -the block that contains the directory entry for update, writing the directory -block back and reading back the current data block. - -It is possible to open a file with two or more instances of SdFile. A file may -be corrupted if data is written to the file by more than one instance of SdFile. - -\section HowTo How to format SD Cards as FAT Volumes - -You should use a freshly formatted SD card for best performance. FAT -file systems become slower if many files have been created and deleted. -This is because the directory entry for a deleted file is marked as deleted, -but is not deleted. When a new file is created, these entries must be scanned -before creating the file, a flaw in the FAT design. Also files can become -fragmented which causes reads and writes to be slower. - -Microsoft operating systems support removable media formatted with a -Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector -in block zero. - -Microsoft operating systems expect MBR formatted removable media -to have only one partition. The first partition should be used. - -Microsoft operating systems do not support partitioning SD flash cards. -If you erase an SD card with a program like KillDisk, Most versions of -Windows will format the card as a super floppy. - -The best way to restore an SD card's format is to use SDFormatter -which can be downloaded from: - -http://www.sdcard.org/consumers/formatter/ - -SDFormatter aligns flash erase boundaries with file -system structures which reduces write latency and file system overhead. - -SDFormatter does not have an option for FAT type so it may format -small cards as FAT12. - -After the MBR is restored by SDFormatter you may need to reformat small -cards that have been formatted FAT12 to force the volume type to be FAT16. - -If you reformat the SD card with an OS utility, choose a cluster size that -will result in: - -4084 < CountOfClusters && CountOfClusters < 65525 - -The volume will then be FAT16. - -If you are formatting an SD card on OS X or Linux, be sure to use the first -partition. Format this partition with a cluster count in above range. - -\section References References - -Adafruit Industries: - -http://www.adafruit.com/ - -http://www.ladyada.net/make/waveshield/ - -The Arduino site: - -http://www.arduino.cc/ - -For more information about FAT file systems see: - -http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx - -For information about using SD cards as SPI devices see: - -http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf - -The ATmega328 datasheet: - -http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf - - - */ +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ + +/** +\mainpage Arduino SdFat Library +
Copyright © 2009 by William Greiman +
+ +\section Intro Introduction +The Arduino SdFat Library is a minimal implementation of FAT16 and FAT32 +file systems on SD flash memory cards. Standard SD and high capacity +SDHC cards are supported. + +The SdFat only supports short 8.3 names. + +The main classes in SdFat are Sd2Card, SdVolume, and SdFile. + +The Sd2Card class supports access to standard SD cards and SDHC cards. Most +applications will only need to call the Sd2Card::init() member function. + +The SdVolume class supports FAT16 and FAT32 partitions. Most applications +will only need to call the SdVolume::init() member function. + +The SdFile class provides file access functions such as open(), read(), +remove(), write(), close() and sync(). This class supports access to the root +directory and subdirectories. + +A number of example are provided in the SdFat/examples folder. These were +developed to test SdFat and illustrate its use. + +SdFat was developed for high speed data recording. SdFat was used to implement +an audio record/play class, WaveRP, for the Adafruit Wave Shield. This +application uses special Sd2Card calls to write to contiguous files in raw mode. +These functions reduce write latency so that audio can be recorded with the +small amount of RAM in the Arduino. + +\section SDcard SD\SDHC Cards + +Arduinos access SD cards using the cards SPI protocol. PCs, Macs, and +most consumer devices use the 4-bit parallel SD protocol. A card that +functions well on A PC or Mac may not work well on the Arduino. + +Most cards have good SPI read performance but cards vary widely in SPI +write performance. Write performance is limited by how efficiently the +card manages internal erase/remapping operations. The Arduino cannot +optimize writes to reduce erase operations because of its limit RAM. + +SanDisk cards generally have good write performance. They seem to have +more internal RAM buffering than other cards and therefore can limit +the number of flash erase operations that the Arduino forces due to its +limited RAM. + +\section Hardware Hardware Configuration + +SdFat was developed using an + Adafruit Industries + Wave Shield. + +The hardware interface to the SD card should not use a resistor based level +shifter. SdFat sets the SPI bus frequency to 8 MHz which results in signal +rise times that are too slow for the edge detectors in many newer SD card +controllers when resistor voltage dividers are used. + +The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the +74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield +uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the +74LCX245. + +If you are using a resistor based level shifter and are having problems try +setting the SPI bus frequency to 4 MHz. This can be done by using +card.init(SPI_HALF_SPEED) to initialize the SD card. + +\section comment Bugs and Comments + +If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net. + +\section SdFatClass SdFat Usage + +SdFat uses a slightly restricted form of short names. +Only printable ASCII characters are supported. No characters with code point +values greater than 127 are allowed. Space is not allowed even though space +was allowed in the API of early versions of DOS. + +Short names are limited to 8 characters followed by an optional period (.) +and extension of up to 3 characters. The characters may be any combination +of letters and digits. The following special characters are also allowed: + +$ % ' - _ @ ~ ` ! ( ) { } ^ # & + +Short names are always converted to upper case and their original case +value is lost. + +\note + The Arduino Print class uses character +at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink +function to control when data is written to the SD card. + +\par +An application which writes to a file using \link Print::print() print()\endlink, +\link Print::println() println() \endlink +or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink +at the appropriate time to force data and directory information to be written +to the SD Card. Data and directory information are also written to the SD card +when \link SdFile::close() close() \endlink is called. + +\par +Applications must use care calling \link SdFile::sync() sync() \endlink +since 2048 bytes of I/O is required to update file and +directory information. This includes writing the current data block, reading +the block that contains the directory entry for update, writing the directory +block back and reading back the current data block. + +It is possible to open a file with two or more instances of SdFile. A file may +be corrupted if data is written to the file by more than one instance of SdFile. + +\section HowTo How to format SD Cards as FAT Volumes + +You should use a freshly formatted SD card for best performance. FAT +file systems become slower if many files have been created and deleted. +This is because the directory entry for a deleted file is marked as deleted, +but is not deleted. When a new file is created, these entries must be scanned +before creating the file, a flaw in the FAT design. Also files can become +fragmented which causes reads and writes to be slower. + +Microsoft operating systems support removable media formatted with a +Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector +in block zero. + +Microsoft operating systems expect MBR formatted removable media +to have only one partition. The first partition should be used. + +Microsoft operating systems do not support partitioning SD flash cards. +If you erase an SD card with a program like KillDisk, Most versions of +Windows will format the card as a super floppy. + +The best way to restore an SD card's format is to use SDFormatter +which can be downloaded from: + +http://www.sdcard.org/consumers/formatter/ + +SDFormatter aligns flash erase boundaries with file +system structures which reduces write latency and file system overhead. + +SDFormatter does not have an option for FAT type so it may format +small cards as FAT12. + +After the MBR is restored by SDFormatter you may need to reformat small +cards that have been formatted FAT12 to force the volume type to be FAT16. + +If you reformat the SD card with an OS utility, choose a cluster size that +will result in: + +4084 < CountOfClusters && CountOfClusters < 65525 + +The volume will then be FAT16. + +If you are formatting an SD card on OS X or Linux, be sure to use the first +partition. Format this partition with a cluster count in above range. + +\section References References + +Adafruit Industries: + +http://www.adafruit.com/ + +http://www.ladyada.net/make/waveshield/ + +The Arduino site: + +http://www.arduino.cc/ + +For more information about FAT file systems see: + +http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx + +For information about using SD cards as SPI devices see: + +http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf + +The ATmega328 datasheet: + +http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf + + + */ diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index 0a27159f43..e7e23d1db7 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -1,1252 +1,1252 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#include "SdFat.h" -#include -#include -//------------------------------------------------------------------------------ -// callback function for date/time -void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL; - -#if ALLOW_DEPRECATED_FUNCTIONS -// suppress cpplint warnings with NOLINT comment -void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL; // NOLINT -#endif // ALLOW_DEPRECATED_FUNCTIONS -//------------------------------------------------------------------------------ -// add a cluster to a file -uint8_t SdFile::addCluster() { - if (!vol_->allocContiguous(1, &curCluster_)) return false; - - // if first cluster of file link to directory entry - if (firstCluster_ == 0) { - firstCluster_ = curCluster_; - flags_ |= F_FILE_DIR_DIRTY; - } - return true; -} -//------------------------------------------------------------------------------ -// Add a cluster to a directory file and zero the cluster. -// return with first block of cluster in the cache -uint8_t SdFile::addDirCluster(void) { - if (!addCluster()) return false; - - // zero data in cluster insure first cluster is in cache - uint32_t block = vol_->clusterStartBlock(curCluster_); - for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) { - if (!SdVolume::cacheZeroBlock(block + i - 1)) return false; - } - // Increase directory file size by cluster size - fileSize_ += 512UL << vol_->clusterSizeShift_; - return true; -} -//------------------------------------------------------------------------------ -// cache a file's directory entry -// return pointer to cached entry or null for failure -dir_t* SdFile::cacheDirEntry(uint8_t action) { - if (!SdVolume::cacheRawBlock(dirBlock_, action)) return NULL; - return SdVolume::cacheBuffer_.dir + dirIndex_; -} -//------------------------------------------------------------------------------ -/** - * Close a file and force cached data and directory information - * to be written to the storage device. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include no file is open or an I/O error. - */ -uint8_t SdFile::close(void) { - if (!sync())return false; - type_ = FAT_FILE_TYPE_CLOSED; - return true; -} -//------------------------------------------------------------------------------ -/** - * Check for contiguous file and return its raw block range. - * - * \param[out] bgnBlock the first block address for the file. - * \param[out] endBlock the last block address for the file. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include file is not contiguous, file has zero length - * or an I/O error occurred. - */ -uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { - // error if no blocks - if (firstCluster_ == 0) return false; - - for (uint32_t c = firstCluster_; ; c++) { - uint32_t next; - if (!vol_->fatGet(c, &next)) return false; - - // check for contiguous - if (next != (c + 1)) { - // error if not end of chain - if (!vol_->isEOC(next)) return false; - *bgnBlock = vol_->clusterStartBlock(firstCluster_); - *endBlock = vol_->clusterStartBlock(c) - + vol_->blocksPerCluster_ - 1; - return true; - } - } -} -//------------------------------------------------------------------------------ -/** - * Create and open a new contiguous file of a specified size. - * - * \note This function only supports short DOS 8.3 names. - * See open() for more information. - * - * \param[in] dirFile The directory where the file will be created. - * \param[in] fileName A valid DOS 8.3 file name. - * \param[in] size The desired file size. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include \a fileName contains - * an invalid DOS 8.3 file name, the FAT volume has not been initialized, - * a file is already open, the file already exists, the root - * directory is full or an I/O error. - * - */ -uint8_t SdFile::createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size) { - // don't allow zero length file - if (size == 0) return false; - if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) return false; - - // calculate number of clusters needed - uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; - - // allocate clusters - if (!vol_->allocContiguous(count, &firstCluster_)) { - remove(); - return false; - } - fileSize_ = size; - - // insure sync() will update dir entry - flags_ |= F_FILE_DIR_DIRTY; - return sync(); -} -//------------------------------------------------------------------------------ -/** - * Return a files directory entry - * - * \param[out] dir Location for return of the files directory entry. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::dirEntry(dir_t* dir) { - // make sure fields on SD are correct - if (!sync()) return false; - - // read entry - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); - if (!p) return false; - - // copy to caller's struct - memcpy(dir, p, sizeof(dir_t)); - return true; -} -//------------------------------------------------------------------------------ -/** - * Format the name field of \a dir into the 13 byte array - * \a name in standard 8.3 short name format. - * - * \param[in] dir The directory structure containing the name. - * \param[out] name A 13 byte char array for the formatted name. - */ -void SdFile::dirName(const dir_t& dir, char* name) { - uint8_t j = 0; - for (uint8_t i = 0; i < 11; i++) { - if (dir.name[i] == ' ')continue; - if (i == 8) name[j++] = '.'; - name[j++] = dir.name[i]; - } - name[j] = 0; -} -//------------------------------------------------------------------------------ -/** List directory contents to Serial. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - * - * \param[in] indent Amount of space before file name. Used for recursive - * list to indicate subdirectory level. - */ -void SdFile::ls(uint8_t flags, uint8_t indent) { - dir_t* p; - - rewind(); - while ((p = readDirCache())) { - // done if past last used entry - if (p->name[0] == DIR_NAME_FREE) break; - - // skip deleted entry and entries for . and .. - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; - - // only list subdirectories and files - if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; - - // print any indent spaces - for (int8_t i = 0; i < indent; i++) Serial.print(' '); - - // print file name with possible blank fill - printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0); - - // print modify date/time if requested - if (flags & LS_DATE) { - printFatDate(p->lastWriteDate); - Serial.print(' '); - printFatTime(p->lastWriteTime); - } - // print size if requested - if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) { - Serial.print(' '); - Serial.print(p->fileSize); - } - Serial.println(); - - // list subdirectory content if requested - if ((flags & LS_R) && DIR_IS_SUBDIR(p)) { - uint16_t index = curPosition()/32 - 1; - SdFile s; - if (s.open(this, index, O_READ)) s.ls(flags, indent + 2); - seekSet(32 * (index + 1)); - } - } -} -//------------------------------------------------------------------------------ -// format directory name field from a 8.3 name string -uint8_t SdFile::make83Name(const char* str, uint8_t* name) { - uint8_t c; - uint8_t n = 7; // max index for part before dot - uint8_t i = 0; - // blank fill name and extension - while (i < 11) name[i++] = ' '; - i = 0; - while ((c = *str++) != '\0') { - if (c == '.') { - if (n == 10) return false; // only one dot allowed - n = 10; // max index for full 8.3 name - i = 8; // place for extension - } else { - // illegal FAT characters - PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); - uint8_t b; - while ((b = pgm_read_byte(p++))) if (b == c) return false; - // check size and only allow ASCII printable characters - if (i > n || c < 0X21 || c > 0X7E)return false; - // only upper case allowed in 8.3 names - convert lower to upper - name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); - } - } - // must have a file name, extension is optional - return name[0] != ' '; -} -//------------------------------------------------------------------------------ -/** Make a new directory. - * - * \param[in] dir An open SdFat instance for the directory that will containing - * the new directory. - * - * \param[in] dirName A valid 8.3 DOS name for the new directory. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include this SdFile is already open, \a dir is not a - * directory, \a dirName is invalid or already exists in \a dir. - */ -uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { - dir_t d; - - // create a normal file - if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) return false; - - // convert SdFile to directory - flags_ = O_READ; - type_ = FAT_FILE_TYPE_SUBDIR; - - // allocate and zero first cluster - if (!addDirCluster())return false; - - // force entry to SD - if (!sync()) return false; - - // cache entry - should already be in cache due to sync() call - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!p) return false; - - // change directory entry attribute - p->attributes = DIR_ATT_DIRECTORY; - - // make entry for '.' - memcpy(&d, p, sizeof(d)); - for (uint8_t i = 1; i < 11; i++) d.name[i] = ' '; - d.name[0] = '.'; - - // cache block for '.' and '..' - uint32_t block = vol_->clusterStartBlock(firstCluster_); - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false; - - // copy '.' to block - memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d)); - - // make entry for '..' - d.name[1] = '.'; - if (dir->isRoot()) { - d.firstClusterLow = 0; - d.firstClusterHigh = 0; - } else { - d.firstClusterLow = dir->firstCluster_ & 0XFFFF; - d.firstClusterHigh = dir->firstCluster_ >> 16; - } - // copy '..' to block - memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d)); - - // set position after '..' - curPosition_ = 2 * sizeof(d); - - // write first block - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - * Open a file or directory by name. - * - * \param[in] dirFile An open SdFat instance for the directory containing the - * file to be opened. - * - * \param[in] fileName A valid 8.3 DOS name for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive - * OR of flags from the following list - * - * O_READ - Open for reading. - * - * O_RDONLY - Same as O_READ. - * - * O_WRITE - Open for writing. - * - * O_WRONLY - Same as O_WRITE. - * - * O_RDWR - Open for reading and writing. - * - * O_APPEND - If set, the file offset shall be set to the end of the - * file prior to each write. - * - * O_CREAT - If the file exists, this flag has no effect except as noted - * under O_EXCL below. Otherwise, the file shall be created - * - * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. - * - * O_SYNC - Call sync() after each write. This flag should not be used with - * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. - * These functions do character at a time writes so sync() will be called - * after each byte. - * - * O_TRUNC - If the file exists and is a regular file, and the file is - * successfully opened and is not read only, its length shall be truncated to 0. - * - * \note Directory files must be opened read only. Write and truncation is - * not allowed for directory files. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include this SdFile is already open, \a difFile is not - * a directory, \a fileName is invalid, the file does not exist - * or can't be opened in the access mode specified by oflag. - */ -uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { - uint8_t dname[11]; - dir_t* p; - - // error if already open - if (isOpen())return false; - - if (!make83Name(fileName, dname)) return false; - vol_ = dirFile->vol_; - dirFile->rewind(); - - // bool for empty entry found - uint8_t emptyFound = false; - - // search for file - while (dirFile->curPosition_ < dirFile->fileSize_) { - uint8_t index = 0XF & (dirFile->curPosition_ >> 5); - p = dirFile->readDirCache(); - if (p == NULL) return false; - - if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { - // remember first empty slot - if (!emptyFound) { - emptyFound = true; - dirIndex_ = index; - dirBlock_ = SdVolume::cacheBlockNumber_; - } - // done if no entries follow - if (p->name[0] == DIR_NAME_FREE) break; - } else if (!memcmp(dname, p->name, 11)) { - // don't open existing file if O_CREAT and O_EXCL - if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; - - // open found file - return openCachedEntry(0XF & index, oflag); - } - } - // only create file if O_CREAT and O_WRITE - if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false; - - // cache found slot or add cluster if end of file - if (emptyFound) { - p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!p) return false; - } else { - if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false; - - // add and zero cluster for dirFile - first cluster is in cache for write - if (!dirFile->addDirCluster()) return false; - - // use first entry in cluster - dirIndex_ = 0; - p = SdVolume::cacheBuffer_.dir; - } - // initialize as empty file - memset(p, 0, sizeof(dir_t)); - memcpy(p->name, dname, 11); - - // set timestamps - if (dateTime_) { - // call user function - dateTime_(&p->creationDate, &p->creationTime); - } else { - // use default date/time - p->creationDate = FAT_DEFAULT_DATE; - p->creationTime = FAT_DEFAULT_TIME; - } - p->lastAccessDate = p->creationDate; - p->lastWriteDate = p->creationDate; - p->lastWriteTime = p->creationTime; - - // force write of entry to SD - if (!SdVolume::cacheFlush()) return false; - - // open entry in cache - return openCachedEntry(dirIndex_, oflag); -} -//------------------------------------------------------------------------------ -/** - * Open a file by index. - * - * \param[in] dirFile An open SdFat instance for the directory. - * - * \param[in] index The \a index of the directory entry for the file to be - * opened. The value for \a index is (directory file position)/32. - * - * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive - * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. - * - * See open() by fileName for definition of flags and return values. - * - */ -uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { - // error if already open - if (isOpen())return false; - - // don't open existing file if O_CREAT and O_EXCL - user call error - if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; - - vol_ = dirFile->vol_; - - // seek to location of entry - if (!dirFile->seekSet(32 * index)) return false; - - // read entry into cache - dir_t* p = dirFile->readDirCache(); - if (p == NULL) return false; - - // error if empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_FREE || - p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { - return false; - } - // open cached entry - return openCachedEntry(index & 0XF, oflag); -} -//------------------------------------------------------------------------------ -// open a cached directory entry. Assumes vol_ is initializes -uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { - // location of entry in cache - dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex; - - // write or truncate is an error for a directory or read-only file - if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { - if (oflag & (O_WRITE | O_TRUNC)) return false; - } - // remember location of directory entry on SD - dirIndex_ = dirIndex; - dirBlock_ = SdVolume::cacheBlockNumber_; - - // copy first cluster number for directory fields - firstCluster_ = (uint32_t)p->firstClusterHigh << 16; - firstCluster_ |= p->firstClusterLow; - - // make sure it is a normal file or subdirectory - if (DIR_IS_FILE(p)) { - fileSize_ = p->fileSize; - type_ = FAT_FILE_TYPE_NORMAL; - } else if (DIR_IS_SUBDIR(p)) { - if (!vol_->chainSize(firstCluster_, &fileSize_)) return false; - type_ = FAT_FILE_TYPE_SUBDIR; - } else { - return false; - } - // save open flags for read/write - flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND); - - // set to start of file - curCluster_ = 0; - curPosition_ = 0; - - // truncate file to zero length if requested - if (oflag & O_TRUNC) return truncate(0); - return true; -} -//------------------------------------------------------------------------------ -/** - * Open a volume's root directory. - * - * \param[in] vol The FAT volume containing the root directory to be opened. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the FAT volume has not been initialized - * or it a FAT12 volume. - */ -uint8_t SdFile::openRoot(SdVolume* vol) { - // error if file is already open - if (isOpen()) return false; - - if (vol->fatType() == 16) { - type_ = FAT_FILE_TYPE_ROOT16; - firstCluster_ = 0; - fileSize_ = 32 * vol->rootDirEntryCount(); - } else if (vol->fatType() == 32) { - type_ = FAT_FILE_TYPE_ROOT32; - firstCluster_ = vol->rootDirStart(); - if (!vol->chainSize(firstCluster_, &fileSize_)) return false; - } else { - // volume is not initialized or FAT12 - return false; - } - vol_ = vol; - // read only - flags_ = O_READ; - - // set to start of file - curCluster_ = 0; - curPosition_ = 0; - - // root has no directory entry - dirBlock_ = 0; - dirIndex_ = 0; - return true; -} -//------------------------------------------------------------------------------ -/** %Print the name field of a directory entry in 8.3 format to Serial. - * - * \param[in] dir The directory structure containing the name. - * \param[in] width Blank fill name if length is less than \a width. - */ -void SdFile::printDirName(const dir_t& dir, uint8_t width) { - uint8_t w = 0; - for (uint8_t i = 0; i < 11; i++) { - if (dir.name[i] == ' ')continue; - if (i == 8) { - Serial.print('.'); - w++; - } - Serial.print(dir.name[i]); - w++; - } - if (DIR_IS_SUBDIR(&dir)) { - Serial.print('/'); - w++; - } - while (w < width) { - Serial.print(' '); - w++; - } -} -//------------------------------------------------------------------------------ -/** %Print a directory date field to Serial. - * - * Format is yyyy-mm-dd. - * - * \param[in] fatDate The date field from a directory entry. - */ -void SdFile::printFatDate(uint16_t fatDate) { - Serial.print(FAT_YEAR(fatDate)); - Serial.print('-'); - printTwoDigits(FAT_MONTH(fatDate)); - Serial.print('-'); - printTwoDigits(FAT_DAY(fatDate)); -} -//------------------------------------------------------------------------------ -/** %Print a directory time field to Serial. - * - * Format is hh:mm:ss. - * - * \param[in] fatTime The time field from a directory entry. - */ -void SdFile::printFatTime(uint16_t fatTime) { - printTwoDigits(FAT_HOUR(fatTime)); - Serial.print(':'); - printTwoDigits(FAT_MINUTE(fatTime)); - Serial.print(':'); - printTwoDigits(FAT_SECOND(fatTime)); -} -//------------------------------------------------------------------------------ -/** %Print a value as two digits to Serial. - * - * \param[in] v Value to be printed, 0 <= \a v <= 99 - */ -void SdFile::printTwoDigits(uint8_t v) { - char str[3]; - str[0] = '0' + v/10; - str[1] = '0' + v % 10; - str[2] = 0; - Serial.print(str); -} -//------------------------------------------------------------------------------ -/** - * Read data from a file starting at the current position. - * - * \param[out] buf Pointer to the location that will receive the data. - * - * \param[in] nbyte Maximum number of bytes to read. - * - * \return For success read() returns the number of bytes read. - * A value less than \a nbyte, including zero, will be returned - * if end of file is reached. - * If an error occurs, read() returns -1. Possible errors include - * read() called before a file has been opened, corrupt file system - * or an I/O error occurred. - */ -int16_t SdFile::read(void* buf, uint16_t nbyte) { - uint8_t* dst = reinterpret_cast(buf); - - // error if not open or write only - if (!isOpen() || !(flags_ & O_READ)) return -1; - - // max bytes left in file - if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_; - - // amount left to read - uint16_t toRead = nbyte; - while (toRead > 0) { - uint32_t block; // raw device block number - uint16_t offset = curPosition_ & 0X1FF; // offset in block - if (type_ == FAT_FILE_TYPE_ROOT16) { - block = vol_->rootDirStart() + (curPosition_ >> 9); - } else { - uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); - if (offset == 0 && blockOfCluster == 0) { - // start of new cluster - if (curPosition_ == 0) { - // use first cluster in file - curCluster_ = firstCluster_; - } else { - // get next cluster from FAT - if (!vol_->fatGet(curCluster_, &curCluster_)) return -1; - } - } - block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; - } - uint16_t n = toRead; - - // amount to be read from current block - if (n > (512 - offset)) n = 512 - offset; - - // no buffering needed if n == 512 or user requests no buffering - if ((unbufferedRead() || n == 512) && - block != SdVolume::cacheBlockNumber_) { - if (!vol_->readData(block, offset, n, dst)) return -1; - dst += n; - } else { - // read block to cache and copy data to caller - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1; - uint8_t* src = SdVolume::cacheBuffer_.data + offset; - uint8_t* end = src + n; - while (src != end) *dst++ = *src++; - } - curPosition_ += n; - toRead -= n; - } - return nbyte; -} -//------------------------------------------------------------------------------ -/** - * Read the next directory entry from a directory file. - * - * \param[out] dir The dir_t struct that will receive the data. - * - * \return For success readDir() returns the number of bytes read. - * A value of zero will be returned if end of file is reached. - * If an error occurs, readDir() returns -1. Possible errors include - * readDir() called before a directory has been opened, this is not - * a directory file or an I/O error occurred. - */ -int8_t SdFile::readDir(dir_t* dir) { - int8_t n; - // if not a directory file or miss-positioned return an error - if (!isDir() || (0X1F & curPosition_)) return -1; - - while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) { - // last entry if DIR_NAME_FREE - if (dir->name[0] == DIR_NAME_FREE) break; - // skip empty entries and entry for . and .. - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; - // return if normal file or subdirectory - if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; - } - // error, end of file, or past last entry - return n < 0 ? -1 : 0; -} -//------------------------------------------------------------------------------ -// Read next directory entry into the cache -// Assumes file is correctly positioned -dir_t* SdFile::readDirCache(void) { - // error if not directory - if (!isDir()) return NULL; - - // index of entry in cache - uint8_t i = (curPosition_ >> 5) & 0XF; - - // use read to locate and cache block - if (read() < 0) return NULL; - - // advance to next entry - curPosition_ += 31; - - // return pointer to entry - return (SdVolume::cacheBuffer_.dir + i); -} -//------------------------------------------------------------------------------ -/** - * Remove a file. - * - * The directory entry and all data for the file are deleted. - * - * \note This function should not be used to delete the 8.3 version of a - * file that has a long name. For example if a file has the long name - * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the file read-only, is a directory, - * or an I/O error occurred. - */ -uint8_t SdFile::remove(void) { - // free any clusters - will fail if read-only or directory - if (!truncate(0)) return false; - - // cache directory entry - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) return false; - - // mark entry deleted - d->name[0] = DIR_NAME_DELETED; - - // set this SdFile closed - type_ = FAT_FILE_TYPE_CLOSED; - - // write entry to SD - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - * Remove a file. - * - * The directory entry and all data for the file are deleted. - * - * \param[in] dirFile The directory that contains the file. - * \param[in] fileName The name of the file to be removed. - * - * \note This function should not be used to delete the 8.3 version of a - * file that has a long name. For example if a file has the long name - * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the file is a directory, is read only, - * \a dirFile is not a directory, \a fileName is not found - * or an I/O error occurred. - */ -uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) { - SdFile file; - if (!file.open(dirFile, fileName, O_WRITE)) return false; - return file.remove(); -} -//------------------------------------------------------------------------------ -/** Remove a directory file. - * - * The directory file will be removed only if it is empty and is not the - * root directory. rmDir() follows DOS and Windows and ignores the - * read-only attribute for the directory. - * - * \note This function should not be used to delete the 8.3 version of a - * directory that has a long name. For example if a directory has the - * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the file is not a directory, is the root - * directory, is not empty, or an I/O error occurred. - */ -uint8_t SdFile::rmDir(void) { - // must be open subdirectory - if (!isSubDir()) return false; - - rewind(); - - // make sure directory is empty - while (curPosition_ < fileSize_) { - dir_t* p = readDirCache(); - if (p == NULL) return false; - // done if past last used entry - if (p->name[0] == DIR_NAME_FREE) break; - // skip empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; - // error not empty - if (DIR_IS_FILE_OR_SUBDIR(p)) return false; - } - // convert empty directory to normal file for remove - type_ = FAT_FILE_TYPE_NORMAL; - flags_ |= O_WRITE; - return remove(); -} -//------------------------------------------------------------------------------ -/** Recursively delete a directory and all contained files. - * - * This is like the Unix/Linux 'rm -rf *' if called with the root directory - * hence the name. - * - * Warning - This will remove all contents of the directory including - * subdirectories. The directory will then be removed if it is not root. - * The read-only attribute for files will be ignored. - * - * \note This function should not be used to delete the 8.3 version of - * a directory that has a long name. See remove() and rmDir(). - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::rmRfStar(void) { - rewind(); - while (curPosition_ < fileSize_) { - SdFile f; - - // remember position - uint16_t index = curPosition_/32; - - dir_t* p = readDirCache(); - if (!p) return false; - - // done if past last entry - if (p->name[0] == DIR_NAME_FREE) break; - - // skip empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; - - // skip if part of long file name or volume label in root - if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; - - if (!f.open(this, index, O_READ)) return false; - if (f.isSubDir()) { - // recursively delete - if (!f.rmRfStar()) return false; - } else { - // ignore read-only - f.flags_ |= O_WRITE; - if (!f.remove()) return false; - } - // position to next entry if required - if (curPosition_ != (32*(index + 1))) { - if (!seekSet(32*(index + 1))) return false; - } - } - // don't try to delete root - if (isRoot()) return true; - return rmDir(); -} -//------------------------------------------------------------------------------ -/** - * Sets a file's position. - * - * \param[in] pos The new position in bytes from the beginning of the file. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::seekSet(uint32_t pos) { - // error if file not open or seek past end of file - if (!isOpen() || pos > fileSize_) return false; - - if (type_ == FAT_FILE_TYPE_ROOT16) { - curPosition_ = pos; - return true; - } - if (pos == 0) { - // set position to start of file - curCluster_ = 0; - curPosition_ = 0; - return true; - } - // calculate cluster index for cur and new position - uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); - uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); - - if (nNew < nCur || curPosition_ == 0) { - // must follow chain from first cluster - curCluster_ = firstCluster_; - } else { - // advance from curPosition - nNew -= nCur; - } - while (nNew--) { - if (!vol_->fatGet(curCluster_, &curCluster_)) return false; - } - curPosition_ = pos; - return true; -} -//------------------------------------------------------------------------------ -/** - * The sync() call causes all modified data and directory fields - * to be written to the storage device. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include a call to sync() before a file has been - * opened or an I/O error. - */ -uint8_t SdFile::sync(void) { - // only allow open files and directories - if (!isOpen()) return false; - - if (flags_ & F_FILE_DIR_DIRTY) { - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) return false; - - // do not set filesize for dir files - if (!isDir()) d->fileSize = fileSize_; - - // update first cluster fields - d->firstClusterLow = firstCluster_ & 0XFFFF; - d->firstClusterHigh = firstCluster_ >> 16; - - // set modify time if user supplied a callback date/time function - if (dateTime_) { - dateTime_(&d->lastWriteDate, &d->lastWriteTime); - d->lastAccessDate = d->lastWriteDate; - } - // clear directory dirty - flags_ &= ~F_FILE_DIR_DIRTY; - } - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - * Set a file's timestamps in its directory entry. - * - * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive - * OR of flags from the following list - * - * T_ACCESS - Set the file's last access date. - * - * T_CREATE - Set the file's creation date and time. - * - * T_WRITE - Set the file's last write/modification date and time. - * - * \param[in] year Valid range 1980 - 2107 inclusive. - * - * \param[in] month Valid range 1 - 12 inclusive. - * - * \param[in] day Valid range 1 - 31 inclusive. - * - * \param[in] hour Valid range 0 - 23 inclusive. - * - * \param[in] minute Valid range 0 - 59 inclusive. - * - * \param[in] second Valid range 0 - 59 inclusive - * - * \note It is possible to set an invalid date since there is no check for - * the number of days in a month. - * - * \note - * Modify and access timestamps may be overwritten if a date time callback - * function has been set by dateTimeCallback(). - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { - if (!isOpen() - || year < 1980 - || year > 2107 - || month < 1 - || month > 12 - || day < 1 - || day > 31 - || hour > 23 - || minute > 59 - || second > 59) { - return false; - } - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) return false; - - uint16_t dirDate = FAT_DATE(year, month, day); - uint16_t dirTime = FAT_TIME(hour, minute, second); - if (flags & T_ACCESS) { - d->lastAccessDate = dirDate; - } - if (flags & T_CREATE) { - d->creationDate = dirDate; - d->creationTime = dirTime; - // seems to be units of 1/100 second not 1/10 as Microsoft states - d->creationTimeTenths = second & 1 ? 100 : 0; - } - if (flags & T_WRITE) { - d->lastWriteDate = dirDate; - d->lastWriteTime = dirTime; - } - SdVolume::cacheSetDirty(); - return sync(); -} -//------------------------------------------------------------------------------ -/** - * Truncate a file to a specified length. The current file position - * will be maintained if it is less than or equal to \a length otherwise - * it will be set to end of file. - * - * \param[in] length The desired length for the file. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include file is read only, file is a directory, - * \a length is greater than the current file size or an I/O error occurs. - */ -uint8_t SdFile::truncate(uint32_t length) { -// error if not a normal file or read-only - if (!isFile() || !(flags_ & O_WRITE)) return false; - - // error if length is greater than current size - if (length > fileSize_) return false; - - // fileSize and length are zero - nothing to do - if (fileSize_ == 0) return true; - - // remember position for seek after truncation - uint32_t newPos = curPosition_ > length ? length : curPosition_; - - // position to last cluster in truncated file - if (!seekSet(length)) return false; - - if (length == 0) { - // free all clusters - if (!vol_->freeChain(firstCluster_)) return false; - firstCluster_ = 0; - } else { - uint32_t toFree; - if (!vol_->fatGet(curCluster_, &toFree)) return false; - - if (!vol_->isEOC(toFree)) { - // free extra clusters - if (!vol_->freeChain(toFree)) return false; - - // current cluster is end of chain - if (!vol_->fatPutEOC(curCluster_)) return false; - } - } - fileSize_ = length; - - // need to update directory entry - flags_ |= F_FILE_DIR_DIRTY; - - if (!sync()) return false; - - // set file to correct position - return seekSet(newPos); -} -//------------------------------------------------------------------------------ -/** - * Write data to an open file. - * - * \note Data is moved to the cache but may not be written to the - * storage device until sync() is called. - * - * \param[in] buf Pointer to the location of the data to be written. - * - * \param[in] nbyte Number of bytes to write. - * - * \return For success write() returns the number of bytes written, always - * \a nbyte. If an error occurs, write() returns -1. Possible errors - * include write() is called before a file has been opened, write is called - * for a read-only file, device is full, a corrupt file system or an I/O error. - * - */ -int16_t SdFile::write(const void* buf, uint16_t nbyte) { - // convert void* to uint8_t* - must be before goto statements - const uint8_t* src = reinterpret_cast(buf); - - // number of bytes left to write - must be before goto statements - uint16_t nToWrite = nbyte; - - // error if not a normal file or is read-only - if (!isFile() || !(flags_ & O_WRITE)) goto writeErrorReturn; - - // seek to end of file if append flag - if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { - if (!seekEnd()) goto writeErrorReturn; - } - - while (nToWrite > 0) { - uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); - uint16_t blockOffset = curPosition_ & 0X1FF; - if (blockOfCluster == 0 && blockOffset == 0) { - // start of new cluster - if (curCluster_ == 0) { - if (firstCluster_ == 0) { - // allocate first cluster of file - if (!addCluster()) goto writeErrorReturn; - } else { - curCluster_ = firstCluster_; - } - } else { - uint32_t next; - if (!vol_->fatGet(curCluster_, &next)) return false; - if (vol_->isEOC(next)) { - // add cluster if at end of chain - if (!addCluster()) goto writeErrorReturn; - } else { - curCluster_ = next; - } - } - } - // max space in block - uint16_t n = 512 - blockOffset; - - // lesser of space and amount to write - if (n > nToWrite) n = nToWrite; - - // block for data write - uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; - if (n == 512) { - // full block - don't need to use cache - // invalidate cache if block is in cache - if (SdVolume::cacheBlockNumber_ == block) { - SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; - } - if (!vol_->writeBlock(block, src)) goto writeErrorReturn; - src += 512; - } else { - if (blockOffset == 0 && curPosition_ >= fileSize_) { - // start of new block don't need to read into cache - if (!SdVolume::cacheFlush()) goto writeErrorReturn; - SdVolume::cacheBlockNumber_ = block; - SdVolume::cacheSetDirty(); - } else { - // rewrite part of block - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { - goto writeErrorReturn; - } - } - uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset; - uint8_t* end = dst + n; - while (dst != end) *dst++ = *src++; - } - nToWrite -= n; - curPosition_ += n; - } - if (curPosition_ > fileSize_) { - // update fileSize and insure sync will update dir entry - fileSize_ = curPosition_; - flags_ |= F_FILE_DIR_DIRTY; - } else if (dateTime_ && nbyte) { - // insure sync will update modified date and time - flags_ |= F_FILE_DIR_DIRTY; - } - - if (flags_ & O_SYNC) { - if (!sync()) goto writeErrorReturn; - } - return nbyte; - - writeErrorReturn: - // return for write error - writeError = true; - return -1; -} -//------------------------------------------------------------------------------ -/** - * Write a byte to a file. Required by the Arduino Print class. - * - * Use SdFile::writeError to check for errors. - */ -void SdFile::write(uint8_t b) { - write(&b, 1); -} -//------------------------------------------------------------------------------ -/** - * Write a string to a file. Used by the Arduino Print class. - * - * Use SdFile::writeError to check for errors. - */ -void SdFile::write(const char* str) { - write(str, strlen(str)); -} -//------------------------------------------------------------------------------ -/** - * Write a PROGMEM string to a file. - * - * Use SdFile::writeError to check for errors. - */ -void SdFile::write_P(PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c); -} -//------------------------------------------------------------------------------ -/** - * Write a PROGMEM string followed by CR/LF to a file. - * - * Use SdFile::writeError to check for errors. - */ -void SdFile::writeln_P(PGM_P str) { - write_P(str); - println(); -} +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#include "SdFat.h" +#include +#include +//------------------------------------------------------------------------------ +// callback function for date/time +void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL; + +#if ALLOW_DEPRECATED_FUNCTIONS +// suppress cpplint warnings with NOLINT comment +void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL; // NOLINT +#endif // ALLOW_DEPRECATED_FUNCTIONS +//------------------------------------------------------------------------------ +// add a cluster to a file +uint8_t SdFile::addCluster() { + if (!vol_->allocContiguous(1, &curCluster_)) return false; + + // if first cluster of file link to directory entry + if (firstCluster_ == 0) { + firstCluster_ = curCluster_; + flags_ |= F_FILE_DIR_DIRTY; + } + return true; +} +//------------------------------------------------------------------------------ +// Add a cluster to a directory file and zero the cluster. +// return with first block of cluster in the cache +uint8_t SdFile::addDirCluster(void) { + if (!addCluster()) return false; + + // zero data in cluster insure first cluster is in cache + uint32_t block = vol_->clusterStartBlock(curCluster_); + for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) { + if (!SdVolume::cacheZeroBlock(block + i - 1)) return false; + } + // Increase directory file size by cluster size + fileSize_ += 512UL << vol_->clusterSizeShift_; + return true; +} +//------------------------------------------------------------------------------ +// cache a file's directory entry +// return pointer to cached entry or null for failure +dir_t* SdFile::cacheDirEntry(uint8_t action) { + if (!SdVolume::cacheRawBlock(dirBlock_, action)) return NULL; + return SdVolume::cacheBuffer_.dir + dirIndex_; +} +//------------------------------------------------------------------------------ +/** + * Close a file and force cached data and directory information + * to be written to the storage device. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include no file is open or an I/O error. + */ +uint8_t SdFile::close(void) { + if (!sync())return false; + type_ = FAT_FILE_TYPE_CLOSED; + return true; +} +//------------------------------------------------------------------------------ +/** + * Check for contiguous file and return its raw block range. + * + * \param[out] bgnBlock the first block address for the file. + * \param[out] endBlock the last block address for the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include file is not contiguous, file has zero length + * or an I/O error occurred. + */ +uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { + // error if no blocks + if (firstCluster_ == 0) return false; + + for (uint32_t c = firstCluster_; ; c++) { + uint32_t next; + if (!vol_->fatGet(c, &next)) return false; + + // check for contiguous + if (next != (c + 1)) { + // error if not end of chain + if (!vol_->isEOC(next)) return false; + *bgnBlock = vol_->clusterStartBlock(firstCluster_); + *endBlock = vol_->clusterStartBlock(c) + + vol_->blocksPerCluster_ - 1; + return true; + } + } +} +//------------------------------------------------------------------------------ +/** + * Create and open a new contiguous file of a specified size. + * + * \note This function only supports short DOS 8.3 names. + * See open() for more information. + * + * \param[in] dirFile The directory where the file will be created. + * \param[in] fileName A valid DOS 8.3 file name. + * \param[in] size The desired file size. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include \a fileName contains + * an invalid DOS 8.3 file name, the FAT volume has not been initialized, + * a file is already open, the file already exists, the root + * directory is full or an I/O error. + * + */ +uint8_t SdFile::createContiguous(SdFile* dirFile, + const char* fileName, uint32_t size) { + // don't allow zero length file + if (size == 0) return false; + if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) return false; + + // calculate number of clusters needed + uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; + + // allocate clusters + if (!vol_->allocContiguous(count, &firstCluster_)) { + remove(); + return false; + } + fileSize_ = size; + + // insure sync() will update dir entry + flags_ |= F_FILE_DIR_DIRTY; + return sync(); +} +//------------------------------------------------------------------------------ +/** + * Return a files directory entry + * + * \param[out] dir Location for return of the files directory entry. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t SdFile::dirEntry(dir_t* dir) { + // make sure fields on SD are correct + if (!sync()) return false; + + // read entry + dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); + if (!p) return false; + + // copy to caller's struct + memcpy(dir, p, sizeof(dir_t)); + return true; +} +//------------------------------------------------------------------------------ +/** + * Format the name field of \a dir into the 13 byte array + * \a name in standard 8.3 short name format. + * + * \param[in] dir The directory structure containing the name. + * \param[out] name A 13 byte char array for the formatted name. + */ +void SdFile::dirName(const dir_t& dir, char* name) { + uint8_t j = 0; + for (uint8_t i = 0; i < 11; i++) { + if (dir.name[i] == ' ')continue; + if (i == 8) name[j++] = '.'; + name[j++] = dir.name[i]; + } + name[j] = 0; +} +//------------------------------------------------------------------------------ +/** List directory contents to Serial. + * + * \param[in] flags The inclusive OR of + * + * LS_DATE - %Print file modification date + * + * LS_SIZE - %Print file size. + * + * LS_R - Recursive list of subdirectories. + * + * \param[in] indent Amount of space before file name. Used for recursive + * list to indicate subdirectory level. + */ +void SdFile::ls(uint8_t flags, uint8_t indent) { + dir_t* p; + + rewind(); + while ((p = readDirCache())) { + // done if past last used entry + if (p->name[0] == DIR_NAME_FREE) break; + + // skip deleted entry and entries for . and .. + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; + + // only list subdirectories and files + if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; + + // print any indent spaces + for (int8_t i = 0; i < indent; i++) Serial.print(' '); + + // print file name with possible blank fill + printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0); + + // print modify date/time if requested + if (flags & LS_DATE) { + printFatDate(p->lastWriteDate); + Serial.print(' '); + printFatTime(p->lastWriteTime); + } + // print size if requested + if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) { + Serial.print(' '); + Serial.print(p->fileSize); + } + Serial.println(); + + // list subdirectory content if requested + if ((flags & LS_R) && DIR_IS_SUBDIR(p)) { + uint16_t index = curPosition()/32 - 1; + SdFile s; + if (s.open(this, index, O_READ)) s.ls(flags, indent + 2); + seekSet(32 * (index + 1)); + } + } +} +//------------------------------------------------------------------------------ +// format directory name field from a 8.3 name string +uint8_t SdFile::make83Name(const char* str, uint8_t* name) { + uint8_t c; + uint8_t n = 7; // max index for part before dot + uint8_t i = 0; + // blank fill name and extension + while (i < 11) name[i++] = ' '; + i = 0; + while ((c = *str++) != '\0') { + if (c == '.') { + if (n == 10) return false; // only one dot allowed + n = 10; // max index for full 8.3 name + i = 8; // place for extension + } else { + // illegal FAT characters + PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); + uint8_t b; + while ((b = pgm_read_byte(p++))) if (b == c) return false; + // check size and only allow ASCII printable characters + if (i > n || c < 0X21 || c > 0X7E)return false; + // only upper case allowed in 8.3 names - convert lower to upper + name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); + } + } + // must have a file name, extension is optional + return name[0] != ' '; +} +//------------------------------------------------------------------------------ +/** Make a new directory. + * + * \param[in] dir An open SdFat instance for the directory that will containing + * the new directory. + * + * \param[in] dirName A valid 8.3 DOS name for the new directory. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include this SdFile is already open, \a dir is not a + * directory, \a dirName is invalid or already exists in \a dir. + */ +uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { + dir_t d; + + // create a normal file + if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) return false; + + // convert SdFile to directory + flags_ = O_READ; + type_ = FAT_FILE_TYPE_SUBDIR; + + // allocate and zero first cluster + if (!addDirCluster())return false; + + // force entry to SD + if (!sync()) return false; + + // cache entry - should already be in cache due to sync() call + dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!p) return false; + + // change directory entry attribute + p->attributes = DIR_ATT_DIRECTORY; + + // make entry for '.' + memcpy(&d, p, sizeof(d)); + for (uint8_t i = 1; i < 11; i++) d.name[i] = ' '; + d.name[0] = '.'; + + // cache block for '.' and '..' + uint32_t block = vol_->clusterStartBlock(firstCluster_); + if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false; + + // copy '.' to block + memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d)); + + // make entry for '..' + d.name[1] = '.'; + if (dir->isRoot()) { + d.firstClusterLow = 0; + d.firstClusterHigh = 0; + } else { + d.firstClusterLow = dir->firstCluster_ & 0XFFFF; + d.firstClusterHigh = dir->firstCluster_ >> 16; + } + // copy '..' to block + memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d)); + + // set position after '..' + curPosition_ = 2 * sizeof(d); + + // write first block + return SdVolume::cacheFlush(); +} +//------------------------------------------------------------------------------ +/** + * Open a file or directory by name. + * + * \param[in] dirFile An open SdFat instance for the directory containing the + * file to be opened. + * + * \param[in] fileName A valid 8.3 DOS name for a file to be opened. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags from the following list + * + * O_READ - Open for reading. + * + * O_RDONLY - Same as O_READ. + * + * O_WRITE - Open for writing. + * + * O_WRONLY - Same as O_WRITE. + * + * O_RDWR - Open for reading and writing. + * + * O_APPEND - If set, the file offset shall be set to the end of the + * file prior to each write. + * + * O_CREAT - If the file exists, this flag has no effect except as noted + * under O_EXCL below. Otherwise, the file shall be created + * + * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. + * + * O_SYNC - Call sync() after each write. This flag should not be used with + * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. + * These functions do character at a time writes so sync() will be called + * after each byte. + * + * O_TRUNC - If the file exists and is a regular file, and the file is + * successfully opened and is not read only, its length shall be truncated to 0. + * + * \note Directory files must be opened read only. Write and truncation is + * not allowed for directory files. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include this SdFile is already open, \a difFile is not + * a directory, \a fileName is invalid, the file does not exist + * or can't be opened in the access mode specified by oflag. + */ +uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { + uint8_t dname[11]; + dir_t* p; + + // error if already open + if (isOpen())return false; + + if (!make83Name(fileName, dname)) return false; + vol_ = dirFile->vol_; + dirFile->rewind(); + + // bool for empty entry found + uint8_t emptyFound = false; + + // search for file + while (dirFile->curPosition_ < dirFile->fileSize_) { + uint8_t index = 0XF & (dirFile->curPosition_ >> 5); + p = dirFile->readDirCache(); + if (p == NULL) return false; + + if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { + // remember first empty slot + if (!emptyFound) { + emptyFound = true; + dirIndex_ = index; + dirBlock_ = SdVolume::cacheBlockNumber_; + } + // done if no entries follow + if (p->name[0] == DIR_NAME_FREE) break; + } else if (!memcmp(dname, p->name, 11)) { + // don't open existing file if O_CREAT and O_EXCL + if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; + + // open found file + return openCachedEntry(0XF & index, oflag); + } + } + // only create file if O_CREAT and O_WRITE + if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false; + + // cache found slot or add cluster if end of file + if (emptyFound) { + p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!p) return false; + } else { + if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false; + + // add and zero cluster for dirFile - first cluster is in cache for write + if (!dirFile->addDirCluster()) return false; + + // use first entry in cluster + dirIndex_ = 0; + p = SdVolume::cacheBuffer_.dir; + } + // initialize as empty file + memset(p, 0, sizeof(dir_t)); + memcpy(p->name, dname, 11); + + // set timestamps + if (dateTime_) { + // call user function + dateTime_(&p->creationDate, &p->creationTime); + } else { + // use default date/time + p->creationDate = FAT_DEFAULT_DATE; + p->creationTime = FAT_DEFAULT_TIME; + } + p->lastAccessDate = p->creationDate; + p->lastWriteDate = p->creationDate; + p->lastWriteTime = p->creationTime; + + // force write of entry to SD + if (!SdVolume::cacheFlush()) return false; + + // open entry in cache + return openCachedEntry(dirIndex_, oflag); +} +//------------------------------------------------------------------------------ +/** + * Open a file by index. + * + * \param[in] dirFile An open SdFat instance for the directory. + * + * \param[in] index The \a index of the directory entry for the file to be + * opened. The value for \a index is (directory file position)/32. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. + * + * See open() by fileName for definition of flags and return values. + * + */ +uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { + // error if already open + if (isOpen())return false; + + // don't open existing file if O_CREAT and O_EXCL - user call error + if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; + + vol_ = dirFile->vol_; + + // seek to location of entry + if (!dirFile->seekSet(32 * index)) return false; + + // read entry into cache + dir_t* p = dirFile->readDirCache(); + if (p == NULL) return false; + + // error if empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_FREE || + p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + return false; + } + // open cached entry + return openCachedEntry(index & 0XF, oflag); +} +//------------------------------------------------------------------------------ +// open a cached directory entry. Assumes vol_ is initializes +uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { + // location of entry in cache + dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex; + + // write or truncate is an error for a directory or read-only file + if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { + if (oflag & (O_WRITE | O_TRUNC)) return false; + } + // remember location of directory entry on SD + dirIndex_ = dirIndex; + dirBlock_ = SdVolume::cacheBlockNumber_; + + // copy first cluster number for directory fields + firstCluster_ = (uint32_t)p->firstClusterHigh << 16; + firstCluster_ |= p->firstClusterLow; + + // make sure it is a normal file or subdirectory + if (DIR_IS_FILE(p)) { + fileSize_ = p->fileSize; + type_ = FAT_FILE_TYPE_NORMAL; + } else if (DIR_IS_SUBDIR(p)) { + if (!vol_->chainSize(firstCluster_, &fileSize_)) return false; + type_ = FAT_FILE_TYPE_SUBDIR; + } else { + return false; + } + // save open flags for read/write + flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND); + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + + // truncate file to zero length if requested + if (oflag & O_TRUNC) return truncate(0); + return true; +} +//------------------------------------------------------------------------------ +/** + * Open a volume's root directory. + * + * \param[in] vol The FAT volume containing the root directory to be opened. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the FAT volume has not been initialized + * or it a FAT12 volume. + */ +uint8_t SdFile::openRoot(SdVolume* vol) { + // error if file is already open + if (isOpen()) return false; + + if (vol->fatType() == 16) { + type_ = FAT_FILE_TYPE_ROOT16; + firstCluster_ = 0; + fileSize_ = 32 * vol->rootDirEntryCount(); + } else if (vol->fatType() == 32) { + type_ = FAT_FILE_TYPE_ROOT32; + firstCluster_ = vol->rootDirStart(); + if (!vol->chainSize(firstCluster_, &fileSize_)) return false; + } else { + // volume is not initialized or FAT12 + return false; + } + vol_ = vol; + // read only + flags_ = O_READ; + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + + // root has no directory entry + dirBlock_ = 0; + dirIndex_ = 0; + return true; +} +//------------------------------------------------------------------------------ +/** %Print the name field of a directory entry in 8.3 format to Serial. + * + * \param[in] dir The directory structure containing the name. + * \param[in] width Blank fill name if length is less than \a width. + */ +void SdFile::printDirName(const dir_t& dir, uint8_t width) { + uint8_t w = 0; + for (uint8_t i = 0; i < 11; i++) { + if (dir.name[i] == ' ')continue; + if (i == 8) { + Serial.print('.'); + w++; + } + Serial.print(dir.name[i]); + w++; + } + if (DIR_IS_SUBDIR(&dir)) { + Serial.print('/'); + w++; + } + while (w < width) { + Serial.print(' '); + w++; + } +} +//------------------------------------------------------------------------------ +/** %Print a directory date field to Serial. + * + * Format is yyyy-mm-dd. + * + * \param[in] fatDate The date field from a directory entry. + */ +void SdFile::printFatDate(uint16_t fatDate) { + Serial.print(FAT_YEAR(fatDate)); + Serial.print('-'); + printTwoDigits(FAT_MONTH(fatDate)); + Serial.print('-'); + printTwoDigits(FAT_DAY(fatDate)); +} +//------------------------------------------------------------------------------ +/** %Print a directory time field to Serial. + * + * Format is hh:mm:ss. + * + * \param[in] fatTime The time field from a directory entry. + */ +void SdFile::printFatTime(uint16_t fatTime) { + printTwoDigits(FAT_HOUR(fatTime)); + Serial.print(':'); + printTwoDigits(FAT_MINUTE(fatTime)); + Serial.print(':'); + printTwoDigits(FAT_SECOND(fatTime)); +} +//------------------------------------------------------------------------------ +/** %Print a value as two digits to Serial. + * + * \param[in] v Value to be printed, 0 <= \a v <= 99 + */ +void SdFile::printTwoDigits(uint8_t v) { + char str[3]; + str[0] = '0' + v/10; + str[1] = '0' + v % 10; + str[2] = 0; + Serial.print(str); +} +//------------------------------------------------------------------------------ +/** + * Read data from a file starting at the current position. + * + * \param[out] buf Pointer to the location that will receive the data. + * + * \param[in] nbyte Maximum number of bytes to read. + * + * \return For success read() returns the number of bytes read. + * A value less than \a nbyte, including zero, will be returned + * if end of file is reached. + * If an error occurs, read() returns -1. Possible errors include + * read() called before a file has been opened, corrupt file system + * or an I/O error occurred. + */ +int16_t SdFile::read(void* buf, uint16_t nbyte) { + uint8_t* dst = reinterpret_cast(buf); + + // error if not open or write only + if (!isOpen() || !(flags_ & O_READ)) return -1; + + // max bytes left in file + if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_; + + // amount left to read + uint16_t toRead = nbyte; + while (toRead > 0) { + uint32_t block; // raw device block number + uint16_t offset = curPosition_ & 0X1FF; // offset in block + if (type_ == FAT_FILE_TYPE_ROOT16) { + block = vol_->rootDirStart() + (curPosition_ >> 9); + } else { + uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); + if (offset == 0 && blockOfCluster == 0) { + // start of new cluster + if (curPosition_ == 0) { + // use first cluster in file + curCluster_ = firstCluster_; + } else { + // get next cluster from FAT + if (!vol_->fatGet(curCluster_, &curCluster_)) return -1; + } + } + block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + } + uint16_t n = toRead; + + // amount to be read from current block + if (n > (512 - offset)) n = 512 - offset; + + // no buffering needed if n == 512 or user requests no buffering + if ((unbufferedRead() || n == 512) && + block != SdVolume::cacheBlockNumber_) { + if (!vol_->readData(block, offset, n, dst)) return -1; + dst += n; + } else { + // read block to cache and copy data to caller + if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1; + uint8_t* src = SdVolume::cacheBuffer_.data + offset; + uint8_t* end = src + n; + while (src != end) *dst++ = *src++; + } + curPosition_ += n; + toRead -= n; + } + return nbyte; +} +//------------------------------------------------------------------------------ +/** + * Read the next directory entry from a directory file. + * + * \param[out] dir The dir_t struct that will receive the data. + * + * \return For success readDir() returns the number of bytes read. + * A value of zero will be returned if end of file is reached. + * If an error occurs, readDir() returns -1. Possible errors include + * readDir() called before a directory has been opened, this is not + * a directory file or an I/O error occurred. + */ +int8_t SdFile::readDir(dir_t* dir) { + int8_t n; + // if not a directory file or miss-positioned return an error + if (!isDir() || (0X1F & curPosition_)) return -1; + + while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) { + // last entry if DIR_NAME_FREE + if (dir->name[0] == DIR_NAME_FREE) break; + // skip empty entries and entry for . and .. + if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; + // return if normal file or subdirectory + if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; + } + // error, end of file, or past last entry + return n < 0 ? -1 : 0; +} +//------------------------------------------------------------------------------ +// Read next directory entry into the cache +// Assumes file is correctly positioned +dir_t* SdFile::readDirCache(void) { + // error if not directory + if (!isDir()) return NULL; + + // index of entry in cache + uint8_t i = (curPosition_ >> 5) & 0XF; + + // use read to locate and cache block + if (read() < 0) return NULL; + + // advance to next entry + curPosition_ += 31; + + // return pointer to entry + return (SdVolume::cacheBuffer_.dir + i); +} +//------------------------------------------------------------------------------ +/** + * Remove a file. + * + * The directory entry and all data for the file are deleted. + * + * \note This function should not be used to delete the 8.3 version of a + * file that has a long name. For example if a file has the long name + * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file read-only, is a directory, + * or an I/O error occurred. + */ +uint8_t SdFile::remove(void) { + // free any clusters - will fail if read-only or directory + if (!truncate(0)) return false; + + // cache directory entry + dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) return false; + + // mark entry deleted + d->name[0] = DIR_NAME_DELETED; + + // set this SdFile closed + type_ = FAT_FILE_TYPE_CLOSED; + + // write entry to SD + return SdVolume::cacheFlush(); +} +//------------------------------------------------------------------------------ +/** + * Remove a file. + * + * The directory entry and all data for the file are deleted. + * + * \param[in] dirFile The directory that contains the file. + * \param[in] fileName The name of the file to be removed. + * + * \note This function should not be used to delete the 8.3 version of a + * file that has a long name. For example if a file has the long name + * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file is a directory, is read only, + * \a dirFile is not a directory, \a fileName is not found + * or an I/O error occurred. + */ +uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) { + SdFile file; + if (!file.open(dirFile, fileName, O_WRITE)) return false; + return file.remove(); +} +//------------------------------------------------------------------------------ +/** Remove a directory file. + * + * The directory file will be removed only if it is empty and is not the + * root directory. rmDir() follows DOS and Windows and ignores the + * read-only attribute for the directory. + * + * \note This function should not be used to delete the 8.3 version of a + * directory that has a long name. For example if a directory has the + * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file is not a directory, is the root + * directory, is not empty, or an I/O error occurred. + */ +uint8_t SdFile::rmDir(void) { + // must be open subdirectory + if (!isSubDir()) return false; + + rewind(); + + // make sure directory is empty + while (curPosition_ < fileSize_) { + dir_t* p = readDirCache(); + if (p == NULL) return false; + // done if past last used entry + if (p->name[0] == DIR_NAME_FREE) break; + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; + // error not empty + if (DIR_IS_FILE_OR_SUBDIR(p)) return false; + } + // convert empty directory to normal file for remove + type_ = FAT_FILE_TYPE_NORMAL; + flags_ |= O_WRITE; + return remove(); +} +//------------------------------------------------------------------------------ +/** Recursively delete a directory and all contained files. + * + * This is like the Unix/Linux 'rm -rf *' if called with the root directory + * hence the name. + * + * Warning - This will remove all contents of the directory including + * subdirectories. The directory will then be removed if it is not root. + * The read-only attribute for files will be ignored. + * + * \note This function should not be used to delete the 8.3 version of + * a directory that has a long name. See remove() and rmDir(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t SdFile::rmRfStar(void) { + rewind(); + while (curPosition_ < fileSize_) { + SdFile f; + + // remember position + uint16_t index = curPosition_/32; + + dir_t* p = readDirCache(); + if (!p) return false; + + // done if past last entry + if (p->name[0] == DIR_NAME_FREE) break; + + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; + + // skip if part of long file name or volume label in root + if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; + + if (!f.open(this, index, O_READ)) return false; + if (f.isSubDir()) { + // recursively delete + if (!f.rmRfStar()) return false; + } else { + // ignore read-only + f.flags_ |= O_WRITE; + if (!f.remove()) return false; + } + // position to next entry if required + if (curPosition_ != (32*(index + 1))) { + if (!seekSet(32*(index + 1))) return false; + } + } + // don't try to delete root + if (isRoot()) return true; + return rmDir(); +} +//------------------------------------------------------------------------------ +/** + * Sets a file's position. + * + * \param[in] pos The new position in bytes from the beginning of the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t SdFile::seekSet(uint32_t pos) { + // error if file not open or seek past end of file + if (!isOpen() || pos > fileSize_) return false; + + if (type_ == FAT_FILE_TYPE_ROOT16) { + curPosition_ = pos; + return true; + } + if (pos == 0) { + // set position to start of file + curCluster_ = 0; + curPosition_ = 0; + return true; + } + // calculate cluster index for cur and new position + uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); + uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); + + if (nNew < nCur || curPosition_ == 0) { + // must follow chain from first cluster + curCluster_ = firstCluster_; + } else { + // advance from curPosition + nNew -= nCur; + } + while (nNew--) { + if (!vol_->fatGet(curCluster_, &curCluster_)) return false; + } + curPosition_ = pos; + return true; +} +//------------------------------------------------------------------------------ +/** + * The sync() call causes all modified data and directory fields + * to be written to the storage device. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include a call to sync() before a file has been + * opened or an I/O error. + */ +uint8_t SdFile::sync(void) { + // only allow open files and directories + if (!isOpen()) return false; + + if (flags_ & F_FILE_DIR_DIRTY) { + dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) return false; + + // do not set filesize for dir files + if (!isDir()) d->fileSize = fileSize_; + + // update first cluster fields + d->firstClusterLow = firstCluster_ & 0XFFFF; + d->firstClusterHigh = firstCluster_ >> 16; + + // set modify time if user supplied a callback date/time function + if (dateTime_) { + dateTime_(&d->lastWriteDate, &d->lastWriteTime); + d->lastAccessDate = d->lastWriteDate; + } + // clear directory dirty + flags_ &= ~F_FILE_DIR_DIRTY; + } + return SdVolume::cacheFlush(); +} +//------------------------------------------------------------------------------ +/** + * Set a file's timestamps in its directory entry. + * + * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive + * OR of flags from the following list + * + * T_ACCESS - Set the file's last access date. + * + * T_CREATE - Set the file's creation date and time. + * + * T_WRITE - Set the file's last write/modification date and time. + * + * \param[in] year Valid range 1980 - 2107 inclusive. + * + * \param[in] month Valid range 1 - 12 inclusive. + * + * \param[in] day Valid range 1 - 31 inclusive. + * + * \param[in] hour Valid range 0 - 23 inclusive. + * + * \param[in] minute Valid range 0 - 59 inclusive. + * + * \param[in] second Valid range 0 - 59 inclusive + * + * \note It is possible to set an invalid date since there is no check for + * the number of days in a month. + * + * \note + * Modify and access timestamps may be overwritten if a date time callback + * function has been set by dateTimeCallback(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, + uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { + if (!isOpen() + || year < 1980 + || year > 2107 + || month < 1 + || month > 12 + || day < 1 + || day > 31 + || hour > 23 + || minute > 59 + || second > 59) { + return false; + } + dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) return false; + + uint16_t dirDate = FAT_DATE(year, month, day); + uint16_t dirTime = FAT_TIME(hour, minute, second); + if (flags & T_ACCESS) { + d->lastAccessDate = dirDate; + } + if (flags & T_CREATE) { + d->creationDate = dirDate; + d->creationTime = dirTime; + // seems to be units of 1/100 second not 1/10 as Microsoft states + d->creationTimeTenths = second & 1 ? 100 : 0; + } + if (flags & T_WRITE) { + d->lastWriteDate = dirDate; + d->lastWriteTime = dirTime; + } + SdVolume::cacheSetDirty(); + return sync(); +} +//------------------------------------------------------------------------------ +/** + * Truncate a file to a specified length. The current file position + * will be maintained if it is less than or equal to \a length otherwise + * it will be set to end of file. + * + * \param[in] length The desired length for the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include file is read only, file is a directory, + * \a length is greater than the current file size or an I/O error occurs. + */ +uint8_t SdFile::truncate(uint32_t length) { +// error if not a normal file or read-only + if (!isFile() || !(flags_ & O_WRITE)) return false; + + // error if length is greater than current size + if (length > fileSize_) return false; + + // fileSize and length are zero - nothing to do + if (fileSize_ == 0) return true; + + // remember position for seek after truncation + uint32_t newPos = curPosition_ > length ? length : curPosition_; + + // position to last cluster in truncated file + if (!seekSet(length)) return false; + + if (length == 0) { + // free all clusters + if (!vol_->freeChain(firstCluster_)) return false; + firstCluster_ = 0; + } else { + uint32_t toFree; + if (!vol_->fatGet(curCluster_, &toFree)) return false; + + if (!vol_->isEOC(toFree)) { + // free extra clusters + if (!vol_->freeChain(toFree)) return false; + + // current cluster is end of chain + if (!vol_->fatPutEOC(curCluster_)) return false; + } + } + fileSize_ = length; + + // need to update directory entry + flags_ |= F_FILE_DIR_DIRTY; + + if (!sync()) return false; + + // set file to correct position + return seekSet(newPos); +} +//------------------------------------------------------------------------------ +/** + * Write data to an open file. + * + * \note Data is moved to the cache but may not be written to the + * storage device until sync() is called. + * + * \param[in] buf Pointer to the location of the data to be written. + * + * \param[in] nbyte Number of bytes to write. + * + * \return For success write() returns the number of bytes written, always + * \a nbyte. If an error occurs, write() returns -1. Possible errors + * include write() is called before a file has been opened, write is called + * for a read-only file, device is full, a corrupt file system or an I/O error. + * + */ +int16_t SdFile::write(const void* buf, uint16_t nbyte) { + // convert void* to uint8_t* - must be before goto statements + const uint8_t* src = reinterpret_cast(buf); + + // number of bytes left to write - must be before goto statements + uint16_t nToWrite = nbyte; + + // error if not a normal file or is read-only + if (!isFile() || !(flags_ & O_WRITE)) goto writeErrorReturn; + + // seek to end of file if append flag + if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { + if (!seekEnd()) goto writeErrorReturn; + } + + while (nToWrite > 0) { + uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); + uint16_t blockOffset = curPosition_ & 0X1FF; + if (blockOfCluster == 0 && blockOffset == 0) { + // start of new cluster + if (curCluster_ == 0) { + if (firstCluster_ == 0) { + // allocate first cluster of file + if (!addCluster()) goto writeErrorReturn; + } else { + curCluster_ = firstCluster_; + } + } else { + uint32_t next; + if (!vol_->fatGet(curCluster_, &next)) return false; + if (vol_->isEOC(next)) { + // add cluster if at end of chain + if (!addCluster()) goto writeErrorReturn; + } else { + curCluster_ = next; + } + } + } + // max space in block + uint16_t n = 512 - blockOffset; + + // lesser of space and amount to write + if (n > nToWrite) n = nToWrite; + + // block for data write + uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + if (n == 512) { + // full block - don't need to use cache + // invalidate cache if block is in cache + if (SdVolume::cacheBlockNumber_ == block) { + SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; + } + if (!vol_->writeBlock(block, src)) goto writeErrorReturn; + src += 512; + } else { + if (blockOffset == 0 && curPosition_ >= fileSize_) { + // start of new block don't need to read into cache + if (!SdVolume::cacheFlush()) goto writeErrorReturn; + SdVolume::cacheBlockNumber_ = block; + SdVolume::cacheSetDirty(); + } else { + // rewrite part of block + if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { + goto writeErrorReturn; + } + } + uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset; + uint8_t* end = dst + n; + while (dst != end) *dst++ = *src++; + } + nToWrite -= n; + curPosition_ += n; + } + if (curPosition_ > fileSize_) { + // update fileSize and insure sync will update dir entry + fileSize_ = curPosition_; + flags_ |= F_FILE_DIR_DIRTY; + } else if (dateTime_ && nbyte) { + // insure sync will update modified date and time + flags_ |= F_FILE_DIR_DIRTY; + } + + if (flags_ & O_SYNC) { + if (!sync()) goto writeErrorReturn; + } + return nbyte; + + writeErrorReturn: + // return for write error + writeError = true; + return -1; +} +//------------------------------------------------------------------------------ +/** + * Write a byte to a file. Required by the Arduino Print class. + * + * Use SdFile::writeError to check for errors. + */ +void SdFile::write(uint8_t b) { + write(&b, 1); +} +//------------------------------------------------------------------------------ +/** + * Write a string to a file. Used by the Arduino Print class. + * + * Use SdFile::writeError to check for errors. + */ +void SdFile::write(const char* str) { + write(str, strlen(str)); +} +//------------------------------------------------------------------------------ +/** + * Write a PROGMEM string to a file. + * + * Use SdFile::writeError to check for errors. + */ +void SdFile::write_P(PGM_P str) { + for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c); +} +//------------------------------------------------------------------------------ +/** + * Write a PROGMEM string followed by CR/LF to a file. + * + * Use SdFile::writeError to check for errors. + */ +void SdFile::writeln_P(PGM_P str) { + write_P(str); + println(); +} diff --git a/Marlin/SdInfo.h b/Marlin/SdInfo.h index bc4c6137f5..acde74d974 100644 --- a/Marlin/SdInfo.h +++ b/Marlin/SdInfo.h @@ -1,232 +1,232 @@ -/* Arduino Sd2Card Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino Sd2Card Library - * - * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see - * . - */ -#ifndef SdInfo_h -#define SdInfo_h -#include -// Based on the document: -// -// SD Specifications -// Part 1 -// Physical Layer -// Simplified Specification -// Version 2.00 -// September 25, 2006 -// -// www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf -//------------------------------------------------------------------------------ -// SD card commands -/** GO_IDLE_STATE - init card in spi mode if CS low */ -uint8_t const CMD0 = 0X00; -/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/ -uint8_t const CMD8 = 0X08; -/** SEND_CSD - read the Card Specific Data (CSD register) */ -uint8_t const CMD9 = 0X09; -/** SEND_CID - read the card identification information (CID register) */ -uint8_t const CMD10 = 0X0A; -/** SEND_STATUS - read the card status register */ -uint8_t const CMD13 = 0X0D; -/** READ_BLOCK - read a single data block from the card */ -uint8_t const CMD17 = 0X11; -/** WRITE_BLOCK - write a single data block to the card */ -uint8_t const CMD24 = 0X18; -/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ -uint8_t const CMD25 = 0X19; -/** ERASE_WR_BLK_START - sets the address of the first block to be erased */ -uint8_t const CMD32 = 0X20; -/** ERASE_WR_BLK_END - sets the address of the last block of the continuous - range to be erased*/ -uint8_t const CMD33 = 0X21; -/** ERASE - erase all previously selected blocks */ -uint8_t const CMD38 = 0X26; -/** APP_CMD - escape for application specific command */ -uint8_t const CMD55 = 0X37; -/** READ_OCR - read the OCR register of a card */ -uint8_t const CMD58 = 0X3A; -/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be - pre-erased before writing */ -uint8_t const ACMD23 = 0X17; -/** SD_SEND_OP_COMD - Sends host capacity support information and - activates the card's initialization process */ -uint8_t const ACMD41 = 0X29; -//------------------------------------------------------------------------------ -/** status for card in the ready state */ -uint8_t const R1_READY_STATE = 0X00; -/** status for card in the idle state */ -uint8_t const R1_IDLE_STATE = 0X01; -/** status bit for illegal command */ -uint8_t const R1_ILLEGAL_COMMAND = 0X04; -/** start data token for read or write single block*/ -uint8_t const DATA_START_BLOCK = 0XFE; -/** stop token for write multiple blocks*/ -uint8_t const STOP_TRAN_TOKEN = 0XFD; -/** start data token for write multiple blocks*/ -uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC; -/** mask for data response tokens after a write block operation */ -uint8_t const DATA_RES_MASK = 0X1F; -/** write data accepted token */ -uint8_t const DATA_RES_ACCEPTED = 0X05; -//------------------------------------------------------------------------------ -typedef struct CID { - // byte 0 - uint8_t mid; // Manufacturer ID - // byte 1-2 - char oid[2]; // OEM/Application ID - // byte 3-7 - char pnm[5]; // Product name - // byte 8 - unsigned prv_m : 4; // Product revision n.m - unsigned prv_n : 4; - // byte 9-12 - uint32_t psn; // Product serial number - // byte 13 - unsigned mdt_year_high : 4; // Manufacturing date - unsigned reserved : 4; - // byte 14 - unsigned mdt_month : 4; - unsigned mdt_year_low :4; - // byte 15 - unsigned always1 : 1; - unsigned crc : 7; -}cid_t; -//------------------------------------------------------------------------------ -// CSD for version 1.00 cards -typedef struct CSDV1 { - // byte 0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; - // byte 1 - uint8_t taac; - // byte 2 - uint8_t nsac; - // byte 3 - uint8_t tran_speed; - // byte 4 - uint8_t ccc_high; - // byte 5 - unsigned read_bl_len : 4; - unsigned ccc_low : 4; - // byte 6 - unsigned c_size_high : 2; - unsigned reserved2 : 2; - unsigned dsr_imp : 1; - unsigned read_blk_misalign :1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; - // byte 7 - uint8_t c_size_mid; - // byte 8 - unsigned vdd_r_curr_max : 3; - unsigned vdd_r_curr_min : 3; - unsigned c_size_low :2; - // byte 9 - unsigned c_size_mult_high : 2; - unsigned vdd_w_cur_max : 3; - unsigned vdd_w_curr_min : 3; - // byte 10 - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned c_size_mult_low : 1; - // byte 11 - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; - // byte 12 - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved3 : 2; - unsigned wp_grp_enable : 1; - // byte 13 - unsigned reserved4 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; - // byte 14 - unsigned reserved5: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; - // byte 15 - unsigned always1 : 1; - unsigned crc : 7; -}csd1_t; -//------------------------------------------------------------------------------ -// CSD for version 2.00 cards -typedef struct CSDV2 { - // byte 0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; - // byte 1 - uint8_t taac; - // byte 2 - uint8_t nsac; - // byte 3 - uint8_t tran_speed; - // byte 4 - uint8_t ccc_high; - // byte 5 - unsigned read_bl_len : 4; - unsigned ccc_low : 4; - // byte 6 - unsigned reserved2 : 4; - unsigned dsr_imp : 1; - unsigned read_blk_misalign :1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; - // byte 7 - unsigned reserved3 : 2; - unsigned c_size_high : 6; - // byte 8 - uint8_t c_size_mid; - // byte 9 - uint8_t c_size_low; - // byte 10 - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned reserved4 : 1; - // byte 11 - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; - // byte 12 - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved5 : 2; - unsigned wp_grp_enable : 1; - // byte 13 - unsigned reserved6 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; - // byte 14 - unsigned reserved7: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; - // byte 15 - unsigned always1 : 1; - unsigned crc : 7; -}csd2_t; -//------------------------------------------------------------------------------ -// union of old and new style CSD register -union csd_t { - csd1_t v1; - csd2_t v2; -}; -#endif // SdInfo_h +/* Arduino Sd2Card Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino Sd2Card Library + * + * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see + * . + */ +#ifndef SdInfo_h +#define SdInfo_h +#include +// Based on the document: +// +// SD Specifications +// Part 1 +// Physical Layer +// Simplified Specification +// Version 2.00 +// September 25, 2006 +// +// www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf +//------------------------------------------------------------------------------ +// SD card commands +/** GO_IDLE_STATE - init card in spi mode if CS low */ +uint8_t const CMD0 = 0X00; +/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/ +uint8_t const CMD8 = 0X08; +/** SEND_CSD - read the Card Specific Data (CSD register) */ +uint8_t const CMD9 = 0X09; +/** SEND_CID - read the card identification information (CID register) */ +uint8_t const CMD10 = 0X0A; +/** SEND_STATUS - read the card status register */ +uint8_t const CMD13 = 0X0D; +/** READ_BLOCK - read a single data block from the card */ +uint8_t const CMD17 = 0X11; +/** WRITE_BLOCK - write a single data block to the card */ +uint8_t const CMD24 = 0X18; +/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ +uint8_t const CMD25 = 0X19; +/** ERASE_WR_BLK_START - sets the address of the first block to be erased */ +uint8_t const CMD32 = 0X20; +/** ERASE_WR_BLK_END - sets the address of the last block of the continuous + range to be erased*/ +uint8_t const CMD33 = 0X21; +/** ERASE - erase all previously selected blocks */ +uint8_t const CMD38 = 0X26; +/** APP_CMD - escape for application specific command */ +uint8_t const CMD55 = 0X37; +/** READ_OCR - read the OCR register of a card */ +uint8_t const CMD58 = 0X3A; +/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be + pre-erased before writing */ +uint8_t const ACMD23 = 0X17; +/** SD_SEND_OP_COMD - Sends host capacity support information and + activates the card's initialization process */ +uint8_t const ACMD41 = 0X29; +//------------------------------------------------------------------------------ +/** status for card in the ready state */ +uint8_t const R1_READY_STATE = 0X00; +/** status for card in the idle state */ +uint8_t const R1_IDLE_STATE = 0X01; +/** status bit for illegal command */ +uint8_t const R1_ILLEGAL_COMMAND = 0X04; +/** start data token for read or write single block*/ +uint8_t const DATA_START_BLOCK = 0XFE; +/** stop token for write multiple blocks*/ +uint8_t const STOP_TRAN_TOKEN = 0XFD; +/** start data token for write multiple blocks*/ +uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC; +/** mask for data response tokens after a write block operation */ +uint8_t const DATA_RES_MASK = 0X1F; +/** write data accepted token */ +uint8_t const DATA_RES_ACCEPTED = 0X05; +//------------------------------------------------------------------------------ +typedef struct CID { + // byte 0 + uint8_t mid; // Manufacturer ID + // byte 1-2 + char oid[2]; // OEM/Application ID + // byte 3-7 + char pnm[5]; // Product name + // byte 8 + unsigned prv_m : 4; // Product revision n.m + unsigned prv_n : 4; + // byte 9-12 + uint32_t psn; // Product serial number + // byte 13 + unsigned mdt_year_high : 4; // Manufacturing date + unsigned reserved : 4; + // byte 14 + unsigned mdt_month : 4; + unsigned mdt_year_low :4; + // byte 15 + unsigned always1 : 1; + unsigned crc : 7; +}cid_t; +//------------------------------------------------------------------------------ +// CSD for version 1.00 cards +typedef struct CSDV1 { + // byte 0 + unsigned reserved1 : 6; + unsigned csd_ver : 2; + // byte 1 + uint8_t taac; + // byte 2 + uint8_t nsac; + // byte 3 + uint8_t tran_speed; + // byte 4 + uint8_t ccc_high; + // byte 5 + unsigned read_bl_len : 4; + unsigned ccc_low : 4; + // byte 6 + unsigned c_size_high : 2; + unsigned reserved2 : 2; + unsigned dsr_imp : 1; + unsigned read_blk_misalign :1; + unsigned write_blk_misalign : 1; + unsigned read_bl_partial : 1; + // byte 7 + uint8_t c_size_mid; + // byte 8 + unsigned vdd_r_curr_max : 3; + unsigned vdd_r_curr_min : 3; + unsigned c_size_low :2; + // byte 9 + unsigned c_size_mult_high : 2; + unsigned vdd_w_cur_max : 3; + unsigned vdd_w_curr_min : 3; + // byte 10 + unsigned sector_size_high : 6; + unsigned erase_blk_en : 1; + unsigned c_size_mult_low : 1; + // byte 11 + unsigned wp_grp_size : 7; + unsigned sector_size_low : 1; + // byte 12 + unsigned write_bl_len_high : 2; + unsigned r2w_factor : 3; + unsigned reserved3 : 2; + unsigned wp_grp_enable : 1; + // byte 13 + unsigned reserved4 : 5; + unsigned write_partial : 1; + unsigned write_bl_len_low : 2; + // byte 14 + unsigned reserved5: 2; + unsigned file_format : 2; + unsigned tmp_write_protect : 1; + unsigned perm_write_protect : 1; + unsigned copy : 1; + unsigned file_format_grp : 1; + // byte 15 + unsigned always1 : 1; + unsigned crc : 7; +}csd1_t; +//------------------------------------------------------------------------------ +// CSD for version 2.00 cards +typedef struct CSDV2 { + // byte 0 + unsigned reserved1 : 6; + unsigned csd_ver : 2; + // byte 1 + uint8_t taac; + // byte 2 + uint8_t nsac; + // byte 3 + uint8_t tran_speed; + // byte 4 + uint8_t ccc_high; + // byte 5 + unsigned read_bl_len : 4; + unsigned ccc_low : 4; + // byte 6 + unsigned reserved2 : 4; + unsigned dsr_imp : 1; + unsigned read_blk_misalign :1; + unsigned write_blk_misalign : 1; + unsigned read_bl_partial : 1; + // byte 7 + unsigned reserved3 : 2; + unsigned c_size_high : 6; + // byte 8 + uint8_t c_size_mid; + // byte 9 + uint8_t c_size_low; + // byte 10 + unsigned sector_size_high : 6; + unsigned erase_blk_en : 1; + unsigned reserved4 : 1; + // byte 11 + unsigned wp_grp_size : 7; + unsigned sector_size_low : 1; + // byte 12 + unsigned write_bl_len_high : 2; + unsigned r2w_factor : 3; + unsigned reserved5 : 2; + unsigned wp_grp_enable : 1; + // byte 13 + unsigned reserved6 : 5; + unsigned write_partial : 1; + unsigned write_bl_len_low : 2; + // byte 14 + unsigned reserved7: 2; + unsigned file_format : 2; + unsigned tmp_write_protect : 1; + unsigned perm_write_protect : 1; + unsigned copy : 1; + unsigned file_format_grp : 1; + // byte 15 + unsigned always1 : 1; + unsigned crc : 7; +}csd2_t; +//------------------------------------------------------------------------------ +// union of old and new style CSD register +union csd_t { + csd1_t v1; + csd2_t v2; +}; +#endif // SdInfo_h diff --git a/Marlin/SdVolume.cpp b/Marlin/SdVolume.cpp index 3c1e641c7b..2fbb8100b9 100644 --- a/Marlin/SdVolume.cpp +++ b/Marlin/SdVolume.cpp @@ -1,295 +1,295 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#include "SdFat.h" -//------------------------------------------------------------------------------ -// raw block cache -// init cacheBlockNumber_to invalid SD block number -uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; -cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card -Sd2Card* SdVolume::sdCard_; // pointer to SD card object -uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true -uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT -//------------------------------------------------------------------------------ -// find a contiguous group of clusters -uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { - // start of group - uint32_t bgnCluster; - - // flag to save place to start next search - uint8_t setStart; - - // set search start cluster - if (*curCluster) { - // try to make file contiguous - bgnCluster = *curCluster + 1; - - // don't save new start location - setStart = false; - } else { - // start at likely place for free cluster - bgnCluster = allocSearchStart_; - - // save next search start if one cluster - setStart = 1 == count; - } - // end of group - uint32_t endCluster = bgnCluster; - - // last cluster of FAT - uint32_t fatEnd = clusterCount_ + 1; - - // search the FAT for free clusters - for (uint32_t n = 0;; n++, endCluster++) { - // can't find space checked all clusters - if (n >= clusterCount_) return false; - - // past end - start from beginning of FAT - if (endCluster > fatEnd) { - bgnCluster = endCluster = 2; - } - uint32_t f; - if (!fatGet(endCluster, &f)) return false; - - if (f != 0) { - // cluster in use try next cluster as bgnCluster - bgnCluster = endCluster + 1; - } else if ((endCluster - bgnCluster + 1) == count) { - // done - found space - break; - } - } - // mark end of chain - if (!fatPutEOC(endCluster)) return false; - - // link clusters - while (endCluster > bgnCluster) { - if (!fatPut(endCluster - 1, endCluster)) return false; - endCluster--; - } - if (*curCluster != 0) { - // connect chains - if (!fatPut(*curCluster, bgnCluster)) return false; - } - // return first cluster number to caller - *curCluster = bgnCluster; - - // remember possible next free cluster - if (setStart) allocSearchStart_ = bgnCluster + 1; - - return true; -} -//------------------------------------------------------------------------------ -uint8_t SdVolume::cacheFlush(void) { - if (cacheDirty_) { - if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) { - return false; - } - // mirror FAT tables - if (cacheMirrorBlock_) { - if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) { - return false; - } - cacheMirrorBlock_ = 0; - } - cacheDirty_ = 0; - } - return true; -} -//------------------------------------------------------------------------------ -uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) { - if (cacheBlockNumber_ != blockNumber) { - if (!cacheFlush()) return false; - if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false; - cacheBlockNumber_ = blockNumber; - } - cacheDirty_ |= action; - return true; -} -//------------------------------------------------------------------------------ -// cache a zero block for blockNumber -uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) { - if (!cacheFlush()) return false; - - // loop take less flash than memset(cacheBuffer_.data, 0, 512); - for (uint16_t i = 0; i < 512; i++) { - cacheBuffer_.data[i] = 0; - } - cacheBlockNumber_ = blockNumber; - cacheSetDirty(); - return true; -} -//------------------------------------------------------------------------------ -// return the size in bytes of a cluster chain -uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { - uint32_t s = 0; - do { - if (!fatGet(cluster, &cluster)) return false; - s += 512UL << clusterSizeShift_; - } while (!isEOC(cluster)); - *size = s; - return true; -} -//------------------------------------------------------------------------------ -// Fetch a FAT entry -uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { - if (cluster > (clusterCount_ + 1)) return false; - uint32_t lba = fatStartBlock_; - lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; - if (lba != cacheBlockNumber_) { - if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; - } - if (fatType_ == 16) { - *value = cacheBuffer_.fat16[cluster & 0XFF]; - } else { - *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; - } - return true; -} -//------------------------------------------------------------------------------ -// Store a FAT entry -uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) { - // error if reserved cluster - if (cluster < 2) return false; - - // error if not in FAT - if (cluster > (clusterCount_ + 1)) return false; - - // calculate block address for entry - uint32_t lba = fatStartBlock_; - lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; - - if (lba != cacheBlockNumber_) { - if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; - } - // store entry - if (fatType_ == 16) { - cacheBuffer_.fat16[cluster & 0XFF] = value; - } else { - cacheBuffer_.fat32[cluster & 0X7F] = value; - } - cacheSetDirty(); - - // mirror second FAT - if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_; - return true; -} -//------------------------------------------------------------------------------ -// free a cluster chain -uint8_t SdVolume::freeChain(uint32_t cluster) { - // clear free cluster location - allocSearchStart_ = 2; - - do { - uint32_t next; - if (!fatGet(cluster, &next)) return false; - - // free cluster - if (!fatPut(cluster, 0)) return false; - - cluster = next; - } while (!isEOC(cluster)); - - return true; -} -//------------------------------------------------------------------------------ -/** - * Initialize a FAT volume. - * - * \param[in] dev The SD card where the volume is located. - * - * \param[in] part The partition to be used. Legal values for \a part are - * 1-4 to use the corresponding partition on a device formatted with - * a MBR, Master Boot Record, or zero if the device is formatted as - * a super floppy with the FAT boot sector in block zero. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. Reasons for - * failure include not finding a valid partition, not finding a valid - * FAT file system in the specified partition or an I/O error. - */ -uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { - uint32_t volumeStartBlock = 0; - sdCard_ = dev; - // if part == 0 assume super floppy with FAT boot sector in block zero - // if part > 0 assume mbr volume with partition table - if (part) { - if (part > 4)return false; - if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; - part_t* p = &cacheBuffer_.mbr.part[part-1]; - if ((p->boot & 0X7F) !=0 || - p->totalSectors < 100 || - p->firstSector == 0) { - // not a valid partition - return false; - } - volumeStartBlock = p->firstSector; - } - if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; - bpb_t* bpb = &cacheBuffer_.fbs.bpb; - if (bpb->bytesPerSector != 512 || - bpb->fatCount == 0 || - bpb->reservedSectorCount == 0 || - bpb->sectorsPerCluster == 0) { - // not valid FAT volume - return false; - } - fatCount_ = bpb->fatCount; - blocksPerCluster_ = bpb->sectorsPerCluster; - - // determine shift that is same as multiply by blocksPerCluster_ - clusterSizeShift_ = 0; - while (blocksPerCluster_ != (1 << clusterSizeShift_)) { - // error if not power of 2 - if (clusterSizeShift_++ > 7) return false; - } - blocksPerFat_ = bpb->sectorsPerFat16 ? - bpb->sectorsPerFat16 : bpb->sectorsPerFat32; - - fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount; - - // count for FAT16 zero for FAT32 - rootDirEntryCount_ = bpb->rootDirEntryCount; - - // directory start for FAT16 dataStart for FAT32 - rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_; - - // data start for FAT16 and FAT32 - dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512); - - // total blocks for FAT16 or FAT32 - uint32_t totalBlocks = bpb->totalSectors16 ? - bpb->totalSectors16 : bpb->totalSectors32; - // total data blocks - clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); - - // divide by cluster size to get cluster count - clusterCount_ >>= clusterSizeShift_; - - // FAT type is determined by cluster count - if (clusterCount_ < 4085) { - fatType_ = 12; - } else if (clusterCount_ < 65525) { - fatType_ = 16; - } else { - rootDirStart_ = bpb->fat32RootCluster; - fatType_ = 32; - } - return true; -} +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#include "SdFat.h" +//------------------------------------------------------------------------------ +// raw block cache +// init cacheBlockNumber_to invalid SD block number +uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; +cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card +Sd2Card* SdVolume::sdCard_; // pointer to SD card object +uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true +uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT +//------------------------------------------------------------------------------ +// find a contiguous group of clusters +uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { + // start of group + uint32_t bgnCluster; + + // flag to save place to start next search + uint8_t setStart; + + // set search start cluster + if (*curCluster) { + // try to make file contiguous + bgnCluster = *curCluster + 1; + + // don't save new start location + setStart = false; + } else { + // start at likely place for free cluster + bgnCluster = allocSearchStart_; + + // save next search start if one cluster + setStart = 1 == count; + } + // end of group + uint32_t endCluster = bgnCluster; + + // last cluster of FAT + uint32_t fatEnd = clusterCount_ + 1; + + // search the FAT for free clusters + for (uint32_t n = 0;; n++, endCluster++) { + // can't find space checked all clusters + if (n >= clusterCount_) return false; + + // past end - start from beginning of FAT + if (endCluster > fatEnd) { + bgnCluster = endCluster = 2; + } + uint32_t f; + if (!fatGet(endCluster, &f)) return false; + + if (f != 0) { + // cluster in use try next cluster as bgnCluster + bgnCluster = endCluster + 1; + } else if ((endCluster - bgnCluster + 1) == count) { + // done - found space + break; + } + } + // mark end of chain + if (!fatPutEOC(endCluster)) return false; + + // link clusters + while (endCluster > bgnCluster) { + if (!fatPut(endCluster - 1, endCluster)) return false; + endCluster--; + } + if (*curCluster != 0) { + // connect chains + if (!fatPut(*curCluster, bgnCluster)) return false; + } + // return first cluster number to caller + *curCluster = bgnCluster; + + // remember possible next free cluster + if (setStart) allocSearchStart_ = bgnCluster + 1; + + return true; +} +//------------------------------------------------------------------------------ +uint8_t SdVolume::cacheFlush(void) { + if (cacheDirty_) { + if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) { + return false; + } + // mirror FAT tables + if (cacheMirrorBlock_) { + if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) { + return false; + } + cacheMirrorBlock_ = 0; + } + cacheDirty_ = 0; + } + return true; +} +//------------------------------------------------------------------------------ +uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) { + if (cacheBlockNumber_ != blockNumber) { + if (!cacheFlush()) return false; + if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false; + cacheBlockNumber_ = blockNumber; + } + cacheDirty_ |= action; + return true; +} +//------------------------------------------------------------------------------ +// cache a zero block for blockNumber +uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) { + if (!cacheFlush()) return false; + + // loop take less flash than memset(cacheBuffer_.data, 0, 512); + for (uint16_t i = 0; i < 512; i++) { + cacheBuffer_.data[i] = 0; + } + cacheBlockNumber_ = blockNumber; + cacheSetDirty(); + return true; +} +//------------------------------------------------------------------------------ +// return the size in bytes of a cluster chain +uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { + uint32_t s = 0; + do { + if (!fatGet(cluster, &cluster)) return false; + s += 512UL << clusterSizeShift_; + } while (!isEOC(cluster)); + *size = s; + return true; +} +//------------------------------------------------------------------------------ +// Fetch a FAT entry +uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { + if (cluster > (clusterCount_ + 1)) return false; + uint32_t lba = fatStartBlock_; + lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; + if (lba != cacheBlockNumber_) { + if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; + } + if (fatType_ == 16) { + *value = cacheBuffer_.fat16[cluster & 0XFF]; + } else { + *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; + } + return true; +} +//------------------------------------------------------------------------------ +// Store a FAT entry +uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) { + // error if reserved cluster + if (cluster < 2) return false; + + // error if not in FAT + if (cluster > (clusterCount_ + 1)) return false; + + // calculate block address for entry + uint32_t lba = fatStartBlock_; + lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; + + if (lba != cacheBlockNumber_) { + if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; + } + // store entry + if (fatType_ == 16) { + cacheBuffer_.fat16[cluster & 0XFF] = value; + } else { + cacheBuffer_.fat32[cluster & 0X7F] = value; + } + cacheSetDirty(); + + // mirror second FAT + if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_; + return true; +} +//------------------------------------------------------------------------------ +// free a cluster chain +uint8_t SdVolume::freeChain(uint32_t cluster) { + // clear free cluster location + allocSearchStart_ = 2; + + do { + uint32_t next; + if (!fatGet(cluster, &next)) return false; + + // free cluster + if (!fatPut(cluster, 0)) return false; + + cluster = next; + } while (!isEOC(cluster)); + + return true; +} +//------------------------------------------------------------------------------ +/** + * Initialize a FAT volume. + * + * \param[in] dev The SD card where the volume is located. + * + * \param[in] part The partition to be used. Legal values for \a part are + * 1-4 to use the corresponding partition on a device formatted with + * a MBR, Master Boot Record, or zero if the device is formatted as + * a super floppy with the FAT boot sector in block zero. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. Reasons for + * failure include not finding a valid partition, not finding a valid + * FAT file system in the specified partition or an I/O error. + */ +uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { + uint32_t volumeStartBlock = 0; + sdCard_ = dev; + // if part == 0 assume super floppy with FAT boot sector in block zero + // if part > 0 assume mbr volume with partition table + if (part) { + if (part > 4)return false; + if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; + part_t* p = &cacheBuffer_.mbr.part[part-1]; + if ((p->boot & 0X7F) !=0 || + p->totalSectors < 100 || + p->firstSector == 0) { + // not a valid partition + return false; + } + volumeStartBlock = p->firstSector; + } + if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; + bpb_t* bpb = &cacheBuffer_.fbs.bpb; + if (bpb->bytesPerSector != 512 || + bpb->fatCount == 0 || + bpb->reservedSectorCount == 0 || + bpb->sectorsPerCluster == 0) { + // not valid FAT volume + return false; + } + fatCount_ = bpb->fatCount; + blocksPerCluster_ = bpb->sectorsPerCluster; + + // determine shift that is same as multiply by blocksPerCluster_ + clusterSizeShift_ = 0; + while (blocksPerCluster_ != (1 << clusterSizeShift_)) { + // error if not power of 2 + if (clusterSizeShift_++ > 7) return false; + } + blocksPerFat_ = bpb->sectorsPerFat16 ? + bpb->sectorsPerFat16 : bpb->sectorsPerFat32; + + fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount; + + // count for FAT16 zero for FAT32 + rootDirEntryCount_ = bpb->rootDirEntryCount; + + // directory start for FAT16 dataStart for FAT32 + rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_; + + // data start for FAT16 and FAT32 + dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512); + + // total blocks for FAT16 or FAT32 + uint32_t totalBlocks = bpb->totalSectors16 ? + bpb->totalSectors16 : bpb->totalSectors32; + // total data blocks + clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); + + // divide by cluster size to get cluster count + clusterCount_ >>= clusterSizeShift_; + + // FAT type is determined by cluster count + if (clusterCount_ < 4085) { + fatType_ = 12; + } else if (clusterCount_ < 65525) { + fatType_ = 16; + } else { + rootDirStart_ = bpb->fat32RootCluster; + fatType_ = 32; + } + return true; +} diff --git a/Marlin/fastio.h b/Marlin/fastio.h index 2d13962523..7fd42a6c8e 100644 --- a/Marlin/fastio.h +++ b/Marlin/fastio.h @@ -1,2559 +1,2559 @@ -/* - This code contibuted by Triffid_Hunter and modified by Kliment - why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html -*/ - -#ifndef _ARDUINO_H -#define _ARDUINO_H - -#include - -/* - utility functions -*/ - -#ifndef MASK -/// MASKING- returns \f$2^PIN\f$ - #define MASK(PIN) (1 << PIN) -#endif - -/* - magic I/O routines - - now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0); -*/ - -/// Read a pin -#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) -/// write to a pin -#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) -//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) -/// toggle a pin -#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) - -/// set pin as input -#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0) -/// set pin as output -#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0) - -/// check if pin is an input -#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0) -/// check if pin is an output -#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0) - -// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html - -/// Read a pin wrapper -#define READ(IO) _READ(IO) -/// Write to a pin wrapper -#define WRITE(IO, v) _WRITE(IO, v) -/// toggle a pin wrapper -#define TOGGLE(IO) _TOGGLE(IO) - -/// set pin as input wrapper -#define SET_INPUT(IO) _SET_INPUT(IO) -/// set pin as output wrapper -#define SET_OUTPUT(IO) _SET_OUTPUT(IO) - -/// check if pin is an input wrapper -#define GET_INPUT(IO) _GET_INPUT(IO) -/// check if pin is an output wrapper -#define GET_OUTPUT(IO) _GET_OUTPUT(IO) - -/* - ports and functions - - added as necessary or if I feel like it- not a comprehensive list! -*/ - -#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) -// UART -#define RXD DIO0 -#define TXD DIO1 - -// SPI -#define SCK DIO13 -#define MISO DIO12 -#define MOSI DIO11 -#define SS DIO10 - -// TWI (I2C) -#define SCL AIO5 -#define SDA AIO4 - -// timers and PWM -#define OC0A DIO6 -#define OC0B DIO5 -#define OC1A DIO9 -#define OC1B DIO10 -#define OC2A DIO11 -#define OC2B DIO3 - -#define DEBUG_LED AIO5 - -/* -pins -*/ - -#define DIO0_PIN PIND0 -#define DIO0_RPORT PIND -#define DIO0_WPORT PORTD -#define DIO0_DDR DDRD -#define DIO0_PWM NULL - -#define DIO1_PIN PIND1 -#define DIO1_RPORT PIND -#define DIO1_WPORT PORTD -#define DIO1_DDR DDRD -#define DIO1_PWM NULL - -#define DIO2_PIN PIND2 -#define DIO2_RPORT PIND -#define DIO2_WPORT PORTD -#define DIO2_DDR DDRD -#define DIO2_PWM NULL - -#define DIO3_PIN PIND3 -#define DIO3_RPORT PIND -#define DIO3_WPORT PORTD -#define DIO3_DDR DDRD -#define DIO3_PWM &OCR2B - -#define DIO4_PIN PIND4 -#define DIO4_RPORT PIND -#define DIO4_WPORT PORTD -#define DIO4_DDR DDRD -#define DIO4_PWM NULL - -#define DIO5_PIN PIND5 -#define DIO5_RPORT PIND -#define DIO5_WPORT PORTD -#define DIO5_DDR DDRD -#define DIO5_PWM &OCR0B - -#define DIO6_PIN PIND6 -#define DIO6_RPORT PIND -#define DIO6_WPORT PORTD -#define DIO6_DDR DDRD -#define DIO6_PWM &OCR0A - -#define DIO7_PIN PIND7 -#define DIO7_RPORT PIND -#define DIO7_WPORT PORTD -#define DIO7_DDR DDRD -#define DIO7_PWM NULL - -#define DIO8_PIN PINB0 -#define DIO8_RPORT PINB -#define DIO8_WPORT PORTB -#define DIO8_DDR DDRB -#define DIO8_PWM NULL - -#define DIO9_PIN PINB1 -#define DIO9_RPORT PINB -#define DIO9_WPORT PORTB -#define DIO9_DDR DDRB -#define DIO9_PWM NULL - -#define DIO10_PIN PINB2 -#define DIO10_RPORT PINB -#define DIO10_WPORT PORTB -#define DIO10_DDR DDRB -#define DIO10_PWM NULL - -#define DIO11_PIN PINB3 -#define DIO11_RPORT PINB -#define DIO11_WPORT PORTB -#define DIO11_DDR DDRB -#define DIO11_PWM &OCR2A - -#define DIO12_PIN PINB4 -#define DIO12_RPORT PINB -#define DIO12_WPORT PORTB -#define DIO12_DDR DDRB -#define DIO12_PWM NULL - -#define DIO13_PIN PINB5 -#define DIO13_RPORT PINB -#define DIO13_WPORT PORTB -#define DIO13_DDR DDRB -#define DIO13_PWM NULL - - -#define DIO14_PIN PINC0 -#define DIO14_RPORT PINC -#define DIO14_WPORT PORTC -#define DIO14_DDR DDRC -#define DIO14_PWM NULL - -#define DIO15_PIN PINC1 -#define DIO15_RPORT PINC -#define DIO15_WPORT PORTC -#define DIO15_DDR DDRC -#define DIO15_PWM NULL - -#define DIO16_PIN PINC2 -#define DIO16_RPORT PINC -#define DIO16_WPORT PORTC -#define DIO16_DDR DDRC -#define DIO16_PWM NULL - -#define DIO17_PIN PINC3 -#define DIO17_RPORT PINC -#define DIO17_WPORT PORTC -#define DIO17_DDR DDRC -#define DIO17_PWM NULL - -#define DIO18_PIN PINC4 -#define DIO18_RPORT PINC -#define DIO18_WPORT PORTC -#define DIO18_DDR DDRC -#define DIO18_PWM NULL - -#define DIO19_PIN PINC5 -#define DIO19_RPORT PINC -#define DIO19_WPORT PORTC -#define DIO19_DDR DDRC -#define DIO19_PWM NULL - -#define DIO20_PIN PINC6 -#define DIO20_RPORT PINC -#define DIO20_WPORT PORTC -#define DIO20_DDR DDRC -#define DIO20_PWM NULL - -#define DIO21_PIN PINC7 -#define DIO21_RPORT PINC -#define DIO21_WPORT PORTC -#define DIO21_DDR DDRC -#define DIO21_PWM NULL - - - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_DDR DDRB -#define PB0_PWM NULL - -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_DDR DDRB -#define PB1_PWM NULL - -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_DDR DDRB -#define PB2_PWM NULL - -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_DDR DDRB -#define PB3_PWM &OCR2A - -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_DDR DDRB -#define PB4_PWM NULL - -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_DDR DDRB -#define PB5_PWM NULL - -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_DDR DDRB -#define PB6_PWM NULL - -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_DDR DDRB -#define PB7_PWM NULL - - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_DDR DDRC -#define PC0_PWM NULL - -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_DDR DDRC -#define PC1_PWM NULL - -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_DDR DDRC -#define PC2_PWM NULL - -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_DDR DDRC -#define PC3_PWM NULL - -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_DDR DDRC -#define PC4_PWM NULL - -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_DDR DDRC -#define PC5_PWM NULL - -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_DDR DDRC -#define PC6_PWM NULL - -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_DDR DDRC -#define PC7_PWM NULL - - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_DDR DDRD -#define PD0_PWM NULL - -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_DDR DDRD -#define PD1_PWM NULL - -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_DDR DDRD -#define PD2_PWM NULL - -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_DDR DDRD -#define PD3_PWM &OCR2B - -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_DDR DDRD -#define PD4_PWM NULL - -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_DDR DDRD -#define PD5_PWM &OCR0B - -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_DDR DDRD -#define PD6_PWM &OCR0A - -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_DDR DDRD -#define PD7_PWM NULL -#endif /* _AVR_ATmega{168,328,328P}__ */ - -#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) -// UART -#define RXD DIO8 -#define TXD DIO9 -#define RXD0 DIO8 -#define TXD0 DIO9 - -#define RXD1 DIO10 -#define TXD1 DIO11 - -// SPI -#define SCK DIO7 -#define MISO DIO6 -#define MOSI DIO5 -#define SS DIO4 - -// TWI (I2C) -#define SCL DIO16 -#define SDA DIO17 - -// timers and PWM -#define OC0A DIO3 -#define OC0B DIO4 -#define OC1A DIO13 -#define OC1B DIO12 -#define OC2A DIO15 -#define OC2B DIO14 - -#define DEBUG_LED DIO0 -/* -pins -*/ - -#define DIO0_PIN PINB0 -#define DIO0_RPORT PINB -#define DIO0_WPORT PORTB -#define DIO0_DDR DDRB -#define DIO0_PWM NULL - -#define DIO1_PIN PINB1 -#define DIO1_RPORT PINB -#define DIO1_WPORT PORTB -#define DIO1_DDR DDRB -#define DIO1_PWM NULL - -#define DIO2_PIN PINB2 -#define DIO2_RPORT PINB -#define DIO2_WPORT PORTB -#define DIO2_DDR DDRB -#define DIO2_PWM NULL - -#define DIO3_PIN PINB3 -#define DIO3_RPORT PINB -#define DIO3_WPORT PORTB -#define DIO3_DDR DDRB -#define DIO3_PWM &OCR0A - -#define DIO4_PIN PINB4 -#define DIO4_RPORT PINB -#define DIO4_WPORT PORTB -#define DIO4_DDR DDRB -#define DIO4_PWM &OCR0B - -#define DIO5_PIN PINB5 -#define DIO5_RPORT PINB -#define DIO5_WPORT PORTB -#define DIO5_DDR DDRB -#define DIO5_PWM NULL - -#define DIO6_PIN PINB6 -#define DIO6_RPORT PINB -#define DIO6_WPORT PORTB -#define DIO6_DDR DDRB -#define DIO6_PWM NULL - -#define DIO7_PIN PINB7 -#define DIO7_RPORT PINB -#define DIO7_WPORT PORTB -#define DIO7_DDR DDRB -#define DIO7_PWM NULL - -#define DIO8_PIN PIND0 -#define DIO8_RPORT PIND -#define DIO8_WPORT PORTD -#define DIO8_DDR DDRD -#define DIO8_PWM NULL - -#define DIO9_PIN PIND1 -#define DIO9_RPORT PIND -#define DIO9_WPORT PORTD -#define DIO9_DDR DDRD -#define DIO9_PWM NULL - -#define DIO10_PIN PIND2 -#define DIO10_RPORT PIND -#define DIO10_WPORT PORTD -#define DIO10_DDR DDRD -#define DIO10_PWM NULL - -#define DIO11_PIN PIND3 -#define DIO11_RPORT PIND -#define DIO11_WPORT PORTD -#define DIO11_DDR DDRD -#define DIO11_PWM NULL - -#define DIO12_PIN PIND4 -#define DIO12_RPORT PIND -#define DIO12_WPORT PORTD -#define DIO12_DDR DDRD -#define DIO12_PWM NULL - -#define DIO13_PIN PIND5 -#define DIO13_RPORT PIND -#define DIO13_WPORT PORTD -#define DIO13_DDR DDRD -#define DIO13_PWM NULL - -#define DIO14_PIN PIND6 -#define DIO14_RPORT PIND -#define DIO14_WPORT PORTD -#define DIO14_DDR DDRD -#define DIO14_PWM &OCR2B - -#define DIO15_PIN PIND7 -#define DIO15_RPORT PIND -#define DIO15_WPORT PORTD -#define DIO15_DDR DDRD -#define DIO15_PWM &OCR2A - -#define DIO16_PIN PINC0 -#define DIO16_RPORT PINC -#define DIO16_WPORT PORTC -#define DIO16_DDR DDRC -#define DIO16_PWM NULL - -#define DIO17_PIN PINC1 -#define DIO17_RPORT PINC -#define DIO17_WPORT PORTC -#define DIO17_DDR DDRC -#define DIO17_PWM NULL - -#define DIO18_PIN PINC2 -#define DIO18_RPORT PINC -#define DIO18_WPORT PORTC -#define DIO18_DDR DDRC -#define DIO18_PWM NULL - -#define DIO19_PIN PINC3 -#define DIO19_RPORT PINC -#define DIO19_WPORT PORTC -#define DIO19_DDR DDRC -#define DIO19_PWM NULL - -#define DIO20_PIN PINC4 -#define DIO20_RPORT PINC -#define DIO20_WPORT PORTC -#define DIO20_DDR DDRC -#define DIO20_PWM NULL - -#define DIO21_PIN PINC5 -#define DIO21_RPORT PINC -#define DIO21_WPORT PORTC -#define DIO21_DDR DDRC -#define DIO21_PWM NULL - -#define DIO22_PIN PINC6 -#define DIO22_RPORT PINC -#define DIO22_WPORT PORTC -#define DIO22_DDR DDRC -#define DIO22_PWM NULL - -#define DIO23_PIN PINC7 -#define DIO23_RPORT PINC -#define DIO23_WPORT PORTC -#define DIO23_DDR DDRC -#define DIO23_PWM NULL - -#define DIO24_PIN PINA7 -#define DIO24_RPORT PINA -#define DIO24_WPORT PORTA -#define DIO24_DDR DDRA -#define DIO24_PWM NULL - -#define DIO25_PIN PINA6 -#define DIO25_RPORT PINA -#define DIO25_WPORT PORTA -#define DIO25_DDR DDRA -#define DIO25_PWM NULL - -#define DIO26_PIN PINA5 -#define DIO26_RPORT PINA -#define DIO26_WPORT PORTA -#define DIO26_DDR DDRA -#define DIO26_PWM NULL - -#define DIO27_PIN PINA4 -#define DIO27_RPORT PINA -#define DIO27_WPORT PORTA -#define DIO27_DDR DDRA -#define DIO27_PWM NULL - -#define DIO28_PIN PINA3 -#define DIO28_RPORT PINA -#define DIO28_WPORT PORTA -#define DIO28_DDR DDRA -#define DIO28_PWM NULL - -#define DIO29_PIN PINA2 -#define DIO29_RPORT PINA -#define DIO29_WPORT PORTA -#define DIO29_DDR DDRA -#define DIO29_PWM NULL - -#define DIO30_PIN PINA1 -#define DIO30_RPORT PINA -#define DIO30_WPORT PORTA -#define DIO30_DDR DDRA -#define DIO30_PWM NULL - -#define DIO31_PIN PINA0 -#define DIO31_RPORT PINA -#define DIO31_WPORT PORTA -#define DIO31_DDR DDRA -#define DIO31_PWM NULL - -#define AIO0_PIN PINA0 -#define AIO0_RPORT PINA -#define AIO0_WPORT PORTA -#define AIO0_DDR DDRA -#define AIO0_PWM NULL - -#define AIO1_PIN PINA1 -#define AIO1_RPORT PINA -#define AIO1_WPORT PORTA -#define AIO1_DDR DDRA -#define AIO1_PWM NULL - -#define AIO2_PIN PINA2 -#define AIO2_RPORT PINA -#define AIO2_WPORT PORTA -#define AIO2_DDR DDRA -#define AIO2_PWM NULL - -#define AIO3_PIN PINA3 -#define AIO3_RPORT PINA -#define AIO3_WPORT PORTA -#define AIO3_DDR DDRA -#define AIO3_PWM NULL - -#define AIO4_PIN PINA4 -#define AIO4_RPORT PINA -#define AIO4_WPORT PORTA -#define AIO4_DDR DDRA -#define AIO4_PWM NULL - -#define AIO5_PIN PINA5 -#define AIO5_RPORT PINA -#define AIO5_WPORT PORTA -#define AIO5_DDR DDRA -#define AIO5_PWM NULL - -#define AIO6_PIN PINA6 -#define AIO6_RPORT PINA -#define AIO6_WPORT PORTA -#define AIO6_DDR DDRA -#define AIO6_PWM NULL - -#define AIO7_PIN PINA7 -#define AIO7_RPORT PINA -#define AIO7_WPORT PORTA -#define AIO7_DDR DDRA -#define AIO7_PWM NULL - - - -#undef PA0 -#define PA0_PIN PINA0 -#define PA0_RPORT PINA -#define PA0_WPORT PORTA -#define PA0_DDR DDRA -#define PA0_PWM NULL - -#undef PA1 -#define PA1_PIN PINA1 -#define PA1_RPORT PINA -#define PA1_WPORT PORTA -#define PA1_DDR DDRA -#define PA1_PWM NULL - -#undef PA2 -#define PA2_PIN PINA2 -#define PA2_RPORT PINA -#define PA2_WPORT PORTA -#define PA2_DDR DDRA -#define PA2_PWM NULL - -#undef PA3 -#define PA3_PIN PINA3 -#define PA3_RPORT PINA -#define PA3_WPORT PORTA -#define PA3_DDR DDRA -#define PA3_PWM NULL - -#undef PA4 -#define PA4_PIN PINA4 -#define PA4_RPORT PINA -#define PA4_WPORT PORTA -#define PA4_DDR DDRA -#define PA4_PWM NULL - -#undef PA5 -#define PA5_PIN PINA5 -#define PA5_RPORT PINA -#define PA5_WPORT PORTA -#define PA5_DDR DDRA -#define PA5_PWM NULL - -#undef PA6 -#define PA6_PIN PINA6 -#define PA6_RPORT PINA -#define PA6_WPORT PORTA -#define PA6_DDR DDRA -#define PA6_PWM NULL - -#undef PA7 -#define PA7_PIN PINA7 -#define PA7_RPORT PINA -#define PA7_WPORT PORTA -#define PA7_DDR DDRA -#define PA7_PWM NULL - - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_DDR DDRB -#define PB0_PWM NULL - -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_DDR DDRB -#define PB1_PWM NULL - -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_DDR DDRB -#define PB2_PWM NULL - -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_DDR DDRB -#define PB3_PWM &OCR0A - -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_DDR DDRB -#define PB4_PWM &OCR0B - -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_DDR DDRB -#define PB5_PWM NULL - -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_DDR DDRB -#define PB6_PWM NULL - -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_DDR DDRB -#define PB7_PWM NULL - - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_DDR DDRC -#define PC0_PWM NULL - -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_DDR DDRC -#define PC1_PWM NULL - -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_DDR DDRC -#define PC2_PWM NULL - -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_DDR DDRC -#define PC3_PWM NULL - -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_DDR DDRC -#define PC4_PWM NULL - -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_DDR DDRC -#define PC5_PWM NULL - -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_DDR DDRC -#define PC6_PWM NULL - -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_DDR DDRC -#define PC7_PWM NULL - - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_DDR DDRD -#define PD0_PWM NULL - -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_DDR DDRD -#define PD1_PWM NULL - -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_DDR DDRD -#define PD2_PWM NULL - -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_DDR DDRD -#define PD3_PWM NULL - -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_DDR DDRD -#define PD4_PWM NULL - -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_DDR DDRD -#define PD5_PWM NULL - -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_DDR DDRD -#define PD6_PWM &OCR2B - -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_DDR DDRD -#define PD7_PWM &OCR2A -#endif /* _AVR_ATmega{644,644P,644PA}__ */ - -#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) -// UART -#define RXD DIO0 -#define TXD DIO1 - -// SPI -#define SCK DIO52 -#define MISO DIO50 -#define MOSI DIO51 -#define SS DIO53 - -// TWI (I2C) -#define SCL DIO21 -#define SDA DIO20 - -// timers and PWM -#define OC0A DIO13 -#define OC0B DIO4 -#define OC1A DIO11 -#define OC1B DIO12 -#define OC2A DIO10 -#define OC2B DIO9 -#define OC3A DIO5 -#define OC3B DIO2 -#define OC3C DIO3 -#define OC4A DIO6 -#define OC4B DIO7 -#define OC4C DIO8 -#define OC5A DIO46 -#define OC5B DIO45 -#define OC5C DIO44 - -// change for your board -#define DEBUG_LED DIO21 - -/* -pins -*/ -#define DIO0_PIN PINE0 -#define DIO0_RPORT PINE -#define DIO0_WPORT PORTE -#define DIO0_DDR DDRE -#define DIO0_PWM NULL - -#define DIO1_PIN PINE1 -#define DIO1_RPORT PINE -#define DIO1_WPORT PORTE -#define DIO1_DDR DDRE -#define DIO1_PWM NULL - -#define DIO2_PIN PINE4 -#define DIO2_RPORT PINE -#define DIO2_WPORT PORTE -#define DIO2_DDR DDRE -#define DIO2_PWM &OCR3BL - -#define DIO3_PIN PINE5 -#define DIO3_RPORT PINE -#define DIO3_WPORT PORTE -#define DIO3_DDR DDRE -#define DIO3_PWM &OCR3CL - -#define DIO4_PIN PING5 -#define DIO4_RPORT PING -#define DIO4_WPORT PORTG -#define DIO4_DDR DDRG -#define DIO4_PWM &OCR0B - -#define DIO5_PIN PINE3 -#define DIO5_RPORT PINE -#define DIO5_WPORT PORTE -#define DIO5_DDR DDRE -#define DIO5_PWM &OCR3AL - -#define DIO6_PIN PINH3 -#define DIO6_RPORT PINH -#define DIO6_WPORT PORTH -#define DIO6_DDR DDRH -#define DIO6_PWM &OCR4AL - -#define DIO7_PIN PINH4 -#define DIO7_RPORT PINH -#define DIO7_WPORT PORTH -#define DIO7_DDR DDRH -#define DIO7_PWM &OCR4BL - -#define DIO8_PIN PINH5 -#define DIO8_RPORT PINH -#define DIO8_WPORT PORTH -#define DIO8_DDR DDRH -#define DIO8_PWM &OCR4CL - -#define DIO9_PIN PINH6 -#define DIO9_RPORT PINH -#define DIO9_WPORT PORTH -#define DIO9_DDR DDRH -#define DIO9_PWM &OCR2B - -#define DIO10_PIN PINB4 -#define DIO10_RPORT PINB -#define DIO10_WPORT PORTB -#define DIO10_DDR DDRB -#define DIO10_PWM &OCR2A - -#define DIO11_PIN PINB5 -#define DIO11_RPORT PINB -#define DIO11_WPORT PORTB -#define DIO11_DDR DDRB -#define DIO11_PWM NULL - -#define DIO12_PIN PINB6 -#define DIO12_RPORT PINB -#define DIO12_WPORT PORTB -#define DIO12_DDR DDRB -#define DIO12_PWM NULL - -#define DIO13_PIN PINB7 -#define DIO13_RPORT PINB -#define DIO13_WPORT PORTB -#define DIO13_DDR DDRB -#define DIO13_PWM &OCR0A - -#define DIO14_PIN PINJ1 -#define DIO14_RPORT PINJ -#define DIO14_WPORT PORTJ -#define DIO14_DDR DDRJ -#define DIO14_PWM NULL - -#define DIO15_PIN PINJ0 -#define DIO15_RPORT PINJ -#define DIO15_WPORT PORTJ -#define DIO15_DDR DDRJ -#define DIO15_PWM NULL - -#define DIO16_PIN PINH1 -#define DIO16_RPORT PINH -#define DIO16_WPORT PORTH -#define DIO16_DDR DDRH -#define DIO16_PWM NULL - -#define DIO17_PIN PINH0 -#define DIO17_RPORT PINH -#define DIO17_WPORT PORTH -#define DIO17_DDR DDRH -#define DIO17_PWM NULL - -#define DIO18_PIN PIND3 -#define DIO18_RPORT PIND -#define DIO18_WPORT PORTD -#define DIO18_DDR DDRD -#define DIO18_PWM NULL - -#define DIO19_PIN PIND2 -#define DIO19_RPORT PIND -#define DIO19_WPORT PORTD -#define DIO19_DDR DDRD -#define DIO19_PWM NULL - -#define DIO20_PIN PIND1 -#define DIO20_RPORT PIND -#define DIO20_WPORT PORTD -#define DIO20_DDR DDRD -#define DIO20_PWM NULL - -#define DIO21_PIN PIND0 -#define DIO21_RPORT PIND -#define DIO21_WPORT PORTD -#define DIO21_DDR DDRD -#define DIO21_PWM NULL - -#define DIO22_PIN PINA0 -#define DIO22_RPORT PINA -#define DIO22_WPORT PORTA -#define DIO22_DDR DDRA -#define DIO22_PWM NULL - -#define DIO23_PIN PINA1 -#define DIO23_RPORT PINA -#define DIO23_WPORT PORTA -#define DIO23_DDR DDRA -#define DIO23_PWM NULL - -#define DIO24_PIN PINA2 -#define DIO24_RPORT PINA -#define DIO24_WPORT PORTA -#define DIO24_DDR DDRA -#define DIO24_PWM NULL - -#define DIO25_PIN PINA3 -#define DIO25_RPORT PINA -#define DIO25_WPORT PORTA -#define DIO25_DDR DDRA -#define DIO25_PWM NULL - -#define DIO26_PIN PINA4 -#define DIO26_RPORT PINA -#define DIO26_WPORT PORTA -#define DIO26_DDR DDRA -#define DIO26_PWM NULL - -#define DIO27_PIN PINA5 -#define DIO27_RPORT PINA -#define DIO27_WPORT PORTA -#define DIO27_DDR DDRA -#define DIO27_PWM NULL - -#define DIO28_PIN PINA6 -#define DIO28_RPORT PINA -#define DIO28_WPORT PORTA -#define DIO28_DDR DDRA -#define DIO28_PWM NULL - -#define DIO29_PIN PINA7 -#define DIO29_RPORT PINA -#define DIO29_WPORT PORTA -#define DIO29_DDR DDRA -#define DIO29_PWM NULL - -#define DIO30_PIN PINC7 -#define DIO30_RPORT PINC -#define DIO30_WPORT PORTC -#define DIO30_DDR DDRC -#define DIO30_PWM NULL - -#define DIO31_PIN PINC6 -#define DIO31_RPORT PINC -#define DIO31_WPORT PORTC -#define DIO31_DDR DDRC -#define DIO31_PWM NULL - -#define DIO32_PIN PINC5 -#define DIO32_RPORT PINC -#define DIO32_WPORT PORTC -#define DIO32_DDR DDRC -#define DIO32_PWM NULL - -#define DIO33_PIN PINC4 -#define DIO33_RPORT PINC -#define DIO33_WPORT PORTC -#define DIO33_DDR DDRC -#define DIO33_PWM NULL - -#define DIO34_PIN PINC3 -#define DIO34_RPORT PINC -#define DIO34_WPORT PORTC -#define DIO34_DDR DDRC -#define DIO34_PWM NULL - -#define DIO35_PIN PINC2 -#define DIO35_RPORT PINC -#define DIO35_WPORT PORTC -#define DIO35_DDR DDRC -#define DIO35_PWM NULL - -#define DIO36_PIN PINC1 -#define DIO36_RPORT PINC -#define DIO36_WPORT PORTC -#define DIO36_DDR DDRC -#define DIO36_PWM NULL - -#define DIO37_PIN PINC0 -#define DIO37_RPORT PINC -#define DIO37_WPORT PORTC -#define DIO37_DDR DDRC -#define DIO37_PWM NULL - -#define DIO38_PIN PIND7 -#define DIO38_RPORT PIND -#define DIO38_WPORT PORTD -#define DIO38_DDR DDRD -#define DIO38_PWM NULL - -#define DIO39_PIN PING2 -#define DIO39_RPORT PING -#define DIO39_WPORT PORTG -#define DIO39_DDR DDRG -#define DIO39_PWM NULL - -#define DIO40_PIN PING1 -#define DIO40_RPORT PING -#define DIO40_WPORT PORTG -#define DIO40_DDR DDRG -#define DIO40_PWM NULL - -#define DIO41_PIN PING0 -#define DIO41_RPORT PING -#define DIO41_WPORT PORTG -#define DIO41_DDR DDRG -#define DIO41_PWM NULL - -#define DIO42_PIN PINL7 -#define DIO42_RPORT PINL -#define DIO42_WPORT PORTL -#define DIO42_DDR DDRL -#define DIO42_PWM NULL - -#define DIO43_PIN PINL6 -#define DIO43_RPORT PINL -#define DIO43_WPORT PORTL -#define DIO43_DDR DDRL -#define DIO43_PWM NULL - -#define DIO44_PIN PINL5 -#define DIO44_RPORT PINL -#define DIO44_WPORT PORTL -#define DIO44_DDR DDRL -#define DIO44_PWM &OCR5CL - -#define DIO45_PIN PINL4 -#define DIO45_RPORT PINL -#define DIO45_WPORT PORTL -#define DIO45_DDR DDRL -#define DIO45_PWM &OCR5BL - -#define DIO46_PIN PINL3 -#define DIO46_RPORT PINL -#define DIO46_WPORT PORTL -#define DIO46_DDR DDRL -#define DIO46_PWM &OCR5AL - -#define DIO47_PIN PINL2 -#define DIO47_RPORT PINL -#define DIO47_WPORT PORTL -#define DIO47_DDR DDRL -#define DIO47_PWM NULL - -#define DIO48_PIN PINL1 -#define DIO48_RPORT PINL -#define DIO48_WPORT PORTL -#define DIO48_DDR DDRL -#define DIO48_PWM NULL - -#define DIO49_PIN PINL0 -#define DIO49_RPORT PINL -#define DIO49_WPORT PORTL -#define DIO49_DDR DDRL -#define DIO49_PWM NULL - -#define DIO50_PIN PINB3 -#define DIO50_RPORT PINB -#define DIO50_WPORT PORTB -#define DIO50_DDR DDRB -#define DIO50_PWM NULL - -#define DIO51_PIN PINB2 -#define DIO51_RPORT PINB -#define DIO51_WPORT PORTB -#define DIO51_DDR DDRB -#define DIO51_PWM NULL - -#define DIO52_PIN PINB1 -#define DIO52_RPORT PINB -#define DIO52_WPORT PORTB -#define DIO52_DDR DDRB -#define DIO52_PWM NULL - -#define DIO53_PIN PINB0 -#define DIO53_RPORT PINB -#define DIO53_WPORT PORTB -#define DIO53_DDR DDRB -#define DIO53_PWM NULL - -#define DIO54_PIN PINF0 -#define DIO54_RPORT PINF -#define DIO54_WPORT PORTF -#define DIO54_DDR DDRF -#define DIO54_PWM NULL - -#define DIO55_PIN PINF1 -#define DIO55_RPORT PINF -#define DIO55_WPORT PORTF -#define DIO55_DDR DDRF -#define DIO55_PWM NULL - -#define DIO56_PIN PINF2 -#define DIO56_RPORT PINF -#define DIO56_WPORT PORTF -#define DIO56_DDR DDRF -#define DIO56_PWM NULL - -#define DIO57_PIN PINF3 -#define DIO57_RPORT PINF -#define DIO57_WPORT PORTF -#define DIO57_DDR DDRF -#define DIO57_PWM NULL - -#define DIO58_PIN PINF4 -#define DIO58_RPORT PINF -#define DIO58_WPORT PORTF -#define DIO58_DDR DDRF -#define DIO58_PWM NULL - -#define DIO59_PIN PINF5 -#define DIO59_RPORT PINF -#define DIO59_WPORT PORTF -#define DIO59_DDR DDRF -#define DIO59_PWM NULL - -#define DIO60_PIN PINF6 -#define DIO60_RPORT PINF -#define DIO60_WPORT PORTF -#define DIO60_DDR DDRF -#define DIO60_PWM NULL - -#define DIO61_PIN PINF7 -#define DIO61_RPORT PINF -#define DIO61_WPORT PORTF -#define DIO61_DDR DDRF -#define DIO61_PWM NULL - -#define DIO62_PIN PINK0 -#define DIO62_RPORT PINK -#define DIO62_WPORT PORTK -#define DIO62_DDR DDRK -#define DIO62_PWM NULL - -#define DIO63_PIN PINK1 -#define DIO63_RPORT PINK -#define DIO63_WPORT PORTK -#define DIO63_DDR DDRK -#define DIO63_PWM NULL - -#define DIO64_PIN PINK2 -#define DIO64_RPORT PINK -#define DIO64_WPORT PORTK -#define DIO64_DDR DDRK -#define DIO64_PWM NULL - -#define DIO65_PIN PINK3 -#define DIO65_RPORT PINK -#define DIO65_WPORT PORTK -#define DIO65_DDR DDRK -#define DIO65_PWM NULL - -#define DIO66_PIN PINK4 -#define DIO66_RPORT PINK -#define DIO66_WPORT PORTK -#define DIO66_DDR DDRK -#define DIO66_PWM NULL - -#define DIO67_PIN PINK5 -#define DIO67_RPORT PINK -#define DIO67_WPORT PORTK -#define DIO67_DDR DDRK -#define DIO67_PWM NULL - -#define DIO68_PIN PINK6 -#define DIO68_RPORT PINK -#define DIO68_WPORT PORTK -#define DIO68_DDR DDRK -#define DIO68_PWM NULL - -#define DIO69_PIN PINK7 -#define DIO69_RPORT PINK -#define DIO69_WPORT PORTK -#define DIO69_DDR DDRK -#define DIO69_PWM NULL - - - -#undef PA0 -#define PA0_PIN PINA0 -#define PA0_RPORT PINA -#define PA0_WPORT PORTA -#define PA0_DDR DDRA -#define PA0_PWM NULL -#undef PA1 -#define PA1_PIN PINA1 -#define PA1_RPORT PINA -#define PA1_WPORT PORTA -#define PA1_DDR DDRA -#define PA1_PWM NULL -#undef PA2 -#define PA2_PIN PINA2 -#define PA2_RPORT PINA -#define PA2_WPORT PORTA -#define PA2_DDR DDRA -#define PA2_PWM NULL -#undef PA3 -#define PA3_PIN PINA3 -#define PA3_RPORT PINA -#define PA3_WPORT PORTA -#define PA3_DDR DDRA -#define PA3_PWM NULL -#undef PA4 -#define PA4_PIN PINA4 -#define PA4_RPORT PINA -#define PA4_WPORT PORTA -#define PA4_DDR DDRA -#define PA4_PWM NULL -#undef PA5 -#define PA5_PIN PINA5 -#define PA5_RPORT PINA -#define PA5_WPORT PORTA -#define PA5_DDR DDRA -#define PA5_PWM NULL -#undef PA6 -#define PA6_PIN PINA6 -#define PA6_RPORT PINA -#define PA6_WPORT PORTA -#define PA6_DDR DDRA -#define PA6_PWM NULL -#undef PA7 -#define PA7_PIN PINA7 -#define PA7_RPORT PINA -#define PA7_WPORT PORTA -#define PA7_DDR DDRA -#define PA7_PWM NULL - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_DDR DDRB -#define PB0_PWM NULL -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_DDR DDRB -#define PB1_PWM NULL -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_DDR DDRB -#define PB2_PWM NULL -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_DDR DDRB -#define PB3_PWM NULL -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_DDR DDRB -#define PB4_PWM &OCR2A -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_DDR DDRB -#define PB5_PWM NULL -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_DDR DDRB -#define PB6_PWM NULL -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_DDR DDRB -#define PB7_PWM &OCR0A - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_DDR DDRC -#define PC0_PWM NULL -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_DDR DDRC -#define PC1_PWM NULL -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_DDR DDRC -#define PC2_PWM NULL -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_DDR DDRC -#define PC3_PWM NULL -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_DDR DDRC -#define PC4_PWM NULL -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_DDR DDRC -#define PC5_PWM NULL -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_DDR DDRC -#define PC6_PWM NULL -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_DDR DDRC -#define PC7_PWM NULL - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_DDR DDRD -#define PD0_PWM NULL -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_DDR DDRD -#define PD1_PWM NULL -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_DDR DDRD -#define PD2_PWM NULL -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_DDR DDRD -#define PD3_PWM NULL -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_DDR DDRD -#define PD4_PWM NULL -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_DDR DDRD -#define PD5_PWM NULL -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_DDR DDRD -#define PD6_PWM NULL -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_DDR DDRD -#define PD7_PWM NULL - -#undef PE0 -#define PE0_PIN PINE0 -#define PE0_RPORT PINE -#define PE0_WPORT PORTE -#define PE0_DDR DDRE -#define PE0_PWM NULL -#undef PE1 -#define PE1_PIN PINE1 -#define PE1_RPORT PINE -#define PE1_WPORT PORTE -#define PE1_DDR DDRE -#define PE1_PWM NULL -#undef PE2 -#define PE2_PIN PINE2 -#define PE2_RPORT PINE -#define PE2_WPORT PORTE -#define PE2_DDR DDRE -#define PE2_PWM NULL -#undef PE3 -#define PE3_PIN PINE3 -#define PE3_RPORT PINE -#define PE3_WPORT PORTE -#define PE3_DDR DDRE -#define PE3_PWM &OCR3AL -#undef PE4 -#define PE4_PIN PINE4 -#define PE4_RPORT PINE -#define PE4_WPORT PORTE -#define PE4_DDR DDRE -#define PE4_PWM &OCR3BL -#undef PE5 -#define PE5_PIN PINE5 -#define PE5_RPORT PINE -#define PE5_WPORT PORTE -#define PE5_DDR DDRE -#define PE5_PWM &OCR3CL -#undef PE6 -#define PE6_PIN PINE6 -#define PE6_RPORT PINE -#define PE6_WPORT PORTE -#define PE6_DDR DDRE -#define PE6_PWM NULL -#undef PE7 -#define PE7_PIN PINE7 -#define PE7_RPORT PINE -#define PE7_WPORT PORTE -#define PE7_DDR DDRE -#define PE7_PWM NULL - -#undef PF0 -#define PF0_PIN PINF0 -#define PF0_RPORT PINF -#define PF0_WPORT PORTF -#define PF0_DDR DDRF -#define PF0_PWM NULL -#undef PF1 -#define PF1_PIN PINF1 -#define PF1_RPORT PINF -#define PF1_WPORT PORTF -#define PF1_DDR DDRF -#define PF1_PWM NULL -#undef PF2 -#define PF2_PIN PINF2 -#define PF2_RPORT PINF -#define PF2_WPORT PORTF -#define PF2_DDR DDRF -#define PF2_PWM NULL -#undef PF3 -#define PF3_PIN PINF3 -#define PF3_RPORT PINF -#define PF3_WPORT PORTF -#define PF3_DDR DDRF -#define PF3_PWM NULL -#undef PF4 -#define PF4_PIN PINF4 -#define PF4_RPORT PINF -#define PF4_WPORT PORTF -#define PF4_DDR DDRF -#define PF4_PWM NULL -#undef PF5 -#define PF5_PIN PINF5 -#define PF5_RPORT PINF -#define PF5_WPORT PORTF -#define PF5_DDR DDRF -#define PF5_PWM NULL -#undef PF6 -#define PF6_PIN PINF6 -#define PF6_RPORT PINF -#define PF6_WPORT PORTF -#define PF6_DDR DDRF -#define PF6_PWM NULL -#undef PF7 -#define PF7_PIN PINF7 -#define PF7_RPORT PINF -#define PF7_WPORT PORTF -#define PF7_DDR DDRF -#define PF7_PWM NULL - -#undef PG0 -#define PG0_PIN PING0 -#define PG0_RPORT PING -#define PG0_WPORT PORTG -#define PG0_DDR DDRG -#define PG0_PWM NULL -#undef PG1 -#define PG1_PIN PING1 -#define PG1_RPORT PING -#define PG1_WPORT PORTG -#define PG1_DDR DDRG -#define PG1_PWM NULL -#undef PG2 -#define PG2_PIN PING2 -#define PG2_RPORT PING -#define PG2_WPORT PORTG -#define PG2_DDR DDRG -#define PG2_PWM NULL -#undef PG3 -#define PG3_PIN PING3 -#define PG3_RPORT PING -#define PG3_WPORT PORTG -#define PG3_DDR DDRG -#define PG3_PWM NULL -#undef PG4 -#define PG4_PIN PING4 -#define PG4_RPORT PING -#define PG4_WPORT PORTG -#define PG4_DDR DDRG -#define PG4_PWM NULL -#undef PG5 -#define PG5_PIN PING5 -#define PG5_RPORT PING -#define PG5_WPORT PORTG -#define PG5_DDR DDRG -#define PG5_PWM &OCR0B -#undef PG6 -#define PG6_PIN PING6 -#define PG6_RPORT PING -#define PG6_WPORT PORTG -#define PG6_DDR DDRG -#define PG6_PWM NULL -#undef PG7 -#define PG7_PIN PING7 -#define PG7_RPORT PING -#define PG7_WPORT PORTG -#define PG7_DDR DDRG -#define PG7_PWM NULL - -#undef PH0 -#define PH0_PIN PINH0 -#define PH0_RPORT PINH -#define PH0_WPORT PORTH -#define PH0_DDR DDRH -#define PH0_PWM NULL -#undef PH1 -#define PH1_PIN PINH1 -#define PH1_RPORT PINH -#define PH1_WPORT PORTH -#define PH1_DDR DDRH -#define PH1_PWM NULL -#undef PH2 -#define PH2_PIN PINH2 -#define PH2_RPORT PINH -#define PH2_WPORT PORTH -#define PH2_DDR DDRH -#define PH2_PWM NULL -#undef PH3 -#define PH3_PIN PINH3 -#define PH3_RPORT PINH -#define PH3_WPORT PORTH -#define PH3_DDR DDRH -#define PH3_PWM &OCR4AL -#undef PH4 -#define PH4_PIN PINH4 -#define PH4_RPORT PINH -#define PH4_WPORT PORTH -#define PH4_DDR DDRH -#define PH4_PWM &OCR4BL -#undef PH5 -#define PH5_PIN PINH5 -#define PH5_RPORT PINH -#define PH5_WPORT PORTH -#define PH5_DDR DDRH -#define PH5_PWM &OCR4CL -#undef PH6 -#define PH6_PIN PINH6 -#define PH6_RPORT PINH -#define PH6_WPORT PORTH -#define PH6_DDR DDRH -#define PH6_PWM &OCR2B -#undef PH7 -#define PH7_PIN PINH7 -#define PH7_RPORT PINH -#define PH7_WPORT PORTH -#define PH7_DDR DDRH -#define PH7_PWM NULL - -#undef PJ0 -#define PJ0_PIN PINJ0 -#define PJ0_RPORT PINJ -#define PJ0_WPORT PORTJ -#define PJ0_DDR DDRJ -#define PJ0_PWM NULL -#undef PJ1 -#define PJ1_PIN PINJ1 -#define PJ1_RPORT PINJ -#define PJ1_WPORT PORTJ -#define PJ1_DDR DDRJ -#define PJ1_PWM NULL -#undef PJ2 -#define PJ2_PIN PINJ2 -#define PJ2_RPORT PINJ -#define PJ2_WPORT PORTJ -#define PJ2_DDR DDRJ -#define PJ2_PWM NULL -#undef PJ3 -#define PJ3_PIN PINJ3 -#define PJ3_RPORT PINJ -#define PJ3_WPORT PORTJ -#define PJ3_DDR DDRJ -#define PJ3_PWM NULL -#undef PJ4 -#define PJ4_PIN PINJ4 -#define PJ4_RPORT PINJ -#define PJ4_WPORT PORTJ -#define PJ4_DDR DDRJ -#define PJ4_PWM NULL -#undef PJ5 -#define PJ5_PIN PINJ5 -#define PJ5_RPORT PINJ -#define PJ5_WPORT PORTJ -#define PJ5_DDR DDRJ -#define PJ5_PWM NULL -#undef PJ6 -#define PJ6_PIN PINJ6 -#define PJ6_RPORT PINJ -#define PJ6_WPORT PORTJ -#define PJ6_DDR DDRJ -#define PJ6_PWM NULL -#undef PJ7 -#define PJ7_PIN PINJ7 -#define PJ7_RPORT PINJ -#define PJ7_WPORT PORTJ -#define PJ7_DDR DDRJ -#define PJ7_PWM NULL - -#undef PK0 -#define PK0_PIN PINK0 -#define PK0_RPORT PINK -#define PK0_WPORT PORTK -#define PK0_DDR DDRK -#define PK0_PWM NULL -#undef PK1 -#define PK1_PIN PINK1 -#define PK1_RPORT PINK -#define PK1_WPORT PORTK -#define PK1_DDR DDRK -#define PK1_PWM NULL -#undef PK2 -#define PK2_PIN PINK2 -#define PK2_RPORT PINK -#define PK2_WPORT PORTK -#define PK2_DDR DDRK -#define PK2_PWM NULL -#undef PK3 -#define PK3_PIN PINK3 -#define PK3_RPORT PINK -#define PK3_WPORT PORTK -#define PK3_DDR DDRK -#define PK3_PWM NULL -#undef PK4 -#define PK4_PIN PINK4 -#define PK4_RPORT PINK -#define PK4_WPORT PORTK -#define PK4_DDR DDRK -#define PK4_PWM NULL -#undef PK5 -#define PK5_PIN PINK5 -#define PK5_RPORT PINK -#define PK5_WPORT PORTK -#define PK5_DDR DDRK -#define PK5_PWM NULL -#undef PK6 -#define PK6_PIN PINK6 -#define PK6_RPORT PINK -#define PK6_WPORT PORTK -#define PK6_DDR DDRK -#define PK6_PWM NULL -#undef PK7 -#define PK7_PIN PINK7 -#define PK7_RPORT PINK -#define PK7_WPORT PORTK -#define PK7_DDR DDRK -#define PK7_PWM NULL - -#undef PL0 -#define PL0_PIN PINL0 -#define PL0_RPORT PINL -#define PL0_WPORT PORTL -#define PL0_DDR DDRL -#define PL0_PWM NULL -#undef PL1 -#define PL1_PIN PINL1 -#define PL1_RPORT PINL -#define PL1_WPORT PORTL -#define PL1_DDR DDRL -#define PL1_PWM NULL -#undef PL2 -#define PL2_PIN PINL2 -#define PL2_RPORT PINL -#define PL2_WPORT PORTL -#define PL2_DDR DDRL -#define PL2_PWM NULL -#undef PL3 -#define PL3_PIN PINL3 -#define PL3_RPORT PINL -#define PL3_WPORT PORTL -#define PL3_DDR DDRL -#define PL3_PWM &OCR5AL -#undef PL4 -#define PL4_PIN PINL4 -#define PL4_RPORT PINL -#define PL4_WPORT PORTL -#define PL4_DDR DDRL -#define PL4_PWM &OCR5BL -#undef PL5 -#define PL5_PIN PINL5 -#define PL5_RPORT PINL -#define PL5_WPORT PORTL -#define PL5_DDR DDRL -#define PL5_PWM &OCR5CL -#undef PL6 -#define PL6_PIN PINL6 -#define PL6_RPORT PINL -#define PL6_WPORT PORTL -#define PL6_DDR DDRL -#define PL6_PWM NULL -#undef PL7 -#define PL7_PIN PINL7 -#define PL7_RPORT PINL -#define PL7_WPORT PORTL -#define PL7_DDR DDRL -#define PL7_PWM NULL - -#endif - -#if defined (__AVR_AT90USB1287__) -// SPI -#define SCK DIO9 -#define MISO DIO11 -#define MOSI DIO10 -#define SS DIO8 - -// change for your board -#define DEBUG_LED DIO31 /* led D5 red */ - -/* -pins -*/ -#define DIO0_PIN PINA0 -#define DIO0_RPORT PINA -#define DIO0_WPORT PORTA -#define DIO0_PWM NULL -#define DIO0_DDR DDRA - -#define DIO1_PIN PINA1 -#define DIO1_RPORT PINA -#define DIO1_WPORT PORTA -#define DIO1_PWM NULL -#define DIO1_DDR DDRA - -#define DIO2_PIN PINA2 -#define DIO2_RPORT PINA -#define DIO2_WPORT PORTA -#define DIO2_PWM NULL -#define DIO2_DDR DDRA - -#define DIO3_PIN PINA3 -#define DIO3_RPORT PINA -#define DIO3_WPORT PORTA -#define DIO3_PWM NULL -#define DIO3_DDR DDRA - -#define DIO4_PIN PINA4 -#define DIO4_RPORT PINA -#define DIO4_WPORT PORTA -#define DIO4_PWM NULL -#define DIO4_DDR DDRA - -#define DIO5_PIN PINA5 -#define DIO5_RPORT PINA -#define DIO5_WPORT PORTA -#define DIO5_PWM NULL -#define DIO5_DDR DDRA - -#define DIO6_PIN PINA6 -#define DIO6_RPORT PINA -#define DIO6_WPORT PORTA -#define DIO6_PWM NULL -#define DIO6_DDR DDRA - -#define DIO7_PIN PINA7 -#define DIO7_RPORT PINA -#define DIO7_WPORT PORTA -#define DIO7_PWM NULL -#define DIO7_DDR DDRA - -#define DIO8_PIN PINB0 -#define DIO8_RPORT PINB -#define DIO8_WPORT PORTB -#define DIO8_PWM NULL -#define DIO8_DDR DDRB - -#define DIO9_PIN PINB1 -#define DIO9_RPORT PINB -#define DIO9_WPORT PORTB -#define DIO9_PWM NULL -#define DIO9_DDR DDRB - -#define DIO10_PIN PINB2 -#define DIO10_RPORT PINB -#define DIO10_WPORT PORTB -#define DIO10_PWM NULL -#define DIO10_DDR DDRB - -#define DIO11_PIN PINB3 -#define DIO11_RPORT PINB -#define DIO11_WPORT PORTB -#define DIO11_PWM NULL -#define DIO11_DDR DDRB - -#define DIO12_PIN PINB4 -#define DIO12_RPORT PINB -#define DIO12_WPORT PORTB -#define DIO12_PWM NULL -#define DIO12_DDR DDRB - -#define DIO13_PIN PINB5 -#define DIO13_RPORT PINB -#define DIO13_WPORT PORTB -#define DIO13_PWM NULL -#define DIO13_DDR DDRB - -#define DIO14_PIN PINB6 -#define DIO14_RPORT PINB -#define DIO14_WPORT PORTB -#define DIO14_PWM NULL -#define DIO14_DDR DDRB - -#define DIO15_PIN PINB7 -#define DIO15_RPORT PINB -#define DIO15_WPORT PORTB -#define DIO15_PWM NULL -#define DIO15_DDR DDRB - -#define DIO16_PIN PINC0 -#define DIO16_RPORT PINC -#define DIO16_WPORT PORTC -#define DIO16_PWM NULL -#define DIO16_DDR DDRC - -#define DIO17_PIN PINC1 -#define DIO17_RPORT PINC -#define DIO17_WPORT PORTC -#define DIO17_PWM NULL -#define DIO17_DDR DDRC - -#define DIO18_PIN PINC2 -#define DIO18_RPORT PINC -#define DIO18_WPORT PORTC -#define DIO18_PWM NULL -#define DIO18_DDR DDRC - -#define DIO19_PIN PINC3 -#define DIO19_RPORT PINC -#define DIO19_WPORT PORTC -#define DIO19_PWM NULL -#define DIO19_DDR DDRC - -#define DIO20_PIN PINC4 -#define DIO20_RPORT PINC -#define DIO20_WPORT PORTC -#define DIO20_PWM NULL -#define DIO20_DDR DDRC - -#define DIO21_PIN PINC5 -#define DIO21_RPORT PINC -#define DIO21_WPORT PORTC -#define DIO21_PWM NULL -#define DIO21_DDR DDRC - -#define DIO22_PIN PINC6 -#define DIO22_RPORT PINC -#define DIO22_WPORT PORTC -#define DIO22_PWM NULL -#define DIO22_DDR DDRC - -#define DIO23_PIN PINC7 -#define DIO23_RPORT PINC -#define DIO23_WPORT PORTC -#define DIO23_PWM NULL -#define DIO23_DDR DDRC - -#define DIO24_PIN PIND0 -#define DIO24_RPORT PIND -#define DIO24_WPORT PORTD -#define DIO24_PWM NULL -#define DIO24_DDR DDRD - -#define DIO25_PIN PIND1 -#define DIO25_RPORT PIND -#define DIO25_WPORT PORTD -#define DIO25_PWM NULL -#define DIO25_DDR DDRD - -#define DIO26_PIN PIND2 -#define DIO26_RPORT PIND -#define DIO26_WPORT PORTD -#define DIO26_PWM NULL -#define DIO26_DDR DDRD - -#define DIO27_PIN PIND3 -#define DIO27_RPORT PIND -#define DIO27_WPORT PORTD -#define DIO27_PWM NULL -#define DIO27_DDR DDRD - -#define DIO28_PIN PIND4 -#define DIO28_RPORT PIND -#define DIO28_WPORT PORTD -#define DIO28_PWM NULL -#define DIO28_DDR DDRD - -#define DIO29_PIN PIND5 -#define DIO29_RPORT PIND -#define DIO29_WPORT PORTD -#define DIO29_PWM NULL -#define DIO29_DDR DDRD - -#define DIO30_PIN PIND6 -#define DIO30_RPORT PIND -#define DIO30_WPORT PORTD -#define DIO30_PWM NULL -#define DIO30_DDR DDRD - -#define DIO31_PIN PIND7 -#define DIO31_RPORT PIND -#define DIO31_WPORT PORTD -#define DIO31_PWM NULL -#define DIO31_DDR DDRD - - -#define DIO32_PIN PINE0 -#define DIO32_RPORT PINE -#define DIO32_WPORT PORTE -#define DIO32_PWM NULL -#define DIO32_DDR DDRE - -#define DIO33_PIN PINE1 -#define DIO33_RPORT PINE -#define DIO33_WPORT PORTE -#define DIO33_PWM NULL -#define DIO33_DDR DDRE - -#define DIO34_PIN PINE2 -#define DIO34_RPORT PINE -#define DIO34_WPORT PORTE -#define DIO34_PWM NULL -#define DIO34_DDR DDRE - -#define DIO35_PIN PINE3 -#define DIO35_RPORT PINE -#define DIO35_WPORT PORTE -#define DIO35_PWM NULL -#define DIO35_DDR DDRE - -#define DIO36_PIN PINE4 -#define DIO36_RPORT PINE -#define DIO36_WPORT PORTE -#define DIO36_PWM NULL -#define DIO36_DDR DDRE - -#define DIO37_PIN PINE5 -#define DIO37_RPORT PINE -#define DIO37_WPORT PORTE -#define DIO37_PWM NULL -#define DIO37_DDR DDRE - -#define DIO38_PIN PINE6 -#define DIO38_RPORT PINE -#define DIO38_WPORT PORTE -#define DIO38_PWM NULL -#define DIO38_DDR DDRE - -#define DIO39_PIN PINE7 -#define DIO39_RPORT PINE -#define DIO39_WPORT PORTE -#define DIO39_PWM NULL -#define DIO39_DDR DDRE - -#define AIO0_PIN PINF0 -#define AIO0_RPORT PINF -#define AIO0_WPORT PORTF -#define AIO0_PWM NULL -#define AIO0_DDR DDRF - -#define AIO1_PIN PINF1 -#define AIO1_RPORT PINF -#define AIO1_WPORT PORTF -#define AIO1_PWM NULL -#define AIO1_DDR DDRF - -#define AIO2_PIN PINF2 -#define AIO2_RPORT PINF -#define AIO2_WPORT PORTF -#define AIO2_PWM NULL -#define AIO2_DDR DDRF - -#define AIO3_PIN PINF3 -#define AIO3_RPORT PINF -#define AIO3_WPORT PORTF -#define AIO3_PWM NULL -#define AIO3_DDR DDRF - -#define AIO4_PIN PINF4 -#define AIO4_RPORT PINF -#define AIO4_WPORT PORTF -#define AIO4_PWM NULL -#define AIO4_DDR DDRF - -#define AIO5_PIN PINF5 -#define AIO5_RPORT PINF -#define AIO5_WPORT PORTF -#define AIO5_PWM NULL -#define AIO5_DDR DDRF - -#define AIO6_PIN PINF6 -#define AIO6_RPORT PINF -#define AIO6_WPORT PORTF -#define AIO6_PWM NULL -#define AIO6_DDR DDRF - -#define AIO7_PIN PINF7 -#define AIO7_RPORT PINF -#define AIO7_WPORT PORTF -#define AIO7_PWM NULL -#define AIO7_DDR DDRF - -#define DIO40_PIN PINF0 -#define DIO40_RPORT PINF -#define DIO40_WPORT PORTF -#define DIO40_PWM NULL -#define DIO40_DDR DDRF - -#define DIO41_PIN PINF1 -#define DIO41_RPORT PINF -#define DIO41_WPORT PORTF -#define DIO41_PWM NULL -#define DIO41_DDR DDRF - -#define DIO42_PIN PINF2 -#define DIO42_RPORT PINF -#define DIO42_WPORT PORTF -#define DIO42_PWM NULL -#define DIO42_DDR DDRF - -#define DIO43_PIN PINF3 -#define DIO43_RPORT PINF -#define DIO43_WPORT PORTF -#define DIO43_PWM NULL -#define DIO43_DDR DDRF - -#define DIO44_PIN PINF4 -#define DIO44_RPORT PINF -#define DIO44_WPORT PORTF -#define DIO44_PWM NULL -#define DIO44_DDR DDRF - -#define DIO45_PIN PINF5 -#define DIO45_RPORT PINF -#define DIO45_WPORT PORTF -#define DIO45_PWM NULL -#define DIO45_DDR DDRF - -#define DIO46_PIN PINF6 -#define DIO46_RPORT PINF -#define DIO46_WPORT PORTF -#define DIO46_PWM NULL -#define DIO46_DDR DDRF - -#define DIO47_PIN PINF7 -#define DIO47_RPORT PINF -#define DIO47_WPORT PORTF -#define DIO47_PWM NULL -#define DIO47_DDR DDRF - - - -#undef PA0 -#define PA0_PIN PINA0 -#define PA0_RPORT PINA -#define PA0_WPORT PORTA -#define PA0_PWM NULL -#define PA0_DDR DDRA -#undef PA1 -#define PA1_PIN PINA1 -#define PA1_RPORT PINA -#define PA1_WPORT PORTA -#define PA1_PWM NULL -#define PA1_DDR DDRA -#undef PA2 -#define PA2_PIN PINA2 -#define PA2_RPORT PINA -#define PA2_WPORT PORTA -#define PA2_PWM NULL -#define PA2_DDR DDRA -#undef PA3 -#define PA3_PIN PINA3 -#define PA3_RPORT PINA -#define PA3_WPORT PORTA -#define PA3_PWM NULL -#define PA3_DDR DDRA -#undef PA4 -#define PA4_PIN PINA4 -#define PA4_RPORT PINA -#define PA4_WPORT PORTA -#define PA4_PWM NULL -#define PA4_DDR DDRA -#undef PA5 -#define PA5_PIN PINA5 -#define PA5_RPORT PINA -#define PA5_WPORT PORTA -#define PA5_PWM NULL -#define PA5_DDR DDRA -#undef PA6 -#define PA6_PIN PINA6 -#define PA6_RPORT PINA -#define PA6_WPORT PORTA -#define PA6_PWM NULL -#define PA6_DDR DDRA -#undef PA7 -#define PA7_PIN PINA7 -#define PA7_RPORT PINA -#define PA7_WPORT PORTA -#define PA7_PWM NULL -#define PA7_DDR DDRA - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_PWM NULL -#define PB0_DDR DDRB -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_PWM NULL -#define PB1_DDR DDRB -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_PWM NULL -#define PB2_DDR DDRB -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_PWM NULL -#define PB3_DDR DDRB -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_PWM NULL -#define PB4_DDR DDRB -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_PWM NULL -#define PB5_DDR DDRB -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_PWM NULL -#define PB6_DDR DDRB -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_PWM NULL -#define PB7_DDR DDRB - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_PWM NULL -#define PC0_DDR DDRC -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_PWM NULL -#define PC1_DDR DDRC -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_PWM NULL -#define PC2_DDR DDRC -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_PWM NULL -#define PC3_DDR DDRC -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_PWM NULL -#define PC4_DDR DDRC -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_PWM NULL -#define PC5_DDR DDRC -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_PWM NULL -#define PC6_DDR DDRC -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_PWM NULL -#define PC7_DDR DDRC - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_PWM NULL -#define PD0_DDR DDRD -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_PWM NULL -#define PD1_DDR DDRD -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_PWM NULL -#define PD2_DDR DDRD -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_PWM NULL -#define PD3_DDR DDRD -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_PWM NULL -#define PD4_DDR DDRD -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_PWM NULL -#define PD5_DDR DDRD -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_PWM NULL -#define PD6_DDR DDRD -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_PWM NULL -#define PD7_DDR DDRD - -#undef PE0 -#define PE0_PIN PINE0 -#define PE0_RPORT PINE -#define PE0_WPORT PORTE -#define PE0_PWM NULL -#define PE0_DDR DDRE -#undef PE1 -#define PE1_PIN PINE1 -#define PE1_RPORT PINE -#define PE1_WPORT PORTE -#define PE1_PWM NULL -#define PE1_DDR DDRE -#undef PE2 -#define PE2_PIN PINE2 -#define PE2_RPORT PINE -#define PE2_WPORT PORTE -#define PE2_PWM NULL -#define PE2_DDR DDRE -#undef PE3 -#define PE3_PIN PINE3 -#define PE3_RPORT PINE -#define PE3_WPORT PORTE -#define PE3_PWM NULL -#define PE3_DDR DDRE -#undef PE4 -#define PE4_PIN PINE4 -#define PE4_RPORT PINE -#define PE4_WPORT PORTE -#define PE4_PWM NULL -#define PE4_DDR DDRE -#undef PE5 -#define PE5_PIN PINE5 -#define PE5_RPORT PINE -#define PE5_WPORT PORTE -#define PE5_PWM NULL -#define PE5_DDR DDRE -#undef PE6 -#define PE6_PIN PINE6 -#define PE6_RPORT PINE -#define PE6_WPORT PORTE -#define PE6_PWM NULL -#define PE6_DDR DDRE -#undef PE7 -#define PE7_PIN PINE7 -#define PE7_RPORT PINE -#define PE7_WPORT PORTE -#define PE7_PWM NULL -#define PE7_DDR DDRE - -#undef PF0 -#define PF0_PIN PINF0 -#define PF0_RPORT PINF -#define PF0_WPORT PORTF -#define PF0_PWM NULL -#define PF0_DDR DDRF -#undef PF1 -#define PF1_PIN PINF1 -#define PF1_RPORT PINF -#define PF1_WPORT PORTF -#define PF1_PWM NULL -#define PF1_DDR DDRF -#undef PF2 -#define PF2_PIN PINF2 -#define PF2_RPORT PINF -#define PF2_WPORT PORTF -#define PF2_PWM NULL -#define PF2_DDR DDRF -#undef PF3 -#define PF3_PIN PINF3 -#define PF3_RPORT PINF -#define PF3_WPORT PORTF -#define PF3_PWM NULL -#define PF3_DDR DDRF -#undef PF4 -#define PF4_PIN PINF4 -#define PF4_RPORT PINF -#define PF4_WPORT PORTF -#define PF4_PWM NULL -#define PF4_DDR DDRF -#undef PF5 -#define PF5_PIN PINF5 -#define PF5_RPORT PINF -#define PF5_WPORT PORTF -#define PF5_PWM NULL -#define PF5_DDR DDRF -#undef PF6 -#define PF6_PIN PINF6 -#define PF6_RPORT PINF -#define PF6_WPORT PORTF -#define PF6_PWM NULL -#define PF6_DDR DDRF -#undef PF7 -#define PF7_PIN PINF7 -#define PF7_RPORT PINF -#define PF7_WPORT PORTF -#define PF7_PWM NULL -#define PF7_DDR DDRF -#endif - -#ifndef DIO0_PIN -#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request -#endif - +/* + This code contibuted by Triffid_Hunter and modified by Kliment + why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html +*/ + +#ifndef _ARDUINO_H +#define _ARDUINO_H + +#include + +/* + utility functions +*/ + +#ifndef MASK +/// MASKING- returns \f$2^PIN\f$ + #define MASK(PIN) (1 << PIN) +#endif + +/* + magic I/O routines + + now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0); +*/ + +/// Read a pin +#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) +/// write to a pin +#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) +//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) +/// toggle a pin +#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) + +/// set pin as input +#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0) +/// set pin as output +#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0) + +/// check if pin is an input +#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0) +/// check if pin is an output +#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0) + +// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html + +/// Read a pin wrapper +#define READ(IO) _READ(IO) +/// Write to a pin wrapper +#define WRITE(IO, v) _WRITE(IO, v) +/// toggle a pin wrapper +#define TOGGLE(IO) _TOGGLE(IO) + +/// set pin as input wrapper +#define SET_INPUT(IO) _SET_INPUT(IO) +/// set pin as output wrapper +#define SET_OUTPUT(IO) _SET_OUTPUT(IO) + +/// check if pin is an input wrapper +#define GET_INPUT(IO) _GET_INPUT(IO) +/// check if pin is an output wrapper +#define GET_OUTPUT(IO) _GET_OUTPUT(IO) + +/* + ports and functions + + added as necessary or if I feel like it- not a comprehensive list! +*/ + +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO13 +#define MISO DIO12 +#define MOSI DIO11 +#define SS DIO10 + +// TWI (I2C) +#define SCL AIO5 +#define SDA AIO4 + +// timers and PWM +#define OC0A DIO6 +#define OC0B DIO5 +#define OC1A DIO9 +#define OC1B DIO10 +#define OC2A DIO11 +#define OC2B DIO3 + +#define DEBUG_LED AIO5 + +/* +pins +*/ + +#define DIO0_PIN PIND0 +#define DIO0_RPORT PIND +#define DIO0_WPORT PORTD +#define DIO0_DDR DDRD +#define DIO0_PWM NULL + +#define DIO1_PIN PIND1 +#define DIO1_RPORT PIND +#define DIO1_WPORT PORTD +#define DIO1_DDR DDRD +#define DIO1_PWM NULL + +#define DIO2_PIN PIND2 +#define DIO2_RPORT PIND +#define DIO2_WPORT PORTD +#define DIO2_DDR DDRD +#define DIO2_PWM NULL + +#define DIO3_PIN PIND3 +#define DIO3_RPORT PIND +#define DIO3_WPORT PORTD +#define DIO3_DDR DDRD +#define DIO3_PWM &OCR2B + +#define DIO4_PIN PIND4 +#define DIO4_RPORT PIND +#define DIO4_WPORT PORTD +#define DIO4_DDR DDRD +#define DIO4_PWM NULL + +#define DIO5_PIN PIND5 +#define DIO5_RPORT PIND +#define DIO5_WPORT PORTD +#define DIO5_DDR DDRD +#define DIO5_PWM &OCR0B + +#define DIO6_PIN PIND6 +#define DIO6_RPORT PIND +#define DIO6_WPORT PORTD +#define DIO6_DDR DDRD +#define DIO6_PWM &OCR0A + +#define DIO7_PIN PIND7 +#define DIO7_RPORT PIND +#define DIO7_WPORT PORTD +#define DIO7_DDR DDRD +#define DIO7_PWM NULL + +#define DIO8_PIN PINB0 +#define DIO8_RPORT PINB +#define DIO8_WPORT PORTB +#define DIO8_DDR DDRB +#define DIO8_PWM NULL + +#define DIO9_PIN PINB1 +#define DIO9_RPORT PINB +#define DIO9_WPORT PORTB +#define DIO9_DDR DDRB +#define DIO9_PWM NULL + +#define DIO10_PIN PINB2 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_DDR DDRB +#define DIO10_PWM NULL + +#define DIO11_PIN PINB3 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_DDR DDRB +#define DIO11_PWM &OCR2A + +#define DIO12_PIN PINB4 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_DDR DDRB +#define DIO12_PWM NULL + +#define DIO13_PIN PINB5 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_DDR DDRB +#define DIO13_PWM NULL + + +#define DIO14_PIN PINC0 +#define DIO14_RPORT PINC +#define DIO14_WPORT PORTC +#define DIO14_DDR DDRC +#define DIO14_PWM NULL + +#define DIO15_PIN PINC1 +#define DIO15_RPORT PINC +#define DIO15_WPORT PORTC +#define DIO15_DDR DDRC +#define DIO15_PWM NULL + +#define DIO16_PIN PINC2 +#define DIO16_RPORT PINC +#define DIO16_WPORT PORTC +#define DIO16_DDR DDRC +#define DIO16_PWM NULL + +#define DIO17_PIN PINC3 +#define DIO17_RPORT PINC +#define DIO17_WPORT PORTC +#define DIO17_DDR DDRC +#define DIO17_PWM NULL + +#define DIO18_PIN PINC4 +#define DIO18_RPORT PINC +#define DIO18_WPORT PORTC +#define DIO18_DDR DDRC +#define DIO18_PWM NULL + +#define DIO19_PIN PINC5 +#define DIO19_RPORT PINC +#define DIO19_WPORT PORTC +#define DIO19_DDR DDRC +#define DIO19_PWM NULL + +#define DIO20_PIN PINC6 +#define DIO20_RPORT PINC +#define DIO20_WPORT PORTC +#define DIO20_DDR DDRC +#define DIO20_PWM NULL + +#define DIO21_PIN PINC7 +#define DIO21_RPORT PINC +#define DIO21_WPORT PORTC +#define DIO21_DDR DDRC +#define DIO21_PWM NULL + + + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB0_PWM NULL + +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB1_PWM NULL + +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB2_PWM NULL + +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB3_PWM &OCR2A + +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB4_PWM NULL + +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB5_PWM NULL + +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB6_PWM NULL + +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB +#define PB7_PWM NULL + + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC0_PWM NULL + +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC1_PWM NULL + +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC2_PWM NULL + +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC3_PWM NULL + +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC4_PWM NULL + +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC5_PWM NULL + +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC6_PWM NULL + +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC +#define PC7_PWM NULL + + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD0_PWM NULL + +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD1_PWM NULL + +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD2_PWM NULL + +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD3_PWM &OCR2B + +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD4_PWM NULL + +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD5_PWM &OCR0B + +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD6_PWM &OCR0A + +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD +#define PD7_PWM NULL +#endif /* _AVR_ATmega{168,328,328P}__ */ + +#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) +// UART +#define RXD DIO8 +#define TXD DIO9 +#define RXD0 DIO8 +#define TXD0 DIO9 + +#define RXD1 DIO10 +#define TXD1 DIO11 + +// SPI +#define SCK DIO7 +#define MISO DIO6 +#define MOSI DIO5 +#define SS DIO4 + +// TWI (I2C) +#define SCL DIO16 +#define SDA DIO17 + +// timers and PWM +#define OC0A DIO3 +#define OC0B DIO4 +#define OC1A DIO13 +#define OC1B DIO12 +#define OC2A DIO15 +#define OC2B DIO14 + +#define DEBUG_LED DIO0 +/* +pins +*/ + +#define DIO0_PIN PINB0 +#define DIO0_RPORT PINB +#define DIO0_WPORT PORTB +#define DIO0_DDR DDRB +#define DIO0_PWM NULL + +#define DIO1_PIN PINB1 +#define DIO1_RPORT PINB +#define DIO1_WPORT PORTB +#define DIO1_DDR DDRB +#define DIO1_PWM NULL + +#define DIO2_PIN PINB2 +#define DIO2_RPORT PINB +#define DIO2_WPORT PORTB +#define DIO2_DDR DDRB +#define DIO2_PWM NULL + +#define DIO3_PIN PINB3 +#define DIO3_RPORT PINB +#define DIO3_WPORT PORTB +#define DIO3_DDR DDRB +#define DIO3_PWM &OCR0A + +#define DIO4_PIN PINB4 +#define DIO4_RPORT PINB +#define DIO4_WPORT PORTB +#define DIO4_DDR DDRB +#define DIO4_PWM &OCR0B + +#define DIO5_PIN PINB5 +#define DIO5_RPORT PINB +#define DIO5_WPORT PORTB +#define DIO5_DDR DDRB +#define DIO5_PWM NULL + +#define DIO6_PIN PINB6 +#define DIO6_RPORT PINB +#define DIO6_WPORT PORTB +#define DIO6_DDR DDRB +#define DIO6_PWM NULL + +#define DIO7_PIN PINB7 +#define DIO7_RPORT PINB +#define DIO7_WPORT PORTB +#define DIO7_DDR DDRB +#define DIO7_PWM NULL + +#define DIO8_PIN PIND0 +#define DIO8_RPORT PIND +#define DIO8_WPORT PORTD +#define DIO8_DDR DDRD +#define DIO8_PWM NULL + +#define DIO9_PIN PIND1 +#define DIO9_RPORT PIND +#define DIO9_WPORT PORTD +#define DIO9_DDR DDRD +#define DIO9_PWM NULL + +#define DIO10_PIN PIND2 +#define DIO10_RPORT PIND +#define DIO10_WPORT PORTD +#define DIO10_DDR DDRD +#define DIO10_PWM NULL + +#define DIO11_PIN PIND3 +#define DIO11_RPORT PIND +#define DIO11_WPORT PORTD +#define DIO11_DDR DDRD +#define DIO11_PWM NULL + +#define DIO12_PIN PIND4 +#define DIO12_RPORT PIND +#define DIO12_WPORT PORTD +#define DIO12_DDR DDRD +#define DIO12_PWM NULL + +#define DIO13_PIN PIND5 +#define DIO13_RPORT PIND +#define DIO13_WPORT PORTD +#define DIO13_DDR DDRD +#define DIO13_PWM NULL + +#define DIO14_PIN PIND6 +#define DIO14_RPORT PIND +#define DIO14_WPORT PORTD +#define DIO14_DDR DDRD +#define DIO14_PWM &OCR2B + +#define DIO15_PIN PIND7 +#define DIO15_RPORT PIND +#define DIO15_WPORT PORTD +#define DIO15_DDR DDRD +#define DIO15_PWM &OCR2A + +#define DIO16_PIN PINC0 +#define DIO16_RPORT PINC +#define DIO16_WPORT PORTC +#define DIO16_DDR DDRC +#define DIO16_PWM NULL + +#define DIO17_PIN PINC1 +#define DIO17_RPORT PINC +#define DIO17_WPORT PORTC +#define DIO17_DDR DDRC +#define DIO17_PWM NULL + +#define DIO18_PIN PINC2 +#define DIO18_RPORT PINC +#define DIO18_WPORT PORTC +#define DIO18_DDR DDRC +#define DIO18_PWM NULL + +#define DIO19_PIN PINC3 +#define DIO19_RPORT PINC +#define DIO19_WPORT PORTC +#define DIO19_DDR DDRC +#define DIO19_PWM NULL + +#define DIO20_PIN PINC4 +#define DIO20_RPORT PINC +#define DIO20_WPORT PORTC +#define DIO20_DDR DDRC +#define DIO20_PWM NULL + +#define DIO21_PIN PINC5 +#define DIO21_RPORT PINC +#define DIO21_WPORT PORTC +#define DIO21_DDR DDRC +#define DIO21_PWM NULL + +#define DIO22_PIN PINC6 +#define DIO22_RPORT PINC +#define DIO22_WPORT PORTC +#define DIO22_DDR DDRC +#define DIO22_PWM NULL + +#define DIO23_PIN PINC7 +#define DIO23_RPORT PINC +#define DIO23_WPORT PORTC +#define DIO23_DDR DDRC +#define DIO23_PWM NULL + +#define DIO24_PIN PINA7 +#define DIO24_RPORT PINA +#define DIO24_WPORT PORTA +#define DIO24_DDR DDRA +#define DIO24_PWM NULL + +#define DIO25_PIN PINA6 +#define DIO25_RPORT PINA +#define DIO25_WPORT PORTA +#define DIO25_DDR DDRA +#define DIO25_PWM NULL + +#define DIO26_PIN PINA5 +#define DIO26_RPORT PINA +#define DIO26_WPORT PORTA +#define DIO26_DDR DDRA +#define DIO26_PWM NULL + +#define DIO27_PIN PINA4 +#define DIO27_RPORT PINA +#define DIO27_WPORT PORTA +#define DIO27_DDR DDRA +#define DIO27_PWM NULL + +#define DIO28_PIN PINA3 +#define DIO28_RPORT PINA +#define DIO28_WPORT PORTA +#define DIO28_DDR DDRA +#define DIO28_PWM NULL + +#define DIO29_PIN PINA2 +#define DIO29_RPORT PINA +#define DIO29_WPORT PORTA +#define DIO29_DDR DDRA +#define DIO29_PWM NULL + +#define DIO30_PIN PINA1 +#define DIO30_RPORT PINA +#define DIO30_WPORT PORTA +#define DIO30_DDR DDRA +#define DIO30_PWM NULL + +#define DIO31_PIN PINA0 +#define DIO31_RPORT PINA +#define DIO31_WPORT PORTA +#define DIO31_DDR DDRA +#define DIO31_PWM NULL + +#define AIO0_PIN PINA0 +#define AIO0_RPORT PINA +#define AIO0_WPORT PORTA +#define AIO0_DDR DDRA +#define AIO0_PWM NULL + +#define AIO1_PIN PINA1 +#define AIO1_RPORT PINA +#define AIO1_WPORT PORTA +#define AIO1_DDR DDRA +#define AIO1_PWM NULL + +#define AIO2_PIN PINA2 +#define AIO2_RPORT PINA +#define AIO2_WPORT PORTA +#define AIO2_DDR DDRA +#define AIO2_PWM NULL + +#define AIO3_PIN PINA3 +#define AIO3_RPORT PINA +#define AIO3_WPORT PORTA +#define AIO3_DDR DDRA +#define AIO3_PWM NULL + +#define AIO4_PIN PINA4 +#define AIO4_RPORT PINA +#define AIO4_WPORT PORTA +#define AIO4_DDR DDRA +#define AIO4_PWM NULL + +#define AIO5_PIN PINA5 +#define AIO5_RPORT PINA +#define AIO5_WPORT PORTA +#define AIO5_DDR DDRA +#define AIO5_PWM NULL + +#define AIO6_PIN PINA6 +#define AIO6_RPORT PINA +#define AIO6_WPORT PORTA +#define AIO6_DDR DDRA +#define AIO6_PWM NULL + +#define AIO7_PIN PINA7 +#define AIO7_RPORT PINA +#define AIO7_WPORT PORTA +#define AIO7_DDR DDRA +#define AIO7_PWM NULL + + + +#undef PA0 +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_DDR DDRA +#define PA0_PWM NULL + +#undef PA1 +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_DDR DDRA +#define PA1_PWM NULL + +#undef PA2 +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_DDR DDRA +#define PA2_PWM NULL + +#undef PA3 +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_DDR DDRA +#define PA3_PWM NULL + +#undef PA4 +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_DDR DDRA +#define PA4_PWM NULL + +#undef PA5 +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_DDR DDRA +#define PA5_PWM NULL + +#undef PA6 +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_DDR DDRA +#define PA6_PWM NULL + +#undef PA7 +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_DDR DDRA +#define PA7_PWM NULL + + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB0_PWM NULL + +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB1_PWM NULL + +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB2_PWM NULL + +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB3_PWM &OCR0A + +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB4_PWM &OCR0B + +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB5_PWM NULL + +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB6_PWM NULL + +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB +#define PB7_PWM NULL + + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC0_PWM NULL + +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC1_PWM NULL + +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC2_PWM NULL + +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC3_PWM NULL + +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC4_PWM NULL + +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC5_PWM NULL + +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC6_PWM NULL + +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC +#define PC7_PWM NULL + + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD0_PWM NULL + +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD1_PWM NULL + +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD2_PWM NULL + +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD3_PWM NULL + +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD4_PWM NULL + +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD5_PWM NULL + +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD6_PWM &OCR2B + +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD +#define PD7_PWM &OCR2A +#endif /* _AVR_ATmega{644,644P,644PA}__ */ + +#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO52 +#define MISO DIO50 +#define MOSI DIO51 +#define SS DIO53 + +// TWI (I2C) +#define SCL DIO21 +#define SDA DIO20 + +// timers and PWM +#define OC0A DIO13 +#define OC0B DIO4 +#define OC1A DIO11 +#define OC1B DIO12 +#define OC2A DIO10 +#define OC2B DIO9 +#define OC3A DIO5 +#define OC3B DIO2 +#define OC3C DIO3 +#define OC4A DIO6 +#define OC4B DIO7 +#define OC4C DIO8 +#define OC5A DIO46 +#define OC5B DIO45 +#define OC5C DIO44 + +// change for your board +#define DEBUG_LED DIO21 + +/* +pins +*/ +#define DIO0_PIN PINE0 +#define DIO0_RPORT PINE +#define DIO0_WPORT PORTE +#define DIO0_DDR DDRE +#define DIO0_PWM NULL + +#define DIO1_PIN PINE1 +#define DIO1_RPORT PINE +#define DIO1_WPORT PORTE +#define DIO1_DDR DDRE +#define DIO1_PWM NULL + +#define DIO2_PIN PINE4 +#define DIO2_RPORT PINE +#define DIO2_WPORT PORTE +#define DIO2_DDR DDRE +#define DIO2_PWM &OCR3BL + +#define DIO3_PIN PINE5 +#define DIO3_RPORT PINE +#define DIO3_WPORT PORTE +#define DIO3_DDR DDRE +#define DIO3_PWM &OCR3CL + +#define DIO4_PIN PING5 +#define DIO4_RPORT PING +#define DIO4_WPORT PORTG +#define DIO4_DDR DDRG +#define DIO4_PWM &OCR0B + +#define DIO5_PIN PINE3 +#define DIO5_RPORT PINE +#define DIO5_WPORT PORTE +#define DIO5_DDR DDRE +#define DIO5_PWM &OCR3AL + +#define DIO6_PIN PINH3 +#define DIO6_RPORT PINH +#define DIO6_WPORT PORTH +#define DIO6_DDR DDRH +#define DIO6_PWM &OCR4AL + +#define DIO7_PIN PINH4 +#define DIO7_RPORT PINH +#define DIO7_WPORT PORTH +#define DIO7_DDR DDRH +#define DIO7_PWM &OCR4BL + +#define DIO8_PIN PINH5 +#define DIO8_RPORT PINH +#define DIO8_WPORT PORTH +#define DIO8_DDR DDRH +#define DIO8_PWM &OCR4CL + +#define DIO9_PIN PINH6 +#define DIO9_RPORT PINH +#define DIO9_WPORT PORTH +#define DIO9_DDR DDRH +#define DIO9_PWM &OCR2B + +#define DIO10_PIN PINB4 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_DDR DDRB +#define DIO10_PWM &OCR2A + +#define DIO11_PIN PINB5 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_DDR DDRB +#define DIO11_PWM NULL + +#define DIO12_PIN PINB6 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_DDR DDRB +#define DIO12_PWM NULL + +#define DIO13_PIN PINB7 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_DDR DDRB +#define DIO13_PWM &OCR0A + +#define DIO14_PIN PINJ1 +#define DIO14_RPORT PINJ +#define DIO14_WPORT PORTJ +#define DIO14_DDR DDRJ +#define DIO14_PWM NULL + +#define DIO15_PIN PINJ0 +#define DIO15_RPORT PINJ +#define DIO15_WPORT PORTJ +#define DIO15_DDR DDRJ +#define DIO15_PWM NULL + +#define DIO16_PIN PINH1 +#define DIO16_RPORT PINH +#define DIO16_WPORT PORTH +#define DIO16_DDR DDRH +#define DIO16_PWM NULL + +#define DIO17_PIN PINH0 +#define DIO17_RPORT PINH +#define DIO17_WPORT PORTH +#define DIO17_DDR DDRH +#define DIO17_PWM NULL + +#define DIO18_PIN PIND3 +#define DIO18_RPORT PIND +#define DIO18_WPORT PORTD +#define DIO18_DDR DDRD +#define DIO18_PWM NULL + +#define DIO19_PIN PIND2 +#define DIO19_RPORT PIND +#define DIO19_WPORT PORTD +#define DIO19_DDR DDRD +#define DIO19_PWM NULL + +#define DIO20_PIN PIND1 +#define DIO20_RPORT PIND +#define DIO20_WPORT PORTD +#define DIO20_DDR DDRD +#define DIO20_PWM NULL + +#define DIO21_PIN PIND0 +#define DIO21_RPORT PIND +#define DIO21_WPORT PORTD +#define DIO21_DDR DDRD +#define DIO21_PWM NULL + +#define DIO22_PIN PINA0 +#define DIO22_RPORT PINA +#define DIO22_WPORT PORTA +#define DIO22_DDR DDRA +#define DIO22_PWM NULL + +#define DIO23_PIN PINA1 +#define DIO23_RPORT PINA +#define DIO23_WPORT PORTA +#define DIO23_DDR DDRA +#define DIO23_PWM NULL + +#define DIO24_PIN PINA2 +#define DIO24_RPORT PINA +#define DIO24_WPORT PORTA +#define DIO24_DDR DDRA +#define DIO24_PWM NULL + +#define DIO25_PIN PINA3 +#define DIO25_RPORT PINA +#define DIO25_WPORT PORTA +#define DIO25_DDR DDRA +#define DIO25_PWM NULL + +#define DIO26_PIN PINA4 +#define DIO26_RPORT PINA +#define DIO26_WPORT PORTA +#define DIO26_DDR DDRA +#define DIO26_PWM NULL + +#define DIO27_PIN PINA5 +#define DIO27_RPORT PINA +#define DIO27_WPORT PORTA +#define DIO27_DDR DDRA +#define DIO27_PWM NULL + +#define DIO28_PIN PINA6 +#define DIO28_RPORT PINA +#define DIO28_WPORT PORTA +#define DIO28_DDR DDRA +#define DIO28_PWM NULL + +#define DIO29_PIN PINA7 +#define DIO29_RPORT PINA +#define DIO29_WPORT PORTA +#define DIO29_DDR DDRA +#define DIO29_PWM NULL + +#define DIO30_PIN PINC7 +#define DIO30_RPORT PINC +#define DIO30_WPORT PORTC +#define DIO30_DDR DDRC +#define DIO30_PWM NULL + +#define DIO31_PIN PINC6 +#define DIO31_RPORT PINC +#define DIO31_WPORT PORTC +#define DIO31_DDR DDRC +#define DIO31_PWM NULL + +#define DIO32_PIN PINC5 +#define DIO32_RPORT PINC +#define DIO32_WPORT PORTC +#define DIO32_DDR DDRC +#define DIO32_PWM NULL + +#define DIO33_PIN PINC4 +#define DIO33_RPORT PINC +#define DIO33_WPORT PORTC +#define DIO33_DDR DDRC +#define DIO33_PWM NULL + +#define DIO34_PIN PINC3 +#define DIO34_RPORT PINC +#define DIO34_WPORT PORTC +#define DIO34_DDR DDRC +#define DIO34_PWM NULL + +#define DIO35_PIN PINC2 +#define DIO35_RPORT PINC +#define DIO35_WPORT PORTC +#define DIO35_DDR DDRC +#define DIO35_PWM NULL + +#define DIO36_PIN PINC1 +#define DIO36_RPORT PINC +#define DIO36_WPORT PORTC +#define DIO36_DDR DDRC +#define DIO36_PWM NULL + +#define DIO37_PIN PINC0 +#define DIO37_RPORT PINC +#define DIO37_WPORT PORTC +#define DIO37_DDR DDRC +#define DIO37_PWM NULL + +#define DIO38_PIN PIND7 +#define DIO38_RPORT PIND +#define DIO38_WPORT PORTD +#define DIO38_DDR DDRD +#define DIO38_PWM NULL + +#define DIO39_PIN PING2 +#define DIO39_RPORT PING +#define DIO39_WPORT PORTG +#define DIO39_DDR DDRG +#define DIO39_PWM NULL + +#define DIO40_PIN PING1 +#define DIO40_RPORT PING +#define DIO40_WPORT PORTG +#define DIO40_DDR DDRG +#define DIO40_PWM NULL + +#define DIO41_PIN PING0 +#define DIO41_RPORT PING +#define DIO41_WPORT PORTG +#define DIO41_DDR DDRG +#define DIO41_PWM NULL + +#define DIO42_PIN PINL7 +#define DIO42_RPORT PINL +#define DIO42_WPORT PORTL +#define DIO42_DDR DDRL +#define DIO42_PWM NULL + +#define DIO43_PIN PINL6 +#define DIO43_RPORT PINL +#define DIO43_WPORT PORTL +#define DIO43_DDR DDRL +#define DIO43_PWM NULL + +#define DIO44_PIN PINL5 +#define DIO44_RPORT PINL +#define DIO44_WPORT PORTL +#define DIO44_DDR DDRL +#define DIO44_PWM &OCR5CL + +#define DIO45_PIN PINL4 +#define DIO45_RPORT PINL +#define DIO45_WPORT PORTL +#define DIO45_DDR DDRL +#define DIO45_PWM &OCR5BL + +#define DIO46_PIN PINL3 +#define DIO46_RPORT PINL +#define DIO46_WPORT PORTL +#define DIO46_DDR DDRL +#define DIO46_PWM &OCR5AL + +#define DIO47_PIN PINL2 +#define DIO47_RPORT PINL +#define DIO47_WPORT PORTL +#define DIO47_DDR DDRL +#define DIO47_PWM NULL + +#define DIO48_PIN PINL1 +#define DIO48_RPORT PINL +#define DIO48_WPORT PORTL +#define DIO48_DDR DDRL +#define DIO48_PWM NULL + +#define DIO49_PIN PINL0 +#define DIO49_RPORT PINL +#define DIO49_WPORT PORTL +#define DIO49_DDR DDRL +#define DIO49_PWM NULL + +#define DIO50_PIN PINB3 +#define DIO50_RPORT PINB +#define DIO50_WPORT PORTB +#define DIO50_DDR DDRB +#define DIO50_PWM NULL + +#define DIO51_PIN PINB2 +#define DIO51_RPORT PINB +#define DIO51_WPORT PORTB +#define DIO51_DDR DDRB +#define DIO51_PWM NULL + +#define DIO52_PIN PINB1 +#define DIO52_RPORT PINB +#define DIO52_WPORT PORTB +#define DIO52_DDR DDRB +#define DIO52_PWM NULL + +#define DIO53_PIN PINB0 +#define DIO53_RPORT PINB +#define DIO53_WPORT PORTB +#define DIO53_DDR DDRB +#define DIO53_PWM NULL + +#define DIO54_PIN PINF0 +#define DIO54_RPORT PINF +#define DIO54_WPORT PORTF +#define DIO54_DDR DDRF +#define DIO54_PWM NULL + +#define DIO55_PIN PINF1 +#define DIO55_RPORT PINF +#define DIO55_WPORT PORTF +#define DIO55_DDR DDRF +#define DIO55_PWM NULL + +#define DIO56_PIN PINF2 +#define DIO56_RPORT PINF +#define DIO56_WPORT PORTF +#define DIO56_DDR DDRF +#define DIO56_PWM NULL + +#define DIO57_PIN PINF3 +#define DIO57_RPORT PINF +#define DIO57_WPORT PORTF +#define DIO57_DDR DDRF +#define DIO57_PWM NULL + +#define DIO58_PIN PINF4 +#define DIO58_RPORT PINF +#define DIO58_WPORT PORTF +#define DIO58_DDR DDRF +#define DIO58_PWM NULL + +#define DIO59_PIN PINF5 +#define DIO59_RPORT PINF +#define DIO59_WPORT PORTF +#define DIO59_DDR DDRF +#define DIO59_PWM NULL + +#define DIO60_PIN PINF6 +#define DIO60_RPORT PINF +#define DIO60_WPORT PORTF +#define DIO60_DDR DDRF +#define DIO60_PWM NULL + +#define DIO61_PIN PINF7 +#define DIO61_RPORT PINF +#define DIO61_WPORT PORTF +#define DIO61_DDR DDRF +#define DIO61_PWM NULL + +#define DIO62_PIN PINK0 +#define DIO62_RPORT PINK +#define DIO62_WPORT PORTK +#define DIO62_DDR DDRK +#define DIO62_PWM NULL + +#define DIO63_PIN PINK1 +#define DIO63_RPORT PINK +#define DIO63_WPORT PORTK +#define DIO63_DDR DDRK +#define DIO63_PWM NULL + +#define DIO64_PIN PINK2 +#define DIO64_RPORT PINK +#define DIO64_WPORT PORTK +#define DIO64_DDR DDRK +#define DIO64_PWM NULL + +#define DIO65_PIN PINK3 +#define DIO65_RPORT PINK +#define DIO65_WPORT PORTK +#define DIO65_DDR DDRK +#define DIO65_PWM NULL + +#define DIO66_PIN PINK4 +#define DIO66_RPORT PINK +#define DIO66_WPORT PORTK +#define DIO66_DDR DDRK +#define DIO66_PWM NULL + +#define DIO67_PIN PINK5 +#define DIO67_RPORT PINK +#define DIO67_WPORT PORTK +#define DIO67_DDR DDRK +#define DIO67_PWM NULL + +#define DIO68_PIN PINK6 +#define DIO68_RPORT PINK +#define DIO68_WPORT PORTK +#define DIO68_DDR DDRK +#define DIO68_PWM NULL + +#define DIO69_PIN PINK7 +#define DIO69_RPORT PINK +#define DIO69_WPORT PORTK +#define DIO69_DDR DDRK +#define DIO69_PWM NULL + + + +#undef PA0 +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_DDR DDRA +#define PA0_PWM NULL +#undef PA1 +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_DDR DDRA +#define PA1_PWM NULL +#undef PA2 +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_DDR DDRA +#define PA2_PWM NULL +#undef PA3 +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_DDR DDRA +#define PA3_PWM NULL +#undef PA4 +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_DDR DDRA +#define PA4_PWM NULL +#undef PA5 +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_DDR DDRA +#define PA5_PWM NULL +#undef PA6 +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_DDR DDRA +#define PA6_PWM NULL +#undef PA7 +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_DDR DDRA +#define PA7_PWM NULL + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB0_PWM NULL +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB1_PWM NULL +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB2_PWM NULL +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB3_PWM NULL +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB4_PWM &OCR2A +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB5_PWM NULL +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB6_PWM NULL +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB +#define PB7_PWM &OCR0A + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC0_PWM NULL +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC1_PWM NULL +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC2_PWM NULL +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC3_PWM NULL +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC4_PWM NULL +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC5_PWM NULL +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC6_PWM NULL +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC +#define PC7_PWM NULL + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD0_PWM NULL +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD1_PWM NULL +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD2_PWM NULL +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD3_PWM NULL +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD4_PWM NULL +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD5_PWM NULL +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD6_PWM NULL +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD +#define PD7_PWM NULL + +#undef PE0 +#define PE0_PIN PINE0 +#define PE0_RPORT PINE +#define PE0_WPORT PORTE +#define PE0_DDR DDRE +#define PE0_PWM NULL +#undef PE1 +#define PE1_PIN PINE1 +#define PE1_RPORT PINE +#define PE1_WPORT PORTE +#define PE1_DDR DDRE +#define PE1_PWM NULL +#undef PE2 +#define PE2_PIN PINE2 +#define PE2_RPORT PINE +#define PE2_WPORT PORTE +#define PE2_DDR DDRE +#define PE2_PWM NULL +#undef PE3 +#define PE3_PIN PINE3 +#define PE3_RPORT PINE +#define PE3_WPORT PORTE +#define PE3_DDR DDRE +#define PE3_PWM &OCR3AL +#undef PE4 +#define PE4_PIN PINE4 +#define PE4_RPORT PINE +#define PE4_WPORT PORTE +#define PE4_DDR DDRE +#define PE4_PWM &OCR3BL +#undef PE5 +#define PE5_PIN PINE5 +#define PE5_RPORT PINE +#define PE5_WPORT PORTE +#define PE5_DDR DDRE +#define PE5_PWM &OCR3CL +#undef PE6 +#define PE6_PIN PINE6 +#define PE6_RPORT PINE +#define PE6_WPORT PORTE +#define PE6_DDR DDRE +#define PE6_PWM NULL +#undef PE7 +#define PE7_PIN PINE7 +#define PE7_RPORT PINE +#define PE7_WPORT PORTE +#define PE7_DDR DDRE +#define PE7_PWM NULL + +#undef PF0 +#define PF0_PIN PINF0 +#define PF0_RPORT PINF +#define PF0_WPORT PORTF +#define PF0_DDR DDRF +#define PF0_PWM NULL +#undef PF1 +#define PF1_PIN PINF1 +#define PF1_RPORT PINF +#define PF1_WPORT PORTF +#define PF1_DDR DDRF +#define PF1_PWM NULL +#undef PF2 +#define PF2_PIN PINF2 +#define PF2_RPORT PINF +#define PF2_WPORT PORTF +#define PF2_DDR DDRF +#define PF2_PWM NULL +#undef PF3 +#define PF3_PIN PINF3 +#define PF3_RPORT PINF +#define PF3_WPORT PORTF +#define PF3_DDR DDRF +#define PF3_PWM NULL +#undef PF4 +#define PF4_PIN PINF4 +#define PF4_RPORT PINF +#define PF4_WPORT PORTF +#define PF4_DDR DDRF +#define PF4_PWM NULL +#undef PF5 +#define PF5_PIN PINF5 +#define PF5_RPORT PINF +#define PF5_WPORT PORTF +#define PF5_DDR DDRF +#define PF5_PWM NULL +#undef PF6 +#define PF6_PIN PINF6 +#define PF6_RPORT PINF +#define PF6_WPORT PORTF +#define PF6_DDR DDRF +#define PF6_PWM NULL +#undef PF7 +#define PF7_PIN PINF7 +#define PF7_RPORT PINF +#define PF7_WPORT PORTF +#define PF7_DDR DDRF +#define PF7_PWM NULL + +#undef PG0 +#define PG0_PIN PING0 +#define PG0_RPORT PING +#define PG0_WPORT PORTG +#define PG0_DDR DDRG +#define PG0_PWM NULL +#undef PG1 +#define PG1_PIN PING1 +#define PG1_RPORT PING +#define PG1_WPORT PORTG +#define PG1_DDR DDRG +#define PG1_PWM NULL +#undef PG2 +#define PG2_PIN PING2 +#define PG2_RPORT PING +#define PG2_WPORT PORTG +#define PG2_DDR DDRG +#define PG2_PWM NULL +#undef PG3 +#define PG3_PIN PING3 +#define PG3_RPORT PING +#define PG3_WPORT PORTG +#define PG3_DDR DDRG +#define PG3_PWM NULL +#undef PG4 +#define PG4_PIN PING4 +#define PG4_RPORT PING +#define PG4_WPORT PORTG +#define PG4_DDR DDRG +#define PG4_PWM NULL +#undef PG5 +#define PG5_PIN PING5 +#define PG5_RPORT PING +#define PG5_WPORT PORTG +#define PG5_DDR DDRG +#define PG5_PWM &OCR0B +#undef PG6 +#define PG6_PIN PING6 +#define PG6_RPORT PING +#define PG6_WPORT PORTG +#define PG6_DDR DDRG +#define PG6_PWM NULL +#undef PG7 +#define PG7_PIN PING7 +#define PG7_RPORT PING +#define PG7_WPORT PORTG +#define PG7_DDR DDRG +#define PG7_PWM NULL + +#undef PH0 +#define PH0_PIN PINH0 +#define PH0_RPORT PINH +#define PH0_WPORT PORTH +#define PH0_DDR DDRH +#define PH0_PWM NULL +#undef PH1 +#define PH1_PIN PINH1 +#define PH1_RPORT PINH +#define PH1_WPORT PORTH +#define PH1_DDR DDRH +#define PH1_PWM NULL +#undef PH2 +#define PH2_PIN PINH2 +#define PH2_RPORT PINH +#define PH2_WPORT PORTH +#define PH2_DDR DDRH +#define PH2_PWM NULL +#undef PH3 +#define PH3_PIN PINH3 +#define PH3_RPORT PINH +#define PH3_WPORT PORTH +#define PH3_DDR DDRH +#define PH3_PWM &OCR4AL +#undef PH4 +#define PH4_PIN PINH4 +#define PH4_RPORT PINH +#define PH4_WPORT PORTH +#define PH4_DDR DDRH +#define PH4_PWM &OCR4BL +#undef PH5 +#define PH5_PIN PINH5 +#define PH5_RPORT PINH +#define PH5_WPORT PORTH +#define PH5_DDR DDRH +#define PH5_PWM &OCR4CL +#undef PH6 +#define PH6_PIN PINH6 +#define PH6_RPORT PINH +#define PH6_WPORT PORTH +#define PH6_DDR DDRH +#define PH6_PWM &OCR2B +#undef PH7 +#define PH7_PIN PINH7 +#define PH7_RPORT PINH +#define PH7_WPORT PORTH +#define PH7_DDR DDRH +#define PH7_PWM NULL + +#undef PJ0 +#define PJ0_PIN PINJ0 +#define PJ0_RPORT PINJ +#define PJ0_WPORT PORTJ +#define PJ0_DDR DDRJ +#define PJ0_PWM NULL +#undef PJ1 +#define PJ1_PIN PINJ1 +#define PJ1_RPORT PINJ +#define PJ1_WPORT PORTJ +#define PJ1_DDR DDRJ +#define PJ1_PWM NULL +#undef PJ2 +#define PJ2_PIN PINJ2 +#define PJ2_RPORT PINJ +#define PJ2_WPORT PORTJ +#define PJ2_DDR DDRJ +#define PJ2_PWM NULL +#undef PJ3 +#define PJ3_PIN PINJ3 +#define PJ3_RPORT PINJ +#define PJ3_WPORT PORTJ +#define PJ3_DDR DDRJ +#define PJ3_PWM NULL +#undef PJ4 +#define PJ4_PIN PINJ4 +#define PJ4_RPORT PINJ +#define PJ4_WPORT PORTJ +#define PJ4_DDR DDRJ +#define PJ4_PWM NULL +#undef PJ5 +#define PJ5_PIN PINJ5 +#define PJ5_RPORT PINJ +#define PJ5_WPORT PORTJ +#define PJ5_DDR DDRJ +#define PJ5_PWM NULL +#undef PJ6 +#define PJ6_PIN PINJ6 +#define PJ6_RPORT PINJ +#define PJ6_WPORT PORTJ +#define PJ6_DDR DDRJ +#define PJ6_PWM NULL +#undef PJ7 +#define PJ7_PIN PINJ7 +#define PJ7_RPORT PINJ +#define PJ7_WPORT PORTJ +#define PJ7_DDR DDRJ +#define PJ7_PWM NULL + +#undef PK0 +#define PK0_PIN PINK0 +#define PK0_RPORT PINK +#define PK0_WPORT PORTK +#define PK0_DDR DDRK +#define PK0_PWM NULL +#undef PK1 +#define PK1_PIN PINK1 +#define PK1_RPORT PINK +#define PK1_WPORT PORTK +#define PK1_DDR DDRK +#define PK1_PWM NULL +#undef PK2 +#define PK2_PIN PINK2 +#define PK2_RPORT PINK +#define PK2_WPORT PORTK +#define PK2_DDR DDRK +#define PK2_PWM NULL +#undef PK3 +#define PK3_PIN PINK3 +#define PK3_RPORT PINK +#define PK3_WPORT PORTK +#define PK3_DDR DDRK +#define PK3_PWM NULL +#undef PK4 +#define PK4_PIN PINK4 +#define PK4_RPORT PINK +#define PK4_WPORT PORTK +#define PK4_DDR DDRK +#define PK4_PWM NULL +#undef PK5 +#define PK5_PIN PINK5 +#define PK5_RPORT PINK +#define PK5_WPORT PORTK +#define PK5_DDR DDRK +#define PK5_PWM NULL +#undef PK6 +#define PK6_PIN PINK6 +#define PK6_RPORT PINK +#define PK6_WPORT PORTK +#define PK6_DDR DDRK +#define PK6_PWM NULL +#undef PK7 +#define PK7_PIN PINK7 +#define PK7_RPORT PINK +#define PK7_WPORT PORTK +#define PK7_DDR DDRK +#define PK7_PWM NULL + +#undef PL0 +#define PL0_PIN PINL0 +#define PL0_RPORT PINL +#define PL0_WPORT PORTL +#define PL0_DDR DDRL +#define PL0_PWM NULL +#undef PL1 +#define PL1_PIN PINL1 +#define PL1_RPORT PINL +#define PL1_WPORT PORTL +#define PL1_DDR DDRL +#define PL1_PWM NULL +#undef PL2 +#define PL2_PIN PINL2 +#define PL2_RPORT PINL +#define PL2_WPORT PORTL +#define PL2_DDR DDRL +#define PL2_PWM NULL +#undef PL3 +#define PL3_PIN PINL3 +#define PL3_RPORT PINL +#define PL3_WPORT PORTL +#define PL3_DDR DDRL +#define PL3_PWM &OCR5AL +#undef PL4 +#define PL4_PIN PINL4 +#define PL4_RPORT PINL +#define PL4_WPORT PORTL +#define PL4_DDR DDRL +#define PL4_PWM &OCR5BL +#undef PL5 +#define PL5_PIN PINL5 +#define PL5_RPORT PINL +#define PL5_WPORT PORTL +#define PL5_DDR DDRL +#define PL5_PWM &OCR5CL +#undef PL6 +#define PL6_PIN PINL6 +#define PL6_RPORT PINL +#define PL6_WPORT PORTL +#define PL6_DDR DDRL +#define PL6_PWM NULL +#undef PL7 +#define PL7_PIN PINL7 +#define PL7_RPORT PINL +#define PL7_WPORT PORTL +#define PL7_DDR DDRL +#define PL7_PWM NULL + +#endif + +#if defined (__AVR_AT90USB1287__) +// SPI +#define SCK DIO9 +#define MISO DIO11 +#define MOSI DIO10 +#define SS DIO8 + +// change for your board +#define DEBUG_LED DIO31 /* led D5 red */ + +/* +pins +*/ +#define DIO0_PIN PINA0 +#define DIO0_RPORT PINA +#define DIO0_WPORT PORTA +#define DIO0_PWM NULL +#define DIO0_DDR DDRA + +#define DIO1_PIN PINA1 +#define DIO1_RPORT PINA +#define DIO1_WPORT PORTA +#define DIO1_PWM NULL +#define DIO1_DDR DDRA + +#define DIO2_PIN PINA2 +#define DIO2_RPORT PINA +#define DIO2_WPORT PORTA +#define DIO2_PWM NULL +#define DIO2_DDR DDRA + +#define DIO3_PIN PINA3 +#define DIO3_RPORT PINA +#define DIO3_WPORT PORTA +#define DIO3_PWM NULL +#define DIO3_DDR DDRA + +#define DIO4_PIN PINA4 +#define DIO4_RPORT PINA +#define DIO4_WPORT PORTA +#define DIO4_PWM NULL +#define DIO4_DDR DDRA + +#define DIO5_PIN PINA5 +#define DIO5_RPORT PINA +#define DIO5_WPORT PORTA +#define DIO5_PWM NULL +#define DIO5_DDR DDRA + +#define DIO6_PIN PINA6 +#define DIO6_RPORT PINA +#define DIO6_WPORT PORTA +#define DIO6_PWM NULL +#define DIO6_DDR DDRA + +#define DIO7_PIN PINA7 +#define DIO7_RPORT PINA +#define DIO7_WPORT PORTA +#define DIO7_PWM NULL +#define DIO7_DDR DDRA + +#define DIO8_PIN PINB0 +#define DIO8_RPORT PINB +#define DIO8_WPORT PORTB +#define DIO8_PWM NULL +#define DIO8_DDR DDRB + +#define DIO9_PIN PINB1 +#define DIO9_RPORT PINB +#define DIO9_WPORT PORTB +#define DIO9_PWM NULL +#define DIO9_DDR DDRB + +#define DIO10_PIN PINB2 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_PWM NULL +#define DIO10_DDR DDRB + +#define DIO11_PIN PINB3 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_PWM NULL +#define DIO11_DDR DDRB + +#define DIO12_PIN PINB4 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_PWM NULL +#define DIO12_DDR DDRB + +#define DIO13_PIN PINB5 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_PWM NULL +#define DIO13_DDR DDRB + +#define DIO14_PIN PINB6 +#define DIO14_RPORT PINB +#define DIO14_WPORT PORTB +#define DIO14_PWM NULL +#define DIO14_DDR DDRB + +#define DIO15_PIN PINB7 +#define DIO15_RPORT PINB +#define DIO15_WPORT PORTB +#define DIO15_PWM NULL +#define DIO15_DDR DDRB + +#define DIO16_PIN PINC0 +#define DIO16_RPORT PINC +#define DIO16_WPORT PORTC +#define DIO16_PWM NULL +#define DIO16_DDR DDRC + +#define DIO17_PIN PINC1 +#define DIO17_RPORT PINC +#define DIO17_WPORT PORTC +#define DIO17_PWM NULL +#define DIO17_DDR DDRC + +#define DIO18_PIN PINC2 +#define DIO18_RPORT PINC +#define DIO18_WPORT PORTC +#define DIO18_PWM NULL +#define DIO18_DDR DDRC + +#define DIO19_PIN PINC3 +#define DIO19_RPORT PINC +#define DIO19_WPORT PORTC +#define DIO19_PWM NULL +#define DIO19_DDR DDRC + +#define DIO20_PIN PINC4 +#define DIO20_RPORT PINC +#define DIO20_WPORT PORTC +#define DIO20_PWM NULL +#define DIO20_DDR DDRC + +#define DIO21_PIN PINC5 +#define DIO21_RPORT PINC +#define DIO21_WPORT PORTC +#define DIO21_PWM NULL +#define DIO21_DDR DDRC + +#define DIO22_PIN PINC6 +#define DIO22_RPORT PINC +#define DIO22_WPORT PORTC +#define DIO22_PWM NULL +#define DIO22_DDR DDRC + +#define DIO23_PIN PINC7 +#define DIO23_RPORT PINC +#define DIO23_WPORT PORTC +#define DIO23_PWM NULL +#define DIO23_DDR DDRC + +#define DIO24_PIN PIND0 +#define DIO24_RPORT PIND +#define DIO24_WPORT PORTD +#define DIO24_PWM NULL +#define DIO24_DDR DDRD + +#define DIO25_PIN PIND1 +#define DIO25_RPORT PIND +#define DIO25_WPORT PORTD +#define DIO25_PWM NULL +#define DIO25_DDR DDRD + +#define DIO26_PIN PIND2 +#define DIO26_RPORT PIND +#define DIO26_WPORT PORTD +#define DIO26_PWM NULL +#define DIO26_DDR DDRD + +#define DIO27_PIN PIND3 +#define DIO27_RPORT PIND +#define DIO27_WPORT PORTD +#define DIO27_PWM NULL +#define DIO27_DDR DDRD + +#define DIO28_PIN PIND4 +#define DIO28_RPORT PIND +#define DIO28_WPORT PORTD +#define DIO28_PWM NULL +#define DIO28_DDR DDRD + +#define DIO29_PIN PIND5 +#define DIO29_RPORT PIND +#define DIO29_WPORT PORTD +#define DIO29_PWM NULL +#define DIO29_DDR DDRD + +#define DIO30_PIN PIND6 +#define DIO30_RPORT PIND +#define DIO30_WPORT PORTD +#define DIO30_PWM NULL +#define DIO30_DDR DDRD + +#define DIO31_PIN PIND7 +#define DIO31_RPORT PIND +#define DIO31_WPORT PORTD +#define DIO31_PWM NULL +#define DIO31_DDR DDRD + + +#define DIO32_PIN PINE0 +#define DIO32_RPORT PINE +#define DIO32_WPORT PORTE +#define DIO32_PWM NULL +#define DIO32_DDR DDRE + +#define DIO33_PIN PINE1 +#define DIO33_RPORT PINE +#define DIO33_WPORT PORTE +#define DIO33_PWM NULL +#define DIO33_DDR DDRE + +#define DIO34_PIN PINE2 +#define DIO34_RPORT PINE +#define DIO34_WPORT PORTE +#define DIO34_PWM NULL +#define DIO34_DDR DDRE + +#define DIO35_PIN PINE3 +#define DIO35_RPORT PINE +#define DIO35_WPORT PORTE +#define DIO35_PWM NULL +#define DIO35_DDR DDRE + +#define DIO36_PIN PINE4 +#define DIO36_RPORT PINE +#define DIO36_WPORT PORTE +#define DIO36_PWM NULL +#define DIO36_DDR DDRE + +#define DIO37_PIN PINE5 +#define DIO37_RPORT PINE +#define DIO37_WPORT PORTE +#define DIO37_PWM NULL +#define DIO37_DDR DDRE + +#define DIO38_PIN PINE6 +#define DIO38_RPORT PINE +#define DIO38_WPORT PORTE +#define DIO38_PWM NULL +#define DIO38_DDR DDRE + +#define DIO39_PIN PINE7 +#define DIO39_RPORT PINE +#define DIO39_WPORT PORTE +#define DIO39_PWM NULL +#define DIO39_DDR DDRE + +#define AIO0_PIN PINF0 +#define AIO0_RPORT PINF +#define AIO0_WPORT PORTF +#define AIO0_PWM NULL +#define AIO0_DDR DDRF + +#define AIO1_PIN PINF1 +#define AIO1_RPORT PINF +#define AIO1_WPORT PORTF +#define AIO1_PWM NULL +#define AIO1_DDR DDRF + +#define AIO2_PIN PINF2 +#define AIO2_RPORT PINF +#define AIO2_WPORT PORTF +#define AIO2_PWM NULL +#define AIO2_DDR DDRF + +#define AIO3_PIN PINF3 +#define AIO3_RPORT PINF +#define AIO3_WPORT PORTF +#define AIO3_PWM NULL +#define AIO3_DDR DDRF + +#define AIO4_PIN PINF4 +#define AIO4_RPORT PINF +#define AIO4_WPORT PORTF +#define AIO4_PWM NULL +#define AIO4_DDR DDRF + +#define AIO5_PIN PINF5 +#define AIO5_RPORT PINF +#define AIO5_WPORT PORTF +#define AIO5_PWM NULL +#define AIO5_DDR DDRF + +#define AIO6_PIN PINF6 +#define AIO6_RPORT PINF +#define AIO6_WPORT PORTF +#define AIO6_PWM NULL +#define AIO6_DDR DDRF + +#define AIO7_PIN PINF7 +#define AIO7_RPORT PINF +#define AIO7_WPORT PORTF +#define AIO7_PWM NULL +#define AIO7_DDR DDRF + +#define DIO40_PIN PINF0 +#define DIO40_RPORT PINF +#define DIO40_WPORT PORTF +#define DIO40_PWM NULL +#define DIO40_DDR DDRF + +#define DIO41_PIN PINF1 +#define DIO41_RPORT PINF +#define DIO41_WPORT PORTF +#define DIO41_PWM NULL +#define DIO41_DDR DDRF + +#define DIO42_PIN PINF2 +#define DIO42_RPORT PINF +#define DIO42_WPORT PORTF +#define DIO42_PWM NULL +#define DIO42_DDR DDRF + +#define DIO43_PIN PINF3 +#define DIO43_RPORT PINF +#define DIO43_WPORT PORTF +#define DIO43_PWM NULL +#define DIO43_DDR DDRF + +#define DIO44_PIN PINF4 +#define DIO44_RPORT PINF +#define DIO44_WPORT PORTF +#define DIO44_PWM NULL +#define DIO44_DDR DDRF + +#define DIO45_PIN PINF5 +#define DIO45_RPORT PINF +#define DIO45_WPORT PORTF +#define DIO45_PWM NULL +#define DIO45_DDR DDRF + +#define DIO46_PIN PINF6 +#define DIO46_RPORT PINF +#define DIO46_WPORT PORTF +#define DIO46_PWM NULL +#define DIO46_DDR DDRF + +#define DIO47_PIN PINF7 +#define DIO47_RPORT PINF +#define DIO47_WPORT PORTF +#define DIO47_PWM NULL +#define DIO47_DDR DDRF + + + +#undef PA0 +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_PWM NULL +#define PA0_DDR DDRA +#undef PA1 +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_PWM NULL +#define PA1_DDR DDRA +#undef PA2 +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_PWM NULL +#define PA2_DDR DDRA +#undef PA3 +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_PWM NULL +#define PA3_DDR DDRA +#undef PA4 +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_PWM NULL +#define PA4_DDR DDRA +#undef PA5 +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_PWM NULL +#define PA5_DDR DDRA +#undef PA6 +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_PWM NULL +#define PA6_DDR DDRA +#undef PA7 +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_PWM NULL +#define PA7_DDR DDRA + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_PWM NULL +#define PB0_DDR DDRB +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_PWM NULL +#define PB1_DDR DDRB +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_PWM NULL +#define PB2_DDR DDRB +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_PWM NULL +#define PB3_DDR DDRB +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_PWM NULL +#define PB4_DDR DDRB +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_PWM NULL +#define PB5_DDR DDRB +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_PWM NULL +#define PB6_DDR DDRB +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_PWM NULL +#define PB7_DDR DDRB + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_PWM NULL +#define PC0_DDR DDRC +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_PWM NULL +#define PC1_DDR DDRC +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_PWM NULL +#define PC2_DDR DDRC +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_PWM NULL +#define PC3_DDR DDRC +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_PWM NULL +#define PC4_DDR DDRC +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_PWM NULL +#define PC5_DDR DDRC +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_PWM NULL +#define PC6_DDR DDRC +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_PWM NULL +#define PC7_DDR DDRC + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_PWM NULL +#define PD0_DDR DDRD +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_PWM NULL +#define PD1_DDR DDRD +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_PWM NULL +#define PD2_DDR DDRD +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_PWM NULL +#define PD3_DDR DDRD +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_PWM NULL +#define PD4_DDR DDRD +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_PWM NULL +#define PD5_DDR DDRD +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_PWM NULL +#define PD6_DDR DDRD +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_PWM NULL +#define PD7_DDR DDRD + +#undef PE0 +#define PE0_PIN PINE0 +#define PE0_RPORT PINE +#define PE0_WPORT PORTE +#define PE0_PWM NULL +#define PE0_DDR DDRE +#undef PE1 +#define PE1_PIN PINE1 +#define PE1_RPORT PINE +#define PE1_WPORT PORTE +#define PE1_PWM NULL +#define PE1_DDR DDRE +#undef PE2 +#define PE2_PIN PINE2 +#define PE2_RPORT PINE +#define PE2_WPORT PORTE +#define PE2_PWM NULL +#define PE2_DDR DDRE +#undef PE3 +#define PE3_PIN PINE3 +#define PE3_RPORT PINE +#define PE3_WPORT PORTE +#define PE3_PWM NULL +#define PE3_DDR DDRE +#undef PE4 +#define PE4_PIN PINE4 +#define PE4_RPORT PINE +#define PE4_WPORT PORTE +#define PE4_PWM NULL +#define PE4_DDR DDRE +#undef PE5 +#define PE5_PIN PINE5 +#define PE5_RPORT PINE +#define PE5_WPORT PORTE +#define PE5_PWM NULL +#define PE5_DDR DDRE +#undef PE6 +#define PE6_PIN PINE6 +#define PE6_RPORT PINE +#define PE6_WPORT PORTE +#define PE6_PWM NULL +#define PE6_DDR DDRE +#undef PE7 +#define PE7_PIN PINE7 +#define PE7_RPORT PINE +#define PE7_WPORT PORTE +#define PE7_PWM NULL +#define PE7_DDR DDRE + +#undef PF0 +#define PF0_PIN PINF0 +#define PF0_RPORT PINF +#define PF0_WPORT PORTF +#define PF0_PWM NULL +#define PF0_DDR DDRF +#undef PF1 +#define PF1_PIN PINF1 +#define PF1_RPORT PINF +#define PF1_WPORT PORTF +#define PF1_PWM NULL +#define PF1_DDR DDRF +#undef PF2 +#define PF2_PIN PINF2 +#define PF2_RPORT PINF +#define PF2_WPORT PORTF +#define PF2_PWM NULL +#define PF2_DDR DDRF +#undef PF3 +#define PF3_PIN PINF3 +#define PF3_RPORT PINF +#define PF3_WPORT PORTF +#define PF3_PWM NULL +#define PF3_DDR DDRF +#undef PF4 +#define PF4_PIN PINF4 +#define PF4_RPORT PINF +#define PF4_WPORT PORTF +#define PF4_PWM NULL +#define PF4_DDR DDRF +#undef PF5 +#define PF5_PIN PINF5 +#define PF5_RPORT PINF +#define PF5_WPORT PORTF +#define PF5_PWM NULL +#define PF5_DDR DDRF +#undef PF6 +#define PF6_PIN PINF6 +#define PF6_RPORT PINF +#define PF6_WPORT PORTF +#define PF6_PWM NULL +#define PF6_DDR DDRF +#undef PF7 +#define PF7_PIN PINF7 +#define PF7_RPORT PINF +#define PF7_WPORT PORTF +#define PF7_PWM NULL +#define PF7_DDR DDRF +#endif + +#ifndef DIO0_PIN +#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request +#endif + #endif /* _ARDUINO_H */ diff --git a/Marlin/pins.h b/Marlin/pins.h index 1e2fd65fd2..e9ebd4412c 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -1,570 +1,570 @@ -#ifndef PINS_H -#define PINS_H - -/**************************************************************************************** -* Arduino pin assignment -* -* ATMega168 -* +-\/-+ -* PC6 1| |28 PC5 (AI 5 / D19) -* (D 0) PD0 2| |27 PC4 (AI 4 / D18) -* (D 1) PD1 3| |26 PC3 (AI 3 / D17) -* (D 2) PD2 4| |25 PC2 (AI 2 / D16) -* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) -* (D 4) PD4 6| |23 PC0 (AI 0 / D14) -* VCC 7| |22 GND -* GND 8| |21 AREF -* PB6 9| |20 AVCC -* PB7 10| |19 PB5 (D 13) -* PWM+ (D 5) PD5 11| |18 PB4 (D 12) -* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -* (D 7) PD7 13| |16 PB2 (D 10) PWM -* (D 8) PB0 14| |15 PB1 (D 9) PWM -* +----+ -****************************************************************************************/ -#if MOTHERBOARD == 0 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega168__ -#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. -#endif - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 4 -#define X_MAX_PIN 9 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN 13 - -#define Z_STEP_PIN 19 -#define Z_DIR_PIN 18 -#define Z_ENABLE_PIN 5 -#define Z_MIN_PIN 17 -#define Z_MAX_PIN 16 - -#define E_STEP_PIN 11 -#define E_DIR_PIN 12 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 15 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#endif - - - -/**************************************************************************************** -* Sanguino/RepRap Motherboard with direct-drive extruders -* -* ATMega644P -* -* +---\/---+ -* (D 0) PB0 1| |40 PA0 (AI 0 / D31) -* (D 1) PB1 2| |39 PA1 (AI 1 / D30) -* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) -* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) -* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) -* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) -* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) -* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) -* RST 9| |32 AREF -* VCC 10| |31 GND -* GND 11| |30 AVCC -* XTAL2 12| |29 PC7 (D 23) -* XTAL1 13| |28 PC6 (D 22) -* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI -* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO -* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS -* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK -* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA -* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL -* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM -* +--------+ -* -****************************************************************************************/ -#if MOTHERBOARD == 1 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 19 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PIN 29 -#define Z_DIR_PIN 30 -#define Z_ENABLE_PIN 31 -#define Z_MIN_PIN 2 -#define Z_MAX_PIN 1 - -#define E_STEP_PIN 12 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN 3 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN 0 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 14 -#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ - - - -#endif - - -/**************************************************************************************** -* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* -* -****************************************************************************************/ -#if MOTHERBOARD == 2 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PINN 27 -#define Z_DIR_PINN 28 -#define Z_ENABLE_PIN 29 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 31 - -#define E_STEP_PIN 17 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 4 -#define LED_PIN 0 - -#define SD_CARD_WRITE 2 -#define SD_CARD_DETECT 3 -#define SD_CARD_SELECT 4 - -//our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 - -//pin for controlling the PSU. -#define PS_ON_PIN 14 - -#define FAN_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN -1 -#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - - - -#endif - -/**************************************************************************************** -* Arduino Mega pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 33 -#define MOTHERBOARD 3 -#define RAMPS_V_1_3 -#endif -#if MOTHERBOARD == 3 -#define KNOWN_BOARD 1 - -//////////////////FIX THIS////////////// -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 -// #define RAMPS_V_1_3 -// #define RAMPS_V_1_0 - -#ifdef RAMPS_V_1_3 - -#define X_STEP_PIN 54 -#define X_DIR_PIN 55 -#define X_ENABLE_PIN 38 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. - -#define Y_STEP_PIN 60 -#define Y_DIR_PIN 61 -#define Y_ENABLE_PIN 56 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 //15 - -#define Z_STEP_PIN 46 -#define Z_DIR_PIN 48 -#define Z_ENABLE_PIN 62 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E_STEP_PIN 26 -#define E_DIR_PIN 28 -#define E_ENABLE_PIN 24 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 9 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#define HEATER_0_PIN 10 -#define HEATER_1_PIN 8 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 14 // ANALOG NUMBERING -#define TEMP_2_PIN -1 // ANALOG NUMBERING - - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default - -#define X_STEP_PIN 26 -#define X_DIR_PIN 28 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 - -#define Y_STEP_PIN 38 -#define Y_DIR_PIN 40 -#define Y_ENABLE_PIN 36 -#define Y_MIN_PIN 16 -#define Y_MAX_PIN -1 //17 - -#define Z_STEP_PIN 44 -#define Z_DIR_PIN 46 -#define Z_ENABLE_PIN 42 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E_STEP_PIN 32 -#define E_DIR_PIN 34 -#define E_ENABLE_PIN 30 - -#define SDPOWER 48 -#define SDSS 53 -#define LED_PIN 13 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - - - -#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 - #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_1_PIN -1 // RAMPS 1.0 - #define FAN_PIN 11 // RAMPS 1.0 - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 - #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_1_PIN 8 // RAMPS 1.1 - #define FAN_PIN 9 // RAMPS 1.1 -#endif -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#endif - -// SPI for Max6675 Thermocouple - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 - #define MISO_PIN 50 - #define MOSI_PIN 51 - #define MAX6675_SS 53 -#else - #define MAX6675_SS 49 -#endif - - -#endif -/**************************************************************************************** -* Duemilanove w/ ATMega328P pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 4 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega328P__ -#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 17 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 13 -#define Z_DIR_PIN 3 -#define Z_ENABLE_PIN 2 -#define Z_MIN_PIN 4 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 11 -#define E_DIR_PIN 12 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN 5 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - -#endif - -/**************************************************************************************** -* Gen6 pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 5 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ - #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -//x axis pins - #define X_STEP_PIN 15 - #define X_DIR_PIN 18 - #define X_ENABLE_PIN 19 - #define X_MIN_PIN 20 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 25 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 27 - #define Z_DIR_PIN 28 - #define Z_ENABLE_PIN 29 - #define Z_MIN_PIN 30 - #define Z_MAX_PIN -1 - - //extruder pins - #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 - #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 - #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_2_PIN -1 - - #define SDPOWER -1 - #define SDSS 17 - #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_2_PIN -1 - #define FAN_PIN -1 //changed @ rkoeppl 20110410 - #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 - //our pin for debugging. - - #define DEBUG_PIN 0 - - //our RS485 pins - #define TX_ENABLE_PIN 12 - #define RX_ENABLE_PIN 13 - -#endif - -/**************************************************************************************** -* Sanguinololu pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 62 -#define MOTHERBOARD 6 -#define SANGUINOLOLU_V_1_2 -#endif -#if MOTHERBOARD == 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 21 -#define X_MIN_PIN 18 -#define X_MAX_PIN -2 - -#define Y_STEP_PIN 22 -#define Y_DIR_PIN 23 -#define Y_MIN_PIN 19 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 3 -#define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 1 -#define E_DIR_PIN 0 - -#define LED_PIN -1 - -#define FAN_PIN -1 - -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 // (extruder) - -#ifdef SANGUINOLOLU_V_1_2 - -#define HEATER_1_PIN 12 // (bed) -#define X_ENABLE_PIN 14 -#define Y_ENABLE_PIN 14 -#define Z_ENABLE_PIN 26 -#define E_ENABLE_PIN 14 - -#else - -#define HEATER_1_PIN 14 // (bed) -#define X_ENABLE_PIN -1 -#define Y_ENABLE_PIN -1 -#define Z_ENABLE_PIN -1 -#define E_ENABLE_PIN -1 - -#endif - -#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define TEMP_2_PIN -1 -#define SDPOWER -1 -#define SDSS 31 -#define HEATER_2_PIN -1 - -#endif - - -#if MOTHERBOARD == 7 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 22 -#define X_MAX_PIN 24 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 26 -#define Y_MAX_PIN 28 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 32 -#define Z_ENABLE_PIN 35 - -#define HEATER_1_PIN 4 -#define TEMP_1_PIN 11 - -#define EXTRUDER_0_STEP_PIN 43 -#define EXTRUDER_0_DIR_PIN 45 -#define EXTRUDER_0_ENABLE_PIN 41 -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define EXTRUDER_1_STEP_PIN 49 -#define EXTRUDER_1_DIR_PIN 47 -#define EXTRUDER_1_ENABLE_PIN 51 -#define EXTRUDER_1_HEATER_PIN 3 -#define EXTRUDER_1_TEMPERATURE_PIN 10 -#define HEATER_2_PIN 51 -#define TEMP_2_PIN 3 - - - -#define E_STEP_PIN EXTRUDER_0_STEP_PIN -#define E_DIR_PIN EXTRUDER_0_DIR_PIN -#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 7 -#define PS_ON_PIN 12 -#define KILL_PIN -1 -#endif - - -#ifndef KNOWN_BOARD -#error Unknown MOTHERBOARD value in configuration.h -#endif - -//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} - -#endif +#ifndef PINS_H +#define PINS_H + +/**************************************************************************************** +* Arduino pin assignment +* +* ATMega168 +* +-\/-+ +* PC6 1| |28 PC5 (AI 5 / D19) +* (D 0) PD0 2| |27 PC4 (AI 4 / D18) +* (D 1) PD1 3| |26 PC3 (AI 3 / D17) +* (D 2) PD2 4| |25 PC2 (AI 2 / D16) +* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) +* (D 4) PD4 6| |23 PC0 (AI 0 / D14) +* VCC 7| |22 GND +* GND 8| |21 AREF +* PB6 9| |20 AVCC +* PB7 10| |19 PB5 (D 13) +* PWM+ (D 5) PD5 11| |18 PB4 (D 12) +* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +* (D 7) PD7 13| |16 PB2 (D 10) PWM +* (D 8) PB0 14| |15 PB1 (D 9) PWM +* +----+ +****************************************************************************************/ +#if MOTHERBOARD == 0 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega168__ +#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. +#endif + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 4 +#define X_MAX_PIN 9 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN 13 + +#define Z_STEP_PIN 19 +#define Z_DIR_PIN 18 +#define Z_ENABLE_PIN 5 +#define Z_MIN_PIN 17 +#define Z_MAX_PIN 16 + +#define E_STEP_PIN 11 +#define E_DIR_PIN 12 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 15 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#endif + + + +/**************************************************************************************** +* Sanguino/RepRap Motherboard with direct-drive extruders +* +* ATMega644P +* +* +---\/---+ +* (D 0) PB0 1| |40 PA0 (AI 0 / D31) +* (D 1) PB1 2| |39 PA1 (AI 1 / D30) +* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +* RST 9| |32 AREF +* VCC 10| |31 GND +* GND 11| |30 AVCC +* XTAL2 12| |29 PC7 (D 23) +* XTAL1 13| |28 PC6 (D 22) +* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +* +--------+ +* +****************************************************************************************/ +#if MOTHERBOARD == 1 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 19 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PIN 29 +#define Z_DIR_PIN 30 +#define Z_ENABLE_PIN 31 +#define Z_MIN_PIN 2 +#define Z_MAX_PIN 1 + +#define E_STEP_PIN 12 +#define E_DIR_PIN 16 +#define E_ENABLE_PIN 3 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN 0 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 14 +#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ + + + +#endif + + +/**************************************************************************************** +* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* +* +****************************************************************************************/ +#if MOTHERBOARD == 2 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PINN 27 +#define Z_DIR_PINN 28 +#define Z_ENABLE_PIN 29 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 31 + +#define E_STEP_PIN 17 +#define E_DIR_PIN 16 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 4 +#define LED_PIN 0 + +#define SD_CARD_WRITE 2 +#define SD_CARD_DETECT 3 +#define SD_CARD_SELECT 4 + +//our RS485 pins +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 + +//pin for controlling the PSU. +#define PS_ON_PIN 14 + +#define FAN_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN -1 +#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + + + +#endif + +/**************************************************************************************** +* Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 33 +#define MOTHERBOARD 3 +#define RAMPS_V_1_3 +#endif +#if MOTHERBOARD == 3 +#define KNOWN_BOARD 1 + +//////////////////FIX THIS////////////// +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 +// #define RAMPS_V_1_3 +// #define RAMPS_V_1_0 + +#ifdef RAMPS_V_1_3 + +#define X_STEP_PIN 54 +#define X_DIR_PIN 55 +#define X_ENABLE_PIN 38 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. + +#define Y_STEP_PIN 60 +#define Y_DIR_PIN 61 +#define Y_ENABLE_PIN 56 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 //15 + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 62 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E_STEP_PIN 26 +#define E_DIR_PIN 28 +#define E_ENABLE_PIN 24 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 9 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#define HEATER_0_PIN 10 +#define HEATER_1_PIN 8 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 13 // ANALOG NUMBERING +#define TEMP_1_PIN 14 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING + + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default + +#define X_STEP_PIN 26 +#define X_DIR_PIN 28 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 + +#define Y_STEP_PIN 38 +#define Y_DIR_PIN 40 +#define Y_ENABLE_PIN 36 +#define Y_MIN_PIN 16 +#define Y_MAX_PIN -1 //17 + +#define Z_STEP_PIN 44 +#define Z_DIR_PIN 46 +#define Z_ENABLE_PIN 42 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E_STEP_PIN 32 +#define E_DIR_PIN 34 +#define E_ENABLE_PIN 30 + +#define SDPOWER 48 +#define SDSS 53 +#define LED_PIN 13 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + + + +#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 + #define HEATER_0_PIN 12 // RAMPS 1.0 + #define HEATER_1_PIN -1 // RAMPS 1.0 + #define FAN_PIN 11 // RAMPS 1.0 + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 + #define HEATER_0_PIN 10 // RAMPS 1.1 + #define HEATER_1_PIN 8 // RAMPS 1.1 + #define FAN_PIN 9 // RAMPS 1.1 +#endif +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#endif + +// SPI for Max6675 Thermocouple + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 + #define MISO_PIN 50 + #define MOSI_PIN 51 + #define MAX6675_SS 53 +#else + #define MAX6675_SS 49 +#endif + + +#endif +/**************************************************************************************** +* Duemilanove w/ ATMega328P pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 4 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega328P__ +#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 17 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 13 +#define Z_DIR_PIN 3 +#define Z_ENABLE_PIN 2 +#define Z_MIN_PIN 4 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 11 +#define E_DIR_PIN 12 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN 5 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#endif + +/**************************************************************************************** +* Gen6 pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 5 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ + #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +//x axis pins + #define X_STEP_PIN 15 + #define X_DIR_PIN 18 + #define X_ENABLE_PIN 19 + #define X_MIN_PIN 20 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 25 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 27 + #define Z_DIR_PIN 28 + #define Z_ENABLE_PIN 29 + #define Z_MIN_PIN 30 + #define Z_MAX_PIN -1 + + //extruder pins + #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 + #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 + #define HEATER_2_PIN -1 + + #define SDPOWER -1 + #define SDSS 17 + #define LED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 + #define FAN_PIN -1 //changed @ rkoeppl 20110410 + #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 + //our pin for debugging. + + #define DEBUG_PIN 0 + + //our RS485 pins + #define TX_ENABLE_PIN 12 + #define RX_ENABLE_PIN 13 + +#endif + +/**************************************************************************************** +* Sanguinololu pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 62 +#define MOTHERBOARD 6 +#define SANGUINOLOLU_V_1_2 +#endif +#if MOTHERBOARD == 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -2 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 1 +#define E_DIR_PIN 0 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) + +#ifdef SANGUINOLOLU_V_1_2 + +#define HEATER_1_PIN 12 // (bed) +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E_ENABLE_PIN 14 + +#else + +#define HEATER_1_PIN 14 // (bed) +#define X_ENABLE_PIN -1 +#define Y_ENABLE_PIN -1 +#define Z_ENABLE_PIN -1 +#define E_ENABLE_PIN -1 + +#endif + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 31 +#define HEATER_2_PIN -1 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_1_PIN 4 +#define TEMP_1_PIN 11 + +#define EXTRUDER_0_STEP_PIN 43 +#define EXTRUDER_0_DIR_PIN 45 +#define EXTRUDER_0_ENABLE_PIN 41 +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define EXTRUDER_1_STEP_PIN 49 +#define EXTRUDER_1_DIR_PIN 47 +#define EXTRUDER_1_ENABLE_PIN 51 +#define EXTRUDER_1_HEATER_PIN 3 +#define EXTRUDER_1_TEMPERATURE_PIN 10 +#define HEATER_2_PIN 51 +#define TEMP_2_PIN 3 + + + +#define E_STEP_PIN EXTRUDER_0_STEP_PIN +#define E_DIR_PIN EXTRUDER_0_DIR_PIN +#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 +#endif + + +#ifndef KNOWN_BOARD +#error Unknown MOTHERBOARD value in configuration.h +#endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} + +#endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index f0ca298214..14f0bb1043 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -1,398 +1,398 @@ -/* - planner.c - buffers movement commands and manages the acceleration profile plan - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ - -/* - Reasoning behind the mathematics in this module (in the key of 'Mathematica'): - - s == speed, a == acceleration, t == time, d == distance - - Basic definitions: - - Speed[s_, a_, t_] := s + (a*t) - Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] - - Distance to reach a specific speed with a constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] - d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() - - Speed after a given distance of travel with constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] - m -> Sqrt[2 a d + s^2] - - DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] - - When to start braking (di) to reach a specified destionation speed (s2) after accelerating - from initial speed s1 without ever stopping at a plateau: - - Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] - di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() - - IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) -*/ - - -//#include -//#include -//#include - -#include "Marlin.h" -#include "Configuration.h" -#include "pins.h" -#include "fastio.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" -#include "ultralcd.h" - -unsigned long minsegmenttime; -float max_feedrate[4]; // set the max speeds -float axis_steps_per_unit[4]; -long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -float minimumfeedrate; -float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -float max_z_jerk; -float mintravelfeedrate; -unsigned long axis_steps_per_sqr_second[NUM_AXIS]; -// Manage heater variables. - -static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions -static volatile unsigned char block_buffer_head; // Index of the next block to be pushed -static volatile unsigned char block_buffer_tail; // Index of the block to process now - -// The current position of the tool in absolute steps - long position[4]; - -#define ONE_MINUTE_OF_MICROSECONDS 60000000.0 - -// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the -// given acceleration: -inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { - if (acceleration!=0) { - return((target_rate*target_rate-initial_rate*initial_rate)/ - (2.0*acceleration)); - } - else { - return 0.0; // acceleration was 0, set acceleration distance to 0 - } -} - -// This function gives you the point at which you must start braking (at the rate of -acceleration) if -// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after -// a total travel of distance. This can be used to compute the intersection point between acceleration and -// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) - -inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { - if (acceleration!=0) { - return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ - (4.0*acceleration) ); - } - else { - return 0.0; // acceleration was 0, set intersection distance to 0 - } -} - -// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. - -void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit_speed) { - if(block->busy == true) return; // If block is busy then bail out. - float entry_factor = entry_speed / block->nominal_speed; - float exit_factor = exit_speed / block->nominal_speed; - long initial_rate = ceil(block->nominal_rate*entry_factor); - long final_rate = ceil(block->nominal_rate*exit_factor); - -#ifdef ADVANCE - long initial_advance = block->advance*entry_factor*entry_factor; - long final_advance = block->advance*exit_factor*exit_factor; -#endif // ADVANCE - - // Limit minimal step rate (Otherwise the timer will overflow.) - if(initial_rate <120) initial_rate=120; - if(final_rate < 120) final_rate=120; - - // Calculate the acceleration steps - long acceleration = block->acceleration_st; - long accelerate_steps = estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration); - long decelerate_steps = estimate_acceleration_distance(final_rate, block->nominal_rate, acceleration); - // Calculate the size of Plateau of Nominal Rate. - long plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; - - // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will - // 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 = intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count); - plateau_steps = 0; - } - - long decelerate_after = accelerate_steps+plateau_steps; - - CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section - if(block->busy == false) { // Don't update variables if block is busy. - block->accelerate_until = accelerate_steps; - block->decelerate_after = decelerate_after; - block->initial_rate = initial_rate; - block->final_rate = final_rate; -#ifdef ADVANCE - block->initial_advance = initial_advance; - block->final_advance = final_advance; -#endif //ADVANCE - } - CRITICAL_SECTION_END; -} - -// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the -// acceleration within the allotted distance. -inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { - return( - sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance) - ); -} - -// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. -// This method will calculate the junction jerk as the euclidean distance between the nominal -// velocities of the respective blocks. -inline float junction_jerk(block_t *before, block_t *after) { - return(sqrt( - pow((before->speed_x-after->speed_x), 2)+ - pow((before->speed_y-after->speed_y), 2))); -} - -// Return the safe speed which is max_jerk/2, e.g. the -// speed under which you cannot exceed max_jerk no matter what you do. -float safe_speed(block_t *block) { - float safe_speed; - safe_speed = max_xy_jerk/2; - if(abs(block->speed_z) > max_z_jerk/2) safe_speed = max_z_jerk/2; - if (safe_speed > block->nominal_speed) safe_speed = block->nominal_speed; - return safe_speed; -} - -// The kernel called by planner_recalculate() when scanning the plan from last to first entry. -void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - - float entry_speed = current->nominal_speed; - float exit_factor; - float exit_speed; - if (next) { - exit_speed = next->entry_speed; - } - else { - exit_speed = safe_speed(current); - } - - // Calculate the entry_factor for the current block. - if (previous) { - // Reduce speed so that junction_jerk is within the maximum allowed - float jerk = junction_jerk(previous, current); - if((previous->steps_x == 0) && (previous->steps_y == 0)) { - entry_speed = safe_speed(current); - } - else if (jerk > max_xy_jerk) { - entry_speed = (max_xy_jerk/jerk) * entry_speed; - } - if(abs(previous->speed_z - current->speed_z) > max_z_jerk) { - entry_speed = (max_z_jerk/abs(previous->speed_z - current->speed_z)) * entry_speed; - } - // If the required deceleration across the block is too rapid, reduce the entry_factor accordingly. - if (entry_speed > exit_speed) { - float max_entry_speed = max_allowable_speed(-current->acceleration,exit_speed, current->millimeters); - if (max_entry_speed < entry_speed) { - entry_speed = max_entry_speed; - } - } - } - else { - entry_speed = safe_speed(current); - } - // Store result - current->entry_speed = entry_speed; -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the reverse pass. -void planner_reverse_pass() { - char block_index = block_buffer_head; - if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { - block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); - block_t *block[5] = { - NULL, NULL, NULL, NULL, NULL }; - while(block_index != block_buffer_tail) { - block_index = (block_index-1) & (BLOCK_BUFFER_SIZE -1); - block[2]= block[1]; - block[1]= block[0]; - block[0] = &block_buffer[block_index]; - planner_reverse_pass_kernel(block[0], block[1], block[2]); - } - planner_reverse_pass_kernel(NULL, block[0], block[1]); - } -} - -// The kernel called by planner_recalculate() when scanning the plan from first to last entry. -void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - if(previous) { - // If the previous block is an acceleration block, but it is not long enough to - // complete the full speed change within the block, we need to adjust out entry - // speed accordingly. Remember current->entry_factor equals the exit factor of - // the previous block. - if(previous->entry_speed < current->entry_speed) { - float max_entry_speed = max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters); - if (max_entry_speed < current->entry_speed) { - current->entry_speed = max_entry_speed; - } - } - } -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the forward pass. -void planner_forward_pass() { - char block_index = block_buffer_tail; - block_t *block[3] = { - NULL, NULL, NULL }; - - while(block_index != block_buffer_head) { - block[0] = block[1]; - block[1] = block[2]; - block[2] = &block_buffer[block_index]; - planner_forward_pass_kernel(block[0],block[1],block[2]); - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - planner_forward_pass_kernel(block[1], block[2], NULL); -} - -// Recalculates the trapezoid speed profiles for all blocks in the plan according to the -// entry_factor for each junction. Must be called by planner_recalculate() after -// updating the blocks. -void planner_recalculate_trapezoids() { - char block_index = block_buffer_tail; - block_t *current; - block_t *next = NULL; - while(block_index != block_buffer_head) { - current = next; - next = &block_buffer[block_index]; - if (current) { - calculate_trapezoid_for_block(current, current->entry_speed, next->entry_speed); - } - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - calculate_trapezoid_for_block(next, next->entry_speed, safe_speed(next)); -} - -// Recalculates the motion plan according to the following algorithm: -// -// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) -// so that: -// a. The junction jerk is within the set limit -// b. No speed reduction within one block requires faster deceleration than the one, true constant -// acceleration. -// 2. Go over every block in chronological order and dial down junction speed reduction values if -// a. The speed increase within one block would require faster accelleration than the one, true -// constant acceleration. -// -// When these stages are complete all blocks have an entry_factor that will allow all speed changes to -// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than -// the set limit. Finally it will: -// -// 3. Recalculate trapezoids for all blocks. - -void planner_recalculate() { - planner_reverse_pass(); - planner_forward_pass(); - planner_recalculate_trapezoids(); -} - -void plan_init() { - block_buffer_head = 0; - block_buffer_tail = 0; - memset(position, 0, sizeof(position)); // clear position -} - - -void plan_discard_current_block() { - if (block_buffer_head != block_buffer_tail) { - block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); - } -} - -block_t *plan_get_current_block() { - if (block_buffer_head == block_buffer_tail) { - return(NULL); - } - block_t *block = &block_buffer[block_buffer_tail]; - block->busy = true; - return(block); -} - -void check_axes_activity() { - unsigned char x_active = 0; - unsigned char y_active = 0; - unsigned char z_active = 0; - unsigned char e_active = 0; - block_t *block; - - if(block_buffer_tail != block_buffer_head) { - char block_index = block_buffer_tail; - while(block_index != block_buffer_head) { - block = &block_buffer[block_index]; - if(block->steps_x != 0) x_active++; - if(block->steps_y != 0) y_active++; - if(block->steps_z != 0) z_active++; - if(block->steps_e != 0) e_active++; - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - } - if((DISABLE_X) && (x_active == 0)) disable_x(); - if((DISABLE_Y) && (y_active == 0)) disable_y(); - if((DISABLE_Z) && (z_active == 0)) disable_z(); - if((DISABLE_E) && (e_active == 0)) disable_e(); -} - -// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in -// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration -// calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { - - - // Calculate the buffer head after we push this byte - int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); - - // If the buffer is full: good! That means we are well ahead of the robot. - // Rest here until there is room in the buffer. - while(block_buffer_tail == next_buffer_head) { - manage_heater(); - manage_inactivity(1); - LCD_STATUS; - } - +/* + planner.c - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ + +/* + Reasoning behind the mathematics in this module (in the key of 'Mathematica'): + + s == speed, a == acceleration, t == time, d == distance + + Basic definitions: + + Speed[s_, a_, t_] := s + (a*t) + Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] + + Distance to reach a specific speed with a constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] + d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() + + Speed after a given distance of travel with constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] + m -> Sqrt[2 a d + s^2] + + DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] + + When to start braking (di) to reach a specified destionation speed (s2) after accelerating + from initial speed s1 without ever stopping at a plateau: + + Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] + di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() + + IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) +*/ + + +//#include +//#include +//#include + +#include "Marlin.h" +#include "Configuration.h" +#include "pins.h" +#include "fastio.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" +#include "ultralcd.h" + +unsigned long minsegmenttime; +float max_feedrate[4]; // set the max speeds +float axis_steps_per_unit[4]; +long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +float minimumfeedrate; +float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +float max_z_jerk; +float mintravelfeedrate; +unsigned long axis_steps_per_sqr_second[NUM_AXIS]; +// Manage heater variables. + +static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +static volatile unsigned char block_buffer_head; // Index of the next block to be pushed +static volatile unsigned char block_buffer_tail; // Index of the block to process now + +// The current position of the tool in absolute steps + long position[4]; + +#define ONE_MINUTE_OF_MICROSECONDS 60000000.0 + +// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the +// given acceleration: +inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { + if (acceleration!=0) { + return((target_rate*target_rate-initial_rate*initial_rate)/ + (2.0*acceleration)); + } + else { + return 0.0; // acceleration was 0, set acceleration distance to 0 + } +} + +// This function gives you the point at which you must start braking (at the rate of -acceleration) if +// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after +// a total travel of distance. This can be used to compute the intersection point between acceleration and +// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) + +inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { + if (acceleration!=0) { + return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ + (4.0*acceleration) ); + } + else { + return 0.0; // acceleration was 0, set intersection distance to 0 + } +} + +// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. + +void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit_speed) { + if(block->busy == true) return; // If block is busy then bail out. + float entry_factor = entry_speed / block->nominal_speed; + float exit_factor = exit_speed / block->nominal_speed; + long initial_rate = ceil(block->nominal_rate*entry_factor); + long final_rate = ceil(block->nominal_rate*exit_factor); + +#ifdef ADVANCE + long initial_advance = block->advance*entry_factor*entry_factor; + long final_advance = block->advance*exit_factor*exit_factor; +#endif // ADVANCE + + // Limit minimal step rate (Otherwise the timer will overflow.) + if(initial_rate <120) initial_rate=120; + if(final_rate < 120) final_rate=120; + + // Calculate the acceleration steps + long acceleration = block->acceleration_st; + long accelerate_steps = estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration); + long decelerate_steps = estimate_acceleration_distance(final_rate, block->nominal_rate, acceleration); + // Calculate the size of Plateau of Nominal Rate. + long plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; + + // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will + // 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 = intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count); + plateau_steps = 0; + } + + long decelerate_after = accelerate_steps+plateau_steps; + + CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section + if(block->busy == false) { // Don't update variables if block is busy. + block->accelerate_until = accelerate_steps; + block->decelerate_after = decelerate_after; + block->initial_rate = initial_rate; + block->final_rate = final_rate; +#ifdef ADVANCE + block->initial_advance = initial_advance; + block->final_advance = final_advance; +#endif //ADVANCE + } + CRITICAL_SECTION_END; +} + +// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the +// acceleration within the allotted distance. +inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { + return( + sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance) + ); +} + +// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. +// This method will calculate the junction jerk as the euclidean distance between the nominal +// velocities of the respective blocks. +inline float junction_jerk(block_t *before, block_t *after) { + return(sqrt( + pow((before->speed_x-after->speed_x), 2)+ + pow((before->speed_y-after->speed_y), 2))); +} + +// Return the safe speed which is max_jerk/2, e.g. the +// speed under which you cannot exceed max_jerk no matter what you do. +float safe_speed(block_t *block) { + float safe_speed; + safe_speed = max_xy_jerk/2; + if(abs(block->speed_z) > max_z_jerk/2) safe_speed = max_z_jerk/2; + if (safe_speed > block->nominal_speed) safe_speed = block->nominal_speed; + return safe_speed; +} + +// The kernel called by planner_recalculate() when scanning the plan from last to first entry. +void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!current) { + return; + } + + float entry_speed = current->nominal_speed; + float exit_factor; + float exit_speed; + if (next) { + exit_speed = next->entry_speed; + } + else { + exit_speed = safe_speed(current); + } + + // Calculate the entry_factor for the current block. + if (previous) { + // Reduce speed so that junction_jerk is within the maximum allowed + float jerk = junction_jerk(previous, current); + if((previous->steps_x == 0) && (previous->steps_y == 0)) { + entry_speed = safe_speed(current); + } + else if (jerk > max_xy_jerk) { + entry_speed = (max_xy_jerk/jerk) * entry_speed; + } + if(abs(previous->speed_z - current->speed_z) > max_z_jerk) { + entry_speed = (max_z_jerk/abs(previous->speed_z - current->speed_z)) * entry_speed; + } + // If the required deceleration across the block is too rapid, reduce the entry_factor accordingly. + if (entry_speed > exit_speed) { + float max_entry_speed = max_allowable_speed(-current->acceleration,exit_speed, current->millimeters); + if (max_entry_speed < entry_speed) { + entry_speed = max_entry_speed; + } + } + } + else { + entry_speed = safe_speed(current); + } + // Store result + current->entry_speed = entry_speed; +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the reverse pass. +void planner_reverse_pass() { + char block_index = block_buffer_head; + if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { + block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); + block_t *block[5] = { + NULL, NULL, NULL, NULL, NULL }; + while(block_index != block_buffer_tail) { + block_index = (block_index-1) & (BLOCK_BUFFER_SIZE -1); + block[2]= block[1]; + block[1]= block[0]; + block[0] = &block_buffer[block_index]; + planner_reverse_pass_kernel(block[0], block[1], block[2]); + } + planner_reverse_pass_kernel(NULL, block[0], block[1]); + } +} + +// The kernel called by planner_recalculate() when scanning the plan from first to last entry. +void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!current) { + return; + } + if(previous) { + // If the previous block is an acceleration block, but it is not long enough to + // complete the full speed change within the block, we need to adjust out entry + // speed accordingly. Remember current->entry_factor equals the exit factor of + // the previous block. + if(previous->entry_speed < current->entry_speed) { + float max_entry_speed = max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters); + if (max_entry_speed < current->entry_speed) { + current->entry_speed = max_entry_speed; + } + } + } +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the forward pass. +void planner_forward_pass() { + char block_index = block_buffer_tail; + block_t *block[3] = { + NULL, NULL, NULL }; + + while(block_index != block_buffer_head) { + block[0] = block[1]; + block[1] = block[2]; + block[2] = &block_buffer[block_index]; + planner_forward_pass_kernel(block[0],block[1],block[2]); + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + planner_forward_pass_kernel(block[1], block[2], NULL); +} + +// Recalculates the trapezoid speed profiles for all blocks in the plan according to the +// entry_factor for each junction. Must be called by planner_recalculate() after +// updating the blocks. +void planner_recalculate_trapezoids() { + char block_index = block_buffer_tail; + block_t *current; + block_t *next = NULL; + while(block_index != block_buffer_head) { + current = next; + next = &block_buffer[block_index]; + if (current) { + calculate_trapezoid_for_block(current, current->entry_speed, next->entry_speed); + } + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + calculate_trapezoid_for_block(next, next->entry_speed, safe_speed(next)); +} + +// Recalculates the motion plan according to the following algorithm: +// +// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) +// so that: +// a. The junction jerk is within the set limit +// b. No speed reduction within one block requires faster deceleration than the one, true constant +// acceleration. +// 2. Go over every block in chronological order and dial down junction speed reduction values if +// a. The speed increase within one block would require faster accelleration than the one, true +// constant acceleration. +// +// When these stages are complete all blocks have an entry_factor that will allow all speed changes to +// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than +// the set limit. Finally it will: +// +// 3. Recalculate trapezoids for all blocks. + +void planner_recalculate() { + planner_reverse_pass(); + planner_forward_pass(); + planner_recalculate_trapezoids(); +} + +void plan_init() { + block_buffer_head = 0; + block_buffer_tail = 0; + memset(position, 0, sizeof(position)); // clear position +} + + +void plan_discard_current_block() { + if (block_buffer_head != block_buffer_tail) { + block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); + } +} + +block_t *plan_get_current_block() { + if (block_buffer_head == block_buffer_tail) { + return(NULL); + } + block_t *block = &block_buffer[block_buffer_tail]; + block->busy = true; + return(block); +} + +void check_axes_activity() { + unsigned char x_active = 0; + unsigned char y_active = 0; + unsigned char z_active = 0; + unsigned char e_active = 0; + block_t *block; + + if(block_buffer_tail != block_buffer_head) { + char block_index = block_buffer_tail; + while(block_index != block_buffer_head) { + block = &block_buffer[block_index]; + if(block->steps_x != 0) x_active++; + if(block->steps_y != 0) y_active++; + if(block->steps_z != 0) z_active++; + if(block->steps_e != 0) e_active++; + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + } + if((DISABLE_X) && (x_active == 0)) disable_x(); + if((DISABLE_Y) && (y_active == 0)) disable_y(); + if((DISABLE_Z) && (z_active == 0)) disable_z(); + if((DISABLE_E) && (e_active == 0)) disable_e(); +} + +// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in +// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration +// calculation the caller must also provide the physical length of the line in millimeters. +void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { + + + // Calculate the buffer head after we push this byte + int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); + + // If the buffer is full: good! That means we are well ahead of the robot. + // Rest here until there is room in the buffer. + while(block_buffer_tail == next_buffer_head) { + manage_heater(); + manage_inactivity(1); + LCD_STATUS; + } + // The target position of the tool in absolute steps // Calculate target position in absolute steps //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow @@ -402,185 +402,185 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - // Prepare to set up new block - block_t *block = &block_buffer[block_buffer_head]; - - // Mark block as not busy (Not executed by the stepper interrupt) - block->busy = false; - - // Number of steps for each axis - block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); - block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); - block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); - block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); - block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); - - // Bail if this is a zero-length block - if (block->step_event_count <=dropsegments) { - return; - }; - - //enable active axes - if(block->steps_x != 0) enable_x(); - if(block->steps_y != 0) enable_y(); - if(block->steps_z != 0) enable_z(); - if(block->steps_e != 0) enable_e(); - - float delta_x_mm = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; - float delta_y_mm = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; - float delta_z_mm = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; - float delta_e_mm = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; - block->millimeters = sqrt(square(delta_x_mm) + square(delta_y_mm) + square(delta_z_mm) + square(delta_e_mm)); - - unsigned long microseconds; - - if (block->steps_e == 0) { - if(feed_ratemillimeters/feed_rate)*1000000); - - // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill - // reduces/removes corner blobs as the machine won't come to a full stop. - int blockcount=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); - - if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { - if (microsecondsspeed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - - - // Limit speed per axis - float speed_factor = 1; //factor <=1 do decrease speed - if(abs(block->speed_x) > max_feedrate[X_AXIS]) { - //// [ErikDeBruijn] IS THIS THE BUG WE'RE LOOING FOR???? - //// [bernhard] No its not, according to Zalm. - //// the if would always be true, since tmp_speedfactor <=0 due the inial if, so its safe to set. the next lines actually compare. - speed_factor = max_feedrate[X_AXIS] / abs(block->speed_x); - //if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_y) > max_feedrate[Y_AXIS]){ - float tmp_speed_factor = max_feedrate[Y_AXIS] / abs(block->speed_y); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_z) > max_feedrate[Z_AXIS]){ - float tmp_speed_factor = max_feedrate[Z_AXIS] / abs(block->speed_z); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_e) > max_feedrate[E_AXIS]){ - float tmp_speed_factor = max_feedrate[E_AXIS] / abs(block->speed_e); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - multiplier = multiplier * speed_factor; - block->speed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - block->nominal_speed = block->millimeters * multiplier; - block->nominal_rate = ceil(block->step_event_count * multiplier / 60); - - if(block->nominal_rate < 120) block->nominal_rate = 120; - block->entry_speed = safe_speed(block); - - // Compute the acceleration rate for the trapezoid generator. - float travel_per_step = block->millimeters/block->step_event_count; - if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { - block->acceleration_st = ceil( (retract_acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - } - else { - block->acceleration_st = ceil( (acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - float tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - // Limit acceleration per axis - if((tmp_acceleration * block->steps_x) > axis_steps_per_sqr_second[X_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_y) > axis_steps_per_sqr_second[Y_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_e) > axis_steps_per_sqr_second[E_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_z) > axis_steps_per_sqr_second[Z_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - } - block->acceleration = block->acceleration_st * travel_per_step; - block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); - -#ifdef ADVANCE - // Calculate advance rate - if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { - block->advance_rate = 0; - block->advance = 0; - } - else { - long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); - float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; - block->advance = advance; - if(acc_dist == 0) { - block->advance_rate = 0; - } - else { - block->advance_rate = advance / (float)acc_dist; - } - } -#endif // ADVANCE - - // compute a preliminary conservative acceleration trapezoid - float safespeed = safe_speed(block); - calculate_trapezoid_for_block(block, safespeed, safespeed); - - // Compute direction bits for this block - block->direction_bits = 0; - if (target[X_AXIS] < position[X_AXIS]) { - block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<busy = false; + + // Number of steps for each axis + block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); + block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); + block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); + block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); + block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); + + // Bail if this is a zero-length block + if (block->step_event_count <=dropsegments) { + return; + }; + + //enable active axes + if(block->steps_x != 0) enable_x(); + if(block->steps_y != 0) enable_y(); + if(block->steps_z != 0) enable_z(); + if(block->steps_e != 0) enable_e(); + + float delta_x_mm = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; + float delta_y_mm = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; + float delta_z_mm = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; + float delta_e_mm = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; + block->millimeters = sqrt(square(delta_x_mm) + square(delta_y_mm) + square(delta_z_mm) + square(delta_e_mm)); + + unsigned long microseconds; + + if (block->steps_e == 0) { + if(feed_ratemillimeters/feed_rate)*1000000); + + // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill + // reduces/removes corner blobs as the machine won't come to a full stop. + int blockcount=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + + if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { + if (microsecondsspeed_z = delta_z_mm * multiplier; + block->speed_x = delta_x_mm * multiplier; + block->speed_y = delta_y_mm * multiplier; + block->speed_e = delta_e_mm * multiplier; + + + // Limit speed per axis + float speed_factor = 1; //factor <=1 do decrease speed + if(abs(block->speed_x) > max_feedrate[X_AXIS]) { + //// [ErikDeBruijn] IS THIS THE BUG WE'RE LOOING FOR???? + //// [bernhard] No its not, according to Zalm. + //// the if would always be true, since tmp_speedfactor <=0 due the inial if, so its safe to set. the next lines actually compare. + speed_factor = max_feedrate[X_AXIS] / abs(block->speed_x); + //if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + if(abs(block->speed_y) > max_feedrate[Y_AXIS]){ + float tmp_speed_factor = max_feedrate[Y_AXIS] / abs(block->speed_y); + if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + if(abs(block->speed_z) > max_feedrate[Z_AXIS]){ + float tmp_speed_factor = max_feedrate[Z_AXIS] / abs(block->speed_z); + if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + if(abs(block->speed_e) > max_feedrate[E_AXIS]){ + float tmp_speed_factor = max_feedrate[E_AXIS] / abs(block->speed_e); + if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + } + multiplier = multiplier * speed_factor; + block->speed_z = delta_z_mm * multiplier; + block->speed_x = delta_x_mm * multiplier; + block->speed_y = delta_y_mm * multiplier; + block->speed_e = delta_e_mm * multiplier; + block->nominal_speed = block->millimeters * multiplier; + block->nominal_rate = ceil(block->step_event_count * multiplier / 60); + + if(block->nominal_rate < 120) block->nominal_rate = 120; + block->entry_speed = safe_speed(block); + + // Compute the acceleration rate for the trapezoid generator. + float travel_per_step = block->millimeters/block->step_event_count; + if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { + block->acceleration_st = ceil( (retract_acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 + } + else { + block->acceleration_st = ceil( (acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 + float tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + // Limit acceleration per axis + if((tmp_acceleration * block->steps_x) > axis_steps_per_sqr_second[X_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + if((tmp_acceleration * block->steps_y) > axis_steps_per_sqr_second[Y_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + if((tmp_acceleration * block->steps_e) > axis_steps_per_sqr_second[E_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + if((tmp_acceleration * block->steps_z) > axis_steps_per_sqr_second[Z_AXIS]) { + block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; + tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; + } + } + block->acceleration = block->acceleration_st * travel_per_step; + block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); + +#ifdef ADVANCE + // Calculate advance rate + if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { + block->advance_rate = 0; + block->advance = 0; + } + else { + long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); + float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * + (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; + block->advance = advance; + if(acc_dist == 0) { + block->advance_rate = 0; + } + else { + block->advance_rate = advance / (float)acc_dist; + } + } +#endif // ADVANCE + + // compute a preliminary conservative acceleration trapezoid + float safespeed = safe_speed(block); + calculate_trapezoid_for_block(block, safespeed, safespeed); + + // Compute direction bits for this block + block->direction_bits = 0; + if (target[X_AXIS] < position[X_AXIS]) { + block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1< - -uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ -{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, -{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, -{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, -{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8}, -{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5}, -{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3}, -{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2}, -{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2}, -{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1}, -{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1}, -{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1}, -{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1}, -{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0}, -{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1}, -{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0}, -{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1}, -{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0}, -{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0}, -{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0}, -{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1}, -{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0}, -{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0}, -{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0}, -{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0}, -{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0}, -{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0}, -{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0}, -{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1}, -{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0}, -{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0}, -{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, -{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0} -}; -uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ -{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, -{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, -{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, -{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198}, -{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132}, -{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94}, -{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71}, -{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55}, -{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44}, -{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36}, -{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30}, -{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25}, -{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22}, -{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18}, -{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16}, -{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15}, -{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13}, -{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11}, -{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10}, -{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9}, -{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8}, -{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8}, -{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7}, -{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7}, -{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6}, -{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5}, -{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5}, -{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5}, -{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4}, -{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4}, -{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4}, -{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3} -}; - -#endif +#ifndef SPEED_LOOKUPTABLE_H +#define SPEED_LOOKUPTABLE_H + +#include + +uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ +{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, +{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, +{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, +{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8}, +{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5}, +{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3}, +{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2}, +{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2}, +{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1}, +{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1}, +{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1}, +{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1}, +{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0}, +{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1}, +{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0}, +{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1}, +{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0}, +{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0}, +{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0}, +{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1}, +{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0}, +{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0}, +{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0}, +{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0}, +{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0}, +{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0}, +{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0}, +{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1}, +{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0}, +{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0}, +{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, +{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0} +}; +uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ +{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, +{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, +{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, +{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198}, +{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132}, +{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94}, +{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71}, +{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55}, +{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44}, +{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36}, +{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30}, +{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25}, +{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22}, +{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18}, +{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16}, +{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15}, +{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13}, +{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11}, +{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10}, +{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9}, +{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8}, +{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8}, +{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7}, +{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7}, +{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6}, +{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5}, +{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5}, +{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5}, +{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4}, +{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4}, +{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4}, +{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3} +}; + +#endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 15f1433497..f4bd1289e0 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -1,592 +1,592 @@ -/* - stepper.c - stepper motor driver: executes motion plans using stepper motors - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith - and Philipp Tiefenbacher. */ - -#include "stepper.h" -#include "Configuration.h" -#include "Marlin.h" -#include "planner.h" -#include "pins.h" -#include "fastio.h" -#include "temperature.h" -#include "ultralcd.h" - -#include "speed_lookuptable.h" - -// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. -// for debugging purposes only, should be disabled by default -#ifdef DEBUG_STEPS -volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; -volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; -#endif - - -// intRes = intIn1 * intIn2 >> 16 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 24 bit result -#define MultiU16X8toH16(intRes, charIn1, intIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %A1, %A2 \n\t" \ -"add %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r0 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (charIn1), \ -"d" (intIn2) \ -: \ -"r26" \ -) - -// intRes = longIn1 * longIn2 >> 24 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 48bit result -#define MultiU24X24toH16(intRes, longIn1, longIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"mov r27, r1 \n\t" \ -"mul %B1, %C2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %C1, %C2 \n\t" \ -"add %B0, r0 \n\t" \ -"mul %C1, %B2 \n\t" \ -"add %A0, r0 \n\t" \ -"adc %B0, r1 \n\t" \ -"mul %A1, %C2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %B2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %C1, %A2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %A2 \n\t" \ -"add r27, r1 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r27 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (longIn1), \ -"d" (longIn2) \ -: \ -"r26" , "r27" \ -) - -// Some useful constants - -#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< -// -// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates -// first block->accelerate_until step_events_completed, then keeps going at constant speed until -// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. -// The slope of acceleration is calculated with the leib ramp alghorithm. - -void st_wake_up() { - // TCNT1 = 0; - ENABLE_STEPPER_DRIVER_INTERRUPT(); -} - -inline unsigned short calc_timer(unsigned short step_rate) { - unsigned short timer; - if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; - - if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times - step_rate = step_rate >> 2; - step_loops = 4; - } - else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times - step_rate = step_rate >> 1; - step_loops = 2; - } - else { - step_loops = 1; - } - - if(step_rate < 32) step_rate = 32; - step_rate -= 32; // Correct for minimal speed - if(step_rate >= (8*256)){ // higher step rate - unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; - unsigned char tmp_step_rate = (step_rate & 0x00ff); - unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); - MultiU16X8toH16(timer, tmp_step_rate, gain); - timer = (unsigned short)pgm_read_word_near(table_address) - timer; - } - else { // lower step rates - unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; - table_address += ((step_rate)>>1) & 0xfffc; - timer = (unsigned short)pgm_read_word_near(table_address); - timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); - } - if(timer < 100) timer = 100; - return timer; -} - -// Initializes the trapezoid generator from the current block. Called whenever a new -// block begins. -inline void trapezoid_generator_reset() { -#ifdef ADVANCE - advance = current_block->initial_advance; - final_advance = current_block->final_advance; -#endif - deceleration_time = 0; - // advance_rate = current_block->advance_rate; - // step_rate to timer interval - acc_step_rate = current_block->initial_rate; - acceleration_time = calc_timer(acc_step_rate); - OCR1A = acceleration_time; -} - -// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. -// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. -ISR(TIMER1_COMPA_vect) -{ - if(busy){ Serial.print(*(unsigned short *)OCR1A); Serial.println(" BUSY"); - return; - } // The busy-flag is used to avoid reentering this interrupt - - busy = true; - sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) - - // If there is no current block, attempt to pop one from the buffer - if (current_block == NULL) { - // Anything in the buffer? - current_block = plan_get_current_block(); - if (current_block != NULL) { - trapezoid_generator_reset(); - counter_x = -(current_block->step_event_count >> 1); - counter_y = counter_x; - counter_z = counter_x; - counter_e = counter_x; - step_events_completed = 0; - #ifdef ADVANCE - e_steps = 0; - #endif - } - else { -// DISABLE_STEPPER_DRIVER_INTERRUPT(); - } - } - - if (current_block != NULL) { - // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt - out_bits = current_block->direction_bits; - -#ifdef ADVANCE - // Calculate E early. - counter_e += current_block->steps_e; - if (counter_e > 0) { - counter_e -= current_block->step_event_count; - if ((out_bits & (1<> 16) - old_advance); - CRITICAL_SECTION_END; - old_advance = advance >> 16; -#endif //ADVANCE - - // Set direction en check limit switches -if ((out_bits & (1< -1 - if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } -#endif - } - else { // +direction - WRITE(X_DIR_PIN,!INVERT_X_DIR); - #ifdef DEBUG_STEPS - count_direction[X_AXIS]=1; - #endif -#if X_MAX_PIN > -1 - if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ - step_events_completed = current_block->step_event_count; - } -#endif - } - - if ((out_bits & (1< -1 - if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } -#endif - } - else { // +direction - WRITE(Y_DIR_PIN,!INVERT_Y_DIR); - #ifdef DEBUG_STEPS - count_direction[Y_AXIS]=1; - #endif -#if Y_MAX_PIN > -1 - if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ - step_events_completed = current_block->step_event_count; - } -#endif - } - - if ((out_bits & (1< -1 - if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } -#endif - } - else { // +direction - WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - #ifdef DEBUG_STEPS - count_direction[Z_AXIS]=1; - #endif -#if Z_MAX_PIN > -1 - if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ - step_events_completed = current_block->step_event_count; - } -#endif - } - -#ifndef ADVANCE - if ((out_bits & (1<steps_x; - if (counter_x > 0) { - WRITE(X_STEP_PIN, HIGH); - counter_x -= current_block->step_event_count; - WRITE(X_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[X_AXIS]+=count_direction[X_AXIS]; - #endif - } - - counter_y += current_block->steps_y; - if (counter_y > 0) { - WRITE(Y_STEP_PIN, HIGH); - counter_y -= current_block->step_event_count; - WRITE(Y_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Y_AXIS]+=count_direction[Y_AXIS]; - #endif - } - - counter_z += current_block->steps_z; - if (counter_z > 0) { - WRITE(Z_STEP_PIN, HIGH); - counter_z -= current_block->step_event_count; - WRITE(Z_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Z_AXIS]+=count_direction[Z_AXIS]; - #endif - } - -#ifndef ADVANCE - counter_e += current_block->steps_e; - if (counter_e > 0) { - WRITE(E_STEP_PIN, HIGH); - counter_e -= current_block->step_event_count; - WRITE(E_STEP_PIN, LOW); - } -#endif //!ADVANCE - step_events_completed += 1; - if(step_events_completed >= current_block->step_event_count) break; - } - // Calculare new timer value - unsigned short timer; - unsigned short step_rate; - if (step_events_completed <= current_block->accelerate_until) { - MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); - acc_step_rate += current_block->initial_rate; - - // upper limit - if(acc_step_rate > current_block->nominal_rate) - acc_step_rate = current_block->nominal_rate; - - // step_rate to timer interval - timer = calc_timer(acc_step_rate); -#ifdef ADVANCE - advance += advance_rate; -#endif - acceleration_time += timer; - OCR1A = timer; - } - else if (step_events_completed > current_block->decelerate_after) { - MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); - - if(step_rate > acc_step_rate) { // Check step_rate stays positive - step_rate = current_block->final_rate; - } - else { - step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. - } - - // lower limit - if(step_rate < current_block->final_rate) - step_rate = current_block->final_rate; - - // step_rate to timer interval - timer = calc_timer(step_rate); -#ifdef ADVANCE - advance -= advance_rate; - if(advance < final_advance) - advance = final_advance; -#endif //ADVANCE - deceleration_time += timer; - OCR1A = timer; - } - // If current block is finished, reset pointer - if (step_events_completed >= current_block->step_event_count) { - current_block = NULL; - plan_discard_current_block(); - } - } - cli(); // disable interrupts - busy=false; -} - -#ifdef ADVANCE - -unsigned char old_OCR0A; -// Timer interrupt for E. e_steps is set in the main routine; -// Timer 0 is shared with millies -ISR(TIMER0_COMPA_vect) -{ - // Critical section needed because Timer 1 interrupt has higher priority. - // The pin set functions are placed on trategic position to comply with the stepper driver timing. - WRITE(E_STEP_PIN, LOW); - // Set E direction (Depends on E direction + advance) - if (e_steps < 0) { - WRITE(E_DIR_PIN,INVERT_E_DIR); - e_steps++; - WRITE(E_STEP_PIN, HIGH); - } - if (e_steps > 0) { - WRITE(E_DIR_PIN,!INVERT_E_DIR); - e_steps--; - WRITE(E_STEP_PIN, HIGH); - } - old_OCR0A += 25; // 10kHz interrupt - OCR0A = old_OCR0A; -} -#endif // ADVANCE - -void st_init() -{ - //Initialize Dir Pins -#if X_DIR_PIN > -1 - SET_OUTPUT(X_DIR_PIN); -#endif -#if Y_DIR_PIN > -1 - SET_OUTPUT(Y_DIR_PIN); -#endif -#if Z_DIR_PIN > -1 - SET_OUTPUT(Z_DIR_PIN); -#endif -#if E_DIR_PIN > -1 - SET_OUTPUT(E_DIR_PIN); -#endif - - //Initialize Enable Pins - steppers default to disabled. - -#if (X_ENABLE_PIN > -1) - SET_OUTPUT(X_ENABLE_PIN); - if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); -#endif -#if (Y_ENABLE_PIN > -1) - SET_OUTPUT(Y_ENABLE_PIN); - if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); -#endif -#if (Z_ENABLE_PIN > -1) - SET_OUTPUT(Z_ENABLE_PIN); - if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); -#endif -#if (E_ENABLE_PIN > -1) - SET_OUTPUT(E_ENABLE_PIN); - if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); -#endif - - //endstops and pullups -#ifdef ENDSTOPPULLUPS -#if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); - WRITE(X_MIN_PIN,HIGH); -#endif -#if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); - WRITE(X_MAX_PIN,HIGH); -#endif -#if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); - WRITE(Y_MIN_PIN,HIGH); -#endif -#if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); - WRITE(Y_MAX_PIN,HIGH); -#endif -#if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); - WRITE(Z_MIN_PIN,HIGH); -#endif -#if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); - WRITE(Z_MAX_PIN,HIGH); -#endif -#else //ENDSTOPPULLUPS -#if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); -#endif -#if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); -#endif -#if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); -#endif -#if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); -#endif -#if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); -#endif -#if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); -#endif -#endif //ENDSTOPPULLUPS - - - //Initialize Step Pins -#if (X_STEP_PIN > -1) - SET_OUTPUT(X_STEP_PIN); -#endif -#if (Y_STEP_PIN > -1) - SET_OUTPUT(Y_STEP_PIN); -#endif -#if (Z_STEP_PIN > -1) - SET_OUTPUT(Z_STEP_PIN); -#endif -#if (E_STEP_PIN > -1) - SET_OUTPUT(E_STEP_PIN); -#endif - - // waveform generation = 0100 = CTC - TCCR1B &= ~(1<. +*/ + +/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith + and Philipp Tiefenbacher. */ + +#include "stepper.h" +#include "Configuration.h" +#include "Marlin.h" +#include "planner.h" +#include "pins.h" +#include "fastio.h" +#include "temperature.h" +#include "ultralcd.h" + +#include "speed_lookuptable.h" + +// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. +// for debugging purposes only, should be disabled by default +#ifdef DEBUG_STEPS +volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; +volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; +#endif + + +// intRes = intIn1 * intIn2 >> 16 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 24 bit result +#define MultiU16X8toH16(intRes, charIn1, intIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %A1, %A2 \n\t" \ +"add %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r0 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (charIn1), \ +"d" (intIn2) \ +: \ +"r26" \ +) + +// intRes = longIn1 * longIn2 >> 24 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 48bit result +#define MultiU24X24toH16(intRes, longIn1, longIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"mov r27, r1 \n\t" \ +"mul %B1, %C2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %C1, %C2 \n\t" \ +"add %B0, r0 \n\t" \ +"mul %C1, %B2 \n\t" \ +"add %A0, r0 \n\t" \ +"adc %B0, r1 \n\t" \ +"mul %A1, %C2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %B2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %C1, %A2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %A2 \n\t" \ +"add r27, r1 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r27 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (longIn1), \ +"d" (longIn2) \ +: \ +"r26" , "r27" \ +) + +// Some useful constants + +#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< +// +// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates +// first block->accelerate_until step_events_completed, then keeps going at constant speed until +// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. +// The slope of acceleration is calculated with the leib ramp alghorithm. + +void st_wake_up() { + // TCNT1 = 0; + ENABLE_STEPPER_DRIVER_INTERRUPT(); +} + +inline unsigned short calc_timer(unsigned short step_rate) { + unsigned short timer; + if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; + + if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times + step_rate = step_rate >> 2; + step_loops = 4; + } + else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times + step_rate = step_rate >> 1; + step_loops = 2; + } + else { + step_loops = 1; + } + + if(step_rate < 32) step_rate = 32; + step_rate -= 32; // Correct for minimal speed + if(step_rate >= (8*256)){ // higher step rate + unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; + unsigned char tmp_step_rate = (step_rate & 0x00ff); + unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); + MultiU16X8toH16(timer, tmp_step_rate, gain); + timer = (unsigned short)pgm_read_word_near(table_address) - timer; + } + else { // lower step rates + unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; + table_address += ((step_rate)>>1) & 0xfffc; + timer = (unsigned short)pgm_read_word_near(table_address); + timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); + } + if(timer < 100) timer = 100; + return timer; +} + +// Initializes the trapezoid generator from the current block. Called whenever a new +// block begins. +inline void trapezoid_generator_reset() { +#ifdef ADVANCE + advance = current_block->initial_advance; + final_advance = current_block->final_advance; +#endif + deceleration_time = 0; + // advance_rate = current_block->advance_rate; + // step_rate to timer interval + acc_step_rate = current_block->initial_rate; + acceleration_time = calc_timer(acc_step_rate); + OCR1A = acceleration_time; +} + +// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. +// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. +ISR(TIMER1_COMPA_vect) +{ + if(busy){ Serial.print(*(unsigned short *)OCR1A); Serial.println(" BUSY"); + return; + } // The busy-flag is used to avoid reentering this interrupt + + busy = true; + sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) + + // If there is no current block, attempt to pop one from the buffer + if (current_block == NULL) { + // Anything in the buffer? + current_block = plan_get_current_block(); + if (current_block != NULL) { + trapezoid_generator_reset(); + counter_x = -(current_block->step_event_count >> 1); + counter_y = counter_x; + counter_z = counter_x; + counter_e = counter_x; + step_events_completed = 0; + #ifdef ADVANCE + e_steps = 0; + #endif + } + else { +// DISABLE_STEPPER_DRIVER_INTERRUPT(); + } + } + + if (current_block != NULL) { + // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt + out_bits = current_block->direction_bits; + +#ifdef ADVANCE + // Calculate E early. + counter_e += current_block->steps_e; + if (counter_e > 0) { + counter_e -= current_block->step_event_count; + if ((out_bits & (1<> 16) - old_advance); + CRITICAL_SECTION_END; + old_advance = advance >> 16; +#endif //ADVANCE + + // Set direction en check limit switches +if ((out_bits & (1< -1 + if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } +#endif + } + else { // +direction + WRITE(X_DIR_PIN,!INVERT_X_DIR); + #ifdef DEBUG_STEPS + count_direction[X_AXIS]=1; + #endif +#if X_MAX_PIN > -1 + if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ + step_events_completed = current_block->step_event_count; + } +#endif + } + + if ((out_bits & (1< -1 + if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } +#endif + } + else { // +direction + WRITE(Y_DIR_PIN,!INVERT_Y_DIR); + #ifdef DEBUG_STEPS + count_direction[Y_AXIS]=1; + #endif +#if Y_MAX_PIN > -1 + if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ + step_events_completed = current_block->step_event_count; + } +#endif + } + + if ((out_bits & (1< -1 + if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } +#endif + } + else { // +direction + WRITE(Z_DIR_PIN,!INVERT_Z_DIR); + #ifdef DEBUG_STEPS + count_direction[Z_AXIS]=1; + #endif +#if Z_MAX_PIN > -1 + if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ + step_events_completed = current_block->step_event_count; + } +#endif + } + +#ifndef ADVANCE + if ((out_bits & (1<steps_x; + if (counter_x > 0) { + WRITE(X_STEP_PIN, HIGH); + counter_x -= current_block->step_event_count; + WRITE(X_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[X_AXIS]+=count_direction[X_AXIS]; + #endif + } + + counter_y += current_block->steps_y; + if (counter_y > 0) { + WRITE(Y_STEP_PIN, HIGH); + counter_y -= current_block->step_event_count; + WRITE(Y_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Y_AXIS]+=count_direction[Y_AXIS]; + #endif + } + + counter_z += current_block->steps_z; + if (counter_z > 0) { + WRITE(Z_STEP_PIN, HIGH); + counter_z -= current_block->step_event_count; + WRITE(Z_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Z_AXIS]+=count_direction[Z_AXIS]; + #endif + } + +#ifndef ADVANCE + counter_e += current_block->steps_e; + if (counter_e > 0) { + WRITE(E_STEP_PIN, HIGH); + counter_e -= current_block->step_event_count; + WRITE(E_STEP_PIN, LOW); + } +#endif //!ADVANCE + step_events_completed += 1; + if(step_events_completed >= current_block->step_event_count) break; + } + // Calculare new timer value + unsigned short timer; + unsigned short step_rate; + if (step_events_completed <= current_block->accelerate_until) { + MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); + acc_step_rate += current_block->initial_rate; + + // upper limit + if(acc_step_rate > current_block->nominal_rate) + acc_step_rate = current_block->nominal_rate; + + // step_rate to timer interval + timer = calc_timer(acc_step_rate); +#ifdef ADVANCE + advance += advance_rate; +#endif + acceleration_time += timer; + OCR1A = timer; + } + else if (step_events_completed > current_block->decelerate_after) { + MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); + + if(step_rate > acc_step_rate) { // Check step_rate stays positive + step_rate = current_block->final_rate; + } + else { + step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. + } + + // lower limit + if(step_rate < current_block->final_rate) + step_rate = current_block->final_rate; + + // step_rate to timer interval + timer = calc_timer(step_rate); +#ifdef ADVANCE + advance -= advance_rate; + if(advance < final_advance) + advance = final_advance; +#endif //ADVANCE + deceleration_time += timer; + OCR1A = timer; + } + // If current block is finished, reset pointer + if (step_events_completed >= current_block->step_event_count) { + current_block = NULL; + plan_discard_current_block(); + } + } + cli(); // disable interrupts + busy=false; +} + +#ifdef ADVANCE + +unsigned char old_OCR0A; +// Timer interrupt for E. e_steps is set in the main routine; +// Timer 0 is shared with millies +ISR(TIMER0_COMPA_vect) +{ + // Critical section needed because Timer 1 interrupt has higher priority. + // The pin set functions are placed on trategic position to comply with the stepper driver timing. + WRITE(E_STEP_PIN, LOW); + // Set E direction (Depends on E direction + advance) + if (e_steps < 0) { + WRITE(E_DIR_PIN,INVERT_E_DIR); + e_steps++; + WRITE(E_STEP_PIN, HIGH); + } + if (e_steps > 0) { + WRITE(E_DIR_PIN,!INVERT_E_DIR); + e_steps--; + WRITE(E_STEP_PIN, HIGH); + } + old_OCR0A += 25; // 10kHz interrupt + OCR0A = old_OCR0A; +} +#endif // ADVANCE + +void st_init() +{ + //Initialize Dir Pins +#if X_DIR_PIN > -1 + SET_OUTPUT(X_DIR_PIN); +#endif +#if Y_DIR_PIN > -1 + SET_OUTPUT(Y_DIR_PIN); +#endif +#if Z_DIR_PIN > -1 + SET_OUTPUT(Z_DIR_PIN); +#endif +#if E_DIR_PIN > -1 + SET_OUTPUT(E_DIR_PIN); +#endif + + //Initialize Enable Pins - steppers default to disabled. + +#if (X_ENABLE_PIN > -1) + SET_OUTPUT(X_ENABLE_PIN); + if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); +#endif +#if (Y_ENABLE_PIN > -1) + SET_OUTPUT(Y_ENABLE_PIN); + if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); +#endif +#if (Z_ENABLE_PIN > -1) + SET_OUTPUT(Z_ENABLE_PIN); + if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); +#endif +#if (E_ENABLE_PIN > -1) + SET_OUTPUT(E_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); +#endif + + //endstops and pullups +#ifdef ENDSTOPPULLUPS +#if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + WRITE(X_MIN_PIN,HIGH); +#endif +#if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + WRITE(X_MAX_PIN,HIGH); +#endif +#if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + WRITE(Y_MIN_PIN,HIGH); +#endif +#if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + WRITE(Y_MAX_PIN,HIGH); +#endif +#if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + WRITE(Z_MIN_PIN,HIGH); +#endif +#if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + WRITE(Z_MAX_PIN,HIGH); +#endif +#else //ENDSTOPPULLUPS +#if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); +#endif +#if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); +#endif +#if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); +#endif +#if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); +#endif +#if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); +#endif +#if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); +#endif +#endif //ENDSTOPPULLUPS + + + //Initialize Step Pins +#if (X_STEP_PIN > -1) + SET_OUTPUT(X_STEP_PIN); +#endif +#if (Y_STEP_PIN > -1) + SET_OUTPUT(Y_STEP_PIN); +#endif +#if (Z_STEP_PIN > -1) + SET_OUTPUT(Z_STEP_PIN); +#endif +#if (E_STEP_PIN > -1) + SET_OUTPUT(E_STEP_PIN); +#endif + + // waveform generation = 0100 = CTC + TCCR1B &= ~(1< - -#define STREAMING_LIBRARY_VERSION 4 - -// Generic template -template -inline Print &operator <<(Print &stream, T arg) -{ stream.print(arg); return stream; } - -struct _BASED -{ - long val; - int base; - _BASED(long v, int b): val(v), base(b) - {} -}; - -#define _HEX(a) _BASED(a, HEX) -#define _DEC(a) _BASED(a, DEC) -#define _OCT(a) _BASED(a, OCT) -#define _BIN(a) _BASED(a, BIN) -#define _BYTE(a) _BASED(a, BYTE) - -// Specialization for class _BASED -// Thanks to Arduino forum user Ben Combee who suggested this -// clever technique to allow for expressions like -// Serial << _HEX(a); - -inline Print &operator <<(Print &obj, const _BASED &arg) -{ obj.print(arg.val, arg.base); return obj; } - -#if ARDUINO >= 18 -// Specialization for class _FLOAT -// Thanks to Michael Margolis for suggesting a way -// to accommodate Arduino 0018's floating point precision -// feature like this: -// Serial << _FLOAT(gps_latitude, 6); // 6 digits of precision - -struct _FLOAT -{ - float val; - int digits; - _FLOAT(double v, int d): val(v), digits(d) - {} -}; - -inline Print &operator <<(Print &obj, const _FLOAT &arg) -{ obj.print(arg.val, arg.digits); return obj; } -#endif - -// Specialization for enum _EndLineCode -// Thanks to Arduino forum user Paul V. who suggested this -// clever technique to allow for expressions like -// Serial << "Hello!" << endl; - -enum _EndLineCode { endl }; - -inline Print &operator <<(Print &obj, _EndLineCode arg) -{ obj.println(); return obj; } - -#endif - +/* +Streaming.h - Arduino library for supporting the << streaming operator +Copyright (c) 2010 Mikal Hart. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ARDUINO_STREAMING +#define ARDUINO_STREAMING + +//#include + +#define STREAMING_LIBRARY_VERSION 4 + +// Generic template +template +inline Print &operator <<(Print &stream, T arg) +{ stream.print(arg); return stream; } + +struct _BASED +{ + long val; + int base; + _BASED(long v, int b): val(v), base(b) + {} +}; + +#define _HEX(a) _BASED(a, HEX) +#define _DEC(a) _BASED(a, DEC) +#define _OCT(a) _BASED(a, OCT) +#define _BIN(a) _BASED(a, BIN) +#define _BYTE(a) _BASED(a, BYTE) + +// Specialization for class _BASED +// Thanks to Arduino forum user Ben Combee who suggested this +// clever technique to allow for expressions like +// Serial << _HEX(a); + +inline Print &operator <<(Print &obj, const _BASED &arg) +{ obj.print(arg.val, arg.base); return obj; } + +#if ARDUINO >= 18 +// Specialization for class _FLOAT +// Thanks to Michael Margolis for suggesting a way +// to accommodate Arduino 0018's floating point precision +// feature like this: +// Serial << _FLOAT(gps_latitude, 6); // 6 digits of precision + +struct _FLOAT +{ + float val; + int digits; + _FLOAT(double v, int d): val(v), digits(d) + {} +}; + +inline Print &operator <<(Print &obj, const _FLOAT &arg) +{ obj.print(arg.val, arg.digits); return obj; } +#endif + +// Specialization for enum _EndLineCode +// Thanks to Arduino forum user Paul V. who suggested this +// clever technique to allow for expressions like +// Serial << "Hello!" << endl; + +enum _EndLineCode { endl }; + +inline Print &operator <<(Print &obj, _EndLineCode arg) +{ obj.println(); return obj; } + +#endif + diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 5aaf6fd975..ebc772e1d8 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -1,483 +1,483 @@ -/* - temperature.c - temperature control - Part of Marlin - - 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 - - This firmware is optimized for gen6 electronics. - */ - -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "streaming.h" -#include "temperature.h" - -int target_bed_raw = 0; -int current_bed_raw = 0; - -int target_raw[3] = {0, 0, 0}; -int current_raw[3] = {0, 0, 0}; -unsigned char temp_meas_ready = false; - -unsigned long previous_millis_heater, previous_millis_bed_heater; - -#ifdef PIDTEMP - double temp_iState = 0; - double temp_dState = 0; - double pTerm; - double iTerm; - double dTerm; - //int output; - double pid_error; - double temp_iState_min; - double temp_iState_max; - double pid_setpoint = 0.0; - double pid_input; - double pid_output; - bool pid_reset; - float HeaterPower; - - float Kp=DEFAULT_Kp; - float Ki=DEFAULT_Ki; - float Kd=DEFAULT_Kd; - float Kc=DEFAULT_Kc; -#endif //PIDTEMP - -#ifdef MINTEMP -int minttemp = temp2analog(MINTEMP); -#endif //MINTEMP -#ifdef MAXTEMP -int maxttemp = temp2analog(MAXTEMP); -#endif //MAXTEMP - -#ifdef BED_MINTEMP -int bed_minttemp = temp2analog(BED_MINTEMP); -#endif //BED_MINTEMP -#ifdef BED_MAXTEMP -int bed_maxttemp = temp2analog(BED_MAXTEMP); -#endif //BED_MAXTEMP - -void manage_heater() -{ -#ifdef USE_WATCHDOG - wd_reset(); -#endif - - float pid_input; - float pid_output; +/* + temperature.c - temperature control + Part of Marlin + + 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 + + This firmware is optimized for gen6 electronics. + */ + +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "temperature.h" + +int target_bed_raw = 0; +int current_bed_raw = 0; + +int target_raw[3] = {0, 0, 0}; +int current_raw[3] = {0, 0, 0}; +unsigned char temp_meas_ready = false; + +unsigned long previous_millis_heater, previous_millis_bed_heater; + +#ifdef PIDTEMP + double temp_iState = 0; + double temp_dState = 0; + double pTerm; + double iTerm; + double dTerm; + //int output; + double pid_error; + double temp_iState_min; + double temp_iState_max; + double pid_setpoint = 0.0; + double pid_input; + double pid_output; + bool pid_reset; + float HeaterPower; + + float Kp=DEFAULT_Kp; + float Ki=DEFAULT_Ki; + float Kd=DEFAULT_Kd; + float Kc=DEFAULT_Kc; +#endif //PIDTEMP + +#ifdef MINTEMP +int minttemp = temp2analog(MINTEMP); +#endif //MINTEMP +#ifdef MAXTEMP +int maxttemp = temp2analog(MAXTEMP); +#endif //MAXTEMP + +#ifdef BED_MINTEMP +int bed_minttemp = temp2analog(BED_MINTEMP); +#endif //BED_MINTEMP +#ifdef BED_MAXTEMP +int bed_maxttemp = temp2analog(BED_MAXTEMP); +#endif //BED_MAXTEMP + +void manage_heater() +{ +#ifdef USE_WATCHDOG + wd_reset(); +#endif + + float pid_input; + float pid_output; if(temp_meas_ready != true) //better readability return; - -CRITICAL_SECTION_START; - temp_meas_ready = false; -CRITICAL_SECTION_END; - -#ifdef PIDTEMP + +CRITICAL_SECTION_START; + temp_meas_ready = false; +CRITICAL_SECTION_END; + +#ifdef PIDTEMP pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND]); - -#ifndef PID_OPENLOOP - pid_error = pid_setpoint - pid_input; - if(pid_error > 10){ - pid_output = PID_MAX; - pid_reset = true; - } - else if(pid_error < -10) { - pid_output = 0; - pid_reset = true; - } - else { - if(pid_reset == true) { - temp_iState = 0.0; - pid_reset = false; - } - pTerm = Kp * pid_error; - temp_iState += pid_error; - temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); - iTerm = Ki * temp_iState; + +#ifndef PID_OPENLOOP + pid_error = pid_setpoint - pid_input; + if(pid_error > 10){ + pid_output = PID_MAX; + pid_reset = true; + } + else if(pid_error < -10) { + pid_output = 0; + pid_reset = true; + } + else { + if(pid_reset == true) { + temp_iState = 0.0; + pid_reset = false; + } + pTerm = Kp * pid_error; + temp_iState += pid_error; + temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); + iTerm = Ki * temp_iState; //K1 defined in Configuration.h in the PID settings - #define K2 (1.0-K1) - dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); - temp_dState = pid_input; + #define K2 (1.0-K1) + dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); + temp_dState = pid_input; #ifdef PID_ADD_EXTRUSION_RATE pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high #endif - pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); - } -#endif //PID_OPENLOOP -#ifdef PID_DEBUG - Serial.print(" Input "); - Serial.print(pid_input); - Serial.print(" Output "); - Serial.print(pid_output); - Serial.print(" pTerm "); - Serial.print(pTerm); - Serial.print(" iTerm "); - Serial.print(iTerm); - Serial.print(" dTerm "); - Serial.print(dTerm); - Serial.println(); -#endif //PID_DEBUG - analogWrite(HEATER_0_PIN, pid_output); -#endif //PIDTEMP - -#ifndef PIDTEMP - if(current_raw[0] >= target_raw[0]) - { - WRITE(HEATER_0_PIN,LOW); - } - else - { - WRITE(HEATER_0_PIN,HIGH); - } -#endif - - if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) - return; - previous_millis_bed_heater = millis(); - - #if TEMP_1_PIN > -1 + pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); + } +#endif //PID_OPENLOOP +#ifdef PID_DEBUG + Serial.print(" Input "); + Serial.print(pid_input); + Serial.print(" Output "); + Serial.print(pid_output); + Serial.print(" pTerm "); + Serial.print(pTerm); + Serial.print(" iTerm "); + Serial.print(iTerm); + Serial.print(" dTerm "); + Serial.print(dTerm); + Serial.println(); +#endif //PID_DEBUG + analogWrite(HEATER_0_PIN, pid_output); +#endif //PIDTEMP + +#ifndef PIDTEMP + if(current_raw[0] >= target_raw[0]) + { + WRITE(HEATER_0_PIN,LOW); + } + else + { + WRITE(HEATER_0_PIN,HIGH); + } +#endif + + if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) + return; + previous_millis_bed_heater = millis(); + + #if TEMP_1_PIN > -1 if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) - { - WRITE(HEATER_1_PIN,LOW); - } - else - { - WRITE(HEATER_1_PIN,HIGH); - } - #endif - } - -// Takes hot end temperature value as input and returns corresponding raw value. -// For a thermistor, it uses the RepRap thermistor temp table. -// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. -// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -float temp2analog(int celsius) { - #ifdef HEATER_USES_THERMISTOR_1 - int raw = 0; - byte i; - - for (i=1; i raw) - { - celsius = temptable_1[i-1][1] + - (raw - temptable_1[i-1][0]) * - (temptable_1[i][1] - temptable_1[i-1][1]) / - (temptable_1[i][0] - temptable_1[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == NUMTEMPS_HEATER_1) celsius = temptable_1[i-1][1]; - - return celsius; - #elif defined HEATER_1_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -// Derived from RepRap FiveD extruder::getTemperature() -// For bed temperature measurement. -float analog2tempBed(int raw) { - #ifdef BED_USES_THERMISTOR - int celsius = 0; - byte i; - - raw = (1023 * OVERSAMPLENR) - raw; - - for (i=1; i raw) - { - celsius = bedtemptable[i-1][1] + - (raw - bedtemptable[i-1][0]) * - (bedtemptable[i][1] - bedtemptable[i-1][1]) / - (bedtemptable[i][0] - bedtemptable[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; - - return celsius; - - #elif defined BED_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -void tp_init() -{ -#if (HEATER_0_PIN > -1) - SET_OUTPUT(HEATER_0_PIN); -#endif -#if (HEATER_1_PIN > -1) - SET_OUTPUT(HEATER_1_PIN); -#endif -#if (HEATER_2_PIN > -1) - SET_OUTPUT(HEATER_2_PIN); -#endif - -#ifdef PIDTEMP - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; -#endif //PIDTEMP - -// Set analog inputs - ADCSRA = 1< -1) - #if TEMP_0_PIN < 8 - DIDR0 = 1 << TEMP_0_PIN; - #else - DIDR2 = 1<<(TEMP_0_PIN - 8); - ADCSRB = 1< -1) - raw_temp_0_value += ADC; - #endif - temp_state = 2; - break; - case 2: // Prepare TEMP_1 - #if (TEMP_1_PIN > -1) - #if TEMP_1_PIN < 7 - DIDR0 = 1< -1) - raw_temp_1_value += ADC; - #endif - temp_state = 4; - break; - case 4: // Prepare TEMP_2 - #if (TEMP_2_PIN > -1) - #if TEMP_2_PIN < 7 - DIDR0 = 1 << TEMP_2_PIN; - #else - DIDR2 = 1<<(TEMP_2_PIN - 8); - ADCSRB = 1< -1) - raw_temp_2_value += ADC; - #endif - temp_state = 0; - temp_count++; - break; - default: - Serial.println("!! Temp measurement error !!"); - break; - } - - if(temp_count >= 16) // 6 ms * 16 = 96ms. - { - #ifdef HEATER_1_USES_AD595 - current_raw[0] = raw_temp_0_value; - #else - current_raw[0] = 16383 - raw_temp_0_value; - #endif - - #ifdef HEATER_2_USES_AD595 - current_raw[2] = raw_temp_2_value; - #else - current_raw[2] = 16383 - raw_temp_2_value; - #endif - - #ifdef BED_USES_AD595 - current_raw[1] = raw_temp_1_value; - #else - current_raw[1] = 16383 - raw_temp_1_value; - #endif - - temp_meas_ready = true; - temp_count = 0; - raw_temp_0_value = 0; - raw_temp_1_value = 0; - raw_temp_2_value = 0; -#ifdef MAXTEMP - #if (HEATER_0_PIN > -1) + { + WRITE(HEATER_1_PIN,LOW); + } + else + { + WRITE(HEATER_1_PIN,HIGH); + } + #endif + } + +// Takes hot end temperature value as input and returns corresponding raw value. +// For a thermistor, it uses the RepRap thermistor temp table. +// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. +// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. +float temp2analog(int celsius) { + #ifdef HEATER_USES_THERMISTOR_1 + int raw = 0; + byte i; + + for (i=1; i raw) + { + celsius = temptable_1[i-1][1] + + (raw - temptable_1[i-1][0]) * + (temptable_1[i][1] - temptable_1[i-1][1]) / + (temptable_1[i][0] - temptable_1[i-1][0]); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == NUMTEMPS_HEATER_1) celsius = temptable_1[i-1][1]; + + return celsius; + #elif defined HEATER_1_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +// Derived from RepRap FiveD extruder::getTemperature() +// For bed temperature measurement. +float analog2tempBed(int raw) { + #ifdef BED_USES_THERMISTOR + int celsius = 0; + byte i; + + raw = (1023 * OVERSAMPLENR) - raw; + + for (i=1; i raw) + { + celsius = bedtemptable[i-1][1] + + (raw - bedtemptable[i-1][0]) * + (bedtemptable[i][1] - bedtemptable[i-1][1]) / + (bedtemptable[i][0] - bedtemptable[i-1][0]); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; + + return celsius; + + #elif defined BED_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +void tp_init() +{ +#if (HEATER_0_PIN > -1) + SET_OUTPUT(HEATER_0_PIN); +#endif +#if (HEATER_1_PIN > -1) + SET_OUTPUT(HEATER_1_PIN); +#endif +#if (HEATER_2_PIN > -1) + SET_OUTPUT(HEATER_2_PIN); +#endif + +#ifdef PIDTEMP + temp_iState_min = 0.0; + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; +#endif //PIDTEMP + +// Set analog inputs + ADCSRA = 1< -1) + #if TEMP_0_PIN < 8 + DIDR0 = 1 << TEMP_0_PIN; + #else + DIDR2 = 1<<(TEMP_0_PIN - 8); + ADCSRB = 1< -1) + raw_temp_0_value += ADC; + #endif + temp_state = 2; + break; + case 2: // Prepare TEMP_1 + #if (TEMP_1_PIN > -1) + #if TEMP_1_PIN < 7 + DIDR0 = 1< -1) + raw_temp_1_value += ADC; + #endif + temp_state = 4; + break; + case 4: // Prepare TEMP_2 + #if (TEMP_2_PIN > -1) + #if TEMP_2_PIN < 7 + DIDR0 = 1 << TEMP_2_PIN; + #else + DIDR2 = 1<<(TEMP_2_PIN - 8); + ADCSRB = 1< -1) + raw_temp_2_value += ADC; + #endif + temp_state = 0; + temp_count++; + break; + default: + Serial.println("!! Temp measurement error !!"); + break; + } + + if(temp_count >= 16) // 6 ms * 16 = 96ms. + { + #ifdef HEATER_1_USES_AD595 + current_raw[0] = raw_temp_0_value; + #else + current_raw[0] = 16383 - raw_temp_0_value; + #endif + + #ifdef HEATER_2_USES_AD595 + current_raw[2] = raw_temp_2_value; + #else + current_raw[2] = 16383 - raw_temp_2_value; + #endif + + #ifdef BED_USES_AD595 + current_raw[1] = raw_temp_1_value; + #else + current_raw[1] = 16383 - raw_temp_1_value; + #endif + + temp_meas_ready = true; + temp_count = 0; + raw_temp_0_value = 0; + raw_temp_1_value = 0; + raw_temp_2_value = 0; +#ifdef MAXTEMP + #if (HEATER_0_PIN > -1) if(current_raw[TEMPSENSOR_HOTEND] >= maxttemp) { target_raw[TEMPSENSOR_HOTEND] = 0; - analogWrite(HEATER_0_PIN, 0); - Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); - } - #endif - #if (HEATER_2_PIN > -1) + analogWrite(HEATER_0_PIN, 0); + Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); + } + #endif + #if (HEATER_2_PIN > -1) if(current_raw[TEMPSENSOR_AUX] >= maxttemp) { target_raw[TEMPSENSOR_AUX] = 0; - analogWrite(HEATER_2_PIN, 0); - Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); - } - #endif -#endif //MAXTEMP -#ifdef MINTEMP - #if (HEATER_0_PIN > -1) + analogWrite(HEATER_2_PIN, 0); + Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); + } + #endif +#endif //MAXTEMP +#ifdef MINTEMP + #if (HEATER_0_PIN > -1) if(current_raw[TEMPSENSOR_HOTEND] <= minttemp) { target_raw[TEMPSENSOR_HOTEND] = 0; - analogWrite(HEATER_0_PIN, 0); - Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); - } - #endif - #if (HEATER_2_PIN > -1) + analogWrite(HEATER_0_PIN, 0); + Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); + } + #endif + #if (HEATER_2_PIN > -1) if(current_raw[TEMPSENSOR_AUX] <= minttemp) { target_raw[TEMPSENSOR_AUX] = 0; - analogWrite(HEATER_2_PIN, 0); - Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); - } - #endif -#endif //MAXTEMP -#ifdef BED_MINTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] <= bed_minttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); - } - #endif -#endif -#ifdef BED_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] >= bed_maxttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); - } - #endif -#endif - } -} + analogWrite(HEATER_2_PIN, 0); + Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); + } + #endif +#endif //MAXTEMP +#ifdef BED_MINTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] <= bed_minttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); + } + #endif +#endif +#ifdef BED_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] >= bed_maxttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); + } + #endif +#endif + } +} diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 6d43d72735..fcefa550f1 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -1,410 +1,410 @@ -#ifndef THERMISTORTABLES_H_ -#define THERMISTORTABLES_H_ - -#define OVERSAMPLENR 16 - -#if (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor - -#define NUMTEMPS_1 61 -const short temptable_1[NUMTEMPS_1][2] = { -{ 23*OVERSAMPLENR , 300 }, -{ 25*OVERSAMPLENR , 295 }, -{ 27*OVERSAMPLENR , 290 }, -{ 28*OVERSAMPLENR , 285 }, -{ 31*OVERSAMPLENR , 280 }, -{ 33*OVERSAMPLENR , 275 }, -{ 35*OVERSAMPLENR , 270 }, -{ 38*OVERSAMPLENR , 265 }, -{ 41*OVERSAMPLENR , 260 }, -{ 44*OVERSAMPLENR , 255 }, -{ 48*OVERSAMPLENR , 250 }, -{ 52*OVERSAMPLENR , 245 }, -{ 56*OVERSAMPLENR , 240 }, -{ 61*OVERSAMPLENR , 235 }, -{ 66*OVERSAMPLENR , 230 }, -{ 71*OVERSAMPLENR , 225 }, -{ 78*OVERSAMPLENR , 220 }, -{ 84*OVERSAMPLENR , 215 }, -{ 92*OVERSAMPLENR , 210 }, -{ 100*OVERSAMPLENR , 205 }, -{ 109*OVERSAMPLENR , 200 }, -{ 120*OVERSAMPLENR , 195 }, -{ 131*OVERSAMPLENR , 190 }, -{ 143*OVERSAMPLENR , 185 }, -{ 156*OVERSAMPLENR , 180 }, -{ 171*OVERSAMPLENR , 175 }, -{ 187*OVERSAMPLENR , 170 }, -{ 205*OVERSAMPLENR , 165 }, -{ 224*OVERSAMPLENR , 160 }, -{ 245*OVERSAMPLENR , 155 }, -{ 268*OVERSAMPLENR , 150 }, -{ 293*OVERSAMPLENR , 145 }, -{ 320*OVERSAMPLENR , 140 }, -{ 348*OVERSAMPLENR , 135 }, -{ 379*OVERSAMPLENR , 130 }, -{ 411*OVERSAMPLENR , 125 }, -{ 445*OVERSAMPLENR , 120 }, -{ 480*OVERSAMPLENR , 115 }, -{ 516*OVERSAMPLENR , 110 }, -{ 553*OVERSAMPLENR , 105 }, -{ 591*OVERSAMPLENR , 100 }, -{ 628*OVERSAMPLENR , 95 }, -{ 665*OVERSAMPLENR , 90 }, -{ 702*OVERSAMPLENR , 85 }, -{ 737*OVERSAMPLENR , 80 }, -{ 770*OVERSAMPLENR , 75 }, -{ 801*OVERSAMPLENR , 70 }, -{ 830*OVERSAMPLENR , 65 }, -{ 857*OVERSAMPLENR , 60 }, -{ 881*OVERSAMPLENR , 55 }, -{ 903*OVERSAMPLENR , 50 }, -{ 922*OVERSAMPLENR , 45 }, -{ 939*OVERSAMPLENR , 40 }, -{ 954*OVERSAMPLENR , 35 }, -{ 966*OVERSAMPLENR , 30 }, -{ 977*OVERSAMPLENR , 25 }, -{ 985*OVERSAMPLENR , 20 }, -{ 993*OVERSAMPLENR , 15 }, -{ 999*OVERSAMPLENR , 10 }, -{ 1004*OVERSAMPLENR , 5 }, -{ 1008*OVERSAMPLENR , 0 } //safety -}; -#endif -#if (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor -#define NUMTEMPS_2 21 -const short temptable_2[NUMTEMPS_2][2] = { - {1*OVERSAMPLENR, 848}, - {54*OVERSAMPLENR, 275}, - {107*OVERSAMPLENR, 228}, - {160*OVERSAMPLENR, 202}, - {213*OVERSAMPLENR, 185}, - {266*OVERSAMPLENR, 171}, - {319*OVERSAMPLENR, 160}, - {372*OVERSAMPLENR, 150}, - {425*OVERSAMPLENR, 141}, - {478*OVERSAMPLENR, 133}, - {531*OVERSAMPLENR, 125}, - {584*OVERSAMPLENR, 118}, - {637*OVERSAMPLENR, 110}, - {690*OVERSAMPLENR, 103}, - {743*OVERSAMPLENR, 95}, - {796*OVERSAMPLENR, 86}, - {849*OVERSAMPLENR, 77}, - {902*OVERSAMPLENR, 65}, - {955*OVERSAMPLENR, 49}, - {1008*OVERSAMPLENR, 17}, - {1020*OVERSAMPLENR, 0} //safety -}; - -#endif -#if (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts -#define NUMTEMPS_3 28 -const short temptable_3[NUMTEMPS_3][2] = { - {1*OVERSAMPLENR,864}, - {21*OVERSAMPLENR,300}, - {25*OVERSAMPLENR,290}, - {29*OVERSAMPLENR,280}, - {33*OVERSAMPLENR,270}, - {39*OVERSAMPLENR,260}, - {46*OVERSAMPLENR,250}, - {54*OVERSAMPLENR,240}, - {64*OVERSAMPLENR,230}, - {75*OVERSAMPLENR,220}, - {90*OVERSAMPLENR,210}, - {107*OVERSAMPLENR,200}, - {128*OVERSAMPLENR,190}, - {154*OVERSAMPLENR,180}, - {184*OVERSAMPLENR,170}, - {221*OVERSAMPLENR,160}, - {265*OVERSAMPLENR,150}, - {316*OVERSAMPLENR,140}, - {375*OVERSAMPLENR,130}, - {441*OVERSAMPLENR,120}, - {513*OVERSAMPLENR,110}, - {588*OVERSAMPLENR,100}, - {734*OVERSAMPLENR,80}, - {856*OVERSAMPLENR,60}, - {938*OVERSAMPLENR,40}, - {986*OVERSAMPLENR,20}, - {1008*OVERSAMPLENR,0}, - {1018*OVERSAMPLENR,-20} - }; - -#endif -#if (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor - -#define NUMTEMPS_4 20 -short temptable_4[NUMTEMPS_4][2] = { - {1*OVERSAMPLENR, 430}, - {54*OVERSAMPLENR, 137}, - {107*OVERSAMPLENR, 107}, - {160*OVERSAMPLENR, 91}, - {213*OVERSAMPLENR, 80}, - {266*OVERSAMPLENR, 71}, - {319*OVERSAMPLENR, 64}, - {372*OVERSAMPLENR, 57}, - {425*OVERSAMPLENR, 51}, - {478*OVERSAMPLENR, 46}, - {531*OVERSAMPLENR, 41}, - {584*OVERSAMPLENR, 35}, - {637*OVERSAMPLENR, 30}, - {690*OVERSAMPLENR, 25}, - {743*OVERSAMPLENR, 20}, - {796*OVERSAMPLENR, 14}, - {849*OVERSAMPLENR, 7}, - {902*OVERSAMPLENR, 0}, - {955*OVERSAMPLENR, -11}, - {1008*OVERSAMPLENR, -35} -}; -#endif - -#if (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) - -#define NUMTEMPS_5 61 -const short temptable_5[NUMTEMPS_5][2] = { -{1*OVERSAMPLENR, 713}, -{18*OVERSAMPLENR, 316}, -{35*OVERSAMPLENR, 266}, -{52*OVERSAMPLENR, 239}, -{69*OVERSAMPLENR, 221}, -{86*OVERSAMPLENR, 208}, -{103*OVERSAMPLENR, 197}, -{120*OVERSAMPLENR, 188}, -{137*OVERSAMPLENR, 181}, -{154*OVERSAMPLENR, 174}, -{171*OVERSAMPLENR, 169}, -{188*OVERSAMPLENR, 163}, -{205*OVERSAMPLENR, 159}, -{222*OVERSAMPLENR, 154}, -{239*OVERSAMPLENR, 150}, -{256*OVERSAMPLENR, 147}, -{273*OVERSAMPLENR, 143}, -{290*OVERSAMPLENR, 140}, -{307*OVERSAMPLENR, 136}, -{324*OVERSAMPLENR, 133}, -{341*OVERSAMPLENR, 130}, -{358*OVERSAMPLENR, 128}, -{375*OVERSAMPLENR, 125}, -{392*OVERSAMPLENR, 122}, -{409*OVERSAMPLENR, 120}, -{426*OVERSAMPLENR, 117}, -{443*OVERSAMPLENR, 115}, -{460*OVERSAMPLENR, 112}, -{477*OVERSAMPLENR, 110}, -{494*OVERSAMPLENR, 108}, -{511*OVERSAMPLENR, 106}, -{528*OVERSAMPLENR, 103}, -{545*OVERSAMPLENR, 101}, -{562*OVERSAMPLENR, 99}, -{579*OVERSAMPLENR, 97}, -{596*OVERSAMPLENR, 95}, -{613*OVERSAMPLENR, 92}, -{630*OVERSAMPLENR, 90}, -{647*OVERSAMPLENR, 88}, -{664*OVERSAMPLENR, 86}, -{681*OVERSAMPLENR, 84}, -{698*OVERSAMPLENR, 81}, -{715*OVERSAMPLENR, 79}, -{732*OVERSAMPLENR, 77}, -{749*OVERSAMPLENR, 75}, -{766*OVERSAMPLENR, 72}, -{783*OVERSAMPLENR, 70}, -{800*OVERSAMPLENR, 67}, -{817*OVERSAMPLENR, 64}, -{834*OVERSAMPLENR, 61}, -{851*OVERSAMPLENR, 58}, -{868*OVERSAMPLENR, 55}, -{885*OVERSAMPLENR, 52}, -{902*OVERSAMPLENR, 48}, -{919*OVERSAMPLENR, 44}, -{936*OVERSAMPLENR, 40}, -{953*OVERSAMPLENR, 34}, -{970*OVERSAMPLENR, 28}, -{987*OVERSAMPLENR, 20}, -{1004*OVERSAMPLENR, 8}, -{1021*OVERSAMPLENR, 0} -}; -#endif - -#if (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor -#define NUMTEMPS_6 36 -const short temptable_6[NUMTEMPS_6][2] = { - {28*OVERSAMPLENR, 250}, - {31*OVERSAMPLENR, 245}, - {35*OVERSAMPLENR, 240}, - {39*OVERSAMPLENR, 235}, - {42*OVERSAMPLENR, 230}, - {44*OVERSAMPLENR, 225}, - {49*OVERSAMPLENR, 220}, - {53*OVERSAMPLENR, 215}, - {62*OVERSAMPLENR, 210}, - {73*OVERSAMPLENR, 205}, - {72*OVERSAMPLENR, 200}, - {94*OVERSAMPLENR, 190}, - {102*OVERSAMPLENR, 185}, - {116*OVERSAMPLENR, 170}, - {143*OVERSAMPLENR, 160}, - {183*OVERSAMPLENR, 150}, - {223*OVERSAMPLENR, 140}, - {270*OVERSAMPLENR, 130}, - {318*OVERSAMPLENR, 120}, - {383*OVERSAMPLENR, 110}, - {413*OVERSAMPLENR, 105}, - {439*OVERSAMPLENR, 100}, - {484*OVERSAMPLENR, 95}, - {513*OVERSAMPLENR, 90}, - {607*OVERSAMPLENR, 80}, - {664*OVERSAMPLENR, 70}, - {781*OVERSAMPLENR, 60}, - {810*OVERSAMPLENR, 55}, - {849*OVERSAMPLENR, 50}, - {914*OVERSAMPLENR, 45}, - {914*OVERSAMPLENR, 40}, - {935*OVERSAMPLENR, 35}, - {954*OVERSAMPLENR, 30}, - {970*OVERSAMPLENR, 25}, - {978*OVERSAMPLENR, 22}, - {1008*OVERSAMPLENR, 3} -}; -#endif - -#if (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 -#define NUMTEMPS_7 54 -const short temptable_7[NUMTEMPS_7][2] = { - {46*OVERSAMPLENR, 270}, - {50*OVERSAMPLENR, 265}, - {54*OVERSAMPLENR, 260}, - {58*OVERSAMPLENR, 255}, - {62*OVERSAMPLENR, 250}, - {67*OVERSAMPLENR, 245}, - {72*OVERSAMPLENR, 240}, - {79*OVERSAMPLENR, 235}, - {85*OVERSAMPLENR, 230}, - {91*OVERSAMPLENR, 225}, - {99*OVERSAMPLENR, 220}, - {107*OVERSAMPLENR, 215}, - {116*OVERSAMPLENR, 210}, - {126*OVERSAMPLENR, 205}, - {136*OVERSAMPLENR, 200}, - {149*OVERSAMPLENR, 195}, - {160*OVERSAMPLENR, 190}, - {175*OVERSAMPLENR, 185}, - {191*OVERSAMPLENR, 180}, - {209*OVERSAMPLENR, 175}, - {224*OVERSAMPLENR, 170}, - {246*OVERSAMPLENR, 165}, - {267*OVERSAMPLENR, 160}, - {293*OVERSAMPLENR, 155}, - {316*OVERSAMPLENR, 150}, - {340*OVERSAMPLENR, 145}, - {364*OVERSAMPLENR, 140}, - {396*OVERSAMPLENR, 135}, - {425*OVERSAMPLENR, 130}, - {460*OVERSAMPLENR, 125}, - {489*OVERSAMPLENR, 120}, - {526*OVERSAMPLENR, 115}, - {558*OVERSAMPLENR, 110}, - {591*OVERSAMPLENR, 105}, - {628*OVERSAMPLENR, 100}, - {660*OVERSAMPLENR, 95}, - {696*OVERSAMPLENR, 90}, - {733*OVERSAMPLENR, 85}, - {761*OVERSAMPLENR, 80}, - {794*OVERSAMPLENR, 75}, - {819*OVERSAMPLENR, 70}, - {847*OVERSAMPLENR, 65}, - {870*OVERSAMPLENR, 60}, - {892*OVERSAMPLENR, 55}, - {911*OVERSAMPLENR, 50}, - {929*OVERSAMPLENR, 45}, - {944*OVERSAMPLENR, 40}, - {959*OVERSAMPLENR, 35}, - {971*OVERSAMPLENR, 30}, - {981*OVERSAMPLENR, 25}, - {989*OVERSAMPLENR, 20}, - {994*OVERSAMPLENR, 15}, - {1001*OVERSAMPLENR, 10}, - {1005*OVERSAMPLENR, 5} -}; -#endif - - - -#if THERMISTORHEATER_1 == 1 -#define NUMTEMPS_HEATER_1 NUMTEMPS_1 -#define temptable_1 temptable_1 -#elif THERMISTORHEATER_1 == 2 -#define NUMTEMPS_HEATER_1 NUMTEMPS_2 -#define temptable_1 temptable_2 -#elif THERMISTORHEATER_1 == 3 -#define NUMTEMPS_HEATER_1 NUMTEMPS_3 -#define temptable_1 temptable_3 -#elif THERMISTORHEATER_1 == 4 -#define NUMTEMPS_HEATER_1 NUMTEMPS_4 -#define temptable_1 temptable_4 -#elif THERMISTORHEATER_1 == 5 -#define NUMTEMPS_HEATER_1 NUMTEMPS_5 -#define temptable_1 temptable_5 -#elif THERMISTORHEATER_1 == 6 -#define NUMTEMPS_HEATER_1 NUMTEMPS_6 -#define temptable_1 temptable_6 -#elif THERMISTORHEATER_1 == 7 -#define NUMTEMPS_HEATER_1 NUMTEMPS_7 -#define temptable_1 temptable_7 -#elif defined HEATER_1_USES_THERMISTOR -#error No heater 1 thermistor table specified -#endif - -#if THERMISTORHEATER_2 == 1 -#define NUMTEMPS_HEATER_2 NUMTEMPS_1 -#define temptable_2 temptable_1 -#elif THERMISTORHEATER_2 == 2 -#define NUMTEMPS_HEATER_2 NUMTEMPS_2 -#define temptable_2 temptable_2 -#elif THERMISTORHEATER_2 == 3 -#define NUMTEMPS_HEATER_2 NUMTEMPS_3 -#define temptable_2 temptable_3 -#elif THERMISTORHEATER_2 == 4 -#define NUMTEMPS_HEATER_2 NUMTEMPS_4 -#define temptable_2 temptable_4 -#elif THERMISTORHEATER_2 == 5 -#define NUMTEMPS_HEATER_2 NUMTEMPS_5 -#define temptable_2 temptable_5 -#elif THERMISTORHEATER_2 == 6 -#define NUMTEMPS_HEATER_2 NUMTEMPS_6 -#define temptable_2 temptable_6 -#elif THERMISTORHEATER_2 == 7 -#define NUMTEMPS_HEATER22 NUMTEMPS_7 -#define temptable_2 temptable_7 -#elif defined HEATER_2_USES_THERMISTOR -#error No heater 2 thermistor table specified -#endif - - -#if THERMISTORBED == 1 -#define BNUMTEMPS NUMTEMPS_1 -#define bedtemptable temptable_1 -#elif THERMISTORBED == 2 -#define BNUMTEMPS NUMTEMPS_2 -#define bedtemptable temptable_2 -#elif THERMISTORBED == 3 -#define BNUMTEMPS NUMTEMPS_3 -#define bedtemptable temptable_3 -#elif THERMISTORBED == 4 -#define BNUMTEMPS NUMTEMPS_4 -#define bedtemptable temptable_4 -#elif THERMISTORBED == 5 -#define BNUMTEMPS NUMTEMPS_5 -#define bedtemptable temptable_5 -#elif THERMISTORBED == 6 -#define BNUMTEMPS NUMTEMPS_6 -#define bedtemptable temptable_6 -#elif THERMISTORBED == 7 -#define BNUMTEMPS NUMTEMPS_7 -#define bedtemptable temptable_7 -#elif defined BED_USES_THERMISTOR -#error No bed thermistor table specified -#endif - -#endif //THERMISTORTABLES_H_ - +#ifndef THERMISTORTABLES_H_ +#define THERMISTORTABLES_H_ + +#define OVERSAMPLENR 16 + +#if (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor + +#define NUMTEMPS_1 61 +const short temptable_1[NUMTEMPS_1][2] = { +{ 23*OVERSAMPLENR , 300 }, +{ 25*OVERSAMPLENR , 295 }, +{ 27*OVERSAMPLENR , 290 }, +{ 28*OVERSAMPLENR , 285 }, +{ 31*OVERSAMPLENR , 280 }, +{ 33*OVERSAMPLENR , 275 }, +{ 35*OVERSAMPLENR , 270 }, +{ 38*OVERSAMPLENR , 265 }, +{ 41*OVERSAMPLENR , 260 }, +{ 44*OVERSAMPLENR , 255 }, +{ 48*OVERSAMPLENR , 250 }, +{ 52*OVERSAMPLENR , 245 }, +{ 56*OVERSAMPLENR , 240 }, +{ 61*OVERSAMPLENR , 235 }, +{ 66*OVERSAMPLENR , 230 }, +{ 71*OVERSAMPLENR , 225 }, +{ 78*OVERSAMPLENR , 220 }, +{ 84*OVERSAMPLENR , 215 }, +{ 92*OVERSAMPLENR , 210 }, +{ 100*OVERSAMPLENR , 205 }, +{ 109*OVERSAMPLENR , 200 }, +{ 120*OVERSAMPLENR , 195 }, +{ 131*OVERSAMPLENR , 190 }, +{ 143*OVERSAMPLENR , 185 }, +{ 156*OVERSAMPLENR , 180 }, +{ 171*OVERSAMPLENR , 175 }, +{ 187*OVERSAMPLENR , 170 }, +{ 205*OVERSAMPLENR , 165 }, +{ 224*OVERSAMPLENR , 160 }, +{ 245*OVERSAMPLENR , 155 }, +{ 268*OVERSAMPLENR , 150 }, +{ 293*OVERSAMPLENR , 145 }, +{ 320*OVERSAMPLENR , 140 }, +{ 348*OVERSAMPLENR , 135 }, +{ 379*OVERSAMPLENR , 130 }, +{ 411*OVERSAMPLENR , 125 }, +{ 445*OVERSAMPLENR , 120 }, +{ 480*OVERSAMPLENR , 115 }, +{ 516*OVERSAMPLENR , 110 }, +{ 553*OVERSAMPLENR , 105 }, +{ 591*OVERSAMPLENR , 100 }, +{ 628*OVERSAMPLENR , 95 }, +{ 665*OVERSAMPLENR , 90 }, +{ 702*OVERSAMPLENR , 85 }, +{ 737*OVERSAMPLENR , 80 }, +{ 770*OVERSAMPLENR , 75 }, +{ 801*OVERSAMPLENR , 70 }, +{ 830*OVERSAMPLENR , 65 }, +{ 857*OVERSAMPLENR , 60 }, +{ 881*OVERSAMPLENR , 55 }, +{ 903*OVERSAMPLENR , 50 }, +{ 922*OVERSAMPLENR , 45 }, +{ 939*OVERSAMPLENR , 40 }, +{ 954*OVERSAMPLENR , 35 }, +{ 966*OVERSAMPLENR , 30 }, +{ 977*OVERSAMPLENR , 25 }, +{ 985*OVERSAMPLENR , 20 }, +{ 993*OVERSAMPLENR , 15 }, +{ 999*OVERSAMPLENR , 10 }, +{ 1004*OVERSAMPLENR , 5 }, +{ 1008*OVERSAMPLENR , 0 } //safety +}; +#endif +#if (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor +#define NUMTEMPS_2 21 +const short temptable_2[NUMTEMPS_2][2] = { + {1*OVERSAMPLENR, 848}, + {54*OVERSAMPLENR, 275}, + {107*OVERSAMPLENR, 228}, + {160*OVERSAMPLENR, 202}, + {213*OVERSAMPLENR, 185}, + {266*OVERSAMPLENR, 171}, + {319*OVERSAMPLENR, 160}, + {372*OVERSAMPLENR, 150}, + {425*OVERSAMPLENR, 141}, + {478*OVERSAMPLENR, 133}, + {531*OVERSAMPLENR, 125}, + {584*OVERSAMPLENR, 118}, + {637*OVERSAMPLENR, 110}, + {690*OVERSAMPLENR, 103}, + {743*OVERSAMPLENR, 95}, + {796*OVERSAMPLENR, 86}, + {849*OVERSAMPLENR, 77}, + {902*OVERSAMPLENR, 65}, + {955*OVERSAMPLENR, 49}, + {1008*OVERSAMPLENR, 17}, + {1020*OVERSAMPLENR, 0} //safety +}; + +#endif +#if (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts +#define NUMTEMPS_3 28 +const short temptable_3[NUMTEMPS_3][2] = { + {1*OVERSAMPLENR,864}, + {21*OVERSAMPLENR,300}, + {25*OVERSAMPLENR,290}, + {29*OVERSAMPLENR,280}, + {33*OVERSAMPLENR,270}, + {39*OVERSAMPLENR,260}, + {46*OVERSAMPLENR,250}, + {54*OVERSAMPLENR,240}, + {64*OVERSAMPLENR,230}, + {75*OVERSAMPLENR,220}, + {90*OVERSAMPLENR,210}, + {107*OVERSAMPLENR,200}, + {128*OVERSAMPLENR,190}, + {154*OVERSAMPLENR,180}, + {184*OVERSAMPLENR,170}, + {221*OVERSAMPLENR,160}, + {265*OVERSAMPLENR,150}, + {316*OVERSAMPLENR,140}, + {375*OVERSAMPLENR,130}, + {441*OVERSAMPLENR,120}, + {513*OVERSAMPLENR,110}, + {588*OVERSAMPLENR,100}, + {734*OVERSAMPLENR,80}, + {856*OVERSAMPLENR,60}, + {938*OVERSAMPLENR,40}, + {986*OVERSAMPLENR,20}, + {1008*OVERSAMPLENR,0}, + {1018*OVERSAMPLENR,-20} + }; + +#endif +#if (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor + +#define NUMTEMPS_4 20 +short temptable_4[NUMTEMPS_4][2] = { + {1*OVERSAMPLENR, 430}, + {54*OVERSAMPLENR, 137}, + {107*OVERSAMPLENR, 107}, + {160*OVERSAMPLENR, 91}, + {213*OVERSAMPLENR, 80}, + {266*OVERSAMPLENR, 71}, + {319*OVERSAMPLENR, 64}, + {372*OVERSAMPLENR, 57}, + {425*OVERSAMPLENR, 51}, + {478*OVERSAMPLENR, 46}, + {531*OVERSAMPLENR, 41}, + {584*OVERSAMPLENR, 35}, + {637*OVERSAMPLENR, 30}, + {690*OVERSAMPLENR, 25}, + {743*OVERSAMPLENR, 20}, + {796*OVERSAMPLENR, 14}, + {849*OVERSAMPLENR, 7}, + {902*OVERSAMPLENR, 0}, + {955*OVERSAMPLENR, -11}, + {1008*OVERSAMPLENR, -35} +}; +#endif + +#if (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) + +#define NUMTEMPS_5 61 +const short temptable_5[NUMTEMPS_5][2] = { +{1*OVERSAMPLENR, 713}, +{18*OVERSAMPLENR, 316}, +{35*OVERSAMPLENR, 266}, +{52*OVERSAMPLENR, 239}, +{69*OVERSAMPLENR, 221}, +{86*OVERSAMPLENR, 208}, +{103*OVERSAMPLENR, 197}, +{120*OVERSAMPLENR, 188}, +{137*OVERSAMPLENR, 181}, +{154*OVERSAMPLENR, 174}, +{171*OVERSAMPLENR, 169}, +{188*OVERSAMPLENR, 163}, +{205*OVERSAMPLENR, 159}, +{222*OVERSAMPLENR, 154}, +{239*OVERSAMPLENR, 150}, +{256*OVERSAMPLENR, 147}, +{273*OVERSAMPLENR, 143}, +{290*OVERSAMPLENR, 140}, +{307*OVERSAMPLENR, 136}, +{324*OVERSAMPLENR, 133}, +{341*OVERSAMPLENR, 130}, +{358*OVERSAMPLENR, 128}, +{375*OVERSAMPLENR, 125}, +{392*OVERSAMPLENR, 122}, +{409*OVERSAMPLENR, 120}, +{426*OVERSAMPLENR, 117}, +{443*OVERSAMPLENR, 115}, +{460*OVERSAMPLENR, 112}, +{477*OVERSAMPLENR, 110}, +{494*OVERSAMPLENR, 108}, +{511*OVERSAMPLENR, 106}, +{528*OVERSAMPLENR, 103}, +{545*OVERSAMPLENR, 101}, +{562*OVERSAMPLENR, 99}, +{579*OVERSAMPLENR, 97}, +{596*OVERSAMPLENR, 95}, +{613*OVERSAMPLENR, 92}, +{630*OVERSAMPLENR, 90}, +{647*OVERSAMPLENR, 88}, +{664*OVERSAMPLENR, 86}, +{681*OVERSAMPLENR, 84}, +{698*OVERSAMPLENR, 81}, +{715*OVERSAMPLENR, 79}, +{732*OVERSAMPLENR, 77}, +{749*OVERSAMPLENR, 75}, +{766*OVERSAMPLENR, 72}, +{783*OVERSAMPLENR, 70}, +{800*OVERSAMPLENR, 67}, +{817*OVERSAMPLENR, 64}, +{834*OVERSAMPLENR, 61}, +{851*OVERSAMPLENR, 58}, +{868*OVERSAMPLENR, 55}, +{885*OVERSAMPLENR, 52}, +{902*OVERSAMPLENR, 48}, +{919*OVERSAMPLENR, 44}, +{936*OVERSAMPLENR, 40}, +{953*OVERSAMPLENR, 34}, +{970*OVERSAMPLENR, 28}, +{987*OVERSAMPLENR, 20}, +{1004*OVERSAMPLENR, 8}, +{1021*OVERSAMPLENR, 0} +}; +#endif + +#if (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor +#define NUMTEMPS_6 36 +const short temptable_6[NUMTEMPS_6][2] = { + {28*OVERSAMPLENR, 250}, + {31*OVERSAMPLENR, 245}, + {35*OVERSAMPLENR, 240}, + {39*OVERSAMPLENR, 235}, + {42*OVERSAMPLENR, 230}, + {44*OVERSAMPLENR, 225}, + {49*OVERSAMPLENR, 220}, + {53*OVERSAMPLENR, 215}, + {62*OVERSAMPLENR, 210}, + {73*OVERSAMPLENR, 205}, + {72*OVERSAMPLENR, 200}, + {94*OVERSAMPLENR, 190}, + {102*OVERSAMPLENR, 185}, + {116*OVERSAMPLENR, 170}, + {143*OVERSAMPLENR, 160}, + {183*OVERSAMPLENR, 150}, + {223*OVERSAMPLENR, 140}, + {270*OVERSAMPLENR, 130}, + {318*OVERSAMPLENR, 120}, + {383*OVERSAMPLENR, 110}, + {413*OVERSAMPLENR, 105}, + {439*OVERSAMPLENR, 100}, + {484*OVERSAMPLENR, 95}, + {513*OVERSAMPLENR, 90}, + {607*OVERSAMPLENR, 80}, + {664*OVERSAMPLENR, 70}, + {781*OVERSAMPLENR, 60}, + {810*OVERSAMPLENR, 55}, + {849*OVERSAMPLENR, 50}, + {914*OVERSAMPLENR, 45}, + {914*OVERSAMPLENR, 40}, + {935*OVERSAMPLENR, 35}, + {954*OVERSAMPLENR, 30}, + {970*OVERSAMPLENR, 25}, + {978*OVERSAMPLENR, 22}, + {1008*OVERSAMPLENR, 3} +}; +#endif + +#if (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 +#define NUMTEMPS_7 54 +const short temptable_7[NUMTEMPS_7][2] = { + {46*OVERSAMPLENR, 270}, + {50*OVERSAMPLENR, 265}, + {54*OVERSAMPLENR, 260}, + {58*OVERSAMPLENR, 255}, + {62*OVERSAMPLENR, 250}, + {67*OVERSAMPLENR, 245}, + {72*OVERSAMPLENR, 240}, + {79*OVERSAMPLENR, 235}, + {85*OVERSAMPLENR, 230}, + {91*OVERSAMPLENR, 225}, + {99*OVERSAMPLENR, 220}, + {107*OVERSAMPLENR, 215}, + {116*OVERSAMPLENR, 210}, + {126*OVERSAMPLENR, 205}, + {136*OVERSAMPLENR, 200}, + {149*OVERSAMPLENR, 195}, + {160*OVERSAMPLENR, 190}, + {175*OVERSAMPLENR, 185}, + {191*OVERSAMPLENR, 180}, + {209*OVERSAMPLENR, 175}, + {224*OVERSAMPLENR, 170}, + {246*OVERSAMPLENR, 165}, + {267*OVERSAMPLENR, 160}, + {293*OVERSAMPLENR, 155}, + {316*OVERSAMPLENR, 150}, + {340*OVERSAMPLENR, 145}, + {364*OVERSAMPLENR, 140}, + {396*OVERSAMPLENR, 135}, + {425*OVERSAMPLENR, 130}, + {460*OVERSAMPLENR, 125}, + {489*OVERSAMPLENR, 120}, + {526*OVERSAMPLENR, 115}, + {558*OVERSAMPLENR, 110}, + {591*OVERSAMPLENR, 105}, + {628*OVERSAMPLENR, 100}, + {660*OVERSAMPLENR, 95}, + {696*OVERSAMPLENR, 90}, + {733*OVERSAMPLENR, 85}, + {761*OVERSAMPLENR, 80}, + {794*OVERSAMPLENR, 75}, + {819*OVERSAMPLENR, 70}, + {847*OVERSAMPLENR, 65}, + {870*OVERSAMPLENR, 60}, + {892*OVERSAMPLENR, 55}, + {911*OVERSAMPLENR, 50}, + {929*OVERSAMPLENR, 45}, + {944*OVERSAMPLENR, 40}, + {959*OVERSAMPLENR, 35}, + {971*OVERSAMPLENR, 30}, + {981*OVERSAMPLENR, 25}, + {989*OVERSAMPLENR, 20}, + {994*OVERSAMPLENR, 15}, + {1001*OVERSAMPLENR, 10}, + {1005*OVERSAMPLENR, 5} +}; +#endif + + + +#if THERMISTORHEATER_1 == 1 +#define NUMTEMPS_HEATER_1 NUMTEMPS_1 +#define temptable_1 temptable_1 +#elif THERMISTORHEATER_1 == 2 +#define NUMTEMPS_HEATER_1 NUMTEMPS_2 +#define temptable_1 temptable_2 +#elif THERMISTORHEATER_1 == 3 +#define NUMTEMPS_HEATER_1 NUMTEMPS_3 +#define temptable_1 temptable_3 +#elif THERMISTORHEATER_1 == 4 +#define NUMTEMPS_HEATER_1 NUMTEMPS_4 +#define temptable_1 temptable_4 +#elif THERMISTORHEATER_1 == 5 +#define NUMTEMPS_HEATER_1 NUMTEMPS_5 +#define temptable_1 temptable_5 +#elif THERMISTORHEATER_1 == 6 +#define NUMTEMPS_HEATER_1 NUMTEMPS_6 +#define temptable_1 temptable_6 +#elif THERMISTORHEATER_1 == 7 +#define NUMTEMPS_HEATER_1 NUMTEMPS_7 +#define temptable_1 temptable_7 +#elif defined HEATER_1_USES_THERMISTOR +#error No heater 1 thermistor table specified +#endif + +#if THERMISTORHEATER_2 == 1 +#define NUMTEMPS_HEATER_2 NUMTEMPS_1 +#define temptable_2 temptable_1 +#elif THERMISTORHEATER_2 == 2 +#define NUMTEMPS_HEATER_2 NUMTEMPS_2 +#define temptable_2 temptable_2 +#elif THERMISTORHEATER_2 == 3 +#define NUMTEMPS_HEATER_2 NUMTEMPS_3 +#define temptable_2 temptable_3 +#elif THERMISTORHEATER_2 == 4 +#define NUMTEMPS_HEATER_2 NUMTEMPS_4 +#define temptable_2 temptable_4 +#elif THERMISTORHEATER_2 == 5 +#define NUMTEMPS_HEATER_2 NUMTEMPS_5 +#define temptable_2 temptable_5 +#elif THERMISTORHEATER_2 == 6 +#define NUMTEMPS_HEATER_2 NUMTEMPS_6 +#define temptable_2 temptable_6 +#elif THERMISTORHEATER_2 == 7 +#define NUMTEMPS_HEATER22 NUMTEMPS_7 +#define temptable_2 temptable_7 +#elif defined HEATER_2_USES_THERMISTOR +#error No heater 2 thermistor table specified +#endif + + +#if THERMISTORBED == 1 +#define BNUMTEMPS NUMTEMPS_1 +#define bedtemptable temptable_1 +#elif THERMISTORBED == 2 +#define BNUMTEMPS NUMTEMPS_2 +#define bedtemptable temptable_2 +#elif THERMISTORBED == 3 +#define BNUMTEMPS NUMTEMPS_3 +#define bedtemptable temptable_3 +#elif THERMISTORBED == 4 +#define BNUMTEMPS NUMTEMPS_4 +#define bedtemptable temptable_4 +#elif THERMISTORBED == 5 +#define BNUMTEMPS NUMTEMPS_5 +#define bedtemptable temptable_5 +#elif THERMISTORBED == 6 +#define BNUMTEMPS NUMTEMPS_6 +#define bedtemptable temptable_6 +#elif THERMISTORBED == 7 +#define BNUMTEMPS NUMTEMPS_7 +#define bedtemptable temptable_7 +#elif defined BED_USES_THERMISTOR +#error No bed thermistor table specified +#endif + +#endif //THERMISTORTABLES_H_ + diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 39cca278ee..b7092c9cb1 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -1,156 +1,156 @@ -#ifndef __ULTRALCDH -#define __ULTRALCDH -#include "Configuration.h" - -#ifdef ULTRA_LCD - - void lcd_status(); - void lcd_init(); - void lcd_status(const char* message); - void beep(); - void buttons_check(); - #define LCDSTATUSRIGHT - - #define LCD_UPDATE_INTERVAL 100 - #define STATUSTIMEOUT 15000 - - #include "Configuration.h" - - #include - extern LiquidCrystal lcd; - - //lcd display size - -#ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - #define EN_C (1< + extern LiquidCrystal lcd; + + //lcd display size + +#ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + #define EN_C (1< Board -> Arduino Mega 2560 -Select the correct serial port in Tools ->Serial Port -Open Marlin.pde - -Click the Verify/Compile button - -Click the Upload button -If all goes well the firmware is uploading - -Start Ultimaker's Custom RepG 25 -Make sure Show Experimental Profiles is enabled in Preferences -Select Sprinter as the Driver - -Press the Connect button. - -KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z - -That's ok. Enjoy Silky Smooth Printing. - +This RepRap firmware is a mashup between Sprinter, grbl and many original parts. + (https://github.com/kliment/Sprinter) + (https://github.com/simen/grbl/tree) + +Derived from Sprinter and Grbl by Erik van der Zalm. +Sprinters lead developers are Kliment and caru. +Grbls lead developer is Simen Svale Skogsrud. +It has been adapted to the Ultimaker Printer by: +Bernhard Kubicek, Matthijs Keuper, Bradley Feldman, and others... + + +Features: + - Interrupt based movement with real linear acceleration + - High steprate + - Look ahead (Keep the speed high when possible. High cornering speed) + - Interrupt based temperature protection + - preliminary support for Matthew Roberts advance algorithm + For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html + - Full endstop support + - Simple LCD support (16x2) + - SD Card support + - Provisions for Bernhard Kubicek's new hardware control console and 20x4 lcd + +This firmware is optimized for Ultimaker's gen6 electronics (including the Ultimaker 1.5.x daughterboard and Arduino Mega 2560). + +The default baudrate is 115200. + + +======================================================================================== + +Configuring and compilation + + +Install the latest arduino software IDE/toolset (currently 0022) + http://www.arduino.cc/en/Main/Software + +Install Ultimaker's RepG 25 build + http://software.ultimaker.com +(or alternatively install Kliment's printrun/pronterface https://github.com/kliment/Printrun_) + +Copy the Ultimaker Marlin firmware + https:/github.com/bkubicek/Marlin + (Use the download button) + +Start the arduino IDE. +Select Tools -> Board -> Arduino Mega 2560 +Select the correct serial port in Tools ->Serial Port +Open Marlin.pde + +Click the Verify/Compile button + +Click the Upload button +If all goes well the firmware is uploading + +Start Ultimaker's Custom RepG 25 +Make sure Show Experimental Profiles is enabled in Preferences +Select Sprinter as the Driver + +Press the Connect button. + +KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z + +That's ok. Enjoy Silky Smooth Printing. + diff --git a/README.md b/README.md index 6cab9fa526..699ebdd64a 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,69 @@ -WARNING: THIS IN A PROCESS OF HEAVY OVERWORKING. -DO NOT USE THIS ON YOUR MACHINE UNTIL FURTHER NOTICE!!! - -=========================================== - -This RepRap firmware is a mashup between Sprinter, grbl and many original parts. - -Derived from Sprinter and Grbl by Erik van der Zalm. -Sprinters lead developers are Kliment and caru. -Grbls lead developer is Simen Svale Skogsrud. -Some features have been added by and configuration has been added by: -Bernhard Kubicek, Matthijs Keuper, Bradley Feldman, and others... - - -Features: - - Interrupt based movement with real linear acceleration - - High steprate - - Look ahead (Keep the speed high when possible. High cornering speed) - - Interrupt based temperature protection - - preliminary support for Matthew Roberts advance algorithm - For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html - - Full endstop support - - Simple LCD support (16x2) - - SD Card support - - Provisions for Bernhard Kubicek's new hardware control console and 20x4 lcd - -This firmware is optimized for Ultimaker's gen6 electronics (including the Ultimaker 1.5.x daughterboard and Arduino Mega 2560). - -The default baudrate is 115200. - - -======================================================================================== - -Configuring and compilation - - -Install the latest arduino software IDE/toolset (currently 0022) - http://www.arduino.cc/en/Main/Software - -Install Ultimaker's RepG 25 build - http://software.ultimaker.com -(or alternatively install Kliment's printrun/pronterface https://github.com/kliment/Printrun_) - -Copy the Ultimaker Marlin firmware - https:/github.com/bkubicek/Marlin - (Use the download button) - -Start the arduino IDE. -Select Tools -> Board -> Arduino Mega 2560 -Select the correct serial port in Tools ->Serial Port -Open Marlin.pde - -Click the Verify/Compile button - -Click the Upload button -If all goes well the firmware is uploading - -Start Ultimaker's Custom RepG 25 -Make sure Show Experimental Profiles is enabled in Preferences -Select Sprinter as the Driver - -Press the Connect button. - -KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z - -That's ok. Enjoy Silky Smooth Printing. - - - +WARNING: THIS IN A PROCESS OF HEAVY OVERWORKING. +DO NOT USE THIS ON YOUR MACHINE UNTIL FURTHER NOTICE!!! + +=========================================== + +This RepRap firmware is a mashup between Sprinter, grbl and many original parts. + +Derived from Sprinter and Grbl by Erik van der Zalm. +Sprinters lead developers are Kliment and caru. +Grbls lead developer is Simen Svale Skogsrud. +Some features have been added by and configuration has been added by: +Bernhard Kubicek, Matthijs Keuper, Bradley Feldman, and others... + + +Features: + - Interrupt based movement with real linear acceleration + - High steprate + - Look ahead (Keep the speed high when possible. High cornering speed) + - Interrupt based temperature protection + - preliminary support for Matthew Roberts advance algorithm + For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html + - Full endstop support + - Simple LCD support (16x2) + - SD Card support + - Provisions for Bernhard Kubicek's new hardware control console and 20x4 lcd + +This firmware is optimized for Ultimaker's gen6 electronics (including the Ultimaker 1.5.x daughterboard and Arduino Mega 2560). + +The default baudrate is 115200. + + +======================================================================================== + +Configuring and compilation + + +Install the latest arduino software IDE/toolset (currently 0022) + http://www.arduino.cc/en/Main/Software + +Install Ultimaker's RepG 25 build + http://software.ultimaker.com +(or alternatively install Kliment's printrun/pronterface https://github.com/kliment/Printrun_) + +Copy the Ultimaker Marlin firmware + https:/github.com/bkubicek/Marlin + (Use the download button) + +Start the arduino IDE. +Select Tools -> Board -> Arduino Mega 2560 +Select the correct serial port in Tools ->Serial Port +Open Marlin.pde + +Click the Verify/Compile button + +Click the Upload button +If all goes well the firmware is uploading + +Start Ultimaker's Custom RepG 25 +Make sure Show Experimental Profiles is enabled in Preferences +Select Sprinter as the Driver + +Press the Connect button. + +KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z + +That's ok. Enjoy Silky Smooth Printing. + + + diff --git a/merging still needs.txt b/merging still needs.txt index 2d369c968a..18e91dcad1 100644 --- a/merging still needs.txt +++ b/merging still needs.txt @@ -1,58 +1,58 @@ -files to compare manually: -planner.cpp -stepper.cpp -temperature.cpp - ---- -things that changed: -* planner.cpp -estimate_acc_distance now works with floats. -in calculate_trapezoid:for_block - long acceleration_rate=(long)((float)acceleration*8.388608) is gone - so is block_>acceleration_rate -void planner_reverse_pass: - some stuff I don't understand right now changed -in planner_forward_pass: - done: BLOCK_BUFFER_SIZE is now necessarily power of 2 (aka 8 16, 32). Inportant to document this somewhere. -no more inline in void plan_discard_current_block() -no more inline in plan_get_current_block() -in plan_buffer_line(...) - the long target[4]; and calculations of thoose should go after the while(block_buffer_tail==..). if the axis_steps_per_unit are changed from the gcode (M92) the calculation for the currently planned buffer move will be corrupt, because Target is calculated with one value, and the stuff afterwards with another. At least this solved the problem I had with the M92 E* changes in the code. Very sure about this, I took me 20min to find this as the solution for the bug I was hunting. -around if(feed_rate!true+return? -done #define K1 0.95 maybe in the configuration.h? -semi-done: PID-C checking needed. Untested but added. ----- - -still needed to finish the merge, before testin! - - manage_heater - ISR - movement planner - -TODO: - -remove traveling at maxpseed -remove Simplelcd - -remove DEBUG_STEPS? - -block_t -pid_dt ->0.1 whats the changes to the PID, checking needed - - ----- -second merge saturday morning: +files to compare manually: +planner.cpp +stepper.cpp +temperature.cpp + +--- +things that changed: +* planner.cpp +estimate_acc_distance now works with floats. +in calculate_trapezoid:for_block + long acceleration_rate=(long)((float)acceleration*8.388608) is gone + so is block_>acceleration_rate +void planner_reverse_pass: + some stuff I don't understand right now changed +in planner_forward_pass: + done: BLOCK_BUFFER_SIZE is now necessarily power of 2 (aka 8 16, 32). Inportant to document this somewhere. +no more inline in void plan_discard_current_block() +no more inline in plan_get_current_block() +in plan_buffer_line(...) + the long target[4]; and calculations of thoose should go after the while(block_buffer_tail==..). if the axis_steps_per_unit are changed from the gcode (M92) the calculation for the currently planned buffer move will be corrupt, because Target is calculated with one value, and the stuff afterwards with another. At least this solved the problem I had with the M92 E* changes in the code. Very sure about this, I took me 20min to find this as the solution for the bug I was hunting. +around if(feed_rate!true+return? +done #define K1 0.95 maybe in the configuration.h? +semi-done: PID-C checking needed. Untested but added. +---- + +still needed to finish the merge, before testin! + + manage_heater + ISR + movement planner + +TODO: + +remove traveling at maxpseed +remove Simplelcd + +remove DEBUG_STEPS? + +block_t +pid_dt ->0.1 whats the changes to the PID, checking needed + + +---- +second merge saturday morning: done: PID_dt->0.1 \ No newline at end of file From 8bcdb9f5f062fe68d90e31752453e1d662b3f0e2 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 5 Nov 2011 16:43:44 +0100 Subject: [PATCH 007/228] this is not working. Do you maybe know why? --- Marlin/EEPROMwrite.h | 16 ++--- Marlin/Marlin.h | 1 + Marlin/Marlin.pde | 80 ++++++++++++------------- Marlin/planner.cpp | 2 +- Marlin/stepper.cpp | 2 +- Marlin/temperature.cpp | 128 +++++++++++++++++++--------------------- Marlin/temperature.h | 131 ++++++++++++++++++++++++++++++++++------- Marlin/ultralcd.pde | 90 ++++++++++++++-------------- 8 files changed, 268 insertions(+), 182 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 2247e2f52d..4e5364d80b 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -48,9 +48,9 @@ void StoreSettings() { EEPROM_writeAnything(i,max_xy_jerk); EEPROM_writeAnything(i,max_z_jerk); #ifdef PIDTEMP - EEPROM_writeAnything(i,Kp); - EEPROM_writeAnything(i,Ki); - EEPROM_writeAnything(i,Kd); + EEPROM_writeAnything(i,Heater::Kp); + EEPROM_writeAnything(i,Heater::Ki); + EEPROM_writeAnything(i,Heater::Kd); #else EEPROM_writeAnything(i,3000); EEPROM_writeAnything(i,0); @@ -81,11 +81,11 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will EEPROM_readAnything(i,max_xy_jerk); EEPROM_readAnything(i,max_z_jerk); #ifndef PIDTEMP - float Kp,Ki,Kd; + float Kp,Ki,Kd; //read and ignore.. #endif - EEPROM_readAnything(i,Kp); - EEPROM_readAnything(i,Ki); - EEPROM_readAnything(i,Kd); + EEPROM_readAnything(i,Heater::Kp); + EEPROM_readAnything(i,Heater::Ki); + EEPROM_readAnything(i,Heater::Kd); ECHOLN("Stored settings retreived:"); } @@ -119,7 +119,7 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); #ifdef PIDTEMP ECHOLN("PID settings:"); - ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); + ECHOLN(" M301 P" << _FLOAT(Heater::Kp,3) << " I" << _FLOAT(Heater::Ki,3) << " D" << _FLOAT(Heater::Kd,3)); #endif } diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index f85dad3576..4cd4c8d39b 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -10,6 +10,7 @@ #define ECHO(x) Serial << "echo: " << x; #define ECHOLN(x) Serial << "echo: "< current_raw[TEMPSENSOR_HOTEND]){ + if(Heater::isHeating(TEMPSENSOR_HOTEND)){ watchmillis = max(1,millis()); watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; }else{ @@ -815,14 +813,14 @@ inline void process_commands() #endif break; case 140: // M140 set bed temp - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); + if (code_seen('S')) Heater::setCelsius(TEMPSENSOR_BED,code_value()); break; case 105: // M105 #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = analog2temp(current_raw[TEMPSENSOR_HOTEND]); + tt = Heater::celsius(TEMPSENSOR_HOTEND); #endif #if TEMP_1_PIN > -1 - bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); + bt = Heater::celsius(TEMPSENSOR_BED); #endif #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) Serial.print("ok T:"); @@ -833,14 +831,14 @@ inline void process_commands() #ifdef PIDTEMP Serial.print(" B:"); #if TEMP_1_PIN > -1 - Serial.println(bt); + Serial.println(bt); #else - Serial.println(HeaterPower); + Serial.println(Heater::HeaterPower); #endif #else Serial.println(); #endif - #else + #else< Serial.println(); #endif #else @@ -850,14 +848,12 @@ inline void process_commands() //break; case 109: {// M109 - Wait for extruder heater to reach target. LCD_MESSAGE("Heating..."); - if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); - #ifdef PIDTEMP - pid_setpoint = code_value(); - #endif //PIDTEM + if (code_seen('S')) Heater::setCelsius(TEMPSENSOR_HOTEND,code_value()); + #ifdef WATCHPERIOD - if(target_raw[TEMPSENSOR_HOTEND]>current_raw[TEMPSENSOR_HOTEND]){ + if(Heater::isHeating(TEMPSENSOR_HOTEND)){ watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; + watch_raw[TEMPSENSOR_HOTEND] = Heater::current_raw[TEMPSENSOR_HOTEND]; } else { watchmillis = 0; } @@ -865,31 +861,31 @@ inline void process_commands() codenum = millis(); /* See if we are heating up or cooling down */ - bool target_direction = (current_raw[0] < target_raw[0]); // true if heating, false if cooling + bool target_direction = Heater::isHeating(TEMPSENSOR_HOTEND); // 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((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || + while((target_direction ? Heater::isHeating(TEMPSENSOR_HOTEND) : Heater::isCooling(TEMPSENSOR_HOTEND)) || (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else - while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { + while ( target_direction ? Heater::isHeating(TEMPSENSOR_HOTEND) : Heater::isCooling(TEMPSENSOR_HOTEND) ) { #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down Serial.print("T:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND]) ); + Serial.println( Heater::celsius(TEMPSENSOR_HOTEND) ); codenum = millis(); } - manage_heater(); + Heater::manage_heater(); 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 && current_raw[0] >= target_raw[0]) || - (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || - (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { + if ((residencyStart == -1 && target_direction && !Heater::isHeating(TEMPSENSOR_HOTEND)) || + (residencyStart == -1 && !target_direction && !Heater::isCooling(TEMPSENSOR_HOTEND)) || + (residencyStart > -1 && labs(Heater::celsius(TEMPSENSOR_HOTEND) - Heater::celsiusTarget(TEMPSENSOR_HOTEND)) > TEMP_HYSTERESIS) ) { residencyStart = millis(); } #endif //TEMP_RESIDENCY_TIME @@ -899,22 +895,22 @@ inline void process_commands() break; case 190: // M190 - Wait bed for heater to reach target. #if TEMP_1_PIN > -1 - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); + if (code_seen('S')) Heater::setCelsius(TEMPSENSOR_BED,code_value()); codenum = millis(); - while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) - { + while(Heater::isHeating(TEMPSENSOR_BED)) + { if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { - float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND]); + float tt=Heater::celsius(TEMPSENSOR_HOTEND); Serial.print("T:"); Serial.println( tt ); Serial.print("ok T:"); Serial.print( tt ); Serial.print(" B:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); + Serial.println( Heater::celsius(TEMPSENSOR_BED) ); codenum = millis(); } - manage_heater(); + Heater::manage_heater(); } #endif break; @@ -1066,9 +1062,13 @@ inline void process_commands() 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; + if(code_seen('P')) Heater::Kp = code_value(); + if(code_seen('I')) Heater::Ki = code_value()*PID_dT; + if(code_seen('D')) Heater::Kd = code_value()/PID_dT; + #ifdef PID_ADD_EXTRUSION_RATE + if(code_seen('C')) Heater::Kc = code_value(); + #endif + // ECHOLN("Kp "<<_FLOAT(Kp,2)); // ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); // ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); @@ -1194,19 +1194,19 @@ void wd_reset() { inline void kill() { #if TEMP_0_PIN > -1 - target_raw[0]=0; + Heater::setCelsius(TEMPSENSOR_HOTEND,0); #if HEATER_0_PIN > -1 WRITE(HEATER_0_PIN,LOW); #endif #endif #if TEMP_1_PIN > -1 - target_raw[1]=0; + Heater::setCelsius(TEMPSENSOR_BED,0); #if HEATER_1_PIN > -1 WRITE(HEATER_1_PIN,LOW); #endif #endif #if TEMP_2_PIN > -1 - target_raw[2]=0; + Heater::setCelsius(TEMPSENSOR_AUX,0); #if HEATER_2_PIN > -1 WRITE(HEATER_2_PIN,LOW); #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 14f0bb1043..cfeb6b2234 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -388,7 +388,7 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. while(block_buffer_tail == next_buffer_head) { - manage_heater(); + htr.manage_heater(); manage_inactivity(1); LCD_STATUS; } diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index f4bd1289e0..01ff430f35 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -585,7 +585,7 @@ void st_init() void st_synchronize() { while(plan_get_current_block()) { - manage_heater(); + htr.manage_heater(); manage_inactivity(1); LCD_STATUS; } diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index ebc772e1d8..9be4bdc2f7 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -37,52 +37,11 @@ #include "streaming.h" #include "temperature.h" -int target_bed_raw = 0; -int current_bed_raw = 0; -int target_raw[3] = {0, 0, 0}; -int current_raw[3] = {0, 0, 0}; -unsigned char temp_meas_ready = false; -unsigned long previous_millis_heater, previous_millis_bed_heater; -#ifdef PIDTEMP - double temp_iState = 0; - double temp_dState = 0; - double pTerm; - double iTerm; - double dTerm; - //int output; - double pid_error; - double temp_iState_min; - double temp_iState_max; - double pid_setpoint = 0.0; - double pid_input; - double pid_output; - bool pid_reset; - float HeaterPower; - - float Kp=DEFAULT_Kp; - float Ki=DEFAULT_Ki; - float Kd=DEFAULT_Kd; - float Kc=DEFAULT_Kc; -#endif //PIDTEMP -#ifdef MINTEMP -int minttemp = temp2analog(MINTEMP); -#endif //MINTEMP -#ifdef MAXTEMP -int maxttemp = temp2analog(MAXTEMP); -#endif //MAXTEMP - -#ifdef BED_MINTEMP -int bed_minttemp = temp2analog(BED_MINTEMP); -#endif //BED_MINTEMP -#ifdef BED_MAXTEMP -int bed_maxttemp = temp2analog(BED_MAXTEMP); -#endif //BED_MAXTEMP - -void manage_heater() +void static Heater::manage_heater() { #ifdef USE_WATCHDOG wd_reset(); @@ -90,11 +49,11 @@ void manage_heater() float pid_input; float pid_output; - if(temp_meas_ready != true) //better readability + if(htr.temp_meas_ready != true) //better readability return; CRITICAL_SECTION_START; - temp_meas_ready = false; + htr.temp_meas_ready = false; CRITICAL_SECTION_END; #ifdef PIDTEMP @@ -176,7 +135,8 @@ CRITICAL_SECTION_END; // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -float temp2analog(int celsius) { +float const static temp2analog(const int celsius) +{ #ifdef HEATER_USES_THERMISTOR_1 int raw = 0; byte i; @@ -207,7 +167,8 @@ float temp2analog(int celsius) { // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -float temp2analogBed(int celsius) { +float const static temp2analogBed(const int celsius) +{ #ifdef BED_USES_THERMISTOR int raw = 0; @@ -237,7 +198,7 @@ float temp2analogBed(int celsius) { // Derived from RepRap FiveD extruder::getTemperature() // For hot end temperature measurement. -float analog2temp(int raw) { +float const static Heater::analog2temp(const int raw) { #ifdef HEATER_1_USES_THERMISTOR int celsius = 0; byte i; @@ -266,7 +227,7 @@ float analog2temp(int raw) { // Derived from RepRap FiveD extruder::getTemperature() // For bed temperature measurement. -float analog2tempBed(int raw) { +float const static Heater::analog2tempBed(const int raw) { #ifdef BED_USES_THERMISTOR int celsius = 0; byte i; @@ -296,8 +257,28 @@ float analog2tempBed(int raw) { #endif } -void tp_init() +Heater::Heater() { + for(short i=0;i<3;i++) + { + target_raw[i]=0; + current_raw[i] =0; + } + htr.temp_meas_ready = false; + #ifdef MINTEMP + minttemp = temp2analog(MINTEMP); + #endif //MINTEMP + #ifdef MAXTEMP + maxttemp = temp2analog(MAXTEMP); + #endif //MAXTEMP + + #ifdef BED_MINTEMP + bed_minttemp = temp2analog(BED_MINTEMP); + #endif //BED_MINTEMP + #ifdef BED_MAXTEMP + bed_maxttemp = temp2analog(BED_MAXTEMP); + #endif //BED_MAXTEMP + #if (HEATER_0_PIN > -1) SET_OUTPUT(HEATER_0_PIN); #endif @@ -311,6 +292,14 @@ void tp_init() #ifdef PIDTEMP temp_iState_min = 0.0; temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; + temp_iState = 0; + temp_dState = 0; + Kp=DEFAULT_Kp; + Ki=DEFAULT_Ki; + Kd=DEFAULT_Kd; + Kc=DEFAULT_Kc; + pid_setpoint = 0.0; + #endif //PIDTEMP // Set analog inputs @@ -407,39 +396,39 @@ ISR(TIMER0_COMPB_vect) if(temp_count >= 16) // 6 ms * 16 = 96ms. { #ifdef HEATER_1_USES_AD595 - current_raw[0] = raw_temp_0_value; + htr.current_raw[0] = raw_temp_0_value; #else - current_raw[0] = 16383 - raw_temp_0_value; + htr.current_raw[0] = 16383 - raw_temp_0_value; #endif #ifdef HEATER_2_USES_AD595 - current_raw[2] = raw_temp_2_value; + htr.current_raw[2] = raw_temp_2_value; #else - current_raw[2] = 16383 - raw_temp_2_value; + htr.current_raw[2] = 16383 - raw_temp_2_value; #endif #ifdef BED_USES_AD595 - current_raw[1] = raw_temp_1_value; + htr.current_raw[1] = raw_temp_1_value; #else - current_raw[1] = 16383 - raw_temp_1_value; + htr.current_raw[1] = 16383 - raw_temp_1_value; #endif - temp_meas_ready = true; + htr.temp_meas_ready = true; temp_count = 0; raw_temp_0_value = 0; raw_temp_1_value = 0; raw_temp_2_value = 0; #ifdef MAXTEMP #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND] >= maxttemp) { - target_raw[TEMPSENSOR_HOTEND] = 0; + if(htr.current_raw[TEMPSENSOR_HOTEND] >= htr.maxttemp) { + htr.target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(current_raw[TEMPSENSOR_AUX] >= maxttemp) { - target_raw[TEMPSENSOR_AUX] = 0; + if(htr.current_raw[TEMPSENSOR_AUX] >= htr.maxttemp) { + htr.target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); } @@ -447,15 +436,15 @@ ISR(TIMER0_COMPB_vect) #endif //MAXTEMP #ifdef MINTEMP #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND] <= minttemp) { - target_raw[TEMPSENSOR_HOTEND] = 0; + if(htr.current_raw[TEMPSENSOR_HOTEND] <= htr.minttemp) { + htr.target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(current_raw[TEMPSENSOR_AUX] <= minttemp) { - target_raw[TEMPSENSOR_AUX] = 0; + if(htr.current_raw[TEMPSENSOR_AUX] <= htr.minttemp) { + htr.target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); } @@ -463,8 +452,8 @@ ISR(TIMER0_COMPB_vect) #endif //MAXTEMP #ifdef BED_MINTEMP #if (HEATER_1_PIN > -1) - if(current_raw[1] <= bed_minttemp) { - target_raw[1] = 0; + if(htr.current_raw[1] <= htr.bed_minttemp) { + htr.target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); } @@ -472,8 +461,8 @@ ISR(TIMER0_COMPB_vect) #endif #ifdef BED_MAXTEMP #if (HEATER_1_PIN > -1) - if(current_raw[1] >= bed_maxttemp) { - target_raw[1] = 0; + if(htr.current_raw[1] >= htr.bed_maxttemp) { + htr.target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); } @@ -481,3 +470,6 @@ ISR(TIMER0_COMPB_vect) #endif } } + +//Heater htr; + diff --git a/Marlin/temperature.h b/Marlin/temperature.h index e2e6c459c6..a93d46ba4b 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -25,14 +25,116 @@ #ifdef PID_ADD_EXTRUSION_RATE #include "stepper.h" #endif -void tp_init(); -void manage_heater(); -//int temp2analogu(int celsius, const short table[][2], int numtemps); -//float analog2tempu(int raw, const short table[][2], int numtemps); -float temp2analog(int celsius); -float temp2analogBed(int celsius); -float analog2temp(int raw); -float analog2tempBed(int raw); + +enum TempSensor {TEMPSENSOR_HOTEND=0,TEMPSENSOR_BED=1, TEMPSENSOR_AUX=2}; + +// ther must be only one instance of this class, and it is created in temperature.cpp by itself and is called "htr". +// all the variables are static, so that of the compiler optimization is more easy. +// I honestly hope that this increases readability and structure. +// none of the variables or routines should be called from an secondary process/interrupt with the exceptino of current_raw[]. + +class Heater +{ +public: + Heater(); //treplaces tp_init(); + ~Heater(); + + void static manage_heater(); /// it is critical that this is called continously. + + // conversion routines, const since they don't change any class variables. + float const static temp2analog(const int celsius); + float const static temp2analogBed(const int celsius); + float const static analog2temp(const int raw); + float const static analog2tempBed(const int raw); + + inline float const static celsius(const TempSensor s) + { + if(s==TEMPSENSOR_BED) + return analog2tempBed(Heater::current_raw[s]); + else + return analog2temp(Heater::current_raw[s]); + }; + inline float const static celsiusTarget(const TempSensor s) + { + if(s==TEMPSENSOR_BED) + return analog2tempBed(Heater::target_raw[s]); + else + return analog2temp(Heater::target_raw[s]); + }; + inline float static setCelsius(const TempSensor s, const int celsius) + { + #ifdef PIDTEMP + if(s==TEMPSENSOR_HOTEND) + Heater::pid_setpoint = celsius; + #endif //PIDTEM + if(s==TEMPSENSOR_BED) + Heater::target_raw[s] = temp2analog(celsius); + else + Heater::target_raw[s] = temp2analogBed(celsius); + }; + + inline bool const static isHeating(TempSensor s) + { return (Heater::target_raw[s]>Heater::current_raw[s]);}; + inline bool const static isCooling(TempSensor s) + { return (Heater::target_raw[s]3)||force_lcd_update) + int tt=Heater::celsius(TEMPSENSOR_HOTEND); + if((abs(tt-oldcurrent)>1)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); - oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(tt)); + oldcurrent=tt; } - if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + int ttg=Heater::celsiusTarget(TEMPSENSOR_HOTEND); + if((ttg!=oldtarget)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); - oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(ttg)); + oldtarget=ttg; } #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - static int oldcurrentbedraw=-1; - static int oldtargetbedraw=-1; - if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) + static int oldcurrentbed=-1; + static int oldtargetbed=-1; + int tb=Heater::celsius(TEMPSENSOR_BED); + if((tb!=oldcurrentbed)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_bed_raw))); - oldcurrentraw=current_raw[TEMPSENSOR_BED]; + lcd.print(ftostr3(tb)); + oldcurrentbed=tb; } - if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) + int tg=Heater::celsiusTarget(TEMPSENSOR_BED); + if((tg!=oldtargebed)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_bed_raw))); - oldtargetraw=target_bed_raw; + lcd.print(Heater::celsiusTarget(TEMPSENSOR_BED)); + oldtargebed=tg; } #endif //starttime=2; @@ -327,8 +330,8 @@ void MainMenu::showStatus() messagetext[0]='\0'; } #else //smaller LCDS---------------------------------- - static int oldcurrentraw=-1; - static int oldtargetraw=-1; + static int oldcurrent=-1; + static int oldtarget=-1; if(force_lcd_update) //initial display of content { encoderpos=feedmultiply; @@ -338,18 +341,19 @@ void MainMenu::showStatus() #endif } - - if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) + int tt=Heater::celsius(TEMPSENSOR_HOTEND); + if((abs(tt-oldcurrent)>1)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); - oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(tt)); + oldcurrent=tt; } - if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + int ttg=Heater::celsiusTarget(TEMPSENSOR_HOTEND); + if((ttg!=oldtarget)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); - oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(ttg)); + oldtarge=ttg; } if(messagetext[0]!='\0') @@ -426,7 +430,7 @@ void MainMenu::showPrepare() if((activeline==line) && CLICKED) { BLOCK - target_raw[TEMPSENSOR_HOTEND] = temp2analog(170); + Heater::setCelsius(TEMPSENSOR_HOTEND, 170); beepshort(); } }break; @@ -531,7 +535,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" \002Nozzle:"); - lcd.setCursor(13,line);lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + lcd.setCursor(13,line);lcd.print(ftostr3(Heater::celsiusTarget(TEMPSENSOR_HOTEND))); } if((activeline==line) ) @@ -541,11 +545,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)analog2temp(target_raw[TEMPSENSOR_HOTEND]); + encoderpos=(int)Heater::celsiusTarget(TEMPSENSOR_HOTEND); } else { - target_raw[TEMPSENSOR_HOTEND] = temp2analog(encoderpos); + Heater::setCelsius(TEMPSENSOR_HOTEND,encoderpos); encoderpos=activeline*lcdslow; beepshort(); } @@ -669,7 +673,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-P: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kp)); + lcd.setCursor(13,line);lcd.print(itostr4(Heater::Kp)); } if((activeline==line) ) @@ -679,11 +683,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Kp/5; + encoderpos=(int)Heater::Kp/5; } else { - Kp= encoderpos*5; + Heater::Kp= encoderpos*5; encoderpos=activeline*lcdslow; } @@ -703,7 +707,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-I: "); - lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); + lcd.setCursor(13,line);lcd.print(ftostr51(Heater::Ki)); } if((activeline==line) ) @@ -713,11 +717,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(Ki*10); + encoderpos=(int)(Heater::Ki*10); } else { - Ki= encoderpos/10.; + Heater::Ki= encoderpos/10.; encoderpos=activeline*lcdslow; } @@ -737,7 +741,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-D: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kd)); + lcd.setCursor(13,line);lcd.print(itostr4(Heater::Kd)); } if((activeline==line) ) @@ -747,11 +751,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Kd/5; + encoderpos=(int)(Heater::Kd/5.); } else { - Kd= encoderpos*5; + Heater::Kd= encoderpos*5; encoderpos=activeline*lcdslow; } @@ -774,7 +778,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-C: "); - lcd.setCursor(13,line);lcd.print(itostr3(Kc)); + lcd.setCursor(13,line);lcd.print(itostr3(Heater::Kc)); } if((activeline==line) ) @@ -784,11 +788,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Kc; + encoderpos=(int)Heater::Kc; } else { - Kc= encoderpos; + Heater::Kc= encoderpos; encoderpos=activeline*lcdslow; } From b9ea0651ec52e0c7c20761c0409cd59259b984bf Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 5 Nov 2011 16:49:29 +0100 Subject: [PATCH 008/228] Revert "this is not working. Do you maybe know why?" This reverts commit 8bcdb9f5f062fe68d90e31752453e1d662b3f0e2. --- Marlin/EEPROMwrite.h | 16 ++--- Marlin/Marlin.h | 1 - Marlin/Marlin.pde | 80 ++++++++++++------------- Marlin/planner.cpp | 2 +- Marlin/stepper.cpp | 2 +- Marlin/temperature.cpp | 128 +++++++++++++++++++++------------------- Marlin/temperature.h | 131 +++++++---------------------------------- Marlin/ultralcd.pde | 90 ++++++++++++++-------------- 8 files changed, 182 insertions(+), 268 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 4e5364d80b..2247e2f52d 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -48,9 +48,9 @@ void StoreSettings() { EEPROM_writeAnything(i,max_xy_jerk); EEPROM_writeAnything(i,max_z_jerk); #ifdef PIDTEMP - EEPROM_writeAnything(i,Heater::Kp); - EEPROM_writeAnything(i,Heater::Ki); - EEPROM_writeAnything(i,Heater::Kd); + EEPROM_writeAnything(i,Kp); + EEPROM_writeAnything(i,Ki); + EEPROM_writeAnything(i,Kd); #else EEPROM_writeAnything(i,3000); EEPROM_writeAnything(i,0); @@ -81,11 +81,11 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will EEPROM_readAnything(i,max_xy_jerk); EEPROM_readAnything(i,max_z_jerk); #ifndef PIDTEMP - float Kp,Ki,Kd; //read and ignore.. + float Kp,Ki,Kd; #endif - EEPROM_readAnything(i,Heater::Kp); - EEPROM_readAnything(i,Heater::Ki); - EEPROM_readAnything(i,Heater::Kd); + EEPROM_readAnything(i,Kp); + EEPROM_readAnything(i,Ki); + EEPROM_readAnything(i,Kd); ECHOLN("Stored settings retreived:"); } @@ -119,7 +119,7 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); #ifdef PIDTEMP ECHOLN("PID settings:"); - ECHOLN(" M301 P" << _FLOAT(Heater::Kp,3) << " I" << _FLOAT(Heater::Ki,3) << " D" << _FLOAT(Heater::Kd,3)); + ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); #endif } diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 4cd4c8d39b..f85dad3576 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -10,7 +10,6 @@ #define ECHO(x) Serial << "echo: " << x; #define ECHOLN(x) Serial << "echo: "< current_raw[TEMPSENSOR_HOTEND]){ watchmillis = max(1,millis()); watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; }else{ @@ -813,14 +815,14 @@ inline void process_commands() #endif break; case 140: // M140 set bed temp - if (code_seen('S')) Heater::setCelsius(TEMPSENSOR_BED,code_value()); + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); break; case 105: // M105 #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = Heater::celsius(TEMPSENSOR_HOTEND); + tt = analog2temp(current_raw[TEMPSENSOR_HOTEND]); #endif #if TEMP_1_PIN > -1 - bt = Heater::celsius(TEMPSENSOR_BED); + bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); #endif #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) Serial.print("ok T:"); @@ -831,14 +833,14 @@ inline void process_commands() #ifdef PIDTEMP Serial.print(" B:"); #if TEMP_1_PIN > -1 - Serial.println(bt); + Serial.println(bt); #else - Serial.println(Heater::HeaterPower); + Serial.println(HeaterPower); #endif #else Serial.println(); #endif - #else< + #else Serial.println(); #endif #else @@ -848,12 +850,14 @@ inline void process_commands() //break; case 109: {// M109 - Wait for extruder heater to reach target. LCD_MESSAGE("Heating..."); - if (code_seen('S')) Heater::setCelsius(TEMPSENSOR_HOTEND,code_value()); - + if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); + #ifdef PIDTEMP + pid_setpoint = code_value(); + #endif //PIDTEM #ifdef WATCHPERIOD - if(Heater::isHeating(TEMPSENSOR_HOTEND)){ + if(target_raw[TEMPSENSOR_HOTEND]>current_raw[TEMPSENSOR_HOTEND]){ watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND] = Heater::current_raw[TEMPSENSOR_HOTEND]; + watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; } else { watchmillis = 0; } @@ -861,31 +865,31 @@ inline void process_commands() codenum = millis(); /* See if we are heating up or cooling down */ - bool target_direction = Heater::isHeating(TEMPSENSOR_HOTEND); // true if heating, false if cooling + bool target_direction = (current_raw[0] < target_raw[0]); // 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((target_direction ? Heater::isHeating(TEMPSENSOR_HOTEND) : Heater::isCooling(TEMPSENSOR_HOTEND)) || + while((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else - while ( target_direction ? Heater::isHeating(TEMPSENSOR_HOTEND) : Heater::isCooling(TEMPSENSOR_HOTEND) ) { + while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down Serial.print("T:"); - Serial.println( Heater::celsius(TEMPSENSOR_HOTEND) ); + Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND]) ); codenum = millis(); } - Heater::manage_heater(); + manage_heater(); 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 && !Heater::isHeating(TEMPSENSOR_HOTEND)) || - (residencyStart == -1 && !target_direction && !Heater::isCooling(TEMPSENSOR_HOTEND)) || - (residencyStart > -1 && labs(Heater::celsius(TEMPSENSOR_HOTEND) - Heater::celsiusTarget(TEMPSENSOR_HOTEND)) > TEMP_HYSTERESIS) ) { + if ((residencyStart == -1 && target_direction && current_raw[0] >= target_raw[0]) || + (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || + (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { residencyStart = millis(); } #endif //TEMP_RESIDENCY_TIME @@ -895,22 +899,22 @@ inline void process_commands() break; case 190: // M190 - Wait bed for heater to reach target. #if TEMP_1_PIN > -1 - if (code_seen('S')) Heater::setCelsius(TEMPSENSOR_BED,code_value()); + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); codenum = millis(); - while(Heater::isHeating(TEMPSENSOR_BED)) - { + while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) + { if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { - float tt=Heater::celsius(TEMPSENSOR_HOTEND); + float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND]); Serial.print("T:"); Serial.println( tt ); Serial.print("ok T:"); Serial.print( tt ); Serial.print(" B:"); - Serial.println( Heater::celsius(TEMPSENSOR_BED) ); + Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); codenum = millis(); } - Heater::manage_heater(); + manage_heater(); } #endif break; @@ -1062,13 +1066,9 @@ inline void process_commands() break; #ifdef PIDTEMP case 301: // M301 - if(code_seen('P')) Heater::Kp = code_value(); - if(code_seen('I')) Heater::Ki = code_value()*PID_dT; - if(code_seen('D')) Heater::Kd = code_value()/PID_dT; - #ifdef PID_ADD_EXTRUSION_RATE - if(code_seen('C')) Heater::Kc = code_value(); - #endif - + 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; // ECHOLN("Kp "<<_FLOAT(Kp,2)); // ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); // ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); @@ -1194,19 +1194,19 @@ void wd_reset() { inline void kill() { #if TEMP_0_PIN > -1 - Heater::setCelsius(TEMPSENSOR_HOTEND,0); + target_raw[0]=0; #if HEATER_0_PIN > -1 WRITE(HEATER_0_PIN,LOW); #endif #endif #if TEMP_1_PIN > -1 - Heater::setCelsius(TEMPSENSOR_BED,0); + target_raw[1]=0; #if HEATER_1_PIN > -1 WRITE(HEATER_1_PIN,LOW); #endif #endif #if TEMP_2_PIN > -1 - Heater::setCelsius(TEMPSENSOR_AUX,0); + target_raw[2]=0; #if HEATER_2_PIN > -1 WRITE(HEATER_2_PIN,LOW); #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index cfeb6b2234..14f0bb1043 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -388,7 +388,7 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. while(block_buffer_tail == next_buffer_head) { - htr.manage_heater(); + manage_heater(); manage_inactivity(1); LCD_STATUS; } diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 01ff430f35..f4bd1289e0 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -585,7 +585,7 @@ void st_init() void st_synchronize() { while(plan_get_current_block()) { - htr.manage_heater(); + manage_heater(); manage_inactivity(1); LCD_STATUS; } diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 9be4bdc2f7..ebc772e1d8 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -37,11 +37,52 @@ #include "streaming.h" #include "temperature.h" +int target_bed_raw = 0; +int current_bed_raw = 0; +int target_raw[3] = {0, 0, 0}; +int current_raw[3] = {0, 0, 0}; +unsigned char temp_meas_ready = false; +unsigned long previous_millis_heater, previous_millis_bed_heater; +#ifdef PIDTEMP + double temp_iState = 0; + double temp_dState = 0; + double pTerm; + double iTerm; + double dTerm; + //int output; + double pid_error; + double temp_iState_min; + double temp_iState_max; + double pid_setpoint = 0.0; + double pid_input; + double pid_output; + bool pid_reset; + float HeaterPower; + + float Kp=DEFAULT_Kp; + float Ki=DEFAULT_Ki; + float Kd=DEFAULT_Kd; + float Kc=DEFAULT_Kc; +#endif //PIDTEMP -void static Heater::manage_heater() +#ifdef MINTEMP +int minttemp = temp2analog(MINTEMP); +#endif //MINTEMP +#ifdef MAXTEMP +int maxttemp = temp2analog(MAXTEMP); +#endif //MAXTEMP + +#ifdef BED_MINTEMP +int bed_minttemp = temp2analog(BED_MINTEMP); +#endif //BED_MINTEMP +#ifdef BED_MAXTEMP +int bed_maxttemp = temp2analog(BED_MAXTEMP); +#endif //BED_MAXTEMP + +void manage_heater() { #ifdef USE_WATCHDOG wd_reset(); @@ -49,11 +90,11 @@ void static Heater::manage_heater() float pid_input; float pid_output; - if(htr.temp_meas_ready != true) //better readability + if(temp_meas_ready != true) //better readability return; CRITICAL_SECTION_START; - htr.temp_meas_ready = false; + temp_meas_ready = false; CRITICAL_SECTION_END; #ifdef PIDTEMP @@ -135,8 +176,7 @@ CRITICAL_SECTION_END; // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -float const static temp2analog(const int celsius) -{ +float temp2analog(int celsius) { #ifdef HEATER_USES_THERMISTOR_1 int raw = 0; byte i; @@ -167,8 +207,7 @@ float const static temp2analog(const int celsius) // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -float const static temp2analogBed(const int celsius) -{ +float temp2analogBed(int celsius) { #ifdef BED_USES_THERMISTOR int raw = 0; @@ -198,7 +237,7 @@ float const static temp2analogBed(const int celsius) // Derived from RepRap FiveD extruder::getTemperature() // For hot end temperature measurement. -float const static Heater::analog2temp(const int raw) { +float analog2temp(int raw) { #ifdef HEATER_1_USES_THERMISTOR int celsius = 0; byte i; @@ -227,7 +266,7 @@ float const static Heater::analog2temp(const int raw) { // Derived from RepRap FiveD extruder::getTemperature() // For bed temperature measurement. -float const static Heater::analog2tempBed(const int raw) { +float analog2tempBed(int raw) { #ifdef BED_USES_THERMISTOR int celsius = 0; byte i; @@ -257,28 +296,8 @@ float const static Heater::analog2tempBed(const int raw) { #endif } -Heater::Heater() +void tp_init() { - for(short i=0;i<3;i++) - { - target_raw[i]=0; - current_raw[i] =0; - } - htr.temp_meas_ready = false; - #ifdef MINTEMP - minttemp = temp2analog(MINTEMP); - #endif //MINTEMP - #ifdef MAXTEMP - maxttemp = temp2analog(MAXTEMP); - #endif //MAXTEMP - - #ifdef BED_MINTEMP - bed_minttemp = temp2analog(BED_MINTEMP); - #endif //BED_MINTEMP - #ifdef BED_MAXTEMP - bed_maxttemp = temp2analog(BED_MAXTEMP); - #endif //BED_MAXTEMP - #if (HEATER_0_PIN > -1) SET_OUTPUT(HEATER_0_PIN); #endif @@ -292,14 +311,6 @@ Heater::Heater() #ifdef PIDTEMP temp_iState_min = 0.0; temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; - temp_iState = 0; - temp_dState = 0; - Kp=DEFAULT_Kp; - Ki=DEFAULT_Ki; - Kd=DEFAULT_Kd; - Kc=DEFAULT_Kc; - pid_setpoint = 0.0; - #endif //PIDTEMP // Set analog inputs @@ -396,39 +407,39 @@ ISR(TIMER0_COMPB_vect) if(temp_count >= 16) // 6 ms * 16 = 96ms. { #ifdef HEATER_1_USES_AD595 - htr.current_raw[0] = raw_temp_0_value; + current_raw[0] = raw_temp_0_value; #else - htr.current_raw[0] = 16383 - raw_temp_0_value; + current_raw[0] = 16383 - raw_temp_0_value; #endif #ifdef HEATER_2_USES_AD595 - htr.current_raw[2] = raw_temp_2_value; + current_raw[2] = raw_temp_2_value; #else - htr.current_raw[2] = 16383 - raw_temp_2_value; + current_raw[2] = 16383 - raw_temp_2_value; #endif #ifdef BED_USES_AD595 - htr.current_raw[1] = raw_temp_1_value; + current_raw[1] = raw_temp_1_value; #else - htr.current_raw[1] = 16383 - raw_temp_1_value; + current_raw[1] = 16383 - raw_temp_1_value; #endif - htr.temp_meas_ready = true; + temp_meas_ready = true; temp_count = 0; raw_temp_0_value = 0; raw_temp_1_value = 0; raw_temp_2_value = 0; #ifdef MAXTEMP #if (HEATER_0_PIN > -1) - if(htr.current_raw[TEMPSENSOR_HOTEND] >= htr.maxttemp) { - htr.target_raw[TEMPSENSOR_HOTEND] = 0; + if(current_raw[TEMPSENSOR_HOTEND] >= maxttemp) { + target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(htr.current_raw[TEMPSENSOR_AUX] >= htr.maxttemp) { - htr.target_raw[TEMPSENSOR_AUX] = 0; + if(current_raw[TEMPSENSOR_AUX] >= maxttemp) { + target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); } @@ -436,15 +447,15 @@ ISR(TIMER0_COMPB_vect) #endif //MAXTEMP #ifdef MINTEMP #if (HEATER_0_PIN > -1) - if(htr.current_raw[TEMPSENSOR_HOTEND] <= htr.minttemp) { - htr.target_raw[TEMPSENSOR_HOTEND] = 0; + if(current_raw[TEMPSENSOR_HOTEND] <= minttemp) { + target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(htr.current_raw[TEMPSENSOR_AUX] <= htr.minttemp) { - htr.target_raw[TEMPSENSOR_AUX] = 0; + if(current_raw[TEMPSENSOR_AUX] <= minttemp) { + target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); } @@ -452,8 +463,8 @@ ISR(TIMER0_COMPB_vect) #endif //MAXTEMP #ifdef BED_MINTEMP #if (HEATER_1_PIN > -1) - if(htr.current_raw[1] <= htr.bed_minttemp) { - htr.target_raw[1] = 0; + if(current_raw[1] <= bed_minttemp) { + target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); } @@ -461,8 +472,8 @@ ISR(TIMER0_COMPB_vect) #endif #ifdef BED_MAXTEMP #if (HEATER_1_PIN > -1) - if(htr.current_raw[1] >= htr.bed_maxttemp) { - htr.target_raw[1] = 0; + if(current_raw[1] >= bed_maxttemp) { + target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); } @@ -470,6 +481,3 @@ ISR(TIMER0_COMPB_vect) #endif } } - -//Heater htr; - diff --git a/Marlin/temperature.h b/Marlin/temperature.h index a93d46ba4b..e2e6c459c6 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -25,116 +25,14 @@ #ifdef PID_ADD_EXTRUSION_RATE #include "stepper.h" #endif - -enum TempSensor {TEMPSENSOR_HOTEND=0,TEMPSENSOR_BED=1, TEMPSENSOR_AUX=2}; - -// ther must be only one instance of this class, and it is created in temperature.cpp by itself and is called "htr". -// all the variables are static, so that of the compiler optimization is more easy. -// I honestly hope that this increases readability and structure. -// none of the variables or routines should be called from an secondary process/interrupt with the exceptino of current_raw[]. - -class Heater -{ -public: - Heater(); //treplaces tp_init(); - ~Heater(); - - void static manage_heater(); /// it is critical that this is called continously. - - // conversion routines, const since they don't change any class variables. - float const static temp2analog(const int celsius); - float const static temp2analogBed(const int celsius); - float const static analog2temp(const int raw); - float const static analog2tempBed(const int raw); - - inline float const static celsius(const TempSensor s) - { - if(s==TEMPSENSOR_BED) - return analog2tempBed(Heater::current_raw[s]); - else - return analog2temp(Heater::current_raw[s]); - }; - inline float const static celsiusTarget(const TempSensor s) - { - if(s==TEMPSENSOR_BED) - return analog2tempBed(Heater::target_raw[s]); - else - return analog2temp(Heater::target_raw[s]); - }; - inline float static setCelsius(const TempSensor s, const int celsius) - { - #ifdef PIDTEMP - if(s==TEMPSENSOR_HOTEND) - Heater::pid_setpoint = celsius; - #endif //PIDTEM - if(s==TEMPSENSOR_BED) - Heater::target_raw[s] = temp2analog(celsius); - else - Heater::target_raw[s] = temp2analogBed(celsius); - }; - - inline bool const static isHeating(TempSensor s) - { return (Heater::target_raw[s]>Heater::current_raw[s]);}; - inline bool const static isCooling(TempSensor s) - { return (Heater::target_raw[s]1)||force_lcd_update) + + if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(tt)); - oldcurrent=tt; + lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); + oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; } - int ttg=Heater::celsiusTarget(TEMPSENSOR_HOTEND); - if((ttg!=oldtarget)||force_lcd_update) + if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(ttg)); - oldtarget=ttg; + lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; } #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - static int oldcurrentbed=-1; - static int oldtargetbed=-1; - int tb=Heater::celsius(TEMPSENSOR_BED); - if((tb!=oldcurrentbed)||force_lcd_update) + static int oldcurrentbedraw=-1; + static int oldtargetbedraw=-1; + if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(tb)); - oldcurrentbed=tb; + lcd.print(ftostr3(analog2temp(current_bed_raw))); + oldcurrentraw=current_raw[TEMPSENSOR_BED]; } - int tg=Heater::celsiusTarget(TEMPSENSOR_BED); - if((tg!=oldtargebed)||force_lcd_update) + if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(Heater::celsiusTarget(TEMPSENSOR_BED)); - oldtargebed=tg; + lcd.print(ftostr3(analog2temp(target_bed_raw))); + oldtargetraw=target_bed_raw; } #endif //starttime=2; @@ -330,8 +327,8 @@ void MainMenu::showStatus() messagetext[0]='\0'; } #else //smaller LCDS---------------------------------- - static int oldcurrent=-1; - static int oldtarget=-1; + static int oldcurrentraw=-1; + static int oldtargetraw=-1; if(force_lcd_update) //initial display of content { encoderpos=feedmultiply; @@ -341,19 +338,18 @@ void MainMenu::showStatus() #endif } - int tt=Heater::celsius(TEMPSENSOR_HOTEND); - if((abs(tt-oldcurrent)>1)||force_lcd_update) + + if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(tt)); - oldcurrent=tt; + lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); + oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; } - int ttg=Heater::celsiusTarget(TEMPSENSOR_HOTEND); - if((ttg!=oldtarget)||force_lcd_update) + if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(ttg)); - oldtarge=ttg; + lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; } if(messagetext[0]!='\0') @@ -430,7 +426,7 @@ void MainMenu::showPrepare() if((activeline==line) && CLICKED) { BLOCK - Heater::setCelsius(TEMPSENSOR_HOTEND, 170); + target_raw[TEMPSENSOR_HOTEND] = temp2analog(170); beepshort(); } }break; @@ -535,7 +531,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" \002Nozzle:"); - lcd.setCursor(13,line);lcd.print(ftostr3(Heater::celsiusTarget(TEMPSENSOR_HOTEND))); + lcd.setCursor(13,line);lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); } if((activeline==line) ) @@ -545,11 +541,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Heater::celsiusTarget(TEMPSENSOR_HOTEND); + encoderpos=(int)analog2temp(target_raw[TEMPSENSOR_HOTEND]); } else { - Heater::setCelsius(TEMPSENSOR_HOTEND,encoderpos); + target_raw[TEMPSENSOR_HOTEND] = temp2analog(encoderpos); encoderpos=activeline*lcdslow; beepshort(); } @@ -673,7 +669,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-P: "); - lcd.setCursor(13,line);lcd.print(itostr4(Heater::Kp)); + lcd.setCursor(13,line);lcd.print(itostr4(Kp)); } if((activeline==line) ) @@ -683,11 +679,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Heater::Kp/5; + encoderpos=(int)Kp/5; } else { - Heater::Kp= encoderpos*5; + Kp= encoderpos*5; encoderpos=activeline*lcdslow; } @@ -707,7 +703,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-I: "); - lcd.setCursor(13,line);lcd.print(ftostr51(Heater::Ki)); + lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); } if((activeline==line) ) @@ -717,11 +713,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(Heater::Ki*10); + encoderpos=(int)(Ki*10); } else { - Heater::Ki= encoderpos/10.; + Ki= encoderpos/10.; encoderpos=activeline*lcdslow; } @@ -741,7 +737,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-D: "); - lcd.setCursor(13,line);lcd.print(itostr4(Heater::Kd)); + lcd.setCursor(13,line);lcd.print(itostr4(Kd)); } if((activeline==line) ) @@ -751,11 +747,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(Heater::Kd/5.); + encoderpos=(int)Kd/5; } else { - Heater::Kd= encoderpos*5; + Kd= encoderpos*5; encoderpos=activeline*lcdslow; } @@ -778,7 +774,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" PID-C: "); - lcd.setCursor(13,line);lcd.print(itostr3(Heater::Kc)); + lcd.setCursor(13,line);lcd.print(itostr3(Kc)); } if((activeline==line) ) @@ -788,11 +784,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Heater::Kc; + encoderpos=(int)Kc; } else { - Heater::Kc= encoderpos; + Kc= encoderpos; encoderpos=activeline*lcdslow; } From ea86a5e10f7b8c0b2e0e0bf97a1fc95dbac4ae89 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 5 Nov 2011 16:53:37 +0100 Subject: [PATCH 009/228] moved the variables in the ISR, thats the most normal use case of static. --- Marlin/temperature.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index ebc772e1d8..25df2f7014 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -322,15 +322,18 @@ void tp_init() TIMSK0 |= (1< -1) From d15f01e1b45119838900da53128c619ebe93895d Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 5 Nov 2011 19:21:36 +0100 Subject: [PATCH 010/228] Temperature changes --- Marlin/Configuration.h | 22 ++++---- Marlin/Marlin.h | 2 +- Marlin/Marlin.pde | 2 + Marlin/temperature.cpp | 86 ++++++++++++++++++------------- Marlin/temperature.h | 4 +- Marlin/thermistortables.h | 106 +++++++++++++++++++------------------- 6 files changed, 121 insertions(+), 101 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index b8c41301c9..dd5fe41525 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -27,10 +27,10 @@ #define THERMISTORHEATER_2 3 #define THERMISTORBED 3 +//#define HEATER_0_USES_THERMISTOR //#define HEATER_1_USES_THERMISTOR -//#define HEATER_2_USES_THERMISTOR -#define HEATER_1_USES_AD595 -//#define HEATER_2_USES_AD595 +#define HEATER_0_USES_AD595 +//#define HEATER_1_USES_AD595 // Select one of these only to define how the bed temp is read. //#define BED_USES_THERMISTOR @@ -47,8 +47,8 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false // This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 +#define BAUDRATE 250000 +//#define BAUDRATE 115200 //#define BAUDRATE 230400 // Comment out (using // at the start of the line) to disable SD support: @@ -57,7 +57,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define LCD_WIDTH 16 #define LCD_HEIGHT 2 -//#define ULTIPANEL +#define ULTIPANEL #ifdef ULTIPANEL //#define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT @@ -157,15 +157,17 @@ const int dropsegments=5; //everything with this number of steps will be ignore //#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one //// The minimal temperature defines the temperature below which the heater will not be enabled -#define MINTEMP 5 -#define BED_MINTEMP 5 +#define HEATER_0_MINTEMP 5 +//#define HEATER_1_MINTEMP 5 +//#define BED_MINTEMP 5 // When temperature exceeds max temp, your heater will be switched off. // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. -#define MAXTEMP 275 -#define BED_MAXTEMP 150 +#define HEATER_0_MAXTEMP 275 +//#define_HEATER_1_MAXTEMP 275 +//#define BED_MAXTEMP 150 /// PID settings: // Uncomment the following line to enable PID support. diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index cc43f00b2d..130cd865e8 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -57,7 +57,7 @@ void ClearToSend(); void get_coordinates(); void prepare_move(); -void kill(byte debug); +void kill(); //void check_axes_activity(); //void plan_init(); diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index cb55131df3..a95ae1fe9c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -54,6 +54,8 @@ char version_string[] = "1.0.0 Alpha 1"; //------------------- // G0 -> G1 // G1 - Coordinated Movement X Y Z E +// G2 - CW ARC +// G3 - CCW ARC // G4 - Dwell S or P // G28 - Home all Axis // G90 - Use Absolute Coordinates diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 7a9c56e10b..4406e94806 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -68,11 +68,18 @@ unsigned long previous_millis_heater, previous_millis_bed_heater; float Kc=DEFAULT_Kc; #endif //PIDTEMP -#ifdef MINTEMP -int minttemp = temp2analog(MINTEMP); +#ifdef HEATER_0_MINTEMP +int minttemp_0 = temp2analog(HEATER_0_MINTEMP); #endif //MINTEMP -#ifdef MAXTEMP -int maxttemp = temp2analog(MAXTEMP); +#ifdef HEATER_0_MAXTEMP +int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); +#endif //MAXTEMP + +#ifdef HEATER_1_MINTEMP +int minttemp_1 = temp2analog(HEATER_1_MINTEMP); +#endif //MINTEMP +#ifdef HEATER_1_MAXTEMP +int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); #endif //MAXTEMP #ifdef BED_MINTEMP @@ -173,29 +180,28 @@ CRITICAL_SECTION_END; // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -float temp2analog(int celsius) { - #ifdef HEATER_USES_THERMISTOR_1 +int temp2analog(int celsius) { + #ifdef HEATER_0_USES_THERMISTOR int raw = 0; byte i; - for (i=1; i raw) + if (heater_0_temptable[i][0] > raw) { - celsius = temptable_1[i-1][1] + - (raw - temptable_1[i-1][0]) * - (temptable_1[i][1] - temptable_1[i-1][1]) / - (temptable_1[i][0] - temptable_1[i-1][0]); + celsius = heater_0_temptable[i-1][1] + + (raw - heater_0_temptable[i-1][0]) * + (float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) / + (float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]); break; } } // Overflow: Set to last value in the table - if (i == NUMTEMPS_HEATER_1) celsius = temptable_1[i-1][1]; + if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1]; return celsius; - #elif defined HEATER_1_USES_AD595 + #elif defined HEATER_0_USES_AD595 return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; #endif } @@ -403,13 +409,13 @@ ISR(TIMER0_COMPB_vect) if(temp_count >= 16) // 6 ms * 16 = 96ms. { - #ifdef HEATER_1_USES_AD595 + #ifdef HEATER_0_USES_AD595 current_raw[0] = raw_temp_0_value; #else current_raw[0] = 16383 - raw_temp_0_value; #endif - #ifdef HEATER_2_USES_AD595 + #ifdef HEATER_1_USES_AD595 current_raw[2] = raw_temp_2_value; #else current_raw[2] = 16383 - raw_temp_2_value; @@ -426,35 +432,43 @@ ISR(TIMER0_COMPB_vect) raw_temp_0_value = 0; raw_temp_1_value = 0; raw_temp_2_value = 0; -#ifdef MAXTEMP +#ifdef HEATER_0_MAXTEMP #if (HEATER_0_PIN > -1) - if(current_raw[0] >= maxttemp) { + if(current_raw[0] >= maxttemp_0) { target_raw[0] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); + kill(); } #endif - #if (HEATER_2_PIN > -1) - if(current_raw[2] >= maxttemp) { +#endif +#ifdef HEATER_1_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[2] >= maxttemp_1) { target_raw[2] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); + kill() } #endif #endif //MAXTEMP -#ifdef MINTEMP +#ifdef HEATER_0_MINTEMP #if (HEATER_0_PIN > -1) - if(current_raw[0] <= minttemp) { + if(current_raw[0] <= minttemp_0) { target_raw[0] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); + kill(); } #endif +#endif +#ifdef HEATER_1_MINTEMP #if (HEATER_2_PIN > -1) - if(current_raw[2] <= minttemp) { + if(current_raw[2] <= minttemp_1) { target_raw[2] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); + kill(); } #endif #endif //MAXTEMP @@ -464,6 +478,7 @@ ISR(TIMER0_COMPB_vect) target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); + kill(); } #endif #endif @@ -473,6 +488,7 @@ ISR(TIMER0_COMPB_vect) target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); + kill(); } #endif #endif diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 986aca9998..7d9b7926e9 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -27,8 +27,8 @@ void tp_init(); void manage_heater(); //int temp2analogu(int celsius, const short table[][2], int numtemps); //float analog2tempu(int raw, const short table[][2], int numtemps); -float temp2analog(int celsius); -float temp2analogBed(int celsius); +int temp2analog(int celsius); +int temp2analogBed(int celsius); float analog2temp(int raw); float analog2tempBed(int raw); diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 0ea1991dce..9e3af6c52b 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -3,7 +3,7 @@ #define OVERSAMPLENR 16 -#if (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor +#if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORBED == 1) //100k bed thermistor #define NUMTEMPS_1 61 const short temptable_1[NUMTEMPS_1][2] = { @@ -70,7 +70,7 @@ const short temptable_1[NUMTEMPS_1][2] = { { 1008*OVERSAMPLENR , 0 } //safety }; #endif -#if (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor +#if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORBED == 2) //200k bed thermistor #define NUMTEMPS_2 21 const short temptable_2[NUMTEMPS_2][2] = { {1*OVERSAMPLENR, 848}, @@ -97,7 +97,7 @@ const short temptable_2[NUMTEMPS_2][2] = { }; #endif -#if (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts +#if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORBED == 3) //mendel-parts #define NUMTEMPS_3 28 const short temptable_3[NUMTEMPS_3][2] = { {1*OVERSAMPLENR,864}, @@ -131,7 +131,7 @@ const short temptable_3[NUMTEMPS_3][2] = { }; #endif -#if (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor +#if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORBED == 4) //10k thermistor #define NUMTEMPS_4 20 short temptable_4[NUMTEMPS_4][2] = { @@ -158,7 +158,7 @@ short temptable_4[NUMTEMPS_4][2] = { }; #endif -#if (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) +#if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) #define NUMTEMPS_5 61 const short temptable_5[NUMTEMPS_5][2] = { @@ -226,7 +226,7 @@ const short temptable_5[NUMTEMPS_5][2] = { }; #endif -#if (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor +#if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor #define NUMTEMPS_6 36 const short temptable_6[NUMTEMPS_6][2] = { {28*OVERSAMPLENR, 250}, @@ -268,7 +268,7 @@ const short temptable_6[NUMTEMPS_6][2] = { }; #endif -#if (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 +#if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 #define NUMTEMPS_7 54 const short temptable_7[NUMTEMPS_7][2] = { {46*OVERSAMPLENR, 270}, @@ -330,54 +330,54 @@ const short temptable_7[NUMTEMPS_7][2] = { -#if THERMISTORHEATER_1 == 1 -#define NUMTEMPS_HEATER_1 NUMTEMPS_1 -#define temptable_1 temptable_1 -#elif THERMISTORHEATER_1 == 2 -#define NUMTEMPS_HEATER_1 NUMTEMPS_2 -#define temptable_1 temptable_2 -#elif THERMISTORHEATER_1 == 3 -#define NUMTEMPS_HEATER_1 NUMTEMPS_3 -#define temptable_1 temptable_3 -#elif THERMISTORHEATER_1 == 4 -#define NUMTEMPS_HEATER_1 NUMTEMPS_4 -#define temptable_1 temptable_4 -#elif THERMISTORHEATER_1 == 5 -#define NUMTEMPS_HEATER_1 NUMTEMPS_5 -#define temptable_1 temptable_5 -#elif THERMISTORHEATER_1 == 6 -#define NUMTEMPS_HEATER_1 NUMTEMPS_6 -#define temptable_1 temptable_6 -#elif THERMISTORHEATER_1 == 7 -#define NUMTEMPS_HEATER_1 NUMTEMPS_7 -#define temptable_1 temptable_7 -#elif defined HEATER_1_USES_THERMISTOR -#error No heater 1 thermistor table specified +#if THERMISTORHEATER_0 == 1 +#define NUMTEMPS_HEATER_0 NUMTEMPS_1 +#define heater_0_temptable temptable_1 +#elif THERMISTORHEATER_0 == 2 +#define NUMTEMPS_HEATER_0 NUMTEMPS_2 +#define heater_0_temptable temptable_2 +#elif THERMISTORHEATER_0 == 3 +#define NUMTEMPS_HEATER_0 NUMTEMPS_3 +#define heater_0_temptable temptable_3 +#elif THERMISTORHEATER_0 == 4 +#define NUMTEMPS_HEATER_0 NUMTEMPS_4 +#define heater_0_temptable temptable_4 +#elif THERMISTORHEATER_0 == 5 +#define NUMTEMPS_HEATER_0 NUMTEMPS_5 +#define heater_0_temptable temptable_5 +#elif THERMISTORHEATER_0 == 6 +#define NUMTEMPS_HEATER_0 NUMTEMPS_6 +#define heater_0_temptable temptable_6 +#elif THERMISTORHEATER_0 == 7 +#define NUMTEMPS_HEATER_0 NUMTEMPS_7 +#define heater_0_temptable temptable_7 +#elif defined HEATER_0_USES_THERMISTOR +#error No heater 0 thermistor table specified #endif -#if THERMISTORHEATER_2 == 1 -#define NUMTEMPS_HEATER_2 NUMTEMPS_1 -#define temptable_2 temptable_1 -#elif THERMISTORHEATER_2 == 2 -#define NUMTEMPS_HEATER_2 NUMTEMPS_2 -#define temptable_2 temptable_2 -#elif THERMISTORHEATER_2 == 3 -#define NUMTEMPS_HEATER_2 NUMTEMPS_3 -#define temptable_2 temptable_3 -#elif THERMISTORHEATER_2 == 4 -#define NUMTEMPS_HEATER_2 NUMTEMPS_4 -#define temptable_2 temptable_4 -#elif THERMISTORHEATER_2 == 5 -#define NUMTEMPS_HEATER_2 NUMTEMPS_5 -#define temptable_2 temptable_5 -#elif THERMISTORHEATER_2 == 6 -#define NUMTEMPS_HEATER_2 NUMTEMPS_6 -#define temptable_2 temptable_6 -#elif THERMISTORHEATER_2 == 7 -#define NUMTEMPS_HEATER22 NUMTEMPS_7 -#define temptable_2 temptable_7 -#elif defined HEATER_2_USES_THERMISTOR -#error No heater 2 thermistor table specified +#if THERMISTORHEATER_1 == 1 +#define NUMTEMPS_HEATER_1 NUMTEMPS_1 +#define heater_1_temptable temptable_1 +#elif THERMISTORHEATER_1 == 2 +#define NUMTEMPS_HEATER_1 NUMTEMPS_2 +#define heater_1_temptable temptable_2 +#elif THERMISTORHEATER_1 == 3 +#define NUMTEMPS_HEATER_1 NUMTEMPS_3 +#define heater_1_temptable temptable_3 +#elif THERMISTORHEATER_1 == 4 +#define NUMTEMPS_HEATER_1 NUMTEMPS_4 +#define heater_1_temptable temptable_4 +#elif THERMISTORHEATER_1 == 5 +#define NUMTEMPS_HEATER_1 NUMTEMPS_5 +#define heater_1_temptable temptable_5 +#elif THERMISTORHEATER_1 == 6 +#define NUMTEMPS_HEATER_1 NUMTEMPS_6 +#define heater_1_temptable temptable_6 +#elif THERMISTORHEATER_1 == 7 +#define NUMTEMPS_HEATER_1 NUMTEMPS_7 +#define heater_1_temptable temptable_7 +#elif defined HEATER_1_USES_THERMISTOR +#error No heater 1 thermistor table specified #endif From 2e8e8878e55f1455155e43590afbaa1ed21e8e3f Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 5 Nov 2011 20:21:09 +0100 Subject: [PATCH 011/228] Corrected temp variables. --- Marlin/Configuration.h | 490 ++++---- Marlin/Marlin.pde | 2470 ++++++++++++++++++++-------------------- Marlin/temperature.cpp | 1004 ++++++++-------- Marlin/temperature.h | 116 +- Marlin/ultralcd.pde | 22 +- 5 files changed, 2052 insertions(+), 2050 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index ed258c71ad..e2d5cb0778 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,245 +1,245 @@ -#ifndef CONFIGURATION_H -#define CONFIGURATION_H - -//#define DEBUG_STEPS - -// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration - -//// The following define selects which electronics board you have. Please choose the one that matches your setup -// MEGA/RAMPS up to 1.2 = 3, -// RAMPS 1.3 = 33 -// Gen6 = 5, -// Sanguinololu 1.2 and above = 62 -// Ultimaker = 7, -#define MOTHERBOARD 7 -//#define MOTHERBOARD 5 - - -//// Thermistor settings: -// 1 is 100k thermistor -// 2 is 200k thermistor -// 3 is mendel-parts thermistor -// 4 is 10k thermistor -// 5 is ParCan supplied 104GT-2 100K -// 6 is EPCOS 100k -// 7 is 100k Honeywell thermistor 135-104LAG-J01 -#define THERMISTORHEATER_1 3 -#define THERMISTORHEATER_2 3 -#define THERMISTORBED 3 - -//#define HEATER_0_USES_THERMISTOR -//#define HEATER_1_USES_THERMISTOR -#define HEATER_0_USES_AD595 -//#define HEATER_1_USES_AD595 - -// Select one of these only to define how the bed temp is read. -//#define BED_USES_THERMISTOR -//#define BED_USES_AD595 - -#define HEATER_CHECK_INTERVAL 50 -#define BED_CHECK_INTERVAL 5000 - - -//// Endstop Settings -#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors -// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false - -// This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 -//#define BAUDRATE 230400 - -// Comment out (using // at the start of the line) to disable SD support: - -// #define ULTRA_LCD //any lcd - -#define ULTIPANEL -#define ULTIPANEL -#ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 -#define LCD_HEIGHT 4 -#else //no panel but just lcd - #ifdef ULTRA_LCD - #define LCD_WIDTH 16 - #define LCD_HEIGHT 2 - #endif -#endif - - -//#define SDSUPPORT // Enable SD Card Support in Hardware Console - - - -const int dropsegments=5; //everything with this number of steps will be ignored as move - -//// ADVANCED SETTINGS - to tweak parameters - -#include "thermistortables.h" - -// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 -#define X_ENABLE_ON 0 -#define Y_ENABLE_ON 0 -#define Z_ENABLE_ON 0 -#define E_ENABLE_ON 0 - -// Disables axis when it's not being used. -#define DISABLE_X false -#define DISABLE_Y false -#define DISABLE_Z false -#define DISABLE_E false - -// Inverting axis direction -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false - -//// ENDSTOP SETTINGS: -// Sets direction of endstops when homing; 1=MAX, -1=MIN -#define X_HOME_DIR -1 -#define Y_HOME_DIR -1 -#define Z_HOME_DIR -1 - -#define min_software_endstops false //If true, axis won't move to coordinates less than zero. -#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 210 -#define Y_MAX_LENGTH 210 -#define Z_MAX_LENGTH 210 - -//// MOVEMENT SETTINGS -#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -//note: on bernhards ultimaker 200 200 12 are working well. -#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds -//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. -//!!!!!!Use only if you know that your printer works at the maximum declared speeds. -// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze -#define TRAVELING_AT_MAXSPEED -#define AXIS_RELATIVE_MODES {false, false, false, false} - -#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) - -// default settings - -#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker -#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} -#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. - -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts - -#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 10 - -// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. -#define DEFAULT_MINSEGMENTTIME 20000 -#define DEFAULT_XYJERK 30.0*60 -#define DEFAULT_ZJERK 10.0*60 - - -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -//this enables the watchdog interrupt. -#define 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: -#define RESET_MANUAL - -#define WATCHDOG_TIMEOUT 4 - - - -//// Experimental watchdog and minimal temp -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 -//#define WATCHPERIOD 5000 //5 seconds - -// Actual temperature must be close to target for this long before M109 returns success -//#define TEMP_RESIDENCY_TIME 20 // (seconds) -//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one - -//// The minimal temperature defines the temperature below which the heater will not be enabled -#define HEATER_0_MINTEMP 5 -//#define HEATER_1_MINTEMP 5 -//#define BED_MINTEMP 5 - - -// When temperature exceeds max temp, your heater will be switched off. -// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! -// You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 275 -//#define_HEATER_1_MAXTEMP 275 -//#define BED_MAXTEMP 150 - - - - - - - -#define PIDTEMP -#ifdef PIDTEMP - /// PID settings: - // Uncomment the following line to enable PID support. - //#define SMOOTHING - //#define SMOOTHFACTOR 5.0 - //float current_raw_average=0; - #define K1 0.95 //smoothing of the PID - //#define PID_DEBUG // Sends debug data to the serial port. - //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_MAX 255 // limits current to nozzle - #define PID_INTEGRAL_DRIVE_MAX 255 - #define PID_dT 0.1 - //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 - - #define PID_CRITIAL_GAIN 3000 - #define PID_SWING_AT_CRITIAL 45 //seconds - #define PIDIADD 5 - /* - //PID according to Ziegler-Nichols method - float Kp = 0.6*PID_CRITIAL_GAIN; - float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; - float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; - */ - //PI according to Ziegler-Nichols method - #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) - #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (0) - - #define PID_ADD_EXTRUSION_RATE - #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) - #endif -#endif // PIDTEMP - -// extruder advance constant (s2/mm3) -// -// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 -// -// hooke's law says: force = k * distance -// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant -// so: v ^ 2 is proportional to number of steps we advance the extruder -//#define ADVANCE - -#ifdef ADVANCE -#define EXTRUDER_ADVANCE_K .3 - -#define D_FILAMENT 1.7 -#define STEPS_MM_E 65 -#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) -#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) - -#endif // ADVANCE - -// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 -#if defined SDSUPPORT -// The number of linear motions that can be in the plan at any give time. - #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller -#else - #define BLOCK_BUFFER_SIZE 16 // maximize block buffer -#endif - - -#endif +#ifndef CONFIGURATION_H +#define CONFIGURATION_H + +//#define DEBUG_STEPS + +// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration + +//// The following define selects which electronics board you have. Please choose the one that matches your setup +// MEGA/RAMPS up to 1.2 = 3, +// RAMPS 1.3 = 33 +// Gen6 = 5, +// Sanguinololu 1.2 and above = 62 +// Ultimaker = 7, +#define MOTHERBOARD 7 +//#define MOTHERBOARD 5 + + +//// Thermistor settings: +// 1 is 100k thermistor +// 2 is 200k thermistor +// 3 is mendel-parts thermistor +// 4 is 10k thermistor +// 5 is ParCan supplied 104GT-2 100K +// 6 is EPCOS 100k +// 7 is 100k Honeywell thermistor 135-104LAG-J01 +#define THERMISTORHEATER_1 3 +#define THERMISTORHEATER_2 3 +#define THERMISTORBED 3 + +//#define HEATER_0_USES_THERMISTOR +//#define HEATER_1_USES_THERMISTOR +#define HEATER_0_USES_AD595 +//#define HEATER_1_USES_AD595 + +// Select one of these only to define how the bed temp is read. +//#define BED_USES_THERMISTOR +//#define BED_USES_AD595 + +#define HEATER_CHECK_INTERVAL 50 +#define BED_CHECK_INTERVAL 5000 + + +//// Endstop Settings +#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors +// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. +const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false + +// This determines the communication speed of the printer +#define BAUDRATE 250000 +//#define BAUDRATE 115200 +//#define BAUDRATE 230400 + +// Comment out (using // at the start of the line) to disable SD support: + +// #define ULTRA_LCD //any lcd + +#define ULTIPANEL +#define ULTIPANEL +#ifdef ULTIPANEL + //#define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 +#define LCD_HEIGHT 4 +#else //no panel but just lcd + #ifdef ULTRA_LCD + #define LCD_WIDTH 16 + #define LCD_HEIGHT 2 + #endif +#endif + + +//#define SDSUPPORT // Enable SD Card Support in Hardware Console + + + +const int dropsegments=5; //everything with this number of steps will be ignored as move + +//// ADVANCED SETTINGS - to tweak parameters + +#include "thermistortables.h" + +// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 +#define X_ENABLE_ON 0 +#define Y_ENABLE_ON 0 +#define Z_ENABLE_ON 0 +#define E_ENABLE_ON 0 + +// Disables axis when it's not being used. +#define DISABLE_X false +#define DISABLE_Y false +#define DISABLE_Z false +#define DISABLE_E false + +// Inverting axis direction +#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false +#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false + +//// ENDSTOP SETTINGS: +// Sets direction of endstops when homing; 1=MAX, -1=MIN +#define X_HOME_DIR -1 +#define Y_HOME_DIR -1 +#define Z_HOME_DIR -1 + +#define min_software_endstops false //If true, axis won't move to coordinates less than zero. +#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. +#define X_MAX_LENGTH 210 +#define Y_MAX_LENGTH 210 +#define Z_MAX_LENGTH 210 + +//// MOVEMENT SETTINGS +#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E +//note: on bernhards ultimaker 200 200 12 are working well. +#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds +//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. +//!!!!!!Use only if you know that your printer works at the maximum declared speeds. +// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze +#define TRAVELING_AT_MAXSPEED +#define AXIS_RELATIVE_MODES {false, false, false, false} + +#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker +#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} +#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts + +#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 10 + +// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. +#define DEFAULT_MINSEGMENTTIME 20000 +#define DEFAULT_XYJERK 30.0*60 +#define DEFAULT_ZJERK 10.0*60 + + +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +//this enables the watchdog interrupt. +#define 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: +#define RESET_MANUAL + +#define WATCHDOG_TIMEOUT 4 + + + +//// Experimental watchdog and minimal temp +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 +//#define WATCHPERIOD 5000 //5 seconds + +// Actual temperature must be close to target for this long before M109 returns success +//#define TEMP_RESIDENCY_TIME 20 // (seconds) +//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one + +//// The minimal temperature defines the temperature below which the heater will not be enabled +#define HEATER_0_MINTEMP 5 +//#define HEATER_1_MINTEMP 5 +//#define BED_MINTEMP 5 + + +// When temperature exceeds max temp, your heater will be switched off. +// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! +// You should use MINTEMP for thermistor short/failure protection. +#define HEATER_0_MAXTEMP 275 +//#define_HEATER_1_MAXTEMP 275 +//#define BED_MAXTEMP 150 + + + + + + + +#define PIDTEMP +#ifdef PIDTEMP + /// PID settings: + // Uncomment the following line to enable PID support. + //#define SMOOTHING + //#define SMOOTHFACTOR 5.0 + //float current_raw_average=0; + #define K1 0.95 //smoothing of the PID + //#define PID_DEBUG // Sends debug data to the serial port. + //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % + #define PID_MAX 255 // limits current to nozzle + #define PID_INTEGRAL_DRIVE_MAX 255 + #define PID_dT 0.1 + //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 + + #define PID_CRITIAL_GAIN 3000 + #define PID_SWING_AT_CRITIAL 45 //seconds + #define PIDIADD 5 + /* + //PID according to Ziegler-Nichols method + float Kp = 0.6*PID_CRITIAL_GAIN; + float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; + float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; + */ + //PI according to Ziegler-Nichols method + #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) + #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (0) + + #define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) + #endif +#endif // PIDTEMP + +// extruder advance constant (s2/mm3) +// +// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 +// +// hooke's law says: force = k * distance +// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant +// so: v ^ 2 is proportional to number of steps we advance the extruder +//#define ADVANCE + +#ifdef ADVANCE +#define EXTRUDER_ADVANCE_K .3 + +#define D_FILAMENT 1.7 +#define STEPS_MM_E 65 +#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) +#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) + +#endif // ADVANCE + +// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 +#if defined SDSUPPORT +// The number of linear motions that can be in the plan at any give time. + #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller +#else + #define BLOCK_BUFFER_SIZE 16 // maximize block buffer +#endif + + +#endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index f1dbc5c441..7615cccf82 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1,1235 +1,1235 @@ -/* - 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 "EEPROMwrite.h" -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "streaming.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" - -#ifdef SIMPLE_LCD - #include "Simplelcd.h" -#endif - -char version_string[] = "1.0.0 Alpha 1"; - -#ifdef SDSUPPORT -#include "SdFat.h" -#endif //SDSUPPORT - - -// 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 -// G28 - Home all Axis -// G90 - Use Absolute Coordinates -// G91 - Use Relative Coordinates -// G92 - Set current position to cordinates given - -//RepRap M Codes -// 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 -// 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 -// 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 -// M115 - Capabilities string -// 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 -// M220 - set speed factor override percentage S:factor in percent -// M301 - Set PID parameters P I and D -// M500 - stores paramters in EEPROM -// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D -// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. - -//Stepper Movement Variables - -char axis_codes[NUM_AXIS] = { - 'X', 'Y', 'Z', 'E'}; -float destination[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -float current_position[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -bool home_all_axis = true; -float feedrate = 1500.0, next_feedrate, saved_feedrate; -long gcode_N, gcode_LastN; - -float homing_feedrate[] = HOMING_FEEDRATE; -bool axis_relative_modes[] = AXIS_RELATIVE_MODES; - -bool relative_mode = false; //Determines Absolute or Relative Coordinates -bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. - -uint8_t fanpwm=0; - -volatile int feedmultiply=100; //100->1 200->2 -int saved_feedmultiply; -volatile bool feedmultiplychanged=false; -// comm variables -#define MAX_CMD_SIZE 96 -#define BUFSIZE 4 -char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; -bool fromsd[BUFSIZE]; -int bufindr = 0; -int bufindw = 0; -int buflen = 0; -int i = 0; -char serial_char; -int serial_count = 0; -boolean comment_mode = false; -char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc -extern float HeaterPower; - -#include "EEPROM.h" - -const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 - -float tt = 0, bt = 0; -#ifdef WATCHPERIOD -int watch_raw = -1000; -unsigned long watchmillis = 0; -#endif //WATCHPERIOD - -//Inactivity shutdown variables -unsigned long previous_millis_cmd = 0; -unsigned long max_inactive_time = 0; -unsigned long stepper_inactive_time = 0; - -unsigned long starttime=0; -unsigned long stoptime=0; -#ifdef SDSUPPORT -Sd2Card card; -SdVolume volume; -SdFile root; -SdFile file; -uint32_t filesize = 0; -uint32_t sdpos = 0; -bool sdmode = false; -bool sdactive = false; -bool savetosd = false; -int16_t n; -unsigned long autostart_atmillis=0; - -void initsd(){ - sdactive = false; -#if SDSS >- 1 - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)){ - //if (!card.init(SPI_HALF_SPEED,SDSS)) - Serial.println("SD init fail"); - } - else if (!volume.init(&card)) - Serial.println("volume.init failed"); - else if (!root.openRoot(&volume)) - Serial.println("openRoot failed"); - else - { - sdactive = true; - Serial.println("SD card ok"); - } -#endif //SDSS -} - -void quickinitsd(){ - sdactive=false; - autostart_atmillis=millis()+5000; -} - -inline void write_command(char *buf){ - char* begin = buf; - char* npos = 0; - char* end = buf + strlen(buf) - 1; - - file.writeError = false; - if((npos = strchr(buf, 'N')) != NULL){ - begin = strchr(npos, ' ') + 1; - end = strchr(npos, '*') - 1; - } - end[1] = '\r'; - end[2] = '\n'; - end[3] = '\0'; - //Serial.println(begin); - file.write(begin); - if (file.writeError){ - Serial.println("error writing to file"); - } -} -#endif //SDSUPPORT - - -///adds an command to the main command buffer -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.print("en:");Serial.println(cmdbuffer[bufindw]); - bufindw= (bufindw + 1)%BUFSIZE; - buflen += 1; - } -} - -void setup() -{ - - Serial.begin(BAUDRATE); - ECHOLN("Marlin "< -1 - SET_OUTPUT(SDPOWER); - WRITE(SDPOWER,HIGH); -#endif //SDPOWER - quickinitsd(); - -#endif //SDSUPPORT - plan_init(); // Initialize planner; - st_init(); // Initialize stepper; - tp_init(); // Initialize temperature loop - //checkautostart(); -} - -#ifdef SDSUPPORT -bool autostart_stilltocheck=true; - - -void checkautostart(bool force) -{ - //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) - { - for(int i=0;i<(int)strlen((char*)p.name);i++) - p.name[i]=tolower(p.name[i]); - //Serial.print((char*)p.name); - //Serial.print(" "); - //Serial.println(autoname); - if(p.name[9]!='~') //skip safety copies - if(strncmp((char*)p.name,autoname,5)==0) - { - char cmd[30]; - - sprintf(cmd,"M23 %s",autoname); - //sprintf(cmd,"M115"); - //enquecommand("G92 Z0"); - //enquecommand("G1 Z10 F2000"); - //enquecommand("G28 X-105 Y-105"); - enquecommand(cmd); - enquecommand("M24"); - found=true; - - } - } - if(!found) - lastnr=-1; - else - lastnr++; - -} -#else - -inline void checkautostart(bool x) -{ -} -#endif - - -void loop() -{ - if(buflen<3) - get_command(); - checkautostart(false); - if(buflen) - { -#ifdef SDSUPPORT - if(savetosd){ - if(strstr(cmdbuffer[bufindr],"M29") == NULL){ - write_command(cmdbuffer[bufindr]); - Serial.println("ok"); - } - else{ - file.sync(); - file.close(); - savetosd = false; - Serial.println("Done saving file."); - } - } - else{ - process_commands(); - } -#else - process_commands(); -#endif //SDSUPPORT - buflen = (buflen-1); - bufindr = (bufindr + 1)%BUFSIZE; - } - //check heater every n milliseconds - manage_heater(); - manage_inactivity(1); - LCD_STATUS; -} - - -inline void get_command() -{ - while( Serial.available() > 0 && buflen < BUFSIZE) { - serial_char = Serial.read(); - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) - { - if(!serial_count) return; //if empty line - cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ - 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.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); - Serial.println(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.print("Error: checksum mismatch, Last Line:"); - Serial.println(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { - Serial.print("Error: No Checksum with line number, Last Line:"); - Serial.println(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.print("Error: No Line Number with checksum, Last Line:"); - Serial.println(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: -#ifdef SDSUPPORT - if(savetosd) - break; -#endif //SDSUPPORT - Serial.println("ok"); - break; - default: - break; - } - - } - bufindw = (bufindw + 1)%BUFSIZE; - buflen += 1; - - } - 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; - } - } -#ifdef SDSUPPORT - if(!sdmode || serial_count!=0){ - return; - } - while( filesize > sdpos && buflen < BUFSIZE) { - n = file.read(); - serial_char = (char)n; - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) - { - sdpos = file.curPosition(); - if(sdpos >= filesize){ - sdmode = false; - Serial.println("Done printing file"); - 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.println(time); - LCD_MESSAGE(time); - checkautostart(true); - } - if(!serial_count) 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 - -} - - -inline float code_value() { - return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); -} -inline long code_value_long() { - return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); -} -inline bool code_seen(char code_string[]) { - return (strstr(cmdbuffer[bufindr], code_string) != NULL); -} //Return True if the string was found - -inline bool code_seen(char code) -{ - strchr_pointer = strchr(cmdbuffer[bufindr], code); - return (strchr_pointer != NULL); //Return True if a character was found -} - -inline 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 - get_coordinates(); // For X Y Z E F - prepare_move(); - previous_millis_cmd = millis(); - //ClearToSend(); - return; - //break; - case 4: // G4 dwell - codenum = 0; - if(code_seen('P')) codenum = code_value(); // milliseconds to wait - if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait - codenum += millis(); // keep track of when we started waiting - while(millis() < codenum ){ - manage_heater(); - } - break; - case 28: //G28 Home all Axis one at a time - saved_feedrate = feedrate; - saved_feedmultiply = feedmultiply; - feedmultiply = 100; - - for(int 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((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { - if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ -// st_synchronize(); - current_position[X_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; - feedrate = homing_feedrate[X_AXIS]; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = -5 * X_HOME_DIR; - prepare_move(); - -// st_synchronize(); - destination[X_AXIS] = 10 * X_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]/2 ; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = current_position[X_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { - if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ - 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[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]; - prepare_move(); -// st_synchronize(); - - 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[Y_AXIS] = -5 * Y_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Y_AXIS] = 10 * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = current_position[Y_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { - if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = -2 * Z_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Z_AXIS] = 3 * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0.0; - } - } - feedrate = saved_feedrate; - feedmultiply = saved_feedmultiply; - previous_millis_cmd = millis(); - break; - case 90: // G90 - relative_mode = false; - break; - case 91: // G91 - relative_mode = true; - break; - case 92: // G92 - if(!code_seen(axis_codes[E_AXIS])) - st_synchronize(); - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) current_position[i] = code_value(); - } - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - break; - } - } - - else if(code_seen('M')) - { - - switch( (int)code_value() ) - { -#ifdef SDSUPPORT - - case 20: // M20 - list SD card - Serial.println("Begin file list"); - root.ls(); - Serial.println("End file list"); - break; - case 21: // M21 - init SD card - sdmode = false; - initsd(); - break; - case 22: //M22 - release SD card - sdmode = false; - sdactive = false; - break; - case 23: //M23 - Select file - if(sdactive){ - sdmode = false; - file.close(); - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos!=NULL) - *(starpos-1)='\0'; - if (file.open(&root, strchr_pointer + 4, O_READ)) { - Serial.print("File opened:"); - Serial.print(strchr_pointer + 4); - Serial.print(" Size:"); - Serial.println(file.fileSize()); - sdpos = 0; - filesize = file.fileSize(); - Serial.println("File selected"); - } - else{ - Serial.println("file.open failed"); - } - } - break; - case 24: //M24 - Start SD print - if(sdactive){ - sdmode = true; - starttime=millis(); - } - break; - case 25: //M25 - Pause SD print - if(sdmode){ - sdmode = false; - } - break; - case 26: //M26 - Set SD index - if(sdactive && code_seen('S')){ - sdpos = code_value_long(); - file.seekSet(sdpos); - } - break; - case 27: //M27 - Get SD status - if(sdactive){ - Serial.print("SD printing byte "); - Serial.print(sdpos); - Serial.print("/"); - Serial.println(filesize); - } - else{ - Serial.println("Not SD printing"); - } - break; - case 28: //M28 - Start SD write - if(sdactive){ - char* npos = 0; - file.close(); - sdmode = false; - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos != NULL){ - npos = strchr(cmdbuffer[bufindr], 'N'); - strchr_pointer = strchr(npos,' ') + 1; - *(starpos-1) = '\0'; - } - if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) - { - Serial.print("open failed, File: "); - Serial.print(strchr_pointer + 4); - Serial.print("."); - } - else{ - savetosd = true; - Serial.print("Writing to file: "); - Serial.println(strchr_pointer + 4); - } - } - break; - case 29: //M29 - Stop SD write - //processed in write to file routine above - //savetosd = false; - break; - case 30: - { - 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.println(time); - LCD_MESSAGE(time); - } - break; -#endif //SDSUPPORT - 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(int i = 0; i < (int)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 (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); -#ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[TEMPSENSOR_HOTEND] > current_raw[TEMPSENSOR_HOTEND]){ - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; - }else{ - watchmillis = 0; - } - #endif - break; - case 140: // M140 set bed temp - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); - break; - case 105: // M105 - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = analog2temp(current_raw[TEMPSENSOR_HOTEND]); - #endif - #if TEMP_1_PIN > -1 - bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); - #endif - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - Serial.print("ok T:"); - Serial.print(tt); -// Serial.print(", raw:"); -// Serial.print(current_raw); - #if TEMP_1_PIN > -1 -#ifdef PIDTEMP - Serial.print(" B:"); - #if TEMP_1_PIN > -1 - Serial.println(bt); - #else - Serial.println(HeaterPower); - #endif -#else - Serial.println(); -#endif - #else - Serial.println(); - #endif - #else - Serial.println("No thermistors - no temp"); - #endif - return; - //break; - case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGE("Heating..."); - if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); - #ifdef PIDTEMP - pid_setpoint = code_value(); - #endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[TEMPSENSOR_HOTEND]>current_raw[TEMPSENSOR_HOTEND]){ - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; - } else { - watchmillis = 0; - } - #endif //WATCHPERIOD - codenum = millis(); - - /* See if we are heating up or cooling down */ - bool target_direction = (current_raw[0] < target_raw[0]); // 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((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || - (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { - #else - while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { - #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down - Serial.print("T:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND]) ); - codenum = millis(); - } - manage_heater(); - 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 && current_raw[0] >= target_raw[0]) || - (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || - (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGE("Marlin ready."); - } - break; - case 190: // M190 - Wait bed for heater to reach target. - #if TEMP_1_PIN > -1 - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); - codenum = millis(); - while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) - { - if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. - { - float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND]); - Serial.print("T:"); - Serial.println( tt ); - Serial.print("ok T:"); - Serial.print( tt ); - Serial.print(" B:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); - codenum = millis(); - } - manage_heater(); - } - #endif - break; -#if FAN_PIN > -1 - case 106: //M106 Fan On - if (code_seen('S')){ - WRITE(FAN_PIN,HIGH); - fanpwm=constrain(code_value(),0,255); - analogWrite(FAN_PIN, fanpwm); - } - else { - WRITE(FAN_PIN,HIGH); - fanpwm=255; - analogWrite(FAN_PIN, fanpwm); - } - break; - case 107: //M107 Fan Off - WRITE(FAN_PIN,LOW); - analogWrite(FAN_PIN, 0); - break; -#endif -#if (PS_ON_PIN > -1) - case 80: // M80 - ATX Power On - SET_OUTPUT(PS_ON_PIN); //GND - break; - case 81: // M81 - ATX Power Off - SET_INPUT(PS_ON_PIN); //Floating - break; -#endif - case 82: - axis_relative_modes[3] = false; - break; - case 83: - axis_relative_modes[3] = true; - break; - case 18: - case 84: - if(code_seen('S')){ - stepper_inactive_time = code_value() * 1000; - } - else{ - st_synchronize(); - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - break; - case 85: // M85 - code_seen('S'); - max_inactive_time = code_value() * 1000; - break; - case 92: // M92 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); - } - - break; - case 115: // M115 - Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); - break; - case 114: // M114 - Serial.print("X:"); - Serial.print(current_position[X_AXIS]); - Serial.print("Y:"); - Serial.print(current_position[Y_AXIS]); - Serial.print("Z:"); - Serial.print(current_position[Z_AXIS]); - Serial.print("E:"); - Serial.print(current_position[E_AXIS]); - #ifdef DEBUG_STEPS - Serial.print(" Count X:"); - Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); - Serial.print("Y:"); - Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); - Serial.print("Z:"); - Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); - #endif - Serial.println(""); - break; - case 119: // M119 -#if (X_MIN_PIN > -1) - Serial.print("x_min:"); - Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (X_MAX_PIN > -1) - Serial.print("x_max:"); - Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MIN_PIN > -1) - Serial.print("y_min:"); - Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MAX_PIN > -1) - Serial.print("y_max:"); - Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MIN_PIN > -1) - Serial.print("z_min:"); - Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MAX_PIN > -1) - Serial.print("z_max:"); - Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif - Serial.println(""); - break; - //TODO: update for all axis, use for loop - case 201: // M201 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) 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(int 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(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; - } - 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()*60 ; - if(code_seen('T')) mintravelfeedrate = code_value()*60 ; - if(code_seen('B')) minsegmenttime = code_value() ; - if(code_seen('X')) max_xy_jerk = code_value()*60 ; - if(code_seen('Z')) max_z_jerk = code_value()*60 ; - } - break; - case 220: // M220 S- set speed factor override percentage - { - if(code_seen('S')) - { - feedmultiply = code_value() ; - feedmultiplychanged=true; - } - } - 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; -// ECHOLN("Kp "<<_FLOAT(Kp,2)); -// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); -// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); - -// temp_iState_min = 0.0; -// if (Ki!=0) { -// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); -// } -// else temp_iState_max = 1.0e10; - break; -#endif //PIDTEMP - case 500: // Store settings in EEPROM - { - StoreSettings(); - } - break; - case 501: // Read settings from EEPROM - { - RetrieveSettings(); - } - break; - case 502: // Revert to default settings - { - RetrieveSettings(true); - } - break; - - } - } - else{ - Serial.println("Unknown command:"); - Serial.println(cmdbuffer[bufindr]); - } - - ClearToSend(); -} - -void FlushSerialRequestResend() -{ - //char cmdbuffer[bufindr][100]="Resend:"; - Serial.flush(); - Serial.print("Resend:"); - Serial.println(gcode_LastN + 1); - ClearToSend(); -} - -void ClearToSend() -{ - previous_millis_cmd = millis(); -#ifdef SDSUPPORT - if(fromsd[bufindr]) - return; -#endif //SDSUPPORT - Serial.println("ok"); -} - -inline void get_coordinates() -{ - for(int 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]; - 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; - } -} - -void prepare_move() -{ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); - for(int i=0; i < NUM_AXIS; i++) { - current_position[i] = destination[i]; - } -} - - - -#ifdef USE_WATCHDOG - -#include -#include - -volatile uint8_t timeout_seconds=0; - -void(* ctrlaltdelete) (void) = 0; - -ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec - if(timeout_seconds++ >= WATCHDOG_TIMEOUT) - { - kill(); -#ifdef RESET_MANUAL - LCD_MESSAGE("Please Reset!"); - ECHOLN("echo_: Something is wrong, please turn off the printer."); -#else - LCD_MESSAGE("Timeout, resetting!"); -#endif - //disable watchdog, it will survife reboot. - WDTCSR |= (1< -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif - disable_x(); - disable_y(); - disable_z(); - disable_e(); - - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); - Serial.println("!! Printer halted. kill() called!!"); - while(1); // Wait for reset -} - -void manage_inactivity(byte debug) { - if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); - if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - check_axes_activity(); -} +/* + 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 "EEPROMwrite.h" +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" + +#ifdef SIMPLE_LCD + #include "Simplelcd.h" +#endif + +char version_string[] = "1.0.0 Alpha 1"; + +#ifdef SDSUPPORT +#include "SdFat.h" +#endif //SDSUPPORT + + +// 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 +// G28 - Home all Axis +// G90 - Use Absolute Coordinates +// G91 - Use Relative Coordinates +// G92 - Set current position to cordinates given + +//RepRap M Codes +// 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 +// 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 +// 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 +// M115 - Capabilities string +// 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 +// M220 - set speed factor override percentage S:factor in percent +// M301 - Set PID parameters P I and D +// M500 - stores paramters in EEPROM +// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D +// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. + +//Stepper Movement Variables + +char axis_codes[NUM_AXIS] = { + 'X', 'Y', 'Z', 'E'}; +float destination[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +float current_position[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +bool home_all_axis = true; +float feedrate = 1500.0, next_feedrate, saved_feedrate; +long gcode_N, gcode_LastN; + +float homing_feedrate[] = HOMING_FEEDRATE; +bool axis_relative_modes[] = AXIS_RELATIVE_MODES; + +bool relative_mode = false; //Determines Absolute or Relative Coordinates +bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. + +uint8_t fanpwm=0; + +volatile int feedmultiply=100; //100->1 200->2 +int saved_feedmultiply; +volatile bool feedmultiplychanged=false; +// comm variables +#define MAX_CMD_SIZE 96 +#define BUFSIZE 4 +char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; +bool fromsd[BUFSIZE]; +int bufindr = 0; +int bufindw = 0; +int buflen = 0; +int i = 0; +char serial_char; +int serial_count = 0; +boolean comment_mode = false; +char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc +extern float HeaterPower; + +#include "EEPROM.h" + +const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 + +float tt = 0, bt = 0; +#ifdef WATCHPERIOD +int watch_raw = -1000; +unsigned long watchmillis = 0; +#endif //WATCHPERIOD + +//Inactivity shutdown variables +unsigned long previous_millis_cmd = 0; +unsigned long max_inactive_time = 0; +unsigned long stepper_inactive_time = 0; + +unsigned long starttime=0; +unsigned long stoptime=0; +#ifdef SDSUPPORT +Sd2Card card; +SdVolume volume; +SdFile root; +SdFile file; +uint32_t filesize = 0; +uint32_t sdpos = 0; +bool sdmode = false; +bool sdactive = false; +bool savetosd = false; +int16_t n; +unsigned long autostart_atmillis=0; + +void initsd(){ + sdactive = false; +#if SDSS >- 1 + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)){ + //if (!card.init(SPI_HALF_SPEED,SDSS)) + Serial.println("SD init fail"); + } + else if (!volume.init(&card)) + Serial.println("volume.init failed"); + else if (!root.openRoot(&volume)) + Serial.println("openRoot failed"); + else + { + sdactive = true; + Serial.println("SD card ok"); + } +#endif //SDSS +} + +void quickinitsd(){ + sdactive=false; + autostart_atmillis=millis()+5000; +} + +inline void write_command(char *buf){ + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL){ + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + //Serial.println(begin); + file.write(begin); + if (file.writeError){ + Serial.println("error writing to file"); + } +} +#endif //SDSUPPORT + + +///adds an command to the main command buffer +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.print("en:");Serial.println(cmdbuffer[bufindw]); + bufindw= (bufindw + 1)%BUFSIZE; + buflen += 1; + } +} + +void setup() +{ + + Serial.begin(BAUDRATE); + ECHOLN("Marlin "< -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); +#endif //SDPOWER + quickinitsd(); + +#endif //SDSUPPORT + plan_init(); // Initialize planner; + st_init(); // Initialize stepper; + tp_init(); // Initialize temperature loop + //checkautostart(); +} + +#ifdef SDSUPPORT +bool autostart_stilltocheck=true; + + +void checkautostart(bool force) +{ + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + //sprintf(cmd,"M115"); + //enquecommand("G92 Z0"); + //enquecommand("G1 Z10 F2000"); + //enquecommand("G28 X-105 Y-105"); + enquecommand(cmd); + enquecommand("M24"); + found=true; + + } + } + if(!found) + lastnr=-1; + else + lastnr++; + +} +#else + +inline void checkautostart(bool x) +{ +} +#endif + + +void loop() +{ + if(buflen<3) + get_command(); + checkautostart(false); + if(buflen) + { +#ifdef SDSUPPORT + if(savetosd){ + if(strstr(cmdbuffer[bufindr],"M29") == NULL){ + write_command(cmdbuffer[bufindr]); + Serial.println("ok"); + } + else{ + file.sync(); + file.close(); + savetosd = false; + Serial.println("Done saving file."); + } + } + else{ + process_commands(); + } +#else + process_commands(); +#endif //SDSUPPORT + buflen = (buflen-1); + bufindr = (bufindr + 1)%BUFSIZE; + } + //check heater every n milliseconds + manage_heater(); + manage_inactivity(1); + LCD_STATUS; +} + + +inline void get_command() +{ + while( Serial.available() > 0 && buflen < BUFSIZE) { + serial_char = Serial.read(); + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) + { + if(!serial_count) return; //if empty line + cmdbuffer[bufindw][serial_count] = 0; //terminate string + if(!comment_mode){ + 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.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); + Serial.println(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.print("Error: checksum mismatch, Last Line:"); + Serial.println(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + //if no errors, continue parsing + } + else + { + Serial.print("Error: No Checksum with line number, Last Line:"); + Serial.println(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.print("Error: No Line Number with checksum, Last Line:"); + Serial.println(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: +#ifdef SDSUPPORT + if(savetosd) + break; +#endif //SDSUPPORT + Serial.println("ok"); + break; + default: + break; + } + + } + bufindw = (bufindw + 1)%BUFSIZE; + buflen += 1; + + } + 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; + } + } +#ifdef SDSUPPORT + if(!sdmode || serial_count!=0){ + return; + } + while( filesize > sdpos && buflen < BUFSIZE) { + n = file.read(); + serial_char = (char)n; + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) + { + sdpos = file.curPosition(); + if(sdpos >= filesize){ + sdmode = false; + Serial.println("Done printing file"); + 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.println(time); + LCD_MESSAGE(time); + checkautostart(true); + } + if(!serial_count) 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 + +} + + +inline float code_value() { + return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); +} +inline long code_value_long() { + return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); +} +inline bool code_seen(char code_string[]) { + return (strstr(cmdbuffer[bufindr], code_string) != NULL); +} //Return True if the string was found + +inline bool code_seen(char code) +{ + strchr_pointer = strchr(cmdbuffer[bufindr], code); + return (strchr_pointer != NULL); //Return True if a character was found +} + +inline 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 + get_coordinates(); // For X Y Z E F + prepare_move(); + previous_millis_cmd = millis(); + //ClearToSend(); + return; + //break; + case 4: // G4 dwell + codenum = 0; + if(code_seen('P')) codenum = code_value(); // milliseconds to wait + if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait + codenum += millis(); // keep track of when we started waiting + while(millis() < codenum ){ + manage_heater(); + } + break; + case 28: //G28 Home all Axis one at a time + saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + + for(int 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((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { + if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ +// st_synchronize(); + current_position[X_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; + feedrate = homing_feedrate[X_AXIS]; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = -5 * X_HOME_DIR; + prepare_move(); + +// st_synchronize(); + destination[X_AXIS] = 10 * X_HOME_DIR; + feedrate = homing_feedrate[X_AXIS]/2 ; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = current_position[X_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { + if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ + 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[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]; + prepare_move(); +// st_synchronize(); + + 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[Y_AXIS] = -5 * Y_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Y_AXIS] = 10 * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Y_AXIS] = current_position[Y_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { + if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = -2 * Z_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Z_AXIS] = 3 * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = current_position[Z_AXIS]; + feedrate = 0.0; + } + } + feedrate = saved_feedrate; + feedmultiply = saved_feedmultiply; + previous_millis_cmd = millis(); + break; + case 90: // G90 + relative_mode = false; + break; + case 91: // G91 + relative_mode = true; + break; + case 92: // G92 + if(!code_seen(axis_codes[E_AXIS])) + st_synchronize(); + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) current_position[i] = code_value(); + } + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + break; + } + } + + else if(code_seen('M')) + { + + switch( (int)code_value() ) + { +#ifdef SDSUPPORT + + case 20: // M20 - list SD card + Serial.println("Begin file list"); + root.ls(); + Serial.println("End file list"); + break; + case 21: // M21 - init SD card + sdmode = false; + initsd(); + break; + case 22: //M22 - release SD card + sdmode = false; + sdactive = false; + break; + case 23: //M23 - Select file + if(sdactive){ + sdmode = false; + file.close(); + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos!=NULL) + *(starpos-1)='\0'; + if (file.open(&root, strchr_pointer + 4, O_READ)) { + Serial.print("File opened:"); + Serial.print(strchr_pointer + 4); + Serial.print(" Size:"); + Serial.println(file.fileSize()); + sdpos = 0; + filesize = file.fileSize(); + Serial.println("File selected"); + } + else{ + Serial.println("file.open failed"); + } + } + break; + case 24: //M24 - Start SD print + if(sdactive){ + sdmode = true; + starttime=millis(); + } + break; + case 25: //M25 - Pause SD print + if(sdmode){ + sdmode = false; + } + break; + case 26: //M26 - Set SD index + if(sdactive && code_seen('S')){ + sdpos = code_value_long(); + file.seekSet(sdpos); + } + break; + case 27: //M27 - Get SD status + if(sdactive){ + Serial.print("SD printing byte "); + Serial.print(sdpos); + Serial.print("/"); + Serial.println(filesize); + } + else{ + Serial.println("Not SD printing"); + } + break; + case 28: //M28 - Start SD write + if(sdactive){ + char* npos = 0; + file.close(); + sdmode = false; + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos != NULL){ + npos = strchr(cmdbuffer[bufindr], 'N'); + strchr_pointer = strchr(npos,' ') + 1; + *(starpos-1) = '\0'; + } + if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + Serial.print("open failed, File: "); + Serial.print(strchr_pointer + 4); + Serial.print("."); + } + else{ + savetosd = true; + Serial.print("Writing to file: "); + Serial.println(strchr_pointer + 4); + } + } + break; + case 29: //M29 - Stop SD write + //processed in write to file routine above + //savetosd = false; + break; + case 30: + { + 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.println(time); + LCD_MESSAGE(time); + } + break; +#endif //SDSUPPORT + 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(int i = 0; i < (int)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 (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); +#ifdef PIDTEMP + pid_setpoint = code_value(); +#endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + }else{ + watchmillis = 0; + } + #endif + break; + case 140: // M140 set bed temp + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); + break; + case 105: // M105 + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + tt = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + #endif + #if TEMP_1_PIN > -1 + bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); + #endif + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + Serial.print("ok T:"); + Serial.print(tt); +// Serial.print(", raw:"); +// Serial.print(current_raw); + #if TEMP_1_PIN > -1 +#ifdef PIDTEMP + Serial.print(" B:"); + #if TEMP_1_PIN > -1 + Serial.println(bt); + #else + Serial.println(HeaterPower); + #endif +#else + Serial.println(); +#endif + #else + Serial.println(); + #endif + #else + Serial.println("No thermistors - no temp"); + #endif + return; + //break; + case 109: {// M109 - Wait for extruder heater to reach target. + LCD_MESSAGE("Heating..."); + if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); + #ifdef PIDTEMP + pid_setpoint = code_value(); + #endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND_0]>current_raw[TEMPSENSOR_HOTEND_0]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + } else { + watchmillis = 0; + } + #endif //WATCHPERIOD + codenum = millis(); + + /* See if we are heating up or cooling down */ + bool target_direction = (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]); // 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((target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0])) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + #else + while ( target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0]) ) { + #endif //TEMP_RESIDENCY_TIME + if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down + Serial.print("T:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) ); + codenum = millis(); + } + manage_heater(); + 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 && current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) || + (residencyStart == -1 && !target_direction && current_raw[TEMPSENSOR_HOTEND_0] <= target_raw[TEMPSENSOR_HOTEND_0]) || + (residencyStart > -1 && labs(analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) - analog2temp(target_raw[TEMPSENSOR_HOTEND_0])) > TEMP_HYSTERESIS) ) { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGE("Marlin ready."); + } + break; + case 190: // M190 - Wait bed for heater to reach target. + #if TEMP_1_PIN > -1 + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); + codenum = millis(); + while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) + { + if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + { + float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + Serial.print("T:"); + Serial.println( tt ); + Serial.print("ok T:"); + Serial.print( tt ); + Serial.print(" B:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); + codenum = millis(); + } + manage_heater(); + } + #endif + break; +#if FAN_PIN > -1 + case 106: //M106 Fan On + if (code_seen('S')){ + WRITE(FAN_PIN,HIGH); + fanpwm=constrain(code_value(),0,255); + analogWrite(FAN_PIN, fanpwm); + } + else { + WRITE(FAN_PIN,HIGH); + fanpwm=255; + analogWrite(FAN_PIN, fanpwm); + } + break; + case 107: //M107 Fan Off + WRITE(FAN_PIN,LOW); + analogWrite(FAN_PIN, 0); + break; +#endif +#if (PS_ON_PIN > -1) + case 80: // M80 - ATX Power On + SET_OUTPUT(PS_ON_PIN); //GND + break; + case 81: // M81 - ATX Power Off + SET_INPUT(PS_ON_PIN); //Floating + break; +#endif + case 82: + axis_relative_modes[3] = false; + break; + case 83: + axis_relative_modes[3] = true; + break; + case 18: + case 84: + if(code_seen('S')){ + stepper_inactive_time = code_value() * 1000; + } + else{ + st_synchronize(); + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + break; + case 85: // M85 + code_seen('S'); + max_inactive_time = code_value() * 1000; + break; + case 92: // M92 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); + } + + break; + case 115: // M115 + Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); + break; + case 114: // M114 + Serial.print("X:"); + Serial.print(current_position[X_AXIS]); + Serial.print("Y:"); + Serial.print(current_position[Y_AXIS]); + Serial.print("Z:"); + Serial.print(current_position[Z_AXIS]); + Serial.print("E:"); + Serial.print(current_position[E_AXIS]); + #ifdef DEBUG_STEPS + Serial.print(" Count X:"); + Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); + Serial.print("Y:"); + Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); + Serial.print("Z:"); + Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); + #endif + Serial.println(""); + break; + case 119: // M119 +#if (X_MIN_PIN > -1) + Serial.print("x_min:"); + Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (X_MAX_PIN > -1) + Serial.print("x_max:"); + Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MIN_PIN > -1) + Serial.print("y_min:"); + Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MAX_PIN > -1) + Serial.print("y_max:"); + Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MIN_PIN > -1) + Serial.print("z_min:"); + Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MAX_PIN > -1) + Serial.print("z_max:"); + Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif + Serial.println(""); + break; + //TODO: update for all axis, use for loop + case 201: // M201 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) 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(int 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(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; + } + 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()*60 ; + if(code_seen('T')) mintravelfeedrate = code_value()*60 ; + if(code_seen('B')) minsegmenttime = code_value() ; + if(code_seen('X')) max_xy_jerk = code_value()*60 ; + if(code_seen('Z')) max_z_jerk = code_value()*60 ; + } + break; + case 220: // M220 S- set speed factor override percentage + { + if(code_seen('S')) + { + feedmultiply = code_value() ; + feedmultiplychanged=true; + } + } + 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; +// ECHOLN("Kp "<<_FLOAT(Kp,2)); +// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); +// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); + +// temp_iState_min = 0.0; +// if (Ki!=0) { +// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); +// } +// else temp_iState_max = 1.0e10; + break; +#endif //PIDTEMP + case 500: // Store settings in EEPROM + { + StoreSettings(); + } + break; + case 501: // Read settings from EEPROM + { + RetrieveSettings(); + } + break; + case 502: // Revert to default settings + { + RetrieveSettings(true); + } + break; + + } + } + else{ + Serial.println("Unknown command:"); + Serial.println(cmdbuffer[bufindr]); + } + + ClearToSend(); +} + +void FlushSerialRequestResend() +{ + //char cmdbuffer[bufindr][100]="Resend:"; + Serial.flush(); + Serial.print("Resend:"); + Serial.println(gcode_LastN + 1); + ClearToSend(); +} + +void ClearToSend() +{ + previous_millis_cmd = millis(); +#ifdef SDSUPPORT + if(fromsd[bufindr]) + return; +#endif //SDSUPPORT + Serial.println("ok"); +} + +inline void get_coordinates() +{ + for(int 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]; + 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; + } +} + +void prepare_move() +{ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); + for(int i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; + } +} + + + +#ifdef USE_WATCHDOG + +#include +#include + +volatile uint8_t timeout_seconds=0; + +void(* ctrlaltdelete) (void) = 0; + +ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec + if(timeout_seconds++ >= WATCHDOG_TIMEOUT) + { + kill(); +#ifdef RESET_MANUAL + LCD_MESSAGE("Please Reset!"); + ECHOLN("echo_: Something is wrong, please turn off the printer."); +#else + LCD_MESSAGE("Timeout, resetting!"); +#endif + //disable watchdog, it will survife reboot. + WDTCSR |= (1< -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif + disable_x(); + disable_y(); + disable_z(); + disable_e(); + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + Serial.println("!! Printer halted. kill() called!!"); + while(1); // Wait for reset +} + +void manage_inactivity(byte debug) { + if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); + if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + check_axes_activity(); +} diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 430e87f5c2..b55573d93c 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -1,501 +1,503 @@ -/* - temperature.c - temperature control - Part of Marlin - - 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 - - This firmware is optimized for gen6 electronics. - */ - -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "streaming.h" -#include "temperature.h" - -int target_bed_raw = 0; -int current_bed_raw = 0; - -int target_raw[3] = {0, 0, 0}; -int current_raw[3] = {0, 0, 0}; -unsigned char temp_meas_ready = false; - -unsigned long previous_millis_heater, previous_millis_bed_heater; - -#ifdef PIDTEMP - double temp_iState = 0; - double temp_dState = 0; - double pTerm; - double iTerm; - double dTerm; - //int output; - double pid_error; - double temp_iState_min; - double temp_iState_max; - double pid_setpoint = 0.0; - double pid_input; - double pid_output; - bool pid_reset; - float HeaterPower; - - float Kp=DEFAULT_Kp; - float Ki=DEFAULT_Ki; - float Kd=DEFAULT_Kd; - float Kc=DEFAULT_Kc; -#endif //PIDTEMP - -#ifdef HEATER_0_MINTEMP -int minttemp_0 = temp2analog(HEATER_0_MINTEMP); -#endif //MINTEMP -#ifdef HEATER_0_MAXTEMP -int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); -#endif //MAXTEMP - -#ifdef HEATER_1_MINTEMP -int minttemp_1 = temp2analog(HEATER_1_MINTEMP); -#endif //MINTEMP -#ifdef HEATER_1_MAXTEMP -int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); -#endif //MAXTEMP - -#ifdef BED_MINTEMP -int bed_minttemp = temp2analog(BED_MINTEMP); -#endif //BED_MINTEMP -#ifdef BED_MAXTEMP -int bed_maxttemp = temp2analog(BED_MAXTEMP); -#endif //BED_MAXTEMP - -void manage_heater() -{ -#ifdef USE_WATCHDOG - wd_reset(); -#endif - - float pid_input; - float pid_output; - if(temp_meas_ready != true) //better readability - return; - -CRITICAL_SECTION_START; - temp_meas_ready = false; -CRITICAL_SECTION_END; - -#ifdef PIDTEMP - pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND]); - -#ifndef PID_OPENLOOP - pid_error = pid_setpoint - pid_input; - if(pid_error > 10){ - pid_output = PID_MAX; - pid_reset = true; - } - else if(pid_error < -10) { - pid_output = 0; - pid_reset = true; - } - else { - if(pid_reset == true) { - temp_iState = 0.0; - pid_reset = false; - } - pTerm = Kp * pid_error; - temp_iState += pid_error; - temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); - iTerm = Ki * temp_iState; - //K1 defined in Configuration.h in the PID settings - #define K2 (1.0-K1) - dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); - temp_dState = pid_input; - #ifdef PID_ADD_EXTRUSION_RATE - pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high - #endif - pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); - } -#endif //PID_OPENLOOP -#ifdef PID_DEBUG - Serial.print(" Input "); - Serial.print(pid_input); - Serial.print(" Output "); - Serial.print(pid_output); - Serial.print(" pTerm "); - Serial.print(pTerm); - Serial.print(" iTerm "); - Serial.print(iTerm); - Serial.print(" dTerm "); - Serial.print(dTerm); - Serial.println(); -#endif //PID_DEBUG - analogWrite(HEATER_0_PIN, pid_output); -#endif //PIDTEMP - -#ifndef PIDTEMP - if(current_raw[0] >= target_raw[0]) - { - WRITE(HEATER_0_PIN,LOW); - } - else - { - WRITE(HEATER_0_PIN,HIGH); - } -#endif - - if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) - return; - previous_millis_bed_heater = millis(); - - #if TEMP_1_PIN > -1 - if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) - { - WRITE(HEATER_1_PIN,LOW); - } - else - { - WRITE(HEATER_1_PIN,HIGH); - } - #endif - } - -// Takes hot end temperature value as input and returns corresponding raw value. -// For a thermistor, it uses the RepRap thermistor temp table. -// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. -// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -int temp2analog(int celsius) { - #ifdef HEATER_0_USES_THERMISTOR - int raw = 0; - byte i; - - for (i=1; i raw) - { - celsius = heater_0_temptable[i-1][1] + - (raw - heater_0_temptable[i-1][0]) * - (float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) / - (float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1]; - - return celsius; - #elif defined HEATER_0_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -// Derived from RepRap FiveD extruder::getTemperature() -// For bed temperature measurement. -float analog2tempBed(int raw) { - #ifdef BED_USES_THERMISTOR - int celsius = 0; - byte i; - - raw = (1023 * OVERSAMPLENR) - raw; - - for (i=1; i raw) - { - celsius = bedtemptable[i-1][1] + - (raw - bedtemptable[i-1][0]) * - (bedtemptable[i][1] - bedtemptable[i-1][1]) / - (bedtemptable[i][0] - bedtemptable[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; - - return celsius; - - #elif defined BED_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -void tp_init() -{ -#if (HEATER_0_PIN > -1) - SET_OUTPUT(HEATER_0_PIN); -#endif -#if (HEATER_1_PIN > -1) - SET_OUTPUT(HEATER_1_PIN); -#endif -#if (HEATER_2_PIN > -1) - SET_OUTPUT(HEATER_2_PIN); -#endif - -#ifdef PIDTEMP - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; -#endif //PIDTEMP - -// Set analog inputs - ADCSRA = 1< -1) - #if TEMP_0_PIN < 8 - DIDR0 = 1 << TEMP_0_PIN; - #else - DIDR2 = 1<<(TEMP_0_PIN - 8); - ADCSRB = 1< -1) - raw_temp_0_value += ADC; - #endif - temp_state = 2; - break; - case 2: // Prepare TEMP_1 - #if (TEMP_1_PIN > -1) - #if TEMP_1_PIN < 7 - DIDR0 = 1< -1) - raw_temp_1_value += ADC; - #endif - temp_state = 4; - break; - case 4: // Prepare TEMP_2 - #if (TEMP_2_PIN > -1) - #if TEMP_2_PIN < 7 - DIDR0 = 1 << TEMP_2_PIN; - #else - DIDR2 = 1<<(TEMP_2_PIN - 8); - ADCSRB = 1< -1) - raw_temp_2_value += ADC; - #endif - temp_state = 0; - temp_count++; - break; - default: - Serial.println("!! Temp measurement error !!"); - break; - } - - if(temp_count >= 16) // 6 ms * 16 = 96ms. - { - #ifdef HEATER_0_USES_AD595 - current_raw[0] = raw_temp_0_value; - #else - current_raw[0] = 16383 - raw_temp_0_value; - #endif - - #ifdef HEATER_1_USES_AD595 - current_raw[2] = raw_temp_2_value; - #else - current_raw[2] = 16383 - raw_temp_2_value; - #endif - - #ifdef BED_USES_AD595 - current_raw[1] = raw_temp_1_value; - #else - current_raw[1] = 16383 - raw_temp_1_value; - #endif - - temp_meas_ready = true; - temp_count = 0; - raw_temp_0_value = 0; - raw_temp_1_value = 0; - raw_temp_2_value = 0; -#ifdef HEATER_0_MAXTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND] >= maxttemp) { - target_raw[TEMPSENSOR_HOTEND] = 0; - analogWrite(HEATER_0_PIN, 0); - Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); - kill(); - } - #endif -#endif - if(current_raw[TEMPSENSOR_AUX] >= maxttemp) { - target_raw[TEMPSENSOR_AUX] = 0; - if(current_raw[2] >= maxttemp_1) { - analogWrite(HEATER_2_PIN, 0); - Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); - kill() - } - #endif -#endif //MAXTEMP -#ifdef HEATER_0_MINTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND] <= minttemp) { - target_raw[TEMPSENSOR_HOTEND] = 0; - analogWrite(HEATER_0_PIN, 0); - Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); - kill(); - } - #endif -#endif -#ifdef HEATER_1_MINTEMP - #if (HEATER_2_PIN > -1) - if(current_raw[TEMPSENSOR_AUX] <= minttemp) { - target_raw[TEMPSENSOR_AUX] = 0; - analogWrite(HEATER_2_PIN, 0); - Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); - kill(); - } - #endif -#endif //MAXTEMP -#ifdef BED_MINTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] <= bed_minttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); - kill(); - } - #endif -#endif -#ifdef BED_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] >= bed_maxttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); - kill(); - } - #endif -#endif - } -} +/* + temperature.c - temperature control + Part of Marlin + + 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 + + This firmware is optimized for gen6 electronics. + */ + +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "temperature.h" + +int target_bed_raw = 0; +int current_bed_raw = 0; + +int target_raw[3] = {0, 0, 0}; +int current_raw[3] = {0, 0, 0}; +unsigned char temp_meas_ready = false; + +unsigned long previous_millis_heater, previous_millis_bed_heater; + +#ifdef PIDTEMP + double temp_iState = 0; + double temp_dState = 0; + double pTerm; + double iTerm; + double dTerm; + //int output; + double pid_error; + double temp_iState_min; + double temp_iState_max; + double pid_setpoint = 0.0; + double pid_input; + double pid_output; + bool pid_reset; + float HeaterPower; + + float Kp=DEFAULT_Kp; + float Ki=DEFAULT_Ki; + float Kd=DEFAULT_Kd; + float Kc=DEFAULT_Kc; +#endif //PIDTEMP + +#ifdef HEATER_0_MINTEMP +int minttemp_0 = temp2analog(HEATER_0_MINTEMP); +#endif //MINTEMP +#ifdef HEATER_0_MAXTEMP +int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); +#endif //MAXTEMP + +#ifdef HEATER_1_MINTEMP +int minttemp_1 = temp2analog(HEATER_1_MINTEMP); +#endif //MINTEMP +#ifdef HEATER_1_MAXTEMP +int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); +#endif //MAXTEMP + +#ifdef BED_MINTEMP +int bed_minttemp = temp2analog(BED_MINTEMP); +#endif //BED_MINTEMP +#ifdef BED_MAXTEMP +int bed_maxttemp = temp2analog(BED_MAXTEMP); +#endif //BED_MAXTEMP + +void manage_heater() +{ +#ifdef USE_WATCHDOG + wd_reset(); +#endif + + float pid_input; + float pid_output; + if(temp_meas_ready != true) //better readability + return; + +CRITICAL_SECTION_START; + temp_meas_ready = false; +CRITICAL_SECTION_END; + +#ifdef PIDTEMP + pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + +#ifndef PID_OPENLOOP + pid_error = pid_setpoint - pid_input; + if(pid_error > 10){ + pid_output = PID_MAX; + pid_reset = true; + } + else if(pid_error < -10) { + pid_output = 0; + pid_reset = true; + } + else { + if(pid_reset == true) { + temp_iState = 0.0; + pid_reset = false; + } + pTerm = Kp * pid_error; + temp_iState += pid_error; + temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); + iTerm = Ki * temp_iState; + //K1 defined in Configuration.h in the PID settings + #define K2 (1.0-K1) + dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); + temp_dState = pid_input; + #ifdef PID_ADD_EXTRUSION_RATE + pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high + #endif + pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); + } +#endif //PID_OPENLOOP +#ifdef PID_DEBUG + Serial.print(" Input "); + Serial.print(pid_input); + Serial.print(" Output "); + Serial.print(pid_output); + Serial.print(" pTerm "); + Serial.print(pTerm); + Serial.print(" iTerm "); + Serial.print(iTerm); + Serial.print(" dTerm "); + Serial.print(dTerm); + Serial.println(); +#endif //PID_DEBUG + analogWrite(HEATER_0_PIN, pid_output); +#endif //PIDTEMP + +#ifndef PIDTEMP + if(current_raw[0] >= target_raw[0]) + { + WRITE(HEATER_0_PIN,LOW); + } + else + { + WRITE(HEATER_0_PIN,HIGH); + } +#endif + + if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) + return; + previous_millis_bed_heater = millis(); + + #if TEMP_1_PIN > -1 + if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) + { + WRITE(HEATER_1_PIN,LOW); + } + else + { + WRITE(HEATER_1_PIN,HIGH); + } + #endif + } + +// Takes hot end temperature value as input and returns corresponding raw value. +// For a thermistor, it uses the RepRap thermistor temp table. +// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. +// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. +int temp2analog(int celsius) { + #ifdef HEATER_0_USES_THERMISTOR + int raw = 0; + byte i; + + for (i=1; i raw) + { + celsius = heater_0_temptable[i-1][1] + + (raw - heater_0_temptable[i-1][0]) * + (float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) / + (float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1]; + + return celsius; + #elif defined HEATER_0_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +// Derived from RepRap FiveD extruder::getTemperature() +// For bed temperature measurement. +float analog2tempBed(int raw) { + #ifdef BED_USES_THERMISTOR + int celsius = 0; + byte i; + + raw = (1023 * OVERSAMPLENR) - raw; + + for (i=1; i raw) + { + celsius = bedtemptable[i-1][1] + + (raw - bedtemptable[i-1][0]) * + (bedtemptable[i][1] - bedtemptable[i-1][1]) / + (bedtemptable[i][0] - bedtemptable[i-1][0]); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; + + return celsius; + + #elif defined BED_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +void tp_init() +{ +#if (HEATER_0_PIN > -1) + SET_OUTPUT(HEATER_0_PIN); +#endif +#if (HEATER_1_PIN > -1) + SET_OUTPUT(HEATER_1_PIN); +#endif +#if (HEATER_2_PIN > -1) + SET_OUTPUT(HEATER_2_PIN); +#endif + +#ifdef PIDTEMP + temp_iState_min = 0.0; + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; +#endif //PIDTEMP + +// Set analog inputs + ADCSRA = 1< -1) + #if TEMP_0_PIN < 8 + DIDR0 = 1 << TEMP_0_PIN; + #else + DIDR2 = 1<<(TEMP_0_PIN - 8); + ADCSRB = 1< -1) + raw_temp_0_value += ADC; + #endif + temp_state = 2; + break; + case 2: // Prepare TEMP_1 + #if (TEMP_1_PIN > -1) + #if TEMP_1_PIN < 7 + DIDR0 = 1< -1) + raw_temp_1_value += ADC; + #endif + temp_state = 4; + break; + case 4: // Prepare TEMP_2 + #if (TEMP_2_PIN > -1) + #if TEMP_2_PIN < 7 + DIDR0 = 1 << TEMP_2_PIN; + #else + DIDR2 = 1<<(TEMP_2_PIN - 8); + ADCSRB = 1< -1) + raw_temp_2_value += ADC; + #endif + temp_state = 0; + temp_count++; + break; + default: + Serial.println("!! Temp measurement error !!"); + break; + } + + if(temp_count >= 16) // 6 ms * 16 = 96ms. + { + #ifdef HEATER_0_USES_AD595 + current_raw[0] = raw_temp_0_value; + #else + current_raw[0] = 16383 - raw_temp_0_value; + #endif + + #ifdef HEATER_1_USES_AD595 + current_raw[2] = raw_temp_2_value; + #else + current_raw[2] = 16383 - raw_temp_2_value; + #endif + + #ifdef BED_USES_AD595 + current_raw[1] = raw_temp_1_value; + #else + current_raw[1] = 16383 - raw_temp_1_value; + #endif + + temp_meas_ready = true; + temp_count = 0; + raw_temp_0_value = 0; + raw_temp_1_value = 0; + raw_temp_2_value = 0; +#ifdef HEATER_0_MAXTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); + kill(); + } + #endif +#endif +#ifdef HEATER_1_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + if(current_raw[2] >= maxttemp_1) { + analogWrite(HEATER_2_PIN, 0); + Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); + kill() + } + #endif +#endif //MAXTEMP +#ifdef HEATER_0_MINTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); + kill(); + } + #endif +#endif +#ifdef HEATER_1_MINTEMP + #if (HEATER_2_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + analogWrite(HEATER_2_PIN, 0); + Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); + kill(); + } + #endif +#endif //MAXTEMP +#ifdef BED_MINTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] <= bed_minttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); + kill(); + } + #endif +#endif +#ifdef BED_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] >= bed_maxttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); + kill(); + } + #endif +#endif + } +} diff --git a/Marlin/temperature.h b/Marlin/temperature.h index b787979780..a36f997815 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -1,58 +1,58 @@ -/* - temperature.h - temperature controller - Part of Marlin - - Copyright (c) 2011 Erik van der Zalm - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -#ifndef temperature_h -#define temperature_h - -#include "Marlin.h" -#ifdef PID_ADD_EXTRUSION_RATE - #include "stepper.h" -#endif -void tp_init(); -void manage_heater(); -//int temp2analogu(int celsius, const short table[][2], int numtemps); -//float analog2tempu(int raw, const short table[][2], int numtemps); -int temp2analog(int celsius); -int temp2analogBed(int celsius); -float analog2temp(int raw); -float analog2tempBed(int raw); - -#ifdef HEATER_USES_THERMISTOR - #define HEATERSOURCE 1 -#endif -#ifdef BED_USES_THERMISTOR - #define BEDSOURCE 1 -#endif - -//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) -//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS - - -extern float Kp; -extern float Ki; -extern float Kd; -extern float Kc; - -enum {TEMPSENSOR_HOTEND=0,TEMPSENSOR_BED=1, TEMPSENSOR_AUX=2}; -extern int target_raw[3]; -extern int current_raw[3]; -extern double pid_setpoint; - -#endif +/* + temperature.h - temperature controller + Part of Marlin + + Copyright (c) 2011 Erik van der Zalm + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +#ifndef temperature_h +#define temperature_h + +#include "Marlin.h" +#ifdef PID_ADD_EXTRUSION_RATE + #include "stepper.h" +#endif +void tp_init(); +void manage_heater(); +//int temp2analogu(int celsius, const short table[][2], int numtemps); +//float analog2tempu(int raw, const short table[][2], int numtemps); +int temp2analog(int celsius); +int temp2analogBed(int celsius); +float analog2temp(int raw); +float analog2tempBed(int raw); + +#ifdef HEATER_0_USES_THERMISTOR + #define HEATERSOURCE 1 +#endif +#ifdef BED_USES_THERMISTOR + #define BEDSOURCE 1 +#endif + +//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) +//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS + + +extern float Kp; +extern float Ki; +extern float Kd; +extern float Kc; + +enum {TEMPSENSOR_HOTEND_0=0,TEMPSENSOR_BED=1, TEMPSENSOR_HOTEND_1=2}; +extern int target_raw[3]; +extern int current_raw[3]; +extern double pid_setpoint; + +#endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index a6c75e0fc2..7eefec6682 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -253,17 +253,17 @@ void MainMenu::showStatus() } - if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) + if((abs(current_raw[TEMPSENSOR_HOTEND_0]-oldcurrentraw)>3)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); - oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND_0]))); + oldcurrentraw=current_raw[TEMPSENSOR_HOTEND_0]; } - if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + if((target_raw[TEMPSENSOR_HOTEND_0]!=oldtargetraw)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); - oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND_0]))); + oldtargetraw=target_raw[TEMPSENSOR_HOTEND_0]; } #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 static int oldcurrentbedraw=-1; @@ -426,7 +426,7 @@ void MainMenu::showPrepare() if((activeline==line) && CLICKED) { BLOCK - target_raw[TEMPSENSOR_HOTEND] = temp2analog(170); + target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(170); beepshort(); } }break; @@ -531,7 +531,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" \002Nozzle:"); - lcd.setCursor(13,line);lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + lcd.setCursor(13,line);lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND_0]))); } if((activeline==line) ) @@ -541,11 +541,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)analog2temp(target_raw[TEMPSENSOR_HOTEND]); + encoderpos=(int)analog2temp(target_raw[TEMPSENSOR_HOTEND_0]); } else { - target_raw[TEMPSENSOR_HOTEND] = temp2analog(encoderpos); + target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(encoderpos); encoderpos=activeline*lcdslow; beepshort(); } @@ -1590,4 +1590,4 @@ char *fillto(int8_t n,char *c) #else inline void lcd_status() {}; #endif - + From 0b82465168e53a16d573610bb30495d70bd050b8 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 6 Nov 2011 12:39:00 +0100 Subject: [PATCH 012/228] First arcs version. (Arcs not working ok) --- Marlin/Configuration.h | 493 +++---- Marlin/Marlin.pde | 2605 +++++++++++++++++++------------------ Marlin/motion_control.cpp | 133 ++ Marlin/motion_control.h | 32 + 4 files changed, 1784 insertions(+), 1479 deletions(-) create mode 100644 Marlin/motion_control.cpp create mode 100644 Marlin/motion_control.h diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index e2d5cb0778..65c4f32a3c 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,245 +1,248 @@ -#ifndef CONFIGURATION_H -#define CONFIGURATION_H - -//#define DEBUG_STEPS - -// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration - -//// The following define selects which electronics board you have. Please choose the one that matches your setup -// MEGA/RAMPS up to 1.2 = 3, -// RAMPS 1.3 = 33 -// Gen6 = 5, -// Sanguinololu 1.2 and above = 62 -// Ultimaker = 7, -#define MOTHERBOARD 7 -//#define MOTHERBOARD 5 - - -//// Thermistor settings: -// 1 is 100k thermistor -// 2 is 200k thermistor -// 3 is mendel-parts thermistor -// 4 is 10k thermistor -// 5 is ParCan supplied 104GT-2 100K -// 6 is EPCOS 100k -// 7 is 100k Honeywell thermistor 135-104LAG-J01 -#define THERMISTORHEATER_1 3 -#define THERMISTORHEATER_2 3 -#define THERMISTORBED 3 - -//#define HEATER_0_USES_THERMISTOR -//#define HEATER_1_USES_THERMISTOR -#define HEATER_0_USES_AD595 -//#define HEATER_1_USES_AD595 - -// Select one of these only to define how the bed temp is read. -//#define BED_USES_THERMISTOR -//#define BED_USES_AD595 - -#define HEATER_CHECK_INTERVAL 50 -#define BED_CHECK_INTERVAL 5000 - - -//// Endstop Settings -#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors -// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false - -// This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 -//#define BAUDRATE 230400 - -// Comment out (using // at the start of the line) to disable SD support: - -// #define ULTRA_LCD //any lcd - -#define ULTIPANEL -#define ULTIPANEL -#ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 -#define LCD_HEIGHT 4 -#else //no panel but just lcd - #ifdef ULTRA_LCD - #define LCD_WIDTH 16 - #define LCD_HEIGHT 2 - #endif -#endif - - -//#define SDSUPPORT // Enable SD Card Support in Hardware Console - - - -const int dropsegments=5; //everything with this number of steps will be ignored as move - -//// ADVANCED SETTINGS - to tweak parameters - -#include "thermistortables.h" - -// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 -#define X_ENABLE_ON 0 -#define Y_ENABLE_ON 0 -#define Z_ENABLE_ON 0 -#define E_ENABLE_ON 0 - -// Disables axis when it's not being used. -#define DISABLE_X false -#define DISABLE_Y false -#define DISABLE_Z false -#define DISABLE_E false - -// Inverting axis direction -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false - -//// ENDSTOP SETTINGS: -// Sets direction of endstops when homing; 1=MAX, -1=MIN -#define X_HOME_DIR -1 -#define Y_HOME_DIR -1 -#define Z_HOME_DIR -1 - -#define min_software_endstops false //If true, axis won't move to coordinates less than zero. -#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 210 -#define Y_MAX_LENGTH 210 -#define Z_MAX_LENGTH 210 - -//// MOVEMENT SETTINGS -#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -//note: on bernhards ultimaker 200 200 12 are working well. -#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds -//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. -//!!!!!!Use only if you know that your printer works at the maximum declared speeds. -// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze -#define TRAVELING_AT_MAXSPEED -#define AXIS_RELATIVE_MODES {false, false, false, false} - -#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) - -// default settings - -#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker -#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} -#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. - -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts - -#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 10 - -// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. -#define DEFAULT_MINSEGMENTTIME 20000 -#define DEFAULT_XYJERK 30.0*60 -#define DEFAULT_ZJERK 10.0*60 - - -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -//this enables the watchdog interrupt. -#define 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: -#define RESET_MANUAL - -#define WATCHDOG_TIMEOUT 4 - - - -//// Experimental watchdog and minimal temp -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 -//#define WATCHPERIOD 5000 //5 seconds - -// Actual temperature must be close to target for this long before M109 returns success -//#define TEMP_RESIDENCY_TIME 20 // (seconds) -//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one - -//// The minimal temperature defines the temperature below which the heater will not be enabled -#define HEATER_0_MINTEMP 5 -//#define HEATER_1_MINTEMP 5 -//#define BED_MINTEMP 5 - - -// When temperature exceeds max temp, your heater will be switched off. -// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! -// You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 275 -//#define_HEATER_1_MAXTEMP 275 -//#define BED_MAXTEMP 150 - - - - - - - -#define PIDTEMP -#ifdef PIDTEMP - /// PID settings: - // Uncomment the following line to enable PID support. - //#define SMOOTHING - //#define SMOOTHFACTOR 5.0 - //float current_raw_average=0; - #define K1 0.95 //smoothing of the PID - //#define PID_DEBUG // Sends debug data to the serial port. - //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_MAX 255 // limits current to nozzle - #define PID_INTEGRAL_DRIVE_MAX 255 - #define PID_dT 0.1 - //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 - - #define PID_CRITIAL_GAIN 3000 - #define PID_SWING_AT_CRITIAL 45 //seconds - #define PIDIADD 5 - /* - //PID according to Ziegler-Nichols method - float Kp = 0.6*PID_CRITIAL_GAIN; - float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; - float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; - */ - //PI according to Ziegler-Nichols method - #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) - #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (0) - - #define PID_ADD_EXTRUSION_RATE - #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) - #endif -#endif // PIDTEMP - -// extruder advance constant (s2/mm3) -// -// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 -// -// hooke's law says: force = k * distance -// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant -// so: v ^ 2 is proportional to number of steps we advance the extruder -//#define ADVANCE - -#ifdef ADVANCE -#define EXTRUDER_ADVANCE_K .3 - -#define D_FILAMENT 1.7 -#define STEPS_MM_E 65 -#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) -#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) - -#endif // ADVANCE - -// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 -#if defined SDSUPPORT -// The number of linear motions that can be in the plan at any give time. - #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller -#else - #define BLOCK_BUFFER_SIZE 16 // maximize block buffer -#endif - - -#endif +#ifndef CONFIGURATION_H +#define CONFIGURATION_H + +//#define DEBUG_STEPS + +#define MM_PER_ARC_SEGMENT 1 +#define N_ARC_CORRECTION 25 + +// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration + +//// The following define selects which electronics board you have. Please choose the one that matches your setup +// MEGA/RAMPS up to 1.2 = 3, +// RAMPS 1.3 = 33 +// Gen6 = 5, +// Sanguinololu 1.2 and above = 62 +// Ultimaker = 7, +#define MOTHERBOARD 7 +//#define MOTHERBOARD 5 + + +//// Thermistor settings: +// 1 is 100k thermistor +// 2 is 200k thermistor +// 3 is mendel-parts thermistor +// 4 is 10k thermistor +// 5 is ParCan supplied 104GT-2 100K +// 6 is EPCOS 100k +// 7 is 100k Honeywell thermistor 135-104LAG-J01 +#define THERMISTORHEATER_1 3 +#define THERMISTORHEATER_2 3 +#define THERMISTORBED 3 + +//#define HEATER_0_USES_THERMISTOR +//#define HEATER_1_USES_THERMISTOR +#define HEATER_0_USES_AD595 +//#define HEATER_1_USES_AD595 + +// Select one of these only to define how the bed temp is read. +//#define BED_USES_THERMISTOR +//#define BED_USES_AD595 + +#define HEATER_CHECK_INTERVAL 50 +#define BED_CHECK_INTERVAL 5000 + + +//// Endstop Settings +#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors +// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. +const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false + +// This determines the communication speed of the printer +#define BAUDRATE 250000 +//#define BAUDRATE 115200 +//#define BAUDRATE 230400 + +// Comment out (using // at the start of the line) to disable SD support: + +// #define ULTRA_LCD //any lcd + +#define ULTIPANEL +#define ULTIPANEL +#ifdef ULTIPANEL + //#define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 +#define LCD_HEIGHT 4 +#else //no panel but just lcd + #ifdef ULTRA_LCD + #define LCD_WIDTH 16 + #define LCD_HEIGHT 2 + #endif +#endif + + +//#define SDSUPPORT // Enable SD Card Support in Hardware Console + + + +const int dropsegments=5; //everything with this number of steps will be ignored as move + +//// ADVANCED SETTINGS - to tweak parameters + +#include "thermistortables.h" + +// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 +#define X_ENABLE_ON 0 +#define Y_ENABLE_ON 0 +#define Z_ENABLE_ON 0 +#define E_ENABLE_ON 0 + +// Disables axis when it's not being used. +#define DISABLE_X false +#define DISABLE_Y false +#define DISABLE_Z false +#define DISABLE_E false + +// Inverting axis direction +#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false +#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false + +//// ENDSTOP SETTINGS: +// Sets direction of endstops when homing; 1=MAX, -1=MIN +#define X_HOME_DIR -1 +#define Y_HOME_DIR -1 +#define Z_HOME_DIR -1 + +#define min_software_endstops false //If true, axis won't move to coordinates less than zero. +#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. +#define X_MAX_LENGTH 210 +#define Y_MAX_LENGTH 210 +#define Z_MAX_LENGTH 210 + +//// MOVEMENT SETTINGS +#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E +//note: on bernhards ultimaker 200 200 12 are working well. +#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds +//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. +//!!!!!!Use only if you know that your printer works at the maximum declared speeds. +// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze +#define TRAVELING_AT_MAXSPEED +#define AXIS_RELATIVE_MODES {false, false, false, false} + +#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker +#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} +#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts + +#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 10 + +// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. +#define DEFAULT_MINSEGMENTTIME 20000 +#define DEFAULT_XYJERK 30.0*60 +#define DEFAULT_ZJERK 10.0*60 + + +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +//this enables the watchdog interrupt. +#define 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: +#define RESET_MANUAL + +#define WATCHDOG_TIMEOUT 4 + + + +//// Experimental watchdog and minimal temp +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 +//#define WATCHPERIOD 5000 //5 seconds + +// Actual temperature must be close to target for this long before M109 returns success +//#define TEMP_RESIDENCY_TIME 20 // (seconds) +//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one + +//// The minimal temperature defines the temperature below which the heater will not be enabled +#define HEATER_0_MINTEMP 5 +//#define HEATER_1_MINTEMP 5 +//#define BED_MINTEMP 5 + + +// When temperature exceeds max temp, your heater will be switched off. +// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! +// You should use MINTEMP for thermistor short/failure protection. +#define HEATER_0_MAXTEMP 275 +//#define_HEATER_1_MAXTEMP 275 +//#define BED_MAXTEMP 150 + + + + + + + +#define PIDTEMP +#ifdef PIDTEMP + /// PID settings: + // Uncomment the following line to enable PID support. + //#define SMOOTHING + //#define SMOOTHFACTOR 5.0 + //float current_raw_average=0; + #define K1 0.95 //smoothing of the PID + //#define PID_DEBUG // Sends debug data to the serial port. + //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % + #define PID_MAX 255 // limits current to nozzle + #define PID_INTEGRAL_DRIVE_MAX 255 + #define PID_dT 0.1 + //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 + + #define PID_CRITIAL_GAIN 3000 + #define PID_SWING_AT_CRITIAL 45 //seconds + #define PIDIADD 5 + /* + //PID according to Ziegler-Nichols method + float Kp = 0.6*PID_CRITIAL_GAIN; + float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; + float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; + */ + //PI according to Ziegler-Nichols method + #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) + #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (0) + + #define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) + #endif +#endif // PIDTEMP + +// extruder advance constant (s2/mm3) +// +// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 +// +// hooke's law says: force = k * distance +// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant +// so: v ^ 2 is proportional to number of steps we advance the extruder +//#define ADVANCE + +#ifdef ADVANCE +#define EXTRUDER_ADVANCE_K .3 + +#define D_FILAMENT 1.7 +#define STEPS_MM_E 65 +#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) +#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) + +#endif // ADVANCE + +// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 +#if defined SDSUPPORT +// The number of linear motions that can be in the plan at any give time. + #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller +#else + #define BLOCK_BUFFER_SIZE 16 // maximize block buffer +#endif + + +#endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 7615cccf82..92907a2d24 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1,1235 +1,1372 @@ -/* - 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 . - */ +/* + 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 "EEPROMwrite.h" +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" +#include "motion_control.h" + +#ifdef SIMPLE_LCD + #include "Simplelcd.h" +#endif + +char version_string[] = "1.0.0 Alpha 1"; + +#ifdef SDSUPPORT +#include "SdFat.h" +#endif //SDSUPPORT + + +// 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 +// G28 - Home all Axis +// G90 - Use Absolute Coordinates +// G91 - Use Relative Coordinates +// G92 - Set current position to cordinates given + +//RepRap M Codes +// 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 +// 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 +// 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 +// M115 - Capabilities string +// 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 +// M220 - set speed factor override percentage S:factor in percent +// M301 - Set PID parameters P I and D +// M500 - stores paramters in EEPROM +// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D +// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. + +//Stepper Movement Variables + +char axis_codes[NUM_AXIS] = { + 'X', 'Y', 'Z', 'E'}; +float destination[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +float current_position[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +float offset[3] = {0.0, 0.0, 0.0}; +bool home_all_axis = true; +float feedrate = 1500.0, next_feedrate, saved_feedrate; +long gcode_N, gcode_LastN; + +float homing_feedrate[] = HOMING_FEEDRATE; +bool axis_relative_modes[] = AXIS_RELATIVE_MODES; + +bool relative_mode = false; //Determines Absolute or Relative Coordinates +bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. + +uint8_t fanpwm=0; + +volatile int feedmultiply=100; //100->1 200->2 +int saved_feedmultiply; +volatile bool feedmultiplychanged=false; +// comm variables +#define MAX_CMD_SIZE 96 +#define BUFSIZE 4 +char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; +bool fromsd[BUFSIZE]; +int bufindr = 0; +int bufindw = 0; +int buflen = 0; +int i = 0; +char serial_char; +int serial_count = 0; +boolean comment_mode = false; +char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc +extern float HeaterPower; + +#include "EEPROM.h" + +const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 + +float tt = 0, bt = 0; +#ifdef WATCHPERIOD +int watch_raw = -1000; +unsigned long watchmillis = 0; +#endif //WATCHPERIOD + +//Inactivity shutdown variables +unsigned long previous_millis_cmd = 0; +unsigned long max_inactive_time = 0; +unsigned long stepper_inactive_time = 0; + +unsigned long starttime=0; +unsigned long stoptime=0; +#ifdef SDSUPPORT +Sd2Card card; +SdVolume volume; +SdFile root; +SdFile file; +uint32_t filesize = 0; +uint32_t sdpos = 0; +bool sdmode = false; +bool sdactive = false; +bool savetosd = false; +int16_t n; +unsigned long autostart_atmillis=0; + +void initsd(){ + sdactive = false; +#if SDSS >- 1 + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)){ + //if (!card.init(SPI_HALF_SPEED,SDSS)) + Serial.println("SD init fail"); + } + else if (!volume.init(&card)) + Serial.println("volume.init failed"); + else if (!root.openRoot(&volume)) + Serial.println("openRoot failed"); + else + { + sdactive = true; + Serial.println("SD card ok"); + } +#endif //SDSS +} + +void quickinitsd(){ + sdactive=false; + autostart_atmillis=millis()+5000; +} + +inline void write_command(char *buf){ + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL){ + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + //Serial.println(begin); + file.write(begin); + if (file.writeError){ + Serial.println("error writing to file"); + } +} +#endif //SDSUPPORT + + +///adds an command to the main command buffer +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.print("en:");Serial.println(cmdbuffer[bufindw]); + bufindw= (bufindw + 1)%BUFSIZE; + buflen += 1; + } +} + +void setup() +{ + + Serial.begin(BAUDRATE); + ECHOLN("Marlin "< -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); +#endif //SDPOWER + quickinitsd(); + +#endif //SDSUPPORT + plan_init(); // Initialize planner; + st_init(); // Initialize stepper; + tp_init(); // Initialize temperature loop + //checkautostart(); +} + +#ifdef SDSUPPORT +bool autostart_stilltocheck=true; + + +void checkautostart(bool force) +{ + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + //sprintf(cmd,"M115"); + //enquecommand("G92 Z0"); + //enquecommand("G1 Z10 F2000"); + //enquecommand("G28 X-105 Y-105"); + enquecommand(cmd); + enquecommand("M24"); + found=true; + + } + } + if(!found) + lastnr=-1; + else + lastnr++; + +} +#else + +inline void checkautostart(bool x) +{ +} +#endif + + +void loop() +{ + if(buflen<3) + get_command(); + checkautostart(false); + if(buflen) + { +#ifdef SDSUPPORT + if(savetosd){ + if(strstr(cmdbuffer[bufindr],"M29") == NULL){ + write_command(cmdbuffer[bufindr]); + Serial.println("ok"); + } + else{ + file.sync(); + file.close(); + savetosd = false; + Serial.println("Done saving file."); + } + } + else{ + process_commands(); + } +#else + process_commands(); +#endif //SDSUPPORT + buflen = (buflen-1); + bufindr = (bufindr + 1)%BUFSIZE; + } + //check heater every n milliseconds + manage_heater(); + manage_inactivity(1); + LCD_STATUS; +} + + +inline void get_command() +{ + while( Serial.available() > 0 && buflen < BUFSIZE) { + serial_char = Serial.read(); + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) + { + if(!serial_count) return; //if empty line + cmdbuffer[bufindw][serial_count] = 0; //terminate string + if(!comment_mode){ + 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.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); + Serial.println(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.print("Error: checksum mismatch, Last Line:"); + Serial.println(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + //if no errors, continue parsing + } + else + { + Serial.print("Error: No Checksum with line number, Last Line:"); + Serial.println(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.print("Error: No Line Number with checksum, Last Line:"); + Serial.println(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: +#ifdef SDSUPPORT + if(savetosd) + break; +#endif //SDSUPPORT + Serial.println("ok"); + break; + default: + break; + } + + } + bufindw = (bufindw + 1)%BUFSIZE; + buflen += 1; + + } + 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; + } + } +#ifdef SDSUPPORT + if(!sdmode || serial_count!=0){ + return; + } + while( filesize > sdpos && buflen < BUFSIZE) { + n = file.read(); + serial_char = (char)n; + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) + { + sdpos = file.curPosition(); + if(sdpos >= filesize){ + sdmode = false; + Serial.println("Done printing file"); + 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.println(time); + LCD_MESSAGE(time); + checkautostart(true); + } + if(!serial_count) 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 + +} + + +inline float code_value() { + return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); +} +inline long code_value_long() { + return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); +} +inline bool code_seen(char code_string[]) { + return (strstr(cmdbuffer[bufindr], code_string) != NULL); +} //Return True if the string was found + +inline bool code_seen(char code) +{ + strchr_pointer = strchr(cmdbuffer[bufindr], code); + return (strchr_pointer != NULL); //Return True if a character was found +} + +inline 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 + get_coordinates(); // For X Y Z E F + prepare_move(); + previous_millis_cmd = millis(); + //ClearToSend(); + return; + //break; + case 2: // G2 - CW ARC + get_arc_coordinates(); + prepare_arc_move(true); + previous_millis_cmd = millis(); + return; + case 3: // G3 - CCW ARC + get_arc_coordinates(); + prepare_arc_move(false); + previous_millis_cmd = millis(); + return; + case 4: // G4 dwell + codenum = 0; + if(code_seen('P')) codenum = code_value(); // milliseconds to wait + if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait + codenum += millis(); // keep track of when we started waiting + while(millis() < codenum ){ + manage_heater(); + } + break; + case 28: //G28 Home all Axis one at a time + saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + + for(int 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((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { + if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ +// st_synchronize(); + current_position[X_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; + feedrate = homing_feedrate[X_AXIS]; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = -5 * X_HOME_DIR; + prepare_move(); + +// st_synchronize(); + destination[X_AXIS] = 10 * X_HOME_DIR; + feedrate = homing_feedrate[X_AXIS]/2 ; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = current_position[X_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { + if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ + 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[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]; + prepare_move(); +// st_synchronize(); + + 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[Y_AXIS] = -5 * Y_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Y_AXIS] = 10 * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Y_AXIS] = current_position[Y_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { + if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = -2 * Z_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Z_AXIS] = 3 * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = current_position[Z_AXIS]; + feedrate = 0.0; + } + } + feedrate = saved_feedrate; + feedmultiply = saved_feedmultiply; + previous_millis_cmd = millis(); + break; + case 90: // G90 + relative_mode = false; + break; + case 91: // G91 + relative_mode = true; + break; + case 92: // G92 + if(!code_seen(axis_codes[E_AXIS])) + st_synchronize(); + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) current_position[i] = code_value(); + } + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + break; + } + } + + else if(code_seen('M')) + { + + switch( (int)code_value() ) + { +#ifdef SDSUPPORT + + case 20: // M20 - list SD card + Serial.println("Begin file list"); + root.ls(); + Serial.println("End file list"); + break; + case 21: // M21 - init SD card + sdmode = false; + initsd(); + break; + case 22: //M22 - release SD card + sdmode = false; + sdactive = false; + break; + case 23: //M23 - Select file + if(sdactive){ + sdmode = false; + file.close(); + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos!=NULL) + *(starpos-1)='\0'; + if (file.open(&root, strchr_pointer + 4, O_READ)) { + Serial.print("File opened:"); + Serial.print(strchr_pointer + 4); + Serial.print(" Size:"); + Serial.println(file.fileSize()); + sdpos = 0; + filesize = file.fileSize(); + Serial.println("File selected"); + } + else{ + Serial.println("file.open failed"); + } + } + break; + case 24: //M24 - Start SD print + if(sdactive){ + sdmode = true; + starttime=millis(); + } + break; + case 25: //M25 - Pause SD print + if(sdmode){ + sdmode = false; + } + break; + case 26: //M26 - Set SD index + if(sdactive && code_seen('S')){ + sdpos = code_value_long(); + file.seekSet(sdpos); + } + break; + case 27: //M27 - Get SD status + if(sdactive){ + Serial.print("SD printing byte "); + Serial.print(sdpos); + Serial.print("/"); + Serial.println(filesize); + } + else{ + Serial.println("Not SD printing"); + } + break; + case 28: //M28 - Start SD write + if(sdactive){ + char* npos = 0; + file.close(); + sdmode = false; + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos != NULL){ + npos = strchr(cmdbuffer[bufindr], 'N'); + strchr_pointer = strchr(npos,' ') + 1; + *(starpos-1) = '\0'; + } + if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + Serial.print("open failed, File: "); + Serial.print(strchr_pointer + 4); + Serial.print("."); + } + else{ + savetosd = true; + Serial.print("Writing to file: "); + Serial.println(strchr_pointer + 4); + } + } + break; + case 29: //M29 - Stop SD write + //processed in write to file routine above + //savetosd = false; + break; + case 30: + { + 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.println(time); + LCD_MESSAGE(time); + } + break; +#endif //SDSUPPORT + 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(int i = 0; i < (int)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 (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); +#ifdef PIDTEMP + pid_setpoint = code_value(); +#endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + }else{ + watchmillis = 0; + } + #endif + break; + case 140: // M140 set bed temp + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); + break; + case 105: // M105 + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + tt = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + #endif + #if TEMP_1_PIN > -1 + bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); + #endif + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + Serial.print("ok T:"); + Serial.print(tt); +// Serial.print(", raw:"); +// Serial.print(current_raw); + #if TEMP_1_PIN > -1 +#ifdef PIDTEMP + Serial.print(" B:"); + #if TEMP_1_PIN > -1 + Serial.println(bt); + #else + Serial.println(HeaterPower); + #endif +#else + Serial.println(); +#endif + #else + Serial.println(); + #endif + #else + Serial.println("No thermistors - no temp"); + #endif + return; + //break; + case 109: {// M109 - Wait for extruder heater to reach target. + LCD_MESSAGE("Heating..."); + if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); + #ifdef PIDTEMP + pid_setpoint = code_value(); + #endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND_0]>current_raw[TEMPSENSOR_HOTEND_0]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + } else { + watchmillis = 0; + } + #endif //WATCHPERIOD + codenum = millis(); + + /* See if we are heating up or cooling down */ + bool target_direction = (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]); // 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((target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0])) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + #else + while ( target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0]) ) { + #endif //TEMP_RESIDENCY_TIME + if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down + Serial.print("T:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) ); + codenum = millis(); + } + manage_heater(); + 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 && current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) || + (residencyStart == -1 && !target_direction && current_raw[TEMPSENSOR_HOTEND_0] <= target_raw[TEMPSENSOR_HOTEND_0]) || + (residencyStart > -1 && labs(analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) - analog2temp(target_raw[TEMPSENSOR_HOTEND_0])) > TEMP_HYSTERESIS) ) { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGE("Marlin ready."); + } + break; + case 190: // M190 - Wait bed for heater to reach target. + #if TEMP_1_PIN > -1 + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); + codenum = millis(); + while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) + { + if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + { + float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + Serial.print("T:"); + Serial.println( tt ); + Serial.print("ok T:"); + Serial.print( tt ); + Serial.print(" B:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); + codenum = millis(); + } + manage_heater(); + } + #endif + break; +#if FAN_PIN > -1 + case 106: //M106 Fan On + if (code_seen('S')){ + WRITE(FAN_PIN,HIGH); + fanpwm=constrain(code_value(),0,255); + analogWrite(FAN_PIN, fanpwm); + } + else { + WRITE(FAN_PIN,HIGH); + fanpwm=255; + analogWrite(FAN_PIN, fanpwm); + } + break; + case 107: //M107 Fan Off + WRITE(FAN_PIN,LOW); + analogWrite(FAN_PIN, 0); + break; +#endif +#if (PS_ON_PIN > -1) + case 80: // M80 - ATX Power On + SET_OUTPUT(PS_ON_PIN); //GND + break; + case 81: // M81 - ATX Power Off + SET_INPUT(PS_ON_PIN); //Floating + break; +#endif + case 82: + axis_relative_modes[3] = false; + break; + case 83: + axis_relative_modes[3] = true; + break; + case 18: + case 84: + if(code_seen('S')){ + stepper_inactive_time = code_value() * 1000; + } + else{ + st_synchronize(); + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + break; + case 85: // M85 + code_seen('S'); + max_inactive_time = code_value() * 1000; + break; + case 92: // M92 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); + } + + break; + case 115: // M115 + Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); + break; + case 114: // M114 + Serial.print("X:"); + Serial.print(current_position[X_AXIS]); + Serial.print("Y:"); + Serial.print(current_position[Y_AXIS]); + Serial.print("Z:"); + Serial.print(current_position[Z_AXIS]); + Serial.print("E:"); + Serial.print(current_position[E_AXIS]); + #ifdef DEBUG_STEPS + Serial.print(" Count X:"); + Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); + Serial.print("Y:"); + Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); + Serial.print("Z:"); + Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); + #endif + Serial.println(""); + break; + case 119: // M119 +#if (X_MIN_PIN > -1) + Serial.print("x_min:"); + Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (X_MAX_PIN > -1) + Serial.print("x_max:"); + Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MIN_PIN > -1) + Serial.print("y_min:"); + Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MAX_PIN > -1) + Serial.print("y_max:"); + Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MIN_PIN > -1) + Serial.print("z_min:"); + Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MAX_PIN > -1) + Serial.print("z_max:"); + Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif + Serial.println(""); + break; + //TODO: update for all axis, use for loop + case 201: // M201 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) 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(int 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(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; + } + 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()*60 ; + if(code_seen('T')) mintravelfeedrate = code_value()*60 ; + if(code_seen('B')) minsegmenttime = code_value() ; + if(code_seen('X')) max_xy_jerk = code_value()*60 ; + if(code_seen('Z')) max_z_jerk = code_value()*60 ; + } + break; + case 220: // M220 S- set speed factor override percentage + { + if(code_seen('S')) + { + feedmultiply = code_value() ; + feedmultiplychanged=true; + } + } + 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; +// ECHOLN("Kp "<<_FLOAT(Kp,2)); +// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); +// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); + +// temp_iState_min = 0.0; +// if (Ki!=0) { +// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); +// } +// else temp_iState_max = 1.0e10; + break; +#endif //PIDTEMP + case 500: // Store settings in EEPROM + { + StoreSettings(); + } + break; + case 501: // Read settings from EEPROM + { + RetrieveSettings(); + } + break; + case 502: // Revert to default settings + { + RetrieveSettings(true); + } + break; + + } + } + else{ + Serial.println("Unknown command:"); + Serial.println(cmdbuffer[bufindr]); + } + + ClearToSend(); +} + +void FlushSerialRequestResend() +{ + //char cmdbuffer[bufindr][100]="Resend:"; + Serial.flush(); + Serial.print("Resend:"); + Serial.println(gcode_LastN + 1); + ClearToSend(); +} + +void ClearToSend() +{ + previous_millis_cmd = millis(); +#ifdef SDSUPPORT + if(fromsd[bufindr]) + return; +#endif //SDSUPPORT + Serial.println("ok"); +} + +inline void get_coordinates() +{ + for(int 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]; + 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; + } +} + +inline void get_arc_coordinates() +{ + get_coordinates(); + if(code_seen("I")) offset[0] = code_value(); + if(code_seen("J")) offset[1] = code_value(); +} + +void prepare_move() +{ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); + for(int i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; + } +} + +void prepare_arc_move(char isclockwise) { +#if 0 + if (radius_mode) { + /* + We need to calculate the center of the circle that has the designated radius and passes + through both the current position and the target position. This method calculates the following + set of equations where [x,y] is the vector from current to target position, d == magnitude of + that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to + the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the + length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point + [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc. + + d^2 == x^2 + y^2 + h^2 == r^2 - (d/2)^2 + i == x/2 - y/d*h + j == y/2 + x/d*h + + O <- [i,j] + - | + r - | + - | + - | h + - | + [0,0] -> C -----------------+--------------- T <- [x,y] + | <------ d/2 ---->| + + C - Current position + T - Target position + O - center of circle that pass through both C and T + d - distance from C to T + r - designated radius + h - distance from center of CT to O + + Expanding the equations: + + d -> sqrt(x^2 + y^2) + h -> sqrt(4 * r^2 - x^2 - y^2)/2 + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + + Which can be written: + + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + + Which we for size and speed reasons optimize to: + + h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) + i = (x - (y * h_x2_div_d))/2 + j = (y + (x * h_x2_div_d))/2 + + */ + + // Calculate the change in position along each selected axis + double x = target[gc.plane_axis_0]-gc.position[gc.plane_axis_0]; + double y = target[gc.plane_axis_1]-gc.position[gc.plane_axis_1]; + + clear_vector(offset); + double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d) + // If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any + // real CNC, and thus - for practical reasons - we will terminate promptly: + if(isnan(h_x2_div_d)) { FAIL(STATUS_FLOATING_POINT_ERROR); return(gc.status_code); } + // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) + if (gc.motion_mode == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; } + + /* The counter clockwise circle lies to the left of the target direction. When offset is positive, + the left hand circle will be generated - when it is negative the right hand circle is generated. + + + T <-- Target position + + ^ + Clockwise circles with this center | Clockwise circles with this center will have + will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing! + \ | / + center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative + | + | + + C <-- Current position */ + + + // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!), + // even though it is advised against ever generating such circles in a single line of g-code. By + // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of + // travel and thus we get the unadvisably long arcs as prescribed. + if (r < 0) { + h_x2_div_d = -h_x2_div_d; + r = -r; // Finished with r. Set to positive for mc_arc + } + // Complete the operation by calculating the actual center of the arc + offset[gc.plane_axis_0] = 0.5*(x-(y*h_x2_div_d)); + offset[gc.plane_axis_1] = 0.5*(y+(x*h_x2_div_d)); + + } else { // Offset mode specific computations +#endif + float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc + +// } + + // Set clockwise/counter-clockwise sign for mc_arc computations +// uint8_t isclockwise = false; +// if (gc.motion_mode == MOTION_MODE_CW_ARC) { isclockwise = true; } + + // Trace the arc + mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60.0/100.0, r, isclockwise); + +// } + + // 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(int ii=0; ii < NUM_AXIS; ii++) { + current_position[ii] = destination[ii]; + } +} + +#ifdef USE_WATCHDOG + +#include +#include + +volatile uint8_t timeout_seconds=0; + +void(* ctrlaltdelete) (void) = 0; + +ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec + if(timeout_seconds++ >= WATCHDOG_TIMEOUT) + { + kill(); +#ifdef RESET_MANUAL + LCD_MESSAGE("Please Reset!"); + ECHOLN("echo_: Something is wrong, please turn off the printer."); +#else + LCD_MESSAGE("Timeout, resetting!"); +#endif + //disable watchdog, it will survife reboot. + WDTCSR |= (1< -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif + disable_x(); + disable_y(); + disable_z(); + disable_e(); + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + Serial.println("!! Printer halted. kill() called !!"); + while(1); // Wait for reset +} + +void manage_inactivity(byte debug) { + if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); + if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + check_axes_activity(); +} -/* - 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 "EEPROMwrite.h" -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "streaming.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" - -#ifdef SIMPLE_LCD - #include "Simplelcd.h" -#endif - -char version_string[] = "1.0.0 Alpha 1"; - -#ifdef SDSUPPORT -#include "SdFat.h" -#endif //SDSUPPORT - - -// 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 -// G28 - Home all Axis -// G90 - Use Absolute Coordinates -// G91 - Use Relative Coordinates -// G92 - Set current position to cordinates given - -//RepRap M Codes -// 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 -// 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 -// 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 -// M115 - Capabilities string -// 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 -// M220 - set speed factor override percentage S:factor in percent -// M301 - Set PID parameters P I and D -// M500 - stores paramters in EEPROM -// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D -// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. - -//Stepper Movement Variables - -char axis_codes[NUM_AXIS] = { - 'X', 'Y', 'Z', 'E'}; -float destination[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -float current_position[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -bool home_all_axis = true; -float feedrate = 1500.0, next_feedrate, saved_feedrate; -long gcode_N, gcode_LastN; - -float homing_feedrate[] = HOMING_FEEDRATE; -bool axis_relative_modes[] = AXIS_RELATIVE_MODES; - -bool relative_mode = false; //Determines Absolute or Relative Coordinates -bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. - -uint8_t fanpwm=0; - -volatile int feedmultiply=100; //100->1 200->2 -int saved_feedmultiply; -volatile bool feedmultiplychanged=false; -// comm variables -#define MAX_CMD_SIZE 96 -#define BUFSIZE 4 -char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; -bool fromsd[BUFSIZE]; -int bufindr = 0; -int bufindw = 0; -int buflen = 0; -int i = 0; -char serial_char; -int serial_count = 0; -boolean comment_mode = false; -char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc -extern float HeaterPower; - -#include "EEPROM.h" - -const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 - -float tt = 0, bt = 0; -#ifdef WATCHPERIOD -int watch_raw = -1000; -unsigned long watchmillis = 0; -#endif //WATCHPERIOD - -//Inactivity shutdown variables -unsigned long previous_millis_cmd = 0; -unsigned long max_inactive_time = 0; -unsigned long stepper_inactive_time = 0; - -unsigned long starttime=0; -unsigned long stoptime=0; -#ifdef SDSUPPORT -Sd2Card card; -SdVolume volume; -SdFile root; -SdFile file; -uint32_t filesize = 0; -uint32_t sdpos = 0; -bool sdmode = false; -bool sdactive = false; -bool savetosd = false; -int16_t n; -unsigned long autostart_atmillis=0; - -void initsd(){ - sdactive = false; -#if SDSS >- 1 - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)){ - //if (!card.init(SPI_HALF_SPEED,SDSS)) - Serial.println("SD init fail"); - } - else if (!volume.init(&card)) - Serial.println("volume.init failed"); - else if (!root.openRoot(&volume)) - Serial.println("openRoot failed"); - else - { - sdactive = true; - Serial.println("SD card ok"); - } -#endif //SDSS -} - -void quickinitsd(){ - sdactive=false; - autostart_atmillis=millis()+5000; -} - -inline void write_command(char *buf){ - char* begin = buf; - char* npos = 0; - char* end = buf + strlen(buf) - 1; - - file.writeError = false; - if((npos = strchr(buf, 'N')) != NULL){ - begin = strchr(npos, ' ') + 1; - end = strchr(npos, '*') - 1; - } - end[1] = '\r'; - end[2] = '\n'; - end[3] = '\0'; - //Serial.println(begin); - file.write(begin); - if (file.writeError){ - Serial.println("error writing to file"); - } -} -#endif //SDSUPPORT - - -///adds an command to the main command buffer -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.print("en:");Serial.println(cmdbuffer[bufindw]); - bufindw= (bufindw + 1)%BUFSIZE; - buflen += 1; - } -} - -void setup() -{ - - Serial.begin(BAUDRATE); - ECHOLN("Marlin "< -1 - SET_OUTPUT(SDPOWER); - WRITE(SDPOWER,HIGH); -#endif //SDPOWER - quickinitsd(); - -#endif //SDSUPPORT - plan_init(); // Initialize planner; - st_init(); // Initialize stepper; - tp_init(); // Initialize temperature loop - //checkautostart(); -} - -#ifdef SDSUPPORT -bool autostart_stilltocheck=true; - - -void checkautostart(bool force) -{ - //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) - { - for(int i=0;i<(int)strlen((char*)p.name);i++) - p.name[i]=tolower(p.name[i]); - //Serial.print((char*)p.name); - //Serial.print(" "); - //Serial.println(autoname); - if(p.name[9]!='~') //skip safety copies - if(strncmp((char*)p.name,autoname,5)==0) - { - char cmd[30]; - - sprintf(cmd,"M23 %s",autoname); - //sprintf(cmd,"M115"); - //enquecommand("G92 Z0"); - //enquecommand("G1 Z10 F2000"); - //enquecommand("G28 X-105 Y-105"); - enquecommand(cmd); - enquecommand("M24"); - found=true; - - } - } - if(!found) - lastnr=-1; - else - lastnr++; - -} -#else - -inline void checkautostart(bool x) -{ -} -#endif - - -void loop() -{ - if(buflen<3) - get_command(); - checkautostart(false); - if(buflen) - { -#ifdef SDSUPPORT - if(savetosd){ - if(strstr(cmdbuffer[bufindr],"M29") == NULL){ - write_command(cmdbuffer[bufindr]); - Serial.println("ok"); - } - else{ - file.sync(); - file.close(); - savetosd = false; - Serial.println("Done saving file."); - } - } - else{ - process_commands(); - } -#else - process_commands(); -#endif //SDSUPPORT - buflen = (buflen-1); - bufindr = (bufindr + 1)%BUFSIZE; - } - //check heater every n milliseconds - manage_heater(); - manage_inactivity(1); - LCD_STATUS; -} - - -inline void get_command() -{ - while( Serial.available() > 0 && buflen < BUFSIZE) { - serial_char = Serial.read(); - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) - { - if(!serial_count) return; //if empty line - cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ - 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.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); - Serial.println(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.print("Error: checksum mismatch, Last Line:"); - Serial.println(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { - Serial.print("Error: No Checksum with line number, Last Line:"); - Serial.println(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.print("Error: No Line Number with checksum, Last Line:"); - Serial.println(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: -#ifdef SDSUPPORT - if(savetosd) - break; -#endif //SDSUPPORT - Serial.println("ok"); - break; - default: - break; - } - - } - bufindw = (bufindw + 1)%BUFSIZE; - buflen += 1; - - } - 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; - } - } -#ifdef SDSUPPORT - if(!sdmode || serial_count!=0){ - return; - } - while( filesize > sdpos && buflen < BUFSIZE) { - n = file.read(); - serial_char = (char)n; - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) - { - sdpos = file.curPosition(); - if(sdpos >= filesize){ - sdmode = false; - Serial.println("Done printing file"); - 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.println(time); - LCD_MESSAGE(time); - checkautostart(true); - } - if(!serial_count) 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 - -} - - -inline float code_value() { - return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); -} -inline long code_value_long() { - return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); -} -inline bool code_seen(char code_string[]) { - return (strstr(cmdbuffer[bufindr], code_string) != NULL); -} //Return True if the string was found - -inline bool code_seen(char code) -{ - strchr_pointer = strchr(cmdbuffer[bufindr], code); - return (strchr_pointer != NULL); //Return True if a character was found -} - -inline 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 - get_coordinates(); // For X Y Z E F - prepare_move(); - previous_millis_cmd = millis(); - //ClearToSend(); - return; - //break; - case 4: // G4 dwell - codenum = 0; - if(code_seen('P')) codenum = code_value(); // milliseconds to wait - if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait - codenum += millis(); // keep track of when we started waiting - while(millis() < codenum ){ - manage_heater(); - } - break; - case 28: //G28 Home all Axis one at a time - saved_feedrate = feedrate; - saved_feedmultiply = feedmultiply; - feedmultiply = 100; - - for(int 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((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { - if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ -// st_synchronize(); - current_position[X_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; - feedrate = homing_feedrate[X_AXIS]; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = -5 * X_HOME_DIR; - prepare_move(); - -// st_synchronize(); - destination[X_AXIS] = 10 * X_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]/2 ; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = current_position[X_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { - if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ - 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[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]; - prepare_move(); -// st_synchronize(); - - 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[Y_AXIS] = -5 * Y_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Y_AXIS] = 10 * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = current_position[Y_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { - if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = -2 * Z_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Z_AXIS] = 3 * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0.0; - } - } - feedrate = saved_feedrate; - feedmultiply = saved_feedmultiply; - previous_millis_cmd = millis(); - break; - case 90: // G90 - relative_mode = false; - break; - case 91: // G91 - relative_mode = true; - break; - case 92: // G92 - if(!code_seen(axis_codes[E_AXIS])) - st_synchronize(); - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) current_position[i] = code_value(); - } - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - break; - } - } - - else if(code_seen('M')) - { - - switch( (int)code_value() ) - { -#ifdef SDSUPPORT - - case 20: // M20 - list SD card - Serial.println("Begin file list"); - root.ls(); - Serial.println("End file list"); - break; - case 21: // M21 - init SD card - sdmode = false; - initsd(); - break; - case 22: //M22 - release SD card - sdmode = false; - sdactive = false; - break; - case 23: //M23 - Select file - if(sdactive){ - sdmode = false; - file.close(); - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos!=NULL) - *(starpos-1)='\0'; - if (file.open(&root, strchr_pointer + 4, O_READ)) { - Serial.print("File opened:"); - Serial.print(strchr_pointer + 4); - Serial.print(" Size:"); - Serial.println(file.fileSize()); - sdpos = 0; - filesize = file.fileSize(); - Serial.println("File selected"); - } - else{ - Serial.println("file.open failed"); - } - } - break; - case 24: //M24 - Start SD print - if(sdactive){ - sdmode = true; - starttime=millis(); - } - break; - case 25: //M25 - Pause SD print - if(sdmode){ - sdmode = false; - } - break; - case 26: //M26 - Set SD index - if(sdactive && code_seen('S')){ - sdpos = code_value_long(); - file.seekSet(sdpos); - } - break; - case 27: //M27 - Get SD status - if(sdactive){ - Serial.print("SD printing byte "); - Serial.print(sdpos); - Serial.print("/"); - Serial.println(filesize); - } - else{ - Serial.println("Not SD printing"); - } - break; - case 28: //M28 - Start SD write - if(sdactive){ - char* npos = 0; - file.close(); - sdmode = false; - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos != NULL){ - npos = strchr(cmdbuffer[bufindr], 'N'); - strchr_pointer = strchr(npos,' ') + 1; - *(starpos-1) = '\0'; - } - if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) - { - Serial.print("open failed, File: "); - Serial.print(strchr_pointer + 4); - Serial.print("."); - } - else{ - savetosd = true; - Serial.print("Writing to file: "); - Serial.println(strchr_pointer + 4); - } - } - break; - case 29: //M29 - Stop SD write - //processed in write to file routine above - //savetosd = false; - break; - case 30: - { - 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.println(time); - LCD_MESSAGE(time); - } - break; -#endif //SDSUPPORT - 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(int i = 0; i < (int)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 (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); -#ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]){ - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; - }else{ - watchmillis = 0; - } - #endif - break; - case 140: // M140 set bed temp - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); - break; - case 105: // M105 - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); - #endif - #if TEMP_1_PIN > -1 - bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); - #endif - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - Serial.print("ok T:"); - Serial.print(tt); -// Serial.print(", raw:"); -// Serial.print(current_raw); - #if TEMP_1_PIN > -1 -#ifdef PIDTEMP - Serial.print(" B:"); - #if TEMP_1_PIN > -1 - Serial.println(bt); - #else - Serial.println(HeaterPower); - #endif -#else - Serial.println(); -#endif - #else - Serial.println(); - #endif - #else - Serial.println("No thermistors - no temp"); - #endif - return; - //break; - case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGE("Heating..."); - if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); - #ifdef PIDTEMP - pid_setpoint = code_value(); - #endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[TEMPSENSOR_HOTEND_0]>current_raw[TEMPSENSOR_HOTEND_0]){ - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; - } else { - watchmillis = 0; - } - #endif //WATCHPERIOD - codenum = millis(); - - /* See if we are heating up or cooling down */ - bool target_direction = (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]); // 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((target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0])) || - (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { - #else - while ( target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0]) ) { - #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down - Serial.print("T:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) ); - codenum = millis(); - } - manage_heater(); - 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 && current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) || - (residencyStart == -1 && !target_direction && current_raw[TEMPSENSOR_HOTEND_0] <= target_raw[TEMPSENSOR_HOTEND_0]) || - (residencyStart > -1 && labs(analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) - analog2temp(target_raw[TEMPSENSOR_HOTEND_0])) > TEMP_HYSTERESIS) ) { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGE("Marlin ready."); - } - break; - case 190: // M190 - Wait bed for heater to reach target. - #if TEMP_1_PIN > -1 - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); - codenum = millis(); - while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) - { - if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. - { - float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); - Serial.print("T:"); - Serial.println( tt ); - Serial.print("ok T:"); - Serial.print( tt ); - Serial.print(" B:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); - codenum = millis(); - } - manage_heater(); - } - #endif - break; -#if FAN_PIN > -1 - case 106: //M106 Fan On - if (code_seen('S')){ - WRITE(FAN_PIN,HIGH); - fanpwm=constrain(code_value(),0,255); - analogWrite(FAN_PIN, fanpwm); - } - else { - WRITE(FAN_PIN,HIGH); - fanpwm=255; - analogWrite(FAN_PIN, fanpwm); - } - break; - case 107: //M107 Fan Off - WRITE(FAN_PIN,LOW); - analogWrite(FAN_PIN, 0); - break; -#endif -#if (PS_ON_PIN > -1) - case 80: // M80 - ATX Power On - SET_OUTPUT(PS_ON_PIN); //GND - break; - case 81: // M81 - ATX Power Off - SET_INPUT(PS_ON_PIN); //Floating - break; -#endif - case 82: - axis_relative_modes[3] = false; - break; - case 83: - axis_relative_modes[3] = true; - break; - case 18: - case 84: - if(code_seen('S')){ - stepper_inactive_time = code_value() * 1000; - } - else{ - st_synchronize(); - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - break; - case 85: // M85 - code_seen('S'); - max_inactive_time = code_value() * 1000; - break; - case 92: // M92 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); - } - - break; - case 115: // M115 - Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); - break; - case 114: // M114 - Serial.print("X:"); - Serial.print(current_position[X_AXIS]); - Serial.print("Y:"); - Serial.print(current_position[Y_AXIS]); - Serial.print("Z:"); - Serial.print(current_position[Z_AXIS]); - Serial.print("E:"); - Serial.print(current_position[E_AXIS]); - #ifdef DEBUG_STEPS - Serial.print(" Count X:"); - Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); - Serial.print("Y:"); - Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); - Serial.print("Z:"); - Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); - #endif - Serial.println(""); - break; - case 119: // M119 -#if (X_MIN_PIN > -1) - Serial.print("x_min:"); - Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (X_MAX_PIN > -1) - Serial.print("x_max:"); - Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MIN_PIN > -1) - Serial.print("y_min:"); - Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MAX_PIN > -1) - Serial.print("y_max:"); - Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MIN_PIN > -1) - Serial.print("z_min:"); - Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MAX_PIN > -1) - Serial.print("z_max:"); - Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif - Serial.println(""); - break; - //TODO: update for all axis, use for loop - case 201: // M201 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) 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(int 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(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; - } - 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()*60 ; - if(code_seen('T')) mintravelfeedrate = code_value()*60 ; - if(code_seen('B')) minsegmenttime = code_value() ; - if(code_seen('X')) max_xy_jerk = code_value()*60 ; - if(code_seen('Z')) max_z_jerk = code_value()*60 ; - } - break; - case 220: // M220 S- set speed factor override percentage - { - if(code_seen('S')) - { - feedmultiply = code_value() ; - feedmultiplychanged=true; - } - } - 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; -// ECHOLN("Kp "<<_FLOAT(Kp,2)); -// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); -// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); - -// temp_iState_min = 0.0; -// if (Ki!=0) { -// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); -// } -// else temp_iState_max = 1.0e10; - break; -#endif //PIDTEMP - case 500: // Store settings in EEPROM - { - StoreSettings(); - } - break; - case 501: // Read settings from EEPROM - { - RetrieveSettings(); - } - break; - case 502: // Revert to default settings - { - RetrieveSettings(true); - } - break; - - } - } - else{ - Serial.println("Unknown command:"); - Serial.println(cmdbuffer[bufindr]); - } - - ClearToSend(); -} - -void FlushSerialRequestResend() -{ - //char cmdbuffer[bufindr][100]="Resend:"; - Serial.flush(); - Serial.print("Resend:"); - Serial.println(gcode_LastN + 1); - ClearToSend(); -} - -void ClearToSend() -{ - previous_millis_cmd = millis(); -#ifdef SDSUPPORT - if(fromsd[bufindr]) - return; -#endif //SDSUPPORT - Serial.println("ok"); -} - -inline void get_coordinates() -{ - for(int 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]; - 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; - } -} - -void prepare_move() -{ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); - for(int i=0; i < NUM_AXIS; i++) { - current_position[i] = destination[i]; - } -} - - - -#ifdef USE_WATCHDOG - -#include -#include - -volatile uint8_t timeout_seconds=0; - -void(* ctrlaltdelete) (void) = 0; - -ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec - if(timeout_seconds++ >= WATCHDOG_TIMEOUT) - { - kill(); -#ifdef RESET_MANUAL - LCD_MESSAGE("Please Reset!"); - ECHOLN("echo_: Something is wrong, please turn off the printer."); -#else - LCD_MESSAGE("Timeout, resetting!"); -#endif - //disable watchdog, it will survife reboot. - WDTCSR |= (1< -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif - disable_x(); - disable_y(); - disable_z(); - disable_e(); - - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); - Serial.println("!! Printer halted. kill() called!!"); - while(1); // Wait for reset -} - -void manage_inactivity(byte debug) { - if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); - if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - check_axes_activity(); -} diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp new file mode 100644 index 0000000000..875531fb78 --- /dev/null +++ b/Marlin/motion_control.cpp @@ -0,0 +1,133 @@ +/* + motion_control.c - high level interface for issuing motion commands + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + Copyright (c) 2011 Sungeun K. Jeon + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +//#include "motion_control.h" +#include "Configuration.h" +#include "Marlin.h" +//#include +//#include +//#include +#include "stepper.h" +#include "planner.h" + +// The arc is approximated by generating a huge number of tiny, linear segments. The length of each +// segment is configured in settings.mm_per_arc_segment. +void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, + uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise) +{ +// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); +// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc + Serial.println("mc_arc"); + float center_axis0 = position[axis_0] + offset[axis_0]; + float center_axis1 = position[axis_1] + offset[axis_1]; + float linear_travel = target[axis_linear] - position[axis_linear]; + float r_axis0 = -offset[axis_0]; // Radius vector from center to current location + float r_axis1 = -offset[axis_1]; + float rt_axis0 = target[axis_0] - center_axis0; + float rt_axis1 = target[axis_1] - center_axis1; + + // CCW angle between position and target from circle center. Only one atan2() trig computation required. + float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1); + if (angular_travel < 0) { angular_travel += 2*M_PI; } + if (isclockwise) { angular_travel -= 2*M_PI; } + + float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel)); + if (millimeters_of_travel == 0.0) { return; } + uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT); +/* + // Multiply inverse feed_rate to compensate for the fact that this movement is approximated + // by a number of discrete segments. The inverse feed_rate should be correct for the sum of + // all segments. + if (invert_feed_rate) { feed_rate *= segments; } +*/ + float theta_per_segment = angular_travel/segments; + float linear_per_segment = linear_travel/segments; + + /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector, + and phi is the angle of rotation. Based on the solution approach by Jens Geisler. + r_T = [cos(phi) -sin(phi); + sin(phi) cos(phi] * r ; + + For arc generation, the center of the circle is the axis of rotation and the radius vector is + defined from the circle center to the initial position. Each line segment is formed by successive + vector rotations. This requires only two cos() and sin() computations to form the rotation + matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since + all double numbers are single precision on the Arduino. (True double precision will not have + round off issues for CNC applications.) Single precision error can accumulate to be greater than + tool precision in some cases. Therefore, arc path correction is implemented. + + Small angle approximation may be used to reduce computation overhead further. This approximation + holds for everything, but very small circles and large mm_per_arc_segment values. In other words, + theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large + to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for + numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an + issue for CNC machines with the single precision Arduino calculations. + + This approximation also allows mc_arc to immediately insert a line segment into the planner + without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied + a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead. + This is important when there are successive arc motions. + */ + // Vector rotation matrix values + float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation + float sin_T = theta_per_segment; + + float arc_target[3]; + float sin_Ti; + float cos_Ti; + float r_axisi; + uint16_t i; + int8_t count = 0; + + // Initialize the linear axis + arc_target[axis_linear] = position[axis_linear]; + + for (i = 1; i. +*/ + +#ifndef motion_control_h +#define motion_control_h + +// Execute an arc in offset mode format. position == current xyz, target == target xyz, +// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is +// the direction of helical travel, radius == circle radius, isclockwise boolean. Used +// for vector transformation direction. +void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1, + unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise); + +#endif From 2afb7bd4cfa130d57dcbca657fa9a81eecbc7a15 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 14:03:41 +0100 Subject: [PATCH 013/228] refactured temperature.cpp so that there are now abstract functions to access temperatures. --- Marlin/Configuration.h | 3 +- Marlin/Marlin.pde | 106 ++++++++++------------------- Marlin/temperature.cpp | 57 +++++++++++----- Marlin/temperature.h | 100 ++++++++++++++++++++++----- Marlin/ultralcd.pde | 150 +++++++++++++++++++++-------------------- 5 files changed, 237 insertions(+), 179 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 65c4f32a3c..8ad0e22829 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -157,6 +157,7 @@ const int dropsegments=5; //everything with this number of steps will be ignore //// Experimental watchdog and minimal temp // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 +/// CURRENTLY NOT IMPLEMENTED AND UNUSEABLE //#define WATCHPERIOD 5000 //5 seconds // Actual temperature must be close to target for this long before M109 returns success @@ -245,4 +246,4 @@ const int dropsegments=5; //everything with this number of steps will be ignore #endif -#endif +#endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 92907a2d24..698b137803 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -150,10 +150,7 @@ extern float HeaterPower; const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 float tt = 0, bt = 0; -#ifdef WATCHPERIOD -int watch_raw = -1000; -unsigned long watchmillis = 0; -#endif //WATCHPERIOD + //Inactivity shutdown variables unsigned long previous_millis_cmd = 0; @@ -817,28 +814,18 @@ inline void process_commands() } break; case 104: // M104 - if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); -#ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]){ - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; - }else{ - watchmillis = 0; - } - #endif + if (code_seen('S')) setTargetHotend0(code_value()); + setWatch(); break; case 140: // M140 set bed temp - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); + if (code_seen('S')) setTargetBed(code_value()); break; case 105: // M105 #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + tt = degHotend0(); #endif #if TEMP_1_PIN > -1 - bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); + bt = degBed(); #endif #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) Serial.print("ok T:"); @@ -866,36 +853,27 @@ inline void process_commands() //break; case 109: {// M109 - Wait for extruder heater to reach target. LCD_MESSAGE("Heating..."); - if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value()); - #ifdef PIDTEMP - pid_setpoint = code_value(); - #endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[TEMPSENSOR_HOTEND_0]>current_raw[TEMPSENSOR_HOTEND_0]){ - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; - } else { - watchmillis = 0; - } - #endif //WATCHPERIOD + if (code_seen('S')) setTargetHotend0(code_value()); + + setWatch(); codenum = millis(); /* See if we are heating up or cooling down */ - bool target_direction = (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]); // true if heating, false if cooling + bool target_direction = isHeatingHotend0(); // 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((target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0])) || + while((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) || (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else - while ( target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0]) ) { + while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) ) { #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down Serial.print("T:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) ); + Serial.println( degHotend0() ); codenum = millis(); } manage_heater(); @@ -903,9 +881,9 @@ inline void process_commands() #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 && current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) || - (residencyStart == -1 && !target_direction && current_raw[TEMPSENSOR_HOTEND_0] <= target_raw[TEMPSENSOR_HOTEND_0]) || - (residencyStart > -1 && labs(analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) - analog2temp(target_raw[TEMPSENSOR_HOTEND_0])) > TEMP_HYSTERESIS) ) { + if ((residencyStart == -1 && target_direction && !isHeatingHotend0()) || + (residencyStart == -1 && !target_direction && !isCoolingHotend0()) || + (residencyStart > -1 && labs(degHotend0() - degTargetHotend0()) > TEMP_HYSTERESIS) ) { residencyStart = millis(); } #endif //TEMP_RESIDENCY_TIME @@ -915,23 +893,23 @@ inline void process_commands() break; case 190: // M190 - Wait bed for heater to reach target. #if TEMP_1_PIN > -1 - if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); - codenum = millis(); - while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) - { - if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + if (code_seen('S')) setTargetBed(code_value()); + codenum = millis(); + while(isHeatingBed()) { - float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); - Serial.print("T:"); - Serial.println( tt ); - Serial.print("ok T:"); - Serial.print( tt ); - Serial.print(" B:"); - Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); - codenum = millis(); - } + if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + { + float tt=degHotend0(); + Serial.print("T:"); + Serial.println( tt ); + Serial.print("ok T:"); + Serial.print( tt ); + Serial.print(" B:"); + Serial.println( degBed() ); + codenum = millis(); + } manage_heater(); - } + } #endif break; #if FAN_PIN > -1 @@ -1331,24 +1309,8 @@ void wd_reset() { inline void kill() { - #if TEMP_0_PIN > -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif + disable_heater(); + disable_x(); disable_y(); disable_z(); @@ -1369,4 +1331,4 @@ void manage_inactivity(byte debug) { } check_axes_activity(); } - + diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index b55573d93c..0c5a2e4ce2 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -37,28 +37,27 @@ #include "streaming.h" #include "temperature.h" -int target_bed_raw = 0; -int current_bed_raw = 0; int target_raw[3] = {0, 0, 0}; int current_raw[3] = {0, 0, 0}; -unsigned char temp_meas_ready = false; + +bool temp_meas_ready = false; unsigned long previous_millis_heater, previous_millis_bed_heater; #ifdef PIDTEMP - double temp_iState = 0; - double temp_dState = 0; - double pTerm; - double iTerm; - double dTerm; + float temp_iState = 0; + float temp_dState = 0; + float pTerm; + float iTerm; + float dTerm; //int output; - double pid_error; - double temp_iState_min; - double temp_iState_max; - double pid_setpoint = 0.0; - double pid_input; - double pid_output; + float pid_error; + float temp_iState_min; + float temp_iState_max; + float pid_setpoint = 0.0; + float pid_input; + float pid_output; bool pid_reset; float HeaterPower; @@ -67,6 +66,11 @@ unsigned long previous_millis_heater, previous_millis_bed_heater; float Kd=DEFAULT_Kd; float Kc=DEFAULT_Kc; #endif //PIDTEMP + +#ifdef WATCHPERIOD + int watch_raw[3] = {-1000,-1000,-1000}; + unsigned long watchmillis = 0; +#endif //WATCHPERIOD #ifdef HEATER_0_MINTEMP int minttemp_0 = temp2analog(HEATER_0_MINTEMP); @@ -91,9 +95,9 @@ int bed_maxttemp = temp2analog(BED_MAXTEMP); void manage_heater() { -#ifdef USE_WATCHDOG - wd_reset(); -#endif + #ifdef USE_WATCHDOG + wd_reset(); + #endif float pid_input; float pid_output; @@ -330,6 +334,22 @@ void tp_init() +void setWatch() +{ +#ifdef WATCHPERIOD + if(isHeatingHotend0()) + { + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + } + else + { + watchmillis = 0; + } +#endif +} + + // Timer 0 is shared with millies ISR(TIMER0_COMPB_vect) { @@ -500,4 +520,5 @@ ISR(TIMER0_COMPB_vect) #endif #endif } -} +} + diff --git a/Marlin/temperature.h b/Marlin/temperature.h index a36f997815..fcc8edb9ea 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -22,18 +22,97 @@ #define temperature_h #include "Marlin.h" +#include "fastio.h" #ifdef PID_ADD_EXTRUSION_RATE #include "stepper.h" #endif -void tp_init(); -void manage_heater(); -//int temp2analogu(int celsius, const short table[][2], int numtemps); -//float analog2tempu(int raw, const short table[][2], int numtemps); + +void tp_init(); //initialise the heating +void manage_heater(); //it is critical that this is called periodically. + +enum TempSensor {TEMPSENSOR_HOTEND_0=0,TEMPSENSOR_BED=1, TEMPSENSOR_HOTEND_1=2}; + +//low leven conversion routines +// do not use this routines and variables outsie of temperature.cpp int temp2analog(int celsius); int temp2analogBed(int celsius); float analog2temp(int raw); float analog2tempBed(int raw); +extern int target_raw[3]; +extern int current_raw[3]; +extern float Kp,Ki,Kd,Kc; +#ifdef PIDTEMP + float pid_setpoint = 0.0; +#endif +#ifdef WATCHPERIOD + extern int watch_raw[3] ; + extern unsigned long watchmillis; +#endif + + +//high level conversion routines, for use outside of temperature.cpp +//inline so that there is no performance decrease. +//deg=degreeCelsius + +inline float degHotend0(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);}; +inline float degHotend1(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]);}; +inline float degBed() { return analog2tempBed(current_raw[TEMPSENSOR_BED]);}; + +inline float degTargetHotend0() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);}; +inline float degTargetHotend1() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);}; +inline float degTargetBed() { return analog2tempBed(target_raw[TEMPSENSOR_BED]);}; + +inline void setTargetHotend0(float celsius) +{ + target_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius); + #ifdef PIDTEMP + pid_setpoint = celsius; + #endif //PIDTEMP +}; +inline void setTargetHotend1(float celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; +inline void setTargetBed(float celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; + +inline bool isHeatingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; +inline bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; +inline bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; + +inline bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];}; +inline bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; +inline bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; + +inline void disable_heater() +{ + #if TEMP_0_PIN > -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif +} +void setWatch() { + if(isHeatingHotend0()) + { + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + } + else + { + watchmillis = 0; + } +} #ifdef HEATER_0_USES_THERMISTOR #define HEATERSOURCE 1 #endif @@ -41,18 +120,9 @@ float analog2tempBed(int raw); #define BEDSOURCE 1 #endif -//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) -//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS -extern float Kp; -extern float Ki; -extern float Kd; -extern float Kc; -enum {TEMPSENSOR_HOTEND_0=0,TEMPSENSOR_BED=1, TEMPSENSOR_HOTEND_1=2}; -extern int target_raw[3]; -extern int current_raw[3]; -extern double pid_setpoint; -#endif +#endif + diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 7eefec6682..444020c228 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -12,7 +12,7 @@ LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PIN unsigned long previous_millis_lcd=0; - +inline int intround(const float &x){return int(0.5+x);} volatile char buttons=0; //the last checked buttons in a bit array. int encoderpos=0; @@ -29,13 +29,10 @@ void lcd_status(const char* message) strncpy(messagetext,message,LCD_WIDTH); } -void clear() +inline void clear() { - //lcd.setCursor(0,0); + lcd.clear(); - //delay(1); - // lcd.begin(LCD_WIDTH,LCD_HEIGHT); - //lcd_init(); } long previous_millis_buttons=0; @@ -78,47 +75,48 @@ void lcd_init() void beep() { //return; -#ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int i=0;i<20;i++){ - WRITE(BEEPER,HIGH); - delay(5); - WRITE(BEEPER,LOW); - delay(5); - } -#endif + #ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<20;i++){ + WRITE(BEEPER,HIGH); + delay(5); + WRITE(BEEPER,LOW); + delay(5); + } + #endif } void beepshort() { //return; -#ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int i=0;i<10;i++){ - WRITE(BEEPER,HIGH); - delay(3); - WRITE(BEEPER,LOW); - delay(3); - } -#endif + #ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<10;i++){ + WRITE(BEEPER,HIGH); + delay(3); + WRITE(BEEPER,LOW); + delay(3); + } + #endif } + void lcd_status() { -#ifdef ULTIPANEL - static uint8_t oldbuttons=0; - static long previous_millis_buttons=0; - static long previous_lcdinit=0; -// buttons_check(); // Done in temperature interrupt - //previous_millis_buttons=millis(); + #ifdef ULTIPANEL + static uint8_t oldbuttons=0; + static long previous_millis_buttons=0; + static long previous_lcdinit=0; + // buttons_check(); // Done in temperature interrupt + //previous_millis_buttons=millis(); + + if((buttons==oldbuttons) && ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; + oldbuttons=buttons; + #else - if((buttons==oldbuttons) && ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) - return; - oldbuttons=buttons; -#else - - if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) - return; -#endif + if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; + #endif previous_millis_lcd=millis(); menu.update(); @@ -161,8 +159,7 @@ void buttons_check() if((blocking3)||force_lcd_update) + int tHotEnd0=intround(degHotend0()); + if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often. { lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND_0]))); - oldcurrentraw=current_raw[TEMPSENSOR_HOTEND_0]; + lcd.print(ftostr3(tHotEnd0)); + olddegHotEnd0=tHotEnd0; } - if((target_raw[TEMPSENSOR_HOTEND_0]!=oldtargetraw)||force_lcd_update) + int ttHotEnd0=intround(degTargetHotend0()); + if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND_0]))); - oldtargetraw=target_raw[TEMPSENSOR_HOTEND_0]; + lcd.print(ftostr3(ttHotEnd0)); + oldtargetHotEnd0=ttHotEnd0; } #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - static int oldcurrentbedraw=-1; - static int oldtargetbedraw=-1; - if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) + static int oldtBed=-1; + static int oldtargetBed=-1; + int tBed=intround(degBed()); + if((tBed!=oldtBed)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_bed_raw))); - oldcurrentraw=current_raw[TEMPSENSOR_BED]; + lcd.print(ftostr3(tBed)); + olddegHotEnd0=tBed; } - if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) + int targetBed=intround(degTargetBed()); + if((targetBed!=oldtargetBed)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_bed_raw))); - oldtargetraw=target_bed_raw; + lcd.print(ftostr3(targetBed)); + oldtargetBed=targetBed; } #endif //starttime=2; @@ -327,8 +327,8 @@ void MainMenu::showStatus() messagetext[0]='\0'; } #else //smaller LCDS---------------------------------- - static int oldcurrentraw=-1; - static int oldtargetraw=-1; + static int olddegHotEnd0=-1; + static int oldtargetHotEnd0=-1; if(force_lcd_update) //initial display of content { encoderpos=feedmultiply; @@ -338,18 +338,21 @@ void MainMenu::showStatus() #endif } + int tHotEnd0=intround(degHotend0()); + int ttHotEnd0=intround(degTargetHotend0()); - if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) + + if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) { lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); - oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(tHotEnd0)); + olddegHotEnd0=tHotEnd0; } - if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update) { lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); - oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + lcd.print(ftostr3(ttHotEnd0)); + oldtargetHotEnd0=ttHotEnd0; } if(messagetext[0]!='\0') @@ -426,7 +429,7 @@ void MainMenu::showPrepare() if((activeline==line) && CLICKED) { BLOCK - target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(170); + setTargetHotend0(170); beepshort(); } }break; @@ -531,7 +534,7 @@ void MainMenu::showControl() if(force_lcd_update) { lcd.setCursor(0,line);lcd.print(" \002Nozzle:"); - lcd.setCursor(13,line);lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND_0]))); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degHotend0()))); } if((activeline==line) ) @@ -541,11 +544,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)analog2temp(target_raw[TEMPSENSOR_HOTEND_0]); + encoderpos=intround(degHotend0()); } else { - target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(encoderpos); + setTargetHotend0(encoderpos); encoderpos=activeline*lcdslow; beepshort(); } @@ -1590,4 +1593,5 @@ char *fillto(int8_t n,char *c) #else inline void lcd_status() {}; #endif - + + From e8092898b1c4db328a2f5d247fe06603f586f924 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 14:22:15 +0100 Subject: [PATCH 014/228] watchdog into dedicated file --- Marlin/Marlin.h | 16 +++++++++++++- Marlin/Marlin.pde | 54 ----------------------------------------------- watchdog.cpp | 48 +++++++++++++++++++++++++++++++++++++++++ watchdog.h | 10 +++++++++ 4 files changed, 73 insertions(+), 55 deletions(-) create mode 100644 watchdog.cpp create mode 100644 watchdog.h diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 15e6570c93..07dd0d8bf1 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -78,5 +78,19 @@ void enquecommand(const char *cmd); extern float homing_feedrate[]; extern bool axis_relative_modes[]; -void wd_reset() ; + +inline void kill() +{ + disable_heater(); + + disable_x(); + disable_y(); + disable_z(); + disable_e(); + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + Serial.println("!! Printer halted. kill() called !!"); + while(1); // Wait for reset +} + #endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 698b137803..6a6fb80f43 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1263,63 +1263,9 @@ void prepare_arc_move(char isclockwise) { } } -#ifdef USE_WATCHDOG - -#include -#include - -volatile uint8_t timeout_seconds=0; - -void(* ctrlaltdelete) (void) = 0; - -ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec - if(timeout_seconds++ >= WATCHDOG_TIMEOUT) - { - kill(); -#ifdef RESET_MANUAL - LCD_MESSAGE("Please Reset!"); - ECHOLN("echo_: Something is wrong, please turn off the printer."); -#else - LCD_MESSAGE("Timeout, resetting!"); -#endif - //disable watchdog, it will survife reboot. - WDTCSR |= (1< -1) pinMode(PS_ON_PIN,INPUT); - Serial.println("!! Printer halted. kill() called !!"); - while(1); // Wait for reset -} void manage_inactivity(byte debug) { if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); diff --git a/watchdog.cpp b/watchdog.cpp new file mode 100644 index 0000000000..0adf9cc7d7 --- /dev/null +++ b/watchdog.cpp @@ -0,0 +1,48 @@ +#ifdef USE_WATCHDOG + +#include +#include + +volatile uint8_t timeout_seconds=0; + +void(* ctrlaltdelete) (void) = 0; //does not work on my atmega2560 + +//Watchdog timer interrupt, called if main program blocks >1sec +ISR(WDT_vect) +{ + if(timeout_seconds++ >= WATCHDOG_TIMEOUT) + { + + #ifdef RESET_MANUAL + LCD_MESSAGE("Please Reset!"); + ECHOLN("echo_: Something is wrong, please turn off the printer."); + #else + LCD_MESSAGE("Timeout, resetting!"); + #endif + //disable watchdog, it will survife reboot. + WDTCSR |= (1< Date: Sun, 6 Nov 2011 14:58:12 +0100 Subject: [PATCH 015/228] wrong file location --- Marlin/watchdog.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++ Marlin/watchdog.h | 10 ++++++++++ 2 files changed, 58 insertions(+) create mode 100644 Marlin/watchdog.cpp create mode 100644 Marlin/watchdog.h diff --git a/Marlin/watchdog.cpp b/Marlin/watchdog.cpp new file mode 100644 index 0000000000..0adf9cc7d7 --- /dev/null +++ b/Marlin/watchdog.cpp @@ -0,0 +1,48 @@ +#ifdef USE_WATCHDOG + +#include +#include + +volatile uint8_t timeout_seconds=0; + +void(* ctrlaltdelete) (void) = 0; //does not work on my atmega2560 + +//Watchdog timer interrupt, called if main program blocks >1sec +ISR(WDT_vect) +{ + if(timeout_seconds++ >= WATCHDOG_TIMEOUT) + { + + #ifdef RESET_MANUAL + LCD_MESSAGE("Please Reset!"); + ECHOLN("echo_: Something is wrong, please turn off the printer."); + #else + LCD_MESSAGE("Timeout, resetting!"); + #endif + //disable watchdog, it will survife reboot. + WDTCSR |= (1< Date: Sun, 6 Nov 2011 15:10:29 +0100 Subject: [PATCH 016/228] correcting commit errors. --- Marlin/Marlin.h | 14 +------- Marlin/Marlin.pde | 15 +++++++++ Marlin/temperature.cpp | 23 +++++++++++++ Marlin/temperature.h | 37 +++------------------ Marlin/watchdog.h | 5 ++- Marlin/{watchdog.cpp => watchdog.pde} | 2 +- watchdog.cpp | 48 --------------------------- watchdog.h | 10 ------ 8 files changed, 48 insertions(+), 106 deletions(-) rename Marlin/{watchdog.cpp => watchdog.pde} (98%) delete mode 100644 watchdog.cpp delete mode 100644 watchdog.h diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 07dd0d8bf1..e56b67128e 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -79,18 +79,6 @@ extern float homing_feedrate[]; extern bool axis_relative_modes[]; -inline void kill() -{ - disable_heater(); - - disable_x(); - disable_y(); - disable_z(); - disable_e(); - - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); - Serial.println("!! Printer halted. kill() called !!"); - while(1); // Wait for reset -} +void kill(); #endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 6a6fb80f43..1c79af6cad 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1278,3 +1278,18 @@ void manage_inactivity(byte debug) { check_axes_activity(); } +void kill() +{ + disable_heater(); + + disable_x(); + disable_y(); + disable_z(); + disable_e(); + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + Serial.println("!! Printer halted. kill() called !!"); + while(1); // Wait for reset +} + + diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 0c5a2e4ce2..14530ca3f6 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -36,6 +36,7 @@ #include "ultralcd.h" #include "streaming.h" #include "temperature.h" +#include "watchdog.h" int target_raw[3] = {0, 0, 0}; @@ -350,6 +351,28 @@ void setWatch() } +void disable_heater() +{ + #if TEMP_0_PIN > -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif +} + // Timer 0 is shared with millies ISR(TIMER0_COMPB_vect) { diff --git a/Marlin/temperature.h b/Marlin/temperature.h index fcc8edb9ea..44d54db141 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -42,7 +42,7 @@ extern int target_raw[3]; extern int current_raw[3]; extern float Kp,Ki,Kd,Kc; #ifdef PIDTEMP - float pid_setpoint = 0.0; + extern float pid_setpoint ; #endif #ifdef WATCHPERIOD extern int watch_raw[3] ; @@ -81,38 +81,9 @@ inline bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current inline bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; inline bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; -inline void disable_heater() -{ - #if TEMP_0_PIN > -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif -} -void setWatch() { - if(isHeatingHotend0()) - { - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; - } - else - { - watchmillis = 0; - } -} +void disable_heater(); +void setWatch(); + #ifdef HEATER_0_USES_THERMISTOR #define HEATERSOURCE 1 #endif diff --git a/Marlin/watchdog.h b/Marlin/watchdog.h index 2577bc1384..7dd31f9f7e 100644 --- a/Marlin/watchdog.h +++ b/Marlin/watchdog.h @@ -1,10 +1,13 @@ #ifndef __WATCHDOGH #define __WATCHDOGH -#ifdef +#include "Configuration.h" +//#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(); +//#endif #endif diff --git a/Marlin/watchdog.cpp b/Marlin/watchdog.pde similarity index 98% rename from Marlin/watchdog.cpp rename to Marlin/watchdog.pde index 0adf9cc7d7..4c677e79e3 100644 --- a/Marlin/watchdog.cpp +++ b/Marlin/watchdog.pde @@ -1,5 +1,5 @@ #ifdef USE_WATCHDOG - +#include "watchdog.h" #include #include diff --git a/watchdog.cpp b/watchdog.cpp deleted file mode 100644 index 0adf9cc7d7..0000000000 --- a/watchdog.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifdef USE_WATCHDOG - -#include -#include - -volatile uint8_t timeout_seconds=0; - -void(* ctrlaltdelete) (void) = 0; //does not work on my atmega2560 - -//Watchdog timer interrupt, called if main program blocks >1sec -ISR(WDT_vect) -{ - if(timeout_seconds++ >= WATCHDOG_TIMEOUT) - { - - #ifdef RESET_MANUAL - LCD_MESSAGE("Please Reset!"); - ECHOLN("echo_: Something is wrong, please turn off the printer."); - #else - LCD_MESSAGE("Timeout, resetting!"); - #endif - //disable watchdog, it will survife reboot. - WDTCSR |= (1< Date: Sun, 6 Nov 2011 17:33:09 +0100 Subject: [PATCH 017/228] overworked the serial responses. Quite difficult, since many texts are Pronterface protocol. --- Marlin/EEPROMwrite.h | 32 ++++++------- Marlin/Makefile | 1 + Marlin/Marlin.h | 10 ++-- Marlin/Marlin.pde | 97 +++++++++++++++++++++------------------ Marlin/motion_control.cpp | 2 +- Marlin/stepper.cpp | 2 +- Marlin/temperature.cpp | 27 ++++------- Marlin/ultralcd.pde | 4 +- Marlin/watchdog.pde | 2 +- 9 files changed, 90 insertions(+), 87 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index ea843344f4..dba2d443e5 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -59,7 +59,7 @@ void StoreSettings() { char ver2[4]=EEPROM_VERSION; i=EEPROM_OFFSET; EEPROM_writeAnything(i,ver2); // validate data - ECHOLN("Settings Stored"); + SERIAL_ECHOLN("Settings Stored"); } @@ -68,7 +68,7 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will char stored_ver[4]; char ver[4]=EEPROM_VERSION; EEPROM_readAnything(i,stored_ver); //read stored version -// ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); +// SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); if ((!def)&&(strncmp(ver,stored_ver,3)==0)) { // version number match EEPROM_readAnything(i,axis_steps_per_unit); EEPROM_readAnything(i,max_feedrate); @@ -87,7 +87,7 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will EEPROM_readAnything(i,Ki); EEPROM_readAnything(i,Kd); - ECHOLN("Stored settings retreived:"); + SERIAL_ECHOLN("Stored settings retreived:"); } else { float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; @@ -105,21 +105,21 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; max_xy_jerk=DEFAULT_XYJERK; max_z_jerk=DEFAULT_ZJERK; - ECHOLN("Using Default settings:"); + SERIAL_ECHOLN("Using Default settings:"); } - ECHOLN("Steps per unit:"); - ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); - ECHOLN("Maximum feedrates (mm/s):"); - ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); - ECHOLN("Maximum Acceleration (mm/s2):"); - ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); - ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); - ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); - ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); - ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); + SERIAL_ECHOLN("Steps per unit:"); + SERIAL_ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); + SERIAL_ECHOLN("Maximum feedrates (mm/s):"); + SERIAL_ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); + SERIAL_ECHOLN("Maximum Acceleration (mm/s2):"); + SERIAL_ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); + SERIAL_ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); + SERIAL_ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); + SERIAL_ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); + SERIAL_ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); #ifdef PIDTEMP - ECHOLN("PID settings:"); - ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); + SERIAL_ECHOLN("PID settings:"); + SERIAL_ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); #endif } diff --git a/Marlin/Makefile b/Marlin/Makefile index f456e3cbd4..0504319f72 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -14,6 +14,7 @@ UPLOAD_SPEED = 115200 UPLOAD_PROTOCOL = stk500v2 BUILD_MCU = atmega2560 BUILD_F_CPU = 16000000L +TERM=bash # getting undefined reference to `__cxa_pure_virtual' #~ [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254180518 Arduino Forum - Makefile] diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index e56b67128e..06f701d034 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -6,9 +6,11 @@ #include #include "fastio.h" - -#define ECHO(x) Serial << "echo: " << x; -#define ECHOLN(x) Serial << "echo: "<- 1 if(root.isOpen()) root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)){ + if (!card.init(SPI_FULL_SPEED,SDSS)) + { //if (!card.init(SPI_HALF_SPEED,SDSS)) - Serial.println("SD init fail"); + SERIAL_ECHOLN("SD init fail"); } else if (!volume.init(&card)) - Serial.println("volume.init failed"); + { + SERIAL_ERRORLN("volume.init failed"); + } else if (!root.openRoot(&volume)) - Serial.println("openRoot failed"); + { + SERIAL_ERRORLN("openRoot failed"); + } else - { + { sdactive = true; - Serial.println("SD card ok"); - } + SERIAL_ECHOLN("SD card ok"); + } #endif //SDSS } @@ -214,7 +221,7 @@ inline void write_command(char *buf){ //Serial.println(begin); file.write(begin); if (file.writeError){ - Serial.println("error writing to file"); + SERIAL_ERRORLN("error writing to file"); } } #endif //SDSUPPORT @@ -227,7 +234,7 @@ void enquecommand(const char *cmd) { //this is dangerous if a mixing of serial and this happsens strcpy(&(cmdbuffer[bufindw][0]),cmd); - Serial.print("en:");Serial.println(cmdbuffer[bufindw]); + SERIAL_ECHOLN("enqueing \""<= filesize){ sdmode = false; - Serial.println("Done printing file"); - 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.println(time); - LCD_MESSAGE(time); - checkautostart(true); + Serial.println("echo: Done printing file"); + stoptime=millis(); + char time[30]; + unsigned long t=(stoptime-starttime)/1000; + int sec,min; + min=t/60; + sec=t%60; + sprintf(time,"echo: %i min, %i sec",min,sec); + Serial.println(time); + LCD_MESSAGE(time); + checkautostart(true); } if(!serial_count) return; //if empty line cmdbuffer[bufindw][serial_count] = 0; //terminate string @@ -721,7 +728,7 @@ inline void process_commands() case 24: //M24 - Start SD print if(sdactive){ sdmode = true; - starttime=millis(); + starttime=millis(); } break; case 25: //M25 - Pause SD print @@ -774,19 +781,19 @@ inline void process_commands() //processed in write to file routine above //savetosd = false; break; - case 30: - { - 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.println(time); - LCD_MESSAGE(time); - } - break; + case 30: //M30 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,"echo: time needed %i min, %i sec",min,sec); + Serial.println(time); + LCD_MESSAGE(time); + } + break; #endif //SDSUPPORT case 42: //M42 -Change pin status via gcode if (code_seen('S')) @@ -847,7 +854,7 @@ inline void process_commands() Serial.println(); #endif #else - Serial.println("No thermistors - no temp"); + Serial.println("echo: No thermistors - no temp"); #endif return; //break; @@ -888,7 +895,8 @@ inline void process_commands() } #endif //TEMP_RESIDENCY_TIME } - LCD_MESSAGE("Marlin ready."); + LCD_MESSAGE("Heating done."); + starttime=millis(); } break; case 190: // M190 - Wait bed for heater to reach target. @@ -1063,9 +1071,9 @@ inline void process_commands() 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; -// ECHOLN("Kp "<<_FLOAT(Kp,2)); -// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); -// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); +// SERIAL_ECHOLN("Kp "<<_FLOAT(Kp,2)); +// SERIAL_ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); +// SERIAL_ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); // temp_iState_min = 0.0; // if (Ki!=0) { @@ -1093,8 +1101,9 @@ inline void process_commands() } } else{ - Serial.println("Unknown command:"); - Serial.println(cmdbuffer[bufindr]); + Serial.print("echo: Unknown command:\""); + Serial.print(cmdbuffer[bufindr]); + Serial.println("\""); } ClearToSend(); @@ -1288,7 +1297,7 @@ void kill() disable_e(); if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); - Serial.println("!! Printer halted. kill() called !!"); + SERIAL_ERRORLN("Printer halted. kill() called !!"); while(1); // Wait for reset } diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index 875531fb78..0b734de4ab 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -35,7 +35,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 { // int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); // plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc - Serial.println("mc_arc"); + SERIAL_ECHOLN("mc_arc."); float center_axis0 = position[axis_0] + offset[axis_0]; float center_axis1 = position[axis_1] + offset[axis_1]; float linear_travel = target[axis_linear] - position[axis_linear]; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index f4bd1289e0..9e5db44a82 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -211,7 +211,7 @@ inline void trapezoid_generator_reset() { // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. ISR(TIMER1_COMPA_vect) { - if(busy){ Serial.print(*(unsigned short *)OCR1A); Serial.println(" BUSY"); + if(busy){ SERIAL_ERRORLN(*(unsigned short *)OCR1A<< " ISR overtaking itself."); return; } // The busy-flag is used to avoid reentering this interrupt diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 14530ca3f6..6971739242 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -142,17 +142,8 @@ CRITICAL_SECTION_END; } #endif //PID_OPENLOOP #ifdef PID_DEBUG - Serial.print(" Input "); - Serial.print(pid_input); - Serial.print(" Output "); - Serial.print(pid_output); - Serial.print(" pTerm "); - Serial.print(pTerm); - Serial.print(" iTerm "); - Serial.print(iTerm); - Serial.print(" dTerm "); - Serial.print(dTerm); - Serial.println(); + SERIAL_ECHOLN(" PIDDEBUG Input "<= maxttemp_0) { target_raw[TEMPSENSOR_HOTEND_0] = 0; analogWrite(HEATER_0_PIN, 0); - Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); + SERIAL_ERRORLN("Temperature extruder 0 switched off. MAXTEMP triggered !!"); kill(); } #endif @@ -497,7 +488,7 @@ ISR(TIMER0_COMPB_vect) target_raw[TEMPSENSOR_HOTEND_1] = 0; if(current_raw[2] >= maxttemp_1) { analogWrite(HEATER_2_PIN, 0); - Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); + SERIAL_ERRORLN("Temperature extruder 1 switched off. MAXTEMP triggered !!"); kill() } #endif @@ -507,7 +498,7 @@ ISR(TIMER0_COMPB_vect) if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { target_raw[TEMPSENSOR_HOTEND_0] = 0; analogWrite(HEATER_0_PIN, 0); - Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); + SERIAL_ERRORLN("Temperature extruder 0 switched off. MINTEMP triggered !!"); kill(); } #endif @@ -517,7 +508,7 @@ ISR(TIMER0_COMPB_vect) if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { target_raw[TEMPSENSOR_HOTEND_1] = 0; analogWrite(HEATER_2_PIN, 0); - Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); + SERIAL_ERRORLN("Temperature extruder 1 switched off. MINTEMP triggered !!"); kill(); } #endif @@ -527,7 +518,7 @@ ISR(TIMER0_COMPB_vect) if(current_raw[1] <= bed_minttemp) { target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); - Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); + SERIAL_ERRORLN("Temperatur heated bed switched off. MINTEMP triggered !!"); kill(); } #endif @@ -537,7 +528,7 @@ ISR(TIMER0_COMPB_vect) if(current_raw[1] >= bed_maxttemp) { target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); - Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); + SERIAL_ERRORLN("Temperature heated bed switched off. MAXTEMP triggered !!"); kill(); } #endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 444020c228..bd256100ab 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1382,7 +1382,7 @@ void MainMenu::showMainMenu() }break; #endif default: - Serial.println('NEVER say never'); + SERIAL_ERRORLN("Something is wrong in the MenuStructure."); break; } } @@ -1414,7 +1414,7 @@ void MainMenu::update() { force_lcd_update=true; oldcardstatus=CARDINSERTED; - //Serial.println("SD CHANGE"); + //Serial.println("echo: SD CHANGE"); if(CARDINSERTED) { initsd(); diff --git a/Marlin/watchdog.pde b/Marlin/watchdog.pde index 4c677e79e3..09d881d1d0 100644 --- a/Marlin/watchdog.pde +++ b/Marlin/watchdog.pde @@ -15,7 +15,7 @@ ISR(WDT_vect) #ifdef RESET_MANUAL LCD_MESSAGE("Please Reset!"); - ECHOLN("echo_: Something is wrong, please turn off the printer."); + SERIAL_ERRORLN("Something is wrong, please turn off the printer."); #else LCD_MESSAGE("Timeout, resetting!"); #endif From 1d171e9e52012c8129dfec2b7f2640e696678f2e Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 19:23:08 +0100 Subject: [PATCH 018/228] reformating and some minor bugs/things found on the way. --- Marlin/Configuration.h | 89 +++-- Marlin/EEPROMwrite.h | 117 +++--- Marlin/Marlin.h | 57 ++- Marlin/Marlin.pde | 781 +++++++++++++++++++------------------ Marlin/motion_control.cpp | 18 +- Marlin/pins.h | 68 ++++ Marlin/planner.cpp | 82 ++-- Marlin/planner.h | 25 +- Marlin/speed_lookuptable.h | 1 + Marlin/stepper.cpp | 402 +++++++++---------- Marlin/stepper.h | 4 +- Marlin/temperature.cpp | 389 +++++++++--------- Marlin/temperature.h | 21 +- Marlin/ultralcd.h | 126 ++---- Marlin/ultralcd.pde | 199 +++++----- Marlin/watchdog.h | 15 +- Marlin/watchdog.pde | 2 +- 17 files changed, 1204 insertions(+), 1192 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 8ad0e22829..b437bfb01f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,5 +1,5 @@ -#ifndef CONFIGURATION_H -#define CONFIGURATION_H +#ifndef __CONFIGURATION_H +#define __CONFIGURATION_H //#define DEBUG_STEPS @@ -118,10 +118,7 @@ const int dropsegments=5; //everything with this number of steps will be ignore #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E //note: on bernhards ultimaker 200 200 12 are working well. #define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds -//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. -//!!!!!!Use only if you know that your printer works at the maximum declared speeds. -// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze -#define TRAVELING_AT_MAXSPEED + #define AXIS_RELATIVE_MODES {false, false, false, false} #define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) @@ -177,41 +174,50 @@ const int dropsegments=5; //everything with this number of steps will be ignore //#define_HEATER_1_MAXTEMP 275 //#define BED_MAXTEMP 150 - - - - - - +/// PID settings: +// Uncomment the following line to enable PID support. + #define PIDTEMP #ifdef PIDTEMP - /// PID settings: - // Uncomment the following line to enable PID support. - //#define SMOOTHING - //#define SMOOTHFACTOR 5.0 - //float current_raw_average=0; - #define K1 0.95 //smoothing of the PID //#define PID_DEBUG // Sends debug data to the serial port. //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_MAX 255 // limits current to nozzle - #define PID_INTEGRAL_DRIVE_MAX 255 - #define PID_dT 0.1 - //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 + + #define PID_MAX 255 // limits current to nozzle; 255=full current + #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term + #define K1 0.95 //smoothing factor withing the PID + #define PID_dT 0.1 //sampling period of the PID + + //To develop some PID settings for your machine, you can initiall follow + // the Ziegler-Nichols method. + // set Ki and Kd to zero. + // heat with a defined Kp and see if the temperature stabilizes + // ideally you do this graphically with repg. + // the PID_CRITIAL_GAIN should be the Kp at which temperature oscillatins are not dampned out/decreas in amplitutde + // PID_SWING_AT_CRITIAL is the time for a full period of the oscillations at the critical Gain + // usually further manual tunine is necessary. #define PID_CRITIAL_GAIN 3000 #define PID_SWING_AT_CRITIAL 45 //seconds - #define PIDIADD 5 - /* - //PID according to Ziegler-Nichols method - float Kp = 0.6*PID_CRITIAL_GAIN; - float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; - float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; - */ - //PI according to Ziegler-Nichols method - #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) - #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (0) + #define PID_PI //no differentail term + //#define PID_PID //normal PID + + #ifdef PID_PID + //PID according to Ziegler-Nichols method + #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) + #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) + #endif + + #ifdef PID_PI + //PI according to Ziegler-Nichols method + #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) + #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (0) + #endif + + // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. + // if Kc is choosen well, the additional required power due to increased melting should be compensated. #define PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) @@ -228,22 +234,21 @@ const int dropsegments=5; //everything with this number of steps will be ignore //#define ADVANCE #ifdef ADVANCE -#define EXTRUDER_ADVANCE_K .3 + #define EXTRUDER_ADVANCE_K .3 -#define D_FILAMENT 1.7 -#define STEPS_MM_E 65 -#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) -#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) + #define D_FILAMENT 1.7 + #define STEPS_MM_E 65 + #define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) + #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) #endif // ADVANCE -// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 -#if defined SDSUPPORT // The number of linear motions that can be in the plan at any give time. +// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ringbuffering. +#if defined SDSUPPORT #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller #else #define BLOCK_BUFFER_SIZE 16 // maximize block buffer #endif - -#endif +#endif //__CONFIGURATION_H diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index dba2d443e5..db9f2fde17 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -1,39 +1,42 @@ #ifndef __EEPROMH #define __EEPROMH + +#include "Marlin.h" #include "planner.h" #include "temperature.h" #include -#include "Marlin.h" -#include "streaming.h" -//====================================================================================== template int EEPROM_writeAnything(int &ee, const T& value) { - const byte* p = (const byte*)(const void*)&value; - int i; - for (i = 0; i < (int)sizeof(value); i++) - EEPROM.write(ee++, *p++); - return i; + const byte* p = (const byte*)(const void*)&value; + int i; + for (i = 0; i < (int)sizeof(value); i++) + EEPROM.write(ee++, *p++); + return i; } -//====================================================================================== + template int EEPROM_readAnything(int &ee, T& value) { - byte* p = (byte*)(void*)&value; - int i; - for (i = 0; i < (int)sizeof(value); i++) - *p++ = EEPROM.read(ee++); - return i; + byte* p = (byte*)(void*)&value; + int i; + for (i = 0; i < (int)sizeof(value); i++) + *p++ = EEPROM.read(ee++); + return i; } //====================================================================================== #define EEPROM_OFFSET 100 -#define EEPROM_VERSION "V04" // IMPORTANT: Whenever there are changes made to the variables stored in EEPROM - // in the functions below, also increment the version number. This makes sure that - // the default values are used whenever there is a change to the data, to prevent - // wrong data being written to the variables. - // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. -void StoreSettings() { + +// IMPORTANT: Whenever there are changes made to the variables stored in EEPROM +// in the functions below, also increment the version number. This makes sure that +// the default values are used whenever there is a change to the data, to prevent +// wrong data being written to the variables. +// ALSO: always make sure the variables in the Store and retrieve sections are in the same order. +#define EEPROM_VERSION "V04" + +void StoreSettings() +{ char ver[4]= "000"; int i=EEPROM_OFFSET; EEPROM_writeAnything(i,ver); // invalidate data first @@ -48,52 +51,55 @@ void StoreSettings() { EEPROM_writeAnything(i,max_xy_jerk); EEPROM_writeAnything(i,max_z_jerk); #ifdef PIDTEMP - EEPROM_writeAnything(i,Kp); - EEPROM_writeAnything(i,Ki); - EEPROM_writeAnything(i,Kd); -#else - EEPROM_writeAnything(i,3000); - EEPROM_writeAnything(i,0); - EEPROM_writeAnything(i,0); -#endif + EEPROM_writeAnything(i,Kp); + EEPROM_writeAnything(i,Ki); + EEPROM_writeAnything(i,Kd); + #else + EEPROM_writeAnything(i,3000); + EEPROM_writeAnything(i,0); + EEPROM_writeAnything(i,0); + #endif char ver2[4]=EEPROM_VERSION; i=EEPROM_OFFSET; EEPROM_writeAnything(i,ver2); // validate data - SERIAL_ECHOLN("Settings Stored"); - + SERIAL_ECHOLN("Settings Stored"); } -void RetrieveSettings(bool def=false){ // if def=true, the default values will be used +void RetrieveSettings(bool def=false) +{ // if def=true, the default values will be used int i=EEPROM_OFFSET; char stored_ver[4]; char ver[4]=EEPROM_VERSION; EEPROM_readAnything(i,stored_ver); //read stored version -// SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); - if ((!def)&&(strncmp(ver,stored_ver,3)==0)) { // version number match - EEPROM_readAnything(i,axis_steps_per_unit); - EEPROM_readAnything(i,max_feedrate); - EEPROM_readAnything(i,max_acceleration_units_per_sq_second); - EEPROM_readAnything(i,acceleration); - EEPROM_readAnything(i,retract_acceleration); - EEPROM_readAnything(i,minimumfeedrate); - EEPROM_readAnything(i,mintravelfeedrate); - EEPROM_readAnything(i,minsegmenttime); - EEPROM_readAnything(i,max_xy_jerk); - EEPROM_readAnything(i,max_z_jerk); -#ifndef PIDTEMP + // SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); + if ((!def)&&(strncmp(ver,stored_ver,3)==0)) + { // version number match + EEPROM_readAnything(i,axis_steps_per_unit); + EEPROM_readAnything(i,max_feedrate); + EEPROM_readAnything(i,max_acceleration_units_per_sq_second); + EEPROM_readAnything(i,acceleration); + EEPROM_readAnything(i,retract_acceleration); + EEPROM_readAnything(i,minimumfeedrate); + EEPROM_readAnything(i,mintravelfeedrate); + EEPROM_readAnything(i,minsegmenttime); + EEPROM_readAnything(i,max_xy_jerk); + EEPROM_readAnything(i,max_z_jerk); + #ifndef PIDTEMP float Kp,Ki,Kd; -#endif - EEPROM_readAnything(i,Kp); - EEPROM_readAnything(i,Ki); - EEPROM_readAnything(i,Kd); + #endif + EEPROM_readAnything(i,Kp); + EEPROM_readAnything(i,Ki); + EEPROM_readAnything(i,Kd); - SERIAL_ECHOLN("Stored settings retreived:"); + SERIAL_ECHOLN("Stored settings retreived:"); } - else { + else + { float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; float tmp2[]=DEFAULT_MAX_FEEDRATE; long tmp3[]=DEFAULT_MAX_ACCELERATION; - for (int i=0;i<4;i++) { + for (short i=0;i<4;i++) + { axis_steps_per_unit[i]=tmp1[i]; max_feedrate[i]=tmp2[i]; max_acceleration_units_per_sq_second[i]=tmp3[i]; @@ -117,11 +123,10 @@ void RetrieveSettings(bool def=false){ // if def=true, the default values will SERIAL_ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); SERIAL_ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); SERIAL_ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); -#ifdef PIDTEMP - SERIAL_ECHOLN("PID settings:"); - SERIAL_ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); -#endif - + #ifdef PIDTEMP + SERIAL_ECHOLN("PID settings:"); + SERIAL_ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); + #endif } #endif diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 06f701d034..21eadeeb5e 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -18,41 +18,39 @@ void process_commands(); void manage_inactivity(byte debug); #if X_ENABLE_PIN > -1 -#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) -#define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) + #define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) + #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) #else -#define enable_x() ; -#define disable_x() ; + #define enable_x() ; + #define disable_x() ; #endif + #if Y_ENABLE_PIN > -1 -#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) -#define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) + #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) + #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) #else -#define enable_y() ; -#define disable_y() ; + #define enable_y() ; + #define disable_y() ; #endif + #if Z_ENABLE_PIN > -1 -#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON) -#define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON) + #define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON) + #define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON) #else -#define enable_z() ; -#define disable_z() ; + #define enable_z() ; + #define disable_z() ; #endif #if E_ENABLE_PIN > -1 - - #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) - #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) - + #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) + #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) #else -#define enable_e() ; -#define disable_e() ; + #define enable_e() ; + #define disable_e() ; #endif -#define X_AXIS 0 -#define Y_AXIS 1 -#define Z_AXIS 2 -#define E_AXIS 3 +enum AxisEnum {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, E_AXIS=3}; + void FlushSerialRequestResend(); void ClearToSend(); @@ -61,26 +59,15 @@ void get_coordinates(); void prepare_move(); void kill(); -//void check_axes_activity(); -//void plan_init(); -//void st_init(); -//void tp_init(); -//void plan_buffer_line(float x, float y, float z, float e, float feed_rate); -//void plan_set_position(float x, float y, float z, float e); -//void st_wake_up(); -//void st_synchronize(); void enquecommand(const char *cmd); //put an ascii command at the end of the current buffer. #ifndef CRITICAL_SECTION_START -#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); -#define CRITICAL_SECTION_END SREG = _sreg; + #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); + #define CRITICAL_SECTION_END SREG = _sreg; #endif //CRITICAL_SECTION_START extern float homing_feedrate[]; extern bool axis_relative_modes[]; - -void kill(); - #endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index b449bb0692..6c2c6c87a4 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -25,6 +25,7 @@ http://reprap.org/pipermail/reprap-dev/2011-May/003323.html */ +#include #include "EEPROMwrite.h" #include "fastio.h" #include "Configuration.h" @@ -37,14 +38,11 @@ #include "temperature.h" #include "motion_control.h" -#ifdef SIMPLE_LCD - #include "Simplelcd.h" -#endif char version_string[] = "1.0.0 Alpha 1"; #ifdef SDSUPPORT -#include "SdFat.h" + #include "SdFat.h" #endif //SDSUPPORT @@ -109,12 +107,9 @@ char version_string[] = "1.0.0 Alpha 1"; //Stepper Movement Variables -char axis_codes[NUM_AXIS] = { - 'X', 'Y', 'Z', 'E'}; -float destination[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -float current_position[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; +const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; +float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; +float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; float offset[3] = {0.0, 0.0, 0.0}; bool home_all_axis = true; float feedrate = 1500.0, next_feedrate, saved_feedrate; @@ -131,6 +126,7 @@ uint8_t fanpwm=0; volatile int feedmultiply=100; //100->1 200->2 int saved_feedmultiply; volatile bool feedmultiplychanged=false; + // comm variables #define MAX_CMD_SIZE 96 #define BUFSIZE 4 @@ -146,13 +142,10 @@ boolean comment_mode = false; char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc extern float HeaterPower; -#include "EEPROM.h" - const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 float tt = 0, bt = 0; - //Inactivity shutdown variables unsigned long previous_millis_cmd = 0; unsigned long max_inactive_time = 0; @@ -161,73 +154,81 @@ unsigned long stepper_inactive_time = 0; unsigned long starttime=0; unsigned long stoptime=0; #ifdef SDSUPPORT -Sd2Card card; -SdVolume volume; -SdFile root; -SdFile file; -uint32_t filesize = 0; -uint32_t sdpos = 0; -bool sdmode = false; -bool sdactive = false; -bool savetosd = false; -int16_t n; -unsigned long autostart_atmillis=0; + Sd2Card card; + SdVolume volume; + SdFile root; + SdFile file; + uint32_t filesize = 0; + uint32_t sdpos = 0; + bool sdmode = false; + bool sdactive = false; + bool savetosd = false; + int16_t n; + unsigned long autostart_atmillis=0; + + bool autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. -void initsd() -{ - sdactive = false; -#if SDSS >- 1 - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)) - { - //if (!card.init(SPI_HALF_SPEED,SDSS)) - SERIAL_ECHOLN("SD init fail"); - } - else if (!volume.init(&card)) - { - SERIAL_ERRORLN("volume.init failed"); - } - else if (!root.openRoot(&volume)) - { - SERIAL_ERRORLN("openRoot failed"); - } - else - { - sdactive = true; - SERIAL_ECHOLN("SD card ok"); - } -#endif //SDSS -} -void quickinitsd(){ - sdactive=false; - autostart_atmillis=millis()+5000; -} - -inline void write_command(char *buf){ - char* begin = buf; - char* npos = 0; - char* end = buf + strlen(buf) - 1; - - file.writeError = false; - if((npos = strchr(buf, 'N')) != NULL){ - begin = strchr(npos, ' ') + 1; - end = strchr(npos, '*') - 1; + void initsd() + { + sdactive = false; + #if SDSS >- 1 + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)) + { + //if (!card.init(SPI_HALF_SPEED,SDSS)) + SERIAL_ECHOLN("SD init fail"); + } + else if (!volume.init(&card)) + { + SERIAL_ERRORLN("volume.init failed"); + } + else if (!root.openRoot(&volume)) + { + SERIAL_ERRORLN("openRoot failed"); + } + else + { + sdactive = true; + SERIAL_ECHOLN("SD card ok"); + } + #endif //SDSS } - end[1] = '\r'; - end[2] = '\n'; - end[3] = '\0'; - //Serial.println(begin); - file.write(begin); - if (file.writeError){ - SERIAL_ERRORLN("error writing to file"); + + void quickinitsd() + { + sdactive=false; + autostart_atmillis=millis()+5000; + } + + inline void write_command(char *buf) + { + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL) + { + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + file.write(begin); + if (file.writeError) + { + SERIAL_ERRORLN("error writing to file"); + } } -} #endif //SDSUPPORT -///adds an command to the main command buffer +//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) @@ -242,106 +243,93 @@ void enquecommand(const char *cmd) void setup() { - Serial.begin(BAUDRATE); SERIAL_ECHOLN("Marlin "< -1 - SET_OUTPUT(SDPOWER); - WRITE(SDPOWER,HIGH); -#endif //SDPOWER - quickinitsd(); - -#endif //SDSUPPORT + #ifdef SDSUPPORT + //power to SD reader + #if SDPOWER > -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); + #endif //SDPOWER + quickinitsd(); + #endif //SDSUPPORT + plan_init(); // Initialize planner; st_init(); // Initialize stepper; tp_init(); // Initialize temperature loop - //checkautostart(); } #ifdef SDSUPPORT -bool autostart_stilltocheck=true; - void checkautostart(bool force) { - //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) + { + for(int i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; - bool found=false; - while (root.readDir(p) > 0) - { - for(int i=0;i<(int)strlen((char*)p.name);i++) - p.name[i]=tolower(p.name[i]); - //Serial.print((char*)p.name); - //Serial.print(" "); - //Serial.println(autoname); - if(p.name[9]!='~') //skip safety copies - if(strncmp((char*)p.name,autoname,5)==0) - { - char cmd[30]; - - sprintf(cmd,"M23 %s",autoname); - //sprintf(cmd,"M115"); - //enquecommand("G92 Z0"); - //enquecommand("G1 Z10 F2000"); - //enquecommand("G28 X-105 Y-105"); - enquecommand(cmd); - enquecommand("M24"); - found=true; - - } - } - if(!found) - lastnr=-1; - else - lastnr++; - -} -#else - -inline void checkautostart(bool x) -{ + sprintf(cmd,"M23 %s",autoname); + //sprintf(cmd,"M115"); + //enquecommand("G92 Z0"); + //enquecommand("G1 Z10 F2000"); + //enquecommand("G28 X-105 Y-105"); + enquecommand(cmd); + enquecommand("M24"); + found=true; + } + } + if(!found) + lastnr=-1; + else + lastnr++; } +#else //NO SD SUPORT + inline void checkautostart(bool x){} #endif @@ -349,28 +337,32 @@ void loop() { if(buflen<3) get_command(); - checkautostart(false); + checkautostart(false); if(buflen) { -#ifdef SDSUPPORT - if(savetosd){ - if(strstr(cmdbuffer[bufindr],"M29") == NULL){ - write_command(cmdbuffer[bufindr]); - Serial.println("ok"); + #ifdef SDSUPPORT + if(savetosd) + { + if(strstr(cmdbuffer[bufindr],"M29") == NULL) + { + write_command(cmdbuffer[bufindr]); + Serial.println("ok"); + } + else + { + file.sync(); + file.close(); + savetosd = false; + Serial.println("Done saving file."); + } } - else{ - file.sync(); - file.close(); - savetosd = false; - Serial.println("Done saving file."); + else + { + process_commands(); } - } - else{ + #else process_commands(); - } -#else - process_commands(); -#endif //SDSUPPORT + #endif //SDSUPPORT buflen = (buflen-1); bufindr = (bufindr + 1)%BUFSIZE; } @@ -449,10 +441,10 @@ inline void get_command() case 1: case 2: case 3: -#ifdef SDSUPPORT + #ifdef SDSUPPORT if(savetosd) break; -#endif //SDSUPPORT + #endif //SDSUPPORT Serial.println("ok"); break; default: @@ -473,7 +465,7 @@ inline void get_command() if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; } } -#ifdef SDSUPPORT + #ifdef SDSUPPORT if(!sdmode || serial_count!=0){ return; } @@ -486,18 +478,19 @@ inline void get_command() if(sdpos >= filesize){ sdmode = false; Serial.println("echo: Done printing file"); - stoptime=millis(); - char time[30]; - unsigned long t=(stoptime-starttime)/1000; - int sec,min; - min=t/60; - sec=t%60; - sprintf(time,"echo: %i min, %i sec",min,sec); - Serial.println(time); - LCD_MESSAGE(time); - checkautostart(true); + stoptime=millis(); + char time[30]; + unsigned long t=(stoptime-starttime)/1000; + int sec,min; + min=t/60; + sec=t%60; + sprintf(time,"echo: %i min, %i sec",min,sec); + Serial.println(time); + LCD_MESSAGE(time); + checkautostart(true); } - if(!serial_count) return; //if empty line + if(!serial_count) + return; //if empty line cmdbuffer[bufindw][serial_count] = 0; //terminate string if(!comment_mode){ fromsd[bufindw] = true; @@ -513,20 +506,23 @@ inline void get_command() if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; } } -#endif //SDSUPPORT + #endif //SDSUPPORT } -inline float code_value() { +inline float code_value() +{ return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); } -inline long code_value_long() { +inline long code_value_long() +{ return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); } -inline bool code_seen(char code_string[]) { +inline bool code_seen(char code_string[]) //Return True if the string was found +{ return (strstr(cmdbuffer[bufindr], code_string) != NULL); -} //Return True if the string was found +} inline bool code_seen(char code) { @@ -579,10 +575,10 @@ inline void process_commands() 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((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { + if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) + { if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ // st_synchronize(); current_position[X_AXIS] = 0; @@ -689,7 +685,7 @@ inline void process_commands() switch( (int)code_value() ) { -#ifdef SDSUPPORT + #ifdef SDSUPPORT case 20: // M20 - list SD card Serial.println("Begin file list"); @@ -781,6 +777,8 @@ inline void process_commands() //processed in write to file routine above //savetosd = false; break; + #endif //SDSUPPORT + case 30: //M30 take time since the start of the SD print or an M109 command { stoptime=millis(); @@ -794,133 +792,134 @@ inline void process_commands() LCD_MESSAGE(time); } break; -#endif //SDSUPPORT - case 42: //M42 -Change pin status via gcode - if (code_seen('S')) + 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_status = code_value(); - if (code_seen('P') && pin_status >= 0 && pin_status <= 255) + int pin_number = code_value(); + for(int i = 0; i < (int)sizeof(sensitive_pins); i++) { - int pin_number = code_value(); - for(int i = 0; i < (int)sizeof(sensitive_pins); i++) + if (sensitive_pins[i] == pin_number) { - 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); + 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 (code_seen('S')) setTargetHotend0(code_value()); - setWatch(); - break; - case 140: // M140 set bed temp - if (code_seen('S')) setTargetBed(code_value()); - break; - case 105: // M105 - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = degHotend0(); - #endif - #if TEMP_1_PIN > -1 - bt = degBed(); - #endif - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - Serial.print("ok T:"); - Serial.print(tt); -// Serial.print(", raw:"); -// Serial.print(current_raw); - #if TEMP_1_PIN > -1 -#ifdef PIDTEMP + } + break; + case 104: // M104 + if (code_seen('S')) setTargetHotend0(code_value()); + setWatch(); + break; + case 140: // M140 set bed temp + if (code_seen('S')) setTargetBed(code_value()); + break; + case 105: // M105 + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + tt = degHotend0(); + #endif + #if TEMP_1_PIN > -1 + bt = degBed(); + #endif + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + Serial.print("ok T:"); + Serial.print(tt); + #if TEMP_1_PIN > -1 + #ifdef PIDTEMP Serial.print(" B:"); #if TEMP_1_PIN > -1 - Serial.println(bt); + Serial.println(bt); #else - Serial.println(HeaterPower); + Serial.println(HeaterPower); #endif -#else + #else //not PIDTEMP Serial.println(); -#endif - #else + #endif //PIDTEMP + #else Serial.println(); - #endif + #endif //TEMP_1_PIN #else Serial.println("echo: No thermistors - no temp"); - #endif - return; - //break; - case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGE("Heating..."); - if (code_seen('S')) setTargetHotend0(code_value()); - - setWatch(); - codenum = millis(); - - /* See if we are heating up or cooling down */ - bool target_direction = isHeatingHotend0(); // 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((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) || - (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { - #else - while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) ) { - #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down - Serial.print("T:"); - Serial.println( degHotend0() ); - codenum = millis(); - } - manage_heater(); - 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 && !isHeatingHotend0()) || - (residencyStart == -1 && !target_direction && !isCoolingHotend0()) || - (residencyStart > -1 && labs(degHotend0() - degTargetHotend0()) > TEMP_HYSTERESIS) ) { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGE("Heating done."); - starttime=millis(); - } - break; - case 190: // M190 - Wait bed for heater to reach target. - #if TEMP_1_PIN > -1 - 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=degHotend0(); - Serial.print("T:"); - Serial.println( tt ); - Serial.print("ok T:"); - Serial.print( tt ); - Serial.print(" B:"); - Serial.println( degBed() ); - codenum = millis(); - } - manage_heater(); - } #endif + return; break; -#if FAN_PIN > -1 + case 109: + {// M109 - Wait for extruder heater to reach target. + LCD_MESSAGE("Heating..."); + if (code_seen('S')) setTargetHotend0(code_value()); + + setWatch(); + codenum = millis(); + + /* See if we are heating up or cooling down */ + bool target_direction = isHeatingHotend0(); // 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((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + #else + while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) ) { + #endif //TEMP_RESIDENCY_TIME + if( (millis() - codenum) > 1000 ) + { //Print Temp Reading every 1 second while heating up/cooling down + Serial.print("T:"); + Serial.println( degHotend0() ); + codenum = millis(); + } + manage_heater(); + 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 && !isHeatingHotend0()) || + (residencyStart == -1 && !target_direction && !isCoolingHotend0()) || + (residencyStart > -1 && labs(degHotend0() - degTargetHotend0()) > TEMP_HYSTERESIS) ) + { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGE("Heating done."); + starttime=millis(); + } + break; + case 190: // M190 - Wait bed for heater to reach target. + #if TEMP_1_PIN > -1 + 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=degHotend0(); + Serial.print("T:"); + Serial.println( tt ); + Serial.print("ok T:"); + Serial.print( tt ); + Serial.print(" B:"); + Serial.println( degBed() ); + codenum = millis(); + } + manage_heater(); + } + #endif + break; + + #if FAN_PIN > -1 case 106: //M106 Fan On if (code_seen('S')){ WRITE(FAN_PIN,HIGH); @@ -937,27 +936,29 @@ inline void process_commands() WRITE(FAN_PIN,LOW); analogWrite(FAN_PIN, 0); break; -#endif -#if (PS_ON_PIN > -1) + #endif //FAN_PIN + + #if (PS_ON_PIN > -1) case 80: // M80 - ATX Power On SET_OUTPUT(PS_ON_PIN); //GND break; case 81: // M81 - ATX Power Off SET_INPUT(PS_ON_PIN); //Floating break; -#endif + #endif case 82: axis_relative_modes[3] = false; break; case 83: axis_relative_modes[3] = true; break; - case 18: + case 18: //compatibility case 84: if(code_seen('S')){ stepper_inactive_time = code_value() * 1000; } - else{ + else + { st_synchronize(); disable_x(); disable_y(); @@ -970,13 +971,14 @@ inline void process_commands() max_inactive_time = code_value() * 1000; break; case 92: // M92 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); + for(int i=0; i < NUM_AXIS; i++) + { + if(code_seen(axis_codes[i])) + axis_steps_per_unit[i] = code_value(); } - break; case 115: // M115 - Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); + Serial.println("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); break; case 114: // M114 Serial.print("X:"); @@ -998,45 +1000,46 @@ inline void process_commands() Serial.println(""); break; case 119: // M119 -#if (X_MIN_PIN > -1) - Serial.print("x_min:"); - Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (X_MAX_PIN > -1) - Serial.print("x_max:"); - Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MIN_PIN > -1) - Serial.print("y_min:"); - Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MAX_PIN > -1) - Serial.print("y_max:"); - Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MIN_PIN > -1) - Serial.print("z_min:"); - Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MAX_PIN > -1) - Serial.print("z_max:"); - Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif + #if (X_MIN_PIN > -1) + Serial.print("x_min:"); + Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + #endif + #if (X_MAX_PIN > -1) + Serial.print("x_max:"); + Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + #endif + #if (Y_MIN_PIN > -1) + Serial.print("y_min:"); + Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + #endif + #if (Y_MAX_PIN > -1) + Serial.print("y_max:"); + Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + #endif + #if (Z_MIN_PIN > -1) + Serial.print("z_min:"); + Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + #endif + #if (Z_MAX_PIN > -1) + Serial.print("z_max:"); + Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + #endif Serial.println(""); break; //TODO: update for all axis, use for loop case 201: // M201 - for(int i=0; i < NUM_AXIS; i++) { + for(int i=0; i < NUM_AXIS; i++) + { if(code_seen(axis_codes[i])) axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; } break; -#if 0 // Not used for Sprinter/grbl gen6 + #if 0 // Not used for Sprinter/grbl gen6 case 202: // M202 for(int 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 + #endif case 203: // M203 max feedrate mm/sec for(int i=0; i < NUM_AXIS; i++) { if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; @@ -1048,59 +1051,52 @@ inline void process_commands() 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 + 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()*60 ; + if(code_seen('T')) mintravelfeedrate = code_value()*60 ; + if(code_seen('B')) minsegmenttime = code_value() ; + if(code_seen('X')) max_xy_jerk = code_value()*60 ; + if(code_seen('Z')) max_z_jerk = code_value()*60 ; + } + break; + case 220: // M220 S- set speed factor override percentage + { + if(code_seen('S')) { - if(code_seen('S')) minimumfeedrate = code_value()*60 ; - if(code_seen('T')) mintravelfeedrate = code_value()*60 ; - if(code_seen('B')) minsegmenttime = code_value() ; - if(code_seen('X')) max_xy_jerk = code_value()*60 ; - if(code_seen('Z')) max_z_jerk = code_value()*60 ; + feedmultiply = code_value() ; + feedmultiplychanged=true; } - break; - case 220: // M220 S- set speed factor override percentage - { - if(code_seen('S')) - { - feedmultiply = code_value() ; - feedmultiplychanged=true; - } - } - break; -#ifdef PIDTEMP + } + 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; -// SERIAL_ECHOLN("Kp "<<_FLOAT(Kp,2)); -// SERIAL_ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); -// SERIAL_ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); - -// temp_iState_min = 0.0; -// if (Ki!=0) { -// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); -// } -// else temp_iState_max = 1.0e10; - break; -#endif //PIDTEMP - case 500: // Store settings in EEPROM - { - StoreSettings(); - } - break; - case 501: // Read settings from EEPROM - { - RetrieveSettings(); - } - break; - case 502: // Revert to default settings - { - RetrieveSettings(true); - } break; + #endif //PIDTEMP + case 500: // Store settings in EEPROM + { + StoreSettings(); + } + break; + case 501: // Read settings from EEPROM + { + RetrieveSettings(); + } + break; + case 502: // Revert to default settings + { + RetrieveSettings(true); + } + break; } } - else{ + else + { Serial.print("echo: Unknown command:\""); Serial.print(cmdbuffer[bufindr]); Serial.println("\""); @@ -1121,10 +1117,10 @@ void FlushSerialRequestResend() void ClearToSend() { previous_millis_cmd = millis(); -#ifdef SDSUPPORT + #ifdef SDSUPPORT if(fromsd[bufindr]) return; -#endif //SDSUPPORT + #endif //SDSUPPORT Serial.println("ok"); } @@ -1132,7 +1128,7 @@ inline void get_coordinates() { for(int 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]; - else destination[i] = current_position[i]; //Are these else lines really needed? + else destination[i] = current_position[i]; //Are these else lines really needed? } if(code_seen('F')) { next_feedrate = code_value(); @@ -1276,14 +1272,19 @@ void prepare_arc_move(char isclockwise) { -void manage_inactivity(byte debug) { - if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); - if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } +void manage_inactivity(byte debug) +{ + if( (millis()-previous_millis_cmd) > max_inactive_time ) + if(max_inactive_time) + kill(); + if( (millis()-previous_millis_cmd) > stepper_inactive_time ) + if(stepper_inactive_time) + { + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } check_axes_activity(); } diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index 0b734de4ab..75396143aa 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -33,8 +33,8 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise) { -// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); -// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc + // int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); + // plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc SERIAL_ECHOLN("mc_arc."); float center_axis0 = position[axis_0] + offset[axis_0]; float center_axis1 = position[axis_1] + offset[axis_1]; @@ -52,12 +52,12 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel)); if (millimeters_of_travel == 0.0) { return; } uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT); -/* - // Multiply inverse feed_rate to compensate for the fact that this movement is approximated - // by a number of discrete segments. The inverse feed_rate should be correct for the sum of - // all segments. - if (invert_feed_rate) { feed_rate *= segments; } -*/ + /* + // Multiply inverse feed_rate to compensate for the fact that this movement is approximated + // by a number of discrete segments. The inverse feed_rate should be correct for the sum of + // all segments. + if (invert_feed_rate) { feed_rate *= segments; } + */ float theta_per_segment = angular_travel/segments; float linear_per_segment = linear_travel/segments; @@ -128,6 +128,6 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 // Ensure last segment arrives at target location. plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate); -// plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled); + // plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled); } diff --git a/Marlin/pins.h b/Marlin/pins.h index e9ebd4412c..4df1bd0e3b 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -557,6 +557,74 @@ #define FAN_PIN 7 #define PS_ON_PIN 12 #define KILL_PIN -1 + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + //buttons are attached to a shift register + #define SHIFT_CLK 38 + #define SHIFT_LD 42 + #define SHIFT_OUT 40 + #define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 5 + #define LCD_PINS_D4 6 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 20 + #define LCD_PINS_D7 19 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 14f0bb1043..b4271bab35 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -83,7 +83,7 @@ static volatile unsigned char block_buffer_head; // Index of the next static volatile unsigned char block_buffer_tail; // Index of the block to process now // The current position of the tool in absolute steps - long position[4]; +long position[4]; #define ONE_MINUTE_OF_MICROSECONDS 60000000.0 @@ -123,10 +123,10 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit long initial_rate = ceil(block->nominal_rate*entry_factor); long final_rate = ceil(block->nominal_rate*exit_factor); -#ifdef ADVANCE - long initial_advance = block->advance*entry_factor*entry_factor; - long final_advance = block->advance*exit_factor*exit_factor; -#endif // ADVANCE + #ifdef ADVANCE + long initial_advance = block->advance*entry_factor*entry_factor; + long final_advance = block->advance*exit_factor*exit_factor; + #endif // ADVANCE // Limit minimal step rate (Otherwise the timer will overflow.) if(initial_rate <120) initial_rate=120; @@ -155,10 +155,10 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit block->decelerate_after = decelerate_after; block->initial_rate = initial_rate; block->final_rate = final_rate; -#ifdef ADVANCE - block->initial_advance = initial_advance; - block->final_advance = final_advance; -#endif //ADVANCE + #ifdef ADVANCE + block->initial_advance = initial_advance; + block->final_advance = final_advance; + #endif //ADVANCE } CRITICAL_SECTION_END; } @@ -166,18 +166,15 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit // Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the // acceleration within the allotted distance. inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { - return( - sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance) - ); + return sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance); } // "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. // This method will calculate the junction jerk as the euclidean distance between the nominal // velocities of the respective blocks. inline float junction_jerk(block_t *before, block_t *after) { - return(sqrt( - pow((before->speed_x-after->speed_x), 2)+ - pow((before->speed_y-after->speed_y), 2))); + return sqrt( + pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); } // Return the safe speed which is max_jerk/2, e.g. the @@ -185,8 +182,10 @@ inline float junction_jerk(block_t *before, block_t *after) { float safe_speed(block_t *block) { float safe_speed; safe_speed = max_xy_jerk/2; - if(abs(block->speed_z) > max_z_jerk/2) safe_speed = max_z_jerk/2; - if (safe_speed > block->nominal_speed) safe_speed = block->nominal_speed; + if(abs(block->speed_z) > max_z_jerk/2) + safe_speed = max_z_jerk/2; + if (safe_speed > block->nominal_speed) + safe_speed = block->nominal_speed; return safe_speed; } @@ -379,9 +378,8 @@ void check_axes_activity() { // Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in // mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration // calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { - - +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate) +{ // Calculate the buffer head after we push this byte int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); @@ -469,11 +467,8 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { // Limit speed per axis float speed_factor = 1; //factor <=1 do decrease speed if(abs(block->speed_x) > max_feedrate[X_AXIS]) { - //// [ErikDeBruijn] IS THIS THE BUG WE'RE LOOING FOR???? - //// [bernhard] No its not, according to Zalm. - //// the if would always be true, since tmp_speedfactor <=0 due the inial if, so its safe to set. the next lines actually compare. speed_factor = max_feedrate[X_AXIS] / abs(block->speed_x); - //if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; + //if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; /is not need here because auf the init above } if(abs(block->speed_y) > max_feedrate[Y_AXIS]){ float tmp_speed_factor = max_feedrate[Y_AXIS] / abs(block->speed_y); @@ -495,7 +490,8 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { block->nominal_speed = block->millimeters * multiplier; block->nominal_rate = ceil(block->step_event_count * multiplier / 60); - if(block->nominal_rate < 120) block->nominal_rate = 120; + if(block->nominal_rate < 120) + block->nominal_rate = 120; block->entry_speed = safe_speed(block); // Compute the acceleration rate for the trapezoid generator. @@ -527,25 +523,25 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { block->acceleration = block->acceleration_st * travel_per_step; block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); -#ifdef ADVANCE - // Calculate advance rate - if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { - block->advance_rate = 0; - block->advance = 0; - } - else { - long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); - float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; - block->advance = advance; - if(acc_dist == 0) { + #ifdef ADVANCE + // Calculate advance rate + if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { block->advance_rate = 0; - } - else { - block->advance_rate = advance / (float)acc_dist; + block->advance = 0; } - } -#endif // ADVANCE + else { + long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); + float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * + (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; + block->advance = advance; + if(acc_dist == 0) { + block->advance_rate = 0; + } + else { + block->advance_rate = advance / (float)acc_dist; + } + } + #endif // ADVANCE // compute a preliminary conservative acceleration trapezoid float safespeed = safe_speed(block); @@ -576,7 +572,7 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { st_wake_up(); } -void plan_set_position(float x, float y, float z, float e) +void plan_set_position(const float &x, const float &y, const float &z, const float &e) { position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); diff --git a/Marlin/planner.h b/Marlin/planner.h index 18ea1e2b1c..79f54d879f 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -32,16 +32,16 @@ typedef struct { // Fields used by the bresenham algorithm for tracing the line long steps_x, steps_y, steps_z, steps_e; // Step count along each axis long step_event_count; // The number of step events required to complete this block - volatile long accelerate_until; // The index of the step event on which to stop acceleration - volatile long decelerate_after; // The index of the step event on which to start decelerating - volatile long acceleration_rate; // The acceleration rate used for acceleration calculation + volatile long accelerate_until; // The index of the step event on which to stop acceleration + volatile long decelerate_after; // The index of the step event on which to start decelerating + volatile long acceleration_rate; // The acceleration rate used for acceleration calculation unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) -#ifdef ADVANCE - long advance_rate; - volatile long initial_advance; - volatile long final_advance; - float advance; -#endif + #ifdef ADVANCE + long advance_rate; + volatile long initial_advance; + volatile long final_advance; + float advance; + #endif // Fields used by the motion planner to manage acceleration float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis @@ -57,16 +57,17 @@ typedef struct { long acceleration_st; // acceleration steps/sec^2 volatile char busy; } block_t; - + // Initialize the motion plan subsystem void plan_init(); // Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in // millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(float x, float y, float z, float e, float feed_rate); +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate); // Set position. Used for G92 instructions. -void plan_set_position(float x, float y, float z, float e); +void plan_set_position(const float &x, const float &y, const float &z, const float &e); + // Called when the current block is no longer needed. Discards the block and makes the memory // availible for new blocks. diff --git a/Marlin/speed_lookuptable.h b/Marlin/speed_lookuptable.h index 05dae47dfb..002f852f62 100644 --- a/Marlin/speed_lookuptable.h +++ b/Marlin/speed_lookuptable.h @@ -37,6 +37,7 @@ uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ { 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, { 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0} }; + uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ { 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, { 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 9e5db44a82..924521119e 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -35,8 +35,8 @@ // if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. // for debugging purposes only, should be disabled by default #ifdef DEBUG_STEPS -volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; -volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; + volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; + volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; #endif @@ -117,6 +117,8 @@ asm volatile ( \ block_t *current_block; // A pointer to the block currently being traced +//static makes it inpossible to be called from outside of this file by extern.! + // Variables used by The Stepper Driver Interrupt static unsigned char out_bits; // The next stepping-bits to be output static long counter_x, // Counter variables for the bresenham line tracer @@ -125,9 +127,9 @@ static long counter_x, // Counter variables for the bresenham line tracer counter_e; static unsigned long step_events_completed; // The number of step events executed in the current block #ifdef ADVANCE -static long advance_rate, advance, final_advance = 0; -static short old_advance = 0; -static short e_steps; + static long advance_rate, advance, final_advance = 0; + static short old_advance = 0; + static short e_steps; #endif static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. static long acceleration_time, deceleration_time; @@ -195,10 +197,10 @@ inline unsigned short calc_timer(unsigned short step_rate) { // Initializes the trapezoid generator from the current block. Called whenever a new // block begins. inline void trapezoid_generator_reset() { -#ifdef ADVANCE - advance = current_block->initial_advance; - final_advance = current_block->final_advance; -#endif + #ifdef ADVANCE + advance = current_block->initial_advance; + final_advance = current_block->final_advance; + #endif deceleration_time = 0; // advance_rate = current_block->advance_rate; // step_rate to timer interval @@ -211,7 +213,8 @@ inline void trapezoid_generator_reset() { // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. ISR(TIMER1_COMPA_vect) { - if(busy){ SERIAL_ERRORLN(*(unsigned short *)OCR1A<< " ISR overtaking itself."); + if(busy){ + SERIAL_ERRORLN(*(unsigned short *)OCR1A<< " ISR overtaking itself."); return; } // The busy-flag is used to avoid reentering this interrupt @@ -242,74 +245,74 @@ ISR(TIMER1_COMPA_vect) // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt out_bits = current_block->direction_bits; -#ifdef ADVANCE - // Calculate E early. - counter_e += current_block->steps_e; - if (counter_e > 0) { - counter_e -= current_block->step_event_count; - if ((out_bits & (1<steps_e; + if (counter_e > 0) { + counter_e -= current_block->step_event_count; + if ((out_bits & (1<> 16) - old_advance); CRITICAL_SECTION_END; - } - else { - CRITICAL_SECTION_START; - e_steps++; - CRITICAL_SECTION_END; - } - } - // Do E steps + advance steps - CRITICAL_SECTION_START; - e_steps += ((advance >> 16) - old_advance); - CRITICAL_SECTION_END; - old_advance = advance >> 16; -#endif //ADVANCE + old_advance = advance >> 16; + #endif //ADVANCE // Set direction en check limit switches -if ((out_bits & (1< -1 + if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } #endif -#if X_MIN_PIN > -1 - if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } -#endif } else { // +direction - WRITE(X_DIR_PIN,!INVERT_X_DIR); - #ifdef DEBUG_STEPS + WRITE(X_DIR_PIN,!INVERT_X_DIR); + #ifdef DEBUG_STEPS count_direction[X_AXIS]=1; - #endif -#if X_MAX_PIN > -1 + #endif + #if X_MAX_PIN > -1 if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ step_events_completed = current_block->step_event_count; } -#endif + #endif } if ((out_bits & (1< -1 + if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } #endif -#if Y_MIN_PIN > -1 - if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } -#endif } else { // +direction WRITE(Y_DIR_PIN,!INVERT_Y_DIR); #ifdef DEBUG_STEPS - count_direction[Y_AXIS]=1; + count_direction[Y_AXIS]=1; + #endif + #if Y_MAX_PIN > -1 + if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ + step_events_completed = current_block->step_event_count; + } #endif -#if Y_MAX_PIN > -1 - if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ - step_events_completed = current_block->step_event_count; - } -#endif } if ((out_bits & (1< -1 - if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } -#endif + #if Z_MIN_PIN > -1 + if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } + #endif } else { // +direction - WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - #ifdef DEBUG_STEPS + WRITE(Z_DIR_PIN,!INVERT_Z_DIR); + #ifdef DEBUG_STEPS count_direction[Z_AXIS]=1; - #endif -#if Z_MAX_PIN > -1 + #endif + #if Z_MAX_PIN > -1 if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ step_events_completed = current_block->step_event_count; } -#endif + #endif } -#ifndef ADVANCE - if ((out_bits & (1<steps_x; @@ -349,7 +352,7 @@ if ((out_bits & (1<step_event_count; WRITE(X_STEP_PIN, LOW); #ifdef DEBUG_STEPS - count_position[X_AXIS]+=count_direction[X_AXIS]; + count_position[X_AXIS]+=count_direction[X_AXIS]; #endif } @@ -359,7 +362,7 @@ if ((out_bits & (1<step_event_count; WRITE(Y_STEP_PIN, LOW); #ifdef DEBUG_STEPS - count_position[Y_AXIS]+=count_direction[Y_AXIS]; + count_position[Y_AXIS]+=count_direction[Y_AXIS]; #endif } @@ -369,18 +372,18 @@ if ((out_bits & (1<step_event_count; WRITE(Z_STEP_PIN, LOW); #ifdef DEBUG_STEPS - count_position[Z_AXIS]+=count_direction[Z_AXIS]; + count_position[Z_AXIS]+=count_direction[Z_AXIS]; #endif } -#ifndef ADVANCE - counter_e += current_block->steps_e; - if (counter_e > 0) { - WRITE(E_STEP_PIN, HIGH); - counter_e -= current_block->step_event_count; - WRITE(E_STEP_PIN, LOW); - } -#endif //!ADVANCE + #ifndef ADVANCE + counter_e += current_block->steps_e; + if (counter_e > 0) { + WRITE(E_STEP_PIN, HIGH); + counter_e -= current_block->step_event_count; + WRITE(E_STEP_PIN, LOW); + } + #endif //!ADVANCE step_events_completed += 1; if(step_events_completed >= current_block->step_event_count) break; } @@ -397,9 +400,9 @@ if ((out_bits & (1< 0) { - WRITE(E_DIR_PIN,!INVERT_E_DIR); - e_steps--; - WRITE(E_STEP_PIN, HIGH); + unsigned char old_OCR0A; + // Timer interrupt for E. e_steps is set in the main routine; + // Timer 0 is shared with millies + ISR(TIMER0_COMPA_vect) + { + // Critical section needed because Timer 1 interrupt has higher priority. + // The pin set functions are placed on trategic position to comply with the stepper driver timing. + WRITE(E_STEP_PIN, LOW); + // Set E direction (Depends on E direction + advance) + if (e_steps < 0) { + WRITE(E_DIR_PIN,INVERT_E_DIR); + e_steps++; + WRITE(E_STEP_PIN, HIGH); + } + if (e_steps > 0) { + WRITE(E_DIR_PIN,!INVERT_E_DIR); + e_steps--; + WRITE(E_STEP_PIN, HIGH); + } + old_OCR0A += 25; // 10kHz interrupt + OCR0A = old_OCR0A; } - old_OCR0A += 25; // 10kHz interrupt - OCR0A = old_OCR0A; -} #endif // ADVANCE void st_init() { //Initialize Dir Pins -#if X_DIR_PIN > -1 - SET_OUTPUT(X_DIR_PIN); -#endif -#if Y_DIR_PIN > -1 - SET_OUTPUT(Y_DIR_PIN); -#endif -#if Z_DIR_PIN > -1 - SET_OUTPUT(Z_DIR_PIN); -#endif -#if E_DIR_PIN > -1 - SET_OUTPUT(E_DIR_PIN); -#endif + #if X_DIR_PIN > -1 + SET_OUTPUT(X_DIR_PIN); + #endif + #if Y_DIR_PIN > -1 + SET_OUTPUT(Y_DIR_PIN); + #endif + #if Z_DIR_PIN > -1 + SET_OUTPUT(Z_DIR_PIN); + #endif + #if E_DIR_PIN > -1 + SET_OUTPUT(E_DIR_PIN); + #endif //Initialize Enable Pins - steppers default to disabled. -#if (X_ENABLE_PIN > -1) - SET_OUTPUT(X_ENABLE_PIN); - if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); -#endif -#if (Y_ENABLE_PIN > -1) - SET_OUTPUT(Y_ENABLE_PIN); - if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); -#endif -#if (Z_ENABLE_PIN > -1) - SET_OUTPUT(Z_ENABLE_PIN); - if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); -#endif -#if (E_ENABLE_PIN > -1) - SET_OUTPUT(E_ENABLE_PIN); - if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); -#endif + #if (X_ENABLE_PIN > -1) + SET_OUTPUT(X_ENABLE_PIN); + if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); + #endif + #if (Y_ENABLE_PIN > -1) + SET_OUTPUT(Y_ENABLE_PIN); + if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); + #endif + #if (Z_ENABLE_PIN > -1) + SET_OUTPUT(Z_ENABLE_PIN); + if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); + #endif + #if (E_ENABLE_PIN > -1) + SET_OUTPUT(E_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); + #endif //endstops and pullups -#ifdef ENDSTOPPULLUPS -#if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); - WRITE(X_MIN_PIN,HIGH); -#endif -#if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); - WRITE(X_MAX_PIN,HIGH); -#endif -#if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); - WRITE(Y_MIN_PIN,HIGH); -#endif -#if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); - WRITE(Y_MAX_PIN,HIGH); -#endif -#if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); - WRITE(Z_MIN_PIN,HIGH); -#endif -#if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); - WRITE(Z_MAX_PIN,HIGH); -#endif -#else //ENDSTOPPULLUPS -#if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); -#endif -#if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); -#endif -#if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); -#endif -#if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); -#endif -#if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); -#endif -#if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); -#endif -#endif //ENDSTOPPULLUPS + #ifdef ENDSTOPPULLUPS + #if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + WRITE(X_MIN_PIN,HIGH); + #endif + #if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + WRITE(X_MAX_PIN,HIGH); + #endif + #if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + WRITE(Y_MIN_PIN,HIGH); + #endif + #if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + WRITE(Y_MAX_PIN,HIGH); + #endif + #if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + WRITE(Z_MIN_PIN,HIGH); + #endif + #if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + WRITE(Z_MAX_PIN,HIGH); + #endif + #else //ENDSTOPPULLUPS + #if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + #endif + #if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + #endif + #if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + #endif + #if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + #endif + #if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + #endif + #if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + #endif + #endif //ENDSTOPPULLUPS //Initialize Step Pins -#if (X_STEP_PIN > -1) - SET_OUTPUT(X_STEP_PIN); -#endif -#if (Y_STEP_PIN > -1) - SET_OUTPUT(Y_STEP_PIN); -#endif -#if (Z_STEP_PIN > -1) - SET_OUTPUT(Z_STEP_PIN); -#endif -#if (E_STEP_PIN > -1) - SET_OUTPUT(E_STEP_PIN); -#endif + #if (X_STEP_PIN > -1) + SET_OUTPUT(X_STEP_PIN); + #endif + #if (Y_STEP_PIN > -1) + SET_OUTPUT(Y_STEP_PIN); + #endif + #if (Z_STEP_PIN > -1) + SET_OUTPUT(Z_STEP_PIN); + #endif + #if (E_STEP_PIN > -1) + SET_OUTPUT(E_STEP_PIN); + #endif // waveform generation = 0100 = CTC TCCR1B &= ~(1< 10){ - pid_output = PID_MAX; - pid_reset = true; - } - else if(pid_error < -10) { - pid_output = 0; - pid_reset = true; - } - else { - if(pid_reset == true) { - temp_iState = 0.0; - pid_reset = false; - } - pTerm = Kp * pid_error; - temp_iState += pid_error; - temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); - iTerm = Ki * temp_iState; - //K1 defined in Configuration.h in the PID settings - #define K2 (1.0-K1) - dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); - temp_dState = pid_input; - #ifdef PID_ADD_EXTRUSION_RATE - pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high - #endif - pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); - } -#endif //PID_OPENLOOP -#ifdef PID_DEBUG - SERIAL_ECHOLN(" PIDDEBUG Input "< 10){ + pid_output = PID_MAX; + pid_reset = true; + } + else if(pid_error < -10) { + pid_output = 0; + pid_reset = true; + } + else { + if(pid_reset == true) { + temp_iState = 0.0; + pid_reset = false; + } + pTerm = Kp * pid_error; + temp_iState += pid_error; + temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); + iTerm = Ki * temp_iState; + //K1 defined in Configuration.h in the PID settings + #define K2 (1.0-K1) + dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); + temp_dState = pid_input; + #ifdef PID_ADD_EXTRUSION_RATE + pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high + #endif + pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); + } + #endif //PID_OPENLOOP + #ifdef PID_DEBUG + SERIAL_ECHOLN(" PIDDEBUG Input "<= target_raw[0]) { WRITE(HEATER_0_PIN,LOW); @@ -157,7 +156,7 @@ CRITICAL_SECTION_END; { WRITE(HEATER_0_PIN,HIGH); } -#endif + #endif if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) return; @@ -173,7 +172,7 @@ CRITICAL_SECTION_END; WRITE(HEATER_1_PIN,HIGH); } #endif - } +} // Takes hot end temperature value as input and returns corresponding raw value. // For a thermistor, it uses the RepRap thermistor temp table. @@ -300,26 +299,26 @@ float analog2tempBed(int raw) { void tp_init() { -#if (HEATER_0_PIN > -1) - SET_OUTPUT(HEATER_0_PIN); -#endif -#if (HEATER_1_PIN > -1) - SET_OUTPUT(HEATER_1_PIN); -#endif -#if (HEATER_2_PIN > -1) - SET_OUTPUT(HEATER_2_PIN); -#endif + #if (HEATER_0_PIN > -1) + SET_OUTPUT(HEATER_0_PIN); + #endif + #if (HEATER_1_PIN > -1) + SET_OUTPUT(HEATER_1_PIN); + #endif + #if (HEATER_2_PIN > -1) + SET_OUTPUT(HEATER_2_PIN); + #endif -#ifdef PIDTEMP - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; -#endif //PIDTEMP + #ifdef PIDTEMP + temp_iState_min = 0.0; + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; + #endif //PIDTEMP -// Set analog inputs + // Set analog inputs ADCSRA = 1< -1 + #if TEMP_0_PIN > -1 target_raw[0]=0; #if HEATER_0_PIN > -1 WRITE(HEATER_0_PIN,LOW); #endif #endif + #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif #endif + #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif #endif } @@ -376,75 +377,75 @@ ISR(TIMER0_COMPB_vect) switch(temp_state) { case 0: // Prepare TEMP_0 - #if (TEMP_0_PIN > -1) - #if TEMP_0_PIN < 8 - DIDR0 = 1 << TEMP_0_PIN; - #else - DIDR2 = 1<<(TEMP_0_PIN - 8); - ADCSRB = 1< -1) + #if TEMP_0_PIN < 8 + DIDR0 = 1 << TEMP_0_PIN; + #else + DIDR2 = 1<<(TEMP_0_PIN - 8); + ADCSRB = 1< -1) - raw_temp_0_value += ADC; - #endif - temp_state = 2; - break; + #if (TEMP_0_PIN > -1) + raw_temp_0_value += ADC; + #endif + temp_state = 2; + break; case 2: // Prepare TEMP_1 - #if (TEMP_1_PIN > -1) - #if TEMP_1_PIN < 7 - DIDR0 = 1< -1) + #if TEMP_1_PIN < 7 + DIDR0 = 1< -1) - raw_temp_1_value += ADC; - #endif - temp_state = 4; - break; + #if (TEMP_1_PIN > -1) + raw_temp_1_value += ADC; + #endif + temp_state = 4; + break; case 4: // Prepare TEMP_2 - #if (TEMP_2_PIN > -1) - #if TEMP_2_PIN < 7 - DIDR0 = 1 << TEMP_2_PIN; - #else - DIDR2 = 1<<(TEMP_2_PIN - 8); - ADCSRB = 1< -1) + #if TEMP_2_PIN < 7 + DIDR0 = 1 << TEMP_2_PIN; + #else + DIDR2 = 1<<(TEMP_2_PIN - 8); + ADCSRB = 1< -1) - raw_temp_2_value += ADC; - #endif - temp_state = 0; - temp_count++; - break; + #if (TEMP_2_PIN > -1) + raw_temp_2_value += ADC; + #endif + temp_state = 0; + temp_count++; + break; default: - SERIAL_ERRORLN("Temp measurement error!"); - break; + SERIAL_ERRORLN("Temp measurement error!"); + break; } if(temp_count >= 16) // 6 ms * 16 = 96ms. @@ -472,67 +473,71 @@ ISR(TIMER0_COMPB_vect) raw_temp_0_value = 0; raw_temp_1_value = 0; raw_temp_2_value = 0; -#ifdef HEATER_0_MAXTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 0 switched off. MAXTEMP triggered !!"); - kill(); - } + #ifdef HEATER_0_MAXTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 0 switched off. MAXTEMP triggered !!"); + kill(); + } + #endif + #endif + #ifdef HEATER_1_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + if(current_raw[2] >= maxttemp_1) { + analogWrite(HEATER_2_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 1 switched off. MAXTEMP triggered !!"); + kill() + } + #endif + #endif //MAXTEMP + + #ifdef HEATER_0_MINTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 0 switched off. MINTEMP triggered !!"); + kill(); + } + #endif #endif -#endif -#ifdef HEATER_1_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - if(current_raw[2] >= maxttemp_1) { - analogWrite(HEATER_2_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 1 switched off. MAXTEMP triggered !!"); - kill() - } + + #ifdef HEATER_1_MINTEMP + #if (HEATER_2_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + analogWrite(HEATER_2_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 1 switched off. MINTEMP triggered !!"); + kill(); + } + #endif + #endif //MAXTEMP + + #ifdef BED_MINTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] <= bed_minttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + SERIAL_ERRORLN("Temperatur heated bed switched off. MINTEMP triggered !!"); + kill(); + } + #endif #endif -#endif //MAXTEMP -#ifdef HEATER_0_MINTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 0 switched off. MINTEMP triggered !!"); - kill(); - } + + #ifdef BED_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] >= bed_maxttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + SERIAL_ERRORLN("Temperature heated bed switched off. MAXTEMP triggered !!"); + kill(); + } + #endif #endif -#endif -#ifdef HEATER_1_MINTEMP - #if (HEATER_2_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - analogWrite(HEATER_2_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 1 switched off. MINTEMP triggered !!"); - kill(); - } - #endif -#endif //MAXTEMP -#ifdef BED_MINTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] <= bed_minttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - SERIAL_ERRORLN("Temperatur heated bed switched off. MINTEMP triggered !!"); - kill(); - } - #endif -#endif -#ifdef BED_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] >= bed_maxttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - SERIAL_ERRORLN("Temperature heated bed switched off. MAXTEMP triggered !!"); - kill(); - } - #endif -#endif } } diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 44d54db141..9c4b59a241 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -27,9 +27,11 @@ #include "stepper.h" #endif +// public functions void tp_init(); //initialise the heating void manage_heater(); //it is critical that this is called periodically. + enum TempSensor {TEMPSENSOR_HOTEND_0=0,TEMPSENSOR_BED=1, TEMPSENSOR_HOTEND_1=2}; //low leven conversion routines @@ -41,9 +43,11 @@ float analog2tempBed(int raw); extern int target_raw[3]; extern int current_raw[3]; extern float Kp,Ki,Kd,Kc; + #ifdef PIDTEMP extern float pid_setpoint ; #endif + #ifdef WATCHPERIOD extern int watch_raw[3] ; extern unsigned long watchmillis; @@ -63,15 +67,15 @@ inline float degTargetHotend0() { return analog2temp(target_raw[TEMPSENSOR_HOTE inline float degTargetHotend1() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);}; inline float degTargetBed() { return analog2tempBed(target_raw[TEMPSENSOR_BED]);}; -inline void setTargetHotend0(float celsius) +inline void setTargetHotend0(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius); #ifdef PIDTEMP pid_setpoint = celsius; #endif //PIDTEMP }; -inline void setTargetHotend1(float celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; -inline void setTargetBed(float celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; +inline void setTargetHotend1(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; +inline void setTargetBed(const float &celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; inline bool isHeatingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; inline bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; @@ -84,16 +88,5 @@ inline bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMP void disable_heater(); void setWatch(); -#ifdef HEATER_0_USES_THERMISTOR - #define HEATERSOURCE 1 -#endif -#ifdef BED_USES_THERMISTOR - #define BEDSOURCE 1 -#endif - - - - - #endif diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index b7092c9cb1..18d1b7f249 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -9,107 +9,48 @@ void lcd_status(const char* message); void beep(); void buttons_check(); - #define LCDSTATUSRIGHT + #define LCD_UPDATE_INTERVAL 100 #define STATUSTIMEOUT 15000 - #include "Configuration.h" #include extern LiquidCrystal lcd; - //lcd display size -#ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 + #ifdef NEWPANEL - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - #define EN_C (1<>1; - if(READ(SHIFT_OUT)) - newbutton|=(1<<7); - WRITE(SHIFT_CLK,HIGH); - WRITE(SHIFT_CLK,LOW); - } - buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 -#endif + #ifdef NEWPANEL + uint8_t newbutton=0; + if(READ(BTN_EN1)==0) newbutton|=EN_A; + if(READ(BTN_EN2)==0) newbutton|=EN_B; + if((blocking>1; + if(READ(SHIFT_OUT)) + newbutton|=(1<<7); + WRITE(SHIFT_CLK,HIGH); + WRITE(SHIFT_CLK,LOW); + } + buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 + #endif + char enc=0; if(buttons&EN_A) enc|=(1<<0); @@ -212,7 +211,6 @@ void buttons_check() } } lastenc=enc; -// busy=false; } #endif @@ -223,9 +221,9 @@ MainMenu::MainMenu() displayStartingRow=0; activeline=0; force_lcd_update=true; -#ifdef ULTIPANEL - buttons_init(); -#endif + #ifdef ULTIPANEL + buttons_init(); + #endif lcd_init(); linechanging=false; } @@ -1154,12 +1152,13 @@ uint8_t getnrfilenames() cnt++; } return cnt; +#else + return 0; #endif } void MainMenu::showSD() { - #ifdef SDSUPPORT uint8_t line=0; @@ -1205,11 +1204,11 @@ void MainMenu::showSD() if(force_lcd_update) { lcd.setCursor(0,line); -#ifdef CARDINSERTED + #ifdef CARDINSERTED if(CARDINSERTED) -#else + #else if(true) -#endif + #endif { lcd.print(" \004Refresh"); } @@ -1306,9 +1305,9 @@ void MainMenu::showMainMenu() { //if(int(encoderpos/lcdslow)!=int(lastencoderpos/lcdslow)) // force_lcd_update=true; -#ifndef ULTIPANEL - force_lcd_update=false; -#endif + #ifndef ULTIPANEL + force_lcd_update=false; + #endif //Serial.println((int)activeline); if(force_lcd_update) clear(); @@ -1347,17 +1346,17 @@ void MainMenu::showMainMenu() beepshort(); } }break; -#ifdef SDSUPPORT + #ifdef SDSUPPORT case ItemM_file: { if(force_lcd_update) { lcd.setCursor(0,line); -#ifdef CARDINSERTED - if(CARDINSERTED) -#else - if(true) -#endif + #ifdef CARDINSERTED + if(CARDINSERTED) + #else + if(true) + #endif { if(sdmode) lcd.print(" Stop Print \x7E"); @@ -1370,7 +1369,7 @@ void MainMenu::showMainMenu() } } #ifdef CARDINSERTED - if(CARDINSERTED) + if(CARDINSERTED) #endif if((activeline==line)&&CLICKED) { @@ -1380,28 +1379,30 @@ void MainMenu::showMainMenu() beepshort(); } }break; -#endif + #endif default: SERIAL_ERRORLN("Something is wrong in the MenuStructure."); break; } } - if(activeline<0) activeline=0; - if(activeline>=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + if(activeline<0) + activeline=0; + if(activeline>=LCD_HEIGHT) + activeline=LCD_HEIGHT-1; if((encoderpos!=lastencoderpos)||force_lcd_update) { lcd.setCursor(0,activeline);lcd.print(activeline?' ':' '); if(encoderpos<0) encoderpos=0; - if(encoderpos>3*lcdslow) encoderpos=3*lcdslow; + if(encoderpos>3*lcdslow) + encoderpos=3*lcdslow; activeline=abs(encoderpos/lcdslow)%LCD_HEIGHT; - if(activeline<0) activeline=0; - if(activeline>=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + if(activeline<0) + activeline=0; + if(activeline>=LCD_HEIGHT) + activeline=LCD_HEIGHT-1; lastencoderpos=encoderpos; lcd.setCursor(0,activeline);lcd.print(activeline?'>':'\003'); } - - - } void MainMenu::update() @@ -1409,25 +1410,24 @@ void MainMenu::update() static MainStatus oldstatus=Main_Menu; //init automatically causes foce_lcd_update=true static long timeoutToStatus=0; static bool oldcardstatus=false; -#ifdef CARDINSERTED - if((CARDINSERTED != oldcardstatus)) - { - force_lcd_update=true; - oldcardstatus=CARDINSERTED; - //Serial.println("echo: SD CHANGE"); - if(CARDINSERTED) + #ifdef CARDINSERTED + if((CARDINSERTED != oldcardstatus)) { - initsd(); - lcd_status("Card inserted"); + force_lcd_update=true; + oldcardstatus=CARDINSERTED; + //Serial.println("echo: SD CHANGE"); + if(CARDINSERTED) + { + initsd(); + lcd_status("Card inserted"); + } + else + { + sdactive=false; + lcd_status("Card removed"); + } } - else - { - sdactive=false; - lcd_status("Card removed"); - - } - } -#endif + #endif if(status!=oldstatus) { @@ -1484,9 +1484,9 @@ void MainMenu::update() //return for string conversion routines -char conv[8]; +static char conv[8]; -/// convert float to string with +123.4 format +// convert float to string with +123.4 format char *ftostr3(const float &x) { //sprintf(conv,"%5.1f",x); @@ -1497,6 +1497,7 @@ char *ftostr3(const float &x) conv[3]=0; return conv; } + char *itostr2(const uint8_t &x) { //sprintf(conv,"%5.1f",x); @@ -1506,10 +1507,10 @@ char *itostr2(const uint8_t &x) conv[2]=0; return conv; } -/// convert float to string with +123.4 format + +// convert float to string with +123.4 format char *ftostr31(const float &x) { - //sprintf(conv,"%5.1f",x); int xx=x*10; conv[0]=(xx>=0)?'+':'-'; xx=abs(xx); @@ -1524,7 +1525,6 @@ char *ftostr31(const float &x) char *itostr31(const int &xx) { - //sprintf(conv,"%5.1f",x); conv[0]=(xx>=0)?'+':'-'; conv[1]=(xx/1000)%10+'0'; conv[2]=(xx/100)%10+'0'; @@ -1534,6 +1534,7 @@ char *itostr31(const int &xx) conv[6]=0; return conv; } + char *itostr3(const int &xx) { conv[0]=(xx/100)%10+'0'; @@ -1553,7 +1554,7 @@ char *itostr4(const int &xx) return conv; } -/// convert float to string with +1234.5 format +// convert float to string with +1234.5 format char *ftostr51(const float &x) { int xx=x*10; @@ -1587,11 +1588,9 @@ char *fillto(int8_t n,char *c) } ret[n]=0; return ret; - } -#else -inline void lcd_status() {}; -#endif + +#endif //ULTRA_LCD diff --git a/Marlin/watchdog.h b/Marlin/watchdog.h index 7dd31f9f7e..44ee9de35d 100644 --- a/Marlin/watchdog.h +++ b/Marlin/watchdog.h @@ -1,13 +1,16 @@ #ifndef __WATCHDOGH #define __WATCHDOGH #include "Configuration.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(); + // 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(); -//#endif +#else + inline void wd_init() {}; + inline void wd_reset() {}; +#endif #endif diff --git a/Marlin/watchdog.pde b/Marlin/watchdog.pde index 09d881d1d0..71868cec5b 100644 --- a/Marlin/watchdog.pde +++ b/Marlin/watchdog.pde @@ -3,7 +3,7 @@ #include #include -volatile uint8_t timeout_seconds=0; +static volatile uint8_t timeout_seconds=0; void(* ctrlaltdelete) (void) = 0; //does not work on my atmega2560 From 76b3f805c08f1ceb0b4a69523d5fd7b1a331c7a6 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 6 Nov 2011 19:30:04 +0100 Subject: [PATCH 019/228] Added teensylu pins --- Marlin/Configuration.h | 4 +- Marlin/pins.h | 1330 +++++++++++++++++++++------------------- 2 files changed, 695 insertions(+), 639 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index b437bfb01f..1c77733039 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -14,8 +14,9 @@ // Gen6 = 5, // Sanguinololu 1.2 and above = 62 // Ultimaker = 7, +// Teensylu = 8 #define MOTHERBOARD 7 -//#define MOTHERBOARD 5 + //// Thermistor settings: @@ -58,7 +59,6 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // #define ULTRA_LCD //any lcd -#define ULTIPANEL #define ULTIPANEL #ifdef ULTIPANEL //#define NEWPANEL //enable this if you have a click-encoder panel diff --git a/Marlin/pins.h b/Marlin/pins.h index 4df1bd0e3b..807709e2be 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -1,638 +1,694 @@ -#ifndef PINS_H -#define PINS_H - -/**************************************************************************************** -* Arduino pin assignment -* -* ATMega168 -* +-\/-+ -* PC6 1| |28 PC5 (AI 5 / D19) -* (D 0) PD0 2| |27 PC4 (AI 4 / D18) -* (D 1) PD1 3| |26 PC3 (AI 3 / D17) -* (D 2) PD2 4| |25 PC2 (AI 2 / D16) -* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) -* (D 4) PD4 6| |23 PC0 (AI 0 / D14) -* VCC 7| |22 GND -* GND 8| |21 AREF -* PB6 9| |20 AVCC -* PB7 10| |19 PB5 (D 13) -* PWM+ (D 5) PD5 11| |18 PB4 (D 12) -* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -* (D 7) PD7 13| |16 PB2 (D 10) PWM -* (D 8) PB0 14| |15 PB1 (D 9) PWM -* +----+ -****************************************************************************************/ -#if MOTHERBOARD == 0 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega168__ -#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. -#endif - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 4 -#define X_MAX_PIN 9 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN 13 - -#define Z_STEP_PIN 19 -#define Z_DIR_PIN 18 -#define Z_ENABLE_PIN 5 -#define Z_MIN_PIN 17 -#define Z_MAX_PIN 16 - -#define E_STEP_PIN 11 -#define E_DIR_PIN 12 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 15 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#endif - - - -/**************************************************************************************** -* Sanguino/RepRap Motherboard with direct-drive extruders -* -* ATMega644P -* -* +---\/---+ -* (D 0) PB0 1| |40 PA0 (AI 0 / D31) -* (D 1) PB1 2| |39 PA1 (AI 1 / D30) -* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) -* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) -* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) -* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) -* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) -* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) -* RST 9| |32 AREF -* VCC 10| |31 GND -* GND 11| |30 AVCC -* XTAL2 12| |29 PC7 (D 23) -* XTAL1 13| |28 PC6 (D 22) -* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI -* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO -* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS -* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK -* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA -* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL -* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM -* +--------+ -* -****************************************************************************************/ -#if MOTHERBOARD == 1 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 19 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PIN 29 -#define Z_DIR_PIN 30 -#define Z_ENABLE_PIN 31 -#define Z_MIN_PIN 2 -#define Z_MAX_PIN 1 - -#define E_STEP_PIN 12 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN 3 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN 0 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 14 -#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ - - - -#endif - - -/**************************************************************************************** -* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* -* -****************************************************************************************/ -#if MOTHERBOARD == 2 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PINN 27 -#define Z_DIR_PINN 28 -#define Z_ENABLE_PIN 29 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 31 - -#define E_STEP_PIN 17 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 4 -#define LED_PIN 0 - -#define SD_CARD_WRITE 2 -#define SD_CARD_DETECT 3 -#define SD_CARD_SELECT 4 - -//our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 - -//pin for controlling the PSU. -#define PS_ON_PIN 14 - -#define FAN_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN -1 -#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - - - -#endif - -/**************************************************************************************** -* Arduino Mega pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 33 -#define MOTHERBOARD 3 -#define RAMPS_V_1_3 -#endif -#if MOTHERBOARD == 3 -#define KNOWN_BOARD 1 - -//////////////////FIX THIS////////////// -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 -// #define RAMPS_V_1_3 -// #define RAMPS_V_1_0 - -#ifdef RAMPS_V_1_3 - -#define X_STEP_PIN 54 -#define X_DIR_PIN 55 -#define X_ENABLE_PIN 38 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. - -#define Y_STEP_PIN 60 -#define Y_DIR_PIN 61 -#define Y_ENABLE_PIN 56 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 //15 - -#define Z_STEP_PIN 46 -#define Z_DIR_PIN 48 -#define Z_ENABLE_PIN 62 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E_STEP_PIN 26 -#define E_DIR_PIN 28 -#define E_ENABLE_PIN 24 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 9 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#define HEATER_0_PIN 10 -#define HEATER_1_PIN 8 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 14 // ANALOG NUMBERING -#define TEMP_2_PIN -1 // ANALOG NUMBERING - - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default - -#define X_STEP_PIN 26 -#define X_DIR_PIN 28 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 - -#define Y_STEP_PIN 38 -#define Y_DIR_PIN 40 -#define Y_ENABLE_PIN 36 -#define Y_MIN_PIN 16 -#define Y_MAX_PIN -1 //17 - -#define Z_STEP_PIN 44 -#define Z_DIR_PIN 46 -#define Z_ENABLE_PIN 42 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E_STEP_PIN 32 -#define E_DIR_PIN 34 -#define E_ENABLE_PIN 30 - -#define SDPOWER 48 -#define SDSS 53 -#define LED_PIN 13 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - - - -#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 - #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_1_PIN -1 // RAMPS 1.0 - #define FAN_PIN 11 // RAMPS 1.0 - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 - #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_1_PIN 8 // RAMPS 1.1 - #define FAN_PIN 9 // RAMPS 1.1 -#endif -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#endif - -// SPI for Max6675 Thermocouple - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 - #define MISO_PIN 50 - #define MOSI_PIN 51 - #define MAX6675_SS 53 -#else - #define MAX6675_SS 49 -#endif - - -#endif -/**************************************************************************************** -* Duemilanove w/ ATMega328P pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 4 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega328P__ -#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 17 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 13 -#define Z_DIR_PIN 3 -#define Z_ENABLE_PIN 2 -#define Z_MIN_PIN 4 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 11 -#define E_DIR_PIN 12 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN 5 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - -#endif - -/**************************************************************************************** -* Gen6 pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 5 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ - #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -//x axis pins - #define X_STEP_PIN 15 - #define X_DIR_PIN 18 - #define X_ENABLE_PIN 19 - #define X_MIN_PIN 20 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 25 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 27 - #define Z_DIR_PIN 28 - #define Z_ENABLE_PIN 29 - #define Z_MIN_PIN 30 - #define Z_MAX_PIN -1 - - //extruder pins - #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 - #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 - #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_2_PIN -1 - - #define SDPOWER -1 - #define SDSS 17 - #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_2_PIN -1 - #define FAN_PIN -1 //changed @ rkoeppl 20110410 - #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 - //our pin for debugging. - - #define DEBUG_PIN 0 - - //our RS485 pins - #define TX_ENABLE_PIN 12 - #define RX_ENABLE_PIN 13 - -#endif - -/**************************************************************************************** -* Sanguinololu pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 62 -#define MOTHERBOARD 6 -#define SANGUINOLOLU_V_1_2 -#endif -#if MOTHERBOARD == 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 21 -#define X_MIN_PIN 18 -#define X_MAX_PIN -2 - -#define Y_STEP_PIN 22 -#define Y_DIR_PIN 23 -#define Y_MIN_PIN 19 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 3 -#define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 1 -#define E_DIR_PIN 0 - -#define LED_PIN -1 - -#define FAN_PIN -1 - -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 // (extruder) - -#ifdef SANGUINOLOLU_V_1_2 - -#define HEATER_1_PIN 12 // (bed) -#define X_ENABLE_PIN 14 -#define Y_ENABLE_PIN 14 -#define Z_ENABLE_PIN 26 -#define E_ENABLE_PIN 14 - -#else - -#define HEATER_1_PIN 14 // (bed) -#define X_ENABLE_PIN -1 -#define Y_ENABLE_PIN -1 -#define Z_ENABLE_PIN -1 -#define E_ENABLE_PIN -1 - -#endif - -#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define TEMP_2_PIN -1 -#define SDPOWER -1 -#define SDSS 31 -#define HEATER_2_PIN -1 - -#endif - - -#if MOTHERBOARD == 7 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 22 -#define X_MAX_PIN 24 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 26 -#define Y_MAX_PIN 28 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 32 -#define Z_ENABLE_PIN 35 - -#define HEATER_1_PIN 4 -#define TEMP_1_PIN 11 - -#define EXTRUDER_0_STEP_PIN 43 -#define EXTRUDER_0_DIR_PIN 45 -#define EXTRUDER_0_ENABLE_PIN 41 -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define EXTRUDER_1_STEP_PIN 49 -#define EXTRUDER_1_DIR_PIN 47 -#define EXTRUDER_1_ENABLE_PIN 51 -#define EXTRUDER_1_HEATER_PIN 3 -#define EXTRUDER_1_TEMPERATURE_PIN 10 -#define HEATER_2_PIN 51 -#define TEMP_2_PIN 3 - - - -#define E_STEP_PIN EXTRUDER_0_STEP_PIN -#define E_DIR_PIN EXTRUDER_0_DIR_PIN -#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 7 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#ifdef ULTRA_LCD - - #ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - #else //old style panel with shift register - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - //buttons are attached to a shift register - #define SHIFT_CLK 38 - #define SHIFT_LD 42 - #define SHIFT_OUT 40 - #define SHIFT_EN 17 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 5 - #define LCD_PINS_D4 6 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 20 - #define LCD_PINS_D7 19 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - - //bits in the shift register that carry the buttons for: - // left up center down right red - #define BL_LE 7 - #define BL_UP 6 - #define BL_MI 5 - #define BL_DW 4 - #define BL_RI 3 - #define BL_ST 2 - - #define BLEN_B 1 - #define BLEN_A 0 - #endif -#endif //ULTRA_LCD - -#endif - - -#ifndef KNOWN_BOARD -#error Unknown MOTHERBOARD value in configuration.h -#endif - -//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} - +#ifndef PINS_H +#define PINS_H + +/**************************************************************************************** +* Arduino pin assignment +* +* ATMega168 +* +-\/-+ +* PC6 1| |28 PC5 (AI 5 / D19) +* (D 0) PD0 2| |27 PC4 (AI 4 / D18) +* (D 1) PD1 3| |26 PC3 (AI 3 / D17) +* (D 2) PD2 4| |25 PC2 (AI 2 / D16) +* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) +* (D 4) PD4 6| |23 PC0 (AI 0 / D14) +* VCC 7| |22 GND +* GND 8| |21 AREF +* PB6 9| |20 AVCC +* PB7 10| |19 PB5 (D 13) +* PWM+ (D 5) PD5 11| |18 PB4 (D 12) +* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +* (D 7) PD7 13| |16 PB2 (D 10) PWM +* (D 8) PB0 14| |15 PB1 (D 9) PWM +* +----+ +****************************************************************************************/ +#if MOTHERBOARD == 0 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega168__ +#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. +#endif + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 4 +#define X_MAX_PIN 9 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN 13 + +#define Z_STEP_PIN 19 +#define Z_DIR_PIN 18 +#define Z_ENABLE_PIN 5 +#define Z_MIN_PIN 17 +#define Z_MAX_PIN 16 + +#define E_STEP_PIN 11 +#define E_DIR_PIN 12 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 15 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#endif + + + +/**************************************************************************************** +* Sanguino/RepRap Motherboard with direct-drive extruders +* +* ATMega644P +* +* +---\/---+ +* (D 0) PB0 1| |40 PA0 (AI 0 / D31) +* (D 1) PB1 2| |39 PA1 (AI 1 / D30) +* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +* RST 9| |32 AREF +* VCC 10| |31 GND +* GND 11| |30 AVCC +* XTAL2 12| |29 PC7 (D 23) +* XTAL1 13| |28 PC6 (D 22) +* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +* +--------+ +* +****************************************************************************************/ +#if MOTHERBOARD == 1 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 19 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PIN 29 +#define Z_DIR_PIN 30 +#define Z_ENABLE_PIN 31 +#define Z_MIN_PIN 2 +#define Z_MAX_PIN 1 + +#define E_STEP_PIN 12 +#define E_DIR_PIN 16 +#define E_ENABLE_PIN 3 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN 0 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 14 +#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ + + + +#endif + + +/**************************************************************************************** +* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* +* +****************************************************************************************/ +#if MOTHERBOARD == 2 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PINN 27 +#define Z_DIR_PINN 28 +#define Z_ENABLE_PIN 29 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 31 + +#define E_STEP_PIN 17 +#define E_DIR_PIN 16 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 4 +#define LED_PIN 0 + +#define SD_CARD_WRITE 2 +#define SD_CARD_DETECT 3 +#define SD_CARD_SELECT 4 + +//our RS485 pins +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 + +//pin for controlling the PSU. +#define PS_ON_PIN 14 + +#define FAN_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN -1 +#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + + + +#endif + +/**************************************************************************************** +* Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 33 +#define MOTHERBOARD 3 +#define RAMPS_V_1_3 +#endif +#if MOTHERBOARD == 3 +#define KNOWN_BOARD 1 + +//////////////////FIX THIS////////////// +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 +// #define RAMPS_V_1_3 +// #define RAMPS_V_1_0 + +#ifdef RAMPS_V_1_3 + +#define X_STEP_PIN 54 +#define X_DIR_PIN 55 +#define X_ENABLE_PIN 38 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. + +#define Y_STEP_PIN 60 +#define Y_DIR_PIN 61 +#define Y_ENABLE_PIN 56 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 //15 + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 62 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E_STEP_PIN 26 +#define E_DIR_PIN 28 +#define E_ENABLE_PIN 24 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 9 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#define HEATER_0_PIN 10 +#define HEATER_1_PIN 8 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 13 // ANALOG NUMBERING +#define TEMP_1_PIN 14 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING + + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default + +#define X_STEP_PIN 26 +#define X_DIR_PIN 28 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 + +#define Y_STEP_PIN 38 +#define Y_DIR_PIN 40 +#define Y_ENABLE_PIN 36 +#define Y_MIN_PIN 16 +#define Y_MAX_PIN -1 //17 + +#define Z_STEP_PIN 44 +#define Z_DIR_PIN 46 +#define Z_ENABLE_PIN 42 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E_STEP_PIN 32 +#define E_DIR_PIN 34 +#define E_ENABLE_PIN 30 + +#define SDPOWER 48 +#define SDSS 53 +#define LED_PIN 13 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + + + +#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 + #define HEATER_0_PIN 12 // RAMPS 1.0 + #define HEATER_1_PIN -1 // RAMPS 1.0 + #define FAN_PIN 11 // RAMPS 1.0 + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 + #define HEATER_0_PIN 10 // RAMPS 1.1 + #define HEATER_1_PIN 8 // RAMPS 1.1 + #define FAN_PIN 9 // RAMPS 1.1 +#endif +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#endif + +// SPI for Max6675 Thermocouple + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 + #define MISO_PIN 50 + #define MOSI_PIN 51 + #define MAX6675_SS 53 +#else + #define MAX6675_SS 49 +#endif + + +#endif +/**************************************************************************************** +* Duemilanove w/ ATMega328P pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 4 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega328P__ +#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 17 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 13 +#define Z_DIR_PIN 3 +#define Z_ENABLE_PIN 2 +#define Z_MIN_PIN 4 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 11 +#define E_DIR_PIN 12 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN 5 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#endif + +/**************************************************************************************** +* Gen6 pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 5 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ + #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +//x axis pins + #define X_STEP_PIN 15 + #define X_DIR_PIN 18 + #define X_ENABLE_PIN 19 + #define X_MIN_PIN 20 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 25 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 27 + #define Z_DIR_PIN 28 + #define Z_ENABLE_PIN 29 + #define Z_MIN_PIN 30 + #define Z_MAX_PIN -1 + + //extruder pins + #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 + #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 + #define HEATER_2_PIN -1 + + #define SDPOWER -1 + #define SDSS 17 + #define LED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 + #define FAN_PIN -1 //changed @ rkoeppl 20110410 + #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 + //our pin for debugging. + + #define DEBUG_PIN 0 + + //our RS485 pins + #define TX_ENABLE_PIN 12 + #define RX_ENABLE_PIN 13 + +#endif + +/**************************************************************************************** +* Sanguinololu pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 62 +#define MOTHERBOARD 6 +#define SANGUINOLOLU_V_1_2 +#endif +#if MOTHERBOARD == 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -2 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 1 +#define E_DIR_PIN 0 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) + +#ifdef SANGUINOLOLU_V_1_2 + +#define HEATER_1_PIN 12 // (bed) +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E_ENABLE_PIN 14 + +#else + +#define HEATER_1_PIN 14 // (bed) +#define X_ENABLE_PIN -1 +#define Y_ENABLE_PIN -1 +#define Z_ENABLE_PIN -1 +#define E_ENABLE_PIN -1 + +#endif + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 31 +#define HEATER_2_PIN -1 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_1_PIN 4 +#define TEMP_1_PIN 11 + +#define EXTRUDER_0_STEP_PIN 43 +#define EXTRUDER_0_DIR_PIN 45 +#define EXTRUDER_0_ENABLE_PIN 41 +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define EXTRUDER_1_STEP_PIN 49 +#define EXTRUDER_1_DIR_PIN 47 +#define EXTRUDER_1_ENABLE_PIN 51 +#define EXTRUDER_1_HEATER_PIN 3 +#define EXTRUDER_1_TEMPERATURE_PIN 10 +#define HEATER_2_PIN 51 +#define TEMP_2_PIN 3 + + + +#define E_STEP_PIN EXTRUDER_0_STEP_PIN +#define E_DIR_PIN EXTRUDER_0_DIR_PIN +#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + //buttons are attached to a shift register + #define SHIFT_CLK 38 + #define SHIFT_LD 42 + #define SHIFT_OUT 40 + #define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 5 + #define LCD_PINS_D4 6 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 20 + #define LCD_PINS_D7 19 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + +#endif + +/**************************************************************************************** +* Teensylu 0.7 pin assingments (ATMEGA90USB) +* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! +****************************************************************************************/ +#if MOTHERBOARD == 8 +#define MOTHERBOARD 8 +#define KNOWN_BOARD 1 + + +#define X_STEP_PIN 0 +#define X_DIR_PIN 1 +#define X_ENABLE_PIN 39 +#define X_MIN_PIN 13 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 2 +#define Y_DIR_PIN 3 +#define Y_ENABLE_PIN 38 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 4 +#define Z_DIR_PIN 5 +#define Z_ENABLE_PIN 23 +#define Z_MIN_PIN 15 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 6 +#define E_DIR_PIN 7 +#define E_ENABLE_PIN 19 + + + +#define HEATER_0_PIN 21 // Extruder +#define HEATER_1_PIN 20 // Bed +#define HEATER_2_PIN -1 +#define FAN_PIN 22 // Fan + +#define TEMP_0_PIN 7 // Extruder +#define TEMP_1_PIN 6 // Bed +#define TEMP_2_PIN -1 + +#define SDPOWER -1 +#define SDSS 8 +#define LED_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define ALARM_PIN -1 + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define SCK_PIN 9 + #define MISO_PIN 11 + #define MOSI_PIN 10 +#endif +#endif + +#ifndef KNOWN_BOARD +#error Unknown MOTHERBOARD value in configuration.h +#endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} + #endif From 79d1bfb5c02793c88f554002e04b5263d81703b7 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 19:36:29 +0100 Subject: [PATCH 020/228] made many possible variables static, so they cannot be used extern. --- Marlin/planner.cpp | 7 ++++-- Marlin/temperature.cpp | 48 +++++++++++++++++++++++------------------- Marlin/ultralcd.pde | 15 +++++++------ 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index b4271bab35..888fe45c8f 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -65,6 +65,7 @@ #include "temperature.h" #include "ultralcd.h" +//public variables unsigned long minsegmenttime; float max_feedrate[4]; // set the max speeds float axis_steps_per_unit[4]; @@ -76,14 +77,16 @@ float max_xy_jerk; //speed than can be stopped at once, if i understand correctl float max_z_jerk; float mintravelfeedrate; unsigned long axis_steps_per_sqr_second[NUM_AXIS]; -// Manage heater variables. +long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode + +//private variables static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions static volatile unsigned char block_buffer_head; // Index of the next block to be pushed static volatile unsigned char block_buffer_tail; // Index of the block to process now // The current position of the tool in absolute steps -long position[4]; + #define ONE_MINUTE_OF_MICROSECONDS 60000000.0 diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index c25b9c3120..1121c654ee 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -42,25 +42,29 @@ int target_raw[3] = {0, 0, 0}; int current_raw[3] = {0, 0, 0}; -bool temp_meas_ready = false; +static bool temp_meas_ready = false; -unsigned long previous_millis_heater, previous_millis_bed_heater; +static unsigned long previous_millis_heater, previous_millis_bed_heater; #ifdef PIDTEMP - float temp_iState = 0; - float temp_dState = 0; - float pTerm; - float iTerm; - float dTerm; + //static cannot be external: + static float temp_iState = 0; + static float temp_dState = 0; + static float pTerm; + static float iTerm; + static float dTerm; //int output; - float pid_error; - float temp_iState_min; - float temp_iState_max; - float pid_setpoint = 0.0; - float pid_input; - float pid_output; - bool pid_reset; + static float pid_error; + static float temp_iState_min; + static float temp_iState_max; + static float pid_input; + static float pid_output; + static bool pid_reset; + + // probably used external float HeaterPower; + float pid_setpoint = 0.0; + float Kp=DEFAULT_Kp; float Ki=DEFAULT_Ki; @@ -69,29 +73,29 @@ unsigned long previous_millis_heater, previous_millis_bed_heater; #endif //PIDTEMP #ifdef WATCHPERIOD - int watch_raw[3] = {-1000,-1000,-1000}; - unsigned long watchmillis = 0; + static int watch_raw[3] = {-1000,-1000,-1000}; + static unsigned long watchmillis = 0; #endif //WATCHPERIOD #ifdef HEATER_0_MINTEMP - int minttemp_0 = temp2analog(HEATER_0_MINTEMP); + static int minttemp_0 = temp2analog(HEATER_0_MINTEMP); #endif //MINTEMP #ifdef HEATER_0_MAXTEMP - int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); + static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); #endif //MAXTEMP #ifdef HEATER_1_MINTEMP - int minttemp_1 = temp2analog(HEATER_1_MINTEMP); + static int minttemp_1 = temp2analog(HEATER_1_MINTEMP); #endif //MINTEMP #ifdef HEATER_1_MAXTEMP - int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); + static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); #endif //MAXTEMP #ifdef BED_MINTEMP - int bed_minttemp = temp2analog(BED_MINTEMP); + static int bed_minttemp = temp2analog(BED_MINTEMP); #endif //BED_MINTEMP #ifdef BED_MAXTEMP - int bed_maxttemp = temp2analog(BED_MAXTEMP); + static int bed_maxttemp = temp2analog(BED_MAXTEMP); #endif //BED_MAXTEMP void manage_heater() diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index a45b3683e7..a0c56e926a 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -3,14 +3,17 @@ extern volatile int feedmultiply; +extern volatile bool feedmultiplychanged; + extern long position[4]; -char messagetext[LCD_WIDTH]=""; +static char messagetext[LCD_WIDTH]=""; #include 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 -unsigned long previous_millis_lcd=0; +static unsigned long previous_millis_lcd=0; +static long previous_millis_buttons=0; inline int intround(const float &x){return int(0.5+x);} @@ -18,9 +21,9 @@ volatile char buttons=0; //the last checked buttons in a bit array. int encoderpos=0; short lastenc=0; #ifdef NEWPANEL - long blocking=0; + static long blocking=0; #else - long blocking[8]={0,0,0,0,0,0,0,0}; + static long blocking[8]={0,0,0,0,0,0,0,0}; #endif MainMenu menu; @@ -31,10 +34,9 @@ void lcd_status(const char* message) inline void clear() { - lcd.clear(); } -long previous_millis_buttons=0; + void lcd_init() { @@ -228,7 +230,6 @@ MainMenu::MainMenu() linechanging=false; } -extern volatile bool feedmultiplychanged; void MainMenu::showStatus() { From 5cf349a24a610d7223c5bc88193c07c713818028 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 6 Nov 2011 19:37:12 +0100 Subject: [PATCH 021/228] Fixed some arc bugs --- Marlin/Marlin.pde | 113 ++------------------------------------ Marlin/motion_control.cpp | 13 +++-- 2 files changed, 12 insertions(+), 114 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 6c2c6c87a4..4cbe570884 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1139,8 +1139,8 @@ inline void get_coordinates() inline void get_arc_coordinates() { get_coordinates(); - if(code_seen("I")) offset[0] = code_value(); - if(code_seen("J")) offset[1] = code_value(); + if(code_seen('I')) offset[0] = code_value(); + if(code_seen('J')) offset[1] = code_value(); } void prepare_move() @@ -1152,119 +1152,16 @@ void prepare_move() } void prepare_arc_move(char isclockwise) { -#if 0 - if (radius_mode) { - /* - We need to calculate the center of the circle that has the designated radius and passes - through both the current position and the target position. This method calculates the following - set of equations where [x,y] is the vector from current to target position, d == magnitude of - that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to - the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the - length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point - [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc. - - d^2 == x^2 + y^2 - h^2 == r^2 - (d/2)^2 - i == x/2 - y/d*h - j == y/2 + x/d*h - - O <- [i,j] - - | - r - | - - | - - | h - - | - [0,0] -> C -----------------+--------------- T <- [x,y] - | <------ d/2 ---->| - - C - Current position - T - Target position - O - center of circle that pass through both C and T - d - distance from C to T - r - designated radius - h - distance from center of CT to O - - Expanding the equations: - - d -> sqrt(x^2 + y^2) - h -> sqrt(4 * r^2 - x^2 - y^2)/2 - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 - - Which can be written: - - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 - - Which we for size and speed reasons optimize to: - - h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) - i = (x - (y * h_x2_div_d))/2 - j = (y + (x * h_x2_div_d))/2 - - */ - - // Calculate the change in position along each selected axis - double x = target[gc.plane_axis_0]-gc.position[gc.plane_axis_0]; - double y = target[gc.plane_axis_1]-gc.position[gc.plane_axis_1]; - - clear_vector(offset); - double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d) - // If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any - // real CNC, and thus - for practical reasons - we will terminate promptly: - if(isnan(h_x2_div_d)) { FAIL(STATUS_FLOATING_POINT_ERROR); return(gc.status_code); } - // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) - if (gc.motion_mode == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; } - - /* The counter clockwise circle lies to the left of the target direction. When offset is positive, - the left hand circle will be generated - when it is negative the right hand circle is generated. - - - T <-- Target position - - ^ - Clockwise circles with this center | Clockwise circles with this center will have - will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing! - \ | / - center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative - | - | - - C <-- Current position */ - - - // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!), - // even though it is advised against ever generating such circles in a single line of g-code. By - // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of - // travel and thus we get the unadvisably long arcs as prescribed. - if (r < 0) { - h_x2_div_d = -h_x2_div_d; - r = -r; // Finished with r. Set to positive for mc_arc - } - // Complete the operation by calculating the actual center of the arc - offset[gc.plane_axis_0] = 0.5*(x-(y*h_x2_div_d)); - offset[gc.plane_axis_1] = 0.5*(y+(x*h_x2_div_d)); - - } else { // Offset mode specific computations -#endif - float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc - -// } - - // Set clockwise/counter-clockwise sign for mc_arc computations -// uint8_t isclockwise = false; -// if (gc.motion_mode == MOTION_MODE_CW_ARC) { isclockwise = true; } + 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.0/100.0, r, isclockwise); - -// } // 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(int ii=0; ii < NUM_AXIS; ii++) { - current_position[ii] = destination[ii]; + for(int i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; } } diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index 75396143aa..c2fce52c71 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -19,12 +19,8 @@ along with Grbl. If not, see . */ -//#include "motion_control.h" #include "Configuration.h" #include "Marlin.h" -//#include -//#include -//#include #include "stepper.h" #include "planner.h" @@ -35,10 +31,10 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 { // int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); // plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc - SERIAL_ECHOLN("mc_arc."); float center_axis0 = position[axis_0] + offset[axis_0]; float center_axis1 = position[axis_1] + offset[axis_1]; float linear_travel = target[axis_linear] - position[axis_linear]; + float extruder_travel = target[E_AXIS] - position[E_AXIS]; float r_axis0 = -offset[axis_0]; // Radius vector from center to current location float r_axis1 = -offset[axis_1]; float rt_axis0 = target[axis_0] - center_axis0; @@ -60,6 +56,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 */ float theta_per_segment = angular_travel/segments; float linear_per_segment = linear_travel/segments; + float extruder_per_segment = extruder_travel/segments; /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector, and phi is the angle of rotation. Based on the solution approach by Jens Geisler. @@ -90,7 +87,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation float sin_T = theta_per_segment; - float arc_target[3]; + float arc_target[4]; float sin_Ti; float cos_Ti; float r_axisi; @@ -99,6 +96,9 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 // Initialize the linear axis arc_target[axis_linear] = position[axis_linear]; + + // Initialize the extruder axis + arc_target[E_AXIS] = position[E_AXIS]; for (i = 1; i Date: Sun, 6 Nov 2011 19:48:37 +0100 Subject: [PATCH 022/228] static'ified Marlin.pde. --- Marlin/Configuration.h | 14 ++- Marlin/Marlin.pde | 223 ++++++++++++++++++++++------------------- 2 files changed, 127 insertions(+), 110 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index b437bfb01f..722cb9642d 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -61,11 +61,11 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define ULTIPANEL #define ULTIPANEL #ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 -#define LCD_HEIGHT 4 + //#define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 + #define LCD_HEIGHT 4 #else //no panel but just lcd #ifdef ULTRA_LCD #define LCD_WIDTH 16 @@ -251,4 +251,8 @@ const int dropsegments=5; //everything with this number of steps will be ignore #define BLOCK_BUFFER_SIZE 16 // maximize block buffer #endif +//The ASCII buffer for recieving from the serial: +#define MAX_CMD_SIZE 96 +#define BUFSIZE 4 + #endif //__CONFIGURATION_H diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 6c2c6c87a4..5a489ec522 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -107,68 +107,82 @@ char version_string[] = "1.0.0 Alpha 1"; //Stepper Movement Variables -const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; -float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; -float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; -float offset[3] = {0.0, 0.0, 0.0}; -bool home_all_axis = true; -float feedrate = 1500.0, next_feedrate, saved_feedrate; -long gcode_N, gcode_LastN; +//=========================================================================== +//=============================imported variables============================ +//=========================================================================== +extern float HeaterPower; +//public variables float homing_feedrate[] = HOMING_FEEDRATE; bool axis_relative_modes[] = AXIS_RELATIVE_MODES; - -bool relative_mode = false; //Determines Absolute or Relative Coordinates -bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. - -uint8_t fanpwm=0; - volatile int feedmultiply=100; //100->1 200->2 int saved_feedmultiply; volatile bool feedmultiplychanged=false; +//=========================================================================== +//=============================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 current_position[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; + + + +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 uint8_t fanpwm=0; + + // comm variables -#define MAX_CMD_SIZE 96 -#define BUFSIZE 4 -char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; -bool fromsd[BUFSIZE]; -int bufindr = 0; -int bufindw = 0; -int buflen = 0; -int i = 0; -char serial_char; -int serial_count = 0; -boolean comment_mode = false; -char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc -extern float HeaterPower; + +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 -float tt = 0, bt = 0; +static float tt = 0, bt = 0; //Inactivity shutdown variables -unsigned long previous_millis_cmd = 0; -unsigned long max_inactive_time = 0; -unsigned long stepper_inactive_time = 0; +static unsigned long previous_millis_cmd = 0; +static unsigned long max_inactive_time = 0; +static unsigned long stepper_inactive_time = 0; + +static unsigned long starttime=0; +static unsigned long stoptime=0; -unsigned long starttime=0; -unsigned long stoptime=0; #ifdef SDSUPPORT - Sd2Card card; - SdVolume volume; - SdFile root; - SdFile file; - uint32_t filesize = 0; - uint32_t sdpos = 0; - bool sdmode = false; - bool sdactive = false; - bool savetosd = false; - int16_t n; - unsigned long autostart_atmillis=0; + static Sd2Card card; + static SdVolume volume; + static SdFile root; + static SdFile file; + static uint32_t filesize = 0; + static uint32_t sdpos = 0; + static bool sdmode = false; + static bool sdactive = false; + static bool savetosd = false; + static int16_t n; + static unsigned long autostart_atmillis=0; - bool autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. - + static bool autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. +#endif //SDSUPPORT +//=========================================================================== +//=============================ROUTINES============================= +//=========================================================================== +#ifdef SDSUPPORT void initsd() { sdactive = false; @@ -223,6 +237,65 @@ unsigned long stoptime=0; SERIAL_ERRORLN("error writing to file"); } } + + + void checkautostart(bool force) + { + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + //sprintf(cmd,"M115"); + //enquecommand("G92 Z0"); + //enquecommand("G1 Z10 F2000"); + //enquecommand("G28 X-105 Y-105"); + enquecommand(cmd); + enquecommand("M24"); + found=true; + } + } + if(!found) + lastnr=-1; + else + lastnr++; + } +#else //NO SD SUPORT + inline void checkautostart(bool x){}; + #endif //SDSUPPORT @@ -272,66 +345,6 @@ void setup() tp_init(); // Initialize temperature loop } -#ifdef SDSUPPORT - -void checkautostart(bool force) -{ -//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) - { - for(int i=0;i<(int)strlen((char*)p.name);i++) - p.name[i]=tolower(p.name[i]); - //Serial.print((char*)p.name); - //Serial.print(" "); - //Serial.println(autoname); - if(p.name[9]!='~') //skip safety copies - if(strncmp((char*)p.name,autoname,5)==0) - { - char cmd[30]; - - sprintf(cmd,"M23 %s",autoname); - //sprintf(cmd,"M115"); - //enquecommand("G92 Z0"); - //enquecommand("G1 Z10 F2000"); - //enquecommand("G28 X-105 Y-105"); - enquecommand(cmd); - enquecommand("M24"); - found=true; - } - } - if(!found) - lastnr=-1; - else - lastnr++; -} -#else //NO SD SUPORT - inline void checkautostart(bool x){} -#endif - void loop() { From 01df04e02c6a94446e19176946b353d701268c93 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 21:39:53 +0100 Subject: [PATCH 023/228] first compile with the cardreader class --- Marlin/Marlin.pde | 229 +++++++++--------------------------------- Marlin/cardreader.h | 47 +++++++++ Marlin/cardreader.pde | 177 ++++++++++++++++++++++++++++++++ Marlin/ultralcd.h | 3 +- Marlin/ultralcd.pde | 81 ++++----------- 5 files changed, 288 insertions(+), 249 deletions(-) create mode 100644 Marlin/cardreader.h create mode 100644 Marlin/cardreader.pde diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index fec01b8c39..5351bce07b 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -37,13 +37,11 @@ #include "stepper.h" #include "temperature.h" #include "motion_control.h" +#include "cardreader.h" char version_string[] = "1.0.0 Alpha 1"; -#ifdef SDSUPPORT - #include "SdFat.h" -#endif //SDSUPPORT // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html @@ -112,7 +110,11 @@ char version_string[] = "1.0.0 Alpha 1"; //=========================================================================== extern float HeaterPower; -//public variables + +//=========================================================================== +//=============================public variables============================= +//=========================================================================== +CardReader card; float homing_feedrate[] = HOMING_FEEDRATE; bool axis_relative_modes[] = AXIS_RELATIVE_MODES; volatile int feedmultiply=100; //100->1 200->2 @@ -138,7 +140,6 @@ static bool relative_mode_e = false; //Determines Absolute or Relative E Codes static uint8_t fanpwm=0; -// comm variables static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; static bool fromsd[BUFSIZE]; @@ -163,140 +164,12 @@ static unsigned long stepper_inactive_time = 0; static unsigned long starttime=0; static unsigned long stoptime=0; -#ifdef SDSUPPORT - static Sd2Card card; - static SdVolume volume; - static SdFile root; - static SdFile file; - static uint32_t filesize = 0; - static uint32_t sdpos = 0; - static bool sdmode = false; - static bool sdactive = false; - static bool savetosd = false; - static int16_t n; - static unsigned long autostart_atmillis=0; - - static bool autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. -#endif //SDSUPPORT + //=========================================================================== //=============================ROUTINES============================= //=========================================================================== -#ifdef SDSUPPORT - void initsd() - { - sdactive = false; - #if SDSS >- 1 - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)) - { - //if (!card.init(SPI_HALF_SPEED,SDSS)) - SERIAL_ECHOLN("SD init fail"); - } - else if (!volume.init(&card)) - { - SERIAL_ERRORLN("volume.init failed"); - } - else if (!root.openRoot(&volume)) - { - SERIAL_ERRORLN("openRoot failed"); - } - else - { - sdactive = true; - SERIAL_ECHOLN("SD card ok"); - } - #endif //SDSS - } - void quickinitsd() - { - sdactive=false; - autostart_atmillis=millis()+5000; - } - - inline void write_command(char *buf) - { - char* begin = buf; - char* npos = 0; - char* end = buf + strlen(buf) - 1; - - file.writeError = false; - if((npos = strchr(buf, 'N')) != NULL) - { - begin = strchr(npos, ' ') + 1; - end = strchr(npos, '*') - 1; - } - end[1] = '\r'; - end[2] = '\n'; - end[3] = '\0'; - file.write(begin); - if (file.writeError) - { - SERIAL_ERRORLN("error writing to file"); - } - } - - - void checkautostart(bool force) - { - //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) - { - for(int i=0;i<(int)strlen((char*)p.name);i++) - p.name[i]=tolower(p.name[i]); - //Serial.print((char*)p.name); - //Serial.print(" "); - //Serial.println(autoname); - if(p.name[9]!='~') //skip safety copies - if(strncmp((char*)p.name,autoname,5)==0) - { - char cmd[30]; - - sprintf(cmd,"M23 %s",autoname); - //sprintf(cmd,"M115"); - //enquecommand("G92 Z0"); - //enquecommand("G1 Z10 F2000"); - //enquecommand("G28 X-105 Y-105"); - enquecommand(cmd); - enquecommand("M24"); - found=true; - } - } - if(!found) - lastnr=-1; - else - lastnr++; - } -#else //NO SD SUPORT - inline void checkautostart(bool x){}; - -#endif //SDSUPPORT //adds an command to the main command buffer @@ -331,14 +204,6 @@ void setup() axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; } - #ifdef SDSUPPORT - //power to SD reader - #if SDPOWER > -1 - SET_OUTPUT(SDPOWER); - WRITE(SDPOWER,HIGH); - #endif //SDPOWER - quickinitsd(); - #endif //SDSUPPORT plan_init(); // Initialize planner; st_init(); // Initialize stepper; @@ -350,22 +215,20 @@ void loop() { if(buflen<3) get_command(); - checkautostart(false); + card.checkautostart(false); if(buflen) { #ifdef SDSUPPORT - if(savetosd) + if(card.savetosd) { if(strstr(cmdbuffer[bufindr],"M29") == NULL) { - write_command(cmdbuffer[bufindr]); + card.write_command(cmdbuffer[bufindr]); Serial.println("ok"); } else { - file.sync(); - file.close(); - savetosd = false; + card.closefile(); Serial.println("Done saving file."); } } @@ -455,7 +318,7 @@ inline void get_command() case 2: case 3: #ifdef SDSUPPORT - if(savetosd) + if(card.savetosd) break; #endif //SDSUPPORT Serial.println("ok"); @@ -479,17 +342,17 @@ inline void get_command() } } #ifdef SDSUPPORT - if(!sdmode || serial_count!=0){ + if(!card.sdmode || serial_count!=0){ return; } - while( filesize > sdpos && buflen < BUFSIZE) { - n = file.read(); + while( card.filesize > card.sdpos && buflen < BUFSIZE) { + short n = card.file.read(); serial_char = (char)n; if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) { - sdpos = file.curPosition(); - if(sdpos >= filesize){ - sdmode = false; + card.sdpos = card.file.curPosition(); + if(card.sdpos >= card.filesize){ + card.sdmode = false; Serial.println("echo: Done printing file"); stoptime=millis(); char time[30]; @@ -500,7 +363,7 @@ inline void get_command() sprintf(time,"echo: %i min, %i sec",min,sec); Serial.println(time); LCD_MESSAGE(time); - checkautostart(true); + card.checkautostart(true); } if(!serial_count) return; //if empty line @@ -702,31 +565,31 @@ inline void process_commands() case 20: // M20 - list SD card Serial.println("Begin file list"); - root.ls(); + card.root.ls(); Serial.println("End file list"); break; case 21: // M21 - init SD card - sdmode = false; - initsd(); + card.sdmode = false; + card.initsd(); break; case 22: //M22 - release SD card - sdmode = false; - sdactive = false; + card.sdmode = false; + card.sdactive = false; break; case 23: //M23 - Select file - if(sdactive){ - sdmode = false; - file.close(); + if(card.sdactive){ + card.sdmode = false; + card.file.close(); starpos = (strchr(strchr_pointer + 4,'*')); if(starpos!=NULL) *(starpos-1)='\0'; - if (file.open(&root, strchr_pointer + 4, O_READ)) { + if (card.file.open(&card.root, strchr_pointer + 4, O_READ)) { Serial.print("File opened:"); Serial.print(strchr_pointer + 4); Serial.print(" Size:"); - Serial.println(file.fileSize()); - sdpos = 0; - filesize = file.fileSize(); + Serial.println(card.file.fileSize()); + card.sdpos = 0; + card.filesize = card.file.fileSize(); Serial.println("File selected"); } else{ @@ -735,52 +598,52 @@ inline void process_commands() } break; case 24: //M24 - Start SD print - if(sdactive){ - sdmode = true; + if(card.sdactive){ + card.sdmode = true; starttime=millis(); } break; case 25: //M25 - Pause SD print - if(sdmode){ - sdmode = false; + if(card.sdmode){ + card.sdmode = false; } break; case 26: //M26 - Set SD index - if(sdactive && code_seen('S')){ - sdpos = code_value_long(); - file.seekSet(sdpos); + if(card.sdactive && code_seen('S')){ + card.sdpos = code_value_long(); + card.file.seekSet(card.sdpos); } break; case 27: //M27 - Get SD status - if(sdactive){ + if(card.sdactive){ Serial.print("SD printing byte "); - Serial.print(sdpos); + Serial.print(card.sdpos); Serial.print("/"); - Serial.println(filesize); + Serial.println(card.filesize); } else{ Serial.println("Not SD printing"); } break; case 28: //M28 - Start SD write - if(sdactive){ + if(card.sdactive){ char* npos = 0; - file.close(); - sdmode = false; + card.file.close(); + card.sdmode = false; starpos = (strchr(strchr_pointer + 4,'*')); if(starpos != NULL){ npos = strchr(cmdbuffer[bufindr], 'N'); strchr_pointer = strchr(npos,' ') + 1; *(starpos-1) = '\0'; } - if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + if (!card.file.open(&card.root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) { Serial.print("open failed, File: "); Serial.print(strchr_pointer + 4); Serial.print("."); } else{ - savetosd = true; + card.savetosd = true; Serial.print("Writing to file: "); Serial.println(strchr_pointer + 4); } diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h new file mode 100644 index 0000000000..a67374ffa9 --- /dev/null +++ b/Marlin/cardreader.h @@ -0,0 +1,47 @@ +#ifndef __CARDREADERH +#define __CARDREADERH + +#ifdef SDSUPPORT + +#include "SdFat.h" + +class CardReader +{ +public: + CardReader(); + + void initsd(); + void write_command(char *buf); + //files auto[0-9].g on the sd card are performed in a row + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + + void checkautostart(bool x); + + void closefile(); + void getfilename(const uint8_t nr); + uint8_t getnrfilenames(); + +public: + bool savetosd; + SdFile file; + uint32_t filesize; + uint32_t sdpos ; + bool sdmode ; + SdFile root; + bool sdactive ; + char filename[11]; +private: + Sd2Card card; + SdVolume volume; + + //int16_t n; + unsigned long autostart_atmillis; + + bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. +}; + +#endif //SDSUPPORT + + + +#endif \ No newline at end of file diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde new file mode 100644 index 0000000000..5773641e4f --- /dev/null +++ b/Marlin/cardreader.pde @@ -0,0 +1,177 @@ +#ifdef SDSUPPORT +#include "cardreader.h" + +CardReader::CardReader() +{ + filesize = 0; + sdpos = 0; + sdmode = false; + sdactive = false; + savetosd = false; + autostart_atmillis=0; + + autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. + //power to SD reader + #if SDPOWER > -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); + #endif //SDPOWER + + autostart_atmillis=millis()+5000; +} + +void CardReader::initsd() +{ + sdactive = false; + #if SDSS >- 1 + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)) + { + //if (!card.init(SPI_HALF_SPEED,SDSS)) + SERIAL_ECHOLN("SD init fail"); + } + else if (!volume.init(&card)) + { + SERIAL_ERRORLN("volume.init failed"); + } + else if (!root.openRoot(&volume)) + { + SERIAL_ERRORLN("openRoot failed"); + } + else + { + sdactive = true; + SERIAL_ECHOLN("SD card ok"); + } + #endif //SDSS +} + +void CardReader::write_command(char *buf) +{ + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL) + { + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + file.write(begin); + if (file.writeError) + { + SERIAL_ERRORLN("error writing to file"); + } +} + + +void CardReader::checkautostart(bool force) +{ + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + enquecommand(cmd); + enquecommand("M24"); + found=true; + } + } + if(!found) + lastnr=-1; + else + lastnr++; +} + +void CardReader::closefile() +{ + file.sync(); + file.close(); + savetosd = false; +} + +void CardReader::getfilename(const uint8_t nr) +{ + + dir_t p; + root.rewind(); + uint8_t cnt=0; + filename[0]='\0'; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + if(cnt++!=nr) continue; + //Serial.println((char*)p.name); + uint8_t writepos=0; + for (uint8_t i = 0; i < 11; i++) + { + if (p.name[i] == ' ') continue; + if (i == 8) { + filename[writepos++]='.'; + } + filename[writepos++]=p.name[i]; + } + filename[writepos++]=0; + } +} + +uint8_t CardReader::getnrfilenames() +{ + dir_t p; + root.rewind(); + uint8_t cnt=0; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + cnt++; + } + return cnt; +} + + +#endif //SDSUPPORT \ No newline at end of file diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 18d1b7f249..0822e502b0 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -57,7 +57,6 @@ public: MainMenu(); void update(); - void getfilename(const uint8_t nr); uint8_t activeline; MainStatus status; uint8_t displayStartingRow; @@ -71,7 +70,7 @@ int lastencoderpos; int8_t lineoffset; int8_t lastlineoffset; - char filename[11]; + bool linechanging; }; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index a0c56e926a..121d8ff7fe 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -6,6 +6,7 @@ extern volatile int feedmultiply; extern volatile bool feedmultiplychanged; extern long position[4]; +extern CardReader card; static char messagetext[LCD_WIDTH]=""; @@ -1107,56 +1108,8 @@ void MainMenu::showControl() #include "SdFat.h" -void MainMenu::getfilename(const uint8_t nr) -{ -#ifdef SDSUPPORT - dir_t p; - root.rewind(); - uint8_t cnt=0; - filename[0]='\0'; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - if(cnt++!=nr) continue; - //Serial.println((char*)p.name); - uint8_t writepos=0; - for (uint8_t i = 0; i < 11; i++) - { - if (p.name[i] == ' ') continue; - if (i == 8) { - filename[writepos++]='.'; - } - filename[writepos++]=p.name[i]; - } - filename[writepos++]=0; - } -#endif -} -uint8_t getnrfilenames() -{ -#ifdef SDSUPPORT - dir_t p; - root.rewind(); - uint8_t cnt=0; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - cnt++; - } - return cnt; -#else - return 0; -#endif -} + void MainMenu::showSD() { @@ -1171,9 +1124,9 @@ void MainMenu::showSD() if(force_lcd_update) { clear(); - if(sdactive) + if(card.sdactive) { - nrfiles=getnrfilenames(); + nrfiles=card.getnrfilenames(); } else { @@ -1223,9 +1176,9 @@ void MainMenu::showSD() { BLOCK; beepshort(); - initsd(); + card.initsd(); force_lcd_update=true; - nrfiles=getnrfilenames(); + nrfiles=card.getnrfilenames(); } }break; default: @@ -1234,24 +1187,24 @@ void MainMenu::showSD() { if(force_lcd_update) { - getfilename(i-2); + card.getfilename(i-2); //Serial.print("Filenr:");Serial.println(i-2); - lcd.setCursor(0,line);lcd.print(" ");lcd.print(filename); + lcd.setCursor(0,line);lcd.print(" ");lcd.print(card.filename); } if((activeline==line) && CLICKED) { BLOCK - getfilename(i-2); + card.getfilename(i-2); char cmd[30]; - for(int i=0;i Date: Sun, 6 Nov 2011 22:37:43 +0100 Subject: [PATCH 024/228] Corrected thermistor naming --- Marlin/Configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index d417d415cf..a0d46bfed7 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -27,8 +27,8 @@ // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 +#define THERMISTORHEATER_0 3 #define THERMISTORHEATER_1 3 -#define THERMISTORHEATER_2 3 #define THERMISTORBED 3 //#define HEATER_0_USES_THERMISTOR From fc0064e525288baec961db28c6c4d07f3206f145 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 22:48:15 +0100 Subject: [PATCH 025/228] made cardreader more selfsustained --- Marlin/Marlin.pde | 107 +++++++++++++----------------------------- Marlin/cardreader.h | 38 ++++++++++----- Marlin/cardreader.pde | 96 +++++++++++++++++++++++++++++++++---- Marlin/ultralcd.pde | 8 ++-- 4 files changed, 149 insertions(+), 100 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 5351bce07b..03d3603265 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -219,7 +219,7 @@ void loop() if(buflen) { #ifdef SDSUPPORT - if(card.savetosd) + if(card.saving) { if(strstr(cmdbuffer[bufindr],"M29") == NULL) { @@ -318,7 +318,7 @@ inline void get_command() case 2: case 3: #ifdef SDSUPPORT - if(card.savetosd) + if(card.saving) break; #endif //SDSUPPORT Serial.println("ok"); @@ -342,17 +342,17 @@ inline void get_command() } } #ifdef SDSUPPORT - if(!card.sdmode || serial_count!=0){ + if(!card.sdprinting || serial_count!=0){ return; } - while( card.filesize > card.sdpos && buflen < BUFSIZE) { - short n = card.file.read(); - serial_char = (char)n; - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) + while( !card.eof() && buflen < BUFSIZE) { + + serial_char = card.get(); + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)) { - card.sdpos = card.file.curPosition(); - if(card.sdpos >= card.filesize){ - card.sdmode = false; + + if(card.eof()){ + card.sdprinting = false; Serial.println("echo: Done printing file"); stoptime=millis(); char time[30]; @@ -565,93 +565,52 @@ inline void process_commands() case 20: // M20 - list SD card Serial.println("Begin file list"); - card.root.ls(); + card.ls(); Serial.println("End file list"); break; case 21: // M21 - init SD card - card.sdmode = false; + card.initsd(); break; case 22: //M22 - release SD card - card.sdmode = false; - card.sdactive = false; + card.release(); + break; case 23: //M23 - Select file - if(card.sdactive){ - card.sdmode = false; - card.file.close(); - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos!=NULL) - *(starpos-1)='\0'; - if (card.file.open(&card.root, strchr_pointer + 4, O_READ)) { - Serial.print("File opened:"); - Serial.print(strchr_pointer + 4); - Serial.print(" Size:"); - Serial.println(card.file.fileSize()); - card.sdpos = 0; - card.filesize = card.file.fileSize(); - Serial.println("File selected"); - } - else{ - Serial.println("file.open failed"); - } - } + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos!=NULL) + *(starpos-1)='\0'; + card.selectFile(strchr_pointer + 4); break; case 24: //M24 - Start SD print - if(card.sdactive){ - card.sdmode = true; - starttime=millis(); - } + card.startFileprint(); + starttime=millis(); break; case 25: //M25 - Pause SD print - if(card.sdmode){ - card.sdmode = false; - } + card.pauseSDPrint(); break; case 26: //M26 - Set SD index - if(card.sdactive && code_seen('S')){ - card.sdpos = code_value_long(); - card.file.seekSet(card.sdpos); + if(card.cardOK && code_seen('S')){ + card.setIndex(code_value_long()); + } break; case 27: //M27 - Get SD status - if(card.sdactive){ - Serial.print("SD printing byte "); - Serial.print(card.sdpos); - Serial.print("/"); - Serial.println(card.filesize); - } - else{ - Serial.println("Not SD printing"); - } + card.getStatus(); break; case 28: //M28 - Start SD write - if(card.sdactive){ - char* npos = 0; - card.file.close(); - card.sdmode = false; - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos != NULL){ - npos = strchr(cmdbuffer[bufindr], 'N'); - strchr_pointer = strchr(npos,' ') + 1; - *(starpos-1) = '\0'; - } - if (!card.file.open(&card.root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) - { - Serial.print("open failed, File: "); - Serial.print(strchr_pointer + 4); - Serial.print("."); - } - else{ - card.savetosd = true; - Serial.print("Writing to file: "); - Serial.println(strchr_pointer + 4); - } + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos != NULL){ + char* npos = strchr(cmdbuffer[bufindr], 'N'); + strchr_pointer = strchr(npos,' ') + 1; + *(starpos-1) = '\0'; } + card.startFilewrite(strchr_pointer+4); + break; case 29: //M29 - Stop SD write //processed in write to file routine above - //savetosd = false; + //card,saving = false; break; #endif //SDSUPPORT diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index a67374ffa9..583c55c74a 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -18,26 +18,38 @@ public: void checkautostart(bool x); void closefile(); + void release(); + void startFileprint(); + void startFilewrite(char *name); + void pauseSDPrint(); + void getStatus(); + + void selectFile(char* name); void getfilename(const uint8_t nr); uint8_t getnrfilenames(); + + + inline void ls() {root.ls();}; + inline bool eof() { sdpos = file.curPosition();return sdpos>=filesize ;}; + inline char get() { int16_t n = file.read(); return (n!=-1)?(char)n:'\n';}; + inline void setIndex(long index) {sdpos = index;file.seekSet(index);}; public: - bool savetosd; - SdFile file; - uint32_t filesize; - uint32_t sdpos ; - bool sdmode ; - SdFile root; - bool sdactive ; + bool saving; + bool sdprinting ; + bool cardOK ; char filename[11]; private: - Sd2Card card; - SdVolume volume; + SdFile root; + Sd2Card card; + SdVolume volume; + SdFile file; + uint32_t filesize; + //int16_t n; + unsigned long autostart_atmillis; + uint32_t sdpos ; - //int16_t n; - unsigned long autostart_atmillis; - - bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. + bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. }; #endif //SDSUPPORT diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 5773641e4f..9f94de0bcd 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -5,9 +5,9 @@ CardReader::CardReader() { filesize = 0; sdpos = 0; - sdmode = false; - sdactive = false; - savetosd = false; + sdprinting = false; + cardOK = false; + saving = false; autostart_atmillis=0; autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. @@ -22,7 +22,7 @@ CardReader::CardReader() void CardReader::initsd() { - sdactive = false; + cardOK = false; #if SDSS >- 1 if(root.isOpen()) root.close(); @@ -41,12 +41,90 @@ void CardReader::initsd() } else { - sdactive = true; + cardOK = true; SERIAL_ECHOLN("SD card ok"); } #endif //SDSS } +void CardReader::release() +{ + sdprinting = false; + cardOK = false; +} +void CardReader::startFileprint() +{ + if(cardOK) + { + sdprinting = true; + + } +} + +void CardReader::pauseSDPrint() +{ + if(sdprinting) + { + sdprinting = false; + } +} + +void CardReader::selectFile(char* name) +{ + if(cardOK){ + sdprinting = false; + file.close(); + + if (file.open(&root, name, O_READ)) { + Serial.print("File opened:"); + Serial.print(name); + Serial.print(" Size:"); + filesize = file.fileSize(); + Serial.println(filesize); + sdpos = 0; + + Serial.println("File selected"); + } + else{ + Serial.println("file.open failed"); + } + } +} + +void CardReader::startFilewrite(char *name) +{ + if(cardOK) + { + + file.close(); + sdprinting = false; + + if (!file.open(&root, name, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + Serial.print("open failed, File: "); + Serial.print(name); + Serial.print("."); + } + else{ + saving = true; + Serial.print("Writing to file: "); + Serial.println(name); + } + } +} + +void CardReader::getStatus() +{ + if(cardOK){ + Serial.print("SD printing byte "); + Serial.print(sdpos); + Serial.print("/"); + Serial.println(filesize); + } + else{ + Serial.println("Not SD printing"); + } +} void CardReader::write_command(char *buf) { char* begin = buf; @@ -80,10 +158,10 @@ void CardReader::checkautostart(bool force) return; } autostart_stilltocheck=false; - if(!sdactive) + if(!cardOK) { initsd(); - if(!sdactive) //fail + if(!cardOK) //fail return; } static int lastnr=0; @@ -122,9 +200,9 @@ void CardReader::checkautostart(bool force) void CardReader::closefile() { - file.sync(); + file.sync(); file.close(); - savetosd = false; + saving = false; } void CardReader::getfilename(const uint8_t nr) diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 121d8ff7fe..77d7151d99 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1124,7 +1124,7 @@ void MainMenu::showSD() if(force_lcd_update) { clear(); - if(card.sdactive) + if(card.cardOK) { nrfiles=card.getnrfilenames(); } @@ -1312,7 +1312,7 @@ void MainMenu::showMainMenu() if(true) #endif { - if(card.sdmode) + if(card.sdprinting) lcd.print(" Stop Print \x7E"); else lcd.print(" Card Menu \x7E"); @@ -1327,7 +1327,7 @@ void MainMenu::showMainMenu() #endif if((activeline==line)&&CLICKED) { - card.sdmode = false; + card.sdprinting = false; BLOCK; status=Main_SD; beepshort(); @@ -1377,7 +1377,7 @@ void MainMenu::update() } else { - card.sdactive=false; + card.release(); lcd_status("Card removed"); } } From 0b43761c3af221bd67bae26ac546846ed15b8ee0 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 23:13:19 +0100 Subject: [PATCH 026/228] preprocessor magic to have a single source principle --- Marlin/Marlin.pde | 101 +++++++++++++--------------------------------- 1 file changed, 27 insertions(+), 74 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 03d3603265..5f138f4bea 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -405,6 +405,29 @@ inline bool code_seen(char code) strchr_pointer = strchr(cmdbuffer[bufindr], code); return (strchr_pointer != NULL); //Return True if a character was found } +#define HOMEAXIS(LETTER) \ + if ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))\ + { \ + current_position[LETTER##_AXIS] = 0; \ + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \ + destination[LETTER##_AXIS] = 1.5 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ + feedrate = homing_feedrate[LETTER##_AXIS]; \ + prepare_move(); \ + \ + current_position[LETTER##_AXIS] = 0;\ + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ + destination[LETTER##_AXIS] = -5 * LETTER##_HOME_DIR;\ + prepare_move(); \ + \ + destination[LETTER##_AXIS] = 10 * LETTER##_HOME_DIR;\ + feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ + prepare_move(); \ + \ + current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? 0 : LETTER##_MAX_LENGTH;\ + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ + destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ + feedrate = 0.0;\ + } inline void process_commands() { @@ -455,85 +478,15 @@ inline void process_commands() if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { - if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ -// st_synchronize(); - current_position[X_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; - feedrate = homing_feedrate[X_AXIS]; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = -5 * X_HOME_DIR; - prepare_move(); - -// st_synchronize(); - destination[X_AXIS] = 10 * X_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]/2 ; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = current_position[X_AXIS]; - feedrate = 0.0; - } + HOMEAXIS(X); } if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { - if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ - 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[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]; - prepare_move(); -// st_synchronize(); - - 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[Y_AXIS] = -5 * Y_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Y_AXIS] = 10 * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = current_position[Y_AXIS]; - feedrate = 0.0; - } + HOMEAXIS(Y); } if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { - if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = -2 * Z_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Z_AXIS] = 3 * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0.0; - } + HOMEAXIS(Z); } feedrate = saved_feedrate; feedmultiply = saved_feedmultiply; @@ -684,7 +637,7 @@ inline void process_commands() Serial.println(); #endif //TEMP_1_PIN #else - Serial.println("echo: No thermistors - no temp"); + SERIAL_ERRORLN("No thermistors - no temp"); #endif return; break; From e3af73ee0c8a8fe46d3206bcf4608be6cfc49f02 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 6 Nov 2011 23:20:01 +0100 Subject: [PATCH 027/228] Thermistor name problem --- Marlin/temperature.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 1121c654ee..d47e07024f 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -200,7 +200,7 @@ int temp2analog(int celsius) { } // Overflow: Set to last value in the table - if (i == NUMTEMPS_0) raw = heater_0_temptable[i-1][0]; + if (i == NUMTEMPS_HEATER_0) raw = heater_0_temptable[i-1][0]; return (1023 * OVERSAMPLENR) - raw; #elif defined HEATER_0_USES_AD595 @@ -544,4 +544,4 @@ ISR(TIMER0_COMPB_vect) #endif } } - + From 907daa49af3a3ca41895007052d8732408e81b95 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 6 Nov 2011 23:21:12 +0100 Subject: [PATCH 028/228] made loop counters uint8_t most were int(16_t) before --- Marlin/Marlin.pde | 24 ++++++++++++------------ Marlin/cardreader.pde | 6 +++--- Marlin/stepper.cpp | 2 +- Marlin/ultralcd.pde | 14 +++++++------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 5f138f4bea..104fc6576e 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -192,14 +192,14 @@ void setup() Serial.begin(BAUDRATE); SERIAL_ECHOLN("Marlin "<= 0 && pin_status <= 255) { int pin_number = code_value(); - for(int i = 0; i < (int)sizeof(sensitive_pins); i++) + for(int8_t i = 0; i < (int8_t)sizeof(sensitive_pins); i++) { if (sensitive_pins[i] == pin_number) { @@ -759,7 +759,7 @@ inline void process_commands() max_inactive_time = code_value() * 1000; break; case 92: // M92 - for(int i=0; i < NUM_AXIS; i++) + for(int8_t i=0; i < NUM_AXIS; i++) { if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); @@ -816,20 +816,20 @@ inline void process_commands() break; //TODO: update for all axis, use for loop case 201: // M201 - for(int i=0; i < NUM_AXIS; i++) + for(int8_t i=0; i < NUM_AXIS; i++) { if(code_seen(axis_codes[i])) 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(int i=0; i < NUM_AXIS; i++) { + 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(int i=0; i < NUM_AXIS; i++) { + for(int8_t i=0; i < NUM_AXIS; i++) { if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; } break; @@ -914,7 +914,7 @@ void ClearToSend() inline void get_coordinates() { - for(int i=0; i < NUM_AXIS; i++) { + 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]; else destination[i] = current_position[i]; //Are these else lines really needed? } @@ -934,7 +934,7 @@ inline void get_arc_coordinates() void prepare_move() { plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); - for(int i=0; i < NUM_AXIS; i++) { + for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } } @@ -948,7 +948,7 @@ void prepare_arc_move(char isclockwise) { // 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(int i=0; i < NUM_AXIS; i++) { + for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } } diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 9f94de0bcd..a49b9999f6 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -167,7 +167,7 @@ void CardReader::checkautostart(bool force) static int lastnr=0; char autoname[30]; sprintf(autoname,"auto%i.g",lastnr); - for(int i=0;i<(int)strlen(autoname);i++) + for(int8_t i=0;i<(int)strlen(autoname);i++) autoname[i]=tolower(autoname[i]); dir_t p; @@ -176,7 +176,7 @@ void CardReader::checkautostart(bool force) bool found=false; while (root.readDir(p) > 0) { - for(int i=0;i<(int)strlen((char*)p.name);i++) + for(int8_t i=0;i<(int)strlen((char*)p.name);i++) p.name[i]=tolower(p.name[i]); //Serial.print((char*)p.name); //Serial.print(" "); @@ -222,7 +222,7 @@ void CardReader::getfilename(const uint8_t nr) if(cnt++!=nr) continue; //Serial.println((char*)p.name); uint8_t writepos=0; - for (uint8_t i = 0; i < 11; i++) + for (int8_t i = 0; i < 11; i++) { if (p.name[i] == ' ') continue; if (i == 8) { diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 924521119e..2607eef60b 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -345,7 +345,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E_DIR_PIN,!INVERT_E_DIR); #endif //!ADVANCE - for(char i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) + for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) counter_x += current_block->steps_x; if (counter_x > 0) { WRITE(X_STEP_PIN, HIGH); diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 77d7151d99..d437cf3a66 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -80,7 +80,7 @@ void beep() //return; #ifdef ULTIPANEL pinMode(BEEPER,OUTPUT); - for(int i=0;i<20;i++){ + for(int8_t i=0;i<20;i++){ WRITE(BEEPER,HIGH); delay(5); WRITE(BEEPER,LOW); @@ -94,7 +94,7 @@ void beepshort() //return; #ifdef ULTIPANEL pinMode(BEEPER,OUTPUT); - for(int i=0;i<10;i++){ + for(int8_t i=0;i<10;i++){ WRITE(BEEPER,HIGH); delay(3); WRITE(BEEPER,LOW); @@ -165,7 +165,7 @@ void buttons_check() WRITE(SHIFT_LD,LOW); WRITE(SHIFT_LD,HIGH); unsigned char tmp_buttons=0; - for(unsigned char i=0;i<8;i++) + for(int8_t i=0;i<8;i++) { newbutton = newbutton>>1; if(READ(SHIFT_OUT)) @@ -375,7 +375,7 @@ void MainMenu::showPrepare() force_lcd_update=true; clear(); } - for(uint8_t i=lineoffset;i Date: Sun, 6 Nov 2011 23:34:40 +0100 Subject: [PATCH 029/228] better visibility of public/private/imported variables --- Marlin/planner.cpp | 15 ++++++++--- Marlin/stepper.cpp | 56 ++++++++++++++++++++++++++++-------------- Marlin/temperature.cpp | 41 +++++++++++++++++++++---------- Marlin/ultralcd.pde | 36 +++++++++++++++++++++------ Marlin/watchdog.pde | 41 ++++++++++++++++++++----------- 5 files changed, 132 insertions(+), 57 deletions(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 888fe45c8f..34e29ff535 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -65,7 +65,10 @@ #include "temperature.h" #include "ultralcd.h" -//public variables +//=========================================================================== +//=============================public variables ============================ +//=========================================================================== + unsigned long minsegmenttime; float max_feedrate[4]; // set the max speeds float axis_steps_per_unit[4]; @@ -77,17 +80,23 @@ float max_xy_jerk; //speed than can be stopped at once, if i understand correctl float max_z_jerk; float mintravelfeedrate; unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + +// The current position of the tool in absolute steps long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode -//private variables +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions static volatile unsigned char block_buffer_head; // Index of the next block to be pushed static volatile unsigned char block_buffer_tail; // Index of the block to process now -// The current position of the tool in absolute steps +//=========================================================================== +//=============================functions ============================ +//=========================================================================== #define ONE_MINUTE_OF_MICROSECONDS 60000000.0 // Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 2607eef60b..7d94d8063d 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -32,6 +32,38 @@ #include "speed_lookuptable.h" + +//=========================================================================== +//=============================public variables ============================ +//=========================================================================== +block_t *current_block; // A pointer to the block currently being traced + + +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== +//static makes it inpossible to be called from outside of this file by extern.! + +// Variables used by The Stepper Driver Interrupt +static unsigned char out_bits; // The next stepping-bits to be output +static long counter_x, // Counter variables for the bresenham line tracer + counter_y, + counter_z, + counter_e; +static unsigned long step_events_completed; // The number of step events executed in the current block +#ifdef ADVANCE + static long advance_rate, advance, final_advance = 0; + static short old_advance = 0; + static short e_steps; +#endif +static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. +static long acceleration_time, deceleration_time; +//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; +static unsigned short acc_step_rate; // needed for deccelaration start point +static char step_loops; + + + // if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. // for debugging purposes only, should be disabled by default #ifdef DEBUG_STEPS @@ -39,6 +71,10 @@ volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; #endif +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + // intRes = intIn1 * intIn2 >> 16 // uses: @@ -115,27 +151,9 @@ asm volatile ( \ #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< 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 static unsigned long previous_millis_lcd=0; static long previous_millis_buttons=0; -inline int intround(const float &x){return int(0.5+x);} -volatile char buttons=0; //the last checked buttons in a bit array. -int encoderpos=0; -short lastenc=0; #ifdef NEWPANEL static long blocking=0; #else static long blocking[8]={0,0,0,0,0,0,0,0}; #endif -MainMenu menu; + +static MainMenu menu; + + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + +inline int intround(const float &x){return int(0.5+x);} void lcd_status(const char* message) { @@ -1106,7 +1127,7 @@ void MainMenu::showControl() } } -#include "SdFat.h" + @@ -1437,8 +1458,7 @@ void MainMenu::update() -//return for string conversion routines -static char conv[8]; + // convert float to string with +123.4 format char *ftostr3(const float &x) diff --git a/Marlin/watchdog.pde b/Marlin/watchdog.pde index 71868cec5b..167bc633d3 100644 --- a/Marlin/watchdog.pde +++ b/Marlin/watchdog.pde @@ -3,10 +3,37 @@ #include #include +//=========================================================================== +//=============================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) { @@ -31,18 +58,4 @@ ISR(WDT_vect) } } -/// intialise watch dog with a 1 sec interrupt time -void wd_init() -{ - WDTCSR = (1< Date: Mon, 7 Nov 2011 22:33:13 +0100 Subject: [PATCH 030/228] made progmem mainly, found one bug in cardreader, added a empty class for cardreader in case no sd support. --- Marlin/EEPROMwrite.h | 79 ++- Marlin/Marlin.h | 6 +- Marlin/Marlin.pde | 147 +++-- Marlin/cardreader.h | 31 +- Marlin/cardreader.pde | 23 +- Marlin/pins.h | 1386 ++++++++++++++++++++--------------------- Marlin/ultralcd.pde | 123 ++-- 7 files changed, 944 insertions(+), 851 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index db9f2fde17..ae31bc9ec4 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -25,6 +25,19 @@ template int EEPROM_readAnything(int &ee, T& value) } //====================================================================================== +#include + +void serialprintPGM(const char *str) +{ + char ch=pgm_read_byte(str); + while(ch) + { + Serial.print(ch); + ch=pgm_read_byte(++str); + } +} +#define SerialprintPGM(x) serialprintPGM(PSTR(x)) + #define EEPROM_OFFSET 100 @@ -62,7 +75,7 @@ void StoreSettings() char ver2[4]=EEPROM_VERSION; i=EEPROM_OFFSET; EEPROM_writeAnything(i,ver2); // validate data - SERIAL_ECHOLN("Settings Stored"); + SerialprintPGM("echo: Settings Stored\n"); } void RetrieveSettings(bool def=false) @@ -91,7 +104,7 @@ void RetrieveSettings(bool def=false) EEPROM_readAnything(i,Ki); EEPROM_readAnything(i,Kd); - SERIAL_ECHOLN("Stored settings retreived:"); + SerialprintPGM("echo: Stored settings retreived:\n"); } else { @@ -111,21 +124,57 @@ void RetrieveSettings(bool def=false) mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; max_xy_jerk=DEFAULT_XYJERK; max_z_jerk=DEFAULT_ZJERK; - SERIAL_ECHOLN("Using Default settings:"); + SerialprintPGM("echo: Using Default settings:\n"); } - SERIAL_ECHOLN("Steps per unit:"); - SERIAL_ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); - SERIAL_ECHOLN("Maximum feedrates (mm/s):"); - SERIAL_ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); - SERIAL_ECHOLN("Maximum Acceleration (mm/s2):"); - SERIAL_ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); - SERIAL_ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); - SERIAL_ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); - SERIAL_ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); - SERIAL_ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); + SerialprintPGM("echo: Steps per unit:\n M92 X"); + Serial.print(axis_steps_per_unit[0]); + SerialprintPGM(" Y"); + Serial.print(axis_steps_per_unit[1]); + SerialprintPGM(" Z"); + Serial.print(axis_steps_per_unit[2]); + SerialprintPGM(" E"); + Serial.print(axis_steps_per_unit[3]); + + SerialprintPGM("\nMaximum feedrates (mm/s):\n M203 X" ); + Serial.print(max_feedrate[0]/60); + SerialprintPGM(" Y" ); + Serial.print(max_feedrate[1]/60 ); + SerialprintPGM(" Z" ); + Serial.print(max_feedrate[2]/60 ); + SerialprintPGM(" E" ); + Serial.print(max_feedrate[3]/60); + SerialprintPGM("\nMaximum Acceleration (mm/s2):\n M201 X" ); + Serial.print(max_acceleration_units_per_sq_second[0] ); + SerialprintPGM(" Y" ); + Serial.print(max_acceleration_units_per_sq_second[1] ); + SerialprintPGM(" Z" ); + Serial.print(max_acceleration_units_per_sq_second[2] ); + SerialprintPGM(" E" ); + Serial.print(max_acceleration_units_per_sq_second[3]); + SerialprintPGM("\necho: Acceleration: S=acceleration, T=retract acceleration\n M204 S" ); + Serial.print(acceleration ); + SerialprintPGM(" T" ); + Serial.print(retract_acceleration); + SerialprintPGM("\necho: Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); + SerialprintPGM(" M205 S" ); + Serial.print(minimumfeedrate/60 ); + SerialprintPGM(" T" ); + Serial.print(mintravelfeedrate/60 ); + SerialprintPGM(" B" ); + Serial.print(minsegmenttime ); + SerialprintPGM(" X" ); + Serial.print(max_xy_jerk/60 ); + SerialprintPGM(" Z" ); + Serial.print(max_z_jerk/60); + SerialprintPGM("\n" ); #ifdef PIDTEMP - SERIAL_ECHOLN("PID settings:"); - SERIAL_ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); + SerialprintPGM("PID settings:"); + SerialprintPGM(" M301 P" ); + Serial.print(Kp ); + SerialprintPGM(" I" ); + Serial.print(Ki ); + SerialprintPGM(" D" ); + Serial.print(Kd); #endif } diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 21eadeeb5e..61b56fb97c 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -9,8 +9,10 @@ #include "streaming.h" #define SERIAL_ECHO(x) Serial << "echo: " << x; #define SERIAL_ECHOLN(x) Serial << "echo: "< -1) || defined (HEATER_USES_AD595) tt = degHotend0(); #endif @@ -620,21 +637,21 @@ inline void process_commands() bt = degBed(); #endif #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - Serial.print("ok T:"); - Serial.print(tt); + SERIAL_PROTOCOL("ok T:"); + SERIAL_PROTOCOL(tt); #if TEMP_1_PIN > -1 #ifdef PIDTEMP - Serial.print(" B:"); + SERIAL_PROTOCOL(" B:"); #if TEMP_1_PIN > -1 - Serial.println(bt); + SERIAL_PROTOCOLLN(bt); #else - Serial.println(HeaterPower); + SERIAL_PROTOCOLLN(HeaterPower); #endif #else //not PIDTEMP - Serial.println(); + SERIAL_PROTOCOLLN(""); #endif //PIDTEMP #else - Serial.println(); + SERIAL_PROTOCOLLN(""); #endif //TEMP_1_PIN #else SERIAL_ERRORLN("No thermistors - no temp"); @@ -664,8 +681,7 @@ inline void process_commands() #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down - Serial.print("T:"); - Serial.println( degHotend0() ); + SERIAL_PROTOCOLLN("T:"<< degHotend0() ); codenum = millis(); } manage_heater(); @@ -694,12 +710,8 @@ inline void process_commands() if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { float tt=degHotend0(); - Serial.print("T:"); - Serial.println( tt ); - Serial.print("ok T:"); - Serial.print( tt ); - Serial.print(" B:"); - Serial.println( degBed() ); + SERIAL_PROTOCOLLN("T:"< -1) - Serial.print("x_min:"); - Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + SERIAL_PROTOCOL("x_min:"); + SERIAL_PROTOCOL(((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (X_MAX_PIN > -1) - Serial.print("x_max:"); - Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + SERIAL_PROTOCOL("x_max:"); + SERIAL_PROTOCOL(((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MIN_PIN > -1) - Serial.print("y_min:"); - Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + SERIAL_PROTOCOL("y_min:"); + SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MAX_PIN > -1) - Serial.print("y_max:"); - Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + SERIAL_PROTOCOL("y_max:"); + SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MIN_PIN > -1) - Serial.print("z_min:"); - Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + SERIAL_PROTOCOL("z_min:"); + SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MAX_PIN > -1) - Serial.print("z_max:"); - Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); + SERIAL_PROTOCOL("z_max:"); + SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif - Serial.println(""); + SERIAL_PROTOCOLLN(""); break; //TODO: update for all axis, use for loop case 201: // M201 @@ -885,9 +897,7 @@ inline void process_commands() } else { - Serial.print("echo: Unknown command:\""); - Serial.print(cmdbuffer[bufindr]); - Serial.println("\""); + SERIAL_ECHOLN("Unknown command:\""<=filesize ;}; - inline char get() { int16_t n = file.read(); return (n!=-1)?(char)n:'\n';}; + inline char get() { int16_t n = file.read(); return (n==-1)?'\n':(char)n;}; inline void setIndex(long index) {sdpos = index;file.seekSet(index);}; public: @@ -52,6 +52,35 @@ private: bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. }; + +#else +class CardReader +{ +public: + inline CardReader(){}; + + inline static void initsd(){}; + inline static void write_command(char *buf){}; + + inline static void checkautostart(bool x) {}; + + inline static void closefile() {}; + inline static void release(){}; + inline static void startFileprint(){}; + inline static void startFilewrite(char *name){}; + inline static void pauseSDPrint(){}; + inline static void getStatus(){}; + + inline static void selectFile(char* name){}; + inline static void getfilename(const uint8_t nr){}; + inline static uint8_t getnrfilenames(){return 0;}; + + + inline static void ls() {}; + inline static bool eof() {return true;}; + inline static char get() {return 0;}; + inline static void setIndex(){}; +}; #endif //SDSUPPORT diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index a49b9999f6..cd4bfeb7ab 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -76,17 +76,14 @@ void CardReader::selectFile(char* name) file.close(); if (file.open(&root, name, O_READ)) { - Serial.print("File opened:"); - Serial.print(name); - Serial.print(" Size:"); filesize = file.fileSize(); - Serial.println(filesize); + SERIAL_PROTOCOLLN("File opened:"< Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 19 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PIN 29 -#define Z_DIR_PIN 30 -#define Z_ENABLE_PIN 31 -#define Z_MIN_PIN 2 -#define Z_MAX_PIN 1 - -#define E_STEP_PIN 12 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN 3 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN 0 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 14 -#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ - - - -#endif - - -/**************************************************************************************** -* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* -* -****************************************************************************************/ -#if MOTHERBOARD == 2 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PINN 27 -#define Z_DIR_PINN 28 -#define Z_ENABLE_PIN 29 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 31 - -#define E_STEP_PIN 17 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 4 -#define LED_PIN 0 - -#define SD_CARD_WRITE 2 -#define SD_CARD_DETECT 3 -#define SD_CARD_SELECT 4 - -//our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 - -//pin for controlling the PSU. -#define PS_ON_PIN 14 - -#define FAN_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN -1 -#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - - - -#endif - -/**************************************************************************************** -* Arduino Mega pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 33 -#define MOTHERBOARD 3 -#define RAMPS_V_1_3 -#endif -#if MOTHERBOARD == 3 -#define KNOWN_BOARD 1 - -//////////////////FIX THIS////////////// -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 -// #define RAMPS_V_1_3 -// #define RAMPS_V_1_0 - -#ifdef RAMPS_V_1_3 - -#define X_STEP_PIN 54 -#define X_DIR_PIN 55 -#define X_ENABLE_PIN 38 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. - -#define Y_STEP_PIN 60 -#define Y_DIR_PIN 61 -#define Y_ENABLE_PIN 56 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 //15 - -#define Z_STEP_PIN 46 -#define Z_DIR_PIN 48 -#define Z_ENABLE_PIN 62 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E_STEP_PIN 26 -#define E_DIR_PIN 28 -#define E_ENABLE_PIN 24 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 9 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#define HEATER_0_PIN 10 -#define HEATER_1_PIN 8 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 14 // ANALOG NUMBERING -#define TEMP_2_PIN -1 // ANALOG NUMBERING - - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default - -#define X_STEP_PIN 26 -#define X_DIR_PIN 28 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 - -#define Y_STEP_PIN 38 -#define Y_DIR_PIN 40 -#define Y_ENABLE_PIN 36 -#define Y_MIN_PIN 16 -#define Y_MAX_PIN -1 //17 - -#define Z_STEP_PIN 44 -#define Z_DIR_PIN 46 -#define Z_ENABLE_PIN 42 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E_STEP_PIN 32 -#define E_DIR_PIN 34 -#define E_ENABLE_PIN 30 - -#define SDPOWER 48 -#define SDSS 53 -#define LED_PIN 13 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - - - -#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 - #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_1_PIN -1 // RAMPS 1.0 - #define FAN_PIN 11 // RAMPS 1.0 - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 - #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_1_PIN 8 // RAMPS 1.1 - #define FAN_PIN 9 // RAMPS 1.1 -#endif -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#endif - -// SPI for Max6675 Thermocouple - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 - #define MISO_PIN 50 - #define MOSI_PIN 51 - #define MAX6675_SS 53 -#else - #define MAX6675_SS 49 -#endif - - -#endif -/**************************************************************************************** -* Duemilanove w/ ATMega328P pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 4 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega328P__ -#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 17 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 13 -#define Z_DIR_PIN 3 -#define Z_ENABLE_PIN 2 -#define Z_MIN_PIN 4 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 11 -#define E_DIR_PIN 12 -#define E_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN 5 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - -#endif - -/**************************************************************************************** -* Gen6 pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 5 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ - #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -//x axis pins - #define X_STEP_PIN 15 - #define X_DIR_PIN 18 - #define X_ENABLE_PIN 19 - #define X_MIN_PIN 20 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 25 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 27 - #define Z_DIR_PIN 28 - #define Z_ENABLE_PIN 29 - #define Z_MIN_PIN 30 - #define Z_MAX_PIN -1 - - //extruder pins - #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 - #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 - #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_2_PIN -1 - - #define SDPOWER -1 - #define SDSS 17 - #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_2_PIN -1 - #define FAN_PIN -1 //changed @ rkoeppl 20110410 - #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 - //our pin for debugging. - - #define DEBUG_PIN 0 - - //our RS485 pins - #define TX_ENABLE_PIN 12 - #define RX_ENABLE_PIN 13 - -#endif - -/**************************************************************************************** -* Sanguinololu pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 62 -#define MOTHERBOARD 6 -#define SANGUINOLOLU_V_1_2 -#endif -#if MOTHERBOARD == 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 21 -#define X_MIN_PIN 18 -#define X_MAX_PIN -2 - -#define Y_STEP_PIN 22 -#define Y_DIR_PIN 23 -#define Y_MIN_PIN 19 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 3 -#define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 1 -#define E_DIR_PIN 0 - -#define LED_PIN -1 - -#define FAN_PIN -1 - -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 // (extruder) - -#ifdef SANGUINOLOLU_V_1_2 - -#define HEATER_1_PIN 12 // (bed) -#define X_ENABLE_PIN 14 -#define Y_ENABLE_PIN 14 -#define Z_ENABLE_PIN 26 -#define E_ENABLE_PIN 14 - -#else - -#define HEATER_1_PIN 14 // (bed) -#define X_ENABLE_PIN -1 -#define Y_ENABLE_PIN -1 -#define Z_ENABLE_PIN -1 -#define E_ENABLE_PIN -1 - -#endif - -#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define TEMP_2_PIN -1 -#define SDPOWER -1 -#define SDSS 31 -#define HEATER_2_PIN -1 - -#endif - - -#if MOTHERBOARD == 7 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 22 -#define X_MAX_PIN 24 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 26 -#define Y_MAX_PIN 28 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 32 -#define Z_ENABLE_PIN 35 - -#define HEATER_1_PIN 4 -#define TEMP_1_PIN 11 - -#define EXTRUDER_0_STEP_PIN 43 -#define EXTRUDER_0_DIR_PIN 45 -#define EXTRUDER_0_ENABLE_PIN 41 -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define EXTRUDER_1_STEP_PIN 49 -#define EXTRUDER_1_DIR_PIN 47 -#define EXTRUDER_1_ENABLE_PIN 51 -#define EXTRUDER_1_HEATER_PIN 3 -#define EXTRUDER_1_TEMPERATURE_PIN 10 -#define HEATER_2_PIN 51 -#define TEMP_2_PIN 3 - - - -#define E_STEP_PIN EXTRUDER_0_STEP_PIN -#define E_DIR_PIN EXTRUDER_0_DIR_PIN -#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 7 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#ifdef ULTRA_LCD - - #ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - #else //old style panel with shift register - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - //buttons are attached to a shift register - #define SHIFT_CLK 38 - #define SHIFT_LD 42 - #define SHIFT_OUT 40 - #define SHIFT_EN 17 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 5 - #define LCD_PINS_D4 6 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 20 - #define LCD_PINS_D7 19 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - - //bits in the shift register that carry the buttons for: - // left up center down right red - #define BL_LE 7 - #define BL_UP 6 - #define BL_MI 5 - #define BL_DW 4 - #define BL_RI 3 - #define BL_ST 2 - - #define BLEN_B 1 - #define BLEN_A 0 - #endif -#endif //ULTRA_LCD - -#endif - -/**************************************************************************************** -* Teensylu 0.7 pin assingments (ATMEGA90USB) -* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! -****************************************************************************************/ -#if MOTHERBOARD == 8 -#define MOTHERBOARD 8 -#define KNOWN_BOARD 1 - - -#define X_STEP_PIN 0 -#define X_DIR_PIN 1 -#define X_ENABLE_PIN 39 -#define X_MIN_PIN 13 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 2 -#define Y_DIR_PIN 3 -#define Y_ENABLE_PIN 38 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 4 -#define Z_DIR_PIN 5 -#define Z_ENABLE_PIN 23 -#define Z_MIN_PIN 15 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 6 -#define E_DIR_PIN 7 -#define E_ENABLE_PIN 19 - - - -#define HEATER_0_PIN 21 // Extruder -#define HEATER_1_PIN 20 // Bed -#define HEATER_2_PIN -1 -#define FAN_PIN 22 // Fan - -#define TEMP_0_PIN 7 // Extruder -#define TEMP_1_PIN 6 // Bed -#define TEMP_2_PIN -1 - -#define SDPOWER -1 -#define SDSS 8 -#define LED_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define ALARM_PIN -1 - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define SCK_PIN 9 - #define MISO_PIN 11 - #define MOSI_PIN 10 -#endif -#endif - -#ifndef KNOWN_BOARD -#error Unknown MOTHERBOARD value in configuration.h -#endif - -//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} - +#ifndef PINS_H +#define PINS_H + +/**************************************************************************************** +* Arduino pin assignment +* +* ATMega168 +* +-\/-+ +* PC6 1| |28 PC5 (AI 5 / D19) +* (D 0) PD0 2| |27 PC4 (AI 4 / D18) +* (D 1) PD1 3| |26 PC3 (AI 3 / D17) +* (D 2) PD2 4| |25 PC2 (AI 2 / D16) +* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) +* (D 4) PD4 6| |23 PC0 (AI 0 / D14) +* VCC 7| |22 GND +* GND 8| |21 AREF +* PB6 9| |20 AVCC +* PB7 10| |19 PB5 (D 13) +* PWM+ (D 5) PD5 11| |18 PB4 (D 12) +* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +* (D 7) PD7 13| |16 PB2 (D 10) PWM +* (D 8) PB0 14| |15 PB1 (D 9) PWM +* +----+ +****************************************************************************************/ +#if MOTHERBOARD == 0 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega168__ +#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. +#endif + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 4 +#define X_MAX_PIN 9 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN 13 + +#define Z_STEP_PIN 19 +#define Z_DIR_PIN 18 +#define Z_ENABLE_PIN 5 +#define Z_MIN_PIN 17 +#define Z_MAX_PIN 16 + +#define E_STEP_PIN 11 +#define E_DIR_PIN 12 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 15 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#endif + + + +/**************************************************************************************** +* Sanguino/RepRap Motherboard with direct-drive extruders +* +* ATMega644P +* +* +---\/---+ +* (D 0) PB0 1| |40 PA0 (AI 0 / D31) +* (D 1) PB1 2| |39 PA1 (AI 1 / D30) +* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +* RST 9| |32 AREF +* VCC 10| |31 GND +* GND 11| |30 AVCC +* XTAL2 12| |29 PC7 (D 23) +* XTAL1 13| |28 PC6 (D 22) +* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +* +--------+ +* +****************************************************************************************/ +#if MOTHERBOARD == 1 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 19 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PIN 29 +#define Z_DIR_PIN 30 +#define Z_ENABLE_PIN 31 +#define Z_MIN_PIN 2 +#define Z_MAX_PIN 1 + +#define E_STEP_PIN 12 +#define E_DIR_PIN 16 +#define E_ENABLE_PIN 3 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN 0 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 14 +#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ + + + +#endif + + +/**************************************************************************************** +* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* +* +****************************************************************************************/ +#if MOTHERBOARD == 2 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PINN 27 +#define Z_DIR_PINN 28 +#define Z_ENABLE_PIN 29 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 31 + +#define E_STEP_PIN 17 +#define E_DIR_PIN 16 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 4 +#define LED_PIN 0 + +#define SD_CARD_WRITE 2 +#define SD_CARD_DETECT 3 +#define SD_CARD_SELECT 4 + +//our RS485 pins +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 + +//pin for controlling the PSU. +#define PS_ON_PIN 14 + +#define FAN_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN -1 +#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + + + +#endif + +/**************************************************************************************** +* Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 33 +#define MOTHERBOARD 3 +#define RAMPS_V_1_3 +#endif +#if MOTHERBOARD == 3 +#define KNOWN_BOARD 1 + +//////////////////FIX THIS////////////// +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 +// #define RAMPS_V_1_3 +// #define RAMPS_V_1_0 + +#ifdef RAMPS_V_1_3 + +#define X_STEP_PIN 54 +#define X_DIR_PIN 55 +#define X_ENABLE_PIN 38 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. + +#define Y_STEP_PIN 60 +#define Y_DIR_PIN 61 +#define Y_ENABLE_PIN 56 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 //15 + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 62 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E_STEP_PIN 26 +#define E_DIR_PIN 28 +#define E_ENABLE_PIN 24 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 9 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#define HEATER_0_PIN 10 +#define HEATER_1_PIN 8 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 13 // ANALOG NUMBERING +#define TEMP_1_PIN 14 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING + + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default + +#define X_STEP_PIN 26 +#define X_DIR_PIN 28 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 + +#define Y_STEP_PIN 38 +#define Y_DIR_PIN 40 +#define Y_ENABLE_PIN 36 +#define Y_MIN_PIN 16 +#define Y_MAX_PIN -1 //17 + +#define Z_STEP_PIN 44 +#define Z_DIR_PIN 46 +#define Z_ENABLE_PIN 42 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E_STEP_PIN 32 +#define E_DIR_PIN 34 +#define E_ENABLE_PIN 30 + +#define SDPOWER 48 +#define SDSS 53 +#define LED_PIN 13 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + + + +#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 + #define HEATER_0_PIN 12 // RAMPS 1.0 + #define HEATER_1_PIN -1 // RAMPS 1.0 + #define FAN_PIN 11 // RAMPS 1.0 + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 + #define HEATER_0_PIN 10 // RAMPS 1.1 + #define HEATER_1_PIN 8 // RAMPS 1.1 + #define FAN_PIN 9 // RAMPS 1.1 +#endif +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#endif + +// SPI for Max6675 Thermocouple + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 + #define MISO_PIN 50 + #define MOSI_PIN 51 + #define MAX6675_SS 53 +#else + #define MAX6675_SS 49 +#endif + + +#endif +/**************************************************************************************** +* Duemilanove w/ ATMega328P pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 4 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega328P__ +#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 17 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 13 +#define Z_DIR_PIN 3 +#define Z_ENABLE_PIN 2 +#define Z_MIN_PIN 4 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 11 +#define E_DIR_PIN 12 +#define E_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN 5 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#endif + +/**************************************************************************************** +* Gen6 pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 5 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ + #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +//x axis pins + #define X_STEP_PIN 15 + #define X_DIR_PIN 18 + #define X_ENABLE_PIN 19 + #define X_MIN_PIN 20 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 25 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 27 + #define Z_DIR_PIN 28 + #define Z_ENABLE_PIN 29 + #define Z_MIN_PIN 30 + #define Z_MAX_PIN -1 + + //extruder pins + #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 + #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 + #define HEATER_2_PIN -1 + + #define SDPOWER -1 + #define SDSS 17 + #define LED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 + #define FAN_PIN -1 //changed @ rkoeppl 20110410 + #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 + //our pin for debugging. + + #define DEBUG_PIN 0 + + //our RS485 pins + #define TX_ENABLE_PIN 12 + #define RX_ENABLE_PIN 13 + +#endif + +/**************************************************************************************** +* Sanguinololu pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 62 +#define MOTHERBOARD 6 +#define SANGUINOLOLU_V_1_2 +#endif +#if MOTHERBOARD == 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -2 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 1 +#define E_DIR_PIN 0 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) + +#ifdef SANGUINOLOLU_V_1_2 + +#define HEATER_1_PIN 12 // (bed) +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E_ENABLE_PIN 14 + +#else + +#define HEATER_1_PIN 14 // (bed) +#define X_ENABLE_PIN -1 +#define Y_ENABLE_PIN -1 +#define Z_ENABLE_PIN -1 +#define E_ENABLE_PIN -1 + +#endif + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 31 +#define HEATER_2_PIN -1 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_1_PIN 4 +#define TEMP_1_PIN 11 + +#define EXTRUDER_0_STEP_PIN 43 +#define EXTRUDER_0_DIR_PIN 45 +#define EXTRUDER_0_ENABLE_PIN 41 +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define EXTRUDER_1_STEP_PIN 49 +#define EXTRUDER_1_DIR_PIN 47 +#define EXTRUDER_1_ENABLE_PIN 51 +#define EXTRUDER_1_HEATER_PIN 3 +#define EXTRUDER_1_TEMPERATURE_PIN 10 +#define HEATER_2_PIN 51 +#define TEMP_2_PIN 3 + + + +#define E_STEP_PIN EXTRUDER_0_STEP_PIN +#define E_DIR_PIN EXTRUDER_0_DIR_PIN +#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + //buttons are attached to a shift register + #define SHIFT_CLK 38 + #define SHIFT_LD 42 + #define SHIFT_OUT 40 + #define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 5 + #define LCD_PINS_D4 6 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 20 + #define LCD_PINS_D7 19 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + +#endif + +/**************************************************************************************** +* Teensylu 0.7 pin assingments (ATMEGA90USB) +* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! +****************************************************************************************/ +#if MOTHERBOARD == 8 +#define MOTHERBOARD 8 +#define KNOWN_BOARD 1 + + +#define X_STEP_PIN 0 +#define X_DIR_PIN 1 +#define X_ENABLE_PIN 39 +#define X_MIN_PIN 13 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 2 +#define Y_DIR_PIN 3 +#define Y_ENABLE_PIN 38 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 4 +#define Z_DIR_PIN 5 +#define Z_ENABLE_PIN 23 +#define Z_MIN_PIN 15 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 6 +#define E_DIR_PIN 7 +#define E_ENABLE_PIN 19 + + + +#define HEATER_0_PIN 21 // Extruder +#define HEATER_1_PIN 20 // Bed +#define HEATER_2_PIN -1 +#define FAN_PIN 22 // Fan + +#define TEMP_0_PIN 7 // Extruder +#define TEMP_1_PIN 6 // Bed +#define TEMP_2_PIN -1 + +#define SDPOWER -1 +#define SDSS 8 +#define LED_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define ALARM_PIN -1 + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define SCK_PIN 9 + #define MISO_PIN 11 + #define MOSI_PIN 10 +#endif +#endif + +#ifndef KNOWN_BOARD +#error Unknown MOTHERBOARD value in configuration.h +#endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} + #endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 981aa81470..91d1a54a80 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -42,6 +42,19 @@ static long previous_millis_buttons=0; static MainMenu menu; +#include + +void lcdProgMemprint(const char *str) +{ + char ch=pgm_read_byte(str); + while(ch) + { + lcd.print(ch); + ch=pgm_read_byte(++str); + } +} +#define lcdprintPGM(x) lcdProgMemprint(PSTR(x)) + //=========================================================================== //=============================functions ============================ @@ -264,9 +277,9 @@ void MainMenu::showStatus() feedmultiplychanged=false; encoderpos=feedmultiply; clear(); - lcd.setCursor(0,0);lcd.print("\002123/567\001 "); + lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 "); #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcd.print("B123/567\001 "); + lcd.setCursor(10,0);lcdprintPGM("B123/567\001 "); #endif } @@ -311,7 +324,7 @@ void MainMenu::showStatus() if(starttime!=oldtime) { - lcd.print(itostr2(time/60));lcd.print("h ");lcd.print(itostr2(time%60));lcd.print("m"); + lcd.print(itostr2(time/60));lcdprintPGM("h ");lcd.print(itostr2(time%60));lcdprintPGM("m"); oldtime=time; } } @@ -320,7 +333,7 @@ void MainMenu::showStatus() if((currentz!=oldzpos)||force_lcd_update) { lcd.setCursor(10,1); - lcd.print("Z:");lcd.print(itostr31(currentz)); + lcdprintPGM("Z:");lcd.print(itostr31(currentz)); oldzpos=currentz; } static int oldfeedmultiply=0; @@ -339,7 +352,7 @@ void MainMenu::showStatus() { oldfeedmultiply=curfeedmultiply; lcd.setCursor(0,2); - lcd.print(itostr3(curfeedmultiply));lcd.print("% "); + lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% "); } if(messagetext[0]!='\0') { @@ -353,9 +366,9 @@ void MainMenu::showStatus() if(force_lcd_update) //initial display of content { encoderpos=feedmultiply; - lcd.setCursor(0,0);lcd.print("\002123/567\001 "); + lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 "); #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcd.print("B123/567\001 "); + lcd.setCursor(10,0);lcdprintPGM("B123/567\001 "); #endif } @@ -405,7 +418,7 @@ void MainMenu::showPrepare() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Prepare"); + lcd.setCursor(0,line);lcdprintPGM(" Prepare"); } if((activeline==line) && CLICKED) { @@ -418,7 +431,7 @@ void MainMenu::showPrepare() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Auto Home"); + lcd.setCursor(0,line);lcdprintPGM(" Auto Home"); } if((activeline==line) && CLICKED) { @@ -431,7 +444,7 @@ void MainMenu::showPrepare() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Set Origin"); + lcd.setCursor(0,line);lcdprintPGM(" Set Origin"); } if((activeline==line) && CLICKED) @@ -445,7 +458,7 @@ void MainMenu::showPrepare() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Preheat"); + lcd.setCursor(0,line);lcdprintPGM(" Preheat"); } if((activeline==line) && CLICKED) { @@ -458,7 +471,7 @@ void MainMenu::showPrepare() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Extrude"); + lcd.setCursor(0,line);lcdprintPGM(" Extrude"); } if((activeline==line) && CLICKED) { @@ -472,7 +485,7 @@ void MainMenu::showPrepare() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Disable Steppers"); + lcd.setCursor(0,line);lcdprintPGM(" Disable Steppers"); } if((activeline==line) && CLICKED) { @@ -541,7 +554,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Control"); + lcd.setCursor(0,line);lcdprintPGM(" Control"); } if((activeline==line) && CLICKED) { @@ -554,7 +567,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" \002Nozzle:"); + lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:"); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degHotend0()))); } @@ -588,7 +601,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Fan speed:"); + lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); } @@ -625,8 +638,8 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Acc:"); - lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcd.print("00"); + lcd.setCursor(0,line);lcdprintPGM(" Acc:"); + lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcdprintPGM("00"); } if((activeline==line) ) @@ -650,7 +663,7 @@ void MainMenu::showControl() { if(encoderpos<5) encoderpos=5; if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); } } }break; @@ -658,7 +671,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Vxy-jerk: "); + lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: "); lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk/60)); } @@ -692,7 +705,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" PID-P: "); + lcd.setCursor(0,line);lcdprintPGM(" PID-P: "); lcd.setCursor(13,line);lcd.print(itostr4(Kp)); } @@ -726,7 +739,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" PID-I: "); + lcd.setCursor(0,line);lcdprintPGM(" PID-I: "); lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); } @@ -760,7 +773,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" PID-D: "); + lcd.setCursor(0,line);lcdprintPGM(" PID-D: "); lcd.setCursor(13,line);lcd.print(itostr4(Kd)); } @@ -797,7 +810,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" PID-C: "); + lcd.setCursor(0,line);lcdprintPGM(" PID-C: "); lcd.setCursor(13,line);lcd.print(itostr3(Kc)); } @@ -834,11 +847,11 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Vmax "); - if(i==ItemC_vmaxx)lcd.print("x:"); - if(i==ItemC_vmaxy)lcd.print("y:"); - if(i==ItemC_vmaxz)lcd.print("z:"); - if(i==ItemC_vmaxe)lcd.print("e:"); + lcd.setCursor(0,line);lcdprintPGM(" Vmax "); + if(i==ItemC_vmaxx)lcdprintPGM("x:"); + if(i==ItemC_vmaxy)lcdprintPGM("y:"); + if(i==ItemC_vmaxz)lcdprintPGM("z:"); + if(i==ItemC_vmaxe)lcdprintPGM("e:"); lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemC_vmaxx]/60)); } @@ -873,7 +886,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Vmin:"); + lcd.setCursor(0,line);lcdprintPGM(" Vmin:"); lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate/60)); } @@ -907,7 +920,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" VTrav min:"); + lcd.setCursor(0,line);lcdprintPGM(" VTrav min:"); lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate/60)); } @@ -945,12 +958,12 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Amax "); - if(i==ItemC_amaxx)lcd.print("x:"); - if(i==ItemC_amaxy)lcd.print("y:"); - if(i==ItemC_amaxz)lcd.print("z:"); - if(i==ItemC_amaxe)lcd.print("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcd.print("00"); + lcd.setCursor(0,line);lcdprintPGM(" Amax "); + if(i==ItemC_amaxx)lcdprintPGM("x:"); + if(i==ItemC_amaxy)lcdprintPGM("y:"); + if(i==ItemC_amaxz)lcdprintPGM("z:"); + if(i==ItemC_amaxe)lcdprintPGM("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcdprintPGM("00"); } if((activeline==line) ) @@ -974,7 +987,7 @@ void MainMenu::showControl() { if(encoderpos<1) encoderpos=1; if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); } } }break; @@ -982,8 +995,8 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" A-retract:"); - lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcd.print("00"); + lcd.setCursor(0,line);lcdprintPGM(" A-retract:"); + lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00"); } if((activeline==line) ) @@ -1008,7 +1021,7 @@ void MainMenu::showControl() { if(encoderpos<10) encoderpos=10; if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); } } }break; @@ -1016,7 +1029,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Esteps/mm:"); + lcd.setCursor(0,line);lcdprintPGM(" Esteps/mm:"); lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); } @@ -1053,7 +1066,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Store EPROM"); + lcd.setCursor(0,line);lcdprintPGM(" Store EPROM"); } if((activeline==line) && CLICKED) { @@ -1067,7 +1080,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Load EPROM"); + lcd.setCursor(0,line);lcdprintPGM(" Load EPROM"); } if((activeline==line) && CLICKED) { @@ -1081,7 +1094,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" Restore Failsafe"); + lcd.setCursor(0,line);lcdprintPGM(" Restore Failsafe"); } if((activeline==line) && CLICKED) { @@ -1165,7 +1178,7 @@ void MainMenu::showSD() { if(force_lcd_update) { - lcd.setCursor(0,line);lcd.print(" File"); + lcd.setCursor(0,line);lcdprintPGM(" File"); } if((activeline==line) && CLICKED) { @@ -1185,11 +1198,11 @@ void MainMenu::showSD() if(true) #endif { - lcd.print(" \004Refresh"); + lcdprintPGM(" \004Refresh"); } else { - lcd.print(" \004Insert Card"); + lcdprintPGM(" \004Insert Card"); } } @@ -1210,7 +1223,7 @@ void MainMenu::showSD() { card.getfilename(i-2); //Serial.print("Filenr:");Serial.println(i-2); - lcd.setCursor(0,line);lcd.print(" ");lcd.print(card.filename); + lcd.setCursor(0,line);lcdprintPGM(" ");lcd.print(card.filename); } if((activeline==line) && CLICKED) { @@ -1292,7 +1305,7 @@ void MainMenu::showMainMenu() { case ItemM_watch: { - if(force_lcd_update) {lcd.setCursor(0,line);lcd.print(" Watch \x7E");} + if(force_lcd_update) {lcd.setCursor(0,line);lcdprintPGM(" Watch \x7E");} if((activeline==line)&&CLICKED) { BLOCK; @@ -1302,7 +1315,7 @@ void MainMenu::showMainMenu() } break; case ItemM_prepare: { - if(force_lcd_update) {lcd.setCursor(0,line);lcd.print(" Prepare \x7E");} + if(force_lcd_update) {lcd.setCursor(0,line);lcdprintPGM(" Prepare \x7E");} if((activeline==line)&&CLICKED) { BLOCK; @@ -1313,7 +1326,7 @@ void MainMenu::showMainMenu() case ItemM_control: { - if(force_lcd_update) {lcd.setCursor(0,line);lcd.print(" Control \x7E");} + if(force_lcd_update) {lcd.setCursor(0,line);lcdprintPGM(" Control \x7E");} if((activeline==line)&&CLICKED) { BLOCK; @@ -1334,13 +1347,13 @@ void MainMenu::showMainMenu() #endif { if(card.sdprinting) - lcd.print(" Stop Print \x7E"); + lcdprintPGM(" Stop Print \x7E"); else - lcd.print(" Card Menu \x7E"); + lcdprintPGM(" Card Menu \x7E"); } else { - lcd.print(" No Card"); + lcdprintPGM(" No Card"); } } #ifdef CARDINSERTED From ab154d55927776add58c878f7de94e82b07bee1c Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Wed, 9 Nov 2011 20:27:15 +0100 Subject: [PATCH 031/228] project progmem finished: total change with ultipanel: 2456 byte free ram initial. now: 4374 ram. --- Marlin/EEPROMwrite.h | 214 ++++++++++++++++++++--------------------- Marlin/Marlin.h | 49 ++++++++-- Marlin/Marlin.pde | 124 +++++++++++++++--------- Marlin/cardreader.h | 4 +- Marlin/cardreader.pde | 38 +++++--- Marlin/stepper.cpp | 4 +- Marlin/temperature.cpp | 23 +++-- Marlin/ultralcd.h | 1 + Marlin/ultralcd.pde | 17 +++- Marlin/watchdog.pde | 7 +- 10 files changed, 294 insertions(+), 187 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index ae31bc9ec4..fcb3d8d391 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -25,18 +25,9 @@ template int EEPROM_readAnything(int &ee, T& value) } //====================================================================================== -#include +#define SERIAL_ECHOPAIR(name,value) {SERIAL_ECHOPGM(name);SERIAL_ECHO(value);} + -void serialprintPGM(const char *str) -{ - char ch=pgm_read_byte(str); - while(ch) - { - Serial.print(ch); - ch=pgm_read_byte(++str); - } -} -#define SerialprintPGM(x) serialprintPGM(PSTR(x)) #define EEPROM_OFFSET 100 @@ -48,8 +39,9 @@ void serialprintPGM(const char *str) // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. #define EEPROM_VERSION "V04" -void StoreSettings() +inline void StoreSettings() { +#ifdef EEPROM_SETTINGS char ver[4]= "000"; int i=EEPROM_OFFSET; EEPROM_writeAnything(i,ver); // invalidate data first @@ -75,107 +67,115 @@ void StoreSettings() char ver2[4]=EEPROM_VERSION; i=EEPROM_OFFSET; EEPROM_writeAnything(i,ver2); // validate data - SerialprintPGM("echo: Settings Stored\n"); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Settings Stored"); +#endif //EEPROM_SETTINGS } -void RetrieveSettings(bool def=false) +inline void RetrieveSettings(bool def=false) { // if def=true, the default values will be used - int i=EEPROM_OFFSET; - char stored_ver[4]; - char ver[4]=EEPROM_VERSION; - EEPROM_readAnything(i,stored_ver); //read stored version - // SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); - if ((!def)&&(strncmp(ver,stored_ver,3)==0)) - { // version number match - EEPROM_readAnything(i,axis_steps_per_unit); - EEPROM_readAnything(i,max_feedrate); - EEPROM_readAnything(i,max_acceleration_units_per_sq_second); - EEPROM_readAnything(i,acceleration); - EEPROM_readAnything(i,retract_acceleration); - EEPROM_readAnything(i,minimumfeedrate); - EEPROM_readAnything(i,mintravelfeedrate); - EEPROM_readAnything(i,minsegmenttime); - EEPROM_readAnything(i,max_xy_jerk); - EEPROM_readAnything(i,max_z_jerk); - #ifndef PIDTEMP - float Kp,Ki,Kd; - #endif - EEPROM_readAnything(i,Kp); - EEPROM_readAnything(i,Ki); - EEPROM_readAnything(i,Kd); + #ifdef EEPROM_SETTINGS + int i=EEPROM_OFFSET; + char stored_ver[4]; + char ver[4]=EEPROM_VERSION; + EEPROM_readAnything(i,stored_ver); //read stored version + // SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); + if ((!def)&&(strncmp(ver,stored_ver,3)==0)) + { // version number match + EEPROM_readAnything(i,axis_steps_per_unit); + EEPROM_readAnything(i,max_feedrate); + EEPROM_readAnything(i,max_acceleration_units_per_sq_second); + EEPROM_readAnything(i,acceleration); + EEPROM_readAnything(i,retract_acceleration); + EEPROM_readAnything(i,minimumfeedrate); + EEPROM_readAnything(i,mintravelfeedrate); + EEPROM_readAnything(i,minsegmenttime); + EEPROM_readAnything(i,max_xy_jerk); + EEPROM_readAnything(i,max_z_jerk); + #ifndef PIDTEMP + float Kp,Ki,Kd; + #endif + EEPROM_readAnything(i,Kp); + EEPROM_readAnything(i,Ki); + EEPROM_readAnything(i,Kd); - SerialprintPGM("echo: Stored settings retreived:\n"); - } - else - { - float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; - float tmp2[]=DEFAULT_MAX_FEEDRATE; - long tmp3[]=DEFAULT_MAX_ACCELERATION; - for (short i=0;i<4;i++) - { - axis_steps_per_unit[i]=tmp1[i]; - max_feedrate[i]=tmp2[i]; - max_acceleration_units_per_sq_second[i]=tmp3[i]; + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Stored settings retreived:"); } - acceleration=DEFAULT_ACCELERATION; - retract_acceleration=DEFAULT_RETRACT_ACCELERATION; - minimumfeedrate=DEFAULT_MINIMUMFEEDRATE; - minsegmenttime=DEFAULT_MINSEGMENTTIME; - mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; - max_xy_jerk=DEFAULT_XYJERK; - max_z_jerk=DEFAULT_ZJERK; - SerialprintPGM("echo: Using Default settings:\n"); - } - SerialprintPGM("echo: Steps per unit:\n M92 X"); - Serial.print(axis_steps_per_unit[0]); - SerialprintPGM(" Y"); - Serial.print(axis_steps_per_unit[1]); - SerialprintPGM(" Z"); - Serial.print(axis_steps_per_unit[2]); - SerialprintPGM(" E"); - Serial.print(axis_steps_per_unit[3]); - - SerialprintPGM("\nMaximum feedrates (mm/s):\n M203 X" ); - Serial.print(max_feedrate[0]/60); - SerialprintPGM(" Y" ); - Serial.print(max_feedrate[1]/60 ); - SerialprintPGM(" Z" ); - Serial.print(max_feedrate[2]/60 ); - SerialprintPGM(" E" ); - Serial.print(max_feedrate[3]/60); - SerialprintPGM("\nMaximum Acceleration (mm/s2):\n M201 X" ); - Serial.print(max_acceleration_units_per_sq_second[0] ); - SerialprintPGM(" Y" ); - Serial.print(max_acceleration_units_per_sq_second[1] ); - SerialprintPGM(" Z" ); - Serial.print(max_acceleration_units_per_sq_second[2] ); - SerialprintPGM(" E" ); - Serial.print(max_acceleration_units_per_sq_second[3]); - SerialprintPGM("\necho: Acceleration: S=acceleration, T=retract acceleration\n M204 S" ); - Serial.print(acceleration ); - SerialprintPGM(" T" ); - Serial.print(retract_acceleration); - SerialprintPGM("\necho: Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); - SerialprintPGM(" M205 S" ); - Serial.print(minimumfeedrate/60 ); - SerialprintPGM(" T" ); - Serial.print(mintravelfeedrate/60 ); - SerialprintPGM(" B" ); - Serial.print(minsegmenttime ); - SerialprintPGM(" X" ); - Serial.print(max_xy_jerk/60 ); - SerialprintPGM(" Z" ); - Serial.print(max_z_jerk/60); - SerialprintPGM("\n" ); - #ifdef PIDTEMP - SerialprintPGM("PID settings:"); - SerialprintPGM(" M301 P" ); - Serial.print(Kp ); - SerialprintPGM(" I" ); - Serial.print(Ki ); - SerialprintPGM(" D" ); - Serial.print(Kd); + else + { + float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; + float tmp2[]=DEFAULT_MAX_FEEDRATE; + long tmp3[]=DEFAULT_MAX_ACCELERATION; + for (short i=0;i<4;i++) + { + axis_steps_per_unit[i]=tmp1[i]; + max_feedrate[i]=tmp2[i]; + max_acceleration_units_per_sq_second[i]=tmp3[i]; + } + acceleration=DEFAULT_ACCELERATION; + retract_acceleration=DEFAULT_RETRACT_ACCELERATION; + minimumfeedrate=DEFAULT_MINIMUMFEEDRATE; + minsegmenttime=DEFAULT_MINSEGMENTTIME; + mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; + max_xy_jerk=DEFAULT_XYJERK; + max_z_jerk=DEFAULT_ZJERK; + SERIAL_ECHO_START; + SERIAL_ECHOLN("Using Default settings:"); + } + #ifdef EEPROM_CHITCHAT + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Steps per unit:"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M92 X",axis_steps_per_unit[0]); + SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[1]); + SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[2]); + SERIAL_ECHOPAIR(" E",axis_steps_per_unit[3]); + SERIAL_ECHOLN(""); + + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Maximum feedrates (mm/s):"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M203 X",max_feedrate[0]/60); + SERIAL_ECHOPAIR(" Y",max_feedrate[1]/60 ); + SERIAL_ECHOPAIR(" Z", max_feedrate[2]/60 ); + SERIAL_ECHOPAIR(" E", max_feedrate[3]/60); + SERIAL_ECHOLN(""); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Maximum Acceleration (mm/s2):"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M201 X" ,max_acceleration_units_per_sq_second[0] ); + SERIAL_ECHOPAIR(" Y" , max_acceleration_units_per_sq_second[1] ); + SERIAL_ECHOPAIR(" Z" ,max_acceleration_units_per_sq_second[2] ); + SERIAL_ECHOPAIR(" E" ,max_acceleration_units_per_sq_second[3]); + SERIAL_ECHOLN(""); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Acceleration: S=acceleration, T=retract acceleration"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M204 S",acceleration ); + SERIAL_ECHOPAIR(" T" ,retract_acceleration); + SERIAL_ECHOLN(""); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M205 S",minimumfeedrate/60 ); + SERIAL_ECHOPAIR(" T" ,mintravelfeedrate/60 ); + SERIAL_ECHOPAIR(" B" ,minsegmenttime ); + SERIAL_ECHOPAIR(" X" ,max_xy_jerk/60 ); + SERIAL_ECHOPAIR(" Z" ,max_z_jerk/60); + SERIAL_ECHOLN(""); + #ifdef PIDTEMP + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("PID settings:"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M301 P",Kp ); + SERIAL_ECHOPAIR(" I" ,Ki ); + SERIAL_ECHOPAIR(" D" ,Kd); + SERIAL_ECHOLN(""); + #endif #endif + + #endif //EEPROM_SETTINGS } #endif diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 61b56fb97c..99cd8021b3 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -5,14 +5,49 @@ // Licence: GPL #include #include "fastio.h" - #include "streaming.h" -#define SERIAL_ECHO(x) Serial << "echo: " << x; -#define SERIAL_ECHOLN(x) Serial << "echo: "< + +//#define SERIAL_ECHO(x) Serial << "echo: " << x; +//#define SERIAL_ECHOLN(x) Serial << "echo: "<= (MAX_CMD_SIZE - 1)) + int16_t n=card.get(); + serial_char = (char)n; + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) { if(card.eof()){ card.sdprinting = false; - SERIAL_PROTOCOL("Done printing file"); + SERIAL_PROTOCOLLNPGM("Done printing file"); stoptime=millis(); char time[30]; unsigned long t=(stoptime-starttime)/1000; @@ -377,6 +391,7 @@ inline void get_command() min=t/60; sec=t%60; sprintf(time,"%i min, %i sec",min,sec); + SERIAL_ECHO_START; SERIAL_ECHOLN(time); LCD_MESSAGE(time); card.checkautostart(true); @@ -398,6 +413,7 @@ inline void get_command() if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; } } + #endif //SDSUPPORT } @@ -473,6 +489,7 @@ inline void process_commands() previous_millis_cmd = millis(); return; case 4: // G4 dwell + LCD_MESSAGEPGM("DWELL..."); codenum = 0; if(code_seen('P')) codenum = code_value(); // milliseconds to wait if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait @@ -533,13 +550,14 @@ inline void process_commands() #ifdef SDSUPPORT case 20: // M20 - list SD card - SERIAL_PROTOCOLLN("Begin file list"); + SERIAL_PROTOCOLLNPGM("Begin file list"); card.ls(); - SERIAL_PROTOCOLLN("End file list"); + SERIAL_PROTOCOLLNPGM("End file list"); break; case 21: // M21 - init SD card card.initsd(); + break; case 22: //M22 - release SD card card.release(); @@ -592,7 +610,8 @@ inline void process_commands() min=t/60; sec=t%60; sprintf(time,"%i min, %i sec",min,sec); - SERIAL_ERRORLN(time); + SERIAL_ECHO_START; + SERIAL_ECHOLN(time); LCD_MESSAGE(time); } break; @@ -637,7 +656,7 @@ inline void process_commands() bt = degBed(); #endif #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - SERIAL_PROTOCOL("ok T:"); + SERIAL_PROTOCOLPGM("ok T:"); SERIAL_PROTOCOL(tt); #if TEMP_1_PIN > -1 #ifdef PIDTEMP @@ -654,13 +673,14 @@ inline void process_commands() SERIAL_PROTOCOLLN(""); #endif //TEMP_1_PIN #else - SERIAL_ERRORLN("No thermistors - no temp"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("No thermistors - no temp"); #endif return; break; case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGE("Heating..."); + LCD_MESSAGEPGM("Heating..."); if (code_seen('S')) setTargetHotend0(code_value()); setWatch(); @@ -681,7 +701,8 @@ inline void process_commands() #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down - SERIAL_PROTOCOLLN("T:"<< degHotend0() ); + SERIAL_PROTOCOLPGM("T:"); + SERIAL_PROTOCOLLN( degHotend0() ); codenum = millis(); } manage_heater(); @@ -697,12 +718,13 @@ inline void process_commands() } #endif //TEMP_RESIDENCY_TIME } - LCD_MESSAGE("Heating done."); + LCD_MESSAGEPGM("Heating done."); starttime=millis(); } break; case 190: // M190 - Wait bed for heater to reach target. #if TEMP_1_PIN > -1 + LCD_MESSAGEPGM("Bed Heating."); if (code_seen('S')) setTargetBed(code_value()); codenum = millis(); while(isHeatingBed()) @@ -710,12 +732,17 @@ inline void process_commands() if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { float tt=degHotend0(); - SERIAL_PROTOCOLLN("T:"< -1) - SERIAL_PROTOCOL("x_min:"); + SERIAL_PROTOCOLPGM("x_min:"); SERIAL_PROTOCOL(((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (X_MAX_PIN > -1) - SERIAL_PROTOCOL("x_max:"); + SERIAL_PROTOCOLPGM("x_max:"); SERIAL_PROTOCOL(((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MIN_PIN > -1) - SERIAL_PROTOCOL("y_min:"); + SERIAL_PROTOCOLPGM("y_min:"); SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MAX_PIN > -1) - SERIAL_PROTOCOL("y_max:"); + SERIAL_PROTOCOLPGM("y_max:"); SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MIN_PIN > -1) - SERIAL_PROTOCOL("z_min:"); + SERIAL_PROTOCOLPGM("z_min:"); SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MAX_PIN > -1) - SERIAL_PROTOCOL("z_max:"); + SERIAL_PROTOCOLPGM("z_max:"); SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); #endif SERIAL_PROTOCOLLN(""); @@ -897,7 +925,10 @@ inline void process_commands() } else { - SERIAL_ECHOLN("Unknown command:\""< -1) pinMode(PS_ON_PIN,INPUT); - SERIAL_ERRORLN("Printer halted. kill() called !!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Printer halted. kill() called !!"); + LCD_MESSAGEPGM("KILLED. "); while(1); // Wait for reset } diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 03696fa616..b3f514f61f 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -30,8 +30,8 @@ public: inline void ls() {root.ls();}; - inline bool eof() { sdpos = file.curPosition();return sdpos>=filesize ;}; - inline char get() { int16_t n = file.read(); return (n==-1)?'\n':(char)n;}; + inline bool eof() { return sdpos>=filesize ;}; + inline int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; inline void setIndex(long index) {sdpos = index;file.seekSet(index);}; public: diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index cd4bfeb7ab..605af11bf5 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -29,20 +29,24 @@ void CardReader::initsd() if (!card.init(SPI_FULL_SPEED,SDSS)) { //if (!card.init(SPI_HALF_SPEED,SDSS)) - SERIAL_ECHOLN("SD init fail"); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("SD init fail"); } else if (!volume.init(&card)) { - SERIAL_ERRORLN("volume.init failed"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("volume.init failed"); } else if (!root.openRoot(&volume)) { - SERIAL_ERRORLN("openRoot failed"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("openRoot failed"); } else { cardOK = true; - SERIAL_ECHOLN("SD card ok"); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("SD card ok"); } #endif //SDSS } @@ -77,13 +81,16 @@ void CardReader::selectFile(char* name) if (file.open(&root, name, O_READ)) { filesize = file.fileSize(); - SERIAL_PROTOCOLLN("File opened:"<= maxttemp_0) { target_raw[TEMPSENSOR_HOTEND_0] = 0; analogWrite(HEATER_0_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 0 switched off. MAXTEMP triggered !!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MAXTEMP triggered !!"); kill(); } #endif @@ -507,7 +509,8 @@ ISR(TIMER0_COMPB_vect) target_raw[TEMPSENSOR_HOTEND_1] = 0; if(current_raw[2] >= maxttemp_1) { analogWrite(HEATER_2_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 1 switched off. MAXTEMP triggered !!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MAXTEMP triggered !!"); kill() } #endif @@ -518,7 +521,8 @@ ISR(TIMER0_COMPB_vect) if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { target_raw[TEMPSENSOR_HOTEND_0] = 0; analogWrite(HEATER_0_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 0 switched off. MINTEMP triggered !!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MINTEMP triggered !!"); kill(); } #endif @@ -529,7 +533,8 @@ ISR(TIMER0_COMPB_vect) if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { target_raw[TEMPSENSOR_HOTEND_1] = 0; analogWrite(HEATER_2_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 1 switched off. MINTEMP triggered !!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MINTEMP triggered !!"); kill(); } #endif @@ -540,7 +545,8 @@ ISR(TIMER0_COMPB_vect) if(current_raw[1] <= bed_minttemp) { target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); - SERIAL_ERRORLN("Temperatur heated bed switched off. MINTEMP triggered !!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperatur heated bed switched off. MINTEMP triggered !!"); kill(); } #endif @@ -551,7 +557,8 @@ ISR(TIMER0_COMPB_vect) if(current_raw[1] >= bed_maxttemp) { target_raw[1] = 0; WRITE(HEATER_1_PIN, 0); - SERIAL_ERRORLN("Temperature heated bed switched off. MAXTEMP triggered !!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); kill(); } #endif diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 0822e502b0..4c725329df 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -83,6 +83,7 @@ #define LCD_MESSAGE(x) lcd_status(x); + #define LCD_MESSAGEPGM(x) lcd_statuspgm(PSTR(x)); #define LCD_STATUS lcd_status() #else //no lcd #define LCD_STATUS diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 91d1a54a80..59edb34702 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -67,6 +67,18 @@ void lcd_status(const char* message) strncpy(messagetext,message,LCD_WIDTH); } +void lcd_statuspgm(const char* message) +{ + char ch=pgm_read_byte(message); + char *target=messagetext; + while(ch) + { + *target=ch; + target++; + ch=pgm_read_byte(++message); + } +} + inline void clear() { lcd.clear(); @@ -105,7 +117,7 @@ void lcd_init() lcd.createChar(2,Thermometer); lcd.createChar(3,uplevel); lcd.createChar(4,refresh); - LCD_MESSAGE(fillto(LCD_WIDTH,"UltiMarlin ready.")); + LCD_MESSAGEPGM("UltiMarlin ready."); } @@ -1369,7 +1381,8 @@ void MainMenu::showMainMenu() }break; #endif default: - SERIAL_ERRORLN("Something is wrong in the MenuStructure."); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Something is wrong in the MenuStructure."); break; } } diff --git a/Marlin/watchdog.pde b/Marlin/watchdog.pde index 167bc633d3..9cf710a0c7 100644 --- a/Marlin/watchdog.pde +++ b/Marlin/watchdog.pde @@ -41,10 +41,11 @@ ISR(WDT_vect) { #ifdef RESET_MANUAL - LCD_MESSAGE("Please Reset!"); - SERIAL_ERRORLN("Something is wrong, please turn off the printer."); + LCD_MESSAGEPGM("Please Reset!"); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Something is wrong, please turn off the printer."); #else - LCD_MESSAGE("Timeout, resetting!"); + LCD_MESSAGEPGM("Timeout, resetting!"); #endif //disable watchdog, it will survife reboot. WDTCSR |= (1< Date: Wed, 9 Nov 2011 20:28:40 +0100 Subject: [PATCH 032/228] beautified the config. ordered it into thematic sections. --- Marlin/Configuration.h | 276 ++++++++++++++++++++++++----------------- 1 file changed, 160 insertions(+), 116 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index a0d46bfed7..f44c858b9a 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,10 +1,13 @@ #ifndef __CONFIGURATION_H #define __CONFIGURATION_H -//#define DEBUG_STEPS -#define MM_PER_ARC_SEGMENT 1 -#define N_ARC_CORRECTION 25 + +// This determines the communication speed of the printer +//#define BAUDRATE 250000 +#define BAUDRATE 115200 +//#define BAUDRATE 230400 + // BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration @@ -17,7 +20,9 @@ // Teensylu = 8 #define MOTHERBOARD 7 - +//=========================================================================== +//=============================Thermal Settings ============================ +//=========================================================================== //// Thermistor settings: // 1 is 100k thermistor @@ -40,49 +45,103 @@ //#define BED_USES_THERMISTOR //#define BED_USES_AD595 -#define HEATER_CHECK_INTERVAL 50 -#define BED_CHECK_INTERVAL 5000 +#define HEATER_CHECK_INTERVAL 50 //ms +#define BED_CHECK_INTERVAL 5000 //ms + +//// Experimental watchdog and minimal temp +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 +/// CURRENTLY NOT IMPLEMENTED AND UNUSEABLE +//#define WATCHPERIOD 5000 //5 seconds + +// Actual temperature must be close to target for this long before M109 returns success +//#define TEMP_RESIDENCY_TIME 20 // (seconds) +//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one + +//// The minimal temperature defines the temperature below which the heater will not be enabled +#define HEATER_0_MINTEMP 5 +//#define HEATER_1_MINTEMP 5 +//#define BED_MINTEMP 5 -//// Endstop Settings +// When temperature exceeds max temp, your heater will be switched off. +// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! +// You should use MINTEMP for thermistor short/failure protection. +#define HEATER_0_MAXTEMP 275 +//#define_HEATER_1_MAXTEMP 275 +//#define BED_MAXTEMP 150 + + + +// PID settings: +// Uncomment the following line to enable PID support. + +#define PIDTEMP +#ifdef PIDTEMP + //#define PID_DEBUG // Sends debug data to the serial port. + //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % + + #define PID_MAX 255 // limits current to nozzle; 255=full current + #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term + #define K1 0.95 //smoothing factor withing the PID + #define PID_dT 0.1 //sampling period of the PID + + //To develop some PID settings for your machine, you can initiall follow + // the Ziegler-Nichols method. + // set Ki and Kd to zero. + // heat with a defined Kp and see if the temperature stabilizes + // ideally you do this graphically with repg. + // the PID_CRITIAL_GAIN should be the Kp at which temperature oscillatins are not dampned out/decreas in amplitutde + // PID_SWING_AT_CRITIAL is the time for a full period of the oscillations at the critical Gain + // usually further manual tunine is necessary. + + #define PID_CRITIAL_GAIN 3000 + #define PID_SWING_AT_CRITIAL 45 //seconds + + #define PID_PI //no differentail term + //#define PID_PID //normal PID + + #ifdef PID_PID + //PID according to Ziegler-Nichols method + #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) + #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) + #endif + + #ifdef PID_PI + //PI according to Ziegler-Nichols method + #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) + #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (0) + #endif + + // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. + // if Kc is choosen well, the additional required power due to increased melting should be compensated. + #define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) + #endif +#endif // PIDTEMP + + + + + + + + + +//=========================================================================== +//=============================Mechanical Settings=========================== +//=========================================================================== + + +// Endstop Settings #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false -// This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 -//#define BAUDRATE 230400 - -// Comment out (using // at the start of the line) to disable SD support: - -// #define ULTRA_LCD //any lcd - -#define ULTIPANEL -#ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 - #define LCD_HEIGHT 4 -#else //no panel but just lcd - #ifdef ULTRA_LCD - #define LCD_WIDTH 16 - #define LCD_HEIGHT 2 - #endif -#endif - - -//#define SDSUPPORT // Enable SD Card Support in Hardware Console - - - -const int dropsegments=5; //everything with this number of steps will be ignored as move - -//// ADVANCED SETTINGS - to tweak parameters - -#include "thermistortables.h" // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 @@ -141,88 +200,33 @@ const int dropsegments=5; //everything with this number of steps will be ignore #define DEFAULT_ZJERK 10.0*60 + + +//=========================================================================== +//=============================Additional Features=========================== +//=========================================================================== + +// EEPROM +// the microcontroller can store settings in the EEPROM, e.g. max velocity... +// 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. +//define this to enable eeprom support +#define EEPROM_SETTINGS +//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: +// please keep turned on if you can. +#define EEPROM_CHITCHAT + + // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -//this enables the watchdog interrupt. +// this enables the watchdog interrupt. #define 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: +// you cannot reboot on a mega2560 due to a bug in he bootloader. Hence, you have to reset manually, and this is done hereby: #define RESET_MANUAL - -#define WATCHDOG_TIMEOUT 4 +#define WATCHDOG_TIMEOUT 4 //seconds -//// Experimental watchdog and minimal temp -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 -/// CURRENTLY NOT IMPLEMENTED AND UNUSEABLE -//#define WATCHPERIOD 5000 //5 seconds - -// Actual temperature must be close to target for this long before M109 returns success -//#define TEMP_RESIDENCY_TIME 20 // (seconds) -//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one - -//// The minimal temperature defines the temperature below which the heater will not be enabled -#define HEATER_0_MINTEMP 5 -//#define HEATER_1_MINTEMP 5 -//#define BED_MINTEMP 5 - - -// When temperature exceeds max temp, your heater will be switched off. -// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! -// You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 275 -//#define_HEATER_1_MAXTEMP 275 -//#define BED_MAXTEMP 150 - -/// PID settings: -// Uncomment the following line to enable PID support. - -#define PIDTEMP -#ifdef PIDTEMP - //#define PID_DEBUG // Sends debug data to the serial port. - //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - - #define PID_MAX 255 // limits current to nozzle; 255=full current - #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term - #define K1 0.95 //smoothing factor withing the PID - #define PID_dT 0.1 //sampling period of the PID - - //To develop some PID settings for your machine, you can initiall follow - // the Ziegler-Nichols method. - // set Ki and Kd to zero. - // heat with a defined Kp and see if the temperature stabilizes - // ideally you do this graphically with repg. - // the PID_CRITIAL_GAIN should be the Kp at which temperature oscillatins are not dampned out/decreas in amplitutde - // PID_SWING_AT_CRITIAL is the time for a full period of the oscillations at the critical Gain - // usually further manual tunine is necessary. - - #define PID_CRITIAL_GAIN 3000 - #define PID_SWING_AT_CRITIAL 45 //seconds - - #define PID_PI //no differentail term - //#define PID_PID //normal PID - - #ifdef PID_PID - //PID according to Ziegler-Nichols method - #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) - #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) - #endif - - #ifdef PID_PI - //PI according to Ziegler-Nichols method - #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) - #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (0) - #endif - - // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. - // if Kc is choosen well, the additional required power due to increased melting should be compensated. - #define PID_ADD_EXTRUSION_RATE - #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) - #endif -#endif // PIDTEMP // extruder advance constant (s2/mm3) // @@ -243,6 +247,42 @@ const int dropsegments=5; //everything with this number of steps will be ignore #endif // ADVANCE + +//LCD and SD support +//#define ULTRA_LCD //general lcd support, also 16x2 +//#define SDSUPPORT // Enable SD Card Support in Hardware Console + +#define ULTIPANEL +#ifdef ULTIPANEL + #define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 + #define LCD_HEIGHT 4 +#else //no panel but just lcd + #ifdef ULTRA_LCD + #define LCD_WIDTH 16 + #define LCD_HEIGHT 2 + #endif +#endif + +// A debugging feature to compare calculated vs performed steps, to see if steps are lost by the software. +//#define DEBUG_STEPS + + +// Arc interpretation settings: +#define MM_PER_ARC_SEGMENT 1 +#define N_ARC_CORRECTION 25 + + +const int dropsegments=0; //everything with less than this number of steps will be ignored as move and joined with the next movement + +//=========================================================================== +//=============================Buffers ============================ +//=========================================================================== + + + // The number of linear motions that can be in the plan at any give time. // THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ringbuffering. #if defined SDSUPPORT @@ -251,8 +291,12 @@ const int dropsegments=5; //everything with this number of steps will be ignore #define BLOCK_BUFFER_SIZE 16 // maximize block buffer #endif + //The ASCII buffer for recieving from the serial: #define MAX_CMD_SIZE 96 #define BUFSIZE 4 + +#include "thermistortables.h" + #endif //__CONFIGURATION_H From ba8a53a40fa0adaa947b536639bab998cc872feb Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Wed, 9 Nov 2011 20:30:41 +0100 Subject: [PATCH 033/228] Streaming.h is gone. It conflicted with PROGMEM. And saving memory is more important than nicer code, imho --- Marlin/Marlin.h | 1 - Marlin/Marlin.pde | 1 - Marlin/streaming.h | 84 ------------------------------------------ Marlin/temperature.cpp | 1 - 4 files changed, 87 deletions(-) delete mode 100644 Marlin/streaming.h diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 99cd8021b3..1e36b61e88 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -5,7 +5,6 @@ // Licence: GPL #include #include "fastio.h" -#include "streaming.h" #include //#define SERIAL_ECHO(x) Serial << "echo: " << x; diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 7b67cfcf5b..dee095d84f 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -32,7 +32,6 @@ #include "pins.h" #include "Marlin.h" #include "ultralcd.h" -#include "streaming.h" #include "planner.h" #include "stepper.h" #include "temperature.h" diff --git a/Marlin/streaming.h b/Marlin/streaming.h deleted file mode 100644 index 1a6afe73d9..0000000000 --- a/Marlin/streaming.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -Streaming.h - Arduino library for supporting the << streaming operator -Copyright (c) 2010 Mikal Hart. All rights reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef ARDUINO_STREAMING -#define ARDUINO_STREAMING - -//#include - -#define STREAMING_LIBRARY_VERSION 4 - -// Generic template -template -inline Print &operator <<(Print &stream, T arg) -{ stream.print(arg); return stream; } - -struct _BASED -{ - long val; - int base; - _BASED(long v, int b): val(v), base(b) - {} -}; - -#define _HEX(a) _BASED(a, HEX) -#define _DEC(a) _BASED(a, DEC) -#define _OCT(a) _BASED(a, OCT) -#define _BIN(a) _BASED(a, BIN) -#define _BYTE(a) _BASED(a, BYTE) - -// Specialization for class _BASED -// Thanks to Arduino forum user Ben Combee who suggested this -// clever technique to allow for expressions like -// Serial << _HEX(a); - -inline Print &operator <<(Print &obj, const _BASED &arg) -{ obj.print(arg.val, arg.base); return obj; } - -#if ARDUINO >= 18 -// Specialization for class _FLOAT -// Thanks to Michael Margolis for suggesting a way -// to accommodate Arduino 0018's floating point precision -// feature like this: -// Serial << _FLOAT(gps_latitude, 6); // 6 digits of precision - -struct _FLOAT -{ - float val; - int digits; - _FLOAT(double v, int d): val(v), digits(d) - {} -}; - -inline Print &operator <<(Print &obj, const _FLOAT &arg) -{ obj.print(arg.val, arg.digits); return obj; } -#endif - -// Specialization for enum _EndLineCode -// Thanks to Arduino forum user Paul V. who suggested this -// clever technique to allow for expressions like -// Serial << "Hello!" << endl; - -enum _EndLineCode { endl }; - -inline Print &operator <<(Print &obj, _EndLineCode arg) -{ obj.println(); return obj; } - -#endif - diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 87d9ee5434..83c173b28c 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -34,7 +34,6 @@ #include "pins.h" #include "Marlin.h" #include "ultralcd.h" -#include "streaming.h" #include "temperature.h" #include "watchdog.h" From 36958ee30576dd282a373c8b1da6ad8d9d22eb7b Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Wed, 9 Nov 2011 22:09:16 +0100 Subject: [PATCH 034/228] minor changes and first not-well working version of autotemp --- Marlin/Configuration.h | 12 +++++++++++- Marlin/EEPROMwrite.h | 1 - Marlin/Marlin.h | 3 +++ Marlin/Marlin.pde | 3 +-- Marlin/planner.cpp | 35 +++++++++++++++++++++++++++++++++++ Marlin/planner.h | 4 +++- Marlin/ultralcd.pde | 4 +++- 7 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f44c858b9a..8661ae438e 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -119,7 +119,7 @@ // if Kc is choosen well, the additional required power due to increased melting should be compensated. #define PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) + #define DEFAULT_Kc (3) //heatingpower=Kc*(e_speed) #endif #endif // PIDTEMP @@ -275,6 +275,16 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define N_ARC_CORRECTION 25 +//automatic temperature: just for testing, this is very dangerous, keep disabled! +// not working yet. +//Erik: the settings currently depend dramatically on skeinforge39 or 41. +//#define AUTOTEMP +#define AUTOTEMP_MIN 190 +#define AUTOTEMP_MAX 260 +#define AUTOTEMP_FACTOR 1000. //current target temperature= min+largest buffered espeeds)*FACTOR + + + const int dropsegments=0; //everything with less than this number of steps will be ignored as move and joined with the next movement //=========================================================================== diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index fcb3d8d391..3d8a0b2b9e 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -25,7 +25,6 @@ template int EEPROM_readAnything(int &ee, T& value) } //====================================================================================== -#define SERIAL_ECHOPAIR(name,value) {SERIAL_ECHOPGM(name);SERIAL_ECHO(value);} diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 1e36b61e88..e14471264f 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -35,6 +35,9 @@ const char echomagic[] PROGMEM ="echo:"; #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x) #define SERIAL_ECHOLNPGM(x) SERIAL_PROTOCOLLNPGM(x) +#define SERIAL_ECHOPAIR(name,value) {SERIAL_ECHOPGM(name);SERIAL_ECHO(value);} + + //things to write to serial from Programmemory. saves 400 to 2k of RAM. #define SerialprintPGM(x) serialprintPGM(PSTR(x)) inline void serialprintPGM(const char *str) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index dee095d84f..672591a72d 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -211,7 +211,6 @@ void setup() { Serial.begin(BAUDRATE); SERIAL_ECHO_START; - SERIAL_ECHOPGM("Marlin "); SERIAL_ECHOLN(version_string); SERIAL_PROTOCOLLNPGM("start"); SERIAL_ECHO_START; @@ -785,8 +784,8 @@ inline void process_commands() } else { - LCD_MESSAGEPGM("Free move."); st_synchronize(); + LCD_MESSAGEPGM("Free move."); disable_x(); disable_y(); disable_z(); diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 34e29ff535..863b116a5b 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -84,6 +84,10 @@ unsigned long axis_steps_per_sqr_second[NUM_AXIS]; // The current position of the tool in absolute steps long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode +#ifdef AUTOTEMP +float high_e_speed=0; +#endif + //=========================================================================== //=============================private variables ============================ @@ -363,6 +367,34 @@ block_t *plan_get_current_block() { return(block); } +#ifdef AUTOTEMP +void getHighESpeed() +{ + if(degTargetHotend0()+2high) + { + high=se; + } + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + high_e_speed=high*axis_steps_per_unit[E_AXIS]/(1000000.0); //so it is independent of the esteps/mm. before + + float g=AUTOTEMP_MIN+high_e_speed*AUTOTEMP_FACTOR; + float t=constrain(AUTOTEMP_MIN,g,AUTOTEMP_MAX); + setTargetHotend0(t); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR("highe",high_e_speed); + SERIAL_ECHOPAIR(" t",t); + SERIAL_ECHOLN(""); +} +#endif + void check_axes_activity() { unsigned char x_active = 0; unsigned char y_active = 0; @@ -581,6 +613,9 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa memcpy(position, target, sizeof(target)); // position[] = target[] planner_recalculate(); + #ifdef AUTOTEMP + getHighESpeed(); + #endif st_wake_up(); } diff --git a/Marlin/planner.h b/Marlin/planner.h index 79f54d879f..c5bc5b8aaf 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -89,5 +89,7 @@ extern float max_xy_jerk; //speed than can be stopped at once, if i understand c extern float max_z_jerk; extern float mintravelfeedrate; extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - +#ifdef AUTOTEMP +extern float high_e_speed; +#endif #endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 59edb34702..d95167166d 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -71,10 +71,12 @@ void lcd_statuspgm(const char* message) { char ch=pgm_read_byte(message); char *target=messagetext; - while(ch) + uint8_t cnt=0; + while(ch &&cnt Date: Sat, 12 Nov 2011 20:37:28 +0100 Subject: [PATCH 035/228] re-enabled heaterpower as storage for the current storage of the heater PWM duty cycle. the M301 now returns the current PID settings of the machine. M105 returns heating pwm duty cylce as "@:" --- Marlin/Marlin.pde | 52 +++++++++++++++++++++++------------------- Marlin/temperature.cpp | 1 + 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 672591a72d..4c1ece07e3 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -647,33 +647,24 @@ inline void process_commands() break; case 105: // M105 //SERIAL_ECHOLN(freeMemory()); - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = degHotend0(); - #endif - #if TEMP_1_PIN > -1 - bt = degBed(); - #endif + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL(tt); + SERIAL_PROTOCOL( degHotend0()); #if TEMP_1_PIN > -1 - #ifdef PIDTEMP - SERIAL_PROTOCOL(" B:"); - #if TEMP_1_PIN > -1 - SERIAL_PROTOCOLLN(bt); - #else - SERIAL_PROTOCOLLN(HeaterPower); - #endif - #else //not PIDTEMP - SERIAL_PROTOCOLLN(""); - #endif //PIDTEMP - #else - SERIAL_PROTOCOLLN(""); - #endif //TEMP_1_PIN - #else - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("No thermistors - no temp"); + SERIAL_PROTOCOLPGM(" B:"); + SERIAL_PROTOCOL(degBed()); + #endif //TEMP_1_PIN + #else + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("No thermistors - no temp"); #endif + #ifdef PIDTEMP + SERIAL_PROTOCOLPGM(" @:"); + SERIAL_PROTOCOL( HeaterPower); + + #endif + SERIAL_PROTOCOLLN(""); return; break; case 109: @@ -901,6 +892,21 @@ inline void process_commands() 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 + SERIAL_PROTOCOL("ok 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 case 500: // Store settings in EEPROM diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 83c173b28c..0772cb324f 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -156,6 +156,7 @@ void manage_heater() pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high #endif pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); + HeaterPower=pid_output; } #endif //PID_OPENLOOP #ifdef PID_DEBUG From ff592b056ad492632a810e6c77a7d063b6ce05e3 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 13 Nov 2011 00:48:55 +0100 Subject: [PATCH 036/228] heater power repair. --- Marlin/temperature.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 0772cb324f..8ea8ee008f 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -156,12 +156,13 @@ void manage_heater() pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high #endif pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); - HeaterPower=pid_output; + } #endif //PID_OPENLOOP #ifdef PID_DEBUG //SERIAL_ECHOLN(" PIDDEBUG Input "< Date: Sun, 13 Nov 2011 19:58:09 +0100 Subject: [PATCH 037/228] added a m400, that finished all moves, and the mechanism so that if an endstop is hit it the ISR, the steps_to_be_taken are stored, and some current_block data that will be deleted in the next move If the normal loop() then finds such an event, the position is calculated (floats would have taken too long in the ISR) A serial message is generated. --- Marlin/Marlin.h | 2 ++ Marlin/Marlin.pde | 20 +++++++++++++++--- Marlin/stepper.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++- Marlin/stepper.h | 7 +++++++ 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index e14471264f..440a44a579 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -6,6 +6,7 @@ #include #include "fastio.h" #include +#include "Configuration.h" //#define SERIAL_ECHO(x) Serial << "echo: " << x; //#define SERIAL_ECHOLN(x) Serial << "echo: "<1 200->2 int saved_feedmultiply; volatile bool feedmultiplychanged=false; +float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; + //=========================================================================== //=============================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 current_position[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; @@ -211,7 +213,7 @@ void setup() { Serial.begin(BAUDRATE); SERIAL_ECHO_START; - SERIAL_ECHOLN(version_string); + SERIAL_ECHOLNPGM(VERSION_STRING); SERIAL_PROTOCOLLNPGM("start"); SERIAL_ECHO_START; SERIAL_ECHOPGM("Free Memory:"); @@ -269,6 +271,7 @@ void loop() //check heater every n milliseconds manage_heater(); manage_inactivity(1); + checkHitEndstops(); LCD_STATUS; } @@ -443,20 +446,25 @@ inline bool code_seen(char code) destination[LETTER##_AXIS] = 1.5 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ feedrate = homing_feedrate[LETTER##_AXIS]; \ prepare_move(); \ + st_synchronize();\ \ current_position[LETTER##_AXIS] = 0;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ destination[LETTER##_AXIS] = -5 * LETTER##_HOME_DIR;\ prepare_move(); \ + st_synchronize();\ \ destination[LETTER##_AXIS] = 10 * LETTER##_HOME_DIR;\ feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ prepare_move(); \ + st_synchronize();\ \ current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? 0 : LETTER##_MAX_LENGTH;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ feedrate = 0.0;\ + st_synchronize();\ + endstops_hit_on_purpose();\ } inline void process_commands() @@ -522,6 +530,7 @@ inline void process_commands() feedrate = saved_feedrate; feedmultiply = saved_feedmultiply; previous_millis_cmd = millis(); + endstops_hit_on_purpose(); break; case 90: // G90 relative_mode = false; @@ -909,6 +918,11 @@ inline void process_commands() break; #endif //PIDTEMP + case 400: // finish all moves + { + st_synchronize(); + } + break; case 500: // Store settings in EEPROM { StoreSettings(); diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index d5d41b1736..23066ef320 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -33,12 +33,14 @@ #include "speed_lookuptable.h" + //=========================================================================== //=============================public variables ============================ //=========================================================================== block_t *current_block; // A pointer to the block currently being traced + //=========================================================================== //=============================private variables ============================ //=========================================================================== @@ -62,7 +64,9 @@ static long acceleration_time, deceleration_time; static unsigned short acc_step_rate; // needed for deccelaration start point static char step_loops; - +volatile long endstops_trigsteps[3]={0,0,0}; +volatile long endstops_stepsTotal,endstops_stepsDone; +static volatile bool endstops_hit=false; // if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. // for debugging purposes only, should be disabled by default @@ -152,9 +156,49 @@ asm volatile ( \ #define DISABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 &= ~(1<step_event_count; + endstops_stepsDone=stepstaken; + endstops_trigsteps[0]=current_block->steps_x; + endstops_trigsteps[1]=current_block->steps_y; + endstops_trigsteps[2]=current_block->steps_z; + endstops_hit=true; +} +void checkHitEndstops() +{ + if( !endstops_hit) + return; + float endstops_triggerpos[3]={0,0,0}; + float ratiodone=endstops_stepsDone/float(endstops_stepsTotal); //ratio of current_block thas was performed + + endstops_triggerpos[0]=current_position[0]-(endstops_trigsteps[0]*ratiodone)/float(axis_steps_per_unit[0]); + endstops_triggerpos[1]=current_position[1]-(endstops_trigsteps[1]*ratiodone)/float(axis_steps_per_unit[1]); + endstops_triggerpos[2]=current_position[2]-(endstops_trigsteps[2]*ratiodone)/float(axis_steps_per_unit[2]); + SERIAL_ECHO_START; + SERIAL_ECHOPGM("endstops hit: "); + SERIAL_ECHOPAIR(" X:",endstops_triggerpos[0]); + SERIAL_ECHOPAIR(" Y:",endstops_triggerpos[1]); + SERIAL_ECHOPAIR(" Z:",endstops_triggerpos[2]); + SERIAL_ECHOLN(""); + endstops_hit=false; +} +void endstops_hit_on_purpose() +{ + endstops_hit=false; +} // __________________________ // /| |\ _________________ ^ @@ -296,6 +340,7 @@ ISR(TIMER1_COMPA_vect) #endif #if X_MIN_PIN > -1 if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { + endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -307,6 +352,7 @@ ISR(TIMER1_COMPA_vect) #endif #if X_MAX_PIN > -1 if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ + endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -319,6 +365,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Y_MIN_PIN > -1 if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { + endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -330,6 +377,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Y_MAX_PIN > -1 if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ + endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -342,6 +390,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Z_MIN_PIN > -1 if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { + endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -353,6 +402,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Z_MAX_PIN > -1 if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ + endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif diff --git a/Marlin/stepper.h b/Marlin/stepper.h index fb649692d3..ecbc713e36 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -39,6 +39,13 @@ void st_wake_up(); extern volatile long count_position[NUM_AXIS]; extern volatile int count_direction[NUM_AXIS]; #endif + +void checkHitEndstops(); //call from somwhere to create an serial error message with the locations the endstops where hit, in case they were triggered +void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after homeing and before a routine call of checkHitEndstops(); + + extern block_t *current_block; // A pointer to the block currently being traced + + #endif From 65934eee9c6ae792c708bc1cea9996c8a5df67f5 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 13 Nov 2011 20:42:08 +0100 Subject: [PATCH 038/228] A lot of changes in the planner code --- Marlin/Configuration.h | 37 +- Marlin/Marlin.pde | 8 +- Marlin/planner.cpp | 1297 ++++++++++++++++++++----------------- Marlin/planner.h | 187 +++--- Marlin/stepper.cpp | 1227 ++++++++++++++++++----------------- Marlin/temperature.cpp | 1124 ++++++++++++++++---------------- Marlin/thermistortables.h | 16 +- 7 files changed, 2019 insertions(+), 1877 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index a0d46bfed7..2f1e8ad837 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -6,6 +6,15 @@ #define MM_PER_ARC_SEGMENT 1 #define N_ARC_CORRECTION 25 +// Frequency limit +// See nophead's blog for more info +#define XY_FREQUENCY_LIMIT 15 + +// Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end +// of the buffer and all stops. This should not be much greater than zero and should only be changed +// if unwanted behavior is observed on a user's machine when running at very slow speeds. +#define MINIMUM_PLANNER_SPEED 2.0 // (mm/sec) + // BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration //// The following define selects which electronics board you have. Please choose the one that matches your setup @@ -97,6 +106,11 @@ const int dropsegments=5; //everything with this number of steps will be ignore #define DISABLE_E false // Inverting axis direction +//#define INVERT_X_DIR false // for Mendel set to false, for Orca set to true +//#define INVERT_Y_DIR true // for Mendel set to true, for Orca set to false +//#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true +//#define INVERT_E_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false + #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false #define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true @@ -117,7 +131,7 @@ const int dropsegments=5; //everything with this number of steps will be ignore //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E //note: on bernhards ultimaker 200 200 12 are working well. -#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds +#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) #define AXIS_RELATIVE_MODES {false, false, false, false} @@ -126,19 +140,20 @@ const int dropsegments=5; //everything with this number of steps will be ignore // default settings #define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker -#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} -#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +//#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} +#define DEFAULT_MAX_FEEDRATE {500, 500, 10, 500000} // (mm/min) +#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. #define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts -#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 10 +#define DEFAULT_MINIMUMFEEDRATE 0 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 0 // minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. #define DEFAULT_MINSEGMENTTIME 20000 -#define DEFAULT_XYJERK 30.0*60 -#define DEFAULT_ZJERK 10.0*60 +#define DEFAULT_XYJERK 30.0 // (mm/sec) +#define DEFAULT_ZJERK 0.4 // (mm/sec) // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature @@ -162,7 +177,7 @@ const int dropsegments=5; //everything with this number of steps will be ignore //#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one //// The minimal temperature defines the temperature below which the heater will not be enabled -#define HEATER_0_MINTEMP 5 +//#define HEATER_0_MINTEMP 5 //#define HEATER_1_MINTEMP 5 //#define BED_MINTEMP 5 @@ -170,7 +185,7 @@ const int dropsegments=5; //everything with this number of steps will be ignore // When temperature exceeds max temp, your heater will be switched off. // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 275 +//#define HEATER_0_MAXTEMP 275 //#define_HEATER_1_MAXTEMP 275 //#define BED_MAXTEMP 150 @@ -246,9 +261,9 @@ const int dropsegments=5; //everything with this number of steps will be ignore // The number of linear motions that can be in the plan at any give time. // THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ringbuffering. #if defined SDSUPPORT - #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller + #define BLOCK_BUFFER_SIZE 8 // SD,LCD,Buttons take more memory, block buffer needs to be smaller #else - #define BLOCK_BUFFER_SIZE 16 // maximize block buffer + #define BLOCK_BUFFER_SIZE 8 // maximize block buffer #endif //The ASCII buffer for recieving from the serial: diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 104fc6576e..1d722879ef 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -114,7 +114,9 @@ extern float HeaterPower; //=========================================================================== //=============================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 @@ -215,7 +217,9 @@ void loop() { if(buflen<3) get_command(); + #ifdef SDSUPPORT card.checkautostart(false); + #endif if(buflen) { #ifdef SDSUPPORT @@ -933,7 +937,7 @@ inline void get_arc_coordinates() void prepare_move() { - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0); for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } @@ -943,7 +947,7 @@ 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.0/100.0, r, isclockwise); + mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise); // 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 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 34e29ff535..fe19055c4b 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -1,594 +1,705 @@ -/* - planner.c - buffers movement commands and manages the acceleration profile plan - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ - -/* - Reasoning behind the mathematics in this module (in the key of 'Mathematica'): - - s == speed, a == acceleration, t == time, d == distance - - Basic definitions: - - Speed[s_, a_, t_] := s + (a*t) - Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] - - Distance to reach a specific speed with a constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] - d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() - - Speed after a given distance of travel with constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] - m -> Sqrt[2 a d + s^2] - - DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] - - When to start braking (di) to reach a specified destionation speed (s2) after accelerating - from initial speed s1 without ever stopping at a plateau: - - Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] - di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() - - IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) -*/ - - -//#include -//#include -//#include - -#include "Marlin.h" -#include "Configuration.h" -#include "pins.h" -#include "fastio.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" -#include "ultralcd.h" - -//=========================================================================== -//=============================public variables ============================ -//=========================================================================== - -unsigned long minsegmenttime; -float max_feedrate[4]; // set the max speeds -float axis_steps_per_unit[4]; -long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -float minimumfeedrate; -float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -float max_z_jerk; -float mintravelfeedrate; -unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - -// The current position of the tool in absolute steps -long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode - - -//=========================================================================== -//=============================private variables ============================ -//=========================================================================== -static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions -static volatile unsigned char block_buffer_head; // Index of the next block to be pushed -static volatile unsigned char block_buffer_tail; // Index of the block to process now - - - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== -#define ONE_MINUTE_OF_MICROSECONDS 60000000.0 - -// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the -// given acceleration: -inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { - if (acceleration!=0) { - return((target_rate*target_rate-initial_rate*initial_rate)/ - (2.0*acceleration)); - } - else { - return 0.0; // acceleration was 0, set acceleration distance to 0 - } -} - -// This function gives you the point at which you must start braking (at the rate of -acceleration) if -// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after -// a total travel of distance. This can be used to compute the intersection point between acceleration and -// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) - -inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { - if (acceleration!=0) { - return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ - (4.0*acceleration) ); - } - else { - return 0.0; // acceleration was 0, set intersection distance to 0 - } -} - -// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. - -void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit_speed) { - if(block->busy == true) return; // If block is busy then bail out. - float entry_factor = entry_speed / block->nominal_speed; - float exit_factor = exit_speed / block->nominal_speed; - long initial_rate = ceil(block->nominal_rate*entry_factor); - long final_rate = ceil(block->nominal_rate*exit_factor); - - #ifdef ADVANCE - long initial_advance = block->advance*entry_factor*entry_factor; - long final_advance = block->advance*exit_factor*exit_factor; - #endif // ADVANCE - - // Limit minimal step rate (Otherwise the timer will overflow.) - if(initial_rate <120) initial_rate=120; - if(final_rate < 120) final_rate=120; - - // Calculate the acceleration steps - long acceleration = block->acceleration_st; - long accelerate_steps = estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration); - long decelerate_steps = estimate_acceleration_distance(final_rate, block->nominal_rate, acceleration); - // Calculate the size of Plateau of Nominal Rate. - long plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; - - // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will - // 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 = intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count); - plateau_steps = 0; - } - - long decelerate_after = accelerate_steps+plateau_steps; - - CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section - if(block->busy == false) { // Don't update variables if block is busy. - block->accelerate_until = accelerate_steps; - block->decelerate_after = decelerate_after; - block->initial_rate = initial_rate; - block->final_rate = final_rate; - #ifdef ADVANCE - block->initial_advance = initial_advance; - block->final_advance = final_advance; - #endif //ADVANCE - } - CRITICAL_SECTION_END; -} - -// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the -// acceleration within the allotted distance. -inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { - return sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance); -} - -// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. -// This method will calculate the junction jerk as the euclidean distance between the nominal -// velocities of the respective blocks. -inline float junction_jerk(block_t *before, block_t *after) { - return sqrt( - pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); -} - -// Return the safe speed which is max_jerk/2, e.g. the -// speed under which you cannot exceed max_jerk no matter what you do. -float safe_speed(block_t *block) { - float safe_speed; - safe_speed = max_xy_jerk/2; - if(abs(block->speed_z) > max_z_jerk/2) - safe_speed = max_z_jerk/2; - if (safe_speed > block->nominal_speed) - safe_speed = block->nominal_speed; - return safe_speed; -} - -// The kernel called by planner_recalculate() when scanning the plan from last to first entry. -void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - - float entry_speed = current->nominal_speed; - float exit_factor; - float exit_speed; - if (next) { - exit_speed = next->entry_speed; - } - else { - exit_speed = safe_speed(current); - } - - // Calculate the entry_factor for the current block. - if (previous) { - // Reduce speed so that junction_jerk is within the maximum allowed - float jerk = junction_jerk(previous, current); - if((previous->steps_x == 0) && (previous->steps_y == 0)) { - entry_speed = safe_speed(current); - } - else if (jerk > max_xy_jerk) { - entry_speed = (max_xy_jerk/jerk) * entry_speed; - } - if(abs(previous->speed_z - current->speed_z) > max_z_jerk) { - entry_speed = (max_z_jerk/abs(previous->speed_z - current->speed_z)) * entry_speed; - } - // If the required deceleration across the block is too rapid, reduce the entry_factor accordingly. - if (entry_speed > exit_speed) { - float max_entry_speed = max_allowable_speed(-current->acceleration,exit_speed, current->millimeters); - if (max_entry_speed < entry_speed) { - entry_speed = max_entry_speed; - } - } - } - else { - entry_speed = safe_speed(current); - } - // Store result - current->entry_speed = entry_speed; -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the reverse pass. -void planner_reverse_pass() { - char block_index = block_buffer_head; - if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { - block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); - block_t *block[5] = { - NULL, NULL, NULL, NULL, NULL }; - while(block_index != block_buffer_tail) { - block_index = (block_index-1) & (BLOCK_BUFFER_SIZE -1); - block[2]= block[1]; - block[1]= block[0]; - block[0] = &block_buffer[block_index]; - planner_reverse_pass_kernel(block[0], block[1], block[2]); - } - planner_reverse_pass_kernel(NULL, block[0], block[1]); - } -} - -// The kernel called by planner_recalculate() when scanning the plan from first to last entry. -void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - if(previous) { - // If the previous block is an acceleration block, but it is not long enough to - // complete the full speed change within the block, we need to adjust out entry - // speed accordingly. Remember current->entry_factor equals the exit factor of - // the previous block. - if(previous->entry_speed < current->entry_speed) { - float max_entry_speed = max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters); - if (max_entry_speed < current->entry_speed) { - current->entry_speed = max_entry_speed; - } - } - } -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the forward pass. -void planner_forward_pass() { - char block_index = block_buffer_tail; - block_t *block[3] = { - NULL, NULL, NULL }; - - while(block_index != block_buffer_head) { - block[0] = block[1]; - block[1] = block[2]; - block[2] = &block_buffer[block_index]; - planner_forward_pass_kernel(block[0],block[1],block[2]); - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - planner_forward_pass_kernel(block[1], block[2], NULL); -} - -// Recalculates the trapezoid speed profiles for all blocks in the plan according to the -// entry_factor for each junction. Must be called by planner_recalculate() after -// updating the blocks. -void planner_recalculate_trapezoids() { - char block_index = block_buffer_tail; - block_t *current; - block_t *next = NULL; - while(block_index != block_buffer_head) { - current = next; - next = &block_buffer[block_index]; - if (current) { - calculate_trapezoid_for_block(current, current->entry_speed, next->entry_speed); - } - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - calculate_trapezoid_for_block(next, next->entry_speed, safe_speed(next)); -} - -// Recalculates the motion plan according to the following algorithm: -// -// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) -// so that: -// a. The junction jerk is within the set limit -// b. No speed reduction within one block requires faster deceleration than the one, true constant -// acceleration. -// 2. Go over every block in chronological order and dial down junction speed reduction values if -// a. The speed increase within one block would require faster accelleration than the one, true -// constant acceleration. -// -// When these stages are complete all blocks have an entry_factor that will allow all speed changes to -// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than -// the set limit. Finally it will: -// -// 3. Recalculate trapezoids for all blocks. - -void planner_recalculate() { - planner_reverse_pass(); - planner_forward_pass(); - planner_recalculate_trapezoids(); -} - -void plan_init() { - block_buffer_head = 0; - block_buffer_tail = 0; - memset(position, 0, sizeof(position)); // clear position -} - - -void plan_discard_current_block() { - if (block_buffer_head != block_buffer_tail) { - block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); - } -} - -block_t *plan_get_current_block() { - if (block_buffer_head == block_buffer_tail) { - return(NULL); - } - block_t *block = &block_buffer[block_buffer_tail]; - block->busy = true; - return(block); -} - -void check_axes_activity() { - unsigned char x_active = 0; - unsigned char y_active = 0; - unsigned char z_active = 0; - unsigned char e_active = 0; - block_t *block; - - if(block_buffer_tail != block_buffer_head) { - char block_index = block_buffer_tail; - while(block_index != block_buffer_head) { - block = &block_buffer[block_index]; - if(block->steps_x != 0) x_active++; - if(block->steps_y != 0) y_active++; - if(block->steps_z != 0) z_active++; - if(block->steps_e != 0) e_active++; - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - } - if((DISABLE_X) && (x_active == 0)) disable_x(); - if((DISABLE_Y) && (y_active == 0)) disable_y(); - if((DISABLE_Z) && (z_active == 0)) disable_z(); - if((DISABLE_E) && (e_active == 0)) disable_e(); -} - -// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in -// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration -// calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate) -{ - // Calculate the buffer head after we push this byte - int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); - - // If the buffer is full: good! That means we are well ahead of the robot. - // Rest here until there is room in the buffer. - while(block_buffer_tail == next_buffer_head) { - manage_heater(); - manage_inactivity(1); - LCD_STATUS; - } - - // The target position of the tool in absolute steps - // Calculate target position in absolute steps - //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow - long target[4]; - target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - - // Prepare to set up new block - block_t *block = &block_buffer[block_buffer_head]; - - // Mark block as not busy (Not executed by the stepper interrupt) - block->busy = false; - - // Number of steps for each axis - block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); - block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); - block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); - block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); - block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); - - // Bail if this is a zero-length block - if (block->step_event_count <=dropsegments) { - return; - }; - - //enable active axes - if(block->steps_x != 0) enable_x(); - if(block->steps_y != 0) enable_y(); - if(block->steps_z != 0) enable_z(); - if(block->steps_e != 0) enable_e(); - - float delta_x_mm = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; - float delta_y_mm = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; - float delta_z_mm = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; - float delta_e_mm = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; - block->millimeters = sqrt(square(delta_x_mm) + square(delta_y_mm) + square(delta_z_mm) + square(delta_e_mm)); - - unsigned long microseconds; - - if (block->steps_e == 0) { - if(feed_ratemillimeters/feed_rate)*1000000); - - // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill - // reduces/removes corner blobs as the machine won't come to a full stop. - int blockcount=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); - - if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { - if (microsecondsspeed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - - - // Limit speed per axis - float speed_factor = 1; //factor <=1 do decrease speed - if(abs(block->speed_x) > max_feedrate[X_AXIS]) { - speed_factor = max_feedrate[X_AXIS] / abs(block->speed_x); - //if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; /is not need here because auf the init above - } - if(abs(block->speed_y) > max_feedrate[Y_AXIS]){ - float tmp_speed_factor = max_feedrate[Y_AXIS] / abs(block->speed_y); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_z) > max_feedrate[Z_AXIS]){ - float tmp_speed_factor = max_feedrate[Z_AXIS] / abs(block->speed_z); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_e) > max_feedrate[E_AXIS]){ - float tmp_speed_factor = max_feedrate[E_AXIS] / abs(block->speed_e); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - multiplier = multiplier * speed_factor; - block->speed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - block->nominal_speed = block->millimeters * multiplier; - block->nominal_rate = ceil(block->step_event_count * multiplier / 60); - - if(block->nominal_rate < 120) - block->nominal_rate = 120; - block->entry_speed = safe_speed(block); - - // Compute the acceleration rate for the trapezoid generator. - float travel_per_step = block->millimeters/block->step_event_count; - if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { - block->acceleration_st = ceil( (retract_acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - } - else { - block->acceleration_st = ceil( (acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - float tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - // Limit acceleration per axis - if((tmp_acceleration * block->steps_x) > axis_steps_per_sqr_second[X_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_y) > axis_steps_per_sqr_second[Y_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_e) > axis_steps_per_sqr_second[E_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_z) > axis_steps_per_sqr_second[Z_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - } - block->acceleration = block->acceleration_st * travel_per_step; - block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); - - #ifdef ADVANCE - // Calculate advance rate - if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { - block->advance_rate = 0; - block->advance = 0; - } - else { - long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); - float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; - block->advance = advance; - if(acc_dist == 0) { - block->advance_rate = 0; - } - else { - block->advance_rate = advance / (float)acc_dist; - } - } - #endif // ADVANCE - - // compute a preliminary conservative acceleration trapezoid - float safespeed = safe_speed(block); - calculate_trapezoid_for_block(block, safespeed, safespeed); - - // Compute direction bits for this block - block->direction_bits = 0; - if (target[X_AXIS] < position[X_AXIS]) { - block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<. +*/ + +/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ + +/* + Reasoning behind the mathematics in this module (in the key of 'Mathematica'): + + s == speed, a == acceleration, t == time, d == distance + + Basic definitions: + + Speed[s_, a_, t_] := s + (a*t) + Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] + + Distance to reach a specific speed with a constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] + d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() + + Speed after a given distance of travel with constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] + m -> Sqrt[2 a d + s^2] + + DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] + + When to start braking (di) to reach a specified destionation speed (s2) after accelerating + from initial speed s1 without ever stopping at a plateau: + + Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] + di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() + + IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) +*/ + + +//#include +//#include +//#include + +#include "Marlin.h" +#include "Configuration.h" +#include "pins.h" +#include "fastio.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" +#include "ultralcd.h" + +//=========================================================================== +//=============================public variables ============================ +//=========================================================================== + +unsigned long minsegmenttime; +float max_feedrate[4]; // set the max speeds +float axis_steps_per_unit[4]; +long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +float minimumfeedrate; +float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +float max_z_jerk; +float mintravelfeedrate; +unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + +// The current position of the tool in absolute steps +long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode +static float previous_speed[4]; // Speed of previous path line segment +static float previous_nominal_speed; // Nominal speed of previous path line segment + + +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== +static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +static volatile unsigned char block_buffer_head; // Index of the next block to be pushed +static volatile unsigned char block_buffer_tail; // Index of the block to process now + +// Used for the frequency limit +static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations +static long x_segment_time[3]={0,0,0}; // Segment times (in us). Used for speed calculations +static long y_segment_time[3]={0,0,0}; + +// Returns the index of the next block in the ring buffer +// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. +static int8_t next_block_index(int8_t block_index) { + block_index++; + if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; } + return(block_index); +} + + +// Returns the index of the previous block in the ring buffer +static int8_t prev_block_index(int8_t block_index) { + if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; } + block_index--; + return(block_index); +} + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + +// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the +// given acceleration: +inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { + if (acceleration!=0) { + return((target_rate*target_rate-initial_rate*initial_rate)/ + (2.0*acceleration)); + } + else { + return 0.0; // acceleration was 0, set acceleration distance to 0 + } +} + +// This function gives you the point at which you must start braking (at the rate of -acceleration) if +// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after +// a total travel of distance. This can be used to compute the intersection point between acceleration and +// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) + +inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { + if (acceleration!=0) { + return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ + (4.0*acceleration) ); + } + else { + return 0.0; // acceleration was 0, set intersection distance to 0 + } +} + +// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. + +void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) { + long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) + long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) + + // Limit minimal step rate (Otherwise the timer will overflow.) + if(initial_rate <120) {initial_rate=120; } + if(final_rate < 120) {final_rate=120; } + + long acceleration = block->acceleration_st; + int32_t accelerate_steps = + ceil(estimate_acceleration_distance(block->initial_rate, block->nominal_rate, acceleration)); + int32_t decelerate_steps = + floor(estimate_acceleration_distance(block->nominal_rate, block->final_rate, -acceleration)); + + // Calculate the size of Plateau of Nominal Rate. + int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; + + // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will + // 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 = max(accelerate_steps,0); // Check limits due to numerical round-off + accelerate_steps = min(accelerate_steps,block->step_event_count); + plateau_steps = 0; + } + + #ifdef ADVANCE + long initial_advance = block->advance*entry_factor*entry_factor; + long final_advance = block->advance*exit_factor*exit_factor; + #endif // ADVANCE + + // block->accelerate_until = accelerate_steps; + // block->decelerate_after = accelerate_steps+plateau_steps; + + CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section + if(block->busy == false) { // Don't update variables if block is busy. + block->accelerate_until = accelerate_steps; + block->decelerate_after = accelerate_steps+plateau_steps; + block->initial_rate = initial_rate; + block->final_rate = final_rate; + #ifdef ADVANCE + block->initial_advance = initial_advance; + block->final_advance = final_advance; + #endif //ADVANCE + } + CRITICAL_SECTION_END; +} + +// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the +// acceleration within the allotted distance. +inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { + return sqrt(target_velocity*target_velocity-2*acceleration*distance); +} + +// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. +// This method will calculate the junction jerk as the euclidean distance between the nominal +// velocities of the respective blocks. +//inline float junction_jerk(block_t *before, block_t *after) { +// return sqrt( +// pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); +//} + + +// The kernel called by planner_recalculate() when scanning the plan from last to first entry. +void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!current) { return; } + + if (next) { + // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising. + // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and + // check for maximum allowable speed reductions to ensure maximum possible planned speed. + if (current->entry_speed != current->max_entry_speed) { + + // If nominal length true, max junction speed is guaranteed to be reached. Only compute + // for max allowable speed if block is decelerating and nominal length is false. + if ((!current->nominal_length_flag) && (current->max_entry_speed > next->entry_speed)) { + current->entry_speed = min( current->max_entry_speed, + max_allowable_speed(-current->acceleration,next->entry_speed,current->millimeters)); + } else { + current->entry_speed = current->max_entry_speed; + } + current->recalculate_flag = true; + + } + } // Skip last block. Already initialized and set for recalculation. +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the reverse pass. +void planner_reverse_pass() { + char block_index = block_buffer_head; + if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { + block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); + block_t *block[3] = { NULL, NULL, NULL }; + while(block_index != block_buffer_tail) { + block_index = prev_block_index(block_index); + block[2]= block[1]; + block[1]= block[0]; + block[0] = &block_buffer[block_index]; + planner_reverse_pass_kernel(block[0], block[1], block[2]); + } + } +} + +// The kernel called by planner_recalculate() when scanning the plan from first to last entry. +void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!previous) { return; } + + // If the previous block is an acceleration block, but it is not long enough to complete the + // full speed change within the block, we need to adjust the entry speed accordingly. Entry + // speeds have already been reset, maximized, and reverse planned by reverse planner. + // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck. + if (!previous->nominal_length_flag) { + if (previous->entry_speed < current->entry_speed) { + double entry_speed = min( current->entry_speed, + max_allowable_speed(-previous->acceleration,previous->entry_speed,previous->millimeters) ); + + // Check for junction speed change + if (current->entry_speed != entry_speed) { + current->entry_speed = entry_speed; + current->recalculate_flag = true; + } + } + } +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the forward pass. +void planner_forward_pass() { + char block_index = block_buffer_tail; + block_t *block[3] = { NULL, NULL, NULL }; + + while(block_index != block_buffer_head) { + block[0] = block[1]; + block[1] = block[2]; + block[2] = &block_buffer[block_index]; + planner_forward_pass_kernel(block[0],block[1],block[2]); + block_index = next_block_index(block_index); + } + planner_forward_pass_kernel(block[1], block[2], NULL); +} + +// Recalculates the trapezoid speed profiles for all blocks in the plan according to the +// entry_factor for each junction. Must be called by planner_recalculate() after +// updating the blocks. +void planner_recalculate_trapezoids() { + int8_t block_index = block_buffer_tail; + block_t *current; + block_t *next = NULL; + + while(block_index != block_buffer_head) { + current = next; + next = &block_buffer[block_index]; + if (current) { + // Recalculate if current block entry or exit junction speed has changed. + if (current->recalculate_flag || next->recalculate_flag) { + // NOTE: Entry and exit factors always > 0 by all previous logic operations. + calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed, + next->entry_speed/current->nominal_speed); + current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed + } + } + block_index = next_block_index( block_index ); + } + // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated. + if(next != NULL) { + calculate_trapezoid_for_block(next, next->entry_speed/next->nominal_speed, + MINIMUM_PLANNER_SPEED/next->nominal_speed); + next->recalculate_flag = false; + } +} + +// Recalculates the motion plan according to the following algorithm: +// +// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) +// so that: +// a. The junction jerk is within the set limit +// b. No speed reduction within one block requires faster deceleration than the one, true constant +// acceleration. +// 2. Go over every block in chronological order and dial down junction speed reduction values if +// a. The speed increase within one block would require faster accelleration than the one, true +// constant acceleration. +// +// When these stages are complete all blocks have an entry_factor that will allow all speed changes to +// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than +// the set limit. Finally it will: +// +// 3. Recalculate trapezoids for all blocks. + +void planner_recalculate() { + planner_reverse_pass(); + planner_forward_pass(); + planner_recalculate_trapezoids(); +} + +void plan_init() { + block_buffer_head = 0; + block_buffer_tail = 0; + memset(position, 0, sizeof(position)); // clear position + previous_speed[0] = 0.0; + previous_speed[1] = 0.0; + previous_speed[2] = 0.0; + previous_speed[3] = 0.0; + previous_nominal_speed = 0.0; +} + + +void plan_discard_current_block() { + if (block_buffer_head != block_buffer_tail) { + block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); + } +} + +block_t *plan_get_current_block() { + if (block_buffer_head == block_buffer_tail) { + return(NULL); + } + block_t *block = &block_buffer[block_buffer_tail]; + block->busy = true; + return(block); +} + +void check_axes_activity() { + unsigned char x_active = 0; + unsigned char y_active = 0; + unsigned char z_active = 0; + unsigned char e_active = 0; + block_t *block; + + if(block_buffer_tail != block_buffer_head) { + char block_index = block_buffer_tail; + while(block_index != block_buffer_head) { + block = &block_buffer[block_index]; + if(block->steps_x != 0) x_active++; + if(block->steps_y != 0) y_active++; + if(block->steps_z != 0) z_active++; + if(block->steps_e != 0) e_active++; + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + } + if((DISABLE_X) && (x_active == 0)) disable_x(); + if((DISABLE_Y) && (y_active == 0)) disable_y(); + if((DISABLE_Z) && (z_active == 0)) disable_z(); + if((DISABLE_E) && (e_active == 0)) disable_e(); +} + + +float junction_deviation = 0.1; +// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in +// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration +// calculation the caller must also provide the physical length of the line in millimeters. +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate) +{ + // Calculate the buffer head after we push this byte + int next_buffer_head = next_block_index(block_buffer_head); + + // If the buffer is full: good! That means we are well ahead of the robot. + // Rest here until there is room in the buffer. + while(block_buffer_tail == next_buffer_head) { + manage_heater(); + manage_inactivity(1); + LCD_STATUS; + } + + // The target position of the tool in absolute steps + // Calculate target position in absolute steps + //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow + long target[4]; + target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + + // Prepare to set up new block + block_t *block = &block_buffer[block_buffer_head]; + + // Mark block as not busy (Not executed by the stepper interrupt) + block->busy = false; + + // Number of steps for each axis + block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); + block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); + block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); + block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); + block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); + + // Bail if this is a zero-length block + if (block->step_event_count <=dropsegments) { return; }; + + // Compute direction bits for this block + block->direction_bits = 0; + if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<steps_x != 0) enable_x(); + if(block->steps_y != 0) enable_y(); + if(block->steps_z != 0) enable_z(); + if(block->steps_e != 0) enable_e(); + + float delta_mm[4]; + delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; + delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; + delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; + delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; + block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + + square(delta_mm[Z_AXIS])); + float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides + + // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. + float inverse_second = feed_rate * inverse_millimeters; + + block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 + block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 + +// unsigned long microseconds; +#if 0 + if (block->steps_e == 0) { + if(feed_ratemillimeters/feed_rate)*1000000); + + // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill + // reduces/removes corner blobs as the machine won't come to a full stop. + int blockcount=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + + if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { + if (microseconds max_feedrate[i]) + speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); + } + +// Max segement time in us. + +#ifdef XY_FREQUENCY_LIMIT +#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT) + + // Check and limit the xy direction change frequency + unsigned char direction_change = block->direction_bits ^ old_direction_bits; + old_direction_bits = block->direction_bits; + long segment_time = lround(1000000.0/inverse_second); + if((direction_change & (1< max_feedrate[i]) + speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); +// Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); + } + for(unsigned char i=0; i < 4; i++) { + current_speed[i] *= speed_factor; + } + block->nominal_speed *= speed_factor; + block->nominal_rate *= speed_factor; + } + + // Compute and limit the acceleration rate for the trapezoid generator. + float steps_per_mm = block->step_event_count/block->millimeters; + if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { + block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 + } + else { + block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 + // Limit acceleration per axis + if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_y / (float)block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_e / (float)block->step_event_count) > axis_steps_per_sqr_second[E_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; + } + block->acceleration = block->acceleration_st / steps_per_mm; + block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); + +#if 0 // Use old jerk for now + // Compute path unit vector + double unit_vec[3]; + + unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; + unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; + unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; + + // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. + // Let a circle be tangent to both previous and current path line segments, where the junction + // deviation is defined as the distance from the junction to the closest edge of the circle, + // colinear with the circle center. The circular segment joining the two paths represents the + // path of centripetal acceleration. Solve for max velocity based on max acceleration about the + // radius of the circle, defined indirectly by junction deviation. This may be also viewed as + // path width or max_jerk in the previous grbl version. This approach does not actually deviate + // from path, but used as a robust way to compute cornering speeds, as it takes into account the + // nonlinearities of both the junction angle and junction velocity. + double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed + + // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles. + if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { + // Compute cosine of angle between previous and current path. (prev_unit_vec is negative) + // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity. + double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] + - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] + - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; + + // Skip and use default max junction speed for 0 degree acute junction. + if (cos_theta < 0.95) { + vmax_junction = min(previous_nominal_speed,block->nominal_speed); + // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds. + if (cos_theta > -0.95) { + // Compute maximum junction velocity based on maximum acceleration and junction deviation + double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. + vmax_junction = min(vmax_junction, + sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); + } + } + } +#endif + // Start with a safe speed + float vmax_junction = max_xy_jerk/2; + if(abs(current_speed[Z_AXIS]) > max_z_jerk/2) + vmax_junction = max_z_jerk/2; + vmax_junction = min(vmax_junction, block->nominal_speed); + + if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { + float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); + if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { + vmax_junction = block->nominal_speed; + } + if (jerk > max_xy_jerk) { + vmax_junction *= (max_xy_jerk/jerk); + } + if(abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { + vmax_junction *= (max_z_jerk/abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); + } + } + block->max_entry_speed = vmax_junction; + + // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. + double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); + block->entry_speed = min(vmax_junction, v_allowable); + + // Initialize planner efficiency flags + // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. + // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then + // the current block and next block junction speeds are guaranteed to always be at their maximum + // junction speeds in deceleration and acceleration, respectively. This is due to how the current + // block nominal speed limits both the current and next maximum junction speeds. Hence, in both + // the reverse and forward planners, the corresponding block junction speed will always be at the + // the maximum junction speed and may always be ignored for any speed reduction checks. + if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } + else { block->nominal_length_flag = false; } + block->recalculate_flag = true; // Always calculate trapezoid for new block + + // Update previous path unit_vector and nominal speed + memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[] + previous_nominal_speed = block->nominal_speed; + + #ifdef ADVANCE + // Calculate advance rate + if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { + block->advance_rate = 0; + block->advance = 0; + } + else { + long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); + float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * + (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; + block->advance = advance; + if(acc_dist == 0) { + block->advance_rate = 0; + } + else { + block->advance_rate = advance / (float)acc_dist; + } + } + #endif // ADVANCE + + + + + calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, + MINIMUM_PLANNER_SPEED/block->nominal_speed); + + // Move buffer head + block_buffer_head = next_buffer_head; + + // Update position + memcpy(position, target, sizeof(target)); // position[] = target[] + + planner_recalculate(); + + st_wake_up(); +} + +void plan_set_position(const float &x, const float &y, const float &z, const float &e) +{ + position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. + previous_speed[0] = 0.0; + previous_speed[1] = 0.0; + previous_speed[2] = 0.0; + previous_speed[3] = 0.0; +} diff --git a/Marlin/planner.h b/Marlin/planner.h index 79f54d879f..40f214ebfb 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -1,93 +1,96 @@ -/* - planner.h - buffers movement commands and manages the acceleration profile plan - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -// This module is to be considered a sub-module of stepper.c. Please don't include -// this file from any other module. - -#ifndef planner_h -#define planner_h - -#include "Configuration.h" - -// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in -// the source g-code and may never actually be reached if acceleration management is active. -typedef struct { - // Fields used by the bresenham algorithm for tracing the line - long steps_x, steps_y, steps_z, steps_e; // Step count along each axis - long step_event_count; // The number of step events required to complete this block - volatile long accelerate_until; // The index of the step event on which to stop acceleration - volatile long decelerate_after; // The index of the step event on which to start decelerating - volatile long acceleration_rate; // The acceleration rate used for acceleration calculation - unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) - #ifdef ADVANCE - long advance_rate; - volatile long initial_advance; - volatile long final_advance; - float advance; - #endif - - // Fields used by the motion planner to manage acceleration - float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis - float nominal_speed; // The nominal speed for this block in mm/min - float millimeters; // The total travel of this block in mm - float entry_speed; - float acceleration; // acceleration mm/sec^2 - - // Settings for the trapezoid generator - long nominal_rate; // The nominal step rate for this block in step_events/sec - volatile long initial_rate; // The jerk-adjusted step rate at start of block - volatile long final_rate; // The minimal rate at exit - long acceleration_st; // acceleration steps/sec^2 - volatile char busy; -} block_t; - -// Initialize the motion plan subsystem -void plan_init(); - -// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in -// millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate); - -// Set position. Used for G92 instructions. -void plan_set_position(const float &x, const float &y, const float &z, const float &e); - - -// Called when the current block is no longer needed. Discards the block and makes the memory -// availible for new blocks. -void plan_discard_current_block(); - -// Gets the current block. Returns NULL if buffer empty -block_t *plan_get_current_block(); - -void check_axes_activity(); - -extern unsigned long minsegmenttime; -extern float max_feedrate[4]; // set the max speeds -extern float axis_steps_per_unit[4]; -extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -extern float minimumfeedrate; -extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -extern float max_z_jerk; -extern float mintravelfeedrate; -extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - +/* + planner.h - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +// This module is to be considered a sub-module of stepper.c. Please don't include +// this file from any other module. + +#ifndef planner_h +#define planner_h + +#include "Configuration.h" + +// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in +// the source g-code and may never actually be reached if acceleration management is active. +typedef struct { + // Fields used by the bresenham algorithm for tracing the line + long steps_x, steps_y, steps_z, steps_e; // Step count along each axis + long step_event_count; // The number of step events required to complete this block + volatile long accelerate_until; // The index of the step event on which to stop acceleration + volatile long decelerate_after; // The index of the step event on which to start decelerating + volatile long acceleration_rate; // The acceleration rate used for acceleration calculation + unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) + #ifdef ADVANCE +// long advance_rate; +// volatile long initial_advance; +// volatile long final_advance; +// float advance; + #endif + + // Fields used by the motion planner to manage acceleration +// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis + float nominal_speed; // The nominal speed for this block in mm/min + float entry_speed; // Entry speed at previous-current junction in mm/min + float max_entry_speed; // Maximum allowable junction entry speed in mm/min + float millimeters; // The total travel of this block in mm + float acceleration; // acceleration mm/sec^2 + unsigned char recalculate_flag; // Planner flag to recalculate trapezoids on entry junction + unsigned char nominal_length_flag; // Planner flag for nominal speed always reached + + // Settings for the trapezoid generator + long nominal_rate; // The nominal step rate for this block in step_events/sec + volatile long initial_rate; // The jerk-adjusted step rate at start of block + volatile long final_rate; // The minimal rate at exit + long acceleration_st; // acceleration steps/sec^2 + volatile char busy; +} block_t; + +// Initialize the motion plan subsystem +void plan_init(); + +// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in +// millimaters. Feed rate specifies the speed of the motion. +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate); + +// Set position. Used for G92 instructions. +void plan_set_position(const float &x, const float &y, const float &z, const float &e); + + +// Called when the current block is no longer needed. Discards the block and makes the memory +// availible for new blocks. +void plan_discard_current_block(); + +// Gets the current block. Returns NULL if buffer empty +block_t *plan_get_current_block(); + +void check_axes_activity(); + +extern unsigned long minsegmenttime; +extern float max_feedrate[4]; // set the max speeds +extern float axis_steps_per_unit[4]; +extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +extern float minimumfeedrate; +extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +extern float max_z_jerk; +extern float mintravelfeedrate; +extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + #endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 7d94d8063d..e50818ca8c 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -1,612 +1,617 @@ -/* - stepper.c - stepper motor driver: executes motion plans using stepper motors - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith - and Philipp Tiefenbacher. */ - -#include "stepper.h" -#include "Configuration.h" -#include "Marlin.h" -#include "planner.h" -#include "pins.h" -#include "fastio.h" -#include "temperature.h" -#include "ultralcd.h" - -#include "speed_lookuptable.h" - - -//=========================================================================== -//=============================public variables ============================ -//=========================================================================== -block_t *current_block; // A pointer to the block currently being traced - - -//=========================================================================== -//=============================private variables ============================ -//=========================================================================== -//static makes it inpossible to be called from outside of this file by extern.! - -// Variables used by The Stepper Driver Interrupt -static unsigned char out_bits; // The next stepping-bits to be output -static long counter_x, // Counter variables for the bresenham line tracer - counter_y, - counter_z, - counter_e; -static unsigned long step_events_completed; // The number of step events executed in the current block -#ifdef ADVANCE - static long advance_rate, advance, final_advance = 0; - static short old_advance = 0; - static short e_steps; -#endif -static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. -static long acceleration_time, deceleration_time; -//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; -static unsigned short acc_step_rate; // needed for deccelaration start point -static char step_loops; - - - -// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. -// for debugging purposes only, should be disabled by default -#ifdef DEBUG_STEPS - volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; - volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; -#endif - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== - - -// intRes = intIn1 * intIn2 >> 16 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 24 bit result -#define MultiU16X8toH16(intRes, charIn1, intIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %A1, %A2 \n\t" \ -"add %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r0 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (charIn1), \ -"d" (intIn2) \ -: \ -"r26" \ -) - -// intRes = longIn1 * longIn2 >> 24 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 48bit result -#define MultiU24X24toH16(intRes, longIn1, longIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"mov r27, r1 \n\t" \ -"mul %B1, %C2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %C1, %C2 \n\t" \ -"add %B0, r0 \n\t" \ -"mul %C1, %B2 \n\t" \ -"add %A0, r0 \n\t" \ -"adc %B0, r1 \n\t" \ -"mul %A1, %C2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %B2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %C1, %A2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %A2 \n\t" \ -"add r27, r1 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r27 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (longIn1), \ -"d" (longIn2) \ -: \ -"r26" , "r27" \ -) - -// Some useful constants - -#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< -// -// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates -// first block->accelerate_until step_events_completed, then keeps going at constant speed until -// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. -// The slope of acceleration is calculated with the leib ramp alghorithm. - -void st_wake_up() { - // TCNT1 = 0; - ENABLE_STEPPER_DRIVER_INTERRUPT(); -} - -inline unsigned short calc_timer(unsigned short step_rate) { - unsigned short timer; - if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; - - if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times - step_rate = step_rate >> 2; - step_loops = 4; - } - else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times - step_rate = step_rate >> 1; - step_loops = 2; - } - else { - step_loops = 1; - } - - if(step_rate < 32) step_rate = 32; - step_rate -= 32; // Correct for minimal speed - if(step_rate >= (8*256)){ // higher step rate - unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; - unsigned char tmp_step_rate = (step_rate & 0x00ff); - unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); - MultiU16X8toH16(timer, tmp_step_rate, gain); - timer = (unsigned short)pgm_read_word_near(table_address) - timer; - } - else { // lower step rates - unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; - table_address += ((step_rate)>>1) & 0xfffc; - timer = (unsigned short)pgm_read_word_near(table_address); - timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); - } - if(timer < 100) timer = 100; - return timer; -} - -// Initializes the trapezoid generator from the current block. Called whenever a new -// block begins. -inline void trapezoid_generator_reset() { - #ifdef ADVANCE - advance = current_block->initial_advance; - final_advance = current_block->final_advance; - #endif - deceleration_time = 0; - // advance_rate = current_block->advance_rate; - // step_rate to timer interval - acc_step_rate = current_block->initial_rate; - acceleration_time = calc_timer(acc_step_rate); - OCR1A = acceleration_time; -} - -// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. -// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. -ISR(TIMER1_COMPA_vect) -{ - if(busy){ - SERIAL_ERRORLN(*(unsigned short *)OCR1A<< " ISR overtaking itself."); - return; - } // The busy-flag is used to avoid reentering this interrupt - - busy = true; - sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) - - // If there is no current block, attempt to pop one from the buffer - if (current_block == NULL) { - // Anything in the buffer? - current_block = plan_get_current_block(); - if (current_block != NULL) { - trapezoid_generator_reset(); - counter_x = -(current_block->step_event_count >> 1); - counter_y = counter_x; - counter_z = counter_x; - counter_e = counter_x; - step_events_completed = 0; - #ifdef ADVANCE - e_steps = 0; - #endif - } - else { -// DISABLE_STEPPER_DRIVER_INTERRUPT(); - } - } - - if (current_block != NULL) { - // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt - out_bits = current_block->direction_bits; - - #ifdef ADVANCE - // Calculate E early. - counter_e += current_block->steps_e; - if (counter_e > 0) { - counter_e -= current_block->step_event_count; - if ((out_bits & (1<> 16) - old_advance); - CRITICAL_SECTION_END; - old_advance = advance >> 16; - #endif //ADVANCE - - // Set direction en check limit switches - if ((out_bits & (1< -1 - if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } - #endif - } - else { // +direction - WRITE(X_DIR_PIN,!INVERT_X_DIR); - #ifdef DEBUG_STEPS - count_direction[X_AXIS]=1; - #endif - #if X_MAX_PIN > -1 - if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ - step_events_completed = current_block->step_event_count; - } - #endif - } - - if ((out_bits & (1< -1 - if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } - #endif - } - else { // +direction - WRITE(Y_DIR_PIN,!INVERT_Y_DIR); - #ifdef DEBUG_STEPS - count_direction[Y_AXIS]=1; - #endif - #if Y_MAX_PIN > -1 - if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ - step_events_completed = current_block->step_event_count; - } - #endif - } - - if ((out_bits & (1< -1 - if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { - step_events_completed = current_block->step_event_count; - } - #endif - } - else { // +direction - WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - #ifdef DEBUG_STEPS - count_direction[Z_AXIS]=1; - #endif - #if Z_MAX_PIN > -1 - if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ - step_events_completed = current_block->step_event_count; - } - #endif - } - - #ifndef ADVANCE - if ((out_bits & (1<steps_x; - if (counter_x > 0) { - WRITE(X_STEP_PIN, HIGH); - counter_x -= current_block->step_event_count; - WRITE(X_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[X_AXIS]+=count_direction[X_AXIS]; - #endif - } - - counter_y += current_block->steps_y; - if (counter_y > 0) { - WRITE(Y_STEP_PIN, HIGH); - counter_y -= current_block->step_event_count; - WRITE(Y_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Y_AXIS]+=count_direction[Y_AXIS]; - #endif - } - - counter_z += current_block->steps_z; - if (counter_z > 0) { - WRITE(Z_STEP_PIN, HIGH); - counter_z -= current_block->step_event_count; - WRITE(Z_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Z_AXIS]+=count_direction[Z_AXIS]; - #endif - } - - #ifndef ADVANCE - counter_e += current_block->steps_e; - if (counter_e > 0) { - WRITE(E_STEP_PIN, HIGH); - counter_e -= current_block->step_event_count; - WRITE(E_STEP_PIN, LOW); - } - #endif //!ADVANCE - step_events_completed += 1; - if(step_events_completed >= current_block->step_event_count) break; - } - // Calculare new timer value - unsigned short timer; - unsigned short step_rate; - if (step_events_completed <= current_block->accelerate_until) { - MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); - acc_step_rate += current_block->initial_rate; - - // upper limit - if(acc_step_rate > current_block->nominal_rate) - acc_step_rate = current_block->nominal_rate; - - // step_rate to timer interval - timer = calc_timer(acc_step_rate); - #ifdef ADVANCE - advance += advance_rate; - #endif - acceleration_time += timer; - OCR1A = timer; - } - else if (step_events_completed > current_block->decelerate_after) { - MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); - - if(step_rate > acc_step_rate) { // Check step_rate stays positive - step_rate = current_block->final_rate; - } - else { - step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. - } - - // lower limit - if(step_rate < current_block->final_rate) - step_rate = current_block->final_rate; - - // step_rate to timer interval - timer = calc_timer(step_rate); - #ifdef ADVANCE - advance -= advance_rate; - if(advance < final_advance) - advance = final_advance; - #endif //ADVANCE - deceleration_time += timer; - OCR1A = timer; - } - // If current block is finished, reset pointer - if (step_events_completed >= current_block->step_event_count) { - current_block = NULL; - plan_discard_current_block(); - } - } - cli(); // disable interrupts - busy=false; -} - -#ifdef ADVANCE - unsigned char old_OCR0A; - // Timer interrupt for E. e_steps is set in the main routine; - // Timer 0 is shared with millies - ISR(TIMER0_COMPA_vect) - { - // Critical section needed because Timer 1 interrupt has higher priority. - // The pin set functions are placed on trategic position to comply with the stepper driver timing. - WRITE(E_STEP_PIN, LOW); - // Set E direction (Depends on E direction + advance) - if (e_steps < 0) { - WRITE(E_DIR_PIN,INVERT_E_DIR); - e_steps++; - WRITE(E_STEP_PIN, HIGH); - } - if (e_steps > 0) { - WRITE(E_DIR_PIN,!INVERT_E_DIR); - e_steps--; - WRITE(E_STEP_PIN, HIGH); - } - old_OCR0A += 25; // 10kHz interrupt - OCR0A = old_OCR0A; - } -#endif // ADVANCE - -void st_init() -{ - //Initialize Dir Pins - #if X_DIR_PIN > -1 - SET_OUTPUT(X_DIR_PIN); - #endif - #if Y_DIR_PIN > -1 - SET_OUTPUT(Y_DIR_PIN); - #endif - #if Z_DIR_PIN > -1 - SET_OUTPUT(Z_DIR_PIN); - #endif - #if E_DIR_PIN > -1 - SET_OUTPUT(E_DIR_PIN); - #endif - - //Initialize Enable Pins - steppers default to disabled. - - #if (X_ENABLE_PIN > -1) - SET_OUTPUT(X_ENABLE_PIN); - if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); - #endif - #if (Y_ENABLE_PIN > -1) - SET_OUTPUT(Y_ENABLE_PIN); - if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); - #endif - #if (Z_ENABLE_PIN > -1) - SET_OUTPUT(Z_ENABLE_PIN); - if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); - #endif - #if (E_ENABLE_PIN > -1) - SET_OUTPUT(E_ENABLE_PIN); - if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); - #endif - - //endstops and pullups - #ifdef ENDSTOPPULLUPS - #if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); - WRITE(X_MIN_PIN,HIGH); - #endif - #if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); - WRITE(X_MAX_PIN,HIGH); - #endif - #if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); - WRITE(Y_MIN_PIN,HIGH); - #endif - #if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); - WRITE(Y_MAX_PIN,HIGH); - #endif - #if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); - WRITE(Z_MIN_PIN,HIGH); - #endif - #if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); - WRITE(Z_MAX_PIN,HIGH); - #endif - #else //ENDSTOPPULLUPS - #if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); - #endif - #if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); - #endif - #if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); - #endif - #if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); - #endif - #if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); - #endif - #if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); - #endif - #endif //ENDSTOPPULLUPS - - - //Initialize Step Pins - #if (X_STEP_PIN > -1) - SET_OUTPUT(X_STEP_PIN); - #endif - #if (Y_STEP_PIN > -1) - SET_OUTPUT(Y_STEP_PIN); - #endif - #if (Z_STEP_PIN > -1) - SET_OUTPUT(Z_STEP_PIN); - #endif - #if (E_STEP_PIN > -1) - SET_OUTPUT(E_STEP_PIN); - #endif - - // waveform generation = 0100 = CTC - TCCR1B &= ~(1<. +*/ + +/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith + and Philipp Tiefenbacher. */ + +#include "stepper.h" +#include "Configuration.h" +#include "Marlin.h" +#include "planner.h" +#include "pins.h" +#include "fastio.h" +#include "temperature.h" +#include "ultralcd.h" + +#include "speed_lookuptable.h" + + +//=========================================================================== +//=============================public variables ============================ +//=========================================================================== +block_t *current_block; // A pointer to the block currently being traced + + +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== +//static makes it inpossible to be called from outside of this file by extern.! + +// Variables used by The Stepper Driver Interrupt +static unsigned char out_bits; // The next stepping-bits to be output +static long counter_x, // Counter variables for the bresenham line tracer + counter_y, + counter_z, + counter_e; +static unsigned long step_events_completed; // The number of step events executed in the current block +#ifdef ADVANCE + static long advance_rate, advance, final_advance = 0; + static short old_advance = 0; + static short e_steps; +#endif +static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. +static long acceleration_time, deceleration_time; +//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; +static unsigned short acc_step_rate; // needed for deccelaration start point +static char step_loops; + + + +// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. +// for debugging purposes only, should be disabled by default +#ifdef DEBUG_STEPS + volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; + volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; +#endif + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + + +// intRes = intIn1 * intIn2 >> 16 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 24 bit result +#define MultiU16X8toH16(intRes, charIn1, intIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %A1, %A2 \n\t" \ +"add %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r0 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (charIn1), \ +"d" (intIn2) \ +: \ +"r26" \ +) + +// intRes = longIn1 * longIn2 >> 24 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 48bit result +#define MultiU24X24toH16(intRes, longIn1, longIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"mov r27, r1 \n\t" \ +"mul %B1, %C2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %C1, %C2 \n\t" \ +"add %B0, r0 \n\t" \ +"mul %C1, %B2 \n\t" \ +"add %A0, r0 \n\t" \ +"adc %B0, r1 \n\t" \ +"mul %A1, %C2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %B2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %C1, %A2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %A2 \n\t" \ +"add r27, r1 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r27 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (longIn1), \ +"d" (longIn2) \ +: \ +"r26" , "r27" \ +) + +// Some useful constants + +#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< +// +// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates +// first block->accelerate_until step_events_completed, then keeps going at constant speed until +// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. +// The slope of acceleration is calculated with the leib ramp alghorithm. + +void st_wake_up() { + // TCNT1 = 0; + if(busy == false) + ENABLE_STEPPER_DRIVER_INTERRUPT(); +} + +inline unsigned short calc_timer(unsigned short step_rate) { + unsigned short timer; + if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; + + if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times + step_rate = step_rate >> 2; + step_loops = 4; + } + else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times + step_rate = step_rate >> 1; + step_loops = 2; + } + else { + step_loops = 1; + } + + if(step_rate < 32) step_rate = 32; + step_rate -= 32; // Correct for minimal speed + if(step_rate >= (8*256)){ // higher step rate + unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; + unsigned char tmp_step_rate = (step_rate & 0x00ff); + unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); + MultiU16X8toH16(timer, tmp_step_rate, gain); + timer = (unsigned short)pgm_read_word_near(table_address) - timer; + } + else { // lower step rates + unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; + table_address += ((step_rate)>>1) & 0xfffc; + timer = (unsigned short)pgm_read_word_near(table_address); + timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); + } + //if(timer < 100) timer = 100; + return timer; +} + +// Initializes the trapezoid generator from the current block. Called whenever a new +// block begins. +inline void trapezoid_generator_reset() { + #ifdef ADVANCE + advance = current_block->initial_advance; + final_advance = current_block->final_advance; + #endif + deceleration_time = 0; + // step_rate to timer interval + acc_step_rate = current_block->initial_rate; + acceleration_time = calc_timer(acc_step_rate); + OCR1A = acceleration_time; +} + +// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. +// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. +ISR(TIMER1_COMPA_vect) +{ + if(busy){ +/* SERIAL_ERRORLN(*(unsigned short *)OCR1A<< " ISR overtaking itself.");*/ + return; + } // The busy-flag is used to avoid reentering this interrupt + + busy = true; + sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) + + // If there is no current block, attempt to pop one from the buffer + if (current_block == NULL) { + // Anything in the buffer? + current_block = plan_get_current_block(); + if (current_block != NULL) { + trapezoid_generator_reset(); + counter_x = -(current_block->step_event_count >> 1); + counter_y = counter_x; + counter_z = counter_x; + counter_e = counter_x; + step_events_completed = 0; + #ifdef ADVANCE + e_steps = 0; + #endif + } + else { +// DISABLE_STEPPER_DRIVER_INTERRUPT(); + } + } + + if (current_block != NULL) { + // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt + out_bits = current_block->direction_bits; + + #ifdef ADVANCE + // Calculate E early. + counter_e += current_block->steps_e; + if (counter_e > 0) { + counter_e -= current_block->step_event_count; + if ((out_bits & (1<> 16) - old_advance); + CRITICAL_SECTION_END; + old_advance = advance >> 16; + #endif //ADVANCE + + // Set direction en check limit switches + if ((out_bits & (1< -1 + if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } + #endif + } + else { // +direction + WRITE(X_DIR_PIN,!INVERT_X_DIR); + #ifdef DEBUG_STEPS + count_direction[X_AXIS]=1; + #endif + #if X_MAX_PIN > -1 + if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ + step_events_completed = current_block->step_event_count; + } + #endif + } + + if ((out_bits & (1< -1 + if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } + #endif + } + else { // +direction + WRITE(Y_DIR_PIN,!INVERT_Y_DIR); + #ifdef DEBUG_STEPS + count_direction[Y_AXIS]=1; + #endif + #if Y_MAX_PIN > -1 + if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ + step_events_completed = current_block->step_event_count; + } + #endif + } + + if ((out_bits & (1< -1 + if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { + step_events_completed = current_block->step_event_count; + } + #endif + } + else { // +direction + WRITE(Z_DIR_PIN,!INVERT_Z_DIR); + #ifdef DEBUG_STEPS + count_direction[Z_AXIS]=1; + #endif + #if Z_MAX_PIN > -1 + if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ + step_events_completed = current_block->step_event_count; + } + #endif + } + + #ifndef ADVANCE + if ((out_bits & (1<steps_x; + if (counter_x > 0) { + WRITE(X_STEP_PIN, HIGH); + counter_x -= current_block->step_event_count; + WRITE(X_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[X_AXIS]+=count_direction[X_AXIS]; + #endif + } + + counter_y += current_block->steps_y; + if (counter_y > 0) { + WRITE(Y_STEP_PIN, HIGH); + counter_y -= current_block->step_event_count; + WRITE(Y_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Y_AXIS]+=count_direction[Y_AXIS]; + #endif + } + + counter_z += current_block->steps_z; + if (counter_z > 0) { + WRITE(Z_STEP_PIN, HIGH); + counter_z -= current_block->step_event_count; + WRITE(Z_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Z_AXIS]+=count_direction[Z_AXIS]; + #endif + } + + #ifndef ADVANCE + counter_e += current_block->steps_e; + if (counter_e > 0) { + WRITE(E_STEP_PIN, HIGH); + counter_e -= current_block->step_event_count; + WRITE(E_STEP_PIN, LOW); + } + #endif //!ADVANCE + step_events_completed += 1; + if(step_events_completed >= current_block->step_event_count) break; + } + // Calculare new timer value + unsigned short timer; + unsigned short step_rate; + if (step_events_completed <= current_block->accelerate_until) { + MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); + acc_step_rate += current_block->initial_rate; + + // upper limit + if(acc_step_rate > current_block->nominal_rate) + acc_step_rate = current_block->nominal_rate; + + // step_rate to timer interval + timer = calc_timer(acc_step_rate); + #ifdef ADVANCE + advance += advance_rate; + #endif + acceleration_time += timer; + OCR1A = timer; + } + else if (step_events_completed > current_block->decelerate_after) { + MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); + + if(step_rate > acc_step_rate) { // Check step_rate stays positive + step_rate = current_block->final_rate; + } + else { + step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. + } + + // lower limit + if(step_rate < current_block->final_rate) + step_rate = current_block->final_rate; + + // step_rate to timer interval + timer = calc_timer(step_rate); + #ifdef ADVANCE + advance -= advance_rate; + if(advance < final_advance) + advance = final_advance; + #endif //ADVANCE + deceleration_time += timer; + OCR1A = timer; + } + else { + timer = calc_timer(current_block->nominal_rate); + OCR1A = timer; + } + + // If current block is finished, reset pointer + if (step_events_completed >= current_block->step_event_count) { + current_block = NULL; + plan_discard_current_block(); + } + } + cli(); // disable interrupts + busy=false; +} + +#ifdef ADVANCE + unsigned char old_OCR0A; + // Timer interrupt for E. e_steps is set in the main routine; + // Timer 0 is shared with millies + ISR(TIMER0_COMPA_vect) + { + // Critical section needed because Timer 1 interrupt has higher priority. + // The pin set functions are placed on trategic position to comply with the stepper driver timing. + WRITE(E_STEP_PIN, LOW); + // Set E direction (Depends on E direction + advance) + if (e_steps < 0) { + WRITE(E_DIR_PIN,INVERT_E_DIR); + e_steps++; + WRITE(E_STEP_PIN, HIGH); + } + if (e_steps > 0) { + WRITE(E_DIR_PIN,!INVERT_E_DIR); + e_steps--; + WRITE(E_STEP_PIN, HIGH); + } + old_OCR0A += 25; // 10kHz interrupt + OCR0A = old_OCR0A; + } +#endif // ADVANCE + +void st_init() +{ + //Initialize Dir Pins + #if X_DIR_PIN > -1 + SET_OUTPUT(X_DIR_PIN); + #endif + #if Y_DIR_PIN > -1 + SET_OUTPUT(Y_DIR_PIN); + #endif + #if Z_DIR_PIN > -1 + SET_OUTPUT(Z_DIR_PIN); + #endif + #if E_DIR_PIN > -1 + SET_OUTPUT(E_DIR_PIN); + #endif + + //Initialize Enable Pins - steppers default to disabled. + + #if (X_ENABLE_PIN > -1) + SET_OUTPUT(X_ENABLE_PIN); + if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); + #endif + #if (Y_ENABLE_PIN > -1) + SET_OUTPUT(Y_ENABLE_PIN); + if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); + #endif + #if (Z_ENABLE_PIN > -1) + SET_OUTPUT(Z_ENABLE_PIN); + if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); + #endif + #if (E_ENABLE_PIN > -1) + SET_OUTPUT(E_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); + #endif + + //endstops and pullups + #ifdef ENDSTOPPULLUPS + #if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + WRITE(X_MIN_PIN,HIGH); + #endif + #if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + WRITE(X_MAX_PIN,HIGH); + #endif + #if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + WRITE(Y_MIN_PIN,HIGH); + #endif + #if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + WRITE(Y_MAX_PIN,HIGH); + #endif + #if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + WRITE(Z_MIN_PIN,HIGH); + #endif + #if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + WRITE(Z_MAX_PIN,HIGH); + #endif + #else //ENDSTOPPULLUPS + #if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + #endif + #if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + #endif + #if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + #endif + #if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + #endif + #if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + #endif + #if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + #endif + #endif //ENDSTOPPULLUPS + + + //Initialize Step Pins + #if (X_STEP_PIN > -1) + SET_OUTPUT(X_STEP_PIN); + #endif + #if (Y_STEP_PIN > -1) + SET_OUTPUT(Y_STEP_PIN); + #endif + #if (Z_STEP_PIN > -1) + SET_OUTPUT(Z_STEP_PIN); + #endif + #if (E_STEP_PIN > -1) + SET_OUTPUT(E_STEP_PIN); + #endif + + // waveform generation = 0100 = CTC + TCCR1B &= ~(1<. - */ - -/* - 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 - - This firmware is optimized for gen6 electronics. - */ - -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "streaming.h" -#include "temperature.h" -#include "watchdog.h" - -//=========================================================================== -//=============================public variables============================ -//=========================================================================== -int target_raw[3] = {0, 0, 0}; -int current_raw[3] = {0, 0, 0}; - -#ifdef PIDTEMP - - // probably used external - float HeaterPower; - float pid_setpoint = 0.0; - - - float Kp=DEFAULT_Kp; - float Ki=DEFAULT_Ki; - float Kd=DEFAULT_Kd; - float Kc=DEFAULT_Kc; -#endif //PIDTEMP - - -//=========================================================================== -//=============================private variables============================ -//=========================================================================== -static bool temp_meas_ready = false; - -static unsigned long previous_millis_heater, previous_millis_bed_heater; - -#ifdef PIDTEMP - //static cannot be external: - static float temp_iState = 0; - static float temp_dState = 0; - static float pTerm; - static float iTerm; - static float dTerm; - //int output; - static float pid_error; - static float temp_iState_min; - static float temp_iState_max; - static float pid_input; - static float pid_output; - static bool pid_reset; - -#endif //PIDTEMP - -#ifdef WATCHPERIOD - static int watch_raw[3] = {-1000,-1000,-1000}; - static unsigned long watchmillis = 0; -#endif //WATCHPERIOD - -#ifdef HEATER_0_MINTEMP - static int minttemp_0 = temp2analog(HEATER_0_MINTEMP); -#endif //MINTEMP -#ifdef HEATER_0_MAXTEMP - static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); -#endif //MAXTEMP - -#ifdef HEATER_1_MINTEMP - static int minttemp_1 = temp2analog(HEATER_1_MINTEMP); -#endif //MINTEMP -#ifdef HEATER_1_MAXTEMP - static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); -#endif //MAXTEMP - -#ifdef BED_MINTEMP - static int bed_minttemp = temp2analog(BED_MINTEMP); -#endif //BED_MINTEMP -#ifdef BED_MAXTEMP - static int bed_maxttemp = temp2analog(BED_MAXTEMP); -#endif //BED_MAXTEMP - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== - -void manage_heater() -{ - #ifdef USE_WATCHDOG - wd_reset(); - #endif - - float pid_input; - float pid_output; - if(temp_meas_ready != true) //better readability - return; - - CRITICAL_SECTION_START; - temp_meas_ready = false; - CRITICAL_SECTION_END; - - #ifdef PIDTEMP - pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); - - #ifndef PID_OPENLOOP - pid_error = pid_setpoint - pid_input; - if(pid_error > 10){ - pid_output = PID_MAX; - pid_reset = true; - } - else if(pid_error < -10) { - pid_output = 0; - pid_reset = true; - } - else { - if(pid_reset == true) { - temp_iState = 0.0; - pid_reset = false; - } - pTerm = Kp * pid_error; - temp_iState += pid_error; - temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); - iTerm = Ki * temp_iState; - //K1 defined in Configuration.h in the PID settings - #define K2 (1.0-K1) - dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); - temp_dState = pid_input; - #ifdef PID_ADD_EXTRUSION_RATE - pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high - #endif - pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); - } - #endif //PID_OPENLOOP - #ifdef PID_DEBUG - SERIAL_ECHOLN(" PIDDEBUG Input "<= target_raw[0]) - { - WRITE(HEATER_0_PIN,LOW); - } - else - { - WRITE(HEATER_0_PIN,HIGH); - } - #endif - - if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) - return; - previous_millis_bed_heater = millis(); - - #if TEMP_1_PIN > -1 - if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) - { - WRITE(HEATER_1_PIN,LOW); - } - else - { - WRITE(HEATER_1_PIN,HIGH); - } - #endif -} - -// Takes hot end temperature value as input and returns corresponding raw value. -// For a thermistor, it uses the RepRap thermistor temp table. -// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. -// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -int temp2analog(int celsius) { - #ifdef HEATER_0_USES_THERMISTOR - int raw = 0; - byte i; - - for (i=1; i raw) - { - celsius = heater_0_temptable[i-1][1] + - (raw - heater_0_temptable[i-1][0]) * - (float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) / - (float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1]; - - return celsius; - #elif defined HEATER_0_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -// Derived from RepRap FiveD extruder::getTemperature() -// For bed temperature measurement. -float analog2tempBed(int raw) { - #ifdef BED_USES_THERMISTOR - int celsius = 0; - byte i; - - raw = (1023 * OVERSAMPLENR) - raw; - - for (i=1; i raw) - { - celsius = bedtemptable[i-1][1] + - (raw - bedtemptable[i-1][0]) * - (bedtemptable[i][1] - bedtemptable[i-1][1]) / - (bedtemptable[i][0] - bedtemptable[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; - - return celsius; - - #elif defined BED_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -void tp_init() -{ - #if (HEATER_0_PIN > -1) - SET_OUTPUT(HEATER_0_PIN); - #endif - #if (HEATER_1_PIN > -1) - SET_OUTPUT(HEATER_1_PIN); - #endif - #if (HEATER_2_PIN > -1) - SET_OUTPUT(HEATER_2_PIN); - #endif - - #ifdef PIDTEMP - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; - #endif //PIDTEMP - - // Set analog inputs - ADCSRA = 1< -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif -} - -// Timer 0 is shared with millies -ISR(TIMER0_COMPB_vect) -{ - //these variables are only accesible from the ISR, but static, so they don't loose their value - static unsigned char temp_count = 0; - static unsigned long raw_temp_0_value = 0; - static unsigned long raw_temp_1_value = 0; - static unsigned long raw_temp_2_value = 0; - static unsigned char temp_state = 0; - - switch(temp_state) { - case 0: // Prepare TEMP_0 - #if (TEMP_0_PIN > -1) - #if TEMP_0_PIN < 8 - DIDR0 = 1 << TEMP_0_PIN; - #else - DIDR2 = 1<<(TEMP_0_PIN - 8); - ADCSRB = 1< -1) - raw_temp_0_value += ADC; - #endif - temp_state = 2; - break; - case 2: // Prepare TEMP_1 - #if (TEMP_1_PIN > -1) - #if TEMP_1_PIN < 7 - DIDR0 = 1< -1) - raw_temp_1_value += ADC; - #endif - temp_state = 4; - break; - case 4: // Prepare TEMP_2 - #if (TEMP_2_PIN > -1) - #if TEMP_2_PIN < 7 - DIDR0 = 1 << TEMP_2_PIN; - #else - DIDR2 = 1<<(TEMP_2_PIN - 8); - ADCSRB = 1< -1) - raw_temp_2_value += ADC; - #endif - temp_state = 0; - temp_count++; - break; - default: - SERIAL_ERRORLN("Temp measurement error!"); - break; - } - - if(temp_count >= 16) // 6 ms * 16 = 96ms. - { - #ifdef HEATER_0_USES_AD595 - current_raw[0] = raw_temp_0_value; - #else - current_raw[0] = 16383 - raw_temp_0_value; - #endif - - #ifdef HEATER_1_USES_AD595 - current_raw[2] = raw_temp_2_value; - #else - current_raw[2] = 16383 - raw_temp_2_value; - #endif - - #ifdef BED_USES_AD595 - current_raw[1] = raw_temp_1_value; - #else - current_raw[1] = 16383 - raw_temp_1_value; - #endif - - temp_meas_ready = true; - temp_count = 0; - raw_temp_0_value = 0; - raw_temp_1_value = 0; - raw_temp_2_value = 0; - #ifdef HEATER_0_MAXTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 0 switched off. MAXTEMP triggered !!"); - kill(); - } - #endif - #endif - #ifdef HEATER_1_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - if(current_raw[2] >= maxttemp_1) { - analogWrite(HEATER_2_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 1 switched off. MAXTEMP triggered !!"); - kill() - } - #endif - #endif //MAXTEMP - - #ifdef HEATER_0_MINTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 0 switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif - - #ifdef HEATER_1_MINTEMP - #if (HEATER_2_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - analogWrite(HEATER_2_PIN, 0); - SERIAL_ERRORLN("Temperature extruder 1 switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif //MAXTEMP - - #ifdef BED_MINTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] <= bed_minttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - SERIAL_ERRORLN("Temperatur heated bed switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif - - #ifdef BED_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] >= bed_maxttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - SERIAL_ERRORLN("Temperature heated bed switched off. MAXTEMP triggered !!"); - kill(); - } - #endif - #endif - } -} - +/* + temperature.c - temperature control + Part of Marlin + + 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 + + This firmware is optimized for gen6 electronics. + */ +#include + +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "temperature.h" +#include "watchdog.h" + +//=========================================================================== +//=============================public variables============================ +//=========================================================================== +int target_raw[3] = {0, 0, 0}; +int current_raw[3] = {0, 0, 0}; + +#ifdef PIDTEMP + + // probably used external + float HeaterPower; + float pid_setpoint = 0.0; + + + float Kp=DEFAULT_Kp; + float Ki=DEFAULT_Ki; + float Kd=DEFAULT_Kd; + #ifdef PID_ADD_EXTRUSION_RATE + float Kc=DEFAULT_Kc; + #endif +#endif //PIDTEMP + + +//=========================================================================== +//=============================private variables============================ +//=========================================================================== +static bool temp_meas_ready = false; + +static unsigned long previous_millis_heater, previous_millis_bed_heater; + +#ifdef PIDTEMP + //static cannot be external: + static float temp_iState = 0; + static float temp_dState = 0; + static float pTerm; + static float iTerm; + static float dTerm; + //int output; + static float pid_error; + static float temp_iState_min; + static float temp_iState_max; + static float pid_input; + static float pid_output; + static bool pid_reset; + +#endif //PIDTEMP + +#ifdef WATCHPERIOD + static int watch_raw[3] = {-1000,-1000,-1000}; + static unsigned long watchmillis = 0; +#endif //WATCHPERIOD + +#ifdef HEATER_0_MINTEMP + static int minttemp_0 = temp2analog(HEATER_0_MINTEMP); +#endif //MINTEMP +#ifdef HEATER_0_MAXTEMP + static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); +#endif //MAXTEMP + +#ifdef HEATER_1_MINTEMP + static int minttemp_1 = temp2analog(HEATER_1_MINTEMP); +#endif //MINTEMP +#ifdef HEATER_1_MAXTEMP + static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); +#endif //MAXTEMP + +#ifdef BED_MINTEMP + static int bed_minttemp = temp2analog(BED_MINTEMP); +#endif //BED_MINTEMP +#ifdef BED_MAXTEMP + static int bed_maxttemp = temp2analog(BED_MAXTEMP); +#endif //BED_MAXTEMP + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + +void manage_heater() +{ + #ifdef USE_WATCHDOG + wd_reset(); + #endif + + float pid_input; + float pid_output; + if(temp_meas_ready != true) //better readability + return; + + CRITICAL_SECTION_START; + temp_meas_ready = false; + CRITICAL_SECTION_END; + + #ifdef PIDTEMP + pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + + #ifndef PID_OPENLOOP + pid_error = pid_setpoint - pid_input; + if(pid_error > 10){ + pid_output = PID_MAX; + pid_reset = true; + } + else if(pid_error < -10) { + pid_output = 0; + pid_reset = true; + } + else { + if(pid_reset == true) { + temp_iState = 0.0; + pid_reset = false; + } + pTerm = Kp * pid_error; + temp_iState += pid_error; + temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); + iTerm = Ki * temp_iState; + //K1 defined in Configuration.h in the PID settings + #define K2 (1.0-K1) + dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); + temp_dState = pid_input; +// #ifdef PID_ADD_EXTRUSION_RATE +// pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high +// #endif + pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); + } + #endif //PID_OPENLOOP + #ifdef PID_DEBUG + SERIAL_ECHOLN(" PIDDEBUG Input "<= target_raw[0]) + { + WRITE(HEATER_0_PIN,LOW); + } + else + { + WRITE(HEATER_0_PIN,HIGH); + } + #endif + + if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) + return; + previous_millis_bed_heater = millis(); + + #if TEMP_1_PIN > -1 + if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) + { + WRITE(HEATER_1_PIN,LOW); + } + else + { + WRITE(HEATER_1_PIN,HIGH); + } + #endif +} + +// Takes hot end temperature value as input and returns corresponding raw value. +// For a thermistor, it uses the RepRap thermistor temp table. +// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. +// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. +int temp2analog(int celsius) { + #ifdef HEATER_0_USES_THERMISTOR + int raw = 0; + byte i; + + for (i=1; i raw) + { + celsius = (short)pgm_read_word(&heater_0_temptable[i-1][1]) + + (raw - (short)pgm_read_word(&heater_0_temptable[i-1][0])) * + (float)((short)pgm_read_word(&heater_0_temptable[i][1]) - (short)pgm_read_word(&heater_0_temptable[i-1][1])) / + (float)((short)pgm_read_word(&heater_0_temptable[i][0]) - (short)pgm_read_word(&heater_0_temptable[i-1][0])); + break; + } + } + + // Overflow: Set to last value in the table + if (i == NUMTEMPS_HEATER_0) celsius = (short)pgm_read_word(&(heater_0_temptable[i-1][1])); + + return celsius; + #elif defined HEATER_0_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +// Derived from RepRap FiveD extruder::getTemperature() +// For bed temperature measurement. +float analog2tempBed(int raw) { + #ifdef BED_USES_THERMISTOR + int celsius = 0; + byte i; + + raw = (1023 * OVERSAMPLENR) - raw; + + for (i=1; i raw) + { + celsius = pgm_read_word(&(bedtemptable[i-1][1])) + + (raw - pgm_read_word(&(bedtemptable[i-1][0]))) * + (pgm_read_word(&(bedtemptable[i][1])) - pgm_read_word(&(bedtemptable[i-1][1]))) / + (pgm_read_word(&(bedtemptable[i][0])) - pgm_read_word(&(bedtemptable[i-1][0]))); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == BNUMTEMPS) celsius = pgm_read_word(&(bedtemptable[i-1][1])); + + return celsius; + + #elif defined BED_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +void tp_init() +{ + #if (HEATER_0_PIN > -1) + SET_OUTPUT(HEATER_0_PIN); + #endif + #if (HEATER_1_PIN > -1) + SET_OUTPUT(HEATER_1_PIN); + #endif + #if (HEATER_2_PIN > -1) + SET_OUTPUT(HEATER_2_PIN); + #endif + + #ifdef PIDTEMP + temp_iState_min = 0.0; + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; + #endif //PIDTEMP + + // Set analog inputs + ADCSRA = 1< -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif +} + +// Timer 0 is shared with millies +ISR(TIMER0_COMPB_vect) +{ + //these variables are only accesible from the ISR, but static, so they don't loose their value + static unsigned char temp_count = 0; + static unsigned long raw_temp_0_value = 0; + static unsigned long raw_temp_1_value = 0; + static unsigned long raw_temp_2_value = 0; + static unsigned char temp_state = 0; + + switch(temp_state) { + case 0: // Prepare TEMP_0 + #if (TEMP_0_PIN > -1) + #if TEMP_0_PIN < 8 + DIDR0 = 1 << TEMP_0_PIN; + #else + DIDR2 = 1<<(TEMP_0_PIN - 8); + ADCSRB = 1< -1) + raw_temp_0_value += ADC; + #endif + temp_state = 2; + break; + case 2: // Prepare TEMP_1 + #if (TEMP_1_PIN > -1) + #if TEMP_1_PIN < 7 + DIDR0 = 1< -1) + raw_temp_1_value += ADC; + #endif + temp_state = 4; + break; + case 4: // Prepare TEMP_2 + #if (TEMP_2_PIN > -1) + #if TEMP_2_PIN < 7 + DIDR0 = 1 << TEMP_2_PIN; + #else + DIDR2 = 1<<(TEMP_2_PIN - 8); + ADCSRB = 1< -1) + raw_temp_2_value += ADC; + #endif + temp_state = 0; + temp_count++; + break; + default: + SERIAL_ERRORLN("Temp measurement error!"); + break; + } + + if(temp_count >= 16) // 6 ms * 16 = 96ms. + { + #ifdef HEATER_0_USES_AD595 + current_raw[0] = raw_temp_0_value; + #else + current_raw[0] = 16383 - raw_temp_0_value; + #endif + + #ifdef HEATER_1_USES_AD595 + current_raw[2] = raw_temp_2_value; + #else + current_raw[2] = 16383 - raw_temp_2_value; + #endif + + #ifdef BED_USES_AD595 + current_raw[1] = raw_temp_1_value; + #else + current_raw[1] = 16383 - raw_temp_1_value; + #endif + + temp_meas_ready = true; + temp_count = 0; + raw_temp_0_value = 0; + raw_temp_1_value = 0; + raw_temp_2_value = 0; + #ifdef HEATER_0_MAXTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 0 switched off. MAXTEMP triggered !!"); + kill(); + } + #endif + #endif + #ifdef HEATER_1_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + if(current_raw[2] >= maxttemp_1) { + analogWrite(HEATER_2_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 1 switched off. MAXTEMP triggered !!"); + kill() + } + #endif + #endif //MAXTEMP + + #ifdef HEATER_0_MINTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 0 switched off. MINTEMP triggered !!"); + kill(); + } + #endif + #endif + + #ifdef HEATER_1_MINTEMP + #if (HEATER_2_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + analogWrite(HEATER_2_PIN, 0); + SERIAL_ERRORLN("Temperature extruder 1 switched off. MINTEMP triggered !!"); + kill(); + } + #endif + #endif //MAXTEMP + + #ifdef BED_MINTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] <= bed_minttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + SERIAL_ERRORLN("Temperatur heated bed switched off. MINTEMP triggered !!"); + kill(); + } + #endif + #endif + + #ifdef BED_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] >= bed_maxttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + SERIAL_ERRORLN("Temperature heated bed switched off. MAXTEMP triggered !!"); + kill(); + } + #endif + #endif + } +} + diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index fbd2ef1446..22d9f02487 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -1,12 +1,14 @@ #ifndef THERMISTORTABLES_H_ #define THERMISTORTABLES_H_ +#include + #define OVERSAMPLENR 16 #if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORBED == 1) //100k bed thermistor #define NUMTEMPS_1 61 -const short temptable_1[NUMTEMPS_1][2] = { +const short temptable_1[NUMTEMPS_1][2] PROGMEM = { { 23*OVERSAMPLENR , 300 }, { 25*OVERSAMPLENR , 295 }, { 27*OVERSAMPLENR , 290 }, @@ -72,7 +74,7 @@ const short temptable_1[NUMTEMPS_1][2] = { #endif #if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORBED == 2) //200k bed thermistor #define NUMTEMPS_2 21 -const short temptable_2[NUMTEMPS_2][2] = { +const short temptable_2[NUMTEMPS_2][2] PROGMEM = { {1*OVERSAMPLENR, 848}, {54*OVERSAMPLENR, 275}, {107*OVERSAMPLENR, 228}, @@ -99,7 +101,7 @@ const short temptable_2[NUMTEMPS_2][2] = { #endif #if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORBED == 3) //mendel-parts #define NUMTEMPS_3 28 -const short temptable_3[NUMTEMPS_3][2] = { +const short temptable_3[NUMTEMPS_3][2] PROGMEM = { {1*OVERSAMPLENR,864}, {21*OVERSAMPLENR,300}, {25*OVERSAMPLENR,290}, @@ -134,7 +136,7 @@ const short temptable_3[NUMTEMPS_3][2] = { #if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORBED == 4) //10k thermistor #define NUMTEMPS_4 20 -short temptable_4[NUMTEMPS_4][2] = { +const short temptable_4[NUMTEMPS_4][2] PROGMEM = { {1*OVERSAMPLENR, 430}, {54*OVERSAMPLENR, 137}, {107*OVERSAMPLENR, 107}, @@ -161,7 +163,7 @@ short temptable_4[NUMTEMPS_4][2] = { #if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) #define NUMTEMPS_5 61 -const short temptable_5[NUMTEMPS_5][2] = { +const short temptable_5[NUMTEMPS_5][2] PROGMEM = { {1*OVERSAMPLENR, 713}, {18*OVERSAMPLENR, 316}, {35*OVERSAMPLENR, 266}, @@ -228,7 +230,7 @@ const short temptable_5[NUMTEMPS_5][2] = { #if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor #define NUMTEMPS_6 36 -const short temptable_6[NUMTEMPS_6][2] = { +const short temptable_6[NUMTEMPS_6][2] PROGMEM = { {28*OVERSAMPLENR, 250}, {31*OVERSAMPLENR, 245}, {35*OVERSAMPLENR, 240}, @@ -270,7 +272,7 @@ const short temptable_6[NUMTEMPS_6][2] = { #if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 #define NUMTEMPS_7 54 -const short temptable_7[NUMTEMPS_7][2] = { +const short temptable_7[NUMTEMPS_7][2] PROGMEM = { {46*OVERSAMPLENR, 270}, {50*OVERSAMPLENR, 265}, {54*OVERSAMPLENR, 260}, From c57906b627bf7245578522ab50e9d35e9c6bc96b Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 13 Nov 2011 21:43:26 +0100 Subject: [PATCH 039/228] fixed bug with adjusting ki in realtime. --- Marlin/Configuration.h | 8 ++++---- Marlin/Marlin.pde | 40 ++++++++++++++++++++++------------------ Marlin/temperature.cpp | 7 +++++++ Marlin/temperature.h | 1 + 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 8661ae438e..5b15dd0a47 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -95,11 +95,11 @@ // PID_SWING_AT_CRITIAL is the time for a full period of the oscillations at the critical Gain // usually further manual tunine is necessary. - #define PID_CRITIAL_GAIN 3000 - #define PID_SWING_AT_CRITIAL 45 //seconds + #define PID_CRITIAL_GAIN 50 + #define PID_SWING_AT_CRITIAL 47 //seconds - #define PID_PI //no differentail term - //#define PID_PID //normal PID + //#define PID_PI //no differentail term + #define PID_PID //normal PID #ifdef PID_PID //PID according to Ziegler-Nichols method diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index e15f025514..84f07b3e68 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -898,24 +898,28 @@ inline void process_commands() #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 - SERIAL_PROTOCOL("ok 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(""); - + { + + + 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("ok 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 case 400: // finish all moves diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 8ea8ee008f..ac299399dc 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -111,6 +111,13 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; //=============================functions ============================ //=========================================================================== +void updatePID() +{ +#ifdef PIDTEMP + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; +#endif +} + void manage_heater() { #ifdef USE_WATCHDOG diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 9c4b59a241..0f0de985f4 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -87,6 +87,7 @@ inline bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMP void disable_heater(); void setWatch(); +void updatePID(); #endif From 1d0452f10ce6d067836e483e3512c4099b4ca524 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 14 Nov 2011 18:24:02 +0100 Subject: [PATCH 040/228] 250000 baud --- Marlin/Configuration.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 6c8b3a4ecf..6a48635f50 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -4,8 +4,8 @@ // This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 +#define BAUDRATE 250000 +//#define BAUDRATE 115200 //#define BAUDRATE 230400 From 2643ae93d69b4171acb18bf9994b12076b4f2496 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 14 Nov 2011 18:27:47 +0100 Subject: [PATCH 041/228] Added modified Sanguino files --- Marlin/Sanguino/boards.txt | 16 + .../bootloaders/atmega644p/ATmegaBOOT.c | 713 ++++++++++++++++++ .../atmega644p/ATmegaBOOT_324P.hex | 121 +++ .../bootloaders/atmega644p/ATmegaBOOT_644.hex | 120 +++ .../atmega644p/ATmegaBOOT_644P.hex | 121 +++ .../Sanguino/bootloaders/atmega644p/Makefile | 56 ++ .../bootloaders/atmega644p/README.txt | 3 + .../cores/Copy of arduino/HardwareSerial.cpp | 303 ++++++++ .../cores/Copy of arduino/HardwareSerial.h | 76 ++ .../Sanguino/cores/Copy of arduino/Print.cpp | 220 ++++++ Marlin/Sanguino/cores/Copy of arduino/Print.h | 66 ++ .../Sanguino/cores/Copy of arduino/Tone.cpp | 515 +++++++++++++ .../cores/Copy of arduino/WCharacter.h | 168 +++++ .../cores/Copy of arduino/WConstants.h | 1 + .../cores/Copy of arduino/WInterrupts.c | 87 +++ .../Sanguino/cores/Copy of arduino/WMath.cpp | 60 ++ .../Sanguino/cores/Copy of arduino/WProgram.h | 63 ++ .../cores/Copy of arduino/WString.cpp | 443 +++++++++++ .../Sanguino/cores/Copy of arduino/WString.h | 112 +++ .../Sanguino/cores/Copy of arduino/binary.h | 515 +++++++++++++ .../Sanguino/cores/Copy of arduino/main.cpp | 14 + .../cores/Copy of arduino/pins_arduino.c | 200 +++++ .../cores/Copy of arduino/pins_arduino.h | 65 ++ .../Sanguino/cores/Copy of arduino/wiring.c | 289 +++++++ .../Sanguino/cores/Copy of arduino/wiring.h | 135 ++++ .../cores/Copy of arduino/wiring_analog.c | 116 +++ .../cores/Copy of arduino/wiring_digital.c | 95 +++ .../cores/Copy of arduino/wiring_private.h | 60 ++ .../cores/Copy of arduino/wiring_pulse.c | 69 ++ .../cores/Copy of arduino/wiring_shift.c | 55 ++ .../Sanguino/cores/arduino/Copy of wiring.h | 135 ++++ .../Sanguino/cores/arduino/HardwareSerial.cpp | 303 ++++++++ .../Sanguino/cores/arduino/HardwareSerial.h | 76 ++ Marlin/Sanguino/cores/arduino/Print.cpp | 220 ++++++ Marlin/Sanguino/cores/arduino/Print.h | 66 ++ Marlin/Sanguino/cores/arduino/Stream.h | 35 + Marlin/Sanguino/cores/arduino/Tone.cpp | 601 +++++++++++++++ Marlin/Sanguino/cores/arduino/WCharacter.h | 168 +++++ Marlin/Sanguino/cores/arduino/WConstants.h | 1 + Marlin/Sanguino/cores/arduino/WInterrupts.c | 249 ++++++ Marlin/Sanguino/cores/arduino/WMath.cpp | 60 ++ Marlin/Sanguino/cores/arduino/WProgram.h | 63 ++ Marlin/Sanguino/cores/arduino/WString.cpp | 443 +++++++++++ Marlin/Sanguino/cores/arduino/WString.h | 112 +++ Marlin/Sanguino/cores/arduino/binary.h | 515 +++++++++++++ Marlin/Sanguino/cores/arduino/main.cpp | 14 + Marlin/Sanguino/cores/arduino/pins_arduino.c | 200 +++++ Marlin/Sanguino/cores/arduino/pins_arduino.h | 65 ++ Marlin/Sanguino/cores/arduino/wiring.c | 289 +++++++ Marlin/Sanguino/cores/arduino/wiring.h | 135 ++++ Marlin/Sanguino/cores/arduino/wiring_analog.c | 259 +++++++ .../Sanguino/cores/arduino/wiring_digital.c | 166 ++++ .../Sanguino/cores/arduino/wiring_private.h | 68 ++ Marlin/Sanguino/cores/arduino/wiring_pulse.c | 69 ++ Marlin/Sanguino/cores/arduino/wiring_shift.c | 55 ++ Marlin/Sanguino/programmers.txt | 20 + 56 files changed, 9264 insertions(+) create mode 100644 Marlin/Sanguino/boards.txt create mode 100644 Marlin/Sanguino/bootloaders/atmega644p/ATmegaBOOT.c create mode 100644 Marlin/Sanguino/bootloaders/atmega644p/ATmegaBOOT_324P.hex create mode 100644 Marlin/Sanguino/bootloaders/atmega644p/ATmegaBOOT_644.hex create mode 100644 Marlin/Sanguino/bootloaders/atmega644p/ATmegaBOOT_644P.hex create mode 100644 Marlin/Sanguino/bootloaders/atmega644p/Makefile create mode 100644 Marlin/Sanguino/bootloaders/atmega644p/README.txt create mode 100644 Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp create mode 100644 Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/Print.cpp create mode 100644 Marlin/Sanguino/cores/Copy of arduino/Print.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/Tone.cpp create mode 100644 Marlin/Sanguino/cores/Copy of arduino/WCharacter.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/WConstants.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c create mode 100644 Marlin/Sanguino/cores/Copy of arduino/WMath.cpp create mode 100644 Marlin/Sanguino/cores/Copy of arduino/WProgram.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/WString.cpp create mode 100644 Marlin/Sanguino/cores/Copy of arduino/WString.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/binary.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/main.cpp create mode 100644 Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c create mode 100644 Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring.c create mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c create mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c create mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_private.h create mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c create mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c create mode 100644 Marlin/Sanguino/cores/arduino/Copy of wiring.h create mode 100644 Marlin/Sanguino/cores/arduino/HardwareSerial.cpp create mode 100644 Marlin/Sanguino/cores/arduino/HardwareSerial.h create mode 100644 Marlin/Sanguino/cores/arduino/Print.cpp create mode 100644 Marlin/Sanguino/cores/arduino/Print.h create mode 100644 Marlin/Sanguino/cores/arduino/Stream.h create mode 100644 Marlin/Sanguino/cores/arduino/Tone.cpp create mode 100644 Marlin/Sanguino/cores/arduino/WCharacter.h create mode 100644 Marlin/Sanguino/cores/arduino/WConstants.h create mode 100644 Marlin/Sanguino/cores/arduino/WInterrupts.c create mode 100644 Marlin/Sanguino/cores/arduino/WMath.cpp create mode 100644 Marlin/Sanguino/cores/arduino/WProgram.h create mode 100644 Marlin/Sanguino/cores/arduino/WString.cpp create mode 100644 Marlin/Sanguino/cores/arduino/WString.h create mode 100644 Marlin/Sanguino/cores/arduino/binary.h create mode 100644 Marlin/Sanguino/cores/arduino/main.cpp create mode 100644 Marlin/Sanguino/cores/arduino/pins_arduino.c create mode 100644 Marlin/Sanguino/cores/arduino/pins_arduino.h create mode 100644 Marlin/Sanguino/cores/arduino/wiring.c create mode 100644 Marlin/Sanguino/cores/arduino/wiring.h create mode 100644 Marlin/Sanguino/cores/arduino/wiring_analog.c create mode 100644 Marlin/Sanguino/cores/arduino/wiring_digital.c create mode 100644 Marlin/Sanguino/cores/arduino/wiring_private.h create mode 100644 Marlin/Sanguino/cores/arduino/wiring_pulse.c create mode 100644 Marlin/Sanguino/cores/arduino/wiring_shift.c create mode 100644 Marlin/Sanguino/programmers.txt diff --git a/Marlin/Sanguino/boards.txt b/Marlin/Sanguino/boards.txt new file mode 100644 index 0000000000..4f71b8ae5a --- /dev/null +++ b/Marlin/Sanguino/boards.txt @@ -0,0 +1,16 @@ +############################################################## + +sanguino.name=Sanguino +sanguino.upload.protocol=stk500 +sanguino.upload.maximum_size=63488 +sanguino.upload.speed=38400 +sanguino.bootloader.low_fuses=0xFF +sanguino.bootloader.high_fuses=0xDC +sanguino.bootloader.extended_fuses=0xFD +sanguino.bootloader.path=atmega644p +sanguino.bootloader.file=ATmegaBOOT_644P.hex +sanguino.bootloader.unlock_bits=0x3F +sanguino.bootloader.lock_bits=0x0F +sanguino.build.mcu=atmega644p +sanguino.build.f_cpu=16000000L +sanguino.build.core=arduino diff --git a/Marlin/Sanguino/bootloaders/atmega644p/ATmegaBOOT.c b/Marlin/Sanguino/bootloaders/atmega644p/ATmegaBOOT.c new file mode 100644 index 0000000000..1711014459 --- /dev/null +++ b/Marlin/Sanguino/bootloaders/atmega644p/ATmegaBOOT.c @@ -0,0 +1,713 @@ +/**********************************************************/ +/* Serial Bootloader for Atmel megaAVR Controllers */ +/* */ +/* tested with ATmega644 and ATmega644P */ +/* should work with other mega's, see code for details */ +/* */ +/* ATmegaBOOT.c */ +/* */ +/* 20090131: Added 324P support from Alex Leone */ +/* Marius Kintel */ +/* 20080915: applied ADABoot mods for Sanguino 644P */ +/* Brian Riley */ +/* 20080711: hacked for Sanguino by Zach Smith */ +/* and Justin Day */ +/* 20070626: hacked for Arduino Diecimila (which auto- */ +/* resets when a USB connection is made to it) */ +/* by D. Mellis */ +/* 20060802: hacked for Arduino by D. Cuartielles */ +/* based on a previous hack by D. Mellis */ +/* and D. Cuartielles */ +/* */ +/* Monitor and debug functions were added to the original */ +/* code by Dr. Erik Lins, chip45.com. (See below) */ +/* */ +/* Thanks to Karl Pitrich for fixing a bootloader pin */ +/* problem and more informative LED blinking! */ +/* */ +/* For the latest version see: */ +/* http://www.chip45.com/ */ +/* */ +/* ------------------------------------------------------ */ +/* */ +/* based on stk500boot.c */ +/* Copyright (c) 2003, Jason P. Kyle */ +/* All rights reserved. */ +/* see avr1.org for original file and information */ +/* */ +/* 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 2 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, write */ +/* to the Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* */ +/* Licence can be viewed at */ +/* http://www.fsf.org/licenses/gpl.txt */ +/* */ +/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */ +/* m8515,m8535. ATmega161 has a very small boot block so */ +/* isn't supported. */ +/* */ +/* Tested with m168 */ +/**********************************************************/ + +/* $Id$ */ + + +/* some includes */ +#include +#include +#include +#include +#include +#include + +#ifdef ADABOOT + #define NUM_LED_FLASHES 3 + #define ADABOOT_VER 1 +#endif + + +/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */ +#define MAX_ERROR_COUNT 5 + +/* set the UART baud rate */ +/* 20080711: hack by Zach Hoeken */ +#define BAUD_RATE 38400 + +/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */ +/* never allow AVR Studio to do an update !!!! */ +#define HW_VER 0x02 +#define SW_MAJOR 0x01 +#define SW_MINOR 0x10 + +/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */ +/* if monitor functions are included, LED goes on after monitor was entered */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB0 + +/* define various device id's */ +/* manufacturer byte is always the same */ +#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :( +#if defined(__AVR_ATmega644P__) +#define SIG2 0x96 +#define SIG3 0x0A +#elif defined(__AVR_ATmega644__) +#define SIG2 0x96 +#define SIG3 0x09 +#elif defined(__AVR_ATmega324P__) +#define SIG2 0x95 +#define SIG3 0x08 +#endif +#define PAGE_SIZE 0x080U //128 words +#define PAGE_SIZE_BYTES 0x100U //256 bytes + +/* function prototypes */ +void putch(char); +char getch(void); +void getNch(uint8_t); +void byte_response(uint8_t); +void nothing_response(void); +char gethex(void); +void puthex(char); +void flash_led(uint8_t); + +/* some variables */ +union address_union +{ + uint16_t word; + uint8_t byte[2]; +} address; + +union length_union +{ + uint16_t word; + uint8_t byte[2]; +} length; + +struct flags_struct +{ + unsigned eeprom : 1; + unsigned rampz : 1; +} flags; + +uint8_t buff[256]; + +uint8_t error_count = 0; +uint8_t sreg; + +void (*app_start)(void) = 0x0000; + +/* main program starts here */ +int main(void) +{ + uint8_t ch,ch2; + uint16_t w; + uint16_t i; + + asm volatile("nop\n\t"); + +#ifdef ADABOOT // BBR/LF 10/8/2007 & 9/13/2008 + ch = MCUSR; + MCUSR = 0; + + WDTCSR |= _BV(WDCE) | _BV(WDE); + WDTCSR = 0; + + // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot. + if (! (ch & _BV(EXTRF))) // if its a not an external reset... + app_start(); // skip bootloader +#endif + + + //initialize our serial port. + UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); + UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; + UCSR0B = (1< 0x85) + getch(); + nothing_response(); + } + + + /* AVR ISP/STK500 board requests */ + else if(ch=='A') + { + ch2 = getch(); + if(ch2 == 0x80) + byte_response(HW_VER); // Hardware version + else if(ch2==0x81) + byte_response(SW_MAJOR); // Software major version + else if(ch2==0x82) + byte_response(SW_MINOR); // Software minor version + else if(ch2==0x98) + byte_response(0x03); // Unknown but seems to be required by avr studio 3.56 + else + byte_response(0x00); // Covers various unnecessary responses we don't care about + } + + + /* Device Parameters DON'T CARE, DEVICE IS FIXED */ + else if(ch=='B') + { + getNch(20); + nothing_response(); + } + + + /* Parallel programming stuff DON'T CARE */ + else if(ch=='E') + { + getNch(5); + nothing_response(); + } + + + /* Enter programming mode */ + else if(ch=='P') + { + nothing_response(); + } + + + /* Leave programming mode */ + else if(ch=='Q') + { + nothing_response(); +#ifdef ADABOOT + // autoreset via watchdog (sneaky!) BBR/LF 9/13/2008 + WDTCSR = _BV(WDE); + while (1); // 16 ms +#endif + } + + + /* Erase device, don't care as we will erase one page at a time anyway. */ + else if(ch=='R') + { + nothing_response(); + } + + + /* Set address, little endian. EEPROM in bytes, FLASH in words */ + /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */ + /* This might explain why little endian was used here, big endian used everywhere else. */ + else if(ch=='U') + { + address.byte[0] = getch(); + address.byte[1] = getch(); + nothing_response(); + } + + + /* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */ + else if(ch=='V') + { + getNch(4); + byte_response(0x00); + } + + + /* Write memory, length is big endian and is in bytes */ + else if(ch=='d') + { + length.byte[1] = getch(); + length.byte[0] = getch(); + + flags.eeprom = 0; + if (getch() == 'E') + flags.eeprom = 1; + + for (i=0; i byte location + address.word = address.word << 1; + + //Even up an odd number of bytes + if ((length.byte[0] & 0x01)) + length.word++; + + // HACKME: EEPE used to be EEWE + //Wait for previous EEPROM writes to complete + //while(bit_is_set(EECR,EEPE)); + while(EECR & (1< byte location + } + + // Command terminator + if (getch() == ' ') + { + putch(0x14); + for (w=0; w= 'a') + ah = ah - 'a' + 0x0a; + else if(ah >= '0') + ah -= '0'; + if(al >= 'a') + al = al - 'a' + 0x0a; + else if(al >= '0') + al -= '0'; + + return (ah << 4) + al; +} + + +void puthex(char ch) +{ + char ah,al; + + ah = (ch & 0xf0) >> 4; + if(ah >= 0x0a) + ah = ah - 0x0a + 'a'; + else + ah += '0'; + + al = (ch & 0x0f); + if(al >= 0x0a) + al = al - 0x0a + 'a'; + else + al += '0'; + + putch(ah); + putch(al); +} + + +void putch(char ch) +{ + while (!(UCSR0A & _BV(UDRE0))); + UDR0 = ch; +} + + + + +char getch(void) +{ + uint32_t count = 0; + +#ifdef ADABOOT + LED_PORT &= ~_BV(LED); // toggle LED to show activity - BBR/LF 10/3/2007 & 9/13/2008 +#endif + + while(!(UCSR0A & _BV(RXC0))) + { + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); + } + +#ifdef ADABOOT + LED_PORT |= _BV(LED); // toggle LED to show activity - BBR/LF 10/3/2007 & 9/13/2008 +#endif + + return UDR0; +} + + +void getNch(uint8_t count) +{ + uint8_t i; + for(i=0;i $@ + +%.srec: %.elf + $(OBJCOPY) -j .text -j .data -O srec $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ + +clean: + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex + \ No newline at end of file diff --git a/Marlin/Sanguino/bootloaders/atmega644p/README.txt b/Marlin/Sanguino/bootloaders/atmega644p/README.txt new file mode 100644 index 0000000000..8286007851 --- /dev/null +++ b/Marlin/Sanguino/bootloaders/atmega644p/README.txt @@ -0,0 +1,3 @@ +Note: This bootloader support ATmega644, ATmega644P and ATmega324P. +To build, set PROGRAM and MCU_TARGET in the Makefile according to your target device. + diff --git a/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp b/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp new file mode 100644 index 0000000000..4397efb7ee --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp @@ -0,0 +1,303 @@ +/* + HardwareSerial.cpp - Hardware serial library for Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 23 November 2006 by David A. Mellis + Modified 28 September 2010 by Mark Sproul +*/ + +#include +#include +#include +#include +#include "wiring.h" +#include "wiring_private.h" + +// this next line disables the entire HardwareSerial.cpp, +// this is so I can support Attiny series and any other chip without a uart +#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) + +#include "HardwareSerial.h" + +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which rx_buffer_head is the index of the +// location to which to write the next incoming character and rx_buffer_tail +// is the index of the location from which to read. +#if (RAMEND < 1000) + #define RX_BUFFER_SIZE 32 +#else + #define RX_BUFFER_SIZE 128 +#endif + +struct ring_buffer +{ + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; +}; + +#if defined(UBRRH) || defined(UBRR0H) + ring_buffer rx_buffer = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR1H) + ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR2H) + ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR3H) + ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; +#endif + +inline void store_char(unsigned char c, ring_buffer *rx_buffer) +{ + int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != rx_buffer->tail) { + rx_buffer->buffer[rx_buffer->head] = c; + rx_buffer->head = i; + } +} + +#if defined(USART_RX_vect) + SIGNAL(USART_RX_vect) + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; // atmega8535 + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } +#elif defined(SIG_USART0_RECV) && defined(UDR0) + SIGNAL(SIG_USART0_RECV) + { + unsigned char c = UDR0; + store_char(c, &rx_buffer); + } +#elif defined(SIG_UART0_RECV) && defined(UDR0) + SIGNAL(SIG_UART0_RECV) + { + unsigned char c = UDR0; + store_char(c, &rx_buffer); + } +//#elif defined(SIG_USART_RECV) +#elif defined(USART0_RX_vect) + // fixed by Mark Sproul this is on the 644/644p + //SIGNAL(SIG_USART_RECV) + SIGNAL(USART0_RX_vect) + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; // atmega8, atmega32 + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } +#elif defined(SIG_UART_RECV) + // this is for atmega8 + SIGNAL(SIG_UART_RECV) + { + #if defined(UDR0) + unsigned char c = UDR0; // atmega645 + #elif defined(UDR) + unsigned char c = UDR; // atmega8 + #endif + store_char(c, &rx_buffer); + } +#elif defined(USBCON) + #warning No interrupt handler for usart 0 + #warning Serial(0) is on USB interface +#else + #error No interrupt handler for usart 0 +#endif + +//#if defined(SIG_USART1_RECV) +#if defined(USART1_RX_vect) + //SIGNAL(SIG_USART1_RECV) + SIGNAL(USART1_RX_vect) + { + unsigned char c = UDR1; + store_char(c, &rx_buffer1); + } +#elif defined(SIG_USART1_RECV) + #error SIG_USART1_RECV +#endif + +#if defined(USART2_RX_vect) && defined(UDR2) + SIGNAL(USART2_RX_vect) + { + unsigned char c = UDR2; + store_char(c, &rx_buffer2); + } +#elif defined(SIG_USART2_RECV) + #error SIG_USART2_RECV +#endif + +#if defined(USART3_RX_vect) && defined(UDR3) + SIGNAL(USART3_RX_vect) + { + unsigned char c = UDR3; + store_char(c, &rx_buffer3); + } +#elif defined(SIG_USART3_RECV) + #error SIG_USART3_RECV +#endif + + + +// Constructors //////////////////////////////////////////////////////////////// + +HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) +{ + _rx_buffer = rx_buffer; + _ubrrh = ubrrh; + _ubrrl = ubrrl; + _ucsra = ucsra; + _ucsrb = ucsrb; + _udr = udr; + _rxen = rxen; + _txen = txen; + _rxcie = rxcie; + _udre = udre; + _u2x = u2x; +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void HardwareSerial::begin(long baud) +{ + uint16_t baud_setting; + bool use_u2x = true; + +#if F_CPU == 16000000UL + // hardcoded exception for compatibility with the bootloader shipped + // with the Duemilanove and previous boards and the firmware on the 8U2 + // on the Uno and Mega 2560. + if (baud == 57600) { + use_u2x = false; + } +#endif + + if (use_u2x) { + *_ucsra = 1 << _u2x; + baud_setting = (F_CPU / 4 / baud - 1) / 2; + } else { + *_ucsra = 0; + baud_setting = (F_CPU / 8 / baud - 1) / 2; + } + + // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) + *_ubrrh = baud_setting >> 8; + *_ubrrl = baud_setting; + + sbi(*_ucsrb, _rxen); + sbi(*_ucsrb, _txen); + sbi(*_ucsrb, _rxcie); +} + +void HardwareSerial::end() +{ + cbi(*_ucsrb, _rxen); + cbi(*_ucsrb, _txen); + cbi(*_ucsrb, _rxcie); +} + +int HardwareSerial::available(void) +{ + return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; +} + +int HardwareSerial::peek(void) +{ + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + return _rx_buffer->buffer[_rx_buffer->tail]; + } +} + +int HardwareSerial::read(void) +{ + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; + _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + return c; + } +} + +void HardwareSerial::flush() +{ + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // were full, not empty. + _rx_buffer->head = _rx_buffer->tail; +} + +void HardwareSerial::write(uint8_t c) +{ + while (!((*_ucsra) & (1 << _udre))) + ; + + *_udr = c; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +#if defined(UBRRH) && defined(UBRRL) + HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); +#elif defined(UBRR0H) && defined(UBRR0L) + HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); +#elif defined(USBCON) + #warning no serial port defined (port 0) +#else + #error no serial port defined (port 0) +#endif + +#if defined(UBRR1H) + HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); +#endif +#if defined(UBRR2H) + HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); +#endif +#if defined(UBRR3H) + HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); +#endif + +#endif // whole file + diff --git a/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h b/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h new file mode 100644 index 0000000000..3efa775f84 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h @@ -0,0 +1,76 @@ +/* + HardwareSerial.h - Hardware serial library for Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 28 September 2010 by Mark Sproul +*/ + +#ifndef HardwareSerial_h +#define HardwareSerial_h + +#include + +#include "Stream.h" + +struct ring_buffer; + +class HardwareSerial : public Stream +{ + private: + ring_buffer *_rx_buffer; + volatile uint8_t *_ubrrh; + volatile uint8_t *_ubrrl; + volatile uint8_t *_ucsra; + volatile uint8_t *_ucsrb; + volatile uint8_t *_udr; + uint8_t _rxen; + uint8_t _txen; + uint8_t _rxcie; + uint8_t _udre; + uint8_t _u2x; + public: + HardwareSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); + void begin(long); + void end(); + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual void write(uint8_t); + using Print::write; // pull in write(str) and write(buf, size) from Print +}; + +#if defined(UBRRH) || defined(UBRR0H) + extern HardwareSerial Serial; +#elif defined(USBCON) + #include "usb_api.h" +#endif +#if defined(UBRR1H) + extern HardwareSerial Serial1; +#endif +#if defined(UBRR2H) + extern HardwareSerial Serial2; +#endif +#if defined(UBRR3H) + extern HardwareSerial Serial3; +#endif + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/Print.cpp b/Marlin/Sanguino/cores/Copy of arduino/Print.cpp new file mode 100644 index 0000000000..4ee556dd82 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/Print.cpp @@ -0,0 +1,220 @@ +/* + Print.cpp - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 23 November 2006 by David A. Mellis + */ + +#include +#include +#include +#include +#include "wiring.h" + +#include "Print.h" + +// Public Methods ////////////////////////////////////////////////////////////// + +/* default implementation: may be overridden */ +void Print::write(const char *str) +{ + while (*str) + write(*str++); +} + +/* default implementation: may be overridden */ +void Print::write(const uint8_t *buffer, size_t size) +{ + while (size--) + write(*buffer++); +} + +void Print::print(const String &s) +{ + for (int i = 0; i < s.length(); i++) { + write(s[i]); + } +} + +void Print::print(const char str[]) +{ + write(str); +} + +void Print::print(char c, int base) +{ + print((long) c, base); +} + +void Print::print(unsigned char b, int base) +{ + print((unsigned long) b, base); +} + +void Print::print(int n, int base) +{ + print((long) n, base); +} + +void Print::print(unsigned int n, int base) +{ + print((unsigned long) n, base); +} + +void Print::print(long n, int base) +{ + if (base == 0) { + write(n); + } else if (base == 10) { + if (n < 0) { + print('-'); + n = -n; + } + printNumber(n, 10); + } else { + printNumber(n, base); + } +} + +void Print::print(unsigned long n, int base) +{ + if (base == 0) write(n); + else printNumber(n, base); +} + +void Print::print(double n, int digits) +{ + printFloat(n, digits); +} + +void Print::println(void) +{ + print('\r'); + print('\n'); +} + +void Print::println(const String &s) +{ + print(s); + println(); +} + +void Print::println(const char c[]) +{ + print(c); + println(); +} + +void Print::println(char c, int base) +{ + print(c, base); + println(); +} + +void Print::println(unsigned char b, int base) +{ + print(b, base); + println(); +} + +void Print::println(int n, int base) +{ + print(n, base); + println(); +} + +void Print::println(unsigned int n, int base) +{ + print(n, base); + println(); +} + +void Print::println(long n, int base) +{ + print(n, base); + println(); +} + +void Print::println(unsigned long n, int base) +{ + print(n, base); + println(); +} + +void Print::println(double n, int digits) +{ + print(n, digits); + println(); +} + +// Private Methods ///////////////////////////////////////////////////////////// + +void Print::printNumber(unsigned long n, uint8_t base) +{ + unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. + unsigned long i = 0; + + if (n == 0) { + print('0'); + return; + } + + while (n > 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) + print((char) (buf[i - 1] < 10 ? + '0' + buf[i - 1] : + 'A' + buf[i - 1] - 10)); +} + +void Print::printFloat(double number, uint8_t digits) +{ + // Handle negative numbers + if (number < 0.0) + { + print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i=0; i 0) + print("."); + + // Extract digits from the remainder one at a time + while (digits-- > 0) + { + remainder *= 10.0; + int toPrint = int(remainder); + print(toPrint); + remainder -= toPrint; + } +} diff --git a/Marlin/Sanguino/cores/Copy of arduino/Print.h b/Marlin/Sanguino/cores/Copy of arduino/Print.h new file mode 100644 index 0000000000..b092ae51d1 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/Print.h @@ -0,0 +1,66 @@ +/* + Print.h - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef Print_h +#define Print_h + +#include +#include // for size_t + +#include "WString.h" + +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 +#define BYTE 0 + +class Print +{ + private: + void printNumber(unsigned long, uint8_t); + void printFloat(double, uint8_t); + public: + virtual void write(uint8_t) = 0; + virtual void write(const char *str); + virtual void write(const uint8_t *buffer, size_t size); + + void print(const String &); + void print(const char[]); + void print(char, int = BYTE); + void print(unsigned char, int = BYTE); + void print(int, int = DEC); + void print(unsigned int, int = DEC); + void print(long, int = DEC); + void print(unsigned long, int = DEC); + void print(double, int = 2); + + void println(const String &s); + void println(const char[]); + void println(char, int = BYTE); + void println(unsigned char, int = BYTE); + void println(int, int = DEC); + void println(unsigned int, int = DEC); + void println(long, int = DEC); + void println(unsigned long, int = DEC); + void println(double, int = 2); + void println(void); +}; + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/Tone.cpp b/Marlin/Sanguino/cores/Copy of arduino/Tone.cpp new file mode 100644 index 0000000000..827fe49ef4 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/Tone.cpp @@ -0,0 +1,515 @@ +/* Tone.cpp + + A Tone Generator Library + + Written by Brett Hagman + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Version Modified By Date Comments +------- ----------- -------- -------- +0001 B Hagman 09/08/02 Initial coding +0002 B Hagman 09/08/18 Multiple pins +0003 B Hagman 09/08/18 Moved initialization from constructor to begin() +0004 B Hagman 09/09/26 Fixed problems with ATmega8 +0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers + 09/11/25 Changed pin toggle method to XOR + 09/11/25 Fixed timer0 from being excluded +0006 D Mellis 09/12/29 Replaced objects with functions + +*************************************************/ + +#include +#include +#include +#include + +#if defined(__AVR_ATmega8__) +#define TCCR2A TCCR2 +#define TCCR2B TCCR2 +#define COM2A1 COM21 +#define COM2A0 COM20 +#define OCR2A OCR2 +#define TIMSK2 TIMSK +#define OCIE2A OCIE2 +#define TIMER2_COMPA_vect TIMER2_COMP_vect +#define TIMSK1 TIMSK +#endif + +// timerx_toggle_count: +// > 0 - duration specified +// = 0 - stopped +// < 0 - infinitely (until stop() method called, or new play() called) + +#if !defined(__AVR_ATmega8__) +volatile long timer0_toggle_count; +volatile uint8_t *timer0_pin_port; +volatile uint8_t timer0_pin_mask; +#endif + +volatile long timer1_toggle_count; +volatile uint8_t *timer1_pin_port; +volatile uint8_t timer1_pin_mask; +volatile long timer2_toggle_count; +volatile uint8_t *timer2_pin_port; +volatile uint8_t timer2_pin_mask; + +#if defined(__AVR_ATmega1280__) +volatile long timer3_toggle_count; +volatile uint8_t *timer3_pin_port; +volatile uint8_t timer3_pin_mask; +volatile long timer4_toggle_count; +volatile uint8_t *timer4_pin_port; +volatile uint8_t timer4_pin_mask; +volatile long timer5_toggle_count; +volatile uint8_t *timer5_pin_port; +volatile uint8_t timer5_pin_mask; +#endif + + +#if defined(__AVR_ATmega1280__) + +#define AVAILABLE_TONE_PINS 1 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; + +#elif defined(__AVR_ATmega8__) + +#define AVAILABLE_TONE_PINS 1 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; + +#else + +#define AVAILABLE_TONE_PINS 1 + +// Leave timer 0 to last. +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; + +#endif + + + +static int8_t toneBegin(uint8_t _pin) +{ + int8_t _timer = -1; + + // if we're already using the pin, the timer should be configured. + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == _pin) { + return pgm_read_byte(tone_pin_to_timer_PGM + i); + } + } + + // search for an unused timer. + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == 255) { + tone_pins[i] = _pin; + _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); + break; + } + } + + if (_timer != -1) + { + // Set timer specific stuff + // All timers in CTC mode + // 8 bit timers will require changing prescalar values, + // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar + switch (_timer) + { +#if !defined(__AVR_ATmega8__) + case 0: + // 8 bit timer + TCCR0A = 0; + TCCR0B = 0; + bitWrite(TCCR0A, WGM01, 1); + bitWrite(TCCR0B, CS00, 1); + timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer0_pin_mask = digitalPinToBitMask(_pin); + break; +#endif + + case 1: + // 16 bit timer + TCCR1A = 0; + TCCR1B = 0; + bitWrite(TCCR1B, WGM12, 1); + bitWrite(TCCR1B, CS10, 1); + timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer1_pin_mask = digitalPinToBitMask(_pin); + break; + case 2: + // 8 bit timer + TCCR2A = 0; + TCCR2B = 0; + bitWrite(TCCR2A, WGM21, 1); + bitWrite(TCCR2B, CS20, 1); + timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer2_pin_mask = digitalPinToBitMask(_pin); + break; + +#if defined(__AVR_ATmega1280__) + case 3: + // 16 bit timer + TCCR3A = 0; + TCCR3B = 0; + bitWrite(TCCR3B, WGM32, 1); + bitWrite(TCCR3B, CS30, 1); + timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer3_pin_mask = digitalPinToBitMask(_pin); + break; + case 4: + // 16 bit timer + TCCR4A = 0; + TCCR4B = 0; + bitWrite(TCCR4B, WGM42, 1); + bitWrite(TCCR4B, CS40, 1); + timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer4_pin_mask = digitalPinToBitMask(_pin); + break; + case 5: + // 16 bit timer + TCCR5A = 0; + TCCR5B = 0; + bitWrite(TCCR5B, WGM52, 1); + bitWrite(TCCR5B, CS50, 1); + timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer5_pin_mask = digitalPinToBitMask(_pin); + break; +#endif + } + } + + return _timer; +} + + + +// frequency (in hertz) and duration (in milliseconds). + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) +{ + uint8_t prescalarbits = 0b001; + long toggle_count = 0; + uint32_t ocr = 0; + int8_t _timer; + + _timer = toneBegin(_pin); + + if (_timer >= 0) + { + // Set the pinMode as OUTPUT + pinMode(_pin, OUTPUT); + + // if we are using an 8 bit timer, scan through prescalars to find the best fit + if (_timer == 0 || _timer == 2) + { + ocr = F_CPU / frequency / 2 - 1; + prescalarbits = 0b001; // ck/1: same for both timers + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 8 - 1; + prescalarbits = 0b010; // ck/8: same for both timers + + if (_timer == 2 && ocr > 255) + { + ocr = F_CPU / frequency / 2 / 32 - 1; + prescalarbits = 0b011; + } + + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = _timer == 0 ? 0b011 : 0b100; + + if (_timer == 2 && ocr > 255) + { + ocr = F_CPU / frequency / 2 / 128 - 1; + prescalarbits = 0b101; + } + + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 256 - 1; + prescalarbits = _timer == 0 ? 0b100 : 0b110; + if (ocr > 255) + { + // can't do any better than /1024 + ocr = F_CPU / frequency / 2 / 1024 - 1; + prescalarbits = _timer == 0 ? 0b101 : 0b111; + } + } + } + } + +#if !defined(__AVR_ATmega8__) + if (_timer == 0) + TCCR0B = prescalarbits; + else +#endif + TCCR2B = prescalarbits; + } + else + { + // two choices for the 16 bit timers: ck/1 or ck/64 + ocr = F_CPU / frequency / 2 - 1; + + prescalarbits = 0b001; + if (ocr > 0xffff) + { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = 0b011; + } + + if (_timer == 1) + TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; +#if defined(__AVR_ATmega1280__) + else if (_timer == 3) + TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; + else if (_timer == 4) + TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; + else if (_timer == 5) + TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; +#endif + + } + + + // Calculate the toggle count + if (duration > 0) + { + toggle_count = 2 * frequency * duration / 1000; + } + else + { + toggle_count = -1; + } + + // Set the OCR for the given timer, + // set the toggle count, + // then turn on the interrupts + switch (_timer) + { + +#if !defined(__AVR_ATmega8__) + case 0: + OCR0A = ocr; + timer0_toggle_count = toggle_count; + bitWrite(TIMSK0, OCIE0A, 1); + break; +#endif + + case 1: + OCR1A = ocr; + timer1_toggle_count = toggle_count; + bitWrite(TIMSK1, OCIE1A, 1); + break; + case 2: + OCR2A = ocr; + timer2_toggle_count = toggle_count; + bitWrite(TIMSK2, OCIE2A, 1); + break; + +#if defined(__AVR_ATmega1280__) + case 3: + OCR3A = ocr; + timer3_toggle_count = toggle_count; + bitWrite(TIMSK3, OCIE3A, 1); + break; + case 4: + OCR4A = ocr; + timer4_toggle_count = toggle_count; + bitWrite(TIMSK4, OCIE4A, 1); + break; + case 5: + OCR5A = ocr; + timer5_toggle_count = toggle_count; + bitWrite(TIMSK5, OCIE5A, 1); + break; +#endif + + } + } +} + + +void noTone(uint8_t _pin) +{ + int8_t _timer = -1; + + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == _pin) { + _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); + tone_pins[i] = 255; + } + } + + switch (_timer) + { +#if defined(__AVR_ATmega8__) + case 1: + bitWrite(TIMSK1, OCIE1A, 0); + break; + case 2: + bitWrite(TIMSK2, OCIE2A, 0); + break; + +#else + case 0: + TIMSK0 = 0; + break; + case 1: + TIMSK1 = 0; + break; + case 2: + TIMSK2 = 0; + break; +#endif + +#if defined(__AVR_ATmega1280__) + case 3: + TIMSK3 = 0; + break; + case 4: + TIMSK4 = 0; + break; + case 5: + TIMSK5 = 0; + break; +#endif + } + + digitalWrite(_pin, 0); +} + +#if 0 +#if !defined(__AVR_ATmega8__) +ISR(TIMER0_COMPA_vect) +{ + if (timer0_toggle_count != 0) + { + // toggle the pin + *timer0_pin_port ^= timer0_pin_mask; + + if (timer0_toggle_count > 0) + timer0_toggle_count--; + } + else + { + TIMSK0 = 0; // disable the interrupt + *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop + } +} +#endif + + +ISR(TIMER1_COMPA_vect) +{ + if (timer1_toggle_count != 0) + { + // toggle the pin + *timer1_pin_port ^= timer1_pin_mask; + + if (timer1_toggle_count > 0) + timer1_toggle_count--; + } + else + { + TIMSK1 = 0; // disable the interrupt + *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop + } +} +#endif + + +ISR(TIMER2_COMPA_vect) +{ + + if (timer2_toggle_count != 0) + { + // toggle the pin + *timer2_pin_port ^= timer2_pin_mask; + + if (timer2_toggle_count > 0) + timer2_toggle_count--; + } + else + { + TIMSK2 = 0; // disable the interrupt + *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop + } +} + + + +//#if defined(__AVR_ATmega1280__) +#if 0 + +ISR(TIMER3_COMPA_vect) +{ + if (timer3_toggle_count != 0) + { + // toggle the pin + *timer3_pin_port ^= timer3_pin_mask; + + if (timer3_toggle_count > 0) + timer3_toggle_count--; + } + else + { + TIMSK3 = 0; // disable the interrupt + *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop + } +} + +ISR(TIMER4_COMPA_vect) +{ + if (timer4_toggle_count != 0) + { + // toggle the pin + *timer4_pin_port ^= timer4_pin_mask; + + if (timer4_toggle_count > 0) + timer4_toggle_count--; + } + else + { + TIMSK4 = 0; // disable the interrupt + *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop + } +} + +ISR(TIMER5_COMPA_vect) +{ + if (timer5_toggle_count != 0) + { + // toggle the pin + *timer5_pin_port ^= timer5_pin_mask; + + if (timer5_toggle_count > 0) + timer5_toggle_count--; + } + else + { + TIMSK5 = 0; // disable the interrupt + *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop + } +} + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/WCharacter.h b/Marlin/Sanguino/cores/Copy of arduino/WCharacter.h new file mode 100644 index 0000000000..79733b50a5 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/WCharacter.h @@ -0,0 +1,168 @@ +/* + WCharacter.h - Character utility functions for Wiring & Arduino + Copyright (c) 2010 Hernando Barragan. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef Character_h +#define Character_h + +#include + +// WCharacter.h prototypes +inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); +inline boolean isAlpha(int c) __attribute__((always_inline)); +inline boolean isAscii(int c) __attribute__((always_inline)); +inline boolean isWhitespace(int c) __attribute__((always_inline)); +inline boolean isControl(int c) __attribute__((always_inline)); +inline boolean isDigit(int c) __attribute__((always_inline)); +inline boolean isGraph(int c) __attribute__((always_inline)); +inline boolean isLowerCase(int c) __attribute__((always_inline)); +inline boolean isPrintable(int c) __attribute__((always_inline)); +inline boolean isPunct(int c) __attribute__((always_inline)); +inline boolean isSpace(int c) __attribute__((always_inline)); +inline boolean isUpperCase(int c) __attribute__((always_inline)); +inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); +inline int toAscii(int c) __attribute__((always_inline)); +inline int toLowerCase(int c) __attribute__((always_inline)); +inline int toUpperCase(int c)__attribute__((always_inline)); + + +// Checks for an alphanumeric character. +// It is equivalent to (isalpha(c) || isdigit(c)). +inline boolean isAlphaNumeric(int c) +{ + return ( isalnum(c) == 0 ? false : true); +} + + +// Checks for an alphabetic character. +// It is equivalent to (isupper(c) || islower(c)). +inline boolean isAlpha(int c) +{ + return ( isalpha(c) == 0 ? false : true); +} + + +// Checks whether c is a 7-bit unsigned char value +// that fits into the ASCII character set. +inline boolean isAscii(int c) +{ + return ( isascii (c) == 0 ? false : true); +} + + +// Checks for a blank character, that is, a space or a tab. +inline boolean isWhitespace(int c) +{ + return ( isblank (c) == 0 ? false : true); +} + + +// Checks for a control character. +inline boolean isControl(int c) +{ + return ( iscntrl (c) == 0 ? false : true); +} + + +// Checks for a digit (0 through 9). +inline boolean isDigit(int c) +{ + return ( isdigit (c) == 0 ? false : true); +} + + +// Checks for any printable character except space. +inline boolean isGraph(int c) +{ + return ( isgraph (c) == 0 ? false : true); +} + + +// Checks for a lower-case character. +inline boolean isLowerCase(int c) +{ + return (islower (c) == 0 ? false : true); +} + + +// Checks for any printable character including space. +inline boolean isPrintable(int c) +{ + return ( isprint (c) == 0 ? false : true); +} + + +// Checks for any printable character which is not a space +// or an alphanumeric character. +inline boolean isPunct(int c) +{ + return ( ispunct (c) == 0 ? false : true); +} + + +// Checks for white-space characters. For the avr-libc library, +// these are: space, formfeed ('\f'), newline ('\n'), carriage +// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). +inline boolean isSpace(int c) +{ + return ( isspace (c) == 0 ? false : true); +} + + +// Checks for an uppercase letter. +inline boolean isUpperCase(int c) +{ + return ( isupper (c) == 0 ? false : true); +} + + +// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 +// 8 9 a b c d e f A B C D E F. +inline boolean isHexadecimalDigit(int c) +{ + return ( isxdigit (c) == 0 ? false : true); +} + + +// Converts c to a 7-bit unsigned char value that fits into the +// ASCII character set, by clearing the high-order bits. +inline int toAscii(int c) +{ + return toascii (c); +} + + +// Warning: +// Many people will be unhappy if you use this function. +// This function will convert accented letters into random +// characters. + +// Converts the letter c to lower case, if possible. +inline int toLowerCase(int c) +{ + return tolower (c); +} + + +// Converts the letter c to upper case, if possible. +inline int toUpperCase(int c) +{ + return toupper (c); +} + +#endif \ No newline at end of file diff --git a/Marlin/Sanguino/cores/Copy of arduino/WConstants.h b/Marlin/Sanguino/cores/Copy of arduino/WConstants.h new file mode 100644 index 0000000000..3e19ac44aa --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/WConstants.h @@ -0,0 +1 @@ +#include "wiring.h" diff --git a/Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c b/Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c new file mode 100644 index 0000000000..6f3f0b130a --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c @@ -0,0 +1,87 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Wiring project - http://wiring.uniandes.edu.co + + Copyright (c) 2004-05 Hernando Barragan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 24 November 2006 by David A. Mellis +*/ + +#include +#include +#include +#include +#include + +#include "WConstants.h" +#include "wiring_private.h" + +volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; +// volatile static voidFuncPtr twiIntFunc; + +void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) +{ + if(interruptNum < EXTERNAL_NUM_INTERRUPTS) + { + intFunc[interruptNum] = userFunc; + + //clear the config for the change settings + EICRA &= ~(B00000011 << (interruptNum * 2)); + + //set our mode. + EICRA |= (mode << (interruptNum * 2)); + + // Enable the interrupt. + EIMSK |= (1 << interruptNum); + } +} + +void detachInterrupt(uint8_t interruptNum) +{ + if(interruptNum < EXTERNAL_NUM_INTERRUPTS) + { + // Disable the interrupt. + EIMSK &= ~(1 << interruptNum); + + intFunc[interruptNum] = 0; + } +} + +ISR(INT0_vect) { + if(intFunc[EXTERNAL_INT_0]) + intFunc[EXTERNAL_INT_0](); +} + +ISR(INT1_vect) { + if(intFunc[EXTERNAL_INT_1]) + intFunc[EXTERNAL_INT_1](); +} + +ISR(INT2_vect) { + if(intFunc[EXTERNAL_INT_2]) + intFunc[EXTERNAL_INT_2](); +} + +/* +SIGNAL(SIG_2WIRE_SERIAL) { + if(twiIntFunc) + twiIntFunc(); +} +*/ + diff --git a/Marlin/Sanguino/cores/Copy of arduino/WMath.cpp b/Marlin/Sanguino/cores/Copy of arduino/WMath.cpp new file mode 100644 index 0000000000..2120c4cc10 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/WMath.cpp @@ -0,0 +1,60 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Wiring project - http://wiring.org.co + Copyright (c) 2004-06 Hernando Barragan + Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +extern "C" { + #include "stdlib.h" +} + +void randomSeed(unsigned int seed) +{ + if (seed != 0) { + srandom(seed); + } +} + +long random(long howbig) +{ + if (howbig == 0) { + return 0; + } + return random() % howbig; +} + +long random(long howsmall, long howbig) +{ + if (howsmall >= howbig) { + return howsmall; + } + long diff = howbig - howsmall; + return random(diff) + howsmall; +} + +long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +unsigned int makeWord(unsigned int w) { return w; } +unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } \ No newline at end of file diff --git a/Marlin/Sanguino/cores/Copy of arduino/WProgram.h b/Marlin/Sanguino/cores/Copy of arduino/WProgram.h new file mode 100644 index 0000000000..f73e760bbe --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/WProgram.h @@ -0,0 +1,63 @@ +#ifndef WProgram_h +#define WProgram_h + +#include +#include +#include + +#include + +#include "wiring.h" + +#ifdef __cplusplus +#include "WCharacter.h" +#include "WString.h" +#include "HardwareSerial.h" + +uint16_t makeWord(uint16_t w); +uint16_t makeWord(byte h, byte l); + +#define word(...) makeWord(__VA_ARGS__) + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); +void noTone(uint8_t _pin); + +// WMath prototypes +long random(long); +long random(long, long); +void randomSeed(unsigned int); +long map(long, long, long, long, long); + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +const static uint8_t A0 = 54; +const static uint8_t A1 = 55; +const static uint8_t A2 = 56; +const static uint8_t A3 = 57; +const static uint8_t A4 = 58; +const static uint8_t A5 = 59; +const static uint8_t A6 = 60; +const static uint8_t A7 = 61; +const static uint8_t A8 = 62; +const static uint8_t A9 = 63; +const static uint8_t A10 = 64; +const static uint8_t A11 = 65; +const static uint8_t A12 = 66; +const static uint8_t A13 = 67; +const static uint8_t A14 = 68; +const static uint8_t A15 = 69; +#else +const static uint8_t A0 = 14; +const static uint8_t A1 = 15; +const static uint8_t A2 = 16; +const static uint8_t A3 = 17; +const static uint8_t A4 = 18; +const static uint8_t A5 = 19; +const static uint8_t A6 = 20; +const static uint8_t A7 = 21; +#endif + +#endif + +#endif \ No newline at end of file diff --git a/Marlin/Sanguino/cores/Copy of arduino/WString.cpp b/Marlin/Sanguino/cores/Copy of arduino/WString.cpp new file mode 100644 index 0000000000..db5a441dc2 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/WString.cpp @@ -0,0 +1,443 @@ +/* + WString.cpp - String library for Wiring & Arduino + Copyright (c) 2009-10 Hernando Barragan. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "WProgram.h" +#include "WString.h" + + +String::String( const char *value ) +{ + if ( value == NULL ) + value = ""; + getBuffer( _length = strlen( value ) ); + if ( _buffer != NULL ) + strcpy( _buffer, value ); +} + +String::String( const String &value ) +{ + getBuffer( _length = value._length ); + if ( _buffer != NULL ) + strcpy( _buffer, value._buffer ); +} + +String::String( const char value ) +{ + _length = 1; + getBuffer(1); + if ( _buffer != NULL ) { + _buffer[0] = value; + _buffer[1] = 0; + } +} + +String::String( const unsigned char value ) +{ + _length = 1; + getBuffer(1); + if ( _buffer != NULL) { + _buffer[0] = value; + _buffer[1] = 0; + } +} + +String::String( const int value, const int base ) +{ + char buf[33]; + itoa((signed long)value, buf, base); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +String::String( const unsigned int value, const int base ) +{ + char buf[33]; + ultoa((unsigned long)value, buf, base); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +String::String( const long value, const int base ) +{ + char buf[33]; + ltoa(value, buf, base); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +String::String( const unsigned long value, const int base ) +{ + char buf[33]; + ultoa(value, buf, 10); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +char String::charAt( unsigned int loc ) const +{ + return operator[]( loc ); +} + +void String::setCharAt( unsigned int loc, const char aChar ) +{ + if(_buffer == NULL) return; + if(_length > loc) { + _buffer[loc] = aChar; + } +} + +int String::compareTo( const String &s2 ) const +{ + return strcmp( _buffer, s2._buffer ); +} + +const String & String::concat( const String &s2 ) +{ + return (*this) += s2; +} + +const String & String::operator=( const String &rhs ) +{ + if ( this == &rhs ) + return *this; + + if ( rhs._length > _length ) + { + free(_buffer); + getBuffer( rhs._length ); + } + + if ( _buffer != NULL ) { + _length = rhs._length; + strcpy( _buffer, rhs._buffer ); + } + return *this; +} + +//const String & String::operator+=( const char aChar ) +//{ +// if ( _length == _capacity ) +// doubleBuffer(); +// +// _buffer[ _length++ ] = aChar; +// _buffer[ _length ] = '\0'; +// return *this; +//} + +const String & String::operator+=( const String &other ) +{ + _length += other._length; + if ( _length > _capacity ) + { + char *temp = (char *)realloc(_buffer, _length + 1); + if ( temp != NULL ) { + _buffer = temp; + _capacity = _length; + } else { + _length -= other._length; + return *this; + } + } + strcat( _buffer, other._buffer ); + return *this; +} + + +int String::operator==( const String &rhs ) const +{ + return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 ); +} + +int String::operator!=( const String &rhs ) const +{ + return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 ); +} + +int String::operator<( const String &rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) < 0; +} + +int String::operator>( const String &rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) > 0; +} + +int String::operator<=( const String &rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) <= 0; +} + +int String::operator>=( const String & rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) >= 0; +} + +char & String::operator[]( unsigned int index ) +{ + static char dummy_writable_char; + if (index >= _length || !_buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return _buffer[ index ]; +} + +char String::operator[]( unsigned int index ) const +{ + // need to check for valid index, to do later + return _buffer[ index ]; +} + +boolean String::endsWith( const String &s2 ) const +{ + if ( _length < s2._length ) + return 0; + + return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0; +} + +boolean String::equals( const String &s2 ) const +{ + return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 ); +} + +boolean String::equalsIgnoreCase( const String &s2 ) const +{ + if ( this == &s2 ) + return true; //1; + else if ( _length != s2._length ) + return false; //0; + + return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0; +} + +String String::replace( char findChar, char replaceChar ) +{ + if ( _buffer == NULL ) return *this; + String theReturn = _buffer; + char* temp = theReturn._buffer; + while( (temp = strchr( temp, findChar )) != 0 ) + *temp = replaceChar; + + return theReturn; +} + +String String::replace( const String& match, const String& replace ) +{ + if ( _buffer == NULL ) return *this; + String temp = _buffer, newString; + + int loc; + while ( (loc = temp.indexOf( match )) != -1 ) + { + newString += temp.substring( 0, loc ); + newString += replace; + temp = temp.substring( loc + match._length ); + } + newString += temp; + return newString; +} + +int String::indexOf( char temp ) const +{ + return indexOf( temp, 0 ); +} + +int String::indexOf( char ch, unsigned int fromIndex ) const +{ + if ( fromIndex >= _length ) + return -1; + + const char* temp = strchr( &_buffer[fromIndex], ch ); + if ( temp == NULL ) + return -1; + + return temp - _buffer; +} + +int String::indexOf( const String &s2 ) const +{ + return indexOf( s2, 0 ); +} + +int String::indexOf( const String &s2, unsigned int fromIndex ) const +{ + if ( fromIndex >= _length ) + return -1; + + const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer ); + + if ( theFind == NULL ) + return -1; + + return theFind - _buffer; // pointer subtraction +} + +int String::lastIndexOf( char theChar ) const +{ + return lastIndexOf( theChar, _length - 1 ); +} + +int String::lastIndexOf( char ch, unsigned int fromIndex ) const +{ + if ( fromIndex >= _length ) + return -1; + + char tempchar = _buffer[fromIndex + 1]; + _buffer[fromIndex + 1] = '\0'; + char* temp = strrchr( _buffer, ch ); + _buffer[fromIndex + 1] = tempchar; + + if ( temp == NULL ) + return -1; + + return temp - _buffer; +} + +int String::lastIndexOf( const String &s2 ) const +{ + return lastIndexOf( s2, _length - s2._length ); +} + +int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const +{ + // check for empty strings + if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length ) + return -1; + + // matching first character + char temp = s2[ 0 ]; + + for ( int i = fromIndex; i >= 0; i-- ) + { + if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) ) + return i; + } + return -1; +} + +boolean String::startsWith( const String &s2 ) const +{ + if ( _length < s2._length ) + return 0; + + return startsWith( s2, 0 ); +} + +boolean String::startsWith( const String &s2, unsigned int offset ) const +{ + if ( offset > _length - s2._length ) + return 0; + + return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0; +} + +String String::substring( unsigned int left ) const +{ + return substring( left, _length ); +} + +String String::substring( unsigned int left, unsigned int right ) const +{ + if ( left > right ) + { + int temp = right; + right = left; + left = temp; + } + + if ( right > _length ) + { + right = _length; + } + + char temp = _buffer[ right ]; // save the replaced character + _buffer[ right ] = '\0'; + String outPut = ( _buffer + left ); // pointer arithmetic + _buffer[ right ] = temp; //restore character + return outPut; +} + +String String::toLowerCase() const +{ + String temp = _buffer; + + for ( unsigned int i = 0; i < _length; i++ ) + temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] ); + return temp; +} + +String String::toUpperCase() const +{ + String temp = _buffer; + + for ( unsigned int i = 0; i < _length; i++ ) + temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] ); + return temp; +} + +String String::trim() const +{ + if ( _buffer == NULL ) return *this; + String temp = _buffer; + unsigned int i,j; + + for ( i = 0; i < _length; i++ ) + { + if ( !isspace(_buffer[i]) ) + break; + } + + for ( j = temp._length - 1; j > i; j-- ) + { + if ( !isspace(_buffer[j]) ) + break; + } + + return temp.substring( i, j + 1); +} + +void String::getBytes(unsigned char *buf, unsigned int bufsize) +{ + if (!bufsize || !buf) return; + unsigned int len = bufsize - 1; + if (len > _length) len = _length; + strncpy((char *)buf, _buffer, len); + buf[len] = 0; +} + +void String::toCharArray(char *buf, unsigned int bufsize) +{ + if (!bufsize || !buf) return; + unsigned int len = bufsize - 1; + if (len > _length) len = _length; + strncpy(buf, _buffer, len); + buf[len] = 0; +} + + +long String::toInt() { + return atol(_buffer); +} diff --git a/Marlin/Sanguino/cores/Copy of arduino/WString.h b/Marlin/Sanguino/cores/Copy of arduino/WString.h new file mode 100644 index 0000000000..cadddb9476 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/WString.h @@ -0,0 +1,112 @@ +/* + WString.h - String library for Wiring & Arduino + Copyright (c) 2009-10 Hernando Barragan. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef String_h +#define String_h + +//#include "WProgram.h" +#include +#include +#include + +class String +{ + public: + // constructors + String( const char *value = "" ); + String( const String &value ); + String( const char ); + String( const unsigned char ); + String( const int, const int base=10); + String( const unsigned int, const int base=10 ); + String( const long, const int base=10 ); + String( const unsigned long, const int base=10 ); + ~String() { free(_buffer); _length = _capacity = 0;} //added _length = _capacity = 0; + + // operators + const String & operator = ( const String &rhs ); + const String & operator +=( const String &rhs ); + //const String & operator +=( const char ); + int operator ==( const String &rhs ) const; + int operator !=( const String &rhs ) const; + int operator < ( const String &rhs ) const; + int operator > ( const String &rhs ) const; + int operator <=( const String &rhs ) const; + int operator >=( const String &rhs ) const; + char operator []( unsigned int index ) const; + char& operator []( unsigned int index ); + //operator const char *() const { return _buffer; } + + // general methods + char charAt( unsigned int index ) const; + int compareTo( const String &anotherString ) const; + unsigned char endsWith( const String &suffix ) const; + unsigned char equals( const String &anObject ) const; + unsigned char equalsIgnoreCase( const String &anotherString ) const; + int indexOf( char ch ) const; + int indexOf( char ch, unsigned int fromIndex ) const; + int indexOf( const String &str ) const; + int indexOf( const String &str, unsigned int fromIndex ) const; + int lastIndexOf( char ch ) const; + int lastIndexOf( char ch, unsigned int fromIndex ) const; + int lastIndexOf( const String &str ) const; + int lastIndexOf( const String &str, unsigned int fromIndex ) const; + const unsigned int length( ) const { return _length; } + void setCharAt(unsigned int index, const char ch); + unsigned char startsWith( const String &prefix ) const; + unsigned char startsWith( const String &prefix, unsigned int toffset ) const; + String substring( unsigned int beginIndex ) const; + String substring( unsigned int beginIndex, unsigned int endIndex ) const; + String toLowerCase( ) const; + String toUpperCase( ) const; + String trim( ) const; + void getBytes(unsigned char *buf, unsigned int bufsize); + void toCharArray(char *buf, unsigned int bufsize); + long toInt( ); + const String& concat( const String &str ); + String replace( char oldChar, char newChar ); + String replace( const String& match, const String& replace ); + friend String operator + ( String lhs, const String &rhs ); + + protected: + char *_buffer; // the actual char array + unsigned int _capacity; // the array length minus one (for the '\0') + unsigned int _length; // the String length (not counting the '\0') + + void getBuffer(unsigned int maxStrLen); + + private: + +}; + +// allocate buffer space +inline void String::getBuffer(unsigned int maxStrLen) +{ + _capacity = maxStrLen; + _buffer = (char *) malloc(_capacity + 1); + if (_buffer == NULL) _length = _capacity = 0; +} + +inline String operator+( String lhs, const String &rhs ) +{ + return lhs += rhs; +} + + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/binary.h b/Marlin/Sanguino/cores/Copy of arduino/binary.h new file mode 100644 index 0000000000..af1498033a --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/binary.h @@ -0,0 +1,515 @@ +#ifndef Binary_h +#define Binary_h + +#define B0 0 +#define B00 0 +#define B000 0 +#define B0000 0 +#define B00000 0 +#define B000000 0 +#define B0000000 0 +#define B00000000 0 +#define B1 1 +#define B01 1 +#define B001 1 +#define B0001 1 +#define B00001 1 +#define B000001 1 +#define B0000001 1 +#define B00000001 1 +#define B10 2 +#define B010 2 +#define B0010 2 +#define B00010 2 +#define B000010 2 +#define B0000010 2 +#define B00000010 2 +#define B11 3 +#define B011 3 +#define B0011 3 +#define B00011 3 +#define B000011 3 +#define B0000011 3 +#define B00000011 3 +#define B100 4 +#define B0100 4 +#define B00100 4 +#define B000100 4 +#define B0000100 4 +#define B00000100 4 +#define B101 5 +#define B0101 5 +#define B00101 5 +#define B000101 5 +#define B0000101 5 +#define B00000101 5 +#define B110 6 +#define B0110 6 +#define B00110 6 +#define B000110 6 +#define B0000110 6 +#define B00000110 6 +#define B111 7 +#define B0111 7 +#define B00111 7 +#define B000111 7 +#define B0000111 7 +#define B00000111 7 +#define B1000 8 +#define B01000 8 +#define B001000 8 +#define B0001000 8 +#define B00001000 8 +#define B1001 9 +#define B01001 9 +#define B001001 9 +#define B0001001 9 +#define B00001001 9 +#define B1010 10 +#define B01010 10 +#define B001010 10 +#define B0001010 10 +#define B00001010 10 +#define B1011 11 +#define B01011 11 +#define B001011 11 +#define B0001011 11 +#define B00001011 11 +#define B1100 12 +#define B01100 12 +#define B001100 12 +#define B0001100 12 +#define B00001100 12 +#define B1101 13 +#define B01101 13 +#define B001101 13 +#define B0001101 13 +#define B00001101 13 +#define B1110 14 +#define B01110 14 +#define B001110 14 +#define B0001110 14 +#define B00001110 14 +#define B1111 15 +#define B01111 15 +#define B001111 15 +#define B0001111 15 +#define B00001111 15 +#define B10000 16 +#define B010000 16 +#define B0010000 16 +#define B00010000 16 +#define B10001 17 +#define B010001 17 +#define B0010001 17 +#define B00010001 17 +#define B10010 18 +#define B010010 18 +#define B0010010 18 +#define B00010010 18 +#define B10011 19 +#define B010011 19 +#define B0010011 19 +#define B00010011 19 +#define B10100 20 +#define B010100 20 +#define B0010100 20 +#define B00010100 20 +#define B10101 21 +#define B010101 21 +#define B0010101 21 +#define B00010101 21 +#define B10110 22 +#define B010110 22 +#define B0010110 22 +#define B00010110 22 +#define B10111 23 +#define B010111 23 +#define B0010111 23 +#define B00010111 23 +#define B11000 24 +#define B011000 24 +#define B0011000 24 +#define B00011000 24 +#define B11001 25 +#define B011001 25 +#define B0011001 25 +#define B00011001 25 +#define B11010 26 +#define B011010 26 +#define B0011010 26 +#define B00011010 26 +#define B11011 27 +#define B011011 27 +#define B0011011 27 +#define B00011011 27 +#define B11100 28 +#define B011100 28 +#define B0011100 28 +#define B00011100 28 +#define B11101 29 +#define B011101 29 +#define B0011101 29 +#define B00011101 29 +#define B11110 30 +#define B011110 30 +#define B0011110 30 +#define B00011110 30 +#define B11111 31 +#define B011111 31 +#define B0011111 31 +#define B00011111 31 +#define B100000 32 +#define B0100000 32 +#define B00100000 32 +#define B100001 33 +#define B0100001 33 +#define B00100001 33 +#define B100010 34 +#define B0100010 34 +#define B00100010 34 +#define B100011 35 +#define B0100011 35 +#define B00100011 35 +#define B100100 36 +#define B0100100 36 +#define B00100100 36 +#define B100101 37 +#define B0100101 37 +#define B00100101 37 +#define B100110 38 +#define B0100110 38 +#define B00100110 38 +#define B100111 39 +#define B0100111 39 +#define B00100111 39 +#define B101000 40 +#define B0101000 40 +#define B00101000 40 +#define B101001 41 +#define B0101001 41 +#define B00101001 41 +#define B101010 42 +#define B0101010 42 +#define B00101010 42 +#define B101011 43 +#define B0101011 43 +#define B00101011 43 +#define B101100 44 +#define B0101100 44 +#define B00101100 44 +#define B101101 45 +#define B0101101 45 +#define B00101101 45 +#define B101110 46 +#define B0101110 46 +#define B00101110 46 +#define B101111 47 +#define B0101111 47 +#define B00101111 47 +#define B110000 48 +#define B0110000 48 +#define B00110000 48 +#define B110001 49 +#define B0110001 49 +#define B00110001 49 +#define B110010 50 +#define B0110010 50 +#define B00110010 50 +#define B110011 51 +#define B0110011 51 +#define B00110011 51 +#define B110100 52 +#define B0110100 52 +#define B00110100 52 +#define B110101 53 +#define B0110101 53 +#define B00110101 53 +#define B110110 54 +#define B0110110 54 +#define B00110110 54 +#define B110111 55 +#define B0110111 55 +#define B00110111 55 +#define B111000 56 +#define B0111000 56 +#define B00111000 56 +#define B111001 57 +#define B0111001 57 +#define B00111001 57 +#define B111010 58 +#define B0111010 58 +#define B00111010 58 +#define B111011 59 +#define B0111011 59 +#define B00111011 59 +#define B111100 60 +#define B0111100 60 +#define B00111100 60 +#define B111101 61 +#define B0111101 61 +#define B00111101 61 +#define B111110 62 +#define B0111110 62 +#define B00111110 62 +#define B111111 63 +#define B0111111 63 +#define B00111111 63 +#define B1000000 64 +#define B01000000 64 +#define B1000001 65 +#define B01000001 65 +#define B1000010 66 +#define B01000010 66 +#define B1000011 67 +#define B01000011 67 +#define B1000100 68 +#define B01000100 68 +#define B1000101 69 +#define B01000101 69 +#define B1000110 70 +#define B01000110 70 +#define B1000111 71 +#define B01000111 71 +#define B1001000 72 +#define B01001000 72 +#define B1001001 73 +#define B01001001 73 +#define B1001010 74 +#define B01001010 74 +#define B1001011 75 +#define B01001011 75 +#define B1001100 76 +#define B01001100 76 +#define B1001101 77 +#define B01001101 77 +#define B1001110 78 +#define B01001110 78 +#define B1001111 79 +#define B01001111 79 +#define B1010000 80 +#define B01010000 80 +#define B1010001 81 +#define B01010001 81 +#define B1010010 82 +#define B01010010 82 +#define B1010011 83 +#define B01010011 83 +#define B1010100 84 +#define B01010100 84 +#define B1010101 85 +#define B01010101 85 +#define B1010110 86 +#define B01010110 86 +#define B1010111 87 +#define B01010111 87 +#define B1011000 88 +#define B01011000 88 +#define B1011001 89 +#define B01011001 89 +#define B1011010 90 +#define B01011010 90 +#define B1011011 91 +#define B01011011 91 +#define B1011100 92 +#define B01011100 92 +#define B1011101 93 +#define B01011101 93 +#define B1011110 94 +#define B01011110 94 +#define B1011111 95 +#define B01011111 95 +#define B1100000 96 +#define B01100000 96 +#define B1100001 97 +#define B01100001 97 +#define B1100010 98 +#define B01100010 98 +#define B1100011 99 +#define B01100011 99 +#define B1100100 100 +#define B01100100 100 +#define B1100101 101 +#define B01100101 101 +#define B1100110 102 +#define B01100110 102 +#define B1100111 103 +#define B01100111 103 +#define B1101000 104 +#define B01101000 104 +#define B1101001 105 +#define B01101001 105 +#define B1101010 106 +#define B01101010 106 +#define B1101011 107 +#define B01101011 107 +#define B1101100 108 +#define B01101100 108 +#define B1101101 109 +#define B01101101 109 +#define B1101110 110 +#define B01101110 110 +#define B1101111 111 +#define B01101111 111 +#define B1110000 112 +#define B01110000 112 +#define B1110001 113 +#define B01110001 113 +#define B1110010 114 +#define B01110010 114 +#define B1110011 115 +#define B01110011 115 +#define B1110100 116 +#define B01110100 116 +#define B1110101 117 +#define B01110101 117 +#define B1110110 118 +#define B01110110 118 +#define B1110111 119 +#define B01110111 119 +#define B1111000 120 +#define B01111000 120 +#define B1111001 121 +#define B01111001 121 +#define B1111010 122 +#define B01111010 122 +#define B1111011 123 +#define B01111011 123 +#define B1111100 124 +#define B01111100 124 +#define B1111101 125 +#define B01111101 125 +#define B1111110 126 +#define B01111110 126 +#define B1111111 127 +#define B01111111 127 +#define B10000000 128 +#define B10000001 129 +#define B10000010 130 +#define B10000011 131 +#define B10000100 132 +#define B10000101 133 +#define B10000110 134 +#define B10000111 135 +#define B10001000 136 +#define B10001001 137 +#define B10001010 138 +#define B10001011 139 +#define B10001100 140 +#define B10001101 141 +#define B10001110 142 +#define B10001111 143 +#define B10010000 144 +#define B10010001 145 +#define B10010010 146 +#define B10010011 147 +#define B10010100 148 +#define B10010101 149 +#define B10010110 150 +#define B10010111 151 +#define B10011000 152 +#define B10011001 153 +#define B10011010 154 +#define B10011011 155 +#define B10011100 156 +#define B10011101 157 +#define B10011110 158 +#define B10011111 159 +#define B10100000 160 +#define B10100001 161 +#define B10100010 162 +#define B10100011 163 +#define B10100100 164 +#define B10100101 165 +#define B10100110 166 +#define B10100111 167 +#define B10101000 168 +#define B10101001 169 +#define B10101010 170 +#define B10101011 171 +#define B10101100 172 +#define B10101101 173 +#define B10101110 174 +#define B10101111 175 +#define B10110000 176 +#define B10110001 177 +#define B10110010 178 +#define B10110011 179 +#define B10110100 180 +#define B10110101 181 +#define B10110110 182 +#define B10110111 183 +#define B10111000 184 +#define B10111001 185 +#define B10111010 186 +#define B10111011 187 +#define B10111100 188 +#define B10111101 189 +#define B10111110 190 +#define B10111111 191 +#define B11000000 192 +#define B11000001 193 +#define B11000010 194 +#define B11000011 195 +#define B11000100 196 +#define B11000101 197 +#define B11000110 198 +#define B11000111 199 +#define B11001000 200 +#define B11001001 201 +#define B11001010 202 +#define B11001011 203 +#define B11001100 204 +#define B11001101 205 +#define B11001110 206 +#define B11001111 207 +#define B11010000 208 +#define B11010001 209 +#define B11010010 210 +#define B11010011 211 +#define B11010100 212 +#define B11010101 213 +#define B11010110 214 +#define B11010111 215 +#define B11011000 216 +#define B11011001 217 +#define B11011010 218 +#define B11011011 219 +#define B11011100 220 +#define B11011101 221 +#define B11011110 222 +#define B11011111 223 +#define B11100000 224 +#define B11100001 225 +#define B11100010 226 +#define B11100011 227 +#define B11100100 228 +#define B11100101 229 +#define B11100110 230 +#define B11100111 231 +#define B11101000 232 +#define B11101001 233 +#define B11101010 234 +#define B11101011 235 +#define B11101100 236 +#define B11101101 237 +#define B11101110 238 +#define B11101111 239 +#define B11110000 240 +#define B11110001 241 +#define B11110010 242 +#define B11110011 243 +#define B11110100 244 +#define B11110101 245 +#define B11110110 246 +#define B11110111 247 +#define B11111000 248 +#define B11111001 249 +#define B11111010 250 +#define B11111011 251 +#define B11111100 252 +#define B11111101 253 +#define B11111110 254 +#define B11111111 255 + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/main.cpp b/Marlin/Sanguino/cores/Copy of arduino/main.cpp new file mode 100644 index 0000000000..cc6e81d906 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/main.cpp @@ -0,0 +1,14 @@ +#include + +int main(void) +{ + init(); + + setup(); + + for (;;) + loop(); + + return 0; +} + diff --git a/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c b/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c new file mode 100644 index 0000000000..ccb88fe989 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c @@ -0,0 +1,200 @@ +/* + pins_arduino.c - pin definitions for the Arduino board + Part of Arduino / Wiring Lite + + Copyright (c) 2005 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: pins_arduino.c 254 2007-04-20 23:17:38Z mellis $ +*/ + +#include +#include "wiring_private.h" +#include "pins_arduino.h" + +// On the Sanguino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ATMEL ATMEGA644P / SANGUINO +// +// +---\/---+ +// INT0 (D 0) PB0 1| |40 PA0 (AI 0 / D31) +// INT1 (D 1) PB1 2| |39 PA1 (AI 1 / D30) +// INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +// PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +// PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +// MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +// MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +// SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +// RST 9| |32 AREF +// VCC 10| |31 GND +// GND 11| |30 AVCC +// XTAL2 12| |29 PC7 (D 23) +// XTAL1 13| |28 PC6 (D 22) +// RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +// TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +// RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +// TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +// PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +// PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +// PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +// +--------+ +// + +#define PA 1 +#define PB 2 +#define PC 3 +#define PD 4 + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint8_t PROGMEM port_to_mode_PGM[] = +{ + NOT_A_PORT, + &DDRA, + &DDRB, + &DDRC, + &DDRD, +}; + +const uint8_t PROGMEM port_to_output_PGM[] = +{ + NOT_A_PORT, + &PORTA, + &PORTB, + &PORTC, + &PORTD, +}; + +const uint8_t PROGMEM port_to_input_PGM[] = +{ + NOT_A_PORT, + &PINA, + &PINB, + &PINC, + &PIND, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = +{ + PB, /* 0 */ + PB, + PB, + PB, + PB, + PB, + PB, + PB, + PD, /* 8 */ + PD, + PD, + PD, + PD, + PD, + PD, + PD, + PC, /* 16 */ + PC, + PC, + PC, + PC, + PC, + PC, + PC, + PA, /* 24 */ + PA, + PA, + PA, + PA, + PA, + PA, + PA /* 31 */ +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = +{ + _BV(0), /* 0, port B */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(0), /* 8, port D */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(0), /* 16, port C */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(7), /* 24, port A */ + _BV(6), + _BV(5), + _BV(4), + _BV(3), + _BV(2), + _BV(1), + _BV(0) +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = +{ + NOT_ON_TIMER, /* 0 - PB0 */ + NOT_ON_TIMER, /* 1 - PB1 */ + NOT_ON_TIMER, /* 2 - PB2 */ + TIMER0A, /* 3 - PB3 */ + TIMER0B, /* 4 - PB4 */ + NOT_ON_TIMER, /* 5 - PB5 */ + NOT_ON_TIMER, /* 6 - PB6 */ + NOT_ON_TIMER, /* 7 - PB7 */ + NOT_ON_TIMER, /* 8 - PD0 */ + NOT_ON_TIMER, /* 9 - PD1 */ + NOT_ON_TIMER, /* 10 - PD2 */ + NOT_ON_TIMER, /* 11 - PD3 */ + TIMER1B, /* 12 - PD4 */ + TIMER1A, /* 13 - PD5 */ + TIMER2B, /* 14 - PD6 */ + TIMER2A, /* 15 - PD7 */ + NOT_ON_TIMER, /* 16 - PC0 */ + NOT_ON_TIMER, /* 17 - PC1 */ + NOT_ON_TIMER, /* 18 - PC2 */ + NOT_ON_TIMER, /* 19 - PC3 */ + NOT_ON_TIMER, /* 20 - PC4 */ + NOT_ON_TIMER, /* 21 - PC5 */ + NOT_ON_TIMER, /* 22 - PC6 */ + NOT_ON_TIMER, /* 23 - PC7 */ + NOT_ON_TIMER, /* 24 - PA0 */ + NOT_ON_TIMER, /* 25 - PA1 */ + NOT_ON_TIMER, /* 26 - PA2 */ + NOT_ON_TIMER, /* 27 - PA3 */ + NOT_ON_TIMER, /* 28 - PA4 */ + NOT_ON_TIMER, /* 29 - PA5 */ + NOT_ON_TIMER, /* 30 - PA6 */ + NOT_ON_TIMER /* 31 - PA7 */ +}; diff --git a/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h b/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h new file mode 100644 index 0000000000..e0b7add867 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h @@ -0,0 +1,65 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define NOT_A_PIN 0 +#define NOT_A_PORT 0 + +#define NOT_ON_TIMER 0 +#define TIMER0A 1 +#define TIMER0B 2 +#define TIMER1A 3 +#define TIMER1B 4 +#define TIMER2 5 +#define TIMER2A 6 +#define TIMER2B 7 + +extern const uint8_t PROGMEM port_to_mode_PGM[]; +extern const uint8_t PROGMEM port_to_input_PGM[]; +extern const uint8_t PROGMEM port_to_output_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. +// +// These perform slightly better as macros compared to inline functions +// +#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) +#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) +#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) +#define analogInPinToBit(P) (P) +#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_output_PGM + (P))) ) +#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_input_PGM + (P))) ) +#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_mode_PGM + (P))) ) + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring.c b/Marlin/Sanguino/cores/Copy of arduino/wiring.c new file mode 100644 index 0000000000..b90d07e592 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/wiring.c @@ -0,0 +1,289 @@ +/* + wiring.c - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +#include "wiring_private.h" + +// the prescaler is set so that timer0 ticks every 64 clock cycles, and the +// the overflow handler is called every 256 ticks. +#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) + +// the whole number of milliseconds per timer0 overflow +#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) + +// the fractional number of milliseconds per timer0 overflow. we shift right +// by three to fit these numbers into a byte. (for the clock speeds we care +// about - 8 and 16 MHz - this doesn't lose precision.) +#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) +#define FRACT_MAX (1000 >> 3) + +volatile unsigned long timer0_overflow_count = 0; +volatile unsigned long timer0_millis = 0; +static unsigned char timer0_fract = 0; + +SIGNAL(TIMER0_OVF_vect) +{ + // copy these to local variables so they can be stored in registers + // (volatile variables must be read from memory on every access) + unsigned long m = timer0_millis; + unsigned char f = timer0_fract; + + m += MILLIS_INC; + f += FRACT_INC; + if (f >= FRACT_MAX) { + f -= FRACT_MAX; + m += 1; + } + + timer0_fract = f; + timer0_millis = m; + timer0_overflow_count++; +} + +unsigned long millis() +{ + unsigned long m; + uint8_t oldSREG = SREG; + + // disable interrupts while we read timer0_millis or we might get an + // inconsistent value (e.g. in the middle of a write to timer0_millis) + cli(); + m = timer0_millis; + SREG = oldSREG; + + return m; +} + +unsigned long micros() { + unsigned long m; + uint8_t oldSREG = SREG, t; + + cli(); + m = timer0_overflow_count; +#if defined(TCNT0) + t = TCNT0; +#elif defined(TCNT0L) + t = TCNT0L; +#else + #error TIMER 0 not defined +#endif + + +#ifdef TIFR0 + if ((TIFR0 & _BV(TOV0)) && (t < 255)) + m++; +#else + if ((TIFR & _BV(TOV0)) && (t < 255)) + m++; +#endif + + SREG = oldSREG; + + return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); +} + +void delay(unsigned long ms) +{ + uint16_t start = (uint16_t)micros(); + + while (ms > 0) { + if (((uint16_t)micros() - start) >= 1000) { + ms--; + start += 1000; + } + } +} + +/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ +void delayMicroseconds(unsigned int us) +{ + // calling avrlib's delay_us() function with low values (e.g. 1 or + // 2 microseconds) gives delays longer than desired. + //delay_us(us); + +#if F_CPU >= 16000000L + // for the 16 MHz clock on most Arduino boards + + // for a one-microsecond delay, simply return. the overhead + // of the function call yields a delay of approximately 1 1/8 us. + if (--us == 0) + return; + + // the following loop takes a quarter of a microsecond (4 cycles) + // per iteration, so execute it four times for each microsecond of + // delay requested. + us <<= 2; + + // account for the time taken in the preceeding commands. + us -= 2; +#else + // for the 8 MHz internal clock on the ATmega168 + + // for a one- or two-microsecond delay, simply return. the overhead of + // the function calls takes more than two microseconds. can't just + // subtract two, since us is unsigned; we'd overflow. + if (--us == 0) + return; + if (--us == 0) + return; + + // the following loop takes half of a microsecond (4 cycles) + // per iteration, so execute it twice for each microsecond of + // delay requested. + us <<= 1; + + // partially compensate for the time taken by the preceeding commands. + // we can't subtract any more than this or we'd overflow w/ small delays. + us--; +#endif + + // busy wait + __asm__ __volatile__ ( + "1: sbiw %0,1" "\n\t" // 2 cycles + "brne 1b" : "=w" (us) : "0" (us) // 2 cycles + ); +} + +void init() +{ + // this needs to be called before setup() or some functions won't + // work there + sei(); + + // on the ATmega168, timer 0 is also used for fast hardware pwm + // (using phase-correct PWM would mean that timer 0 overflowed half as often + // resulting in different millis() behavior on the ATmega8 and ATmega168) +#if defined(TCCR0A) && defined(WGM01) + sbi(TCCR0A, WGM01); + sbi(TCCR0A, WGM00); +#endif + + // set timer 0 prescale factor to 64 +#if defined(__AVR_ATmega128__) + // CPU specific: different values for the ATmega128 + sbi(TCCR0, CS02); +#elif defined(TCCR0) && defined(CS01) && defined(CS00) + // this combination is for the standard atmega8 + sbi(TCCR0, CS01); + sbi(TCCR0, CS00); +#elif defined(TCCR0B) && defined(CS01) && defined(CS00) + // this combination is for the standard 168/328/1280/2560 + sbi(TCCR0B, CS01); + sbi(TCCR0B, CS00); +#elif defined(TCCR0A) && defined(CS01) && defined(CS00) + // this combination is for the __AVR_ATmega645__ series + sbi(TCCR0A, CS01); + sbi(TCCR0A, CS00); +#else + #error Timer 0 prescale factor 64 not set correctly +#endif + + // enable timer 0 overflow interrupt +#if defined(TIMSK) && defined(TOIE0) + sbi(TIMSK, TOIE0); +#elif defined(TIMSK0) && defined(TOIE0) + sbi(TIMSK0, TOIE0); +#else + #error Timer 0 overflow interrupt not set correctly +#endif + + // timers 1 and 2 are used for phase-correct hardware pwm + // this is better for motors as it ensures an even waveform + // note, however, that fast pwm mode can achieve a frequency of up + // 8 MHz (with a 16 MHz clock) at 50% duty cycle + + TCCR1B = 0; + + // set timer 1 prescale factor to 64 +#if defined(TCCR1B) && defined(CS11) && defined(CS10) + sbi(TCCR1B, CS11); + sbi(TCCR1B, CS10); +#elif defined(TCCR1) && defined(CS11) && defined(CS10) + sbi(TCCR1, CS11); + sbi(TCCR1, CS10); +#endif + // put timer 1 in 8-bit phase correct pwm mode +#if defined(TCCR1A) && defined(WGM10) + sbi(TCCR1A, WGM10); +#elif defined(TCCR1) + #warning this needs to be finished +#endif + + // set timer 2 prescale factor to 64 +#if defined(TCCR2) && defined(CS22) + sbi(TCCR2, CS22); +#elif defined(TCCR2B) && defined(CS22) + sbi(TCCR2B, CS22); +#else + #warning Timer 2 not finished (may not be present on this CPU) +#endif + + // configure timer 2 for phase correct pwm (8-bit) +#if defined(TCCR2) && defined(WGM20) + sbi(TCCR2, WGM20); +#elif defined(TCCR2A) && defined(WGM20) + sbi(TCCR2A, WGM20); +#else + #warning Timer 2 not finished (may not be present on this CPU) +#endif + +#if defined(TCCR3B) && defined(CS31) && defined(WGM30) + sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64 + sbi(TCCR3B, CS30); + sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode +#endif + +#if defined(TCCR4B) && defined(CS41) && defined(WGM40) + sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64 + sbi(TCCR4B, CS40); + sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode +#endif + +#if defined(TCCR5B) && defined(CS51) && defined(WGM50) + sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64 + sbi(TCCR5B, CS50); + sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode +#endif + +#if defined(ADCSRA) + // set a2d prescale factor to 128 + // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. + // XXX: this will not work properly for other clock speeds, and + // this code should use F_CPU to determine the prescale factor. + sbi(ADCSRA, ADPS2); + sbi(ADCSRA, ADPS1); + sbi(ADCSRA, ADPS0); + + // enable a2d conversions + sbi(ADCSRA, ADEN); +#endif + + // the bootloader connects pins 0 and 1 to the USART; disconnect them + // here so they can be used as normal digital i/o; they will be + // reconnected in Serial.begin() +#if defined(UCSRB) + UCSRB = 0; +#elif defined(UCSR0B) + UCSR0B = 0; +#endif +} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring.h b/Marlin/Sanguino/cores/Copy of arduino/wiring.h new file mode 100644 index 0000000000..e29959b865 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/wiring.h @@ -0,0 +1,135 @@ +/* + wiring.h - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +#ifndef Wiring_h +#define Wiring_h + +#include +#include +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 + +#define true 0x1 +#define false 0x0 + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define INTERNAL1V1 2 +#define INTERNAL2V56 3 +#else +#define INTERNAL 3 +#endif +#define DEFAULT 1 +#define EXTERNAL 0 + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() sei() +#define noInterrupts() cli() + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) +#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogReference(uint8_t mode); +void analogWrite(uint8_t, int); + +unsigned long millis(void); +unsigned long micros(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int us); +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +void loop(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c new file mode 100644 index 0000000000..b98bb1a196 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c @@ -0,0 +1,116 @@ +/* + wiring_analog.c - analog input and output + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +uint8_t analog_reference = DEFAULT; + +void analogReference(uint8_t mode) +{ + // can't actually set the register here because the default setting + // will connect AVCC and the AREF pin, which would cause a short if + // there's something connected to AREF. + analog_reference = mode; +} + +int analogRead(uint8_t pin) +{ + uint8_t low, high, ch = analogInPinToBit(pin); + + // set the analog reference (high two bits of ADMUX) and select the + // channel (low 4 bits). this also sets ADLAR (left-adjust result) + // to 0 (the default). + // the final AND is to clear the pos/neg reference bits + ADMUX = ((analog_reference << 6) | (pin & 0x0f)) & B11000111; + + // without a delay, we seem to read from the wrong channel + //delay(1); + + // start the conversion + sbi(ADCSRA, ADSC); + + // ADSC is cleared when the conversion finishes + while (bit_is_set(ADCSRA, ADSC)); + + // we have to read ADCL first; doing so locks both ADCL + // and ADCH until ADCH is read. reading ADCL second would + // cause the results of each conversion to be discarded, + // as ADCL and ADCH would be locked when it completed. + low = ADCL; + high = ADCH; + + // combine the two bytes + return (high << 8) | low; +} + +// Right now, PWM output only works on the pins with +// hardware support. These are defined in the appropriate +// pins_*.c file. For the rest of the pins, we default +// to digital output. +void analogWrite(uint8_t pin, int val) +{ + // We need to make sure the PWM output is enabled for those pins + // that support it, as we turn it off when digitally reading or + // writing with them. Also, make sure the pin is in output mode + // for consistenty with Wiring, which doesn't require a pinMode + // call for the analog output pins. + pinMode(pin, OUTPUT); + + if (digitalPinToTimer(pin) == TIMER1A) { + // connect pwm to pin on timer 1, channel A + sbi(TCCR1A, COM1A1); + // set pwm duty + OCR1A = val; + } else if (digitalPinToTimer(pin) == TIMER1B) { + // connect pwm to pin on timer 1, channel B + sbi(TCCR1A, COM1B1); + // set pwm duty + OCR1B = val; + } else if (digitalPinToTimer(pin) == TIMER0A) { + // connect pwm to pin on timer 0, channel A + sbi(TCCR0A, COM0A1); + // set pwm duty + OCR0A = val; + } else if (digitalPinToTimer(pin) == TIMER0B) { + // connect pwm to pin on timer 0, channel B + sbi(TCCR0A, COM0B1); + // set pwm duty + OCR0B = val; + } else if (digitalPinToTimer(pin) == TIMER2A) { + // connect pwm to pin on timer 2, channel A + sbi(TCCR2A, COM2A1); + // set pwm duty + OCR2A = val; + } else if (digitalPinToTimer(pin) == TIMER2B) { + // connect pwm to pin on timer 2, channel B + sbi(TCCR2A, COM2B1); + // set pwm duty + OCR2B = val; + } else if (val < 128) + //fail semi-intelligently + digitalWrite(pin, LOW); + else + digitalWrite(pin, HIGH); +} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c new file mode 100644 index 0000000000..3d4b4ebd1c --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c @@ -0,0 +1,95 @@ +/* + wiring_digital.c - digital input and output functions + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +void pinMode(uint8_t pin, uint8_t mode) +{ + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *reg; + + if (port == NOT_A_PIN) return; + + // JWS: can I let the optimizer do this? + reg = portModeRegister(port); + + if (mode == INPUT) *reg &= ~bit; + else *reg |= bit; +} + +// Forcing this inline keeps the callers from having to push their own stuff +// on the stack. It is a good performance win and only takes 1 more byte per +// user than calling. (It will take more bytes on the 168.) +// +// But shouldn't this be moved into pinMode? Seems silly to check and do on +// each digitalread or write. +// +static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); +static inline void turnOffPWM(uint8_t timer) +{ + if (timer == TIMER0A) cbi(TCCR0A, COM0A1); + if (timer == TIMER0B) cbi(TCCR0A, COM0B1); + if (timer == TIMER1A) cbi(TCCR1A, COM1A1); + if (timer == TIMER1B) cbi(TCCR1A, COM1B1); + if (timer == TIMER2A) cbi(TCCR2A, COM2A1); + if (timer == TIMER2B) cbi(TCCR2A, COM2B1); +} + +void digitalWrite(uint8_t pin, uint8_t val) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *out; + + if (port == NOT_A_PIN) return; + + // If the pin that support PWM output, we need to turn it off + // before doing a digital write. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + out = portOutputRegister(port); + + if (val == LOW) *out &= ~bit; + else *out |= bit; +} + +int digitalRead(uint8_t pin) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + + if (port == NOT_A_PIN) return LOW; + + // If the pin that support PWM output, we need to turn it off + // before getting a digital reading. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + if (*portInputRegister(port) & bit) return HIGH; + + return LOW; +} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_private.h b/Marlin/Sanguino/cores/Copy of arduino/wiring_private.h new file mode 100644 index 0000000000..14394a0b61 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/wiring_private.h @@ -0,0 +1,60 @@ +/* + wiring_private.h - Internal header file. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ +*/ + +#ifndef WiringPrivate_h +#define WiringPrivate_h + +#include +#include +#include +#include +#include +#include + +#include "wiring.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#define EXTERNAL_INT_0 0 +#define EXTERNAL_INT_1 1 +#define EXTERNAL_INT_2 2 + +#define EXTERNAL_NUM_INTERRUPTS 3 + +typedef void (*voidFuncPtr)(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c new file mode 100644 index 0000000000..0d968865d2 --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c @@ -0,0 +1,69 @@ +/* + wiring_pulse.c - pulseIn() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH + * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds + * to 3 minutes in length, but must be called at least a few dozen microseconds + * before the start of the pulse. */ +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) +{ + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + uint8_t stateMask = (state ? bit : 0); + unsigned long width = 0; // keep initialization out of time critical area + + // convert the timeout from microseconds to a number of times through + // the initial loop; it takes 16 clock cycles per iteration. + unsigned long numloops = 0; + unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; + + // wait for any previous pulse to end + while ((*portInputRegister(port) & bit) == stateMask) + if (numloops++ == maxloops) + return 0; + + // wait for the pulse to start + while ((*portInputRegister(port) & bit) != stateMask) + if (numloops++ == maxloops) + return 0; + + // wait for the pulse to stop + while ((*portInputRegister(port) & bit) == stateMask) { + if (numloops++ == maxloops) + return 0; + width++; + } + + // convert the reading to microseconds. The loop has been determined + // to be 20 clock cycles long and have about 16 clocks between the edge + // and the start of the loop. There will be some error introduced by + // the interrupt handlers. + return clockCyclesToMicroseconds(width * 21 + 16); +} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c new file mode 100644 index 0000000000..cfe786758c --- /dev/null +++ b/Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c @@ -0,0 +1,55 @@ +/* + wiring_shift.c - shiftOut() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { + uint8_t value = 0; + uint8_t i; + + for (i = 0; i < 8; ++i) { + digitalWrite(clockPin, HIGH); + if (bitOrder == LSBFIRST) + value |= digitalRead(dataPin) << i; + else + value |= digitalRead(dataPin) << (7 - i); + digitalWrite(clockPin, LOW); + } + return value; +} + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + if (bitOrder == LSBFIRST) + digitalWrite(dataPin, !!(val & (1 << i))); + else + digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + + digitalWrite(clockPin, HIGH); + digitalWrite(clockPin, LOW); + } +} diff --git a/Marlin/Sanguino/cores/arduino/Copy of wiring.h b/Marlin/Sanguino/cores/arduino/Copy of wiring.h new file mode 100644 index 0000000000..e29959b865 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/Copy of wiring.h @@ -0,0 +1,135 @@ +/* + wiring.h - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +#ifndef Wiring_h +#define Wiring_h + +#include +#include +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 + +#define true 0x1 +#define false 0x0 + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define INTERNAL1V1 2 +#define INTERNAL2V56 3 +#else +#define INTERNAL 3 +#endif +#define DEFAULT 1 +#define EXTERNAL 0 + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() sei() +#define noInterrupts() cli() + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) +#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogReference(uint8_t mode); +void analogWrite(uint8_t, int); + +unsigned long millis(void); +unsigned long micros(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int us); +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +void loop(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/Marlin/Sanguino/cores/arduino/HardwareSerial.cpp b/Marlin/Sanguino/cores/arduino/HardwareSerial.cpp new file mode 100644 index 0000000000..4397efb7ee --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/HardwareSerial.cpp @@ -0,0 +1,303 @@ +/* + HardwareSerial.cpp - Hardware serial library for Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 23 November 2006 by David A. Mellis + Modified 28 September 2010 by Mark Sproul +*/ + +#include +#include +#include +#include +#include "wiring.h" +#include "wiring_private.h" + +// this next line disables the entire HardwareSerial.cpp, +// this is so I can support Attiny series and any other chip without a uart +#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) + +#include "HardwareSerial.h" + +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which rx_buffer_head is the index of the +// location to which to write the next incoming character and rx_buffer_tail +// is the index of the location from which to read. +#if (RAMEND < 1000) + #define RX_BUFFER_SIZE 32 +#else + #define RX_BUFFER_SIZE 128 +#endif + +struct ring_buffer +{ + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; +}; + +#if defined(UBRRH) || defined(UBRR0H) + ring_buffer rx_buffer = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR1H) + ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR2H) + ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR3H) + ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; +#endif + +inline void store_char(unsigned char c, ring_buffer *rx_buffer) +{ + int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != rx_buffer->tail) { + rx_buffer->buffer[rx_buffer->head] = c; + rx_buffer->head = i; + } +} + +#if defined(USART_RX_vect) + SIGNAL(USART_RX_vect) + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; // atmega8535 + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } +#elif defined(SIG_USART0_RECV) && defined(UDR0) + SIGNAL(SIG_USART0_RECV) + { + unsigned char c = UDR0; + store_char(c, &rx_buffer); + } +#elif defined(SIG_UART0_RECV) && defined(UDR0) + SIGNAL(SIG_UART0_RECV) + { + unsigned char c = UDR0; + store_char(c, &rx_buffer); + } +//#elif defined(SIG_USART_RECV) +#elif defined(USART0_RX_vect) + // fixed by Mark Sproul this is on the 644/644p + //SIGNAL(SIG_USART_RECV) + SIGNAL(USART0_RX_vect) + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; // atmega8, atmega32 + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } +#elif defined(SIG_UART_RECV) + // this is for atmega8 + SIGNAL(SIG_UART_RECV) + { + #if defined(UDR0) + unsigned char c = UDR0; // atmega645 + #elif defined(UDR) + unsigned char c = UDR; // atmega8 + #endif + store_char(c, &rx_buffer); + } +#elif defined(USBCON) + #warning No interrupt handler for usart 0 + #warning Serial(0) is on USB interface +#else + #error No interrupt handler for usart 0 +#endif + +//#if defined(SIG_USART1_RECV) +#if defined(USART1_RX_vect) + //SIGNAL(SIG_USART1_RECV) + SIGNAL(USART1_RX_vect) + { + unsigned char c = UDR1; + store_char(c, &rx_buffer1); + } +#elif defined(SIG_USART1_RECV) + #error SIG_USART1_RECV +#endif + +#if defined(USART2_RX_vect) && defined(UDR2) + SIGNAL(USART2_RX_vect) + { + unsigned char c = UDR2; + store_char(c, &rx_buffer2); + } +#elif defined(SIG_USART2_RECV) + #error SIG_USART2_RECV +#endif + +#if defined(USART3_RX_vect) && defined(UDR3) + SIGNAL(USART3_RX_vect) + { + unsigned char c = UDR3; + store_char(c, &rx_buffer3); + } +#elif defined(SIG_USART3_RECV) + #error SIG_USART3_RECV +#endif + + + +// Constructors //////////////////////////////////////////////////////////////// + +HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) +{ + _rx_buffer = rx_buffer; + _ubrrh = ubrrh; + _ubrrl = ubrrl; + _ucsra = ucsra; + _ucsrb = ucsrb; + _udr = udr; + _rxen = rxen; + _txen = txen; + _rxcie = rxcie; + _udre = udre; + _u2x = u2x; +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void HardwareSerial::begin(long baud) +{ + uint16_t baud_setting; + bool use_u2x = true; + +#if F_CPU == 16000000UL + // hardcoded exception for compatibility with the bootloader shipped + // with the Duemilanove and previous boards and the firmware on the 8U2 + // on the Uno and Mega 2560. + if (baud == 57600) { + use_u2x = false; + } +#endif + + if (use_u2x) { + *_ucsra = 1 << _u2x; + baud_setting = (F_CPU / 4 / baud - 1) / 2; + } else { + *_ucsra = 0; + baud_setting = (F_CPU / 8 / baud - 1) / 2; + } + + // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) + *_ubrrh = baud_setting >> 8; + *_ubrrl = baud_setting; + + sbi(*_ucsrb, _rxen); + sbi(*_ucsrb, _txen); + sbi(*_ucsrb, _rxcie); +} + +void HardwareSerial::end() +{ + cbi(*_ucsrb, _rxen); + cbi(*_ucsrb, _txen); + cbi(*_ucsrb, _rxcie); +} + +int HardwareSerial::available(void) +{ + return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; +} + +int HardwareSerial::peek(void) +{ + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + return _rx_buffer->buffer[_rx_buffer->tail]; + } +} + +int HardwareSerial::read(void) +{ + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; + _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + return c; + } +} + +void HardwareSerial::flush() +{ + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // were full, not empty. + _rx_buffer->head = _rx_buffer->tail; +} + +void HardwareSerial::write(uint8_t c) +{ + while (!((*_ucsra) & (1 << _udre))) + ; + + *_udr = c; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +#if defined(UBRRH) && defined(UBRRL) + HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); +#elif defined(UBRR0H) && defined(UBRR0L) + HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); +#elif defined(USBCON) + #warning no serial port defined (port 0) +#else + #error no serial port defined (port 0) +#endif + +#if defined(UBRR1H) + HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); +#endif +#if defined(UBRR2H) + HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); +#endif +#if defined(UBRR3H) + HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); +#endif + +#endif // whole file + diff --git a/Marlin/Sanguino/cores/arduino/HardwareSerial.h b/Marlin/Sanguino/cores/arduino/HardwareSerial.h new file mode 100644 index 0000000000..3efa775f84 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/HardwareSerial.h @@ -0,0 +1,76 @@ +/* + HardwareSerial.h - Hardware serial library for Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 28 September 2010 by Mark Sproul +*/ + +#ifndef HardwareSerial_h +#define HardwareSerial_h + +#include + +#include "Stream.h" + +struct ring_buffer; + +class HardwareSerial : public Stream +{ + private: + ring_buffer *_rx_buffer; + volatile uint8_t *_ubrrh; + volatile uint8_t *_ubrrl; + volatile uint8_t *_ucsra; + volatile uint8_t *_ucsrb; + volatile uint8_t *_udr; + uint8_t _rxen; + uint8_t _txen; + uint8_t _rxcie; + uint8_t _udre; + uint8_t _u2x; + public: + HardwareSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); + void begin(long); + void end(); + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual void write(uint8_t); + using Print::write; // pull in write(str) and write(buf, size) from Print +}; + +#if defined(UBRRH) || defined(UBRR0H) + extern HardwareSerial Serial; +#elif defined(USBCON) + #include "usb_api.h" +#endif +#if defined(UBRR1H) + extern HardwareSerial Serial1; +#endif +#if defined(UBRR2H) + extern HardwareSerial Serial2; +#endif +#if defined(UBRR3H) + extern HardwareSerial Serial3; +#endif + +#endif diff --git a/Marlin/Sanguino/cores/arduino/Print.cpp b/Marlin/Sanguino/cores/arduino/Print.cpp new file mode 100644 index 0000000000..4ee556dd82 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/Print.cpp @@ -0,0 +1,220 @@ +/* + Print.cpp - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 23 November 2006 by David A. Mellis + */ + +#include +#include +#include +#include +#include "wiring.h" + +#include "Print.h" + +// Public Methods ////////////////////////////////////////////////////////////// + +/* default implementation: may be overridden */ +void Print::write(const char *str) +{ + while (*str) + write(*str++); +} + +/* default implementation: may be overridden */ +void Print::write(const uint8_t *buffer, size_t size) +{ + while (size--) + write(*buffer++); +} + +void Print::print(const String &s) +{ + for (int i = 0; i < s.length(); i++) { + write(s[i]); + } +} + +void Print::print(const char str[]) +{ + write(str); +} + +void Print::print(char c, int base) +{ + print((long) c, base); +} + +void Print::print(unsigned char b, int base) +{ + print((unsigned long) b, base); +} + +void Print::print(int n, int base) +{ + print((long) n, base); +} + +void Print::print(unsigned int n, int base) +{ + print((unsigned long) n, base); +} + +void Print::print(long n, int base) +{ + if (base == 0) { + write(n); + } else if (base == 10) { + if (n < 0) { + print('-'); + n = -n; + } + printNumber(n, 10); + } else { + printNumber(n, base); + } +} + +void Print::print(unsigned long n, int base) +{ + if (base == 0) write(n); + else printNumber(n, base); +} + +void Print::print(double n, int digits) +{ + printFloat(n, digits); +} + +void Print::println(void) +{ + print('\r'); + print('\n'); +} + +void Print::println(const String &s) +{ + print(s); + println(); +} + +void Print::println(const char c[]) +{ + print(c); + println(); +} + +void Print::println(char c, int base) +{ + print(c, base); + println(); +} + +void Print::println(unsigned char b, int base) +{ + print(b, base); + println(); +} + +void Print::println(int n, int base) +{ + print(n, base); + println(); +} + +void Print::println(unsigned int n, int base) +{ + print(n, base); + println(); +} + +void Print::println(long n, int base) +{ + print(n, base); + println(); +} + +void Print::println(unsigned long n, int base) +{ + print(n, base); + println(); +} + +void Print::println(double n, int digits) +{ + print(n, digits); + println(); +} + +// Private Methods ///////////////////////////////////////////////////////////// + +void Print::printNumber(unsigned long n, uint8_t base) +{ + unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. + unsigned long i = 0; + + if (n == 0) { + print('0'); + return; + } + + while (n > 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) + print((char) (buf[i - 1] < 10 ? + '0' + buf[i - 1] : + 'A' + buf[i - 1] - 10)); +} + +void Print::printFloat(double number, uint8_t digits) +{ + // Handle negative numbers + if (number < 0.0) + { + print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i=0; i 0) + print("."); + + // Extract digits from the remainder one at a time + while (digits-- > 0) + { + remainder *= 10.0; + int toPrint = int(remainder); + print(toPrint); + remainder -= toPrint; + } +} diff --git a/Marlin/Sanguino/cores/arduino/Print.h b/Marlin/Sanguino/cores/arduino/Print.h new file mode 100644 index 0000000000..b092ae51d1 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/Print.h @@ -0,0 +1,66 @@ +/* + Print.h - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef Print_h +#define Print_h + +#include +#include // for size_t + +#include "WString.h" + +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 +#define BYTE 0 + +class Print +{ + private: + void printNumber(unsigned long, uint8_t); + void printFloat(double, uint8_t); + public: + virtual void write(uint8_t) = 0; + virtual void write(const char *str); + virtual void write(const uint8_t *buffer, size_t size); + + void print(const String &); + void print(const char[]); + void print(char, int = BYTE); + void print(unsigned char, int = BYTE); + void print(int, int = DEC); + void print(unsigned int, int = DEC); + void print(long, int = DEC); + void print(unsigned long, int = DEC); + void print(double, int = 2); + + void println(const String &s); + void println(const char[]); + void println(char, int = BYTE); + void println(unsigned char, int = BYTE); + void println(int, int = DEC); + void println(unsigned int, int = DEC); + void println(long, int = DEC); + void println(unsigned long, int = DEC); + void println(double, int = 2); + void println(void); +}; + +#endif diff --git a/Marlin/Sanguino/cores/arduino/Stream.h b/Marlin/Sanguino/cores/arduino/Stream.h new file mode 100644 index 0000000000..93d8275dc2 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/Stream.h @@ -0,0 +1,35 @@ +/* + Stream.h - base class for character-based streams. + Copyright (c) 2010 David A. Mellis. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef Stream_h +#define Stream_h + +#include +#include "Print.h" + +class Stream : public Print +{ + public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; + virtual void flush() = 0; +}; + +#endif diff --git a/Marlin/Sanguino/cores/arduino/Tone.cpp b/Marlin/Sanguino/cores/arduino/Tone.cpp new file mode 100644 index 0000000000..c3910e7a61 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/Tone.cpp @@ -0,0 +1,601 @@ +/* Tone.cpp + + A Tone Generator Library + + Written by Brett Hagman + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Version Modified By Date Comments +------- ----------- -------- -------- +0001 B Hagman 09/08/02 Initial coding +0002 B Hagman 09/08/18 Multiple pins +0003 B Hagman 09/08/18 Moved initialization from constructor to begin() +0004 B Hagman 09/09/26 Fixed problems with ATmega8 +0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers + 09/11/25 Changed pin toggle method to XOR + 09/11/25 Fixed timer0 from being excluded +0006 D Mellis 09/12/29 Replaced objects with functions +0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register +*************************************************/ + +#include +#include +#include "wiring.h" +#include "pins_arduino.h" + +#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) +#define TCCR2A TCCR2 +#define TCCR2B TCCR2 +#define COM2A1 COM21 +#define COM2A0 COM20 +#define OCR2A OCR2 +#define TIMSK2 TIMSK +#define OCIE2A OCIE2 +#define TIMER2_COMPA_vect TIMER2_COMP_vect +#define TIMSK1 TIMSK +#endif + +// timerx_toggle_count: +// > 0 - duration specified +// = 0 - stopped +// < 0 - infinitely (until stop() method called, or new play() called) + +#if !defined(__AVR_ATmega8__) +volatile long timer0_toggle_count; +volatile uint8_t *timer0_pin_port; +volatile uint8_t timer0_pin_mask; +#endif + +volatile long timer1_toggle_count; +volatile uint8_t *timer1_pin_port; +volatile uint8_t timer1_pin_mask; +volatile long timer2_toggle_count; +volatile uint8_t *timer2_pin_port; +volatile uint8_t timer2_pin_mask; + +#if defined(TIMSK3) +volatile long timer3_toggle_count; +volatile uint8_t *timer3_pin_port; +volatile uint8_t timer3_pin_mask; +#endif + +#if defined(TIMSK4) +volatile long timer4_toggle_count; +volatile uint8_t *timer4_pin_port; +volatile uint8_t timer4_pin_mask; +#endif + +#if defined(TIMSK5) +volatile long timer5_toggle_count; +volatile uint8_t *timer5_pin_port; +volatile uint8_t timer5_pin_mask; +#endif + + +// MLS: This does not make sense, the 3 options are the same +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + +#define AVAILABLE_TONE_PINS 1 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; + +#elif defined(__AVR_ATmega8__) + +#define AVAILABLE_TONE_PINS 1 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; + +#else + +#define AVAILABLE_TONE_PINS 1 + +// Leave timer 0 to last. +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; + +#endif + + + +static int8_t toneBegin(uint8_t _pin) +{ + int8_t _timer = -1; + + // if we're already using the pin, the timer should be configured. + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == _pin) { + return pgm_read_byte(tone_pin_to_timer_PGM + i); + } + } + + // search for an unused timer. + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == 255) { + tone_pins[i] = _pin; + _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); + break; + } + } + + if (_timer != -1) + { + // Set timer specific stuff + // All timers in CTC mode + // 8 bit timers will require changing prescalar values, + // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar + switch (_timer) + { + #if defined(TCCR0A) && defined(TCCR0B) + case 0: + // 8 bit timer + TCCR0A = 0; + TCCR0B = 0; + bitWrite(TCCR0A, WGM01, 1); + bitWrite(TCCR0B, CS00, 1); + timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer0_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12) + case 1: + // 16 bit timer + TCCR1A = 0; + TCCR1B = 0; + bitWrite(TCCR1B, WGM12, 1); + bitWrite(TCCR1B, CS10, 1); + timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer1_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR2A) && defined(TCCR2B) + case 2: + // 8 bit timer + TCCR2A = 0; + TCCR2B = 0; + bitWrite(TCCR2A, WGM21, 1); + bitWrite(TCCR2B, CS20, 1); + timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer2_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3) + case 3: + // 16 bit timer + TCCR3A = 0; + TCCR3B = 0; + bitWrite(TCCR3B, WGM32, 1); + bitWrite(TCCR3B, CS30, 1); + timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer3_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4) + case 4: + // 16 bit timer + TCCR4A = 0; + TCCR4B = 0; + #if defined(WGM42) + bitWrite(TCCR4B, WGM42, 1); + #elif defined(CS43) + #warning this may not be correct + // atmega32u4 + bitWrite(TCCR4B, CS43, 1); + #endif + bitWrite(TCCR4B, CS40, 1); + timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer4_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + + #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5) + case 5: + // 16 bit timer + TCCR5A = 0; + TCCR5B = 0; + bitWrite(TCCR5B, WGM52, 1); + bitWrite(TCCR5B, CS50, 1); + timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer5_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + } + } + + return _timer; +} + + + +// frequency (in hertz) and duration (in milliseconds). + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) +{ + uint8_t prescalarbits = 0b001; + long toggle_count = 0; + uint32_t ocr = 0; + int8_t _timer; + + _timer = toneBegin(_pin); + + if (_timer >= 0) + { + // Set the pinMode as OUTPUT + pinMode(_pin, OUTPUT); + + // if we are using an 8 bit timer, scan through prescalars to find the best fit + if (_timer == 0 || _timer == 2) + { + ocr = F_CPU / frequency / 2 - 1; + prescalarbits = 0b001; // ck/1: same for both timers + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 8 - 1; + prescalarbits = 0b010; // ck/8: same for both timers + + if (_timer == 2 && ocr > 255) + { + ocr = F_CPU / frequency / 2 / 32 - 1; + prescalarbits = 0b011; + } + + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = _timer == 0 ? 0b011 : 0b100; + + if (_timer == 2 && ocr > 255) + { + ocr = F_CPU / frequency / 2 / 128 - 1; + prescalarbits = 0b101; + } + + if (ocr > 255) + { + ocr = F_CPU / frequency / 2 / 256 - 1; + prescalarbits = _timer == 0 ? 0b100 : 0b110; + if (ocr > 255) + { + // can't do any better than /1024 + ocr = F_CPU / frequency / 2 / 1024 - 1; + prescalarbits = _timer == 0 ? 0b101 : 0b111; + } + } + } + } + +#if defined(TCCR0B) + if (_timer == 0) + { + TCCR0B = prescalarbits; + } + else +#endif +#if defined(TCCR2B) + { + TCCR2B = prescalarbits; + } +#else + { + // dummy place holder to make the above ifdefs work + } +#endif + } + else + { + // two choices for the 16 bit timers: ck/1 or ck/64 + ocr = F_CPU / frequency / 2 - 1; + + prescalarbits = 0b001; + if (ocr > 0xffff) + { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = 0b011; + } + + if (_timer == 1) + { +#if defined(TCCR1B) + TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; +#endif + } +#if defined(TCCR3B) + else if (_timer == 3) + TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; +#endif +#if defined(TCCR4B) + else if (_timer == 4) + TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; +#endif +#if defined(TCCR5B) + else if (_timer == 5) + TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; +#endif + + } + + + // Calculate the toggle count + if (duration > 0) + { + toggle_count = 2 * frequency * duration / 1000; + } + else + { + toggle_count = -1; + } + + // Set the OCR for the given timer, + // set the toggle count, + // then turn on the interrupts + switch (_timer) + { + +#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A) + case 0: + OCR0A = ocr; + timer0_toggle_count = toggle_count; + bitWrite(TIMSK0, OCIE0A, 1); + break; +#endif + + case 1: +#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A) + OCR1A = ocr; + timer1_toggle_count = toggle_count; + bitWrite(TIMSK1, OCIE1A, 1); +#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A) + // this combination is for at least the ATmega32 + OCR1A = ocr; + timer1_toggle_count = toggle_count; + bitWrite(TIMSK, OCIE1A, 1); +#endif + break; + +#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A) + case 2: + OCR2A = ocr; + timer2_toggle_count = toggle_count; + bitWrite(TIMSK2, OCIE2A, 1); + break; +#endif + +#if defined(TIMSK3) + case 3: + OCR3A = ocr; + timer3_toggle_count = toggle_count; + bitWrite(TIMSK3, OCIE3A, 1); + break; +#endif + +#if defined(TIMSK4) + case 4: + OCR4A = ocr; + timer4_toggle_count = toggle_count; + bitWrite(TIMSK4, OCIE4A, 1); + break; +#endif + +#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A) + case 5: + OCR5A = ocr; + timer5_toggle_count = toggle_count; + bitWrite(TIMSK5, OCIE5A, 1); + break; +#endif + + } + } +} + + +// XXX: this function only works properly for timer 2 (the only one we use +// currently). for the others, it should end the tone, but won't restore +// proper PWM functionality for the timer. +void disableTimer(uint8_t _timer) +{ + switch (_timer) + { + case 0: + #if defined(TIMSK0) + TIMSK0 = 0; + #elif defined(TIMSK) + TIMSK = 0; // atmega32 + #endif + break; + +#if defined(TIMSK1) && defined(OCIE1A) + case 1: + bitWrite(TIMSK1, OCIE1A, 0); + break; +#endif + + case 2: + #if defined(TIMSK2) && defined(OCIE2A) + bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt + #endif + #if defined(TCCR2A) && defined(WGM20) + TCCR2A = (1 << WGM20); + #endif + #if defined(TCCR2B) && defined(CS22) + TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); + #endif + #if defined(OCR2A) + OCR2A = 0; + #endif + break; + +#if defined(TIMSK3) + case 3: + TIMSK3 = 0; + break; +#endif + +#if defined(TIMSK4) + case 4: + TIMSK4 = 0; + break; +#endif + +#if defined(TIMSK5) + case 5: + TIMSK5 = 0; + break; +#endif + } +} + + +void noTone(uint8_t _pin) +{ + int8_t _timer = -1; + + for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { + if (tone_pins[i] == _pin) { + _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); + tone_pins[i] = 255; + } + } + + disableTimer(_timer); + + digitalWrite(_pin, 0); +} + +#if 0 +#if !defined(__AVR_ATmega8__) +ISR(TIMER0_COMPA_vect) +{ + if (timer0_toggle_count != 0) + { + // toggle the pin + *timer0_pin_port ^= timer0_pin_mask; + + if (timer0_toggle_count > 0) + timer0_toggle_count--; + } + else + { + disableTimer(0); + *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop + } +} +#endif + + +ISR(TIMER1_COMPA_vect) +{ + if (timer1_toggle_count != 0) + { + // toggle the pin + *timer1_pin_port ^= timer1_pin_mask; + + if (timer1_toggle_count > 0) + timer1_toggle_count--; + } + else + { + disableTimer(1); + *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop + } +} +#endif + + +ISR(TIMER2_COMPA_vect) +{ + + if (timer2_toggle_count != 0) + { + // toggle the pin + *timer2_pin_port ^= timer2_pin_mask; + + if (timer2_toggle_count > 0) + timer2_toggle_count--; + } + else + { + // need to call noTone() so that the tone_pins[] entry is reset, so the + // timer gets initialized next time we call tone(). + // XXX: this assumes timer 2 is always the first one used. + noTone(tone_pins[0]); +// disableTimer(2); +// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop + } +} + + + +//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if 0 + +ISR(TIMER3_COMPA_vect) +{ + if (timer3_toggle_count != 0) + { + // toggle the pin + *timer3_pin_port ^= timer3_pin_mask; + + if (timer3_toggle_count > 0) + timer3_toggle_count--; + } + else + { + disableTimer(3); + *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop + } +} + +ISR(TIMER4_COMPA_vect) +{ + if (timer4_toggle_count != 0) + { + // toggle the pin + *timer4_pin_port ^= timer4_pin_mask; + + if (timer4_toggle_count > 0) + timer4_toggle_count--; + } + else + { + disableTimer(4); + *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop + } +} + +ISR(TIMER5_COMPA_vect) +{ + if (timer5_toggle_count != 0) + { + // toggle the pin + *timer5_pin_port ^= timer5_pin_mask; + + if (timer5_toggle_count > 0) + timer5_toggle_count--; + } + else + { + disableTimer(5); + *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop + } +} + +#endif diff --git a/Marlin/Sanguino/cores/arduino/WCharacter.h b/Marlin/Sanguino/cores/arduino/WCharacter.h new file mode 100644 index 0000000000..79733b50a5 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/WCharacter.h @@ -0,0 +1,168 @@ +/* + WCharacter.h - Character utility functions for Wiring & Arduino + Copyright (c) 2010 Hernando Barragan. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef Character_h +#define Character_h + +#include + +// WCharacter.h prototypes +inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); +inline boolean isAlpha(int c) __attribute__((always_inline)); +inline boolean isAscii(int c) __attribute__((always_inline)); +inline boolean isWhitespace(int c) __attribute__((always_inline)); +inline boolean isControl(int c) __attribute__((always_inline)); +inline boolean isDigit(int c) __attribute__((always_inline)); +inline boolean isGraph(int c) __attribute__((always_inline)); +inline boolean isLowerCase(int c) __attribute__((always_inline)); +inline boolean isPrintable(int c) __attribute__((always_inline)); +inline boolean isPunct(int c) __attribute__((always_inline)); +inline boolean isSpace(int c) __attribute__((always_inline)); +inline boolean isUpperCase(int c) __attribute__((always_inline)); +inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); +inline int toAscii(int c) __attribute__((always_inline)); +inline int toLowerCase(int c) __attribute__((always_inline)); +inline int toUpperCase(int c)__attribute__((always_inline)); + + +// Checks for an alphanumeric character. +// It is equivalent to (isalpha(c) || isdigit(c)). +inline boolean isAlphaNumeric(int c) +{ + return ( isalnum(c) == 0 ? false : true); +} + + +// Checks for an alphabetic character. +// It is equivalent to (isupper(c) || islower(c)). +inline boolean isAlpha(int c) +{ + return ( isalpha(c) == 0 ? false : true); +} + + +// Checks whether c is a 7-bit unsigned char value +// that fits into the ASCII character set. +inline boolean isAscii(int c) +{ + return ( isascii (c) == 0 ? false : true); +} + + +// Checks for a blank character, that is, a space or a tab. +inline boolean isWhitespace(int c) +{ + return ( isblank (c) == 0 ? false : true); +} + + +// Checks for a control character. +inline boolean isControl(int c) +{ + return ( iscntrl (c) == 0 ? false : true); +} + + +// Checks for a digit (0 through 9). +inline boolean isDigit(int c) +{ + return ( isdigit (c) == 0 ? false : true); +} + + +// Checks for any printable character except space. +inline boolean isGraph(int c) +{ + return ( isgraph (c) == 0 ? false : true); +} + + +// Checks for a lower-case character. +inline boolean isLowerCase(int c) +{ + return (islower (c) == 0 ? false : true); +} + + +// Checks for any printable character including space. +inline boolean isPrintable(int c) +{ + return ( isprint (c) == 0 ? false : true); +} + + +// Checks for any printable character which is not a space +// or an alphanumeric character. +inline boolean isPunct(int c) +{ + return ( ispunct (c) == 0 ? false : true); +} + + +// Checks for white-space characters. For the avr-libc library, +// these are: space, formfeed ('\f'), newline ('\n'), carriage +// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). +inline boolean isSpace(int c) +{ + return ( isspace (c) == 0 ? false : true); +} + + +// Checks for an uppercase letter. +inline boolean isUpperCase(int c) +{ + return ( isupper (c) == 0 ? false : true); +} + + +// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 +// 8 9 a b c d e f A B C D E F. +inline boolean isHexadecimalDigit(int c) +{ + return ( isxdigit (c) == 0 ? false : true); +} + + +// Converts c to a 7-bit unsigned char value that fits into the +// ASCII character set, by clearing the high-order bits. +inline int toAscii(int c) +{ + return toascii (c); +} + + +// Warning: +// Many people will be unhappy if you use this function. +// This function will convert accented letters into random +// characters. + +// Converts the letter c to lower case, if possible. +inline int toLowerCase(int c) +{ + return tolower (c); +} + + +// Converts the letter c to upper case, if possible. +inline int toUpperCase(int c) +{ + return toupper (c); +} + +#endif \ No newline at end of file diff --git a/Marlin/Sanguino/cores/arduino/WConstants.h b/Marlin/Sanguino/cores/arduino/WConstants.h new file mode 100644 index 0000000000..3e19ac44aa --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/WConstants.h @@ -0,0 +1 @@ +#include "wiring.h" diff --git a/Marlin/Sanguino/cores/arduino/WInterrupts.c b/Marlin/Sanguino/cores/arduino/WInterrupts.c new file mode 100644 index 0000000000..3b3e0c9ec4 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/WInterrupts.c @@ -0,0 +1,249 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Wiring project - http://wiring.uniandes.edu.co + + Copyright (c) 2004-05 Hernando Barragan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 24 November 2006 by David A. Mellis + Modified 1 August 2010 by Mark Sproul +*/ + +#include +#include +#include +#include +#include + +#include "WConstants.h" +#include "wiring_private.h" + +volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; +// volatile static voidFuncPtr twiIntFunc; + +void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { + if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { + intFunc[interruptNum] = userFunc; + + // Configure the interrupt mode (trigger on low input, any change, rising + // edge, or falling edge). The mode constants were chosen to correspond + // to the configuration bits in the hardware register, so we simply shift + // the mode into place. + + // Enable the interrupt. + + switch (interruptNum) { +#if defined(EICRA) && defined(EICRB) && defined(EIMSK) + case 2: + EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + EIMSK |= (1 << INT0); + break; + case 3: + EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + EIMSK |= (1 << INT1); + break; + case 4: + EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20); + EIMSK |= (1 << INT2); + break; + case 5: + EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30); + EIMSK |= (1 << INT3); + break; + case 0: + EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40); + EIMSK |= (1 << INT4); + break; + case 1: + EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50); + EIMSK |= (1 << INT5); + break; + case 6: + EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60); + EIMSK |= (1 << INT6); + break; + case 7: + EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70); + EIMSK |= (1 << INT7); + break; +#else + case 0: + #if defined(EICRA) && defined(ISC00) && defined(EIMSK) + EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + EIMSK |= (1 << INT0); + #elif defined(MCUCR) && defined(ISC00) && defined(GICR) + MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + GICR |= (1 << INT0); + #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK) + MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + GIMSK |= (1 << INT0); + #else + #error attachInterrupt not finished for this CPU (case 0) + #endif + break; + + case 1: + #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK) + EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + EIMSK |= (1 << INT1); + #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR) + MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + GICR |= (1 << INT1); + #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK) + MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + GIMSK |= (1 << INT1); + #else + #warning attachInterrupt may need some more work for this cpu (case 1) + #endif + break; +#endif + } + } +} + +void detachInterrupt(uint8_t interruptNum) { + if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { + // Disable the interrupt. (We can't assume that interruptNum is equal + // to the number of the EIMSK bit to clear, as this isn't true on the + // ATmega8. There, INT0 is 6 and INT1 is 7.) + switch (interruptNum) { +#if defined(EICRA) && defined(EICRB) && defined(EIMSK) + case 2: + EIMSK &= ~(1 << INT0); + break; + case 3: + EIMSK &= ~(1 << INT1); + break; + case 4: + EIMSK &= ~(1 << INT2); + break; + case 5: + EIMSK &= ~(1 << INT3); + break; + case 0: + EIMSK &= ~(1 << INT4); + break; + case 1: + EIMSK &= ~(1 << INT5); + break; + case 6: + EIMSK &= ~(1 << INT6); + break; + case 7: + EIMSK &= ~(1 << INT7); + break; +#else + case 0: + #if defined(EIMSK) && defined(INT0) + EIMSK &= ~(1 << INT0); + #elif defined(GICR) && defined(ISC00) + GICR &= ~(1 << INT0); // atmega32 + #elif defined(GIMSK) && defined(INT0) + GIMSK &= ~(1 << INT0); + #else + #error detachInterrupt not finished for this cpu + #endif + break; + + case 1: + #if defined(EIMSK) && defined(INT1) + EIMSK &= ~(1 << INT1); + #elif defined(GICR) && defined(INT1) + GICR &= ~(1 << INT1); // atmega32 + #elif defined(GIMSK) && defined(INT1) + GIMSK &= ~(1 << INT1); + #else + #warning detachInterrupt may need some more work for this cpu (case 1) + #endif + break; +#endif + } + + intFunc[interruptNum] = 0; + } +} + +/* +void attachInterruptTwi(void (*userFunc)(void) ) { + twiIntFunc = userFunc; +} +*/ + +#if defined(EICRA) && defined(EICRB) + +SIGNAL(INT0_vect) { + if(intFunc[EXTERNAL_INT_2]) + intFunc[EXTERNAL_INT_2](); +} + +SIGNAL(INT1_vect) { + if(intFunc[EXTERNAL_INT_3]) + intFunc[EXTERNAL_INT_3](); +} + +SIGNAL(INT2_vect) { + if(intFunc[EXTERNAL_INT_4]) + intFunc[EXTERNAL_INT_4](); +} + +SIGNAL(INT3_vect) { + if(intFunc[EXTERNAL_INT_5]) + intFunc[EXTERNAL_INT_5](); +} + +SIGNAL(INT4_vect) { + if(intFunc[EXTERNAL_INT_0]) + intFunc[EXTERNAL_INT_0](); +} + +SIGNAL(INT5_vect) { + if(intFunc[EXTERNAL_INT_1]) + intFunc[EXTERNAL_INT_1](); +} + +SIGNAL(INT6_vect) { + if(intFunc[EXTERNAL_INT_6]) + intFunc[EXTERNAL_INT_6](); +} + +SIGNAL(INT7_vect) { + if(intFunc[EXTERNAL_INT_7]) + intFunc[EXTERNAL_INT_7](); +} + +#else + +SIGNAL(INT0_vect) { + if(intFunc[EXTERNAL_INT_0]) + intFunc[EXTERNAL_INT_0](); +} + +SIGNAL(INT1_vect) { + if(intFunc[EXTERNAL_INT_1]) + intFunc[EXTERNAL_INT_1](); +} + +#endif + +/* +SIGNAL(SIG_2WIRE_SERIAL) { + if(twiIntFunc) + twiIntFunc(); +} +*/ + diff --git a/Marlin/Sanguino/cores/arduino/WMath.cpp b/Marlin/Sanguino/cores/arduino/WMath.cpp new file mode 100644 index 0000000000..2120c4cc10 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/WMath.cpp @@ -0,0 +1,60 @@ +/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Wiring project - http://wiring.org.co + Copyright (c) 2004-06 Hernando Barragan + Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +extern "C" { + #include "stdlib.h" +} + +void randomSeed(unsigned int seed) +{ + if (seed != 0) { + srandom(seed); + } +} + +long random(long howbig) +{ + if (howbig == 0) { + return 0; + } + return random() % howbig; +} + +long random(long howsmall, long howbig) +{ + if (howsmall >= howbig) { + return howsmall; + } + long diff = howbig - howsmall; + return random(diff) + howsmall; +} + +long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +unsigned int makeWord(unsigned int w) { return w; } +unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } \ No newline at end of file diff --git a/Marlin/Sanguino/cores/arduino/WProgram.h b/Marlin/Sanguino/cores/arduino/WProgram.h new file mode 100644 index 0000000000..f73e760bbe --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/WProgram.h @@ -0,0 +1,63 @@ +#ifndef WProgram_h +#define WProgram_h + +#include +#include +#include + +#include + +#include "wiring.h" + +#ifdef __cplusplus +#include "WCharacter.h" +#include "WString.h" +#include "HardwareSerial.h" + +uint16_t makeWord(uint16_t w); +uint16_t makeWord(byte h, byte l); + +#define word(...) makeWord(__VA_ARGS__) + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); +void noTone(uint8_t _pin); + +// WMath prototypes +long random(long); +long random(long, long); +void randomSeed(unsigned int); +long map(long, long, long, long, long); + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +const static uint8_t A0 = 54; +const static uint8_t A1 = 55; +const static uint8_t A2 = 56; +const static uint8_t A3 = 57; +const static uint8_t A4 = 58; +const static uint8_t A5 = 59; +const static uint8_t A6 = 60; +const static uint8_t A7 = 61; +const static uint8_t A8 = 62; +const static uint8_t A9 = 63; +const static uint8_t A10 = 64; +const static uint8_t A11 = 65; +const static uint8_t A12 = 66; +const static uint8_t A13 = 67; +const static uint8_t A14 = 68; +const static uint8_t A15 = 69; +#else +const static uint8_t A0 = 14; +const static uint8_t A1 = 15; +const static uint8_t A2 = 16; +const static uint8_t A3 = 17; +const static uint8_t A4 = 18; +const static uint8_t A5 = 19; +const static uint8_t A6 = 20; +const static uint8_t A7 = 21; +#endif + +#endif + +#endif \ No newline at end of file diff --git a/Marlin/Sanguino/cores/arduino/WString.cpp b/Marlin/Sanguino/cores/arduino/WString.cpp new file mode 100644 index 0000000000..db5a441dc2 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/WString.cpp @@ -0,0 +1,443 @@ +/* + WString.cpp - String library for Wiring & Arduino + Copyright (c) 2009-10 Hernando Barragan. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "WProgram.h" +#include "WString.h" + + +String::String( const char *value ) +{ + if ( value == NULL ) + value = ""; + getBuffer( _length = strlen( value ) ); + if ( _buffer != NULL ) + strcpy( _buffer, value ); +} + +String::String( const String &value ) +{ + getBuffer( _length = value._length ); + if ( _buffer != NULL ) + strcpy( _buffer, value._buffer ); +} + +String::String( const char value ) +{ + _length = 1; + getBuffer(1); + if ( _buffer != NULL ) { + _buffer[0] = value; + _buffer[1] = 0; + } +} + +String::String( const unsigned char value ) +{ + _length = 1; + getBuffer(1); + if ( _buffer != NULL) { + _buffer[0] = value; + _buffer[1] = 0; + } +} + +String::String( const int value, const int base ) +{ + char buf[33]; + itoa((signed long)value, buf, base); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +String::String( const unsigned int value, const int base ) +{ + char buf[33]; + ultoa((unsigned long)value, buf, base); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +String::String( const long value, const int base ) +{ + char buf[33]; + ltoa(value, buf, base); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +String::String( const unsigned long value, const int base ) +{ + char buf[33]; + ultoa(value, buf, 10); + getBuffer( _length = strlen(buf) ); + if ( _buffer != NULL ) + strcpy( _buffer, buf ); +} + +char String::charAt( unsigned int loc ) const +{ + return operator[]( loc ); +} + +void String::setCharAt( unsigned int loc, const char aChar ) +{ + if(_buffer == NULL) return; + if(_length > loc) { + _buffer[loc] = aChar; + } +} + +int String::compareTo( const String &s2 ) const +{ + return strcmp( _buffer, s2._buffer ); +} + +const String & String::concat( const String &s2 ) +{ + return (*this) += s2; +} + +const String & String::operator=( const String &rhs ) +{ + if ( this == &rhs ) + return *this; + + if ( rhs._length > _length ) + { + free(_buffer); + getBuffer( rhs._length ); + } + + if ( _buffer != NULL ) { + _length = rhs._length; + strcpy( _buffer, rhs._buffer ); + } + return *this; +} + +//const String & String::operator+=( const char aChar ) +//{ +// if ( _length == _capacity ) +// doubleBuffer(); +// +// _buffer[ _length++ ] = aChar; +// _buffer[ _length ] = '\0'; +// return *this; +//} + +const String & String::operator+=( const String &other ) +{ + _length += other._length; + if ( _length > _capacity ) + { + char *temp = (char *)realloc(_buffer, _length + 1); + if ( temp != NULL ) { + _buffer = temp; + _capacity = _length; + } else { + _length -= other._length; + return *this; + } + } + strcat( _buffer, other._buffer ); + return *this; +} + + +int String::operator==( const String &rhs ) const +{ + return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 ); +} + +int String::operator!=( const String &rhs ) const +{ + return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 ); +} + +int String::operator<( const String &rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) < 0; +} + +int String::operator>( const String &rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) > 0; +} + +int String::operator<=( const String &rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) <= 0; +} + +int String::operator>=( const String & rhs ) const +{ + return strcmp( _buffer, rhs._buffer ) >= 0; +} + +char & String::operator[]( unsigned int index ) +{ + static char dummy_writable_char; + if (index >= _length || !_buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return _buffer[ index ]; +} + +char String::operator[]( unsigned int index ) const +{ + // need to check for valid index, to do later + return _buffer[ index ]; +} + +boolean String::endsWith( const String &s2 ) const +{ + if ( _length < s2._length ) + return 0; + + return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0; +} + +boolean String::equals( const String &s2 ) const +{ + return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 ); +} + +boolean String::equalsIgnoreCase( const String &s2 ) const +{ + if ( this == &s2 ) + return true; //1; + else if ( _length != s2._length ) + return false; //0; + + return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0; +} + +String String::replace( char findChar, char replaceChar ) +{ + if ( _buffer == NULL ) return *this; + String theReturn = _buffer; + char* temp = theReturn._buffer; + while( (temp = strchr( temp, findChar )) != 0 ) + *temp = replaceChar; + + return theReturn; +} + +String String::replace( const String& match, const String& replace ) +{ + if ( _buffer == NULL ) return *this; + String temp = _buffer, newString; + + int loc; + while ( (loc = temp.indexOf( match )) != -1 ) + { + newString += temp.substring( 0, loc ); + newString += replace; + temp = temp.substring( loc + match._length ); + } + newString += temp; + return newString; +} + +int String::indexOf( char temp ) const +{ + return indexOf( temp, 0 ); +} + +int String::indexOf( char ch, unsigned int fromIndex ) const +{ + if ( fromIndex >= _length ) + return -1; + + const char* temp = strchr( &_buffer[fromIndex], ch ); + if ( temp == NULL ) + return -1; + + return temp - _buffer; +} + +int String::indexOf( const String &s2 ) const +{ + return indexOf( s2, 0 ); +} + +int String::indexOf( const String &s2, unsigned int fromIndex ) const +{ + if ( fromIndex >= _length ) + return -1; + + const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer ); + + if ( theFind == NULL ) + return -1; + + return theFind - _buffer; // pointer subtraction +} + +int String::lastIndexOf( char theChar ) const +{ + return lastIndexOf( theChar, _length - 1 ); +} + +int String::lastIndexOf( char ch, unsigned int fromIndex ) const +{ + if ( fromIndex >= _length ) + return -1; + + char tempchar = _buffer[fromIndex + 1]; + _buffer[fromIndex + 1] = '\0'; + char* temp = strrchr( _buffer, ch ); + _buffer[fromIndex + 1] = tempchar; + + if ( temp == NULL ) + return -1; + + return temp - _buffer; +} + +int String::lastIndexOf( const String &s2 ) const +{ + return lastIndexOf( s2, _length - s2._length ); +} + +int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const +{ + // check for empty strings + if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length ) + return -1; + + // matching first character + char temp = s2[ 0 ]; + + for ( int i = fromIndex; i >= 0; i-- ) + { + if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) ) + return i; + } + return -1; +} + +boolean String::startsWith( const String &s2 ) const +{ + if ( _length < s2._length ) + return 0; + + return startsWith( s2, 0 ); +} + +boolean String::startsWith( const String &s2, unsigned int offset ) const +{ + if ( offset > _length - s2._length ) + return 0; + + return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0; +} + +String String::substring( unsigned int left ) const +{ + return substring( left, _length ); +} + +String String::substring( unsigned int left, unsigned int right ) const +{ + if ( left > right ) + { + int temp = right; + right = left; + left = temp; + } + + if ( right > _length ) + { + right = _length; + } + + char temp = _buffer[ right ]; // save the replaced character + _buffer[ right ] = '\0'; + String outPut = ( _buffer + left ); // pointer arithmetic + _buffer[ right ] = temp; //restore character + return outPut; +} + +String String::toLowerCase() const +{ + String temp = _buffer; + + for ( unsigned int i = 0; i < _length; i++ ) + temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] ); + return temp; +} + +String String::toUpperCase() const +{ + String temp = _buffer; + + for ( unsigned int i = 0; i < _length; i++ ) + temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] ); + return temp; +} + +String String::trim() const +{ + if ( _buffer == NULL ) return *this; + String temp = _buffer; + unsigned int i,j; + + for ( i = 0; i < _length; i++ ) + { + if ( !isspace(_buffer[i]) ) + break; + } + + for ( j = temp._length - 1; j > i; j-- ) + { + if ( !isspace(_buffer[j]) ) + break; + } + + return temp.substring( i, j + 1); +} + +void String::getBytes(unsigned char *buf, unsigned int bufsize) +{ + if (!bufsize || !buf) return; + unsigned int len = bufsize - 1; + if (len > _length) len = _length; + strncpy((char *)buf, _buffer, len); + buf[len] = 0; +} + +void String::toCharArray(char *buf, unsigned int bufsize) +{ + if (!bufsize || !buf) return; + unsigned int len = bufsize - 1; + if (len > _length) len = _length; + strncpy(buf, _buffer, len); + buf[len] = 0; +} + + +long String::toInt() { + return atol(_buffer); +} diff --git a/Marlin/Sanguino/cores/arduino/WString.h b/Marlin/Sanguino/cores/arduino/WString.h new file mode 100644 index 0000000000..cadddb9476 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/WString.h @@ -0,0 +1,112 @@ +/* + WString.h - String library for Wiring & Arduino + Copyright (c) 2009-10 Hernando Barragan. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef String_h +#define String_h + +//#include "WProgram.h" +#include +#include +#include + +class String +{ + public: + // constructors + String( const char *value = "" ); + String( const String &value ); + String( const char ); + String( const unsigned char ); + String( const int, const int base=10); + String( const unsigned int, const int base=10 ); + String( const long, const int base=10 ); + String( const unsigned long, const int base=10 ); + ~String() { free(_buffer); _length = _capacity = 0;} //added _length = _capacity = 0; + + // operators + const String & operator = ( const String &rhs ); + const String & operator +=( const String &rhs ); + //const String & operator +=( const char ); + int operator ==( const String &rhs ) const; + int operator !=( const String &rhs ) const; + int operator < ( const String &rhs ) const; + int operator > ( const String &rhs ) const; + int operator <=( const String &rhs ) const; + int operator >=( const String &rhs ) const; + char operator []( unsigned int index ) const; + char& operator []( unsigned int index ); + //operator const char *() const { return _buffer; } + + // general methods + char charAt( unsigned int index ) const; + int compareTo( const String &anotherString ) const; + unsigned char endsWith( const String &suffix ) const; + unsigned char equals( const String &anObject ) const; + unsigned char equalsIgnoreCase( const String &anotherString ) const; + int indexOf( char ch ) const; + int indexOf( char ch, unsigned int fromIndex ) const; + int indexOf( const String &str ) const; + int indexOf( const String &str, unsigned int fromIndex ) const; + int lastIndexOf( char ch ) const; + int lastIndexOf( char ch, unsigned int fromIndex ) const; + int lastIndexOf( const String &str ) const; + int lastIndexOf( const String &str, unsigned int fromIndex ) const; + const unsigned int length( ) const { return _length; } + void setCharAt(unsigned int index, const char ch); + unsigned char startsWith( const String &prefix ) const; + unsigned char startsWith( const String &prefix, unsigned int toffset ) const; + String substring( unsigned int beginIndex ) const; + String substring( unsigned int beginIndex, unsigned int endIndex ) const; + String toLowerCase( ) const; + String toUpperCase( ) const; + String trim( ) const; + void getBytes(unsigned char *buf, unsigned int bufsize); + void toCharArray(char *buf, unsigned int bufsize); + long toInt( ); + const String& concat( const String &str ); + String replace( char oldChar, char newChar ); + String replace( const String& match, const String& replace ); + friend String operator + ( String lhs, const String &rhs ); + + protected: + char *_buffer; // the actual char array + unsigned int _capacity; // the array length minus one (for the '\0') + unsigned int _length; // the String length (not counting the '\0') + + void getBuffer(unsigned int maxStrLen); + + private: + +}; + +// allocate buffer space +inline void String::getBuffer(unsigned int maxStrLen) +{ + _capacity = maxStrLen; + _buffer = (char *) malloc(_capacity + 1); + if (_buffer == NULL) _length = _capacity = 0; +} + +inline String operator+( String lhs, const String &rhs ) +{ + return lhs += rhs; +} + + +#endif diff --git a/Marlin/Sanguino/cores/arduino/binary.h b/Marlin/Sanguino/cores/arduino/binary.h new file mode 100644 index 0000000000..af1498033a --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/binary.h @@ -0,0 +1,515 @@ +#ifndef Binary_h +#define Binary_h + +#define B0 0 +#define B00 0 +#define B000 0 +#define B0000 0 +#define B00000 0 +#define B000000 0 +#define B0000000 0 +#define B00000000 0 +#define B1 1 +#define B01 1 +#define B001 1 +#define B0001 1 +#define B00001 1 +#define B000001 1 +#define B0000001 1 +#define B00000001 1 +#define B10 2 +#define B010 2 +#define B0010 2 +#define B00010 2 +#define B000010 2 +#define B0000010 2 +#define B00000010 2 +#define B11 3 +#define B011 3 +#define B0011 3 +#define B00011 3 +#define B000011 3 +#define B0000011 3 +#define B00000011 3 +#define B100 4 +#define B0100 4 +#define B00100 4 +#define B000100 4 +#define B0000100 4 +#define B00000100 4 +#define B101 5 +#define B0101 5 +#define B00101 5 +#define B000101 5 +#define B0000101 5 +#define B00000101 5 +#define B110 6 +#define B0110 6 +#define B00110 6 +#define B000110 6 +#define B0000110 6 +#define B00000110 6 +#define B111 7 +#define B0111 7 +#define B00111 7 +#define B000111 7 +#define B0000111 7 +#define B00000111 7 +#define B1000 8 +#define B01000 8 +#define B001000 8 +#define B0001000 8 +#define B00001000 8 +#define B1001 9 +#define B01001 9 +#define B001001 9 +#define B0001001 9 +#define B00001001 9 +#define B1010 10 +#define B01010 10 +#define B001010 10 +#define B0001010 10 +#define B00001010 10 +#define B1011 11 +#define B01011 11 +#define B001011 11 +#define B0001011 11 +#define B00001011 11 +#define B1100 12 +#define B01100 12 +#define B001100 12 +#define B0001100 12 +#define B00001100 12 +#define B1101 13 +#define B01101 13 +#define B001101 13 +#define B0001101 13 +#define B00001101 13 +#define B1110 14 +#define B01110 14 +#define B001110 14 +#define B0001110 14 +#define B00001110 14 +#define B1111 15 +#define B01111 15 +#define B001111 15 +#define B0001111 15 +#define B00001111 15 +#define B10000 16 +#define B010000 16 +#define B0010000 16 +#define B00010000 16 +#define B10001 17 +#define B010001 17 +#define B0010001 17 +#define B00010001 17 +#define B10010 18 +#define B010010 18 +#define B0010010 18 +#define B00010010 18 +#define B10011 19 +#define B010011 19 +#define B0010011 19 +#define B00010011 19 +#define B10100 20 +#define B010100 20 +#define B0010100 20 +#define B00010100 20 +#define B10101 21 +#define B010101 21 +#define B0010101 21 +#define B00010101 21 +#define B10110 22 +#define B010110 22 +#define B0010110 22 +#define B00010110 22 +#define B10111 23 +#define B010111 23 +#define B0010111 23 +#define B00010111 23 +#define B11000 24 +#define B011000 24 +#define B0011000 24 +#define B00011000 24 +#define B11001 25 +#define B011001 25 +#define B0011001 25 +#define B00011001 25 +#define B11010 26 +#define B011010 26 +#define B0011010 26 +#define B00011010 26 +#define B11011 27 +#define B011011 27 +#define B0011011 27 +#define B00011011 27 +#define B11100 28 +#define B011100 28 +#define B0011100 28 +#define B00011100 28 +#define B11101 29 +#define B011101 29 +#define B0011101 29 +#define B00011101 29 +#define B11110 30 +#define B011110 30 +#define B0011110 30 +#define B00011110 30 +#define B11111 31 +#define B011111 31 +#define B0011111 31 +#define B00011111 31 +#define B100000 32 +#define B0100000 32 +#define B00100000 32 +#define B100001 33 +#define B0100001 33 +#define B00100001 33 +#define B100010 34 +#define B0100010 34 +#define B00100010 34 +#define B100011 35 +#define B0100011 35 +#define B00100011 35 +#define B100100 36 +#define B0100100 36 +#define B00100100 36 +#define B100101 37 +#define B0100101 37 +#define B00100101 37 +#define B100110 38 +#define B0100110 38 +#define B00100110 38 +#define B100111 39 +#define B0100111 39 +#define B00100111 39 +#define B101000 40 +#define B0101000 40 +#define B00101000 40 +#define B101001 41 +#define B0101001 41 +#define B00101001 41 +#define B101010 42 +#define B0101010 42 +#define B00101010 42 +#define B101011 43 +#define B0101011 43 +#define B00101011 43 +#define B101100 44 +#define B0101100 44 +#define B00101100 44 +#define B101101 45 +#define B0101101 45 +#define B00101101 45 +#define B101110 46 +#define B0101110 46 +#define B00101110 46 +#define B101111 47 +#define B0101111 47 +#define B00101111 47 +#define B110000 48 +#define B0110000 48 +#define B00110000 48 +#define B110001 49 +#define B0110001 49 +#define B00110001 49 +#define B110010 50 +#define B0110010 50 +#define B00110010 50 +#define B110011 51 +#define B0110011 51 +#define B00110011 51 +#define B110100 52 +#define B0110100 52 +#define B00110100 52 +#define B110101 53 +#define B0110101 53 +#define B00110101 53 +#define B110110 54 +#define B0110110 54 +#define B00110110 54 +#define B110111 55 +#define B0110111 55 +#define B00110111 55 +#define B111000 56 +#define B0111000 56 +#define B00111000 56 +#define B111001 57 +#define B0111001 57 +#define B00111001 57 +#define B111010 58 +#define B0111010 58 +#define B00111010 58 +#define B111011 59 +#define B0111011 59 +#define B00111011 59 +#define B111100 60 +#define B0111100 60 +#define B00111100 60 +#define B111101 61 +#define B0111101 61 +#define B00111101 61 +#define B111110 62 +#define B0111110 62 +#define B00111110 62 +#define B111111 63 +#define B0111111 63 +#define B00111111 63 +#define B1000000 64 +#define B01000000 64 +#define B1000001 65 +#define B01000001 65 +#define B1000010 66 +#define B01000010 66 +#define B1000011 67 +#define B01000011 67 +#define B1000100 68 +#define B01000100 68 +#define B1000101 69 +#define B01000101 69 +#define B1000110 70 +#define B01000110 70 +#define B1000111 71 +#define B01000111 71 +#define B1001000 72 +#define B01001000 72 +#define B1001001 73 +#define B01001001 73 +#define B1001010 74 +#define B01001010 74 +#define B1001011 75 +#define B01001011 75 +#define B1001100 76 +#define B01001100 76 +#define B1001101 77 +#define B01001101 77 +#define B1001110 78 +#define B01001110 78 +#define B1001111 79 +#define B01001111 79 +#define B1010000 80 +#define B01010000 80 +#define B1010001 81 +#define B01010001 81 +#define B1010010 82 +#define B01010010 82 +#define B1010011 83 +#define B01010011 83 +#define B1010100 84 +#define B01010100 84 +#define B1010101 85 +#define B01010101 85 +#define B1010110 86 +#define B01010110 86 +#define B1010111 87 +#define B01010111 87 +#define B1011000 88 +#define B01011000 88 +#define B1011001 89 +#define B01011001 89 +#define B1011010 90 +#define B01011010 90 +#define B1011011 91 +#define B01011011 91 +#define B1011100 92 +#define B01011100 92 +#define B1011101 93 +#define B01011101 93 +#define B1011110 94 +#define B01011110 94 +#define B1011111 95 +#define B01011111 95 +#define B1100000 96 +#define B01100000 96 +#define B1100001 97 +#define B01100001 97 +#define B1100010 98 +#define B01100010 98 +#define B1100011 99 +#define B01100011 99 +#define B1100100 100 +#define B01100100 100 +#define B1100101 101 +#define B01100101 101 +#define B1100110 102 +#define B01100110 102 +#define B1100111 103 +#define B01100111 103 +#define B1101000 104 +#define B01101000 104 +#define B1101001 105 +#define B01101001 105 +#define B1101010 106 +#define B01101010 106 +#define B1101011 107 +#define B01101011 107 +#define B1101100 108 +#define B01101100 108 +#define B1101101 109 +#define B01101101 109 +#define B1101110 110 +#define B01101110 110 +#define B1101111 111 +#define B01101111 111 +#define B1110000 112 +#define B01110000 112 +#define B1110001 113 +#define B01110001 113 +#define B1110010 114 +#define B01110010 114 +#define B1110011 115 +#define B01110011 115 +#define B1110100 116 +#define B01110100 116 +#define B1110101 117 +#define B01110101 117 +#define B1110110 118 +#define B01110110 118 +#define B1110111 119 +#define B01110111 119 +#define B1111000 120 +#define B01111000 120 +#define B1111001 121 +#define B01111001 121 +#define B1111010 122 +#define B01111010 122 +#define B1111011 123 +#define B01111011 123 +#define B1111100 124 +#define B01111100 124 +#define B1111101 125 +#define B01111101 125 +#define B1111110 126 +#define B01111110 126 +#define B1111111 127 +#define B01111111 127 +#define B10000000 128 +#define B10000001 129 +#define B10000010 130 +#define B10000011 131 +#define B10000100 132 +#define B10000101 133 +#define B10000110 134 +#define B10000111 135 +#define B10001000 136 +#define B10001001 137 +#define B10001010 138 +#define B10001011 139 +#define B10001100 140 +#define B10001101 141 +#define B10001110 142 +#define B10001111 143 +#define B10010000 144 +#define B10010001 145 +#define B10010010 146 +#define B10010011 147 +#define B10010100 148 +#define B10010101 149 +#define B10010110 150 +#define B10010111 151 +#define B10011000 152 +#define B10011001 153 +#define B10011010 154 +#define B10011011 155 +#define B10011100 156 +#define B10011101 157 +#define B10011110 158 +#define B10011111 159 +#define B10100000 160 +#define B10100001 161 +#define B10100010 162 +#define B10100011 163 +#define B10100100 164 +#define B10100101 165 +#define B10100110 166 +#define B10100111 167 +#define B10101000 168 +#define B10101001 169 +#define B10101010 170 +#define B10101011 171 +#define B10101100 172 +#define B10101101 173 +#define B10101110 174 +#define B10101111 175 +#define B10110000 176 +#define B10110001 177 +#define B10110010 178 +#define B10110011 179 +#define B10110100 180 +#define B10110101 181 +#define B10110110 182 +#define B10110111 183 +#define B10111000 184 +#define B10111001 185 +#define B10111010 186 +#define B10111011 187 +#define B10111100 188 +#define B10111101 189 +#define B10111110 190 +#define B10111111 191 +#define B11000000 192 +#define B11000001 193 +#define B11000010 194 +#define B11000011 195 +#define B11000100 196 +#define B11000101 197 +#define B11000110 198 +#define B11000111 199 +#define B11001000 200 +#define B11001001 201 +#define B11001010 202 +#define B11001011 203 +#define B11001100 204 +#define B11001101 205 +#define B11001110 206 +#define B11001111 207 +#define B11010000 208 +#define B11010001 209 +#define B11010010 210 +#define B11010011 211 +#define B11010100 212 +#define B11010101 213 +#define B11010110 214 +#define B11010111 215 +#define B11011000 216 +#define B11011001 217 +#define B11011010 218 +#define B11011011 219 +#define B11011100 220 +#define B11011101 221 +#define B11011110 222 +#define B11011111 223 +#define B11100000 224 +#define B11100001 225 +#define B11100010 226 +#define B11100011 227 +#define B11100100 228 +#define B11100101 229 +#define B11100110 230 +#define B11100111 231 +#define B11101000 232 +#define B11101001 233 +#define B11101010 234 +#define B11101011 235 +#define B11101100 236 +#define B11101101 237 +#define B11101110 238 +#define B11101111 239 +#define B11110000 240 +#define B11110001 241 +#define B11110010 242 +#define B11110011 243 +#define B11110100 244 +#define B11110101 245 +#define B11110110 246 +#define B11110111 247 +#define B11111000 248 +#define B11111001 249 +#define B11111010 250 +#define B11111011 251 +#define B11111100 252 +#define B11111101 253 +#define B11111110 254 +#define B11111111 255 + +#endif diff --git a/Marlin/Sanguino/cores/arduino/main.cpp b/Marlin/Sanguino/cores/arduino/main.cpp new file mode 100644 index 0000000000..cc6e81d906 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/main.cpp @@ -0,0 +1,14 @@ +#include + +int main(void) +{ + init(); + + setup(); + + for (;;) + loop(); + + return 0; +} + diff --git a/Marlin/Sanguino/cores/arduino/pins_arduino.c b/Marlin/Sanguino/cores/arduino/pins_arduino.c new file mode 100644 index 0000000000..ccb88fe989 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/pins_arduino.c @@ -0,0 +1,200 @@ +/* + pins_arduino.c - pin definitions for the Arduino board + Part of Arduino / Wiring Lite + + Copyright (c) 2005 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: pins_arduino.c 254 2007-04-20 23:17:38Z mellis $ +*/ + +#include +#include "wiring_private.h" +#include "pins_arduino.h" + +// On the Sanguino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ATMEL ATMEGA644P / SANGUINO +// +// +---\/---+ +// INT0 (D 0) PB0 1| |40 PA0 (AI 0 / D31) +// INT1 (D 1) PB1 2| |39 PA1 (AI 1 / D30) +// INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +// PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +// PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +// MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +// MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +// SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +// RST 9| |32 AREF +// VCC 10| |31 GND +// GND 11| |30 AVCC +// XTAL2 12| |29 PC7 (D 23) +// XTAL1 13| |28 PC6 (D 22) +// RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +// TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +// RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +// TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +// PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +// PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +// PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +// +--------+ +// + +#define PA 1 +#define PB 2 +#define PC 3 +#define PD 4 + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint8_t PROGMEM port_to_mode_PGM[] = +{ + NOT_A_PORT, + &DDRA, + &DDRB, + &DDRC, + &DDRD, +}; + +const uint8_t PROGMEM port_to_output_PGM[] = +{ + NOT_A_PORT, + &PORTA, + &PORTB, + &PORTC, + &PORTD, +}; + +const uint8_t PROGMEM port_to_input_PGM[] = +{ + NOT_A_PORT, + &PINA, + &PINB, + &PINC, + &PIND, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = +{ + PB, /* 0 */ + PB, + PB, + PB, + PB, + PB, + PB, + PB, + PD, /* 8 */ + PD, + PD, + PD, + PD, + PD, + PD, + PD, + PC, /* 16 */ + PC, + PC, + PC, + PC, + PC, + PC, + PC, + PA, /* 24 */ + PA, + PA, + PA, + PA, + PA, + PA, + PA /* 31 */ +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = +{ + _BV(0), /* 0, port B */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(0), /* 8, port D */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(0), /* 16, port C */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(7), /* 24, port A */ + _BV(6), + _BV(5), + _BV(4), + _BV(3), + _BV(2), + _BV(1), + _BV(0) +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = +{ + NOT_ON_TIMER, /* 0 - PB0 */ + NOT_ON_TIMER, /* 1 - PB1 */ + NOT_ON_TIMER, /* 2 - PB2 */ + TIMER0A, /* 3 - PB3 */ + TIMER0B, /* 4 - PB4 */ + NOT_ON_TIMER, /* 5 - PB5 */ + NOT_ON_TIMER, /* 6 - PB6 */ + NOT_ON_TIMER, /* 7 - PB7 */ + NOT_ON_TIMER, /* 8 - PD0 */ + NOT_ON_TIMER, /* 9 - PD1 */ + NOT_ON_TIMER, /* 10 - PD2 */ + NOT_ON_TIMER, /* 11 - PD3 */ + TIMER1B, /* 12 - PD4 */ + TIMER1A, /* 13 - PD5 */ + TIMER2B, /* 14 - PD6 */ + TIMER2A, /* 15 - PD7 */ + NOT_ON_TIMER, /* 16 - PC0 */ + NOT_ON_TIMER, /* 17 - PC1 */ + NOT_ON_TIMER, /* 18 - PC2 */ + NOT_ON_TIMER, /* 19 - PC3 */ + NOT_ON_TIMER, /* 20 - PC4 */ + NOT_ON_TIMER, /* 21 - PC5 */ + NOT_ON_TIMER, /* 22 - PC6 */ + NOT_ON_TIMER, /* 23 - PC7 */ + NOT_ON_TIMER, /* 24 - PA0 */ + NOT_ON_TIMER, /* 25 - PA1 */ + NOT_ON_TIMER, /* 26 - PA2 */ + NOT_ON_TIMER, /* 27 - PA3 */ + NOT_ON_TIMER, /* 28 - PA4 */ + NOT_ON_TIMER, /* 29 - PA5 */ + NOT_ON_TIMER, /* 30 - PA6 */ + NOT_ON_TIMER /* 31 - PA7 */ +}; diff --git a/Marlin/Sanguino/cores/arduino/pins_arduino.h b/Marlin/Sanguino/cores/arduino/pins_arduino.h new file mode 100644 index 0000000000..e0b7add867 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/pins_arduino.h @@ -0,0 +1,65 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define NOT_A_PIN 0 +#define NOT_A_PORT 0 + +#define NOT_ON_TIMER 0 +#define TIMER0A 1 +#define TIMER0B 2 +#define TIMER1A 3 +#define TIMER1B 4 +#define TIMER2 5 +#define TIMER2A 6 +#define TIMER2B 7 + +extern const uint8_t PROGMEM port_to_mode_PGM[]; +extern const uint8_t PROGMEM port_to_input_PGM[]; +extern const uint8_t PROGMEM port_to_output_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. +// +// These perform slightly better as macros compared to inline functions +// +#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) +#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) +#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) +#define analogInPinToBit(P) (P) +#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_output_PGM + (P))) ) +#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_input_PGM + (P))) ) +#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_mode_PGM + (P))) ) + +#endif diff --git a/Marlin/Sanguino/cores/arduino/wiring.c b/Marlin/Sanguino/cores/arduino/wiring.c new file mode 100644 index 0000000000..b90d07e592 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/wiring.c @@ -0,0 +1,289 @@ +/* + wiring.c - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +#include "wiring_private.h" + +// the prescaler is set so that timer0 ticks every 64 clock cycles, and the +// the overflow handler is called every 256 ticks. +#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) + +// the whole number of milliseconds per timer0 overflow +#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) + +// the fractional number of milliseconds per timer0 overflow. we shift right +// by three to fit these numbers into a byte. (for the clock speeds we care +// about - 8 and 16 MHz - this doesn't lose precision.) +#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) +#define FRACT_MAX (1000 >> 3) + +volatile unsigned long timer0_overflow_count = 0; +volatile unsigned long timer0_millis = 0; +static unsigned char timer0_fract = 0; + +SIGNAL(TIMER0_OVF_vect) +{ + // copy these to local variables so they can be stored in registers + // (volatile variables must be read from memory on every access) + unsigned long m = timer0_millis; + unsigned char f = timer0_fract; + + m += MILLIS_INC; + f += FRACT_INC; + if (f >= FRACT_MAX) { + f -= FRACT_MAX; + m += 1; + } + + timer0_fract = f; + timer0_millis = m; + timer0_overflow_count++; +} + +unsigned long millis() +{ + unsigned long m; + uint8_t oldSREG = SREG; + + // disable interrupts while we read timer0_millis or we might get an + // inconsistent value (e.g. in the middle of a write to timer0_millis) + cli(); + m = timer0_millis; + SREG = oldSREG; + + return m; +} + +unsigned long micros() { + unsigned long m; + uint8_t oldSREG = SREG, t; + + cli(); + m = timer0_overflow_count; +#if defined(TCNT0) + t = TCNT0; +#elif defined(TCNT0L) + t = TCNT0L; +#else + #error TIMER 0 not defined +#endif + + +#ifdef TIFR0 + if ((TIFR0 & _BV(TOV0)) && (t < 255)) + m++; +#else + if ((TIFR & _BV(TOV0)) && (t < 255)) + m++; +#endif + + SREG = oldSREG; + + return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); +} + +void delay(unsigned long ms) +{ + uint16_t start = (uint16_t)micros(); + + while (ms > 0) { + if (((uint16_t)micros() - start) >= 1000) { + ms--; + start += 1000; + } + } +} + +/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ +void delayMicroseconds(unsigned int us) +{ + // calling avrlib's delay_us() function with low values (e.g. 1 or + // 2 microseconds) gives delays longer than desired. + //delay_us(us); + +#if F_CPU >= 16000000L + // for the 16 MHz clock on most Arduino boards + + // for a one-microsecond delay, simply return. the overhead + // of the function call yields a delay of approximately 1 1/8 us. + if (--us == 0) + return; + + // the following loop takes a quarter of a microsecond (4 cycles) + // per iteration, so execute it four times for each microsecond of + // delay requested. + us <<= 2; + + // account for the time taken in the preceeding commands. + us -= 2; +#else + // for the 8 MHz internal clock on the ATmega168 + + // for a one- or two-microsecond delay, simply return. the overhead of + // the function calls takes more than two microseconds. can't just + // subtract two, since us is unsigned; we'd overflow. + if (--us == 0) + return; + if (--us == 0) + return; + + // the following loop takes half of a microsecond (4 cycles) + // per iteration, so execute it twice for each microsecond of + // delay requested. + us <<= 1; + + // partially compensate for the time taken by the preceeding commands. + // we can't subtract any more than this or we'd overflow w/ small delays. + us--; +#endif + + // busy wait + __asm__ __volatile__ ( + "1: sbiw %0,1" "\n\t" // 2 cycles + "brne 1b" : "=w" (us) : "0" (us) // 2 cycles + ); +} + +void init() +{ + // this needs to be called before setup() or some functions won't + // work there + sei(); + + // on the ATmega168, timer 0 is also used for fast hardware pwm + // (using phase-correct PWM would mean that timer 0 overflowed half as often + // resulting in different millis() behavior on the ATmega8 and ATmega168) +#if defined(TCCR0A) && defined(WGM01) + sbi(TCCR0A, WGM01); + sbi(TCCR0A, WGM00); +#endif + + // set timer 0 prescale factor to 64 +#if defined(__AVR_ATmega128__) + // CPU specific: different values for the ATmega128 + sbi(TCCR0, CS02); +#elif defined(TCCR0) && defined(CS01) && defined(CS00) + // this combination is for the standard atmega8 + sbi(TCCR0, CS01); + sbi(TCCR0, CS00); +#elif defined(TCCR0B) && defined(CS01) && defined(CS00) + // this combination is for the standard 168/328/1280/2560 + sbi(TCCR0B, CS01); + sbi(TCCR0B, CS00); +#elif defined(TCCR0A) && defined(CS01) && defined(CS00) + // this combination is for the __AVR_ATmega645__ series + sbi(TCCR0A, CS01); + sbi(TCCR0A, CS00); +#else + #error Timer 0 prescale factor 64 not set correctly +#endif + + // enable timer 0 overflow interrupt +#if defined(TIMSK) && defined(TOIE0) + sbi(TIMSK, TOIE0); +#elif defined(TIMSK0) && defined(TOIE0) + sbi(TIMSK0, TOIE0); +#else + #error Timer 0 overflow interrupt not set correctly +#endif + + // timers 1 and 2 are used for phase-correct hardware pwm + // this is better for motors as it ensures an even waveform + // note, however, that fast pwm mode can achieve a frequency of up + // 8 MHz (with a 16 MHz clock) at 50% duty cycle + + TCCR1B = 0; + + // set timer 1 prescale factor to 64 +#if defined(TCCR1B) && defined(CS11) && defined(CS10) + sbi(TCCR1B, CS11); + sbi(TCCR1B, CS10); +#elif defined(TCCR1) && defined(CS11) && defined(CS10) + sbi(TCCR1, CS11); + sbi(TCCR1, CS10); +#endif + // put timer 1 in 8-bit phase correct pwm mode +#if defined(TCCR1A) && defined(WGM10) + sbi(TCCR1A, WGM10); +#elif defined(TCCR1) + #warning this needs to be finished +#endif + + // set timer 2 prescale factor to 64 +#if defined(TCCR2) && defined(CS22) + sbi(TCCR2, CS22); +#elif defined(TCCR2B) && defined(CS22) + sbi(TCCR2B, CS22); +#else + #warning Timer 2 not finished (may not be present on this CPU) +#endif + + // configure timer 2 for phase correct pwm (8-bit) +#if defined(TCCR2) && defined(WGM20) + sbi(TCCR2, WGM20); +#elif defined(TCCR2A) && defined(WGM20) + sbi(TCCR2A, WGM20); +#else + #warning Timer 2 not finished (may not be present on this CPU) +#endif + +#if defined(TCCR3B) && defined(CS31) && defined(WGM30) + sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64 + sbi(TCCR3B, CS30); + sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode +#endif + +#if defined(TCCR4B) && defined(CS41) && defined(WGM40) + sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64 + sbi(TCCR4B, CS40); + sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode +#endif + +#if defined(TCCR5B) && defined(CS51) && defined(WGM50) + sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64 + sbi(TCCR5B, CS50); + sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode +#endif + +#if defined(ADCSRA) + // set a2d prescale factor to 128 + // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. + // XXX: this will not work properly for other clock speeds, and + // this code should use F_CPU to determine the prescale factor. + sbi(ADCSRA, ADPS2); + sbi(ADCSRA, ADPS1); + sbi(ADCSRA, ADPS0); + + // enable a2d conversions + sbi(ADCSRA, ADEN); +#endif + + // the bootloader connects pins 0 and 1 to the USART; disconnect them + // here so they can be used as normal digital i/o; they will be + // reconnected in Serial.begin() +#if defined(UCSRB) + UCSRB = 0; +#elif defined(UCSR0B) + UCSR0B = 0; +#endif +} diff --git a/Marlin/Sanguino/cores/arduino/wiring.h b/Marlin/Sanguino/cores/arduino/wiring.h new file mode 100644 index 0000000000..e29959b865 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/wiring.h @@ -0,0 +1,135 @@ +/* + wiring.h - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +#ifndef Wiring_h +#define Wiring_h + +#include +#include +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 + +#define true 0x1 +#define false 0x0 + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define INTERNAL1V1 2 +#define INTERNAL2V56 3 +#else +#define INTERNAL 3 +#endif +#define DEFAULT 1 +#define EXTERNAL 0 + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() sei() +#define noInterrupts() cli() + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) +#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogReference(uint8_t mode); +void analogWrite(uint8_t, int); + +unsigned long millis(void); +unsigned long micros(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int us); +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +void loop(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/Marlin/Sanguino/cores/arduino/wiring_analog.c b/Marlin/Sanguino/cores/arduino/wiring_analog.c new file mode 100644 index 0000000000..d248f4ce82 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/wiring_analog.c @@ -0,0 +1,259 @@ +/* + wiring_analog.c - analog input and output + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 28 September 2010 by Mark Sproul + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +uint8_t analog_reference = DEFAULT; + +void analogReference(uint8_t mode) +{ + // can't actually set the register here because the default setting + // will connect AVCC and the AREF pin, which would cause a short if + // there's something connected to AREF. + analog_reference = mode; +} + +int analogRead(uint8_t pin) +{ + uint8_t low, high; + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + if (pin >= 54) pin -= 54; // allow for channel or pin numbers +#else + if (pin >= 14) pin -= 14; // allow for channel or pin numbers +#endif + +#if defined(ADCSRB) && defined(MUX5) + // the MUX5 bit of ADCSRB selects whether we're reading from channels + // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high). + ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); +#endif + + // set the analog reference (high two bits of ADMUX) and select the + // channel (low 4 bits). this also sets ADLAR (left-adjust result) + // to 0 (the default). +#if defined(ADMUX) + ADMUX = (analog_reference << 6) | (pin & 0x07); +#endif + + // without a delay, we seem to read from the wrong channel + //delay(1); + +#if defined(ADCSRA) && defined(ADCL) + // start the conversion + sbi(ADCSRA, ADSC); + + // ADSC is cleared when the conversion finishes + while (bit_is_set(ADCSRA, ADSC)); + + // we have to read ADCL first; doing so locks both ADCL + // and ADCH until ADCH is read. reading ADCL second would + // cause the results of each conversion to be discarded, + // as ADCL and ADCH would be locked when it completed. + low = ADCL; + high = ADCH; +#else + // we dont have an ADC, return 0 + low = 0; + high = 0; +#endif + + // combine the two bytes + return (high << 8) | low; +} + +// Right now, PWM output only works on the pins with +// hardware support. These are defined in the appropriate +// pins_*.c file. For the rest of the pins, we default +// to digital output. +void analogWrite(uint8_t pin, int val) +{ + // We need to make sure the PWM output is enabled for those pins + // that support it, as we turn it off when digitally reading or + // writing with them. Also, make sure the pin is in output mode + // for consistenty with Wiring, which doesn't require a pinMode + // call for the analog output pins. + pinMode(pin, OUTPUT); + if (val == 0) + { + digitalWrite(pin, LOW); + } + else if (val == 255) + { + digitalWrite(pin, HIGH); + } + else + { + switch(digitalPinToTimer(pin)) + { + // XXX fix needed for atmega8 + #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__) + case TIMER0A: + // connect pwm to pin on timer 0 + sbi(TCCR0, COM00); + OCR0 = val; // set pwm duty + break; + #endif + + #if defined(TCCR0A) && defined(COM0A1) + case TIMER0A: + // connect pwm to pin on timer 0, channel A + sbi(TCCR0A, COM0A1); + OCR0A = val; // set pwm duty + break; + #endif + + #if defined(TCCR0A) && defined(COM0B1) + case TIMER0B: + // connect pwm to pin on timer 0, channel B + sbi(TCCR0A, COM0B1); + OCR0B = val; // set pwm duty + break; + #endif + + #if defined(TCCR1A) && defined(COM1A1) + case TIMER1A: + // connect pwm to pin on timer 1, channel A + sbi(TCCR1A, COM1A1); + OCR1A = val; // set pwm duty + break; + #endif + + #if defined(TCCR1A) && defined(COM1B1) + case TIMER1B: + // connect pwm to pin on timer 1, channel B + sbi(TCCR1A, COM1B1); + OCR1B = val; // set pwm duty + break; + #endif + + #if defined(TCCR2) && defined(COM21) + case TIMER2: + // connect pwm to pin on timer 2 + sbi(TCCR2, COM21); + OCR2 = val; // set pwm duty + break; + #endif + + #if defined(TCCR2A) && defined(COM2A1) + case TIMER2A: + // connect pwm to pin on timer 2, channel A + sbi(TCCR2A, COM2A1); + OCR2A = val; // set pwm duty + break; + #endif + + #if defined(TCCR2A) && defined(COM2B1) + case TIMER2B: + // connect pwm to pin on timer 2, channel B + sbi(TCCR2A, COM2B1); + OCR2B = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3A1) + case TIMER3A: + // connect pwm to pin on timer 3, channel A + sbi(TCCR3A, COM3A1); + OCR3A = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3B1) + case TIMER3B: + // connect pwm to pin on timer 3, channel B + sbi(TCCR3A, COM3B1); + OCR3B = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3C1) + case TIMER3C: + // connect pwm to pin on timer 3, channel C + sbi(TCCR3A, COM3C1); + OCR3C = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4A1) + case TIMER4A: + // connect pwm to pin on timer 4, channel A + sbi(TCCR4A, COM4A1); + OCR4A = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4B1) + case TIMER4B: + // connect pwm to pin on timer 4, channel B + sbi(TCCR4A, COM4B1); + OCR4B = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4C1) + case TIMER4C: + // connect pwm to pin on timer 4, channel C + sbi(TCCR4A, COM4C1); + OCR4C = val; // set pwm duty + break; + #endif + + #if defined(TCCR5A) && defined(COM5A1) + case TIMER5A: + // connect pwm to pin on timer 5, channel A + sbi(TCCR5A, COM5A1); + OCR5A = val; // set pwm duty + break; + #endif + + #if defined(TCCR5A) && defined(COM5B1) + case TIMER5B: + // connect pwm to pin on timer 5, channel B + sbi(TCCR5A, COM5B1); + OCR5B = val; // set pwm duty + break; + #endif + + #if defined(TCCR5A) && defined(COM5C1) + case TIMER5C: + // connect pwm to pin on timer 5, channel C + sbi(TCCR5A, COM5C1); + OCR5C = val; // set pwm duty + break; + #endif + + case NOT_ON_TIMER: + default: + if (val < 128) { + digitalWrite(pin, LOW); + } else { + digitalWrite(pin, HIGH); + } + } + } +} diff --git a/Marlin/Sanguino/cores/arduino/wiring_digital.c b/Marlin/Sanguino/cores/arduino/wiring_digital.c new file mode 100644 index 0000000000..0949da42d7 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/wiring_digital.c @@ -0,0 +1,166 @@ +/* + wiring_digital.c - digital input and output functions + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 28 September 2010 by Mark Sproul + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +void pinMode(uint8_t pin, uint8_t mode) +{ + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *reg; + + if (port == NOT_A_PIN) return; + + // JWS: can I let the optimizer do this? + reg = portModeRegister(port); + + if (mode == INPUT) { + uint8_t oldSREG = SREG; + cli(); + *reg &= ~bit; + SREG = oldSREG; + } else { + uint8_t oldSREG = SREG; + cli(); + *reg |= bit; + SREG = oldSREG; + } +} + +// Forcing this inline keeps the callers from having to push their own stuff +// on the stack. It is a good performance win and only takes 1 more byte per +// user than calling. (It will take more bytes on the 168.) +// +// But shouldn't this be moved into pinMode? Seems silly to check and do on +// each digitalread or write. +// +// Mark Sproul: +// - Removed inline. Save 170 bytes on atmega1280 +// - changed to a switch statment; added 32 bytes but much easier to read and maintain. +// - Added more #ifdefs, now compiles for atmega645 +// +//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); +//static inline void turnOffPWM(uint8_t timer) +static void turnOffPWM(uint8_t timer) +{ + switch (timer) + { + #if defined(TCCR1A) && defined(COM1A1) + case TIMER1A: cbi(TCCR1A, COM1A1); break; + #endif + #if defined(TCCR1A) && defined(COM1B1) + case TIMER1B: cbi(TCCR1A, COM1B1); break; + #endif + + #if defined(TCCR2) && defined(COM21) + case TIMER2: cbi(TCCR2, COM21); break; + #endif + + #if defined(TCCR0A) && defined(COM0A1) + case TIMER0A: cbi(TCCR0A, COM0A1); break; + #endif + + #if defined(TIMER0B) && defined(COM0B1) + case TIMER0B: cbi(TCCR0A, COM0B1); break; + #endif + #if defined(TCCR2A) && defined(COM2A1) + case TIMER2A: cbi(TCCR2A, COM2A1); break; + #endif + #if defined(TCCR2A) && defined(COM2B1) + case TIMER2B: cbi(TCCR2A, COM2B1); break; + #endif + + #if defined(TCCR3A) && defined(COM3A1) + case TIMER3A: cbi(TCCR3A, COM3A1); break; + #endif + #if defined(TCCR3A) && defined(COM3B1) + case TIMER3B: cbi(TCCR3A, COM3B1); break; + #endif + #if defined(TCCR3A) && defined(COM3C1) + case TIMER3C: cbi(TCCR3A, COM3C1); break; + #endif + + #if defined(TCCR4A) && defined(COM4A1) + case TIMER4A: cbi(TCCR4A, COM4A1); break; + #endif + #if defined(TCCR4A) && defined(COM4B1) + case TIMER4B: cbi(TCCR4A, COM4B1); break; + #endif + #if defined(TCCR4A) && defined(COM4C1) + case TIMER4C: cbi(TCCR4A, COM4C1); break; + #endif + #if defined(TCCR5A) + case TIMER5A: cbi(TCCR5A, COM5A1); break; + case TIMER5B: cbi(TCCR5A, COM5B1); break; + case TIMER5C: cbi(TCCR5A, COM5C1); break; + #endif + } +} + +void digitalWrite(uint8_t pin, uint8_t val) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *out; + + if (port == NOT_A_PIN) return; + + // If the pin that support PWM output, we need to turn it off + // before doing a digital write. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + out = portOutputRegister(port); + + if (val == LOW) { + uint8_t oldSREG = SREG; + cli(); + *out &= ~bit; + SREG = oldSREG; + } else { + uint8_t oldSREG = SREG; + cli(); + *out |= bit; + SREG = oldSREG; + } +} + +int digitalRead(uint8_t pin) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + + if (port == NOT_A_PIN) return LOW; + + // If the pin that support PWM output, we need to turn it off + // before getting a digital reading. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + if (*portInputRegister(port) & bit) return HIGH; + return LOW; +} diff --git a/Marlin/Sanguino/cores/arduino/wiring_private.h b/Marlin/Sanguino/cores/arduino/wiring_private.h new file mode 100644 index 0000000000..11f6f00f28 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/wiring_private.h @@ -0,0 +1,68 @@ +/* + wiring_private.h - Internal header file. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ +*/ + +#ifndef WiringPrivate_h +#define WiringPrivate_h + +#include +#include +#include +#include +#include + +#include "wiring.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#define EXTERNAL_INT_0 0 +#define EXTERNAL_INT_1 1 +#define EXTERNAL_INT_2 2 +#define EXTERNAL_INT_3 3 +#define EXTERNAL_INT_4 4 +#define EXTERNAL_INT_5 5 +#define EXTERNAL_INT_6 6 +#define EXTERNAL_INT_7 7 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define EXTERNAL_NUM_INTERRUPTS 8 +#else +#define EXTERNAL_NUM_INTERRUPTS 2 +#endif + +typedef void (*voidFuncPtr)(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/Marlin/Sanguino/cores/arduino/wiring_pulse.c b/Marlin/Sanguino/cores/arduino/wiring_pulse.c new file mode 100644 index 0000000000..0d968865d2 --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/wiring_pulse.c @@ -0,0 +1,69 @@ +/* + wiring_pulse.c - pulseIn() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" +#include "pins_arduino.h" + +/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH + * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds + * to 3 minutes in length, but must be called at least a few dozen microseconds + * before the start of the pulse. */ +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) +{ + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + uint8_t stateMask = (state ? bit : 0); + unsigned long width = 0; // keep initialization out of time critical area + + // convert the timeout from microseconds to a number of times through + // the initial loop; it takes 16 clock cycles per iteration. + unsigned long numloops = 0; + unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; + + // wait for any previous pulse to end + while ((*portInputRegister(port) & bit) == stateMask) + if (numloops++ == maxloops) + return 0; + + // wait for the pulse to start + while ((*portInputRegister(port) & bit) != stateMask) + if (numloops++ == maxloops) + return 0; + + // wait for the pulse to stop + while ((*portInputRegister(port) & bit) == stateMask) { + if (numloops++ == maxloops) + return 0; + width++; + } + + // convert the reading to microseconds. The loop has been determined + // to be 20 clock cycles long and have about 16 clocks between the edge + // and the start of the loop. There will be some error introduced by + // the interrupt handlers. + return clockCyclesToMicroseconds(width * 21 + 16); +} diff --git a/Marlin/Sanguino/cores/arduino/wiring_shift.c b/Marlin/Sanguino/cores/arduino/wiring_shift.c new file mode 100644 index 0000000000..cfe786758c --- /dev/null +++ b/Marlin/Sanguino/cores/arduino/wiring_shift.c @@ -0,0 +1,55 @@ +/* + wiring_shift.c - shiftOut() function + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#include "wiring_private.h" + +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { + uint8_t value = 0; + uint8_t i; + + for (i = 0; i < 8; ++i) { + digitalWrite(clockPin, HIGH); + if (bitOrder == LSBFIRST) + value |= digitalRead(dataPin) << i; + else + value |= digitalRead(dataPin) << (7 - i); + digitalWrite(clockPin, LOW); + } + return value; +} + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + if (bitOrder == LSBFIRST) + digitalWrite(dataPin, !!(val & (1 << i))); + else + digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + + digitalWrite(clockPin, HIGH); + digitalWrite(clockPin, LOW); + } +} diff --git a/Marlin/Sanguino/programmers.txt b/Marlin/Sanguino/programmers.txt new file mode 100644 index 0000000000..466f602a3c --- /dev/null +++ b/Marlin/Sanguino/programmers.txt @@ -0,0 +1,20 @@ +avrisp.name=AVR ISP +avrisp.communication=serial +avrisp.protocol=stk500v1 + +avrispmkii.name=AVRISP mkII +avrispmkii.communication=usb +avrispmkii.protocol=stk500v2 + +usbtinyisp.name=USBtinyISP +usbtinyisp.protocol=usbtiny + +parallel.name=Parallel Programmer +parallel.protocol=dapa +parallel.force=true +# parallel.delay=200 + +arduinoisp.name=Arduino as ISP +arduinoisp.communication=serial +arduinoisp.protocol=stk500v1 +arduinoisp.speed=19200 From 331e82dcd3d7eaf9f76dbec8759f2f730335fea3 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 14 Nov 2011 18:53:09 +0100 Subject: [PATCH 042/228] Buffer size > 16 --- Marlin/Configuration.h | 4 +- Marlin/temperature.cpp | 49 +++++----- Marlin/ultralcd.h | 203 +++++++++++++++++++++-------------------- 3 files changed, 129 insertions(+), 127 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 2d890b7215..89104fde9b 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -311,9 +311,9 @@ const int dropsegments=0; //everything with less than this number of steps will // The number of linear motions that can be in the plan at any give time. // THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ringbuffering. #if defined SDSUPPORT - #define BLOCK_BUFFER_SIZE 8 // SD,LCD,Buttons take more memory, block buffer needs to be smaller + #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller #else - #define BLOCK_BUFFER_SIZE 8 // maximize block buffer + #define BLOCK_BUFFER_SIZE 16 // maximize block buffer #endif diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 89ee47d847..42064104b4 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -203,6 +203,7 @@ void manage_heater() #endif } +#define PGM_RD_W(x) (short)pgm_read_word(&x) // Takes hot end temperature value as input and returns corresponding raw value. // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. @@ -214,18 +215,18 @@ int temp2analog(int celsius) { for (i=1; i raw) + if (PGM_RD_W(heater_0_temptable[i][0]) > raw) { - celsius = (short)pgm_read_word(&heater_0_temptable[i-1][1]) + - (raw - (short)pgm_read_word(&heater_0_temptable[i-1][0])) * - (float)((short)pgm_read_word(&heater_0_temptable[i][1]) - (short)pgm_read_word(&heater_0_temptable[i-1][1])) / - (float)((short)pgm_read_word(&heater_0_temptable[i][0]) - (short)pgm_read_word(&heater_0_temptable[i-1][0])); + celsius = PGM_RD_W(heater_0_temptable[i-1][1]) + + (raw - PGM_RD_W(heater_0_temptable[i-1][0])) * + (float)(PGM_RD_W(heater_0_temptable[i][1]) - PGM_RD_W(heater_0_temptable[i-1][1])) / + (float)(PGM_RD_W(heater_0_temptable[i][0]) - PGM_RD_W(heater_0_temptable[i-1][0])); break; } } // Overflow: Set to last value in the table - if (i == NUMTEMPS_HEATER_0) celsius = (short)pgm_read_word(&(heater_0_temptable[i-1][1])); + if (i == NUMTEMPS_HEATER_0) celsius = PGM_RD_W(heater_0_temptable[i-1][1]); return celsius; #elif defined HEATER_0_USES_AD595 @@ -304,19 +305,19 @@ float analog2tempBed(int raw) { for (i=1; i raw) + if (PGM_RD_W(bedtemptable[i][0]) > raw) { - celsius = pgm_read_word(&(bedtemptable[i-1][1])) + - (raw - pgm_read_word(&(bedtemptable[i-1][0]))) * - (pgm_read_word(&(bedtemptable[i][1])) - pgm_read_word(&(bedtemptable[i-1][1]))) / - (pgm_read_word(&(bedtemptable[i][0])) - pgm_read_word(&(bedtemptable[i-1][0]))); + celsius = PGM_RD_W(bedtemptable[i-1][1]) + + (raw - PGM_RD_W(bedtemptable[i-1][0])) * + (PGM_RD_W(bedtemptable[i][1]) - PGM_RD_W(bedtemptable[i-1][1])) / + (PGM_RD_W(bedtemptable[i][0]) - PGM_RD_W(bedtemptable[i-1][0])); break; } } // Overflow: Set to last value in the table - if (i == BNUMTEMPS) celsius = pgm_read_word(&(bedtemptable[i-1][1])); + if (i == BNUMTEMPS) celsius = PGM_RD_W(bedtemptable[i-1][1]); return celsius; diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 4c725329df..bc07c25a82 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -1,102 +1,103 @@ -#ifndef __ULTRALCDH -#define __ULTRALCDH -#include "Configuration.h" - -#ifdef ULTRA_LCD - - void lcd_status(); - void lcd_init(); - void lcd_status(const char* message); - void beep(); - void buttons_check(); - - - #define LCD_UPDATE_INTERVAL 100 - #define STATUSTIMEOUT 15000 - - - #include - extern LiquidCrystal lcd; - - - #ifdef NEWPANEL - - - #define EN_C (1< + extern LiquidCrystal lcd; + + + #ifdef NEWPANEL + + + #define EN_C (1< Date: Mon, 14 Nov 2011 20:04:29 +0100 Subject: [PATCH 043/228] Added slowdown --- Marlin/Configuration.h | 7 +++++-- Marlin/planner.cpp | 32 +++++++++++++++++++------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 89104fde9b..5a6fc47023 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -18,6 +18,9 @@ // if unwanted behavior is observed on a user's machine when running at very slow speeds. #define MINIMUM_PLANNER_SPEED 2.0 // (mm/sec) +// If defined the movements slow down when the look ahead buffer is only half full +#define SLOWDOWN + // BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration //// The following define selects which electronics board you have. Please choose the one that matches your setup @@ -210,7 +213,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define DEFAULT_MINTRAVELFEEDRATE 0 // minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. -#define DEFAULT_MINSEGMENTTIME 20000 +#define DEFAULT_MINSEGMENTTIME 20000 // Obsolete delete this #define DEFAULT_XYJERK 30.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) @@ -269,7 +272,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define ULTIPANEL #ifdef ULTIPANEL - #define NEWPANEL //enable this if you have a click-encoder panel +// #define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT #define ULTRA_LCD #define LCD_WIDTH 20 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 998a609101..8dfa44f543 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -499,31 +499,37 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 -// unsigned long microseconds; -#if 0 + // segment time im micro seconds + long segment_time = lround(1000000.0/inverse_second); + + if (block->steps_e == 0) { if(feed_ratemillimeters/feed_rate)*1000000); - + +#ifdef SLOWDOWN // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill - // reduces/removes corner blobs as the machine won't come to a full stop. - int blockcount=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + + if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5)) feed_rate = feed_rate / ((BLOCK_BUFFER_SIZE * 0.5)/moves_queued); +#endif + +/* + if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { - if (microsecondsdirection_bits ^ old_direction_bits; old_direction_bits = block->direction_bits; - long segment_time = lround(1000000.0/inverse_second); + if((direction_change & (1< Date: Mon, 14 Nov 2011 23:57:34 +0100 Subject: [PATCH 044/228] Some fixes in planner --- Marlin/Configuration.h | 22 +++++++++++++--------- Marlin/planner.cpp | 9 +++------ Marlin/stepper.cpp | 16 ++++++++-------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 5a6fc47023..135b61e013 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -115,11 +115,15 @@ #ifdef PID_PID //PID according to Ziegler-Nichols method - #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) - #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) +// #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) +// #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) +// #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) + + #define DEFAULT_Kp 22.2 + #define DEFAULT_Ki (1.25*PID_dT) + #define DEFAULT_Kd (99/PID_dT) #endif - + #ifdef PID_PI //PI according to Ziegler-Nichols method #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) @@ -197,20 +201,20 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define AXIS_RELATIVE_MODES {false, false, false, false} -#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) +#define MAX_STEP_FREQUENCY 40000L // Max step frequency for Ultimaker (5000 pps / half step) // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker +#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,760*1.1} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} -#define DEFAULT_MAX_FEEDRATE {500, 500, 10, 500000} // (mm/min) +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 200000} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. #define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts -#define DEFAULT_MINIMUMFEEDRATE 0 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 0 +#define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 0.0 // minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. #define DEFAULT_MINSEGMENTTIME 20000 // Obsolete delete this diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 8dfa44f543..a3dde6c312 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -490,7 +490,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + - square(delta_mm[Z_AXIS])); + square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. @@ -502,7 +502,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // segment time im micro seconds long segment_time = lround(1000000.0/inverse_second); - + if (block->steps_e == 0) { if(feed_rate0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { if (segment_time MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times - step_rate = step_rate >> 2; + step_rate = (step_rate >> 2)&0x3fff; step_loops = 4; } else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times - step_rate = step_rate >> 1; + step_rate = (step_rate >> 1)&0x7fff; step_loops = 2; } else { @@ -253,7 +253,7 @@ inline unsigned short calc_timer(unsigned short step_rate) { timer = (unsigned short)pgm_read_word_near(table_address); timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); } - //if(timer < 100) timer = 100; + if(timer < 100) timer = 100; //(20kHz this should never happen) return timer; } @@ -340,7 +340,7 @@ ISR(TIMER1_COMPA_vect) #endif #if X_MIN_PIN > -1 if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { - endstops_triggered(step_events_completed); + // endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -352,7 +352,7 @@ ISR(TIMER1_COMPA_vect) #endif #if X_MAX_PIN > -1 if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ - endstops_triggered(step_events_completed); + // endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -365,7 +365,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Y_MIN_PIN > -1 if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { - endstops_triggered(step_events_completed); + // endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -377,7 +377,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Y_MAX_PIN > -1 if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ - endstops_triggered(step_events_completed); + // endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -402,7 +402,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Z_MAX_PIN > -1 if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ - endstops_triggered(step_events_completed); + // endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif From 805d37f77b25fba70c05518cda4edd1c349b7f04 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Tue, 15 Nov 2011 18:14:00 +0100 Subject: [PATCH 045/228] Fixed some small planner bugs --- Marlin/Configuration.h | 5 +++-- Marlin/planner.cpp | 15 ++++++++++----- Marlin/planner.h | 20 ++++++++++---------- Marlin/stepper.cpp | 2 +- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 135b61e013..3b0cfacfeb 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -11,7 +11,8 @@ // Frequency limit // See nophead's blog for more info -#define XY_FREQUENCY_LIMIT 15 +// Not working OK +//#define XY_FREQUENCY_LIMIT 15 // Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end // of the buffer and all stops. This should not be much greater than zero and should only be changed @@ -201,7 +202,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define AXIS_RELATIVE_MODES {false, false, false, false} -#define MAX_STEP_FREQUENCY 40000L // Max step frequency for Ultimaker (5000 pps / half step) +#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) // default settings diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index a3dde6c312..c27d586017 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -72,7 +72,7 @@ unsigned long minsegmenttime; float max_feedrate[4]; // set the max speeds float axis_steps_per_unit[4]; -long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software float minimumfeedrate; float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX @@ -153,8 +153,8 @@ inline float intersection_distance(float initial_rate, float final_rate, float a // Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) { - long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) - long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) + unsigned long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) + unsigned long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) // Limit minimal step rate (Otherwise the timer will overflow.) if(initial_rate <120) {initial_rate=120; } @@ -570,7 +570,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa long max_x_segment_time = max(x_segment_time[0], max(x_segment_time[1], x_segment_time[2])); long max_y_segment_time = max(y_segment_time[0], max(y_segment_time[1], y_segment_time[2])); long min_xy_segment_time =min(max_x_segment_time, max_y_segment_time); - if(min_xy_segment_time < MAX_FREQ_TIME) speed_factor = min(speed_factor, (float)min_xy_segment_time / (float)MAX_FREQ_TIME); + if(min_xy_segment_time < MAX_FREQ_TIME) speed_factor = min(speed_factor, speed_factor * (float)min_xy_segment_time / (float)MAX_FREQ_TIME); #endif // Correct the speed @@ -579,7 +579,12 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa for(int i=0; i < 4; i++) { if(abs(current_speed[i]) > max_feedrate[i]) speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); -// Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); + /* + if(speed_factor < 0.1) { + Serial.print("speed factor : "); Serial.println(speed_factor); + Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); + } + */ } for(unsigned char i=0; i < 4; i++) { current_speed[i] *= speed_factor; diff --git a/Marlin/planner.h b/Marlin/planner.h index f5c01ea266..be1587d6b8 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -32,9 +32,9 @@ typedef struct { // Fields used by the bresenham algorithm for tracing the line long steps_x, steps_y, steps_z, steps_e; // Step count along each axis long step_event_count; // The number of step events required to complete this block - volatile long accelerate_until; // The index of the step event on which to stop acceleration - volatile long decelerate_after; // The index of the step event on which to start decelerating - volatile long acceleration_rate; // The acceleration rate used for acceleration calculation + long accelerate_until; // The index of the step event on which to stop acceleration + long decelerate_after; // The index of the step event on which to start decelerating + long acceleration_rate; // The acceleration rate used for acceleration calculation unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) #ifdef ADVANCE // long advance_rate; @@ -50,14 +50,14 @@ typedef struct { float max_entry_speed; // Maximum allowable junction entry speed in mm/min float millimeters; // The total travel of this block in mm float acceleration; // acceleration mm/sec^2 - unsigned char recalculate_flag; // Planner flag to recalculate trapezoids on entry junction - unsigned char nominal_length_flag; // Planner flag for nominal speed always reached + unsigned char recalculate_flag; // Planner flag to recalculate trapezoids on entry junction + unsigned char nominal_length_flag; // Planner flag for nominal speed always reached // Settings for the trapezoid generator - long nominal_rate; // The nominal step rate for this block in step_events/sec - volatile long initial_rate; // The jerk-adjusted step rate at start of block - volatile long final_rate; // The minimal rate at exit - long acceleration_st; // acceleration steps/sec^2 + unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec + unsigned long initial_rate; // The jerk-adjusted step rate at start of block + unsigned long final_rate; // The minimal rate at exit + unsigned long acceleration_st; // acceleration steps/sec^2 volatile char busy; } block_t; @@ -84,7 +84,7 @@ void check_axes_activity(); extern unsigned long minsegmenttime; extern float max_feedrate[4]; // set the max speeds extern float axis_steps_per_unit[4]; -extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +extern unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software extern float minimumfeedrate; extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 96a43ed7ed..2e232201bf 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -253,7 +253,7 @@ inline unsigned short calc_timer(unsigned short step_rate) { timer = (unsigned short)pgm_read_word_near(table_address); timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); } - if(timer < 100) timer = 100; //(20kHz this should never happen) + if(timer < 100) { timer = 100; Serial.print("Steprate to high : "); Serial.println(step_rate); }//(20kHz this should never happen) return timer; } From 7919a40d066116203dd2e703df9af7f3fe4d1bd4 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Tue, 15 Nov 2011 20:54:40 +0100 Subject: [PATCH 046/228] watchdog,percent done, --- Marlin/Configuration.h | 11 ++++---- Marlin/Marlin.h | 2 +- Marlin/Marlin.pde | 60 ++++++++++++++++++++++++------------------ Marlin/cardreader.h | 1 + Marlin/ultralcd.h | 2 +- Marlin/ultralcd.pde | 10 +++++++ Marlin/watchdog.pde | 2 ++ 7 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 5b15dd0a47..f0dbe6a6e7 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -220,11 +220,12 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // this enables the watchdog interrupt. -#define 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: -#define RESET_MANUAL -#define WATCHDOG_TIMEOUT 4 //seconds - +//#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: + #define RESET_MANUAL + #define WATCHDOG_TIMEOUT 4 //seconds +#endif diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 440a44a579..acfc3c2fa6 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -100,7 +100,7 @@ void prepare_move(); void kill(); void enquecommand(const char *cmd); //put an ascii command at the end of the current buffer. - +void prepare_arc_move(char isclockwise); #ifndef CRITICAL_SECTION_START #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 84f07b3e68..cacd728742 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -37,6 +37,7 @@ #include "temperature.h" #include "motion_control.h" #include "cardreader.h" +#include "watchdog.h" #define VERSION_STRING "1.0.0 Alpha 1" @@ -191,6 +192,36 @@ extern "C"{ } + +inline void get_coordinates() +{ + 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]; + 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; + } +} + +inline void get_arc_coordinates() +{ + get_coordinates(); + if(code_seen('I')) offset[0] = code_value(); + if(code_seen('J')) offset[1] = code_value(); +} + +void prepare_move() +{ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); + for(int8_t i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; + } +} + + + //adds an command to the main command buffer //thats really done in a non-safe way. //needs overworking someday @@ -234,6 +265,7 @@ void setup() plan_init(); // Initialize planner; st_init(); // Initialize stepper; tp_init(); // Initialize temperature loop + wd_init(); } @@ -656,7 +688,8 @@ inline void process_commands() break; case 105: // M105 //SERIAL_ECHOLN(freeMemory()); - + //test watchdog: + //delay(20000); #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) SERIAL_PROTOCOLPGM("ok T:"); SERIAL_PROTOCOL( degHotend0()); @@ -975,32 +1008,7 @@ void ClearToSend() SERIAL_PROTOCOLLNPGM("ok"); } -inline void get_coordinates() -{ - 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]; - 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; - } -} -inline void get_arc_coordinates() -{ - get_coordinates(); - if(code_seen('I')) offset[0] = code_value(); - if(code_seen('J')) offset[1] = code_value(); -} - -void prepare_move() -{ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); - 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 diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index b3f514f61f..d75f93a523 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -33,6 +33,7 @@ public: inline bool eof() { return sdpos>=filesize ;}; inline int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; inline void setIndex(long index) {sdpos = index;file.seekSet(index);}; + inline uint8_t percentDone(){if(!sdprinting) return 0; if(filesize) return sdpos*100/filesize; else return 0;}; public: bool saving; diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 4c725329df..c836757e1c 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -96,7 +96,7 @@ #define BLOCK ; #endif - +void lcd_statuspgm(const char* message); #endif //ULTRALCD diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index d95167166d..1bf225641a 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -374,6 +374,16 @@ void MainMenu::showStatus() lcd.print(fillto(LCD_WIDTH,messagetext)); messagetext[0]='\0'; } + + static uint8_t oldpercent=101; + uint8_t percent=card.percentDone(); + if(oldpercent!=percent) + { + lcd.setCursor(6,3); + lcd.print(oldpercent); + lcdprintPGM("done"); + } + #else //smaller LCDS---------------------------------- static int olddegHotEnd0=-1; static int oldtargetHotEnd0=-1; diff --git a/Marlin/watchdog.pde b/Marlin/watchdog.pde index 9cf710a0c7..6c883c9d40 100644 --- a/Marlin/watchdog.pde +++ b/Marlin/watchdog.pde @@ -42,10 +42,12 @@ ISR(WDT_vect) #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< Date: Tue, 15 Nov 2011 20:55:00 +0100 Subject: [PATCH 047/228] show sd% --- Marlin/ultralcd.pde | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 1bf225641a..51a3c46f9c 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -377,11 +377,12 @@ void MainMenu::showStatus() static uint8_t oldpercent=101; uint8_t percent=card.percentDone(); - if(oldpercent!=percent) + if(oldpercent!=percent ||force_lcd_update) { - lcd.setCursor(6,3); - lcd.print(oldpercent); - lcdprintPGM("done"); + lcd.setCursor(7,2); + lcd.print(itostr3((int)percent)); + lcdprintPGM("%SD"); + } #else //smaller LCDS---------------------------------- From a9c7da06e398101517acc5b7a07e8dcb544df294 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Tue, 15 Nov 2011 22:50:43 +0100 Subject: [PATCH 048/228] and changed ultipanel to have the mm/sec and not mm/min Merge branch 'Marlin_v1' of https://github.com/ErikZalm/Marlin into Marlin_v1 Conflicts: Marlin/Marlin.pde Marlin/ultralcd.h --- Marlin/Configuration.h | 50 +- Marlin/Marlin.pde | 55 +- Marlin/planner.cpp | 1376 ++++++++++++++++++++----------------- Marlin/planner.h | 193 +++--- Marlin/stepper.cpp | 1333 +++++++++++++++++------------------ Marlin/temperature.cpp | 1157 +++++++++++++++---------------- Marlin/thermistortables.h | 16 +- Marlin/ultralcd.h | 205 +++--- Marlin/ultralcd.pde | 24 +- 9 files changed, 2284 insertions(+), 2125 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f0dbe6a6e7..f1f0c651cf 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -9,6 +9,19 @@ //#define BAUDRATE 230400 +// Frequency limit +// See nophead's blog for more info +// Not working OK +//#define XY_FREQUENCY_LIMIT 15 + +// Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end +// of the buffer and all stops. This should not be much greater than zero and should only be changed +// if unwanted behavior is observed on a user's machine when running at very slow speeds. +#define MINIMUM_PLANNER_SPEED 2.0 // (mm/sec) + +// If defined the movements slow down when the look ahead buffer is only half full +#define SLOWDOWN + // BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration //// The following define selects which electronics board you have. Please choose the one that matches your setup @@ -45,7 +58,6 @@ //#define BED_USES_THERMISTOR //#define BED_USES_AD595 -#define HEATER_CHECK_INTERVAL 50 //ms #define BED_CHECK_INTERVAL 5000 //ms //// Experimental watchdog and minimal temp @@ -103,11 +115,15 @@ #ifdef PID_PID //PID according to Ziegler-Nichols method - #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) - #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) +// #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) +// #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) +// #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) + + #define DEFAULT_Kp 22.2 + #define DEFAULT_Ki (1.25*PID_dT) + #define DEFAULT_Kd (99/PID_dT) #endif - + #ifdef PID_PI //PI according to Ziegler-Nichols method #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) @@ -156,6 +172,11 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define DISABLE_E false // Inverting axis direction +//#define INVERT_X_DIR false // for Mendel set to false, for Orca set to true +//#define INVERT_Y_DIR true // for Mendel set to true, for Orca set to false +//#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true +//#define INVERT_E_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false + #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false #define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true @@ -176,7 +197,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E //note: on bernhards ultimaker 200 200 12 are working well. -#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds +#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) #define AXIS_RELATIVE_MODES {false, false, false, false} @@ -184,20 +205,21 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker -#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} -#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,760*1.1} // default steps per unit for ultimaker +//#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 200000} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. #define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts -#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 10 +#define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 0.0 // minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. -#define DEFAULT_MINSEGMENTTIME 20000 -#define DEFAULT_XYJERK 30.0*60 -#define DEFAULT_ZJERK 10.0*60 +#define DEFAULT_MINSEGMENTTIME 20000 // Obsolete delete this +#define DEFAULT_XYJERK 30.0 // (mm/sec) +#define DEFAULT_ZJERK 0.4 // (mm/sec) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index cacd728742..f808742c9c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -116,7 +116,9 @@ extern float HeaterPower; //=========================================================================== //=============================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 @@ -193,32 +195,8 @@ extern "C"{ -inline void get_coordinates() -{ - 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]; - 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; - } -} -inline void get_arc_coordinates() -{ - get_coordinates(); - if(code_seen('I')) offset[0] = code_value(); - if(code_seen('J')) offset[1] = code_value(); -} -void prepare_move() -{ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); - for(int8_t i=0; i < NUM_AXIS; i++) { - current_position[i] = destination[i]; - } -} @@ -273,7 +251,9 @@ void loop() { if(buflen<3) get_command(); + #ifdef SDSUPPORT card.checkautostart(false); + #endif if(buflen) { #ifdef SDSUPPORT @@ -1008,13 +988,38 @@ void ClearToSend() SERIAL_PROTOCOLLNPGM("ok"); } +inline void get_coordinates() +{ + 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]; + 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; + } +} +inline void get_arc_coordinates() +{ + get_coordinates(); + if(code_seen('I')) offset[0] = code_value(); + if(code_seen('J')) offset[1] = code_value(); +} + +void prepare_move() +{ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0); + 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.0/100.0, r, isclockwise); + mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise); // 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 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 863b116a5b..c27d586017 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -1,629 +1,747 @@ -/* - planner.c - buffers movement commands and manages the acceleration profile plan - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ - -/* - Reasoning behind the mathematics in this module (in the key of 'Mathematica'): - - s == speed, a == acceleration, t == time, d == distance - - Basic definitions: - - Speed[s_, a_, t_] := s + (a*t) - Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] - - Distance to reach a specific speed with a constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] - d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() - - Speed after a given distance of travel with constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] - m -> Sqrt[2 a d + s^2] - - DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] - - When to start braking (di) to reach a specified destionation speed (s2) after accelerating - from initial speed s1 without ever stopping at a plateau: - - Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] - di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() - - IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) -*/ - - -//#include -//#include -//#include - -#include "Marlin.h" -#include "Configuration.h" -#include "pins.h" -#include "fastio.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" -#include "ultralcd.h" - -//=========================================================================== -//=============================public variables ============================ -//=========================================================================== - -unsigned long minsegmenttime; -float max_feedrate[4]; // set the max speeds -float axis_steps_per_unit[4]; -long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -float minimumfeedrate; -float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -float max_z_jerk; -float mintravelfeedrate; -unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - -// The current position of the tool in absolute steps -long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode - -#ifdef AUTOTEMP -float high_e_speed=0; -#endif - - -//=========================================================================== -//=============================private variables ============================ -//=========================================================================== -static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions -static volatile unsigned char block_buffer_head; // Index of the next block to be pushed -static volatile unsigned char block_buffer_tail; // Index of the block to process now - - - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== -#define ONE_MINUTE_OF_MICROSECONDS 60000000.0 - -// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the -// given acceleration: -inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { - if (acceleration!=0) { - return((target_rate*target_rate-initial_rate*initial_rate)/ - (2.0*acceleration)); - } - else { - return 0.0; // acceleration was 0, set acceleration distance to 0 - } -} - -// This function gives you the point at which you must start braking (at the rate of -acceleration) if -// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after -// a total travel of distance. This can be used to compute the intersection point between acceleration and -// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) - -inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { - if (acceleration!=0) { - return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ - (4.0*acceleration) ); - } - else { - return 0.0; // acceleration was 0, set intersection distance to 0 - } -} - -// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. - -void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit_speed) { - if(block->busy == true) return; // If block is busy then bail out. - float entry_factor = entry_speed / block->nominal_speed; - float exit_factor = exit_speed / block->nominal_speed; - long initial_rate = ceil(block->nominal_rate*entry_factor); - long final_rate = ceil(block->nominal_rate*exit_factor); - - #ifdef ADVANCE - long initial_advance = block->advance*entry_factor*entry_factor; - long final_advance = block->advance*exit_factor*exit_factor; - #endif // ADVANCE - - // Limit minimal step rate (Otherwise the timer will overflow.) - if(initial_rate <120) initial_rate=120; - if(final_rate < 120) final_rate=120; - - // Calculate the acceleration steps - long acceleration = block->acceleration_st; - long accelerate_steps = estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration); - long decelerate_steps = estimate_acceleration_distance(final_rate, block->nominal_rate, acceleration); - // Calculate the size of Plateau of Nominal Rate. - long plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; - - // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will - // 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 = intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count); - plateau_steps = 0; - } - - long decelerate_after = accelerate_steps+plateau_steps; - - CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section - if(block->busy == false) { // Don't update variables if block is busy. - block->accelerate_until = accelerate_steps; - block->decelerate_after = decelerate_after; - block->initial_rate = initial_rate; - block->final_rate = final_rate; - #ifdef ADVANCE - block->initial_advance = initial_advance; - block->final_advance = final_advance; - #endif //ADVANCE - } - CRITICAL_SECTION_END; -} - -// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the -// acceleration within the allotted distance. -inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { - return sqrt(target_velocity*target_velocity-2*acceleration*60*60*distance); -} - -// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. -// This method will calculate the junction jerk as the euclidean distance between the nominal -// velocities of the respective blocks. -inline float junction_jerk(block_t *before, block_t *after) { - return sqrt( - pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); -} - -// Return the safe speed which is max_jerk/2, e.g. the -// speed under which you cannot exceed max_jerk no matter what you do. -float safe_speed(block_t *block) { - float safe_speed; - safe_speed = max_xy_jerk/2; - if(abs(block->speed_z) > max_z_jerk/2) - safe_speed = max_z_jerk/2; - if (safe_speed > block->nominal_speed) - safe_speed = block->nominal_speed; - return safe_speed; -} - -// The kernel called by planner_recalculate() when scanning the plan from last to first entry. -void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - - float entry_speed = current->nominal_speed; - float exit_factor; - float exit_speed; - if (next) { - exit_speed = next->entry_speed; - } - else { - exit_speed = safe_speed(current); - } - - // Calculate the entry_factor for the current block. - if (previous) { - // Reduce speed so that junction_jerk is within the maximum allowed - float jerk = junction_jerk(previous, current); - if((previous->steps_x == 0) && (previous->steps_y == 0)) { - entry_speed = safe_speed(current); - } - else if (jerk > max_xy_jerk) { - entry_speed = (max_xy_jerk/jerk) * entry_speed; - } - if(abs(previous->speed_z - current->speed_z) > max_z_jerk) { - entry_speed = (max_z_jerk/abs(previous->speed_z - current->speed_z)) * entry_speed; - } - // If the required deceleration across the block is too rapid, reduce the entry_factor accordingly. - if (entry_speed > exit_speed) { - float max_entry_speed = max_allowable_speed(-current->acceleration,exit_speed, current->millimeters); - if (max_entry_speed < entry_speed) { - entry_speed = max_entry_speed; - } - } - } - else { - entry_speed = safe_speed(current); - } - // Store result - current->entry_speed = entry_speed; -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the reverse pass. -void planner_reverse_pass() { - char block_index = block_buffer_head; - if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { - block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); - block_t *block[5] = { - NULL, NULL, NULL, NULL, NULL }; - while(block_index != block_buffer_tail) { - block_index = (block_index-1) & (BLOCK_BUFFER_SIZE -1); - block[2]= block[1]; - block[1]= block[0]; - block[0] = &block_buffer[block_index]; - planner_reverse_pass_kernel(block[0], block[1], block[2]); - } - planner_reverse_pass_kernel(NULL, block[0], block[1]); - } -} - -// The kernel called by planner_recalculate() when scanning the plan from first to last entry. -void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { - return; - } - if(previous) { - // If the previous block is an acceleration block, but it is not long enough to - // complete the full speed change within the block, we need to adjust out entry - // speed accordingly. Remember current->entry_factor equals the exit factor of - // the previous block. - if(previous->entry_speed < current->entry_speed) { - float max_entry_speed = max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters); - if (max_entry_speed < current->entry_speed) { - current->entry_speed = max_entry_speed; - } - } - } -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the forward pass. -void planner_forward_pass() { - char block_index = block_buffer_tail; - block_t *block[3] = { - NULL, NULL, NULL }; - - while(block_index != block_buffer_head) { - block[0] = block[1]; - block[1] = block[2]; - block[2] = &block_buffer[block_index]; - planner_forward_pass_kernel(block[0],block[1],block[2]); - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - planner_forward_pass_kernel(block[1], block[2], NULL); -} - -// Recalculates the trapezoid speed profiles for all blocks in the plan according to the -// entry_factor for each junction. Must be called by planner_recalculate() after -// updating the blocks. -void planner_recalculate_trapezoids() { - char block_index = block_buffer_tail; - block_t *current; - block_t *next = NULL; - while(block_index != block_buffer_head) { - current = next; - next = &block_buffer[block_index]; - if (current) { - calculate_trapezoid_for_block(current, current->entry_speed, next->entry_speed); - } - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - calculate_trapezoid_for_block(next, next->entry_speed, safe_speed(next)); -} - -// Recalculates the motion plan according to the following algorithm: -// -// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) -// so that: -// a. The junction jerk is within the set limit -// b. No speed reduction within one block requires faster deceleration than the one, true constant -// acceleration. -// 2. Go over every block in chronological order and dial down junction speed reduction values if -// a. The speed increase within one block would require faster accelleration than the one, true -// constant acceleration. -// -// When these stages are complete all blocks have an entry_factor that will allow all speed changes to -// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than -// the set limit. Finally it will: -// -// 3. Recalculate trapezoids for all blocks. - -void planner_recalculate() { - planner_reverse_pass(); - planner_forward_pass(); - planner_recalculate_trapezoids(); -} - -void plan_init() { - block_buffer_head = 0; - block_buffer_tail = 0; - memset(position, 0, sizeof(position)); // clear position -} - - -void plan_discard_current_block() { - if (block_buffer_head != block_buffer_tail) { - block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); - } -} - -block_t *plan_get_current_block() { - if (block_buffer_head == block_buffer_tail) { - return(NULL); - } - block_t *block = &block_buffer[block_buffer_tail]; - block->busy = true; - return(block); -} - -#ifdef AUTOTEMP -void getHighESpeed() -{ - if(degTargetHotend0()+2high) - { - high=se; - } - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - high_e_speed=high*axis_steps_per_unit[E_AXIS]/(1000000.0); //so it is independent of the esteps/mm. before - - float g=AUTOTEMP_MIN+high_e_speed*AUTOTEMP_FACTOR; - float t=constrain(AUTOTEMP_MIN,g,AUTOTEMP_MAX); - setTargetHotend0(t); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR("highe",high_e_speed); - SERIAL_ECHOPAIR(" t",t); - SERIAL_ECHOLN(""); -} -#endif - -void check_axes_activity() { - unsigned char x_active = 0; - unsigned char y_active = 0; - unsigned char z_active = 0; - unsigned char e_active = 0; - block_t *block; - - if(block_buffer_tail != block_buffer_head) { - char block_index = block_buffer_tail; - while(block_index != block_buffer_head) { - block = &block_buffer[block_index]; - if(block->steps_x != 0) x_active++; - if(block->steps_y != 0) y_active++; - if(block->steps_z != 0) z_active++; - if(block->steps_e != 0) e_active++; - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - } - if((DISABLE_X) && (x_active == 0)) disable_x(); - if((DISABLE_Y) && (y_active == 0)) disable_y(); - if((DISABLE_Z) && (z_active == 0)) disable_z(); - if((DISABLE_E) && (e_active == 0)) disable_e(); -} - -// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in -// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration -// calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate) -{ - // Calculate the buffer head after we push this byte - int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); - - // If the buffer is full: good! That means we are well ahead of the robot. - // Rest here until there is room in the buffer. - while(block_buffer_tail == next_buffer_head) { - manage_heater(); - manage_inactivity(1); - LCD_STATUS; - } - - // The target position of the tool in absolute steps - // Calculate target position in absolute steps - //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow - long target[4]; - target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - - // Prepare to set up new block - block_t *block = &block_buffer[block_buffer_head]; - - // Mark block as not busy (Not executed by the stepper interrupt) - block->busy = false; - - // Number of steps for each axis - block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); - block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); - block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); - block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); - block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); - - // Bail if this is a zero-length block - if (block->step_event_count <=dropsegments) { - return; - }; - - //enable active axes - if(block->steps_x != 0) enable_x(); - if(block->steps_y != 0) enable_y(); - if(block->steps_z != 0) enable_z(); - if(block->steps_e != 0) enable_e(); - - float delta_x_mm = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; - float delta_y_mm = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; - float delta_z_mm = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; - float delta_e_mm = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; - block->millimeters = sqrt(square(delta_x_mm) + square(delta_y_mm) + square(delta_z_mm) + square(delta_e_mm)); - - unsigned long microseconds; - - if (block->steps_e == 0) { - if(feed_ratemillimeters/feed_rate)*1000000); - - // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill - // reduces/removes corner blobs as the machine won't come to a full stop. - int blockcount=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); - - if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { - if (microsecondsspeed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - - - // Limit speed per axis - float speed_factor = 1; //factor <=1 do decrease speed - if(abs(block->speed_x) > max_feedrate[X_AXIS]) { - speed_factor = max_feedrate[X_AXIS] / abs(block->speed_x); - //if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; /is not need here because auf the init above - } - if(abs(block->speed_y) > max_feedrate[Y_AXIS]){ - float tmp_speed_factor = max_feedrate[Y_AXIS] / abs(block->speed_y); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_z) > max_feedrate[Z_AXIS]){ - float tmp_speed_factor = max_feedrate[Z_AXIS] / abs(block->speed_z); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - if(abs(block->speed_e) > max_feedrate[E_AXIS]){ - float tmp_speed_factor = max_feedrate[E_AXIS] / abs(block->speed_e); - if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; - } - multiplier = multiplier * speed_factor; - block->speed_z = delta_z_mm * multiplier; - block->speed_x = delta_x_mm * multiplier; - block->speed_y = delta_y_mm * multiplier; - block->speed_e = delta_e_mm * multiplier; - block->nominal_speed = block->millimeters * multiplier; - block->nominal_rate = ceil(block->step_event_count * multiplier / 60); - - if(block->nominal_rate < 120) - block->nominal_rate = 120; - block->entry_speed = safe_speed(block); - - // Compute the acceleration rate for the trapezoid generator. - float travel_per_step = block->millimeters/block->step_event_count; - if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { - block->acceleration_st = ceil( (retract_acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - } - else { - block->acceleration_st = ceil( (acceleration)/travel_per_step); // convert to: acceleration steps/sec^2 - float tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - // Limit acceleration per axis - if((tmp_acceleration * block->steps_x) > axis_steps_per_sqr_second[X_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_y) > axis_steps_per_sqr_second[Y_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_e) > axis_steps_per_sqr_second[E_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - if((tmp_acceleration * block->steps_z) > axis_steps_per_sqr_second[Z_AXIS]) { - block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; - tmp_acceleration = (float)block->acceleration_st / (float)block->step_event_count; - } - } - block->acceleration = block->acceleration_st * travel_per_step; - block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); - - #ifdef ADVANCE - // Calculate advance rate - if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { - block->advance_rate = 0; - block->advance = 0; - } - else { - long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); - float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; - block->advance = advance; - if(acc_dist == 0) { - block->advance_rate = 0; - } - else { - block->advance_rate = advance / (float)acc_dist; - } - } - #endif // ADVANCE - - // compute a preliminary conservative acceleration trapezoid - float safespeed = safe_speed(block); - calculate_trapezoid_for_block(block, safespeed, safespeed); - - // Compute direction bits for this block - block->direction_bits = 0; - if (target[X_AXIS] < position[X_AXIS]) { - block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<. +*/ + +/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ + +/* + Reasoning behind the mathematics in this module (in the key of 'Mathematica'): + + s == speed, a == acceleration, t == time, d == distance + + Basic definitions: + + Speed[s_, a_, t_] := s + (a*t) + Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] + + Distance to reach a specific speed with a constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] + d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() + + Speed after a given distance of travel with constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] + m -> Sqrt[2 a d + s^2] + + DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] + + When to start braking (di) to reach a specified destionation speed (s2) after accelerating + from initial speed s1 without ever stopping at a plateau: + + Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] + di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() + + IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) +*/ + + +//#include +//#include +//#include + +#include "Marlin.h" +#include "Configuration.h" +#include "pins.h" +#include "fastio.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" +#include "ultralcd.h" + +//=========================================================================== +//=============================public variables ============================ +//=========================================================================== + +unsigned long minsegmenttime; +float max_feedrate[4]; // set the max speeds +float axis_steps_per_unit[4]; +unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +float minimumfeedrate; +float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +float max_z_jerk; +float mintravelfeedrate; +unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + +// The current position of the tool in absolute steps +long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode +static float previous_speed[4]; // Speed of previous path line segment +static float previous_nominal_speed; // Nominal speed of previous path line segment + +#ifdef AUTOTEMP +float high_e_speed=0; +#endif + + +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== +static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +static volatile unsigned char block_buffer_head; // Index of the next block to be pushed +static volatile unsigned char block_buffer_tail; // Index of the block to process now + +// Used for the frequency limit +static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations +static long x_segment_time[3]={0,0,0}; // Segment times (in us). Used for speed calculations +static long y_segment_time[3]={0,0,0}; + +// Returns the index of the next block in the ring buffer +// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. +static int8_t next_block_index(int8_t block_index) { + block_index++; + if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; } + return(block_index); +} + + +// Returns the index of the previous block in the ring buffer +static int8_t prev_block_index(int8_t block_index) { + if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; } + block_index--; + return(block_index); +} + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + +// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the +// given acceleration: +inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { + if (acceleration!=0) { + return((target_rate*target_rate-initial_rate*initial_rate)/ + (2.0*acceleration)); + } + else { + return 0.0; // acceleration was 0, set acceleration distance to 0 + } +} + +// This function gives you the point at which you must start braking (at the rate of -acceleration) if +// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after +// a total travel of distance. This can be used to compute the intersection point between acceleration and +// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) + +inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { + if (acceleration!=0) { + return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ + (4.0*acceleration) ); + } + else { + return 0.0; // acceleration was 0, set intersection distance to 0 + } +} + +// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. + +void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) { + unsigned long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) + unsigned long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) + + // Limit minimal step rate (Otherwise the timer will overflow.) + if(initial_rate <120) {initial_rate=120; } + if(final_rate < 120) {final_rate=120; } + + long acceleration = block->acceleration_st; + int32_t accelerate_steps = + ceil(estimate_acceleration_distance(block->initial_rate, block->nominal_rate, acceleration)); + int32_t decelerate_steps = + floor(estimate_acceleration_distance(block->nominal_rate, block->final_rate, -acceleration)); + + // Calculate the size of Plateau of Nominal Rate. + int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; + + // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will + // 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 = max(accelerate_steps,0); // Check limits due to numerical round-off + accelerate_steps = min(accelerate_steps,block->step_event_count); + plateau_steps = 0; + } + + #ifdef ADVANCE + long initial_advance = block->advance*entry_factor*entry_factor; + long final_advance = block->advance*exit_factor*exit_factor; + #endif // ADVANCE + + // block->accelerate_until = accelerate_steps; + // block->decelerate_after = accelerate_steps+plateau_steps; + + CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section + if(block->busy == false) { // Don't update variables if block is busy. + block->accelerate_until = accelerate_steps; + block->decelerate_after = accelerate_steps+plateau_steps; + block->initial_rate = initial_rate; + block->final_rate = final_rate; + #ifdef ADVANCE + block->initial_advance = initial_advance; + block->final_advance = final_advance; + #endif //ADVANCE + } + CRITICAL_SECTION_END; +} + +// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the +// acceleration within the allotted distance. +inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { + return sqrt(target_velocity*target_velocity-2*acceleration*distance); +} + +// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. +// This method will calculate the junction jerk as the euclidean distance between the nominal +// velocities of the respective blocks. +//inline float junction_jerk(block_t *before, block_t *after) { +// return sqrt( +// pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); +//} + + +// The kernel called by planner_recalculate() when scanning the plan from last to first entry. +void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!current) { return; } + + if (next) { + // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising. + // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and + // check for maximum allowable speed reductions to ensure maximum possible planned speed. + if (current->entry_speed != current->max_entry_speed) { + + // If nominal length true, max junction speed is guaranteed to be reached. Only compute + // for max allowable speed if block is decelerating and nominal length is false. + if ((!current->nominal_length_flag) && (current->max_entry_speed > next->entry_speed)) { + current->entry_speed = min( current->max_entry_speed, + max_allowable_speed(-current->acceleration,next->entry_speed,current->millimeters)); + } else { + current->entry_speed = current->max_entry_speed; + } + current->recalculate_flag = true; + + } + } // Skip last block. Already initialized and set for recalculation. +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the reverse pass. +void planner_reverse_pass() { + char block_index = block_buffer_head; + if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { + block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); + block_t *block[3] = { NULL, NULL, NULL }; + while(block_index != block_buffer_tail) { + block_index = prev_block_index(block_index); + block[2]= block[1]; + block[1]= block[0]; + block[0] = &block_buffer[block_index]; + planner_reverse_pass_kernel(block[0], block[1], block[2]); + } + } +} + +// The kernel called by planner_recalculate() when scanning the plan from first to last entry. +void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!previous) { return; } + + // If the previous block is an acceleration block, but it is not long enough to complete the + // full speed change within the block, we need to adjust the entry speed accordingly. Entry + // speeds have already been reset, maximized, and reverse planned by reverse planner. + // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck. + if (!previous->nominal_length_flag) { + if (previous->entry_speed < current->entry_speed) { + double entry_speed = min( current->entry_speed, + max_allowable_speed(-previous->acceleration,previous->entry_speed,previous->millimeters) ); + + // Check for junction speed change + if (current->entry_speed != entry_speed) { + current->entry_speed = entry_speed; + current->recalculate_flag = true; + } + } + } +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the forward pass. +void planner_forward_pass() { + char block_index = block_buffer_tail; + block_t *block[3] = { NULL, NULL, NULL }; + + while(block_index != block_buffer_head) { + block[0] = block[1]; + block[1] = block[2]; + block[2] = &block_buffer[block_index]; + planner_forward_pass_kernel(block[0],block[1],block[2]); + block_index = next_block_index(block_index); + } + planner_forward_pass_kernel(block[1], block[2], NULL); +} + +// Recalculates the trapezoid speed profiles for all blocks in the plan according to the +// entry_factor for each junction. Must be called by planner_recalculate() after +// updating the blocks. +void planner_recalculate_trapezoids() { + int8_t block_index = block_buffer_tail; + block_t *current; + block_t *next = NULL; + + while(block_index != block_buffer_head) { + current = next; + next = &block_buffer[block_index]; + if (current) { + // Recalculate if current block entry or exit junction speed has changed. + if (current->recalculate_flag || next->recalculate_flag) { + // NOTE: Entry and exit factors always > 0 by all previous logic operations. + calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed, + next->entry_speed/current->nominal_speed); + current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed + } + } + block_index = next_block_index( block_index ); + } + // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated. + if(next != NULL) { + calculate_trapezoid_for_block(next, next->entry_speed/next->nominal_speed, + MINIMUM_PLANNER_SPEED/next->nominal_speed); + next->recalculate_flag = false; + } +} + +// Recalculates the motion plan according to the following algorithm: +// +// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) +// so that: +// a. The junction jerk is within the set limit +// b. No speed reduction within one block requires faster deceleration than the one, true constant +// acceleration. +// 2. Go over every block in chronological order and dial down junction speed reduction values if +// a. The speed increase within one block would require faster accelleration than the one, true +// constant acceleration. +// +// When these stages are complete all blocks have an entry_factor that will allow all speed changes to +// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than +// the set limit. Finally it will: +// +// 3. Recalculate trapezoids for all blocks. + +void planner_recalculate() { + planner_reverse_pass(); + planner_forward_pass(); + planner_recalculate_trapezoids(); +} + +void plan_init() { + block_buffer_head = 0; + block_buffer_tail = 0; + memset(position, 0, sizeof(position)); // clear position + previous_speed[0] = 0.0; + previous_speed[1] = 0.0; + previous_speed[2] = 0.0; + previous_speed[3] = 0.0; + previous_nominal_speed = 0.0; +} + + +void plan_discard_current_block() { + if (block_buffer_head != block_buffer_tail) { + block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); + } +} + +block_t *plan_get_current_block() { + if (block_buffer_head == block_buffer_tail) { + return(NULL); + } + block_t *block = &block_buffer[block_buffer_tail]; + block->busy = true; + return(block); +} + +#ifdef AUTOTEMP +void getHighESpeed() +{ + if(degTargetHotend0()+2high) + { + high=se; + } + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + high_e_speed=high*axis_steps_per_unit[E_AXIS]/(1000000.0); //so it is independent of the esteps/mm. before + + float g=AUTOTEMP_MIN+high_e_speed*AUTOTEMP_FACTOR; + float t=constrain(AUTOTEMP_MIN,g,AUTOTEMP_MAX); + setTargetHotend0(t); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR("highe",high_e_speed); + SERIAL_ECHOPAIR(" t",t); + SERIAL_ECHOLN(""); +} +#endif + +void check_axes_activity() { + unsigned char x_active = 0; + unsigned char y_active = 0; + unsigned char z_active = 0; + unsigned char e_active = 0; + block_t *block; + + if(block_buffer_tail != block_buffer_head) { + char block_index = block_buffer_tail; + while(block_index != block_buffer_head) { + block = &block_buffer[block_index]; + if(block->steps_x != 0) x_active++; + if(block->steps_y != 0) y_active++; + if(block->steps_z != 0) z_active++; + if(block->steps_e != 0) e_active++; + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + } + if((DISABLE_X) && (x_active == 0)) disable_x(); + if((DISABLE_Y) && (y_active == 0)) disable_y(); + if((DISABLE_Z) && (z_active == 0)) disable_z(); + if((DISABLE_E) && (e_active == 0)) disable_e(); +} + + +float junction_deviation = 0.1; +// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in +// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration +// calculation the caller must also provide the physical length of the line in millimeters. +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate) +{ + // Calculate the buffer head after we push this byte + int next_buffer_head = next_block_index(block_buffer_head); + + // If the buffer is full: good! That means we are well ahead of the robot. + // Rest here until there is room in the buffer. + while(block_buffer_tail == next_buffer_head) { + manage_heater(); + manage_inactivity(1); + LCD_STATUS; + } + + // The target position of the tool in absolute steps + // Calculate target position in absolute steps + //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow + long target[4]; + target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + + // Prepare to set up new block + block_t *block = &block_buffer[block_buffer_head]; + + // Mark block as not busy (Not executed by the stepper interrupt) + block->busy = false; + + // Number of steps for each axis + block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); + block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); + block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); + block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); + block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); + + // Bail if this is a zero-length block + if (block->step_event_count <=dropsegments) { return; }; + + // Compute direction bits for this block + block->direction_bits = 0; + if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<steps_x != 0) enable_x(); + if(block->steps_y != 0) enable_y(); + if(block->steps_z != 0) enable_z(); + if(block->steps_e != 0) enable_e(); + + float delta_mm[4]; + delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; + delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; + delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; + delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; + block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + + square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); + float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides + + // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. + float inverse_second = feed_rate * inverse_millimeters; + + block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 + block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 + + // segment time im micro seconds + long segment_time = lround(1000000.0/inverse_second); + + + if (block->steps_e == 0) { + if(feed_rate0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { + if (segment_time max_feedrate[i]) + speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); + } + +// Max segement time in us. +#ifdef XY_FREQUENCY_LIMIT +#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT) + + // Check and limit the xy direction change frequency + unsigned char direction_change = block->direction_bits ^ old_direction_bits; + old_direction_bits = block->direction_bits; + + if((direction_change & (1< max_feedrate[i]) + speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); + /* + if(speed_factor < 0.1) { + Serial.print("speed factor : "); Serial.println(speed_factor); + Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); + } + */ + } + for(unsigned char i=0; i < 4; i++) { + current_speed[i] *= speed_factor; + } + block->nominal_speed *= speed_factor; + block->nominal_rate *= speed_factor; + } + + // Compute and limit the acceleration rate for the trapezoid generator. + float steps_per_mm = block->step_event_count/block->millimeters; + if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { + block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 + } + else { + block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 + // Limit acceleration per axis + if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_y / (float)block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_e / (float)block->step_event_count) > axis_steps_per_sqr_second[E_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; + } + block->acceleration = block->acceleration_st / steps_per_mm; + block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); + +#if 0 // Use old jerk for now + // Compute path unit vector + double unit_vec[3]; + + unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; + unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; + unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; + + // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. + // Let a circle be tangent to both previous and current path line segments, where the junction + // deviation is defined as the distance from the junction to the closest edge of the circle, + // colinear with the circle center. The circular segment joining the two paths represents the + // path of centripetal acceleration. Solve for max velocity based on max acceleration about the + // radius of the circle, defined indirectly by junction deviation. This may be also viewed as + // path width or max_jerk in the previous grbl version. This approach does not actually deviate + // from path, but used as a robust way to compute cornering speeds, as it takes into account the + // nonlinearities of both the junction angle and junction velocity. + double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed + + // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles. + if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { + // Compute cosine of angle between previous and current path. (prev_unit_vec is negative) + // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity. + double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] + - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] + - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; + + // Skip and use default max junction speed for 0 degree acute junction. + if (cos_theta < 0.95) { + vmax_junction = min(previous_nominal_speed,block->nominal_speed); + // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds. + if (cos_theta > -0.95) { + // Compute maximum junction velocity based on maximum acceleration and junction deviation + double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. + vmax_junction = min(vmax_junction, + sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); + } + } + } +#endif + // Start with a safe speed + float vmax_junction = max_xy_jerk/2; + if(abs(current_speed[Z_AXIS]) > max_z_jerk/2) + vmax_junction = max_z_jerk/2; + vmax_junction = min(vmax_junction, block->nominal_speed); + + if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { + float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); + if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { + vmax_junction = block->nominal_speed; + } + if (jerk > max_xy_jerk) { + vmax_junction *= (max_xy_jerk/jerk); + } + if(abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { + vmax_junction *= (max_z_jerk/abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); + } + } + block->max_entry_speed = vmax_junction; + + // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. + double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); + block->entry_speed = min(vmax_junction, v_allowable); + + // Initialize planner efficiency flags + // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. + // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then + // the current block and next block junction speeds are guaranteed to always be at their maximum + // junction speeds in deceleration and acceleration, respectively. This is due to how the current + // block nominal speed limits both the current and next maximum junction speeds. Hence, in both + // the reverse and forward planners, the corresponding block junction speed will always be at the + // the maximum junction speed and may always be ignored for any speed reduction checks. + if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } + else { block->nominal_length_flag = false; } + block->recalculate_flag = true; // Always calculate trapezoid for new block + + // Update previous path unit_vector and nominal speed + memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[] + previous_nominal_speed = block->nominal_speed; + + #ifdef ADVANCE + // Calculate advance rate + if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { + block->advance_rate = 0; + block->advance = 0; + } + else { + long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); + float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * + (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; + block->advance = advance; + if(acc_dist == 0) { + block->advance_rate = 0; + } + else { + block->advance_rate = advance / (float)acc_dist; + } + } + #endif // ADVANCE + + + + + calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, + MINIMUM_PLANNER_SPEED/block->nominal_speed); + + // Move buffer head + block_buffer_head = next_buffer_head; + + // Update position + memcpy(position, target, sizeof(target)); // position[] = target[] + + planner_recalculate(); + #ifdef AUTOTEMP + getHighESpeed(); + #endif + st_wake_up(); +} + +void plan_set_position(const float &x, const float &y, const float &z, const float &e) +{ + position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. + previous_speed[0] = 0.0; + previous_speed[1] = 0.0; + previous_speed[2] = 0.0; + previous_speed[3] = 0.0; +} + diff --git a/Marlin/planner.h b/Marlin/planner.h index c5bc5b8aaf..be1587d6b8 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -1,95 +1,98 @@ -/* - planner.h - buffers movement commands and manages the acceleration profile plan - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -// This module is to be considered a sub-module of stepper.c. Please don't include -// this file from any other module. - -#ifndef planner_h -#define planner_h - -#include "Configuration.h" - -// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in -// the source g-code and may never actually be reached if acceleration management is active. -typedef struct { - // Fields used by the bresenham algorithm for tracing the line - long steps_x, steps_y, steps_z, steps_e; // Step count along each axis - long step_event_count; // The number of step events required to complete this block - volatile long accelerate_until; // The index of the step event on which to stop acceleration - volatile long decelerate_after; // The index of the step event on which to start decelerating - volatile long acceleration_rate; // The acceleration rate used for acceleration calculation - unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) - #ifdef ADVANCE - long advance_rate; - volatile long initial_advance; - volatile long final_advance; - float advance; - #endif - - // Fields used by the motion planner to manage acceleration - float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis - float nominal_speed; // The nominal speed for this block in mm/min - float millimeters; // The total travel of this block in mm - float entry_speed; - float acceleration; // acceleration mm/sec^2 - - // Settings for the trapezoid generator - long nominal_rate; // The nominal step rate for this block in step_events/sec - volatile long initial_rate; // The jerk-adjusted step rate at start of block - volatile long final_rate; // The minimal rate at exit - long acceleration_st; // acceleration steps/sec^2 - volatile char busy; -} block_t; - -// Initialize the motion plan subsystem -void plan_init(); - -// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in -// millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate); - -// Set position. Used for G92 instructions. -void plan_set_position(const float &x, const float &y, const float &z, const float &e); - - -// Called when the current block is no longer needed. Discards the block and makes the memory -// availible for new blocks. -void plan_discard_current_block(); - -// Gets the current block. Returns NULL if buffer empty -block_t *plan_get_current_block(); - -void check_axes_activity(); - -extern unsigned long minsegmenttime; -extern float max_feedrate[4]; // set the max speeds -extern float axis_steps_per_unit[4]; -extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -extern float minimumfeedrate; -extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -extern float max_z_jerk; -extern float mintravelfeedrate; -extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; -#ifdef AUTOTEMP -extern float high_e_speed; -#endif -#endif +/* + planner.h - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +// This module is to be considered a sub-module of stepper.c. Please don't include +// this file from any other module. + +#ifndef planner_h +#define planner_h + +#include "Configuration.h" + +// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in +// the source g-code and may never actually be reached if acceleration management is active. +typedef struct { + // Fields used by the bresenham algorithm for tracing the line + long steps_x, steps_y, steps_z, steps_e; // Step count along each axis + long step_event_count; // The number of step events required to complete this block + long accelerate_until; // The index of the step event on which to stop acceleration + long decelerate_after; // The index of the step event on which to start decelerating + long acceleration_rate; // The acceleration rate used for acceleration calculation + unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) + #ifdef ADVANCE +// long advance_rate; +// volatile long initial_advance; +// volatile long final_advance; +// float advance; + #endif + + // Fields used by the motion planner to manage acceleration +// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis + float nominal_speed; // The nominal speed for this block in mm/min + float entry_speed; // Entry speed at previous-current junction in mm/min + float max_entry_speed; // Maximum allowable junction entry speed in mm/min + float millimeters; // The total travel of this block in mm + float acceleration; // acceleration mm/sec^2 + unsigned char recalculate_flag; // Planner flag to recalculate trapezoids on entry junction + unsigned char nominal_length_flag; // Planner flag for nominal speed always reached + + // Settings for the trapezoid generator + unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec + unsigned long initial_rate; // The jerk-adjusted step rate at start of block + unsigned long final_rate; // The minimal rate at exit + unsigned long acceleration_st; // acceleration steps/sec^2 + volatile char busy; +} block_t; + +// Initialize the motion plan subsystem +void plan_init(); + +// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in +// millimaters. Feed rate specifies the speed of the motion. +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate); + +// Set position. Used for G92 instructions. +void plan_set_position(const float &x, const float &y, const float &z, const float &e); + + +// Called when the current block is no longer needed. Discards the block and makes the memory +// availible for new blocks. +void plan_discard_current_block(); + +// Gets the current block. Returns NULL if buffer empty +block_t *plan_get_current_block(); + +void check_axes_activity(); + +extern unsigned long minsegmenttime; +extern float max_feedrate[4]; // set the max speeds +extern float axis_steps_per_unit[4]; +extern unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +extern float minimumfeedrate; +extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +extern float max_z_jerk; +extern float mintravelfeedrate; +extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; +#ifdef AUTOTEMP +extern float high_e_speed; +#endif +#endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 23066ef320..2e232201bf 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -1,664 +1,669 @@ -/* - stepper.c - stepper motor driver: executes motion plans using stepper motors - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith - and Philipp Tiefenbacher. */ - -#include "stepper.h" -#include "Configuration.h" -#include "Marlin.h" -#include "planner.h" -#include "pins.h" -#include "fastio.h" -#include "temperature.h" -#include "ultralcd.h" - -#include "speed_lookuptable.h" - - - -//=========================================================================== -//=============================public variables ============================ -//=========================================================================== -block_t *current_block; // A pointer to the block currently being traced - - - -//=========================================================================== -//=============================private variables ============================ -//=========================================================================== -//static makes it inpossible to be called from outside of this file by extern.! - -// Variables used by The Stepper Driver Interrupt -static unsigned char out_bits; // The next stepping-bits to be output -static long counter_x, // Counter variables for the bresenham line tracer - counter_y, - counter_z, - counter_e; -static unsigned long step_events_completed; // The number of step events executed in the current block -#ifdef ADVANCE - static long advance_rate, advance, final_advance = 0; - static short old_advance = 0; - static short e_steps; -#endif -static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. -static long acceleration_time, deceleration_time; -//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; -static unsigned short acc_step_rate; // needed for deccelaration start point -static char step_loops; - -volatile long endstops_trigsteps[3]={0,0,0}; -volatile long endstops_stepsTotal,endstops_stepsDone; -static volatile bool endstops_hit=false; - -// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. -// for debugging purposes only, should be disabled by default -#ifdef DEBUG_STEPS - volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; - volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; -#endif - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== - - -// intRes = intIn1 * intIn2 >> 16 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 24 bit result -#define MultiU16X8toH16(intRes, charIn1, intIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %A1, %A2 \n\t" \ -"add %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r0 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (charIn1), \ -"d" (intIn2) \ -: \ -"r26" \ -) - -// intRes = longIn1 * longIn2 >> 24 -// uses: -// r26 to store 0 -// r27 to store the byte 1 of the 48bit result -#define MultiU24X24toH16(intRes, longIn1, longIn2) \ -asm volatile ( \ -"clr r26 \n\t" \ -"mul %A1, %B2 \n\t" \ -"mov r27, r1 \n\t" \ -"mul %B1, %C2 \n\t" \ -"movw %A0, r0 \n\t" \ -"mul %C1, %C2 \n\t" \ -"add %B0, r0 \n\t" \ -"mul %C1, %B2 \n\t" \ -"add %A0, r0 \n\t" \ -"adc %B0, r1 \n\t" \ -"mul %A1, %C2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %B2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %C1, %A2 \n\t" \ -"add r27, r0 \n\t" \ -"adc %A0, r1 \n\t" \ -"adc %B0, r26 \n\t" \ -"mul %B1, %A2 \n\t" \ -"add r27, r1 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"lsr r27 \n\t" \ -"adc %A0, r26 \n\t" \ -"adc %B0, r26 \n\t" \ -"clr r1 \n\t" \ -: \ -"=&r" (intRes) \ -: \ -"d" (longIn1), \ -"d" (longIn2) \ -: \ -"r26" , "r27" \ -) - -// Some useful constants - -#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<step_event_count; - endstops_stepsDone=stepstaken; - endstops_trigsteps[0]=current_block->steps_x; - endstops_trigsteps[1]=current_block->steps_y; - endstops_trigsteps[2]=current_block->steps_z; - - endstops_hit=true; -} - -void checkHitEndstops() -{ - if( !endstops_hit) - return; - float endstops_triggerpos[3]={0,0,0}; - float ratiodone=endstops_stepsDone/float(endstops_stepsTotal); //ratio of current_block thas was performed - - endstops_triggerpos[0]=current_position[0]-(endstops_trigsteps[0]*ratiodone)/float(axis_steps_per_unit[0]); - endstops_triggerpos[1]=current_position[1]-(endstops_trigsteps[1]*ratiodone)/float(axis_steps_per_unit[1]); - endstops_triggerpos[2]=current_position[2]-(endstops_trigsteps[2]*ratiodone)/float(axis_steps_per_unit[2]); - SERIAL_ECHO_START; - SERIAL_ECHOPGM("endstops hit: "); - SERIAL_ECHOPAIR(" X:",endstops_triggerpos[0]); - SERIAL_ECHOPAIR(" Y:",endstops_triggerpos[1]); - SERIAL_ECHOPAIR(" Z:",endstops_triggerpos[2]); - SERIAL_ECHOLN(""); - endstops_hit=false; -} - -void endstops_hit_on_purpose() -{ - endstops_hit=false; -} - -// __________________________ -// /| |\ _________________ ^ -// / | | \ /| |\ | -// / | | \ / | | \ s -// / | | | | | \ p -// / | | | | | \ e -// +-----+------------------------+---+--+---------------+----+ e -// | BLOCK 1 | BLOCK 2 | d -// -// time -----> -// -// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates -// first block->accelerate_until step_events_completed, then keeps going at constant speed until -// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. -// The slope of acceleration is calculated with the leib ramp alghorithm. - -void st_wake_up() { - // TCNT1 = 0; - ENABLE_STEPPER_DRIVER_INTERRUPT(); -} - -inline unsigned short calc_timer(unsigned short step_rate) { - unsigned short timer; - if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; - - if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times - step_rate = step_rate >> 2; - step_loops = 4; - } - else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times - step_rate = step_rate >> 1; - step_loops = 2; - } - else { - step_loops = 1; - } - - if(step_rate < 32) step_rate = 32; - step_rate -= 32; // Correct for minimal speed - if(step_rate >= (8*256)){ // higher step rate - unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; - unsigned char tmp_step_rate = (step_rate & 0x00ff); - unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); - MultiU16X8toH16(timer, tmp_step_rate, gain); - timer = (unsigned short)pgm_read_word_near(table_address) - timer; - } - else { // lower step rates - unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; - table_address += ((step_rate)>>1) & 0xfffc; - timer = (unsigned short)pgm_read_word_near(table_address); - timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); - } - if(timer < 100) timer = 100; - return timer; -} - -// Initializes the trapezoid generator from the current block. Called whenever a new -// block begins. -inline void trapezoid_generator_reset() { - #ifdef ADVANCE - advance = current_block->initial_advance; - final_advance = current_block->final_advance; - #endif - deceleration_time = 0; - // advance_rate = current_block->advance_rate; - // step_rate to timer interval - acc_step_rate = current_block->initial_rate; - acceleration_time = calc_timer(acc_step_rate); - OCR1A = acceleration_time; -} - -// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. -// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. -ISR(TIMER1_COMPA_vect) -{ - if(busy){ - SERIAL_ERROR_START - SERIAL_ERROR(*(unsigned short *)OCR1A); - SERIAL_ERRORLNPGM(" ISR overtaking itself."); - return; - } // The busy-flag is used to avoid reentering this interrupt - - busy = true; - sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) - - // If there is no current block, attempt to pop one from the buffer - if (current_block == NULL) { - // Anything in the buffer? - current_block = plan_get_current_block(); - if (current_block != NULL) { - trapezoid_generator_reset(); - counter_x = -(current_block->step_event_count >> 1); - counter_y = counter_x; - counter_z = counter_x; - counter_e = counter_x; - step_events_completed = 0; - #ifdef ADVANCE - e_steps = 0; - #endif - } - else { -// DISABLE_STEPPER_DRIVER_INTERRUPT(); - } - } - - if (current_block != NULL) { - // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt - out_bits = current_block->direction_bits; - - #ifdef ADVANCE - // Calculate E early. - counter_e += current_block->steps_e; - if (counter_e > 0) { - counter_e -= current_block->step_event_count; - if ((out_bits & (1<> 16) - old_advance); - CRITICAL_SECTION_END; - old_advance = advance >> 16; - #endif //ADVANCE - - // Set direction en check limit switches - if ((out_bits & (1< -1 - if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { - endstops_triggered(step_events_completed); - step_events_completed = current_block->step_event_count; - } - #endif - } - else { // +direction - WRITE(X_DIR_PIN,!INVERT_X_DIR); - #ifdef DEBUG_STEPS - count_direction[X_AXIS]=1; - #endif - #if X_MAX_PIN > -1 - if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ - endstops_triggered(step_events_completed); - step_events_completed = current_block->step_event_count; - } - #endif - } - - if ((out_bits & (1< -1 - if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { - endstops_triggered(step_events_completed); - step_events_completed = current_block->step_event_count; - } - #endif - } - else { // +direction - WRITE(Y_DIR_PIN,!INVERT_Y_DIR); - #ifdef DEBUG_STEPS - count_direction[Y_AXIS]=1; - #endif - #if Y_MAX_PIN > -1 - if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ - endstops_triggered(step_events_completed); - step_events_completed = current_block->step_event_count; - } - #endif - } - - if ((out_bits & (1< -1 - if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { - endstops_triggered(step_events_completed); - step_events_completed = current_block->step_event_count; - } - #endif - } - else { // +direction - WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - #ifdef DEBUG_STEPS - count_direction[Z_AXIS]=1; - #endif - #if Z_MAX_PIN > -1 - if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ - endstops_triggered(step_events_completed); - step_events_completed = current_block->step_event_count; - } - #endif - } - - #ifndef ADVANCE - if ((out_bits & (1<steps_x; - if (counter_x > 0) { - WRITE(X_STEP_PIN, HIGH); - counter_x -= current_block->step_event_count; - WRITE(X_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[X_AXIS]+=count_direction[X_AXIS]; - #endif - } - - counter_y += current_block->steps_y; - if (counter_y > 0) { - WRITE(Y_STEP_PIN, HIGH); - counter_y -= current_block->step_event_count; - WRITE(Y_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Y_AXIS]+=count_direction[Y_AXIS]; - #endif - } - - counter_z += current_block->steps_z; - if (counter_z > 0) { - WRITE(Z_STEP_PIN, HIGH); - counter_z -= current_block->step_event_count; - WRITE(Z_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Z_AXIS]+=count_direction[Z_AXIS]; - #endif - } - - #ifndef ADVANCE - counter_e += current_block->steps_e; - if (counter_e > 0) { - WRITE(E_STEP_PIN, HIGH); - counter_e -= current_block->step_event_count; - WRITE(E_STEP_PIN, LOW); - } - #endif //!ADVANCE - step_events_completed += 1; - if(step_events_completed >= current_block->step_event_count) break; - } - // Calculare new timer value - unsigned short timer; - unsigned short step_rate; - if (step_events_completed <= current_block->accelerate_until) { - MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); - acc_step_rate += current_block->initial_rate; - - // upper limit - if(acc_step_rate > current_block->nominal_rate) - acc_step_rate = current_block->nominal_rate; - - // step_rate to timer interval - timer = calc_timer(acc_step_rate); - #ifdef ADVANCE - advance += advance_rate; - #endif - acceleration_time += timer; - OCR1A = timer; - } - else if (step_events_completed > current_block->decelerate_after) { - MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); - - if(step_rate > acc_step_rate) { // Check step_rate stays positive - step_rate = current_block->final_rate; - } - else { - step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. - } - - // lower limit - if(step_rate < current_block->final_rate) - step_rate = current_block->final_rate; - - // step_rate to timer interval - timer = calc_timer(step_rate); - #ifdef ADVANCE - advance -= advance_rate; - if(advance < final_advance) - advance = final_advance; - #endif //ADVANCE - deceleration_time += timer; - OCR1A = timer; - } - // If current block is finished, reset pointer - if (step_events_completed >= current_block->step_event_count) { - current_block = NULL; - plan_discard_current_block(); - } - } - cli(); // disable interrupts - busy=false; -} - -#ifdef ADVANCE - unsigned char old_OCR0A; - // Timer interrupt for E. e_steps is set in the main routine; - // Timer 0 is shared with millies - ISR(TIMER0_COMPA_vect) - { - // Critical section needed because Timer 1 interrupt has higher priority. - // The pin set functions are placed on trategic position to comply with the stepper driver timing. - WRITE(E_STEP_PIN, LOW); - // Set E direction (Depends on E direction + advance) - if (e_steps < 0) { - WRITE(E_DIR_PIN,INVERT_E_DIR); - e_steps++; - WRITE(E_STEP_PIN, HIGH); - } - if (e_steps > 0) { - WRITE(E_DIR_PIN,!INVERT_E_DIR); - e_steps--; - WRITE(E_STEP_PIN, HIGH); - } - old_OCR0A += 25; // 10kHz interrupt - OCR0A = old_OCR0A; - } -#endif // ADVANCE - -void st_init() -{ - //Initialize Dir Pins - #if X_DIR_PIN > -1 - SET_OUTPUT(X_DIR_PIN); - #endif - #if Y_DIR_PIN > -1 - SET_OUTPUT(Y_DIR_PIN); - #endif - #if Z_DIR_PIN > -1 - SET_OUTPUT(Z_DIR_PIN); - #endif - #if E_DIR_PIN > -1 - SET_OUTPUT(E_DIR_PIN); - #endif - - //Initialize Enable Pins - steppers default to disabled. - - #if (X_ENABLE_PIN > -1) - SET_OUTPUT(X_ENABLE_PIN); - if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); - #endif - #if (Y_ENABLE_PIN > -1) - SET_OUTPUT(Y_ENABLE_PIN); - if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); - #endif - #if (Z_ENABLE_PIN > -1) - SET_OUTPUT(Z_ENABLE_PIN); - if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); - #endif - #if (E_ENABLE_PIN > -1) - SET_OUTPUT(E_ENABLE_PIN); - if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); - #endif - - //endstops and pullups - #ifdef ENDSTOPPULLUPS - #if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); - WRITE(X_MIN_PIN,HIGH); - #endif - #if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); - WRITE(X_MAX_PIN,HIGH); - #endif - #if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); - WRITE(Y_MIN_PIN,HIGH); - #endif - #if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); - WRITE(Y_MAX_PIN,HIGH); - #endif - #if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); - WRITE(Z_MIN_PIN,HIGH); - #endif - #if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); - WRITE(Z_MAX_PIN,HIGH); - #endif - #else //ENDSTOPPULLUPS - #if X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); - #endif - #if X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); - #endif - #if Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); - #endif - #if Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); - #endif - #if Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); - #endif - #if Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); - #endif - #endif //ENDSTOPPULLUPS - - - //Initialize Step Pins - #if (X_STEP_PIN > -1) - SET_OUTPUT(X_STEP_PIN); - #endif - #if (Y_STEP_PIN > -1) - SET_OUTPUT(Y_STEP_PIN); - #endif - #if (Z_STEP_PIN > -1) - SET_OUTPUT(Z_STEP_PIN); - #endif - #if (E_STEP_PIN > -1) - SET_OUTPUT(E_STEP_PIN); - #endif - - // waveform generation = 0100 = CTC - TCCR1B &= ~(1<. +*/ + +/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith + and Philipp Tiefenbacher. */ + +#include "stepper.h" +#include "Configuration.h" +#include "Marlin.h" +#include "planner.h" +#include "pins.h" +#include "fastio.h" +#include "temperature.h" +#include "ultralcd.h" + +#include "speed_lookuptable.h" + + + +//=========================================================================== +//=============================public variables ============================ +//=========================================================================== +block_t *current_block; // A pointer to the block currently being traced + + + +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== +//static makes it inpossible to be called from outside of this file by extern.! + +// Variables used by The Stepper Driver Interrupt +static unsigned char out_bits; // The next stepping-bits to be output +static long counter_x, // Counter variables for the bresenham line tracer + counter_y, + counter_z, + counter_e; +static unsigned long step_events_completed; // The number of step events executed in the current block +#ifdef ADVANCE + static long advance_rate, advance, final_advance = 0; + static short old_advance = 0; + static short e_steps; +#endif +static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. +static long acceleration_time, deceleration_time; +//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; +static unsigned short acc_step_rate; // needed for deccelaration start point +static char step_loops; + +volatile long endstops_trigsteps[3]={0,0,0}; +volatile long endstops_stepsTotal,endstops_stepsDone; +static volatile bool endstops_hit=false; + +// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. +// for debugging purposes only, should be disabled by default +#ifdef DEBUG_STEPS + volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; + volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; +#endif + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + + +// intRes = intIn1 * intIn2 >> 16 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 24 bit result +#define MultiU16X8toH16(intRes, charIn1, intIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %A1, %A2 \n\t" \ +"add %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r0 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (charIn1), \ +"d" (intIn2) \ +: \ +"r26" \ +) + +// intRes = longIn1 * longIn2 >> 24 +// uses: +// r26 to store 0 +// r27 to store the byte 1 of the 48bit result +#define MultiU24X24toH16(intRes, longIn1, longIn2) \ +asm volatile ( \ +"clr r26 \n\t" \ +"mul %A1, %B2 \n\t" \ +"mov r27, r1 \n\t" \ +"mul %B1, %C2 \n\t" \ +"movw %A0, r0 \n\t" \ +"mul %C1, %C2 \n\t" \ +"add %B0, r0 \n\t" \ +"mul %C1, %B2 \n\t" \ +"add %A0, r0 \n\t" \ +"adc %B0, r1 \n\t" \ +"mul %A1, %C2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %B2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %C1, %A2 \n\t" \ +"add r27, r0 \n\t" \ +"adc %A0, r1 \n\t" \ +"adc %B0, r26 \n\t" \ +"mul %B1, %A2 \n\t" \ +"add r27, r1 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"lsr r27 \n\t" \ +"adc %A0, r26 \n\t" \ +"adc %B0, r26 \n\t" \ +"clr r1 \n\t" \ +: \ +"=&r" (intRes) \ +: \ +"d" (longIn1), \ +"d" (longIn2) \ +: \ +"r26" , "r27" \ +) + +// Some useful constants + +#define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<step_event_count; + endstops_stepsDone=stepstaken; + endstops_trigsteps[0]=current_block->steps_x; + endstops_trigsteps[1]=current_block->steps_y; + endstops_trigsteps[2]=current_block->steps_z; + + endstops_hit=true; +} + +void checkHitEndstops() +{ + if( !endstops_hit) + return; + float endstops_triggerpos[3]={0,0,0}; + float ratiodone=endstops_stepsDone/float(endstops_stepsTotal); //ratio of current_block thas was performed + + endstops_triggerpos[0]=current_position[0]-(endstops_trigsteps[0]*ratiodone)/float(axis_steps_per_unit[0]); + endstops_triggerpos[1]=current_position[1]-(endstops_trigsteps[1]*ratiodone)/float(axis_steps_per_unit[1]); + endstops_triggerpos[2]=current_position[2]-(endstops_trigsteps[2]*ratiodone)/float(axis_steps_per_unit[2]); + SERIAL_ECHO_START; + SERIAL_ECHOPGM("endstops hit: "); + SERIAL_ECHOPAIR(" X:",endstops_triggerpos[0]); + SERIAL_ECHOPAIR(" Y:",endstops_triggerpos[1]); + SERIAL_ECHOPAIR(" Z:",endstops_triggerpos[2]); + SERIAL_ECHOLN(""); + endstops_hit=false; +} + +void endstops_hit_on_purpose() +{ + endstops_hit=false; +} + +// __________________________ +// /| |\ _________________ ^ +// / | | \ /| |\ | +// / | | \ / | | \ s +// / | | | | | \ p +// / | | | | | \ e +// +-----+------------------------+---+--+---------------+----+ e +// | BLOCK 1 | BLOCK 2 | d +// +// time -----> +// +// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates +// first block->accelerate_until step_events_completed, then keeps going at constant speed until +// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. +// The slope of acceleration is calculated with the leib ramp alghorithm. + +void st_wake_up() { + // TCNT1 = 0; + if(busy == false) + ENABLE_STEPPER_DRIVER_INTERRUPT(); +} + +inline unsigned short calc_timer(unsigned short step_rate) { + unsigned short timer; + if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; + + if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times + step_rate = (step_rate >> 2)&0x3fff; + step_loops = 4; + } + else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times + step_rate = (step_rate >> 1)&0x7fff; + step_loops = 2; + } + else { + step_loops = 1; + } + + if(step_rate < 32) step_rate = 32; + step_rate -= 32; // Correct for minimal speed + if(step_rate >= (8*256)){ // higher step rate + unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; + unsigned char tmp_step_rate = (step_rate & 0x00ff); + unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); + MultiU16X8toH16(timer, tmp_step_rate, gain); + timer = (unsigned short)pgm_read_word_near(table_address) - timer; + } + else { // lower step rates + unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; + table_address += ((step_rate)>>1) & 0xfffc; + timer = (unsigned short)pgm_read_word_near(table_address); + timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); + } + if(timer < 100) { timer = 100; Serial.print("Steprate to high : "); Serial.println(step_rate); }//(20kHz this should never happen) + return timer; +} + +// Initializes the trapezoid generator from the current block. Called whenever a new +// block begins. +inline void trapezoid_generator_reset() { + #ifdef ADVANCE + advance = current_block->initial_advance; + final_advance = current_block->final_advance; + #endif + deceleration_time = 0; + // step_rate to timer interval + acc_step_rate = current_block->initial_rate; + acceleration_time = calc_timer(acc_step_rate); + OCR1A = acceleration_time; +} + +// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. +// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. +ISR(TIMER1_COMPA_vect) +{ + if(busy){ + SERIAL_ERROR_START + SERIAL_ERROR(*(unsigned short *)OCR1A); + SERIAL_ERRORLNPGM(" ISR overtaking itself."); + return; + } // The busy-flag is used to avoid reentering this interrupt + + busy = true; + sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) + + // If there is no current block, attempt to pop one from the buffer + if (current_block == NULL) { + // Anything in the buffer? + current_block = plan_get_current_block(); + if (current_block != NULL) { + trapezoid_generator_reset(); + counter_x = -(current_block->step_event_count >> 1); + counter_y = counter_x; + counter_z = counter_x; + counter_e = counter_x; + step_events_completed = 0; + #ifdef ADVANCE + e_steps = 0; + #endif + } + else { +// DISABLE_STEPPER_DRIVER_INTERRUPT(); + } + } + + if (current_block != NULL) { + // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt + out_bits = current_block->direction_bits; + + #ifdef ADVANCE + // Calculate E early. + counter_e += current_block->steps_e; + if (counter_e > 0) { + counter_e -= current_block->step_event_count; + if ((out_bits & (1<> 16) - old_advance); + CRITICAL_SECTION_END; + old_advance = advance >> 16; + #endif //ADVANCE + + // Set direction en check limit switches + if ((out_bits & (1< -1 + if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { + // endstops_triggered(step_events_completed); + step_events_completed = current_block->step_event_count; + } + #endif + } + else { // +direction + WRITE(X_DIR_PIN,!INVERT_X_DIR); + #ifdef DEBUG_STEPS + count_direction[X_AXIS]=1; + #endif + #if X_MAX_PIN > -1 + if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ + // endstops_triggered(step_events_completed); + step_events_completed = current_block->step_event_count; + } + #endif + } + + if ((out_bits & (1< -1 + if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { + // endstops_triggered(step_events_completed); + step_events_completed = current_block->step_event_count; + } + #endif + } + else { // +direction + WRITE(Y_DIR_PIN,!INVERT_Y_DIR); + #ifdef DEBUG_STEPS + count_direction[Y_AXIS]=1; + #endif + #if Y_MAX_PIN > -1 + if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ + // endstops_triggered(step_events_completed); + step_events_completed = current_block->step_event_count; + } + #endif + } + + if ((out_bits & (1< -1 + if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { + endstops_triggered(step_events_completed); + step_events_completed = current_block->step_event_count; + } + #endif + } + else { // +direction + WRITE(Z_DIR_PIN,!INVERT_Z_DIR); + #ifdef DEBUG_STEPS + count_direction[Z_AXIS]=1; + #endif + #if Z_MAX_PIN > -1 + if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ + // endstops_triggered(step_events_completed); + step_events_completed = current_block->step_event_count; + } + #endif + } + + #ifndef ADVANCE + if ((out_bits & (1<steps_x; + if (counter_x > 0) { + WRITE(X_STEP_PIN, HIGH); + counter_x -= current_block->step_event_count; + WRITE(X_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[X_AXIS]+=count_direction[X_AXIS]; + #endif + } + + counter_y += current_block->steps_y; + if (counter_y > 0) { + WRITE(Y_STEP_PIN, HIGH); + counter_y -= current_block->step_event_count; + WRITE(Y_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Y_AXIS]+=count_direction[Y_AXIS]; + #endif + } + + counter_z += current_block->steps_z; + if (counter_z > 0) { + WRITE(Z_STEP_PIN, HIGH); + counter_z -= current_block->step_event_count; + WRITE(Z_STEP_PIN, LOW); + #ifdef DEBUG_STEPS + count_position[Z_AXIS]+=count_direction[Z_AXIS]; + #endif + } + + #ifndef ADVANCE + counter_e += current_block->steps_e; + if (counter_e > 0) { + WRITE(E_STEP_PIN, HIGH); + counter_e -= current_block->step_event_count; + WRITE(E_STEP_PIN, LOW); + } + #endif //!ADVANCE + step_events_completed += 1; + if(step_events_completed >= current_block->step_event_count) break; + } + // Calculare new timer value + unsigned short timer; + unsigned short step_rate; + if (step_events_completed <= current_block->accelerate_until) { + MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); + acc_step_rate += current_block->initial_rate; + + // upper limit + if(acc_step_rate > current_block->nominal_rate) + acc_step_rate = current_block->nominal_rate; + + // step_rate to timer interval + timer = calc_timer(acc_step_rate); + #ifdef ADVANCE + advance += advance_rate; + #endif + acceleration_time += timer; + OCR1A = timer; + } + else if (step_events_completed > current_block->decelerate_after) { + MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); + + if(step_rate > acc_step_rate) { // Check step_rate stays positive + step_rate = current_block->final_rate; + } + else { + step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point. + } + + // lower limit + if(step_rate < current_block->final_rate) + step_rate = current_block->final_rate; + + // step_rate to timer interval + timer = calc_timer(step_rate); + #ifdef ADVANCE + advance -= advance_rate; + if(advance < final_advance) + advance = final_advance; + #endif //ADVANCE + deceleration_time += timer; + OCR1A = timer; + } + else { + timer = calc_timer(current_block->nominal_rate); + OCR1A = timer; + } + + // If current block is finished, reset pointer + if (step_events_completed >= current_block->step_event_count) { + current_block = NULL; + plan_discard_current_block(); + } + } + cli(); // disable interrupts + busy=false; +} + +#ifdef ADVANCE + unsigned char old_OCR0A; + // Timer interrupt for E. e_steps is set in the main routine; + // Timer 0 is shared with millies + ISR(TIMER0_COMPA_vect) + { + // Critical section needed because Timer 1 interrupt has higher priority. + // The pin set functions are placed on trategic position to comply with the stepper driver timing. + WRITE(E_STEP_PIN, LOW); + // Set E direction (Depends on E direction + advance) + if (e_steps < 0) { + WRITE(E_DIR_PIN,INVERT_E_DIR); + e_steps++; + WRITE(E_STEP_PIN, HIGH); + } + if (e_steps > 0) { + WRITE(E_DIR_PIN,!INVERT_E_DIR); + e_steps--; + WRITE(E_STEP_PIN, HIGH); + } + old_OCR0A += 25; // 10kHz interrupt + OCR0A = old_OCR0A; + } +#endif // ADVANCE + +void st_init() +{ + //Initialize Dir Pins + #if X_DIR_PIN > -1 + SET_OUTPUT(X_DIR_PIN); + #endif + #if Y_DIR_PIN > -1 + SET_OUTPUT(Y_DIR_PIN); + #endif + #if Z_DIR_PIN > -1 + SET_OUTPUT(Z_DIR_PIN); + #endif + #if E_DIR_PIN > -1 + SET_OUTPUT(E_DIR_PIN); + #endif + + //Initialize Enable Pins - steppers default to disabled. + + #if (X_ENABLE_PIN > -1) + SET_OUTPUT(X_ENABLE_PIN); + if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); + #endif + #if (Y_ENABLE_PIN > -1) + SET_OUTPUT(Y_ENABLE_PIN); + if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); + #endif + #if (Z_ENABLE_PIN > -1) + SET_OUTPUT(Z_ENABLE_PIN); + if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); + #endif + #if (E_ENABLE_PIN > -1) + SET_OUTPUT(E_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); + #endif + + //endstops and pullups + #ifdef ENDSTOPPULLUPS + #if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + WRITE(X_MIN_PIN,HIGH); + #endif + #if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + WRITE(X_MAX_PIN,HIGH); + #endif + #if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + WRITE(Y_MIN_PIN,HIGH); + #endif + #if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + WRITE(Y_MAX_PIN,HIGH); + #endif + #if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + WRITE(Z_MIN_PIN,HIGH); + #endif + #if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + WRITE(Z_MAX_PIN,HIGH); + #endif + #else //ENDSTOPPULLUPS + #if X_MIN_PIN > -1 + SET_INPUT(X_MIN_PIN); + #endif + #if X_MAX_PIN > -1 + SET_INPUT(X_MAX_PIN); + #endif + #if Y_MIN_PIN > -1 + SET_INPUT(Y_MIN_PIN); + #endif + #if Y_MAX_PIN > -1 + SET_INPUT(Y_MAX_PIN); + #endif + #if Z_MIN_PIN > -1 + SET_INPUT(Z_MIN_PIN); + #endif + #if Z_MAX_PIN > -1 + SET_INPUT(Z_MAX_PIN); + #endif + #endif //ENDSTOPPULLUPS + + + //Initialize Step Pins + #if (X_STEP_PIN > -1) + SET_OUTPUT(X_STEP_PIN); + #endif + #if (Y_STEP_PIN > -1) + SET_OUTPUT(Y_STEP_PIN); + #endif + #if (Z_STEP_PIN > -1) + SET_OUTPUT(Z_STEP_PIN); + #endif + #if (E_STEP_PIN > -1) + SET_OUTPUT(E_STEP_PIN); + #endif + + // waveform generation = 0100 = CTC + TCCR1B &= ~(1<. - */ - -/* - 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 - - This firmware is optimized for gen6 electronics. - */ - -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "temperature.h" -#include "watchdog.h" - -//=========================================================================== -//=============================public variables============================ -//=========================================================================== -int target_raw[3] = {0, 0, 0}; -int current_raw[3] = {0, 0, 0}; - -#ifdef PIDTEMP - - // probably used external - float HeaterPower; - float pid_setpoint = 0.0; - - - float Kp=DEFAULT_Kp; - float Ki=DEFAULT_Ki; - float Kd=DEFAULT_Kd; - float Kc=DEFAULT_Kc; -#endif //PIDTEMP - - -//=========================================================================== -//=============================private variables============================ -//=========================================================================== -static bool temp_meas_ready = false; - -static unsigned long previous_millis_heater, previous_millis_bed_heater; - -#ifdef PIDTEMP - //static cannot be external: - static float temp_iState = 0; - static float temp_dState = 0; - static float pTerm; - static float iTerm; - static float dTerm; - //int output; - static float pid_error; - static float temp_iState_min; - static float temp_iState_max; - static float pid_input; - static float pid_output; - static bool pid_reset; - -#endif //PIDTEMP - -#ifdef WATCHPERIOD - static int watch_raw[3] = {-1000,-1000,-1000}; - static unsigned long watchmillis = 0; -#endif //WATCHPERIOD - -#ifdef HEATER_0_MINTEMP - static int minttemp_0 = temp2analog(HEATER_0_MINTEMP); -#endif //MINTEMP -#ifdef HEATER_0_MAXTEMP - static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); -#endif //MAXTEMP - -#ifdef HEATER_1_MINTEMP - static int minttemp_1 = temp2analog(HEATER_1_MINTEMP); -#endif //MINTEMP -#ifdef HEATER_1_MAXTEMP - static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); -#endif //MAXTEMP - -#ifdef BED_MINTEMP - static int bed_minttemp = temp2analog(BED_MINTEMP); -#endif //BED_MINTEMP -#ifdef BED_MAXTEMP - static int bed_maxttemp = temp2analog(BED_MAXTEMP); -#endif //BED_MAXTEMP - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== - -void updatePID() -{ -#ifdef PIDTEMP - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; -#endif -} - -void manage_heater() -{ - #ifdef USE_WATCHDOG - wd_reset(); - #endif - - float pid_input; - float pid_output; - if(temp_meas_ready != true) //better readability - return; - - CRITICAL_SECTION_START; - temp_meas_ready = false; - CRITICAL_SECTION_END; - - #ifdef PIDTEMP - pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); - - #ifndef PID_OPENLOOP - pid_error = pid_setpoint - pid_input; - if(pid_error > 10){ - pid_output = PID_MAX; - pid_reset = true; - } - else if(pid_error < -10) { - pid_output = 0; - pid_reset = true; - } - else { - if(pid_reset == true) { - temp_iState = 0.0; - pid_reset = false; - } - pTerm = Kp * pid_error; - temp_iState += pid_error; - temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); - iTerm = Ki * temp_iState; - //K1 defined in Configuration.h in the PID settings - #define K2 (1.0-K1) - dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); - temp_dState = pid_input; - #ifdef PID_ADD_EXTRUSION_RATE - pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high - #endif - pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); - - } - #endif //PID_OPENLOOP - #ifdef PID_DEBUG - //SERIAL_ECHOLN(" PIDDEBUG Input "<= target_raw[0]) - { - WRITE(HEATER_0_PIN,LOW); - } - else - { - WRITE(HEATER_0_PIN,HIGH); - } - #endif - - if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) - return; - previous_millis_bed_heater = millis(); - - #if TEMP_1_PIN > -1 - if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) - { - WRITE(HEATER_1_PIN,LOW); - } - else - { - WRITE(HEATER_1_PIN,HIGH); - } - #endif -} - -// Takes hot end temperature value as input and returns corresponding raw value. -// For a thermistor, it uses the RepRap thermistor temp table. -// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. -// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -int temp2analog(int celsius) { - #ifdef HEATER_0_USES_THERMISTOR - int raw = 0; - byte i; - - for (i=1; i raw) - { - celsius = heater_0_temptable[i-1][1] + - (raw - heater_0_temptable[i-1][0]) * - (float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) / - (float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1]; - - return celsius; - #elif defined HEATER_0_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -// Derived from RepRap FiveD extruder::getTemperature() -// For bed temperature measurement. -float analog2tempBed(int raw) { - #ifdef BED_USES_THERMISTOR - int celsius = 0; - byte i; - - raw = (1023 * OVERSAMPLENR) - raw; - - for (i=1; i raw) - { - celsius = bedtemptable[i-1][1] + - (raw - bedtemptable[i-1][0]) * - (bedtemptable[i][1] - bedtemptable[i-1][1]) / - (bedtemptable[i][0] - bedtemptable[i-1][0]); - - break; - } - } - - // Overflow: Set to last value in the table - if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; - - return celsius; - - #elif defined BED_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #endif -} - -void tp_init() -{ - #if (HEATER_0_PIN > -1) - SET_OUTPUT(HEATER_0_PIN); - #endif - #if (HEATER_1_PIN > -1) - SET_OUTPUT(HEATER_1_PIN); - #endif - #if (HEATER_2_PIN > -1) - SET_OUTPUT(HEATER_2_PIN); - #endif - - #ifdef PIDTEMP - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; - #endif //PIDTEMP - - // Set analog inputs - ADCSRA = 1< -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif -} - -// Timer 0 is shared with millies -ISR(TIMER0_COMPB_vect) -{ - //these variables are only accesible from the ISR, but static, so they don't loose their value - static unsigned char temp_count = 0; - static unsigned long raw_temp_0_value = 0; - static unsigned long raw_temp_1_value = 0; - static unsigned long raw_temp_2_value = 0; - static unsigned char temp_state = 0; - - switch(temp_state) { - case 0: // Prepare TEMP_0 - #if (TEMP_0_PIN > -1) - #if TEMP_0_PIN < 8 - DIDR0 = 1 << TEMP_0_PIN; - #else - DIDR2 = 1<<(TEMP_0_PIN - 8); - ADCSRB = 1< -1) - raw_temp_0_value += ADC; - #endif - temp_state = 2; - break; - case 2: // Prepare TEMP_1 - #if (TEMP_1_PIN > -1) - #if TEMP_1_PIN < 7 - DIDR0 = 1< -1) - raw_temp_1_value += ADC; - #endif - temp_state = 4; - break; - case 4: // Prepare TEMP_2 - #if (TEMP_2_PIN > -1) - #if TEMP_2_PIN < 7 - DIDR0 = 1 << TEMP_2_PIN; - #else - DIDR2 = 1<<(TEMP_2_PIN - 8); - ADCSRB = 1< -1) - raw_temp_2_value += ADC; - #endif - temp_state = 0; - temp_count++; - break; - default: - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temp measurement error!"); - break; - } - - if(temp_count >= 16) // 6 ms * 16 = 96ms. - { - #ifdef HEATER_0_USES_AD595 - current_raw[0] = raw_temp_0_value; - #else - current_raw[0] = 16383 - raw_temp_0_value; - #endif - - #ifdef HEATER_1_USES_AD595 - current_raw[2] = raw_temp_2_value; - #else - current_raw[2] = 16383 - raw_temp_2_value; - #endif - - #ifdef BED_USES_AD595 - current_raw[1] = raw_temp_1_value; - #else - current_raw[1] = 16383 - raw_temp_1_value; - #endif - - temp_meas_ready = true; - temp_count = 0; - raw_temp_0_value = 0; - raw_temp_1_value = 0; - raw_temp_2_value = 0; - #ifdef HEATER_0_MAXTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MAXTEMP triggered !!"); - kill(); - } - #endif - #endif - #ifdef HEATER_1_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - if(current_raw[2] >= maxttemp_1) { - analogWrite(HEATER_2_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MAXTEMP triggered !!"); - kill() - } - #endif - #endif //MAXTEMP - - #ifdef HEATER_0_MINTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif - - #ifdef HEATER_1_MINTEMP - #if (HEATER_2_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - analogWrite(HEATER_2_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif //MAXTEMP - - #ifdef BED_MINTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] <= bed_minttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperatur heated bed switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif - - #ifdef BED_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] >= bed_maxttemp) { - target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); - kill(); - } - #endif - #endif - } -} - - +/* + temperature.c - temperature control + Part of Marlin + + 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 + + This firmware is optimized for gen6 electronics. + */ +#include + +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "temperature.h" +#include "watchdog.h" + +//=========================================================================== +//=============================public variables============================ +//=========================================================================== +int target_raw[3] = {0, 0, 0}; +int current_raw[3] = {0, 0, 0}; + +#ifdef PIDTEMP + + // probably used external + float HeaterPower; + float pid_setpoint = 0.0; + + + float Kp=DEFAULT_Kp; + float Ki=DEFAULT_Ki; + float Kd=DEFAULT_Kd; + #ifdef PID_ADD_EXTRUSION_RATE + float Kc=DEFAULT_Kc; + #endif +#endif //PIDTEMP + + +//=========================================================================== +//=============================private variables============================ +//=========================================================================== +static bool temp_meas_ready = false; + +static unsigned long previous_millis_heater, previous_millis_bed_heater; + +#ifdef PIDTEMP + //static cannot be external: + static float temp_iState = 0; + static float temp_dState = 0; + static float pTerm; + static float iTerm; + static float dTerm; + //int output; + static float pid_error; + static float temp_iState_min; + static float temp_iState_max; + static float pid_input; + static float pid_output; + static bool pid_reset; + +#endif //PIDTEMP + +#ifdef WATCHPERIOD + static int watch_raw[3] = {-1000,-1000,-1000}; + static unsigned long watchmillis = 0; +#endif //WATCHPERIOD + +#ifdef HEATER_0_MINTEMP + static int minttemp_0 = temp2analog(HEATER_0_MINTEMP); +#endif //MINTEMP +#ifdef HEATER_0_MAXTEMP + static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); +#endif //MAXTEMP + +#ifdef HEATER_1_MINTEMP + static int minttemp_1 = temp2analog(HEATER_1_MINTEMP); +#endif //MINTEMP +#ifdef HEATER_1_MAXTEMP + static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); +#endif //MAXTEMP + +#ifdef BED_MINTEMP + static int bed_minttemp = temp2analog(BED_MINTEMP); +#endif //BED_MINTEMP +#ifdef BED_MAXTEMP + static int bed_maxttemp = temp2analog(BED_MAXTEMP); +#endif //BED_MAXTEMP + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + +void updatePID() +{ +#ifdef PIDTEMP + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; +#endif +} + +void manage_heater() +{ + #ifdef USE_WATCHDOG + wd_reset(); + #endif + + float pid_input; + float pid_output; + if(temp_meas_ready != true) //better readability + return; + + CRITICAL_SECTION_START; + temp_meas_ready = false; + CRITICAL_SECTION_END; + + #ifdef PIDTEMP + pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + + #ifndef PID_OPENLOOP + pid_error = pid_setpoint - pid_input; + if(pid_error > 10){ + pid_output = PID_MAX; + pid_reset = true; + } + else if(pid_error < -10) { + pid_output = 0; + pid_reset = true; + } + else { + if(pid_reset == true) { + temp_iState = 0.0; + pid_reset = false; + } + pTerm = Kp * pid_error; + temp_iState += pid_error; + temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); + iTerm = Ki * temp_iState; + //K1 defined in Configuration.h in the PID settings + #define K2 (1.0-K1) + dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); + temp_dState = pid_input; +// #ifdef PID_ADD_EXTRUSION_RATE +// pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high +// #endif + pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); + + } + #endif //PID_OPENLOOP + #ifdef PID_DEBUG + //SERIAL_ECHOLN(" PIDDEBUG Input "<= target_raw[0]) + { + WRITE(HEATER_0_PIN,LOW); + } + else + { + WRITE(HEATER_0_PIN,HIGH); + } + #endif + + if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) + return; + previous_millis_bed_heater = millis(); + + #if TEMP_1_PIN > -1 + if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) + { + WRITE(HEATER_1_PIN,LOW); + } + else + { + WRITE(HEATER_1_PIN,HIGH); + } + #endif +} + +#define PGM_RD_W(x) (short)pgm_read_word(&x) +// Takes hot end temperature value as input and returns corresponding raw value. +// For a thermistor, it uses the RepRap thermistor temp table. +// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. +// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. +int temp2analog(int celsius) { + #ifdef HEATER_0_USES_THERMISTOR + int raw = 0; + byte i; + + for (i=1; i raw) + { + celsius = PGM_RD_W(heater_0_temptable[i-1][1]) + + (raw - PGM_RD_W(heater_0_temptable[i-1][0])) * + (float)(PGM_RD_W(heater_0_temptable[i][1]) - PGM_RD_W(heater_0_temptable[i-1][1])) / + (float)(PGM_RD_W(heater_0_temptable[i][0]) - PGM_RD_W(heater_0_temptable[i-1][0])); + break; + } + } + + // Overflow: Set to last value in the table + if (i == NUMTEMPS_HEATER_0) celsius = PGM_RD_W(heater_0_temptable[i-1][1]); + + return celsius; + #elif defined HEATER_0_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +// Derived from RepRap FiveD extruder::getTemperature() +// For bed temperature measurement. +float analog2tempBed(int raw) { + #ifdef BED_USES_THERMISTOR + int celsius = 0; + byte i; + + raw = (1023 * OVERSAMPLENR) - raw; + + for (i=1; i raw) + { + celsius = PGM_RD_W(bedtemptable[i-1][1]) + + (raw - PGM_RD_W(bedtemptable[i-1][0])) * + (PGM_RD_W(bedtemptable[i][1]) - PGM_RD_W(bedtemptable[i-1][1])) / + (PGM_RD_W(bedtemptable[i][0]) - PGM_RD_W(bedtemptable[i-1][0])); + + break; + } + } + + // Overflow: Set to last value in the table + if (i == BNUMTEMPS) celsius = PGM_RD_W(bedtemptable[i-1][1]); + + return celsius; + + #elif defined BED_USES_AD595 + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #endif +} + +void tp_init() +{ + #if (HEATER_0_PIN > -1) + SET_OUTPUT(HEATER_0_PIN); + #endif + #if (HEATER_1_PIN > -1) + SET_OUTPUT(HEATER_1_PIN); + #endif + #if (HEATER_2_PIN > -1) + SET_OUTPUT(HEATER_2_PIN); + #endif + + #ifdef PIDTEMP + temp_iState_min = 0.0; + temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; + #endif //PIDTEMP + + // Set analog inputs + ADCSRA = 1< -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif +} + +// Timer 0 is shared with millies +ISR(TIMER0_COMPB_vect) +{ + //these variables are only accesible from the ISR, but static, so they don't loose their value + static unsigned char temp_count = 0; + static unsigned long raw_temp_0_value = 0; + static unsigned long raw_temp_1_value = 0; + static unsigned long raw_temp_2_value = 0; + static unsigned char temp_state = 0; + + switch(temp_state) { + case 0: // Prepare TEMP_0 + #if (TEMP_0_PIN > -1) + #if TEMP_0_PIN < 8 + DIDR0 = 1 << TEMP_0_PIN; + #else + DIDR2 = 1<<(TEMP_0_PIN - 8); + ADCSRB = 1< -1) + raw_temp_0_value += ADC; + #endif + temp_state = 2; + break; + case 2: // Prepare TEMP_1 + #if (TEMP_1_PIN > -1) + #if TEMP_1_PIN < 7 + DIDR0 = 1< -1) + raw_temp_1_value += ADC; + #endif + temp_state = 4; + break; + case 4: // Prepare TEMP_2 + #if (TEMP_2_PIN > -1) + #if TEMP_2_PIN < 7 + DIDR0 = 1 << TEMP_2_PIN; + #else + DIDR2 = 1<<(TEMP_2_PIN - 8); + ADCSRB = 1< -1) + raw_temp_2_value += ADC; + #endif + temp_state = 0; + temp_count++; + break; + default: + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temp measurement error!"); + break; + } + + if(temp_count >= 16) // 6 ms * 16 = 96ms. + { + #ifdef HEATER_0_USES_AD595 + current_raw[0] = raw_temp_0_value; + #else + current_raw[0] = 16383 - raw_temp_0_value; + #endif + + #ifdef HEATER_1_USES_AD595 + current_raw[2] = raw_temp_2_value; + #else + current_raw[2] = 16383 - raw_temp_2_value; + #endif + + #ifdef BED_USES_AD595 + current_raw[1] = raw_temp_1_value; + #else + current_raw[1] = 16383 - raw_temp_1_value; + #endif + + temp_meas_ready = true; + temp_count = 0; + raw_temp_0_value = 0; + raw_temp_1_value = 0; + raw_temp_2_value = 0; + #ifdef HEATER_0_MAXTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MAXTEMP triggered !!"); + kill(); + } + #endif + #endif + #ifdef HEATER_1_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + if(current_raw[2] >= maxttemp_1) { + analogWrite(HEATER_2_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MAXTEMP triggered !!"); + kill() + } + #endif + #endif //MAXTEMP + + #ifdef HEATER_0_MINTEMP + #if (HEATER_0_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { + target_raw[TEMPSENSOR_HOTEND_0] = 0; + analogWrite(HEATER_0_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MINTEMP triggered !!"); + kill(); + } + #endif + #endif + + #ifdef HEATER_1_MINTEMP + #if (HEATER_2_PIN > -1) + if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { + target_raw[TEMPSENSOR_HOTEND_1] = 0; + analogWrite(HEATER_2_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MINTEMP triggered !!"); + kill(); + } + #endif + #endif //MAXTEMP + + #ifdef BED_MINTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] <= bed_minttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperatur heated bed switched off. MINTEMP triggered !!"); + kill(); + } + #endif + #endif + + #ifdef BED_MAXTEMP + #if (HEATER_1_PIN > -1) + if(current_raw[1] >= bed_maxttemp) { + target_raw[1] = 0; + WRITE(HEATER_1_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); + kill(); + } + #endif + #endif + } +} + + diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index fbd2ef1446..22d9f02487 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -1,12 +1,14 @@ #ifndef THERMISTORTABLES_H_ #define THERMISTORTABLES_H_ +#include + #define OVERSAMPLENR 16 #if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORBED == 1) //100k bed thermistor #define NUMTEMPS_1 61 -const short temptable_1[NUMTEMPS_1][2] = { +const short temptable_1[NUMTEMPS_1][2] PROGMEM = { { 23*OVERSAMPLENR , 300 }, { 25*OVERSAMPLENR , 295 }, { 27*OVERSAMPLENR , 290 }, @@ -72,7 +74,7 @@ const short temptable_1[NUMTEMPS_1][2] = { #endif #if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORBED == 2) //200k bed thermistor #define NUMTEMPS_2 21 -const short temptable_2[NUMTEMPS_2][2] = { +const short temptable_2[NUMTEMPS_2][2] PROGMEM = { {1*OVERSAMPLENR, 848}, {54*OVERSAMPLENR, 275}, {107*OVERSAMPLENR, 228}, @@ -99,7 +101,7 @@ const short temptable_2[NUMTEMPS_2][2] = { #endif #if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORBED == 3) //mendel-parts #define NUMTEMPS_3 28 -const short temptable_3[NUMTEMPS_3][2] = { +const short temptable_3[NUMTEMPS_3][2] PROGMEM = { {1*OVERSAMPLENR,864}, {21*OVERSAMPLENR,300}, {25*OVERSAMPLENR,290}, @@ -134,7 +136,7 @@ const short temptable_3[NUMTEMPS_3][2] = { #if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORBED == 4) //10k thermistor #define NUMTEMPS_4 20 -short temptable_4[NUMTEMPS_4][2] = { +const short temptable_4[NUMTEMPS_4][2] PROGMEM = { {1*OVERSAMPLENR, 430}, {54*OVERSAMPLENR, 137}, {107*OVERSAMPLENR, 107}, @@ -161,7 +163,7 @@ short temptable_4[NUMTEMPS_4][2] = { #if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) #define NUMTEMPS_5 61 -const short temptable_5[NUMTEMPS_5][2] = { +const short temptable_5[NUMTEMPS_5][2] PROGMEM = { {1*OVERSAMPLENR, 713}, {18*OVERSAMPLENR, 316}, {35*OVERSAMPLENR, 266}, @@ -228,7 +230,7 @@ const short temptable_5[NUMTEMPS_5][2] = { #if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor #define NUMTEMPS_6 36 -const short temptable_6[NUMTEMPS_6][2] = { +const short temptable_6[NUMTEMPS_6][2] PROGMEM = { {28*OVERSAMPLENR, 250}, {31*OVERSAMPLENR, 245}, {35*OVERSAMPLENR, 240}, @@ -270,7 +272,7 @@ const short temptable_6[NUMTEMPS_6][2] = { #if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 #define NUMTEMPS_7 54 -const short temptable_7[NUMTEMPS_7][2] = { +const short temptable_7[NUMTEMPS_7][2] PROGMEM = { {46*OVERSAMPLENR, 270}, {50*OVERSAMPLENR, 265}, {54*OVERSAMPLENR, 260}, diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index c836757e1c..6bae43dccb 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -1,102 +1,103 @@ -#ifndef __ULTRALCDH -#define __ULTRALCDH -#include "Configuration.h" - -#ifdef ULTRA_LCD - - void lcd_status(); - void lcd_init(); - void lcd_status(const char* message); - void beep(); - void buttons_check(); - - - #define LCD_UPDATE_INTERVAL 100 - #define STATUSTIMEOUT 15000 - - - #include - extern LiquidCrystal lcd; - - - #ifdef NEWPANEL - - - #define EN_C (1< + extern LiquidCrystal lcd; + + + #ifdef NEWPANEL + + + #define EN_C (1< Date: Fri, 18 Nov 2011 18:59:17 +0100 Subject: [PATCH 049/228] Advance experiments. Not working yet. --- Marlin/Configuration.h | 45 ++++++++++++-------------- Marlin/Marlin.pde | 3 +- Marlin/stepper.cpp | 72 ++++++++++++++++++++++-------------------- Marlin/watchdog.pde | 6 ++-- 4 files changed, 61 insertions(+), 65 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 3b0cfacfeb..7cbb66cf74 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -11,7 +11,7 @@ // Frequency limit // See nophead's blog for more info -// Not working OK +// Not working O //#define XY_FREQUENCY_LIMIT 15 // Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end @@ -31,7 +31,7 @@ // Sanguinololu 1.2 and above = 62 // Ultimaker = 7, // Teensylu = 8 -#define MOTHERBOARD 7 +#define MOTHERBOARD 5 //=========================================================================== //=============================Thermal Settings ============================ @@ -45,9 +45,9 @@ // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 -#define THERMISTORHEATER_0 3 -#define THERMISTORHEATER_1 3 -#define THERMISTORBED 3 +//#define THERMISTORHEATER_0 3 +//#define THERMISTORHEATER_1 3 +//#define THERMISTORBED 3 //#define HEATER_0_USES_THERMISTOR //#define HEATER_1_USES_THERMISTOR @@ -120,9 +120,15 @@ // #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) // #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) +// Ultitmaker #define DEFAULT_Kp 22.2 #define DEFAULT_Ki (1.25*PID_dT) #define DEFAULT_Kd (99/PID_dT) + +// Mendel Parts V9 on 12V +// #define DEFAULT_Kp 63.0 +// #define DEFAULT_Ki (2.25*PID_dT) +// #define DEFAULT_Kd (440/PID_dT) #endif #ifdef PID_PI @@ -141,13 +147,6 @@ #endif // PIDTEMP - - - - - - - //=========================================================================== //=============================Mechanical Settings=========================== //=========================================================================== @@ -178,10 +177,10 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true //#define INVERT_E_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +//#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +//#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false +//#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +//#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false //// ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -243,13 +242,10 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // this enables the watchdog interrupt. -#define USE_WATCHDOG +//#define 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: -#define RESET_MANUAL -#define WATCHDOG_TIMEOUT 4 //seconds - - - +//#define RESET_MANUAL +//#define WATCHDOG_TIMEOUT 4 //seconds // extruder advance constant (s2/mm3) // @@ -275,7 +271,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //#define ULTRA_LCD //general lcd support, also 16x2 //#define SDSUPPORT // Enable SD Card Support in Hardware Console -#define ULTIPANEL +//#define ULTIPANEL #ifdef ULTIPANEL // #define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT @@ -307,8 +303,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define AUTOTEMP_FACTOR 1000. //current target temperature= min+largest buffered espeeds)*FACTOR - -const int dropsegments=0; //everything with less than this number of steps will be ignored as move and joined with the next movement +const int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement //=========================================================================== //=============================Buffers ============================ diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 9f84f6c33d..3a6d4e6724 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -232,10 +232,9 @@ void setup() 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; - tp_init(); // Initialize temperature loop } diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 2e232201bf..b08e61ae45 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -56,8 +56,8 @@ static unsigned long step_events_completed; // The number of step events execute #ifdef ADVANCE static long advance_rate, advance, final_advance = 0; static short old_advance = 0; - static short e_steps; #endif +static short e_steps; static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. static long acceleration_time, deceleration_time; //static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; @@ -156,7 +156,7 @@ asm volatile ( \ #define DISABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 &= ~(1< interrupt out_bits = current_block->direction_bits; - #ifdef ADVANCE - // Calculate E early. - counter_e += current_block->steps_e; - if (counter_e > 0) { - counter_e -= current_block->step_event_count; - if ((out_bits & (1<> 16) - old_advance); - CRITICAL_SECTION_END; - old_advance = advance >> 16; - #endif //ADVANCE - // Set direction en check limit switches if ((out_bits & (1< -1 - if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { - // endstops_triggered(step_events_completed); - step_events_completed = current_block->step_event_count; - } + if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { + // endstops_triggered(step_events_completed); + step_events_completed = current_block->step_event_count; + } #endif } else { // +direction @@ -355,7 +332,7 @@ ISR(TIMER1_COMPA_vect) // endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } - #endif + #endif } if ((out_bits & (1< -1 if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { - // endstops_triggered(step_events_completed); +// endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -390,7 +367,7 @@ ISR(TIMER1_COMPA_vect) #endif #if Z_MIN_PIN > -1 if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { - endstops_triggered(step_events_completed); + // endstops_triggered(step_events_completed); step_events_completed = current_block->step_event_count; } #endif @@ -416,6 +393,30 @@ ISR(TIMER1_COMPA_vect) #endif //!ADVANCE for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) + /* + counter_e += current_block->steps_e; + if (counter_e > 0) { + counter_e -= current_block->step_event_count; + if ((out_bits & (1<> 16) - old_advance); + CRITICAL_SECTION_END; + old_advance = advance >> 16; + */ + counter_x += current_block->steps_x; if (counter_x > 0) { WRITE(X_STEP_PIN, HIGH); @@ -649,7 +650,8 @@ void st_init() TCCR1B = (TCCR1B & ~(0x07< Date: Fri, 18 Nov 2011 19:46:16 +0100 Subject: [PATCH 050/228] Fixed bug in configuration.h --- Marlin/Configuration.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index cf38cea368..9bcddc8723 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -31,7 +31,7 @@ // Sanguinololu 1.2 and above = 62 // Ultimaker = 7, // Teensylu = 8 -#define MOTHERBOARD 5 +#define MOTHERBOARD 7 //=========================================================================== //=============================Thermal Settings ============================ @@ -176,10 +176,10 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true //#define INVERT_E_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -//#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -//#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -//#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -//#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false +#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false //// ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -242,11 +242,11 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // this enables the watchdog interrupt. //#define USE_WATCHDOG -#ifdef 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: //#define RESET_MANUAL //#define WATCHDOG_TIMEOUT 4 //seconds - +//#endif // extruder advance constant (s2/mm3) // @@ -272,7 +272,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //#define ULTRA_LCD //general lcd support, also 16x2 //#define SDSUPPORT // Enable SD Card Support in Hardware Console -//#define ULTIPANEL +#define ULTIPANEL #ifdef ULTIPANEL // #define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT From 64f2121ab1ba530753715c19574721f55076bdb0 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Fri, 18 Nov 2011 22:17:37 +0100 Subject: [PATCH 051/228] updated to sdfatlib2010902 --- Marlin/Configuration.h | 6 +- Marlin/Marlin.pde | 20 +- Marlin/Sd2Card.cpp | 443 +++--- Marlin/Sd2Card.h | 253 ++-- Marlin/Sd2PinMap.h | 83 +- Marlin/SdBaseFile.cpp | 1818 +++++++++++++++++++++++ Marlin/SdBaseFile.h | 489 ++++++ Marlin/SdFat.cpp | 329 ++++ Marlin/SdFat.h | 561 +------ Marlin/SdFatConfig.h | 108 ++ Marlin/{FatStructs.h => SdFatStructs.h} | 1022 +++++++------ Marlin/SdFatUtil.cpp | 74 + Marlin/SdFatUtil.h | 54 +- Marlin/SdFatmainpage.h | 202 --- Marlin/SdFile.cpp | 1215 +-------------- Marlin/SdFile.h | 42 + Marlin/SdInfo.h | 237 +-- Marlin/SdVolume.cpp | 278 ++-- Marlin/SdVolume.h | 211 +++ Marlin/cardreader.h | 1 + merging still needs.txt | 58 - 21 files changed, 4502 insertions(+), 3002 deletions(-) create mode 100644 Marlin/SdBaseFile.cpp create mode 100644 Marlin/SdBaseFile.h create mode 100644 Marlin/SdFat.cpp create mode 100644 Marlin/SdFatConfig.h rename Marlin/{FatStructs.h => SdFatStructs.h} (59%) create mode 100644 Marlin/SdFatUtil.cpp delete mode 100644 Marlin/SdFatmainpage.h create mode 100644 Marlin/SdFile.h create mode 100644 Marlin/SdVolume.h delete mode 100644 merging still needs.txt diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 1e12d4e225..f1f0c651cf 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -4,8 +4,8 @@ // This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 +//#define BAUDRATE 250000 +#define BAUDRATE 115200 //#define BAUDRATE 230400 @@ -277,7 +277,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define ULTIPANEL #ifdef ULTIPANEL -// #define NEWPANEL //enable this if you have a click-encoder panel + #define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT #define ULTRA_LCD #define LCD_WIDTH 20 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index f808742c9c..db51361398 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -26,6 +26,7 @@ */ #include + #include "EEPROMwrite.h" #include "fastio.h" #include "Configuration.h" @@ -391,9 +392,15 @@ inline void get_command() while( !card.eof() && buflen < BUFSIZE) { int16_t n=card.get(); serial_char = (char)n; +// Serial.print((char)serial_char); +// Serial.print(" "); +// Serial.println((int)serial_count); if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) { - +// if(serial_char == '\n' || serial_char == '\r' ) +// Serial.println("newline or :"); +// if(serial_count >= (MAX_CMD_SIZE - 1)) +// Serial.println("too long line"); if(card.eof()){ card.sdprinting = false; SERIAL_PROTOCOLLNPGM("Done printing file"); @@ -409,15 +416,20 @@ inline void get_command() LCD_MESSAGE(time); card.checkautostart(true); } - if(!serial_count) - return; //if empty line + if(serial_char=='\n') + comment_mode = false; //for new command + if(!serial_count) + { +// Serial.println("empty line"); + 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 diff --git a/Marlin/Sd2Card.cpp b/Marlin/Sd2Card.cpp index 8222cfd939..ab060c121e 100644 --- a/Marlin/Sd2Card.cpp +++ b/Marlin/Sd2Card.cpp @@ -17,28 +17,77 @@ * along with the Arduino Sd2Card Library. If not, see * . */ +#if ARDUINO < 100 #include +#else // ARDUINO +#include +#endif // ARDUINO #include "Sd2Card.h" //------------------------------------------------------------------------------ #ifndef SOFTWARE_SPI // functions for hardware SPI -/** Send a byte to the card */ +//------------------------------------------------------------------------------ +// make sure SPCR rate is in expected bits +#if (SPR0 != 0 || SPR1 != 1) +#error unexpected SPCR bits +#endif +/** + * Initialize hardware SPI + * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6] + */ +static void spiInit(uint8_t spiRate) { + // See avr processor documentation + SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1); + SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X; +} +//------------------------------------------------------------------------------ +/** SPI receive a byte */ +static uint8_t spiRec() { + SPDR = 0XFF; + while (!(SPSR & (1 << SPIF))); + return SPDR; +} +//------------------------------------------------------------------------------ +/** SPI read data - only one call so force inline */ +static inline __attribute__((always_inline)) + void spiRead(uint8_t* buf, uint16_t nbyte) { + if (nbyte-- == 0) return; + SPDR = 0XFF; + for (uint16_t i = 0; i < nbyte; i++) { + while (!(SPSR & (1 << SPIF))); + buf[i] = SPDR; + SPDR = 0XFF; + } + while (!(SPSR & (1 << SPIF))); + buf[nbyte] = SPDR; +} +//------------------------------------------------------------------------------ +/** SPI send a byte */ static void spiSend(uint8_t b) { SPDR = b; while (!(SPSR & (1 << SPIF))); } -/** Receive a byte from the card */ -static uint8_t spiRec(void) { - spiSend(0XFF); - return SPDR; +//------------------------------------------------------------------------------ +/** SPI send block - only one call so force inline */ +static inline __attribute__((always_inline)) + void spiSendBlock(uint8_t token, const uint8_t* buf) { + SPDR = token; + for (uint16_t i = 0; i < 512; i += 2) { + while (!(SPSR & (1 << SPIF))); + SPDR = buf[i]; + while (!(SPSR & (1 << SPIF))); + SPDR = buf[i + 1]; + } + while (!(SPSR & (1 << SPIF))); } +//------------------------------------------------------------------------------ #else // SOFTWARE_SPI //------------------------------------------------------------------------------ /** nop to tune soft SPI timing */ #define nop asm volatile ("nop\n\t") //------------------------------------------------------------------------------ -/** Soft SPI receive */ -uint8_t spiRec(void) { +/** Soft SPI receive byte */ +static uint8_t spiRec() { uint8_t data = 0; // no interrupts during byte receive - about 8 us cli(); @@ -63,8 +112,15 @@ uint8_t spiRec(void) { return data; } //------------------------------------------------------------------------------ -/** Soft SPI send */ -void spiSend(uint8_t data) { +/** Soft SPI read data */ +static void spiRead(uint8_t* buf, uint16_t nbyte) { + for (uint16_t i = 0; i < nbyte; i++) { + buf[i] = spiRec(); + } +} +//------------------------------------------------------------------------------ +/** Soft SPI send byte */ +static void spiSend(uint8_t data) { // no interrupts during byte send - about 8 us cli(); for (uint8_t i = 0; i < 8; i++) { @@ -86,13 +142,18 @@ void spiSend(uint8_t data) { // enable interrupts sei(); } +//------------------------------------------------------------------------------ +/** Soft SPI send block */ + void spiSendBlock(uint8_t token, const uint8_t* buf) { + spiSend(token); + for (uint16_t i = 0; i < 512; i++) { + spiSend(buf[i]); + } +} #endif // SOFTWARE_SPI //------------------------------------------------------------------------------ // send command and return error code. Return zero for OK uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { - // end read if in partialBlockRead mode - readEnd(); - // select card chipSelectLow(); @@ -111,6 +172,9 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA spiSend(crc); + // skip stuff byte for stop read + if (cmd == CMD12) spiRec(); + // wait for response for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); return status_; @@ -122,7 +186,7 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { * \return The number of 512 byte data blocks in the card * or zero if an error occurs. */ -uint32_t Sd2Card::cardSize(void) { +uint32_t Sd2Card::cardSize() { csd_t csd; if (!readCSD(&csd)) return 0; if (csd.v1.csd_ver == 0) { @@ -142,11 +206,14 @@ uint32_t Sd2Card::cardSize(void) { } } //------------------------------------------------------------------------------ -void Sd2Card::chipSelectHigh(void) { +void Sd2Card::chipSelectHigh() { digitalWrite(chipSelectPin_, HIGH); } //------------------------------------------------------------------------------ -void Sd2Card::chipSelectLow(void) { +void Sd2Card::chipSelectLow() { +#ifndef SOFTWARE_SPI + spiInit(spiRate_); +#endif // SOFTWARE_SPI digitalWrite(chipSelectPin_, LOW); } //------------------------------------------------------------------------------ @@ -163,10 +230,18 @@ void Sd2Card::chipSelectLow(void) { * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ -uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { - if (!eraseSingleBlockEnable()) { - error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); - goto fail; +bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { + csd_t csd; + if (!readCSD(&csd)) goto fail; + // check for single block erase + if (!csd.v1.erase_blk_en) { + // erase size mask + uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; + if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { + // error card can't erase specified area + error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); + goto fail; + } } if (type_ != SD_CARD_TYPE_SDHC) { firstBlock <<= 9; @@ -195,9 +270,9 @@ uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { * \return The value one, true, is returned if single block erase is supported. * The value zero, false, is returned if single block erase is not supported. */ -uint8_t Sd2Card::eraseSingleBlockEnable(void) { +bool Sd2Card::eraseSingleBlockEnable() { csd_t csd; - return readCSD(&csd) ? csd.v1.erase_blk_en : 0; + return readCSD(&csd) ? csd.v1.erase_blk_en : false; } //------------------------------------------------------------------------------ /** @@ -210,8 +285,8 @@ uint8_t Sd2Card::eraseSingleBlockEnable(void) { * the value zero, false, is returned for failure. The reason for failure * can be determined by calling errorCode() and errorData(). */ -uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { - errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0; +bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { + errorCode_ = type_ = 0; chipSelectPin_ = chipSelectPin; // 16-bit init start time allows over a minute uint16_t t0 = (uint16_t)millis(); @@ -227,17 +302,18 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { #ifndef SOFTWARE_SPI // SS must be in output mode even it is not chip select pinMode(SS_PIN, OUTPUT); - // Enable SPI, Master, clock rate f_osc/128 - SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); - // clear double speed - SPSR &= ~(1 << SPI2X); + // set SS high - may be chip select for another SPI device +#if SET_SPI_SS_HIGH + digitalWrite(SS_PIN, HIGH); +#endif // SET_SPI_SS_HIGH + // set SCK rate for initialization commands + spiRate_ = SPI_SD_INIT_RATE; + spiInit(spiRate_); #endif // SOFTWARE_SPI // must supply min of 74 clock cycles with CS high. for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); - chipSelectLow(); - // command to go idle in SPI mode while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { @@ -291,105 +367,60 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { } //------------------------------------------------------------------------------ /** - * Enable or disable partial block reads. + * Read a 512 byte block from an SD card. * - * Enabling partial block reads improves performance by allowing a block - * to be read over the SPI bus as several sub-blocks. Errors may occur - * if the time between reads is too long since the SD card may timeout. - * The SPI SS line will be held low until the entire block is read or - * readEnd() is called. - * - * Use this for applications like the Adafruit Wave Shield. - * - * \param[in] value The value TRUE (non-zero) or FALSE (zero).) - */ -void Sd2Card::partialBlockRead(uint8_t value) { - readEnd(); - partialBlockRead_ = value; -} -//------------------------------------------------------------------------------ -/** - * Read a 512 byte block from an SD card device. - * - * \param[in] block Logical block to be read. + * \param[in] blockNumber Logical block to be read. * \param[out] dst Pointer to the location that will receive the data. * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ -uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { - return readData(block, 0, 512, dst); -} -//------------------------------------------------------------------------------ -/** - * Read part of a 512 byte block from an SD card. - * - * \param[in] block Logical block to be read. - * \param[in] offset Number of bytes to skip at start of block - * \param[out] dst Pointer to the location that will receive the data. - * \param[in] count Number of bytes to read - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t Sd2Card::readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst) { - uint16_t n; - if (count == 0) return true; - if ((count + offset) > 512) { +bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) { + // use address if not SDHC card + if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD17, blockNumber)) { + error(SD_CARD_ERROR_CMD17); goto fail; } - if (!inBlock_ || block != block_ || offset < offset_) { - block_ = block; - // use address if not SDHC card - if (type()!= SD_CARD_TYPE_SDHC) block <<= 9; - if (cardCommand(CMD17, block)) { - error(SD_CARD_ERROR_CMD17); + return readData(dst, 512); + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Read one data block in a multiple block read sequence + * + * \param[in] dst Pointer to the location for the data to be read. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readData(uint8_t *dst) { + chipSelectLow(); + return readData(dst, 512); +} +//------------------------------------------------------------------------------ +bool Sd2Card::readData(uint8_t* dst, uint16_t count) { + // wait for start block token + uint16_t t0 = millis(); + while ((status_ = spiRec()) == 0XFF) { + if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) { + error(SD_CARD_ERROR_READ_TIMEOUT); goto fail; } - if (!waitStartBlock()) { - goto fail; - } - offset_ = 0; - inBlock_ = 1; } - -#ifdef OPTIMIZE_HARDWARE_SPI - // start first spi transfer - SPDR = 0XFF; - - // skip data before offset - for (;offset_ < offset; offset_++) { - while (!(SPSR & (1 << SPIF))); - SPDR = 0XFF; + if (status_ != DATA_START_BLOCK) { + error(SD_CARD_ERROR_READ); + goto fail; } // transfer data - n = count - 1; - for (uint16_t i = 0; i < n; i++) { - while (!(SPSR & (1 << SPIF))); - dst[i] = SPDR; - SPDR = 0XFF; - } - // wait for last byte - while (!(SPSR & (1 << SPIF))); - dst[n] = SPDR; + spiRead(dst, count); -#else // OPTIMIZE_HARDWARE_SPI - - // skip data before offset - for (;offset_ < offset; offset_++) { - spiRec(); - } - // transfer data - for (uint16_t i = 0; i < count; i++) { - dst[i] = spiRec(); - } -#endif // OPTIMIZE_HARDWARE_SPI - - offset_ += count; - if (!partialBlockRead_ || offset_ >= 512) { - // read rest of data, checksum and set chip select high - readEnd(); - } + // discard CRC + spiRec(); + spiRec(); + chipSelectHigh(); return true; fail: @@ -397,39 +428,55 @@ uint8_t Sd2Card::readData(uint32_t block, return false; } //------------------------------------------------------------------------------ -/** Skip remaining data in a block when in partial block read mode. */ -void Sd2Card::readEnd(void) { - if (inBlock_) { - // skip data and crc -#ifdef OPTIMIZE_HARDWARE_SPI - // optimize skip for hardware - SPDR = 0XFF; - while (offset_++ < 513) { - while (!(SPSR & (1 << SPIF))); - SPDR = 0XFF; - } - // wait for last crc byte - while (!(SPSR & (1 << SPIF))); -#else // OPTIMIZE_HARDWARE_SPI - while (offset_++ < 514) spiRec(); -#endif // OPTIMIZE_HARDWARE_SPI - chipSelectHigh(); - inBlock_ = 0; - } -} -//------------------------------------------------------------------------------ /** read CID or CSR register */ -uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { +bool Sd2Card::readRegister(uint8_t cmd, void* buf) { uint8_t* dst = reinterpret_cast(buf); if (cardCommand(cmd, 0)) { error(SD_CARD_ERROR_READ_REG); goto fail; } - if (!waitStartBlock()) goto fail; - // transfer data - for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec(); - spiRec(); // get first crc byte - spiRec(); // get second crc byte + return readData(dst, 16); + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Start a read multiple blocks sequence. + * + * \param[in] blockNumber Address of first block in sequence. + * + * \note This function is used with readData() and readStop() for optimized + * multiple block reads. SPI chipSelect must be low for the entire sequence. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readStart(uint32_t blockNumber) { + if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD18, blockNumber)) { + error(SD_CARD_ERROR_CMD18); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** End a read multiple blocks sequence. + * +* \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readStop() { + chipSelectLow(); + if (cardCommand(CMD12, 0)) { + error(SD_CARD_ERROR_CMD12); + goto fail; + } chipSelectHigh(); return true; @@ -450,50 +497,24 @@ uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { * \return The value one, true, is returned for success and the value zero, * false, is returned for an invalid value of \a sckRateID. */ -uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { +bool Sd2Card::setSckRate(uint8_t sckRateID) { if (sckRateID > 6) { error(SD_CARD_ERROR_SCK_RATE); return false; } - // see avr processor datasheet for SPI register bit definitions - if ((sckRateID & 1) || sckRateID == 6) { - SPSR &= ~(1 << SPI2X); - } else { - SPSR |= (1 << SPI2X); - } - SPCR &= ~((1 < SD_READ_TIMEOUT) { - error(SD_CARD_ERROR_READ_TIMEOUT); - goto fail; - } - } - if (status_ != DATA_START_BLOCK) { - error(SD_CARD_ERROR_READ); - goto fail; + while (spiRec() != 0XFF) { + if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail; } return true; fail: - chipSelectHigh(); return false; } //------------------------------------------------------------------------------ @@ -505,15 +526,7 @@ uint8_t Sd2Card::waitStartBlock(void) { * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ -uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { -#if SD_PROTECT_BLOCK_ZERO - // don't allow write to first block - if (blockNumber == 0) { - error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); - goto fail; - } -#endif // SD_PROTECT_BLOCK_ZERO - +bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { // use address if not SDHC card if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; if (cardCommand(CMD24, blockNumber)) { @@ -540,51 +553,42 @@ uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { return false; } //------------------------------------------------------------------------------ -/** Write one data block in a multiple block write sequence */ -uint8_t Sd2Card::writeData(const uint8_t* src) { +/** Write one data block in a multiple block write sequence + * \param[in] src Pointer to the location of the data to be written. + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeData(const uint8_t* src) { + chipSelectLow(); // wait for previous write to finish - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_MULTIPLE); - chipSelectHigh(); - return false; - } - return writeData(WRITE_MULTIPLE_TOKEN, src); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail; + chipSelectHigh(); + return true; + + fail: + error(SD_CARD_ERROR_WRITE_MULTIPLE); + chipSelectHigh(); + return false; } //------------------------------------------------------------------------------ // send one block of data for write block or write multiple blocks -uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { -#ifdef OPTIMIZE_HARDWARE_SPI +bool Sd2Card::writeData(uint8_t token, const uint8_t* src) { + spiSendBlock(token, src); - // send data - optimized loop - SPDR = token; - - // send two byte per iteration - for (uint16_t i = 0; i < 512; i += 2) { - while (!(SPSR & (1 << SPIF))); - SPDR = src[i]; - while (!(SPSR & (1 << SPIF))); - SPDR = src[i+1]; - } - - // wait for last data byte - while (!(SPSR & (1 << SPIF))); - -#else // OPTIMIZE_HARDWARE_SPI - spiSend(token); - for (uint16_t i = 0; i < 512; i++) { - spiSend(src[i]); - } -#endif // OPTIMIZE_HARDWARE_SPI spiSend(0xff); // dummy crc spiSend(0xff); // dummy crc status_ = spiRec(); if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { error(SD_CARD_ERROR_WRITE); - chipSelectHigh(); - return false; + goto fail; } return true; + + fail: + chipSelectHigh(); + return false; } //------------------------------------------------------------------------------ /** Start a write multiple blocks sequence. @@ -598,14 +602,7 @@ uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ -uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { -#if SD_PROTECT_BLOCK_ZERO - // don't allow write to first block - if (blockNumber == 0) { - error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); - goto fail; - } -#endif // SD_PROTECT_BLOCK_ZERO +bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { // send pre-erase count if (cardAcmd(ACMD23, eraseCount)) { error(SD_CARD_ERROR_ACMD23); @@ -617,6 +614,7 @@ uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { error(SD_CARD_ERROR_CMD25); goto fail; } + chipSelectHigh(); return true; fail: @@ -629,7 +627,8 @@ uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { * \return The value one, true, is returned for success and * the value zero, false, is returned for failure. */ -uint8_t Sd2Card::writeStop(void) { +bool Sd2Card::writeStop() { + chipSelectLow(); if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; spiSend(STOP_TRAN_TOKEN); if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; diff --git a/Marlin/Sd2Card.h b/Marlin/Sd2Card.h index 73b46fb44b..0e8b6665e9 100644 --- a/Marlin/Sd2Card.h +++ b/Marlin/Sd2Card.h @@ -21,67 +21,24 @@ #define Sd2Card_h /** * \file - * Sd2Card class + * \brief Sd2Card class for V2 SD/SDHC cards */ +#include "SdFatConfig.h" #include "Sd2PinMap.h" #include "SdInfo.h" +//------------------------------------------------------------------------------ +// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6 /** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */ uint8_t const SPI_FULL_SPEED = 0; /** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */ uint8_t const SPI_HALF_SPEED = 1; -/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */ +/** Set SCK rate to F_CPU/8. See Sd2Card::setSckRate(). */ uint8_t const SPI_QUARTER_SPEED = 2; -/** - * Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos. - * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. - * - * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used - * on Mega Arduinos. Software SPI works well with GPS Shield V1.1 - * but many SD cards will fail with GPS Shield V1.0. - */ -#define MEGA_SOFT_SPI 0 +/** Set SCK rate to F_CPU/16. See Sd2Card::setSckRate(). */ +uint8_t const SPI_EIGHTH_SPEED = 3; +/** Set SCK rate to F_CPU/32. See Sd2Card::setSckRate(). */ +uint8_t const SPI_SIXTEENTH_SPEED = 4; //------------------------------------------------------------------------------ -#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) -#define SOFTWARE_SPI -#endif // MEGA_SOFT_SPI -//------------------------------------------------------------------------------ -// SPI pin definitions -// -#ifndef SOFTWARE_SPI -// hardware pin defs -/** - * SD Chip Select pin - * - * Warning if this pin is redefined the hardware SS will pin will be enabled - * as an output by init(). An avr processor will not function as an SPI - * master unless SS is set to output mode. - */ -/** The default chip select pin for the SD card is SS. */ -uint8_t const SD_CHIP_SELECT_PIN = SS_PIN; -// The following three pins must not be redefined for hardware SPI. -/** SPI Master Out Slave In pin */ -uint8_t const SPI_MOSI_PIN = MOSI_PIN; -/** SPI Master In Slave Out pin */ -uint8_t const SPI_MISO_PIN = MISO_PIN; -/** SPI Clock pin */ -uint8_t const SPI_SCK_PIN = SCK_PIN; -/** optimize loops for hardware SPI */ -#define OPTIMIZE_HARDWARE_SPI - -#else // SOFTWARE_SPI -// define software SPI pins so Mega can use unmodified GPS Shield -/** SPI chip select pin */ -uint8_t const SD_CHIP_SELECT_PIN = 10; -/** SPI Master Out Slave In pin */ -uint8_t const SPI_MOSI_PIN = 11; -/** SPI Master In Slave Out pin */ -uint8_t const SPI_MISO_PIN = 12; -/** SPI Clock pin */ -uint8_t const SPI_SCK_PIN = 13; -#endif // SOFTWARE_SPI -//------------------------------------------------------------------------------ -/** Protect block zero from write if nonzero */ -#define SD_PROTECT_BLOCK_ZERO 1 /** init timeout ms */ uint16_t const SD_INIT_TIMEOUT = 2000; /** erase timeout ms */ @@ -92,58 +49,99 @@ uint16_t const SD_READ_TIMEOUT = 300; uint16_t const SD_WRITE_TIMEOUT = 600; //------------------------------------------------------------------------------ // SD card errors -/** timeout error for command CMD0 */ +/** timeout error for command CMD0 (initialize card in SPI mode) */ uint8_t const SD_CARD_ERROR_CMD0 = 0X1; /** CMD8 was not accepted - not a valid SD card*/ uint8_t const SD_CARD_ERROR_CMD8 = 0X2; +/** card returned an error response for CMD12 (write stop) */ +uint8_t const SD_CARD_ERROR_CMD12 = 0X3; /** card returned an error response for CMD17 (read block) */ -uint8_t const SD_CARD_ERROR_CMD17 = 0X3; +uint8_t const SD_CARD_ERROR_CMD17 = 0X4; +/** card returned an error response for CMD18 (read multiple block) */ +uint8_t const SD_CARD_ERROR_CMD18 = 0X5; /** card returned an error response for CMD24 (write block) */ -uint8_t const SD_CARD_ERROR_CMD24 = 0X4; +uint8_t const SD_CARD_ERROR_CMD24 = 0X6; /** WRITE_MULTIPLE_BLOCKS command failed */ -uint8_t const SD_CARD_ERROR_CMD25 = 0X05; +uint8_t const SD_CARD_ERROR_CMD25 = 0X7; /** card returned an error response for CMD58 (read OCR) */ -uint8_t const SD_CARD_ERROR_CMD58 = 0X06; +uint8_t const SD_CARD_ERROR_CMD58 = 0X8; /** SET_WR_BLK_ERASE_COUNT failed */ -uint8_t const SD_CARD_ERROR_ACMD23 = 0X07; -/** card's ACMD41 initialization process timeout */ -uint8_t const SD_CARD_ERROR_ACMD41 = 0X08; +uint8_t const SD_CARD_ERROR_ACMD23 = 0X9; +/** ACMD41 initialization process timeout */ +uint8_t const SD_CARD_ERROR_ACMD41 = 0XA; /** card returned a bad CSR version field */ -uint8_t const SD_CARD_ERROR_BAD_CSD = 0X09; +uint8_t const SD_CARD_ERROR_BAD_CSD = 0XB; /** erase block group command failed */ -uint8_t const SD_CARD_ERROR_ERASE = 0X0A; +uint8_t const SD_CARD_ERROR_ERASE = 0XC; /** card not capable of single block erase */ -uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B; +uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD; /** Erase sequence timed out */ -uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C; +uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0XE; /** card returned an error token instead of read data */ -uint8_t const SD_CARD_ERROR_READ = 0X0D; +uint8_t const SD_CARD_ERROR_READ = 0XF; /** read CID or CSD failed */ -uint8_t const SD_CARD_ERROR_READ_REG = 0X0E; +uint8_t const SD_CARD_ERROR_READ_REG = 0X10; /** timeout while waiting for start of read data */ -uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F; +uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X11; /** card did not accept STOP_TRAN_TOKEN */ -uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10; +uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X12; /** card returned an error token as a response to a write operation */ -uint8_t const SD_CARD_ERROR_WRITE = 0X11; +uint8_t const SD_CARD_ERROR_WRITE = 0X13; /** attempt to write protected block zero */ -uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12; +uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14; // REMOVE - not used /** card did not go ready for a multiple block write */ -uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13; +uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X15; /** card returned an error to a CMD13 status check after a write */ -uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14; +uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16; /** timeout occurred during write programming */ -uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15; +uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X17; /** incorrect rate selected */ -uint8_t const SD_CARD_ERROR_SCK_RATE = 0X16; +uint8_t const SD_CARD_ERROR_SCK_RATE = 0X18; +/** init() not called */ +uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0X19; //------------------------------------------------------------------------------ // card types /** Standard capacity V1 SD card */ -uint8_t const SD_CARD_TYPE_SD1 = 1; +uint8_t const SD_CARD_TYPE_SD1 = 1; /** Standard capacity V2 SD card */ -uint8_t const SD_CARD_TYPE_SD2 = 2; +uint8_t const SD_CARD_TYPE_SD2 = 2; /** High Capacity SD card */ uint8_t const SD_CARD_TYPE_SDHC = 3; +/** + * define SOFTWARE_SPI to use bit-bang SPI + */ +//------------------------------------------------------------------------------ +#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) +#define SOFTWARE_SPI +#elif USE_SOFTWARE_SPI +#define SOFTWARE_SPI +#endif // MEGA_SOFT_SPI +//------------------------------------------------------------------------------ +// SPI pin definitions - do not edit here - change in SdFatConfig.h +// +#ifndef SOFTWARE_SPI +// hardware pin defs +/** The default chip select pin for the SD card is SS. */ +uint8_t const SD_CHIP_SELECT_PIN = SS_PIN; +// The following three pins must not be redefined for hardware SPI. +/** SPI Master Out Slave In pin */ +uint8_t const SPI_MOSI_PIN = MOSI_PIN; +/** SPI Master In Slave Out pin */ +uint8_t const SPI_MISO_PIN = MISO_PIN; +/** SPI Clock pin */ +uint8_t const SPI_SCK_PIN = SCK_PIN; + +#else // SOFTWARE_SPI + +/** SPI chip select pin */ +uint8_t const SD_CHIP_SELECT_PIN = SOFT_SPI_CS_PIN; +/** SPI Master Out Slave In pin */ +uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN; +/** SPI Master In Slave Out pin */ +uint8_t const SPI_MISO_PIN = SOFT_SPI_MISO_PIN; +/** SPI Clock pin */ +uint8_t const SPI_SCK_PIN = SOFT_SPI_SCK_PIN; +#endif // SOFTWARE_SPI //------------------------------------------------------------------------------ /** * \class Sd2Card @@ -152,66 +150,70 @@ uint8_t const SD_CARD_TYPE_SDHC = 3; class Sd2Card { public: /** Construct an instance of Sd2Card. */ - Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} - uint32_t cardSize(void); - uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); - uint8_t eraseSingleBlockEnable(void); + Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0) {} + uint32_t cardSize(); + bool erase(uint32_t firstBlock, uint32_t lastBlock); + bool eraseSingleBlockEnable(); + /** + * Set SD error code. + * \param[in] code value for error code. + */ + void error(uint8_t code) {errorCode_ = code;} /** * \return error code for last error. See Sd2Card.h for a list of error codes. */ - uint8_t errorCode(void) const {return errorCode_;} + int errorCode() const {return errorCode_;} /** \return error data for last error. */ - uint8_t errorData(void) const {return status_;} + int errorData() const {return status_;} /** * Initialize an SD flash memory card with default clock rate and chip * select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + * + * \return true for success or false for failure. */ - uint8_t init(void) { - return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); - } + bool init(uint8_t sckRateID = SPI_FULL_SPEED, + uint8_t chipSelectPin = SD_CHIP_SELECT_PIN); + bool readBlock(uint32_t block, uint8_t* dst); /** - * Initialize an SD flash memory card with the selected SPI clock rate - * and the default SD chip select pin. - * See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). - */ - uint8_t init(uint8_t sckRateID) { - return init(sckRateID, SD_CHIP_SELECT_PIN); - } - uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); - void partialBlockRead(uint8_t value); - /** Returns the current value, true or false, for partial block read. */ - uint8_t partialBlockRead(void) const {return partialBlockRead_;} - uint8_t readBlock(uint32_t block, uint8_t* dst); - uint8_t readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst); - /** - * Read a cards CID register. The CID contains card identification + * Read a card's CID register. The CID contains card identification * information such as Manufacturer ID, Product name, Product serial - * number and Manufacturing date. */ - uint8_t readCID(cid_t* cid) { + * number and Manufacturing date. + * + * \param[out] cid pointer to area for returned data. + * + * \return true for success or false for failure. + */ + bool readCID(cid_t* cid) { return readRegister(CMD10, cid); } /** - * Read a cards CSD register. The CSD contains Card-Specific Data that - * provides information regarding access to the card's contents. */ - uint8_t readCSD(csd_t* csd) { + * Read a card's CSD register. The CSD contains Card-Specific Data that + * provides information regarding access to the card's contents. + * + * \param[out] csd pointer to area for returned data. + * + * \return true for success or false for failure. + */ + bool readCSD(csd_t* csd) { return readRegister(CMD9, csd); } - void readEnd(void); - uint8_t setSckRate(uint8_t sckRateID); - /** Return the card type: SD V1, SD V2 or SDHC */ - uint8_t type(void) const {return type_;} - uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src); - uint8_t writeData(const uint8_t* src); - uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); - uint8_t writeStop(void); + bool readData(uint8_t *dst); + bool readStart(uint32_t blockNumber); + bool readStop(); + bool setSckRate(uint8_t sckRateID); + /** Return the card type: SD V1, SD V2 or SDHC + * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC. + */ + int type() const {return type_;} + bool writeBlock(uint32_t blockNumber, const uint8_t* src); + bool writeData(const uint8_t* src); + bool writeStart(uint32_t blockNumber, uint32_t eraseCount); + bool writeStop(); private: - uint32_t block_; + //---------------------------------------------------------------------------- uint8_t chipSelectPin_; uint8_t errorCode_; - uint8_t inBlock_; - uint16_t offset_; - uint8_t partialBlockRead_; + uint8_t spiRate_; uint8_t status_; uint8_t type_; // private functions @@ -220,14 +222,13 @@ class Sd2Card { return cardCommand(cmd, arg); } uint8_t cardCommand(uint8_t cmd, uint32_t arg); - void error(uint8_t code) {errorCode_ = code;} - uint8_t readRegister(uint8_t cmd, void* buf); - uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); - void chipSelectHigh(void); - void chipSelectLow(void); + + bool readData(uint8_t* dst, uint16_t count); + bool readRegister(uint8_t cmd, void* buf); + void chipSelectHigh(); + void chipSelectLow(); void type(uint8_t value) {type_ = value;} - uint8_t waitNotBusy(uint16_t timeoutMillis); - uint8_t writeData(uint8_t token, const uint8_t* src); - uint8_t waitStartBlock(void); + bool waitNotBusy(uint16_t timeoutMillis); + bool writeData(uint8_t token, const uint8_t* src); }; #endif // Sd2Card_h diff --git a/Marlin/Sd2PinMap.h b/Marlin/Sd2PinMap.h index 4bd75a35db..847f9f33bb 100644 --- a/Marlin/Sd2PinMap.h +++ b/Marlin/Sd2PinMap.h @@ -21,7 +21,6 @@ #ifndef Sd2PinMap_h #define Sd2PinMap_h #include - //------------------------------------------------------------------------------ /** struct for mapping digital pins */ struct pin_map_t { @@ -31,18 +30,19 @@ struct pin_map_t { uint8_t bit; }; //------------------------------------------------------------------------------ -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(__AVR_ATmega1280__)\ +|| defined(__AVR_ATmega2560__) // Mega // Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 20; -uint8_t const SCL_PIN = 21; +uint8_t const SDA_PIN = 20; // D1 +uint8_t const SCL_PIN = 21; // D0 // SPI port -uint8_t const SS_PIN = 53; -uint8_t const MOSI_PIN = 51; -uint8_t const MISO_PIN = 50; -uint8_t const SCK_PIN = 52; +uint8_t const SS_PIN = 53; // B0 +uint8_t const MOSI_PIN = 51; // B2 +uint8_t const MISO_PIN = 50; // B3 +uint8_t const SCK_PIN = 52; // B1 static const pin_map_t digitalPinMap[] = { {&DDRE, &PINE, &PORTE, 0}, // E0 0 @@ -117,18 +117,20 @@ static const pin_map_t digitalPinMap[] = { {&DDRK, &PINK, &PORTK, 7} // K7 69 }; //------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) +#elif defined(__AVR_ATmega644P__)\ +|| defined(__AVR_ATmega644__)\ +|| defined(__AVR_ATmega1284P__) // Sanguino // Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 17; -uint8_t const SCL_PIN = 18; +uint8_t const SDA_PIN = 17; // C1 +uint8_t const SCL_PIN = 18; // C2 // SPI port -uint8_t const SS_PIN = 4; -uint8_t const MOSI_PIN = 5; -uint8_t const MISO_PIN = 6; -uint8_t const SCK_PIN = 7; +uint8_t const SS_PIN = 4; // B4 +uint8_t const MOSI_PIN = 5; // B5 +uint8_t const MISO_PIN = 6; // B6 +uint8_t const SCK_PIN = 7; // B7 static const pin_map_t digitalPinMap[] = { {&DDRB, &PINB, &PORTB, 0}, // B0 0 @@ -169,14 +171,14 @@ static const pin_map_t digitalPinMap[] = { // Teensy 2.0 // Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 6; -uint8_t const SCL_PIN = 5; +uint8_t const SDA_PIN = 6; // D1 +uint8_t const SCL_PIN = 5; // D0 // SPI port -uint8_t const SS_PIN = 0; -uint8_t const MOSI_PIN = 2; -uint8_t const MISO_PIN = 3; -uint8_t const SCK_PIN = 1; +uint8_t const SS_PIN = 0; // B0 +uint8_t const MOSI_PIN = 2; // B2 +uint8_t const MISO_PIN = 3; // B3 +uint8_t const SCK_PIN = 1; // B1 static const pin_map_t digitalPinMap[] = { {&DDRB, &PINB, &PORTB, 0}, // B0 0 @@ -206,18 +208,19 @@ static const pin_map_t digitalPinMap[] = { {&DDRE, &PINE, &PORTE, 6} // E6 24 }; //------------------------------------------------------------------------------ -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +#elif defined(__AVR_AT90USB646__)\ +|| defined(__AVR_AT90USB1286__) // Teensy++ 1.0 & 2.0 // Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 1; -uint8_t const SCL_PIN = 0; +uint8_t const SDA_PIN = 1; // D1 +uint8_t const SCL_PIN = 0; // D0 // SPI port -uint8_t const SS_PIN = 20; -uint8_t const MOSI_PIN = 22; -uint8_t const MISO_PIN = 23; -uint8_t const SCK_PIN = 21; +uint8_t const SS_PIN = 20; // B0 +uint8_t const MOSI_PIN = 22; // B2 +uint8_t const MISO_PIN = 23; // B3 +uint8_t const SCK_PIN = 21; // B1 static const pin_map_t digitalPinMap[] = { {&DDRD, &PIND, &PORTD, 0}, // D0 0 @@ -268,18 +271,20 @@ static const pin_map_t digitalPinMap[] = { {&DDRF, &PINF, &PORTF, 7} // F7 45 }; //------------------------------------------------------------------------------ -#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#elif defined(__AVR_ATmega168__)\ +||defined(__AVR_ATmega168P__)\ +||defined(__AVR_ATmega328P__) // 168 and 328 Arduinos // Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 18; -uint8_t const SCL_PIN = 19; +uint8_t const SDA_PIN = 18; // C4 +uint8_t const SCL_PIN = 19; // C5 // SPI port -uint8_t const SS_PIN = 10; -uint8_t const MOSI_PIN = 11; -uint8_t const MISO_PIN = 12; -uint8_t const SCK_PIN = 13; +uint8_t const SS_PIN = 10; // B2 +uint8_t const MOSI_PIN = 11; // B3 +uint8_t const MISO_PIN = 12; // B4 +uint8_t const SCK_PIN = 13; // B5 static const pin_map_t digitalPinMap[] = { {&DDRD, &PIND, &PORTD, 0}, // D0 0 @@ -303,7 +308,9 @@ static const pin_map_t digitalPinMap[] = { {&DDRC, &PINC, &PORTC, 4}, // C4 18 {&DDRC, &PINC, &PORTC, 5} // C5 19 }; -#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#else // defined(__AVR_ATmega1280__) +#error unknown chip +#endif // defined(__AVR_ATmega1280__) //------------------------------------------------------------------------------ static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t); @@ -311,7 +318,7 @@ uint8_t badPinNumber(void) __attribute__((error("Pin number is too large or not a constant"))); static inline __attribute__((always_inline)) - uint8_t getPinMode(uint8_t pin) { + bool getPinMode(uint8_t pin) { if (__builtin_constant_p(pin) && pin < digitalPinCount) { return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1; } else { @@ -331,7 +338,7 @@ static inline __attribute__((always_inline)) } } static inline __attribute__((always_inline)) - uint8_t fastDigitalRead(uint8_t pin) { + bool fastDigitalRead(uint8_t pin) { if (__builtin_constant_p(pin) && pin < digitalPinCount) { return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1; } else { diff --git a/Marlin/SdBaseFile.cpp b/Marlin/SdBaseFile.cpp new file mode 100644 index 0000000000..dda44ec3ca --- /dev/null +++ b/Marlin/SdBaseFile.cpp @@ -0,0 +1,1818 @@ +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#include "SdBaseFile.h" +//------------------------------------------------------------------------------ +// pointer to cwd directory +SdBaseFile* SdBaseFile::cwd_ = 0; +// callback function for date/time +void (*SdBaseFile::dateTime_)(uint16_t* date, uint16_t* time) = 0; +//------------------------------------------------------------------------------ +// add a cluster to a file +bool SdBaseFile::addCluster() { + if (!vol_->allocContiguous(1, &curCluster_)) goto fail; + + // if first cluster of file link to directory entry + if (firstCluster_ == 0) { + firstCluster_ = curCluster_; + flags_ |= F_FILE_DIR_DIRTY; + } + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +// Add a cluster to a directory file and zero the cluster. +// return with first block of cluster in the cache +bool SdBaseFile::addDirCluster() { + uint32_t block; + // max folder size + if (fileSize_/sizeof(dir_t) >= 0XFFFF) goto fail; + + if (!addCluster()) goto fail; + if (!vol_->cacheFlush()) goto fail; + + block = vol_->clusterStartBlock(curCluster_); + + // set cache to first block of cluster + vol_->cacheSetBlockNumber(block, true); + + // zero first block of cluster + memset(vol_->cacheBuffer_.data, 0, 512); + + // zero rest of cluster + for (uint8_t i = 1; i < vol_->blocksPerCluster_; i++) { + if (!vol_->writeBlock(block + i, vol_->cacheBuffer_.data)) goto fail; + } + // Increase directory file size by cluster size + fileSize_ += 512UL << vol_->clusterSizeShift_; + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +// cache a file's directory entry +// return pointer to cached entry or null for failure +dir_t* SdBaseFile::cacheDirEntry(uint8_t action) { + if (!vol_->cacheRawBlock(dirBlock_, action)) goto fail; + return vol_->cache()->dir + dirIndex_; + + fail: + return 0; +} +//------------------------------------------------------------------------------ +/** Close a file and force cached data and directory information + * to be written to the storage device. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include no file is open or an I/O error. + */ +bool SdBaseFile::close() { + bool rtn = sync(); + type_ = FAT_FILE_TYPE_CLOSED; + return rtn; +} +//------------------------------------------------------------------------------ +/** Check for contiguous file and return its raw block range. + * + * \param[out] bgnBlock the first block address for the file. + * \param[out] endBlock the last block address for the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include file is not contiguous, file has zero length + * or an I/O error occurred. + */ +bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { + // error if no blocks + if (firstCluster_ == 0) goto fail; + + for (uint32_t c = firstCluster_; ; c++) { + uint32_t next; + if (!vol_->fatGet(c, &next)) goto fail; + + // check for contiguous + if (next != (c + 1)) { + // error if not end of chain + if (!vol_->isEOC(next)) goto fail; + *bgnBlock = vol_->clusterStartBlock(firstCluster_); + *endBlock = vol_->clusterStartBlock(c) + + vol_->blocksPerCluster_ - 1; + return true; + } + } + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Create and open a new contiguous file of a specified size. + * + * \note This function only supports short DOS 8.3 names. + * See open() for more information. + * + * \param[in] dirFile The directory where the file will be created. + * \param[in] path A path with a valid DOS 8.3 file name. + * \param[in] size The desired file size. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include \a path contains + * an invalid DOS 8.3 file name, the FAT volume has not been initialized, + * a file is already open, the file already exists, the root + * directory is full or an I/O error. + * + */ +bool SdBaseFile::createContiguous(SdBaseFile* dirFile, + const char* path, uint32_t size) { + uint32_t count; + // don't allow zero length file + if (size == 0) goto fail; + if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) goto fail; + + // calculate number of clusters needed + count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; + + // allocate clusters + if (!vol_->allocContiguous(count, &firstCluster_)) { + remove(); + goto fail; + } + fileSize_ = size; + + // insure sync() will update dir entry + flags_ |= F_FILE_DIR_DIRTY; + + return sync(); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Return a file's directory entry. + * + * \param[out] dir Location for return of the file's directory entry. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::dirEntry(dir_t* dir) { + dir_t* p; + // make sure fields on SD are correct + if (!sync()) goto fail; + + // read entry + p = cacheDirEntry(SdVolume::CACHE_FOR_READ); + if (!p) goto fail; + + // copy to caller's struct + memcpy(dir, p, sizeof(dir_t)); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Format the name field of \a dir into the 13 byte array + * \a name in standard 8.3 short name format. + * + * \param[in] dir The directory structure containing the name. + * \param[out] name A 13 byte char array for the formatted name. + */ +void SdBaseFile::dirName(const dir_t& dir, char* name) { + uint8_t j = 0; + for (uint8_t i = 0; i < 11; i++) { + if (dir.name[i] == ' ')continue; + if (i == 8) name[j++] = '.'; + name[j++] = dir.name[i]; + } + name[j] = 0; +} +//------------------------------------------------------------------------------ +/** Test for the existence of a file in a directory + * + * \param[in] name Name of the file to be tested for. + * + * The calling instance must be an open directory file. + * + * dirFile.exists("TOFIND.TXT") searches for "TOFIND.TXT" in the directory + * dirFile. + * + * \return true if the file exists else false. + */ +bool SdBaseFile::exists(const char* name) { + SdBaseFile file; + return file.open(this, name, O_READ); +} +//------------------------------------------------------------------------------ +/** + * Get a string from a file. + * + * fgets() reads bytes from a file into the array pointed to by \a str, until + * \a num - 1 bytes are read, or a delimiter is read and transferred to \a str, + * or end-of-file is encountered. The string is then terminated + * with a null byte. + * + * fgets() deletes CR, '\\r', from the string. This insures only a '\\n' + * terminates the string for Windows text files which use CRLF for newline. + * + * \param[out] str Pointer to the array where the string is stored. + * \param[in] num Maximum number of characters to be read + * (including the final null byte). Usually the length + * of the array \a str is used. + * \param[in] delim Optional set of delimiters. The default is "\n". + * + * \return For success fgets() returns the length of the string in \a str. + * If no data is read, fgets() returns zero for EOF or -1 if an error occurred. + **/ +int16_t SdBaseFile::fgets(char* str, int16_t num, char* delim) { + char ch; + int16_t n = 0; + int16_t r = -1; + while ((n + 1) < num && (r = read(&ch, 1)) == 1) { + // delete CR + if (ch == '\r') continue; + str[n++] = ch; + if (!delim) { + if (ch == '\n') break; + } else { + if (strchr(delim, ch)) break; + } + } + if (r < 0) { + // read error + return -1; + } + str[n] = '\0'; + return n; +} +//------------------------------------------------------------------------------ +/** Get a file's name + * + * \param[out] name An array of 13 characters for the file's name. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::getFilename(char* name) { + if (!isOpen()) return false; + + if (isRoot()) { + name[0] = '/'; + name[1] = '\0'; + return true; + } + // cache entry + dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); + if (!p) return false; + + // format name + dirName(*p, name); + return true; +} +//------------------------------------------------------------------------------ +void SdBaseFile::getpos(fpos_t* pos) { + pos->position = curPosition_; + pos->cluster = curCluster_; +} +//------------------------------------------------------------------------------ +/** List directory contents to Serial. + * + * \param[in] flags The inclusive OR of + * + * LS_DATE - %Print file modification date + * + * LS_SIZE - %Print file size. + * + * LS_R - Recursive list of subdirectories. + */ +void SdBaseFile::ls(uint8_t flags) { + ls(&Serial, flags, 0); +} +//------------------------------------------------------------------------------ +/** List directory contents. + * + * \param[in] pr Print stream for list. + * + * \param[in] flags The inclusive OR of + * + * LS_DATE - %Print file modification date + * + * LS_SIZE - %Print file size. + * + * LS_R - Recursive list of subdirectories. + * + * \param[in] indent Amount of space before file name. Used for recursive + * list to indicate subdirectory level. + */ +void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) { + rewind(); + int8_t status; + while ((status = lsPrintNext(pr, flags, indent))) { + if (status > 1 && (flags & LS_R)) { + uint16_t index = curPosition()/32 - 1; + SdBaseFile s; + if (s.open(this, index, O_READ)) s.ls(pr, flags, indent + 2); + seekSet(32 * (index + 1)); + } + } +} +//------------------------------------------------------------------------------ +// saves 32 bytes on stack for ls recursion +// return 0 - EOF, 1 - normal file, or 2 - directory +int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) { + dir_t dir; + uint8_t w = 0; + + while (1) { + if (read(&dir, sizeof(dir)) != sizeof(dir)) return 0; + if (dir.name[0] == DIR_NAME_FREE) return 0; + + // skip deleted entry and entries for . and .. + if (dir.name[0] != DIR_NAME_DELETED && dir.name[0] != '.' + && DIR_IS_FILE_OR_SUBDIR(&dir)) break; + } + // indent for dir level + for (uint8_t i = 0; i < indent; i++) pr->write(' '); + + // print name + for (uint8_t i = 0; i < 11; i++) { + if (dir.name[i] == ' ')continue; + if (i == 8) { + pr->write('.'); + w++; + } + pr->write(dir.name[i]); + w++; + } + if (DIR_IS_SUBDIR(&dir)) { + pr->write('/'); + w++; + } + if (flags & (LS_DATE | LS_SIZE)) { + while (w++ < 14) pr->write(' '); + } + // print modify date/time if requested + if (flags & LS_DATE) { + pr->write(' '); + printFatDate(pr, dir.lastWriteDate); + pr->write(' '); + printFatTime(pr, dir.lastWriteTime); + } + // print size if requested + if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) { + pr->write(' '); + pr->print(dir.fileSize); + } + pr->println(); + return DIR_IS_FILE(&dir) ? 1 : 2; +} +//------------------------------------------------------------------------------ +// format directory name field from a 8.3 name string +bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) { + uint8_t c; + uint8_t n = 7; // max index for part before dot + uint8_t i = 0; + // blank fill name and extension + while (i < 11) name[i++] = ' '; + i = 0; + while (*str != '\0' && *str != '/') { + c = *str++; + if (c == '.') { + if (n == 10) goto fail; // only one dot allowed + n = 10; // max index for full 8.3 name + i = 8; // place for extension + } else { + // illegal FAT characters + PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); + uint8_t b; + while ((b = pgm_read_byte(p++))) if (b == c) goto fail; + // check size and only allow ASCII printable characters + if (i > n || c < 0X21 || c > 0X7E)goto fail; + // only upper case allowed in 8.3 names - convert lower to upper + name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); + } + } + *ptr = str; + // must have a file name, extension is optional + return name[0] != ' '; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Make a new directory. + * + * \param[in] parent An open SdFat instance for the directory that will contain + * the new directory. + * + * \param[in] path A path with a valid 8.3 DOS name for the new directory. + * + * \param[in] pFlag Create missing parent directories if true. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include this file is already open, \a parent is not a + * directory, \a path is invalid or already exists in \a parent. + */ +bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) { + uint8_t dname[11]; + SdBaseFile dir1, dir2; + SdBaseFile* sub = &dir1; + SdBaseFile* start = parent; + + if (!parent || isOpen()) goto fail; + + if (*path == '/') { + while (*path == '/') path++; + if (!parent->isRoot()) { + if (!dir2.openRoot(parent->vol_)) goto fail; + parent = &dir2; + } + } + while (1) { + if (!make83Name(path, dname, &path)) goto fail; + while (*path == '/') path++; + if (!*path) break; + if (!sub->open(parent, dname, O_READ)) { + if (!pFlag || !sub->mkdir(parent, dname)) { + goto fail; + } + } + if (parent != start) parent->close(); + parent = sub; + sub = parent != &dir1 ? &dir1 : &dir2; + } + return mkdir(parent, dname); + + fail: + return false; +} +//------------------------------------------------------------------------------ +bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) { + uint32_t block; + dir_t d; + dir_t* p; + + if (!parent->isDir()) goto fail; + + // create a normal file + if (!open(parent, dname, O_CREAT | O_EXCL | O_RDWR)) goto fail; + + // convert file to directory + flags_ = O_READ; + type_ = FAT_FILE_TYPE_SUBDIR; + + // allocate and zero first cluster + if (!addDirCluster())goto fail; + + // force entry to SD + if (!sync()) goto fail; + + // cache entry - should already be in cache due to sync() call + p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!p) goto fail; + + // change directory entry attribute + p->attributes = DIR_ATT_DIRECTORY; + + // make entry for '.' + memcpy(&d, p, sizeof(d)); + d.name[0] = '.'; + for (uint8_t i = 1; i < 11; i++) d.name[i] = ' '; + + // cache block for '.' and '..' + block = vol_->clusterStartBlock(firstCluster_); + if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail; + + // copy '.' to block + memcpy(&vol_->cache()->dir[0], &d, sizeof(d)); + + // make entry for '..' + d.name[1] = '.'; + if (parent->isRoot()) { + d.firstClusterLow = 0; + d.firstClusterHigh = 0; + } else { + d.firstClusterLow = parent->firstCluster_ & 0XFFFF; + d.firstClusterHigh = parent->firstCluster_ >> 16; + } + // copy '..' to block + memcpy(&vol_->cache()->dir[1], &d, sizeof(d)); + + // write first block + return vol_->cacheFlush(); + + fail: + return false; +} +//------------------------------------------------------------------------------ + /** Open a file in the current working directory. + * + * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ + bool SdBaseFile::open(const char* path, uint8_t oflag) { + return open(cwd_, path, oflag); + } +//------------------------------------------------------------------------------ +/** Open a file or directory by name. + * + * \param[in] dirFile An open SdFat instance for the directory containing the + * file to be opened. + * + * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags from the following list + * + * O_READ - Open for reading. + * + * O_RDONLY - Same as O_READ. + * + * O_WRITE - Open for writing. + * + * O_WRONLY - Same as O_WRITE. + * + * O_RDWR - Open for reading and writing. + * + * O_APPEND - If set, the file offset shall be set to the end of the + * file prior to each write. + * + * O_AT_END - Set the initial position at the end of the file. + * + * O_CREAT - If the file exists, this flag has no effect except as noted + * under O_EXCL below. Otherwise, the file shall be created + * + * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. + * + * O_SYNC - Call sync() after each write. This flag should not be used with + * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. + * These functions do character at a time writes so sync() will be called + * after each byte. + * + * O_TRUNC - If the file exists and is a regular file, and the file is + * successfully opened and is not read only, its length shall be truncated to 0. + * + * WARNING: A given file must not be opened by more than one SdBaseFile object + * of file corruption may occur. + * + * \note Directory files must be opened read only. Write and truncation is + * not allowed for directory files. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include this file is already open, \a dirFile is not + * a directory, \a path is invalid, the file does not exist + * or can't be opened in the access mode specified by oflag. + */ +bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag) { + uint8_t dname[11]; + SdBaseFile dir1, dir2; + SdBaseFile *parent = dirFile; + SdBaseFile *sub = &dir1; + + if (!dirFile) goto fail; + + // error if already open + if (isOpen()) goto fail; + + if (*path == '/') { + while (*path == '/') path++; + if (!dirFile->isRoot()) { + if (!dir2.openRoot(dirFile->vol_)) goto fail; + parent = &dir2; + } + } + while (1) { + if (!make83Name(path, dname, &path)) goto fail; + while (*path == '/') path++; + if (!*path) break; + if (!sub->open(parent, dname, O_READ)) goto fail; + if (parent != dirFile) parent->close(); + parent = sub; + sub = parent != &dir1 ? &dir1 : &dir2; + } + return open(parent, dname, oflag); + + fail: + return false; +} +//------------------------------------------------------------------------------ +// open with filename in dname +bool SdBaseFile::open(SdBaseFile* dirFile, + const uint8_t dname[11], uint8_t oflag) { + bool emptyFound = false; + bool fileFound = false; + uint8_t index; + dir_t* p; + + vol_ = dirFile->vol_; + + dirFile->rewind(); + // search for file + + while (dirFile->curPosition_ < dirFile->fileSize_) { + index = 0XF & (dirFile->curPosition_ >> 5); + p = dirFile->readDirCache(); + if (!p) goto fail; + + if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { + // remember first empty slot + if (!emptyFound) { + dirBlock_ = dirFile->vol_->cacheBlockNumber(); + dirIndex_ = index; + emptyFound = true; + } + // done if no entries follow + if (p->name[0] == DIR_NAME_FREE) break; + } else if (!memcmp(dname, p->name, 11)) { + fileFound = true; + break; + } + } + if (fileFound) { + // don't open existing file if O_EXCL + if (oflag & O_EXCL) goto fail; + } else { + // don't create unless O_CREAT and O_WRITE + if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) goto fail; + if (emptyFound) { + index = dirIndex_; + p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!p) goto fail; + } else { + if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) goto fail; + + // add and zero cluster for dirFile - first cluster is in cache for write + if (!dirFile->addDirCluster()) goto fail; + + // use first entry in cluster + p = dirFile->vol_->cache()->dir; + index = 0; + } + // initialize as empty file + memset(p, 0, sizeof(dir_t)); + memcpy(p->name, dname, 11); + + // set timestamps + if (dateTime_) { + // call user date/time function + dateTime_(&p->creationDate, &p->creationTime); + } else { + // use default date/time + p->creationDate = FAT_DEFAULT_DATE; + p->creationTime = FAT_DEFAULT_TIME; + } + p->lastAccessDate = p->creationDate; + p->lastWriteDate = p->creationDate; + p->lastWriteTime = p->creationTime; + + // write entry to SD + if (!dirFile->vol_->cacheFlush()) goto fail; + } + // open entry in cache + return openCachedEntry(index, oflag); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Open a file by index. + * + * \param[in] dirFile An open SdFat instance for the directory. + * + * \param[in] index The \a index of the directory entry for the file to be + * opened. The value for \a index is (directory file position)/32. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. + * + * See open() by path for definition of flags. + * \return true for success or false for failure. + */ +bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) { + dir_t* p; + + vol_ = dirFile->vol_; + + // error if already open + if (isOpen() || !dirFile) goto fail; + + // don't open existing file if O_EXCL - user call error + if (oflag & O_EXCL) goto fail; + + // seek to location of entry + if (!dirFile->seekSet(32 * index)) goto fail; + + // read entry into cache + p = dirFile->readDirCache(); + if (!p) goto fail; + + // error if empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_FREE || + p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + goto fail; + } + // open cached entry + return openCachedEntry(index & 0XF, oflag); + + fail: + return false; +} +//------------------------------------------------------------------------------ +// open a cached directory entry. Assumes vol_ is initialized +bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { + // location of entry in cache + dir_t* p = &vol_->cache()->dir[dirIndex]; + + // write or truncate is an error for a directory or read-only file + if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { + if (oflag & (O_WRITE | O_TRUNC)) goto fail; + } + // remember location of directory entry on SD + dirBlock_ = vol_->cacheBlockNumber(); + dirIndex_ = dirIndex; + + // copy first cluster number for directory fields + firstCluster_ = (uint32_t)p->firstClusterHigh << 16; + firstCluster_ |= p->firstClusterLow; + + // make sure it is a normal file or subdirectory + if (DIR_IS_FILE(p)) { + fileSize_ = p->fileSize; + type_ = FAT_FILE_TYPE_NORMAL; + } else if (DIR_IS_SUBDIR(p)) { + if (!vol_->chainSize(firstCluster_, &fileSize_)) goto fail; + type_ = FAT_FILE_TYPE_SUBDIR; + } else { + goto fail; + } + // save open flags for read/write + flags_ = oflag & F_OFLAG; + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + if ((oflag & O_TRUNC) && !truncate(0)) return false; + return oflag & O_AT_END ? seekEnd(0) : true; + + fail: + type_ = FAT_FILE_TYPE_CLOSED; + return false; +} +//------------------------------------------------------------------------------ +/** Open the next file or subdirectory in a directory. + * + * \param[in] dirFile An open SdFat instance for the directory containing the + * file to be opened. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. + * + * See open() by path for definition of flags. + * \return true for success or false for failure. + */ +bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) { + dir_t* p; + uint8_t index; + + if (!dirFile) goto fail; + + // error if already open + if (isOpen()) goto fail; + + vol_ = dirFile->vol_; + + while (1) { + index = 0XF & (dirFile->curPosition_ >> 5); + + // read entry into cache + p = dirFile->readDirCache(); + if (!p) goto fail; + + // done if last entry + if (p->name[0] == DIR_NAME_FREE) goto fail; + + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + continue; + } + // must be file or dir + if (DIR_IS_FILE_OR_SUBDIR(p)) { + return openCachedEntry(index, oflag); + } + } + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Open a directory's parent directory. + * + * \param[in] dir Parent of this directory will be opened. Must not be root. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::openParent(SdBaseFile* dir) { + dir_t entry; + dir_t* p; + SdBaseFile file; + uint32_t c; + uint32_t cluster; + uint32_t lbn; + // error if already open or dir is root or dir is not a directory + if (isOpen() || !dir || dir->isRoot() || !dir->isDir()) goto fail; + vol_ = dir->vol_; + // position to '..' + if (!dir->seekSet(32)) goto fail; + // read '..' entry + if (dir->read(&entry, sizeof(entry)) != 32) goto fail; + // verify it is '..' + if (entry.name[0] != '.' || entry.name[1] != '.') goto fail; + // start cluster for '..' + cluster = entry.firstClusterLow; + cluster |= (uint32_t)entry.firstClusterHigh << 16; + if (cluster == 0) return openRoot(vol_); + // start block for '..' + lbn = vol_->clusterStartBlock(cluster); + // first block of parent dir + if (!vol_->cacheRawBlock(lbn, SdVolume::CACHE_FOR_READ)) { + goto fail; + } + p = &vol_->cacheBuffer_.dir[1]; + // verify name for '../..' + if (p->name[0] != '.' || p->name[1] != '.') goto fail; + // '..' is pointer to first cluster of parent. open '../..' to find parent + if (p->firstClusterHigh == 0 && p->firstClusterLow == 0) { + if (!file.openRoot(dir->volume())) goto fail; + } else { + if (!file.openCachedEntry(1, O_READ)) goto fail; + } + // search for parent in '../..' + do { + if (file.readDir(&entry) != 32) goto fail; + c = entry.firstClusterLow; + c |= (uint32_t)entry.firstClusterHigh << 16; + } while (c != cluster); + // open parent + return open(&file, file.curPosition()/32 - 1, O_READ); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Open a volume's root directory. + * + * \param[in] vol The FAT volume containing the root directory to be opened. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file is already open, the FAT volume has + * not been initialized or it a FAT12 volume. + */ +bool SdBaseFile::openRoot(SdVolume* vol) { + // error if file is already open + if (isOpen()) goto fail; + + if (vol->fatType() == 16 || (FAT12_SUPPORT && vol->fatType() == 12)) { + type_ = FAT_FILE_TYPE_ROOT_FIXED; + firstCluster_ = 0; + fileSize_ = 32 * vol->rootDirEntryCount(); + } else if (vol->fatType() == 32) { + type_ = FAT_FILE_TYPE_ROOT32; + firstCluster_ = vol->rootDirStart(); + if (!vol->chainSize(firstCluster_, &fileSize_)) goto fail; + } else { + // volume is not initialized, invalid, or FAT12 without support + return false; + } + vol_ = vol; + // read only + flags_ = O_READ; + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + + // root has no directory entry + dirBlock_ = 0; + dirIndex_ = 0; + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Return the next available byte without consuming it. + * + * \return The byte if no error and not at eof else -1; + */ +int SdBaseFile::peek() { + fpos_t pos; + getpos(&pos); + int c = read(); + if (c >= 0) setpos(&pos); + return c; +} +//------------------------------------------------------------------------------ +/** %Print the name field of a directory entry in 8.3 format to Serial. + * + * \param[in] dir The directory structure containing the name. + * \param[in] width Blank fill name if length is less than \a width. + * \param[in] printSlash Print '/' after directory names if true. + */ +void SdBaseFile::printDirName(const dir_t& dir, + uint8_t width, bool printSlash) { + printDirName(&Serial, dir, width, printSlash); +} +//------------------------------------------------------------------------------ +/** %Print the name field of a directory entry in 8.3 format. + * \param[in] pr Print stream for output. + * \param[in] dir The directory structure containing the name. + * \param[in] width Blank fill name if length is less than \a width. + * \param[in] printSlash Print '/' after directory names if true. + */ +void SdBaseFile::printDirName(Print* pr, const dir_t& dir, + uint8_t width, bool printSlash) { + uint8_t w = 0; + for (uint8_t i = 0; i < 11; i++) { + if (dir.name[i] == ' ')continue; + if (i == 8) { + pr->write('.'); + w++; + } + pr->write(dir.name[i]); + w++; + } + if (DIR_IS_SUBDIR(&dir) && printSlash) { + pr->write('/'); + w++; + } + while (w < width) { + pr->write(' '); + w++; + } +} +//------------------------------------------------------------------------------ +// print uint8_t with width 2 +static void print2u(Print* pr, uint8_t v) { + if (v < 10) pr->write('0'); + pr->print(v, DEC); +} +//------------------------------------------------------------------------------ +/** %Print a directory date field to Serial. + * + * Format is yyyy-mm-dd. + * + * \param[in] fatDate The date field from a directory entry. + */ +void SdBaseFile::printFatDate(uint16_t fatDate) { + printFatDate(&Serial, fatDate); +} +//------------------------------------------------------------------------------ +/** %Print a directory date field. + * + * Format is yyyy-mm-dd. + * + * \param[in] pr Print stream for output. + * \param[in] fatDate The date field from a directory entry. + */ +void SdBaseFile::printFatDate(Print* pr, uint16_t fatDate) { + pr->print(FAT_YEAR(fatDate)); + pr->write('-'); + print2u(pr, FAT_MONTH(fatDate)); + pr->write('-'); + print2u(pr, FAT_DAY(fatDate)); +} +//------------------------------------------------------------------------------ +/** %Print a directory time field to Serial. + * + * Format is hh:mm:ss. + * + * \param[in] fatTime The time field from a directory entry. + */ +void SdBaseFile::printFatTime(uint16_t fatTime) { + printFatTime(&Serial, fatTime); +} +//------------------------------------------------------------------------------ +/** %Print a directory time field. + * + * Format is hh:mm:ss. + * + * \param[in] pr Print stream for output. + * \param[in] fatTime The time field from a directory entry. + */ +void SdBaseFile::printFatTime(Print* pr, uint16_t fatTime) { + print2u(pr, FAT_HOUR(fatTime)); + pr->write(':'); + print2u(pr, FAT_MINUTE(fatTime)); + pr->write(':'); + print2u(pr, FAT_SECOND(fatTime)); +} +//------------------------------------------------------------------------------ +/** Print a file's name to Serial + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::printName() { + char name[13]; + if (!getFilename(name)) return false; + Serial.print(name); + return true; +} +//------------------------------------------------------------------------------ +/** Read the next byte from a file. + * + * \return For success read returns the next byte in the file as an int. + * If an error occurs or end of file is reached -1 is returned. + */ +int16_t SdBaseFile::read() { + uint8_t b; + return read(&b, 1) == 1 ? b : -1; +} +//------------------------------------------------------------------------------ +/** Read data from a file starting at the current position. + * + * \param[out] buf Pointer to the location that will receive the data. + * + * \param[in] nbyte Maximum number of bytes to read. + * + * \return For success read() returns the number of bytes read. + * A value less than \a nbyte, including zero, will be returned + * if end of file is reached. + * If an error occurs, read() returns -1. Possible errors include + * read() called before a file has been opened, corrupt file system + * or an I/O error occurred. + */ +int16_t SdBaseFile::read(void* buf, uint16_t nbyte) { + uint8_t* dst = reinterpret_cast(buf); + uint16_t offset; + uint16_t toRead; + uint32_t block; // raw device block number + + // error if not open or write only + if (!isOpen() || !(flags_ & O_READ)) goto fail; + + // max bytes left in file + if (nbyte >= (fileSize_ - curPosition_)) { + nbyte = fileSize_ - curPosition_; + } + // amount left to read + toRead = nbyte; + while (toRead > 0) { + offset = curPosition_ & 0X1FF; // offset in block + if (type_ == FAT_FILE_TYPE_ROOT_FIXED) { + block = vol_->rootDirStart() + (curPosition_ >> 9); + } else { + uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); + if (offset == 0 && blockOfCluster == 0) { + // start of new cluster + if (curPosition_ == 0) { + // use first cluster in file + curCluster_ = firstCluster_; + } else { + // get next cluster from FAT + if (!vol_->fatGet(curCluster_, &curCluster_)) goto fail; + } + } + block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + } + uint16_t n = toRead; + + // amount to be read from current block + if (n > (512 - offset)) n = 512 - offset; + + // no buffering needed if n == 512 + if (n == 512 && block != vol_->cacheBlockNumber()) { + if (!vol_->readBlock(block, dst)) goto fail; + } else { + // read block to cache and copy data to caller + if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto fail; + uint8_t* src = vol_->cache()->data + offset; + memcpy(dst, src, n); + } + dst += n; + curPosition_ += n; + toRead -= n; + } + return nbyte; + + fail: + return -1; +} +//------------------------------------------------------------------------------ +/** Read the next directory entry from a directory file. + * + * \param[out] dir The dir_t struct that will receive the data. + * + * \return For success readDir() returns the number of bytes read. + * A value of zero will be returned if end of file is reached. + * If an error occurs, readDir() returns -1. Possible errors include + * readDir() called before a directory has been opened, this is not + * a directory file or an I/O error occurred. + */ +int8_t SdBaseFile::readDir(dir_t* dir) { + int16_t n; + // if not a directory file or miss-positioned return an error + if (!isDir() || (0X1F & curPosition_)) return -1; + + while (1) { + n = read(dir, sizeof(dir_t)); + if (n != sizeof(dir_t)) return n == 0 ? 0 : -1; + // last entry if DIR_NAME_FREE + if (dir->name[0] == DIR_NAME_FREE) return 0; + // skip empty entries and entry for . and .. + if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; + // return if normal file or subdirectory + if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; + } +} +//------------------------------------------------------------------------------ +// Read next directory entry into the cache +// Assumes file is correctly positioned +dir_t* SdBaseFile::readDirCache() { + uint8_t i; + // error if not directory + if (!isDir()) goto fail; + + // index of entry in cache + i = (curPosition_ >> 5) & 0XF; + + // use read to locate and cache block + if (read() < 0) goto fail; + + // advance to next entry + curPosition_ += 31; + + // return pointer to entry + return vol_->cache()->dir + i; + + fail: + return 0; +} +//------------------------------------------------------------------------------ +/** Remove a file. + * + * The directory entry and all data for the file are deleted. + * + * \note This function should not be used to delete the 8.3 version of a + * file that has a long name. For example if a file has the long name + * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file read-only, is a directory, + * or an I/O error occurred. + */ +bool SdBaseFile::remove() { + dir_t* d; + // free any clusters - will fail if read-only or directory + if (!truncate(0)) goto fail; + + // cache directory entry + d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) goto fail; + + // mark entry deleted + d->name[0] = DIR_NAME_DELETED; + + // set this file closed + type_ = FAT_FILE_TYPE_CLOSED; + + // write entry to SD + return vol_->cacheFlush(); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Remove a file. + * + * The directory entry and all data for the file are deleted. + * + * \param[in] dirFile The directory that contains the file. + * \param[in] path Path for the file to be removed. + * + * \note This function should not be used to delete the 8.3 version of a + * file that has a long name. For example if a file has the long name + * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file is a directory, is read only, + * \a dirFile is not a directory, \a path is not found + * or an I/O error occurred. + */ +bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) { + SdBaseFile file; + if (!file.open(dirFile, path, O_WRITE)) goto fail; + return file.remove(); + + fail: + // can't set iostate - static function + return false; +} +//------------------------------------------------------------------------------ +/** Rename a file or subdirectory. + * + * \param[in] dirFile Directory for the new path. + * \param[in] newPath New path name for the file/directory. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include \a dirFile is not open or is not a directory + * file, newPath is invalid or already exists, or an I/O error occurs. + */ +bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) { + dir_t entry; + uint32_t dirCluster = 0; + SdBaseFile file; + dir_t* d; + + // must be an open file or subdirectory + if (!(isFile() || isSubDir())) goto fail; + + // can't move file + if (vol_ != dirFile->vol_) goto fail; + + // sync() and cache directory entry + sync(); + d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) goto fail; + + // save directory entry + memcpy(&entry, d, sizeof(entry)); + + // mark entry deleted + d->name[0] = DIR_NAME_DELETED; + + // make directory entry for new path + if (isFile()) { + if (!file.open(dirFile, newPath, O_CREAT | O_EXCL | O_WRITE)) { + goto restore; + } + } else { + // don't create missing path prefix components + if (!file.mkdir(dirFile, newPath, false)) { + goto restore; + } + // save cluster containing new dot dot + dirCluster = file.firstCluster_; + } + // change to new directory entry + dirBlock_ = file.dirBlock_; + dirIndex_ = file.dirIndex_; + + // mark closed to avoid possible destructor close call + file.type_ = FAT_FILE_TYPE_CLOSED; + + // cache new directory entry + d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) goto fail; + + // copy all but name field to new directory entry + memcpy(&d->attributes, &entry.attributes, sizeof(entry) - sizeof(d->name)); + + // update dot dot if directory + if (dirCluster) { + // get new dot dot + uint32_t block = vol_->clusterStartBlock(dirCluster); + if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto fail; + memcpy(&entry, &vol_->cache()->dir[1], sizeof(entry)); + + // free unused cluster + if (!vol_->freeChain(dirCluster)) goto fail; + + // store new dot dot + block = vol_->clusterStartBlock(firstCluster_); + if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail; + memcpy(&vol_->cache()->dir[1], &entry, sizeof(entry)); + } + return vol_->cacheFlush(); + + restore: + d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) goto fail; + // restore entry + d->name[0] = entry.name[0]; + vol_->cacheFlush(); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Remove a directory file. + * + * The directory file will be removed only if it is empty and is not the + * root directory. rmdir() follows DOS and Windows and ignores the + * read-only attribute for the directory. + * + * \note This function should not be used to delete the 8.3 version of a + * directory that has a long name. For example if a directory has the + * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file is not a directory, is the root + * directory, is not empty, or an I/O error occurred. + */ +bool SdBaseFile::rmdir() { + // must be open subdirectory + if (!isSubDir()) goto fail; + + rewind(); + + // make sure directory is empty + while (curPosition_ < fileSize_) { + dir_t* p = readDirCache(); + if (!p) goto fail; + // done if past last used entry + if (p->name[0] == DIR_NAME_FREE) break; + // skip empty slot, '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; + // error not empty + if (DIR_IS_FILE_OR_SUBDIR(p)) goto fail; + } + // convert empty directory to normal file for remove + type_ = FAT_FILE_TYPE_NORMAL; + flags_ |= O_WRITE; + return remove(); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Recursively delete a directory and all contained files. + * + * This is like the Unix/Linux 'rm -rf *' if called with the root directory + * hence the name. + * + * Warning - This will remove all contents of the directory including + * subdirectories. The directory will then be removed if it is not root. + * The read-only attribute for files will be ignored. + * + * \note This function should not be used to delete the 8.3 version of + * a directory that has a long name. See remove() and rmdir(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::rmRfStar() { + uint16_t index; + SdBaseFile f; + rewind(); + while (curPosition_ < fileSize_) { + // remember position + index = curPosition_/32; + + dir_t* p = readDirCache(); + if (!p) goto fail; + + // done if past last entry + if (p->name[0] == DIR_NAME_FREE) break; + + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; + + // skip if part of long file name or volume label in root + if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; + + if (!f.open(this, index, O_READ)) goto fail; + if (f.isSubDir()) { + // recursively delete + if (!f.rmRfStar()) goto fail; + } else { + // ignore read-only + f.flags_ |= O_WRITE; + if (!f.remove()) goto fail; + } + // position to next entry if required + if (curPosition_ != (32*(index + 1))) { + if (!seekSet(32*(index + 1))) goto fail; + } + } + // don't try to delete root + if (!isRoot()) { + if (!rmdir()) goto fail; + } + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Create a file object and open it in the current working directory. + * + * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t). + */ +SdBaseFile::SdBaseFile(const char* path, uint8_t oflag) { + type_ = FAT_FILE_TYPE_CLOSED; + writeError = false; + open(path, oflag); +} +//------------------------------------------------------------------------------ +/** Sets a file's position. + * + * \param[in] pos The new position in bytes from the beginning of the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::seekSet(uint32_t pos) { + uint32_t nCur; + uint32_t nNew; + // error if file not open or seek past end of file + if (!isOpen() || pos > fileSize_) goto fail; + + if (type_ == FAT_FILE_TYPE_ROOT_FIXED) { + curPosition_ = pos; + goto done; + } + if (pos == 0) { + // set position to start of file + curCluster_ = 0; + curPosition_ = 0; + goto done; + } + // calculate cluster index for cur and new position + nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); + nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); + + if (nNew < nCur || curPosition_ == 0) { + // must follow chain from first cluster + curCluster_ = firstCluster_; + } else { + // advance from curPosition + nNew -= nCur; + } + while (nNew--) { + if (!vol_->fatGet(curCluster_, &curCluster_)) goto fail; + } + curPosition_ = pos; + + done: + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +void SdBaseFile::setpos(fpos_t* pos) { + curPosition_ = pos->position; + curCluster_ = pos->cluster; +} +//------------------------------------------------------------------------------ +/** The sync() call causes all modified data and directory fields + * to be written to the storage device. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include a call to sync() before a file has been + * opened or an I/O error. + */ +bool SdBaseFile::sync() { + // only allow open files and directories + if (!isOpen()) goto fail; + + if (flags_ & F_FILE_DIR_DIRTY) { + dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + // check for deleted by another open file object + if (!d || d->name[0] == DIR_NAME_DELETED) goto fail; + + // do not set filesize for dir files + if (!isDir()) d->fileSize = fileSize_; + + // update first cluster fields + d->firstClusterLow = firstCluster_ & 0XFFFF; + d->firstClusterHigh = firstCluster_ >> 16; + + // set modify time if user supplied a callback date/time function + if (dateTime_) { + dateTime_(&d->lastWriteDate, &d->lastWriteTime); + d->lastAccessDate = d->lastWriteDate; + } + // clear directory dirty + flags_ &= ~F_FILE_DIR_DIRTY; + } + return vol_->cacheFlush(); + + fail: + writeError = true; + return false; +} +//------------------------------------------------------------------------------ +/** Copy a file's timestamps + * + * \param[in] file File to copy timestamps from. + * + * \note + * Modify and access timestamps may be overwritten if a date time callback + * function has been set by dateTimeCallback(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::timestamp(SdBaseFile* file) { + dir_t* d; + dir_t dir; + + // get timestamps + if (!file->dirEntry(&dir)) goto fail; + + // update directory fields + if (!sync()) goto fail; + + d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) goto fail; + + // copy timestamps + d->lastAccessDate = dir.lastAccessDate; + d->creationDate = dir.creationDate; + d->creationTime = dir.creationTime; + d->creationTimeTenths = dir.creationTimeTenths; + d->lastWriteDate = dir.lastWriteDate; + d->lastWriteTime = dir.lastWriteTime; + + // write back entry + return vol_->cacheFlush(); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Set a file's timestamps in its directory entry. + * + * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive + * OR of flags from the following list + * + * T_ACCESS - Set the file's last access date. + * + * T_CREATE - Set the file's creation date and time. + * + * T_WRITE - Set the file's last write/modification date and time. + * + * \param[in] year Valid range 1980 - 2107 inclusive. + * + * \param[in] month Valid range 1 - 12 inclusive. + * + * \param[in] day Valid range 1 - 31 inclusive. + * + * \param[in] hour Valid range 0 - 23 inclusive. + * + * \param[in] minute Valid range 0 - 59 inclusive. + * + * \param[in] second Valid range 0 - 59 inclusive + * + * \note It is possible to set an invalid date since there is no check for + * the number of days in a month. + * + * \note + * Modify and access timestamps may be overwritten if a date time callback + * function has been set by dateTimeCallback(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, + uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { + uint16_t dirDate; + uint16_t dirTime; + dir_t* d; + + if (!isOpen() + || year < 1980 + || year > 2107 + || month < 1 + || month > 12 + || day < 1 + || day > 31 + || hour > 23 + || minute > 59 + || second > 59) { + goto fail; + } + // update directory entry + if (!sync()) goto fail; + + d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) goto fail; + + dirDate = FAT_DATE(year, month, day); + dirTime = FAT_TIME(hour, minute, second); + if (flags & T_ACCESS) { + d->lastAccessDate = dirDate; + } + if (flags & T_CREATE) { + d->creationDate = dirDate; + d->creationTime = dirTime; + // seems to be units of 1/100 second not 1/10 as Microsoft states + d->creationTimeTenths = second & 1 ? 100 : 0; + } + if (flags & T_WRITE) { + d->lastWriteDate = dirDate; + d->lastWriteTime = dirTime; + } + return vol_->cacheFlush(); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Truncate a file to a specified length. The current file position + * will be maintained if it is less than or equal to \a length otherwise + * it will be set to end of file. + * + * \param[in] length The desired length for the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include file is read only, file is a directory, + * \a length is greater than the current file size or an I/O error occurs. + */ +bool SdBaseFile::truncate(uint32_t length) { + uint32_t newPos; + // error if not a normal file or read-only + if (!isFile() || !(flags_ & O_WRITE)) goto fail; + + // error if length is greater than current size + if (length > fileSize_) goto fail; + + // fileSize and length are zero - nothing to do + if (fileSize_ == 0) return true; + + // remember position for seek after truncation + newPos = curPosition_ > length ? length : curPosition_; + + // position to last cluster in truncated file + if (!seekSet(length)) goto fail; + + if (length == 0) { + // free all clusters + if (!vol_->freeChain(firstCluster_)) goto fail; + firstCluster_ = 0; + } else { + uint32_t toFree; + if (!vol_->fatGet(curCluster_, &toFree)) goto fail; + + if (!vol_->isEOC(toFree)) { + // free extra clusters + if (!vol_->freeChain(toFree)) goto fail; + + // current cluster is end of chain + if (!vol_->fatPutEOC(curCluster_)) goto fail; + } + } + fileSize_ = length; + + // need to update directory entry + flags_ |= F_FILE_DIR_DIRTY; + + if (!sync()) goto fail; + + // set file to correct position + return seekSet(newPos); + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Write data to an open file. + * + * \note Data is moved to the cache but may not be written to the + * storage device until sync() is called. + * + * \param[in] buf Pointer to the location of the data to be written. + * + * \param[in] nbyte Number of bytes to write. + * + * \return For success write() returns the number of bytes written, always + * \a nbyte. If an error occurs, write() returns -1. Possible errors + * include write() is called before a file has been opened, write is called + * for a read-only file, device is full, a corrupt file system or an I/O error. + * + */ +int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) { + // convert void* to uint8_t* - must be before goto statements + const uint8_t* src = reinterpret_cast(buf); + + // number of bytes left to write - must be before goto statements + uint16_t nToWrite = nbyte; + + // error if not a normal file or is read-only + if (!isFile() || !(flags_ & O_WRITE)) goto fail; + + // seek to end of file if append flag + if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { + if (!seekEnd()) goto fail; + } + + while (nToWrite > 0) { + uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); + uint16_t blockOffset = curPosition_ & 0X1FF; + if (blockOfCluster == 0 && blockOffset == 0) { + // start of new cluster + if (curCluster_ == 0) { + if (firstCluster_ == 0) { + // allocate first cluster of file + if (!addCluster()) goto fail; + } else { + curCluster_ = firstCluster_; + } + } else { + uint32_t next; + if (!vol_->fatGet(curCluster_, &next)) goto fail; + if (vol_->isEOC(next)) { + // add cluster if at end of chain + if (!addCluster()) goto fail; + } else { + curCluster_ = next; + } + } + } + // max space in block + uint16_t n = 512 - blockOffset; + + // lesser of space and amount to write + if (n > nToWrite) n = nToWrite; + + // block for data write + uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + if (n == 512) { + // full block - don't need to use cache + if (vol_->cacheBlockNumber() == block) { + // invalidate cache if block is in cache + vol_->cacheSetBlockNumber(0XFFFFFFFF, false); + } + if (!vol_->writeBlock(block, src)) goto fail; + } else { + if (blockOffset == 0 && curPosition_ >= fileSize_) { + // start of new block don't need to read into cache + if (!vol_->cacheFlush()) goto fail; + // set cache dirty and SD address of block + vol_->cacheSetBlockNumber(block, true); + } else { + // rewrite part of block + if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail; + } + uint8_t* dst = vol_->cache()->data + blockOffset; + memcpy(dst, src, n); + } + curPosition_ += n; + src += n; + nToWrite -= n; + } + if (curPosition_ > fileSize_) { + // update fileSize and insure sync will update dir entry + fileSize_ = curPosition_; + flags_ |= F_FILE_DIR_DIRTY; + } else if (dateTime_ && nbyte) { + // insure sync will update modified date and time + flags_ |= F_FILE_DIR_DIRTY; + } + + if (flags_ & O_SYNC) { + if (!sync()) goto fail; + } + return nbyte; + + fail: + // return for write error + writeError = true; + return -1; +} +//------------------------------------------------------------------------------ +// suppress cpplint warnings with NOLINT comment +#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN) +void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT +#endif // ALLOW_DEPRECATED_FUNCTIONS diff --git a/Marlin/SdBaseFile.h b/Marlin/SdBaseFile.h new file mode 100644 index 0000000000..9363401c96 --- /dev/null +++ b/Marlin/SdBaseFile.h @@ -0,0 +1,489 @@ +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdBaseFile_h +#define SdBaseFile_h +/** + * \file + * \brief SdBaseFile class + */ +#include +#if ARDUINO < 100 +#include +#else // ARDUINO +#include +#endif // ARDUINO +#include "SdFatConfig.h" +#include "SdVolume.h" +//------------------------------------------------------------------------------ +/** + * \struct fpos_t + * \brief internal type for istream + * do not use in user apps + */ +struct fpos_t { + /** stream position */ + uint32_t position; + /** cluster for position */ + uint32_t cluster; + fpos_t() : position(0), cluster(0) {} +}; + +// use the gnu style oflag in open() +/** open() oflag for reading */ +uint8_t const O_READ = 0X01; +/** open() oflag - same as O_IN */ +uint8_t const O_RDONLY = O_READ; +/** open() oflag for write */ +uint8_t const O_WRITE = 0X02; +/** open() oflag - same as O_WRITE */ +uint8_t const O_WRONLY = O_WRITE; +/** open() oflag for reading and writing */ +uint8_t const O_RDWR = (O_READ | O_WRITE); +/** open() oflag mask for access modes */ +uint8_t const O_ACCMODE = (O_READ | O_WRITE); +/** The file offset shall be set to the end of the file prior to each write. */ +uint8_t const O_APPEND = 0X04; +/** synchronous writes - call sync() after each write */ +uint8_t const O_SYNC = 0X08; +/** truncate the file to zero length */ +uint8_t const O_TRUNC = 0X10; +/** set the initial position at the end of the file */ +uint8_t const O_AT_END = 0X20; +/** create the file if nonexistent */ +uint8_t const O_CREAT = 0X40; +/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ +uint8_t const O_EXCL = 0X80; + +// SdBaseFile class static and const definitions +// flags for ls() +/** ls() flag to print modify date */ +uint8_t const LS_DATE = 1; +/** ls() flag to print file size */ +uint8_t const LS_SIZE = 2; +/** ls() flag for recursive list of subdirectories */ +uint8_t const LS_R = 4; + + +// flags for timestamp +/** set the file's last access date */ +uint8_t const T_ACCESS = 1; +/** set the file's creation date and time */ +uint8_t const T_CREATE = 2; +/** Set the file's write date and time */ +uint8_t const T_WRITE = 4; +// values for type_ +/** This file has not been opened. */ +uint8_t const FAT_FILE_TYPE_CLOSED = 0; +/** A normal file */ +uint8_t const FAT_FILE_TYPE_NORMAL = 1; +/** A FAT12 or FAT16 root directory */ +uint8_t const FAT_FILE_TYPE_ROOT_FIXED = 2; +/** A FAT32 root directory */ +uint8_t const FAT_FILE_TYPE_ROOT32 = 3; +/** A subdirectory file*/ +uint8_t const FAT_FILE_TYPE_SUBDIR = 4; +/** Test value for directory type */ +uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED; + +/** date field for FAT directory entry + * \param[in] year [1980,2107] + * \param[in] month [1,12] + * \param[in] day [1,31] + * + * \return Packed date for dir_t entry. + */ +static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { + return (year - 1980) << 9 | month << 5 | day; +} +/** year part of FAT directory date field + * \param[in] fatDate Date in packed dir format. + * + * \return Extracted year [1980,2107] + */ +static inline uint16_t FAT_YEAR(uint16_t fatDate) { + return 1980 + (fatDate >> 9); +} +/** month part of FAT directory date field + * \param[in] fatDate Date in packed dir format. + * + * \return Extracted month [1,12] + */ +static inline uint8_t FAT_MONTH(uint16_t fatDate) { + return (fatDate >> 5) & 0XF; +} +/** day part of FAT directory date field + * \param[in] fatDate Date in packed dir format. + * + * \return Extracted day [1,31] + */ +static inline uint8_t FAT_DAY(uint16_t fatDate) { + return fatDate & 0X1F; +} +/** time field for FAT directory entry + * \param[in] hour [0,23] + * \param[in] minute [0,59] + * \param[in] second [0,59] + * + * \return Packed time for dir_t entry. + */ +static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { + return hour << 11 | minute << 5 | second >> 1; +} +/** hour part of FAT directory time field + * \param[in] fatTime Time in packed dir format. + * + * \return Extracted hour [0,23] + */ +static inline uint8_t FAT_HOUR(uint16_t fatTime) { + return fatTime >> 11; +} +/** minute part of FAT directory time field + * \param[in] fatTime Time in packed dir format. + * + * \return Extracted minute [0,59] + */ +static inline uint8_t FAT_MINUTE(uint16_t fatTime) { + return(fatTime >> 5) & 0X3F; +} +/** second part of FAT directory time field + * Note second/2 is stored in packed time. + * + * \param[in] fatTime Time in packed dir format. + * + * \return Extracted second [0,58] + */ +static inline uint8_t FAT_SECOND(uint16_t fatTime) { + return 2*(fatTime & 0X1F); +} +/** Default date for file timestamps is 1 Jan 2000 */ +uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; +/** Default time for file timestamp is 1 am */ +uint16_t const FAT_DEFAULT_TIME = (1 << 11); +//------------------------------------------------------------------------------ +/** + * \class SdBaseFile + * \brief Base class for SdFile with Print and C++ streams. + */ +class SdBaseFile { + public: + /** Create an instance. */ + SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {} + SdBaseFile(const char* path, uint8_t oflag); + ~SdBaseFile() {if(isOpen()) close();} + /** + * writeError is set to true if an error occurs during a write(). + * Set writeError to false before calling print() and/or write() and check + * for true after calls to print() and/or write(). + */ + bool writeError; + //---------------------------------------------------------------------------- + // helpers for stream classes + /** get position for streams + * \param[out] pos struct to receive position + */ + void getpos(fpos_t* pos); + /** set position for streams + * \param[out] pos struct with value for new position + */ + void setpos(fpos_t* pos); + //---------------------------------------------------------------------------- + bool close(); + bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); + bool createContiguous(SdBaseFile* dirFile, + const char* path, uint32_t size); + /** \return The current cluster number for a file or directory. */ + uint32_t curCluster() const {return curCluster_;} + /** \return The current position for a file or directory. */ + uint32_t curPosition() const {return curPosition_;} + /** \return Current working directory */ + static SdBaseFile* cwd() {return cwd_;} + /** Set the date/time callback function + * + * \param[in] dateTime The user's call back function. The callback + * function is of the form: + * + * \code + * void dateTime(uint16_t* date, uint16_t* time) { + * uint16_t year; + * uint8_t month, day, hour, minute, second; + * + * // User gets date and time from GPS or real-time clock here + * + * // return date using FAT_DATE macro to format fields + * *date = FAT_DATE(year, month, day); + * + * // return time using FAT_TIME macro to format fields + * *time = FAT_TIME(hour, minute, second); + * } + * \endcode + * + * Sets the function that is called when a file is created or when + * a file's directory entry is modified by sync(). All timestamps, + * access, creation, and modify, are set when a file is created. + * sync() maintains the last access date and last modify date/time. + * + * See the timestamp() function. + */ + static void dateTimeCallback( + void (*dateTime)(uint16_t* date, uint16_t* time)) { + dateTime_ = dateTime; + } + /** Cancel the date/time callback function. */ + static void dateTimeCallbackCancel() {dateTime_ = 0;} + bool dirEntry(dir_t* dir); + static void dirName(const dir_t& dir, char* name); + bool exists(const char* name); + int16_t fgets(char* str, int16_t num, char* delim = 0); + /** \return The total number of bytes in a file or directory. */ + uint32_t fileSize() const {return fileSize_;} + /** \return The first cluster number for a file or directory. */ + uint32_t firstCluster() const {return firstCluster_;} + bool getFilename(char* name); + /** \return True if this is a directory else false. */ + bool isDir() const {return type_ >= FAT_FILE_TYPE_MIN_DIR;} + /** \return True if this is a normal file else false. */ + bool isFile() const {return type_ == FAT_FILE_TYPE_NORMAL;} + /** \return True if this is an open file/directory else false. */ + bool isOpen() const {return type_ != FAT_FILE_TYPE_CLOSED;} + /** \return True if this is a subdirectory else false. */ + bool isSubDir() const {return type_ == FAT_FILE_TYPE_SUBDIR;} + /** \return True if this is the root directory. */ + bool isRoot() const { + return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32; + } + void ls(Print* pr, uint8_t flags = 0, uint8_t indent = 0); + void ls(uint8_t flags = 0); + bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true); + // alias for backward compactability + bool makeDir(SdBaseFile* dir, const char* path) { + return mkdir(dir, path, false); + } + bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag); + bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag); + bool open(const char* path, uint8_t oflag = O_READ); + bool openNext(SdBaseFile* dirFile, uint8_t oflag); + bool openRoot(SdVolume* vol); + int peek(); + static void printFatDate(uint16_t fatDate); + static void printFatDate(Print* pr, uint16_t fatDate); + static void printFatTime(uint16_t fatTime); + static void printFatTime(Print* pr, uint16_t fatTime); + bool printName(); + int16_t read(); + int16_t read(void* buf, uint16_t nbyte); + int8_t readDir(dir_t* dir); + static bool remove(SdBaseFile* dirFile, const char* path); + bool remove(); + /** Set the file's current position to zero. */ + void rewind() {seekSet(0);} + bool rename(SdBaseFile* dirFile, const char* newPath); + bool rmdir(); + // for backward compatibility + bool rmDir() {return rmdir();} + bool rmRfStar(); + /** Set the files position to current position + \a pos. See seekSet(). + * \param[in] offset The new position in bytes from the current position. + * \return true for success or false for failure. + */ + bool seekCur(int32_t offset) { + return seekSet(curPosition_ + offset); + } + /** Set the files position to end-of-file + \a offset. See seekSet(). + * \param[in] offset The new position in bytes from end-of-file. + * \return true for success or false for failure. + */ + bool seekEnd(int32_t offset = 0) {return seekSet(fileSize_ + offset);} + bool seekSet(uint32_t pos); + bool sync(); + bool timestamp(SdBaseFile* file); + bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, + uint8_t hour, uint8_t minute, uint8_t second); + /** Type of file. You should use isFile() or isDir() instead of type() + * if possible. + * + * \return The file or directory type. + */ + uint8_t type() const {return type_;} + bool truncate(uint32_t size); + /** \return SdVolume that contains this file. */ + SdVolume* volume() const {return vol_;} + int16_t write(const void* buf, uint16_t nbyte); +//------------------------------------------------------------------------------ + private: + // allow SdFat to set cwd_ + friend class SdFat; + // global pointer to cwd dir + static SdBaseFile* cwd_; + // data time callback function + static void (*dateTime_)(uint16_t* date, uint16_t* time); + // bits defined in flags_ + // should be 0X0F + static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); + // sync of directory entry required + static uint8_t const F_FILE_DIR_DIRTY = 0X80; + + // private data + uint8_t flags_; // See above for definition of flags_ bits + uint8_t fstate_; // error and eof indicator + uint8_t type_; // type of file see above for values + uint32_t curCluster_; // cluster for current file position + uint32_t curPosition_; // current file position in bytes from beginning + uint32_t dirBlock_; // block for this files directory entry + uint8_t dirIndex_; // index of directory entry in dirBlock + uint32_t fileSize_; // file size in bytes + uint32_t firstCluster_; // first cluster of file + SdVolume* vol_; // volume where file is located + + /** experimental don't use */ + bool openParent(SdBaseFile* dir); + // private functions + bool addCluster(); + bool addDirCluster(); + dir_t* cacheDirEntry(uint8_t action); + int8_t lsPrintNext(Print *pr, uint8_t flags, uint8_t indent); + static bool make83Name(const char* str, uint8_t* name, const char** ptr); + bool mkdir(SdBaseFile* parent, const uint8_t dname[11]); + bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag); + bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags); + dir_t* readDirCache(); +//------------------------------------------------------------------------------ +// to be deleted + static void printDirName(const dir_t& dir, + uint8_t width, bool printSlash); + static void printDirName(Print* pr, const dir_t& dir, + uint8_t width, bool printSlash); +//------------------------------------------------------------------------------ +// Deprecated functions - suppress cpplint warnings with NOLINT comment +#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN) + public: + /** \deprecated Use: + * bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); + * \param[out] bgnBlock the first block address for the file. + * \param[out] endBlock the last block address for the file. + * \return true for success or false for failure. + */ + bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT + return contiguousRange(&bgnBlock, &endBlock); + } + /** \deprecated Use: + * bool createContiguous(SdBaseFile* dirFile, + * const char* path, uint32_t size) + * \param[in] dirFile The directory where the file will be created. + * \param[in] path A path with a valid DOS 8.3 file name. + * \param[in] size The desired file size. + * \return true for success or false for failure. + */ + bool createContiguous(SdBaseFile& dirFile, // NOLINT + const char* path, uint32_t size) { + return createContiguous(&dirFile, path, size); + } + /** \deprecated Use: + * static void dateTimeCallback( + * void (*dateTime)(uint16_t* date, uint16_t* time)); + * \param[in] dateTime The user's call back function. + */ + static void dateTimeCallback( + void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT + oldDateTime_ = dateTime; + dateTime_ = dateTime ? oldToNew : 0; + } + /** \deprecated Use: bool dirEntry(dir_t* dir); + * \param[out] dir Location for return of the file's directory entry. + * \return true for success or false for failure. + */ + bool dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT + /** \deprecated Use: + * bool mkdir(SdBaseFile* dir, const char* path); + * \param[in] dir An open SdFat instance for the directory that will contain + * the new directory. + * \param[in] path A path with a valid 8.3 DOS name for the new directory. + * \return true for success or false for failure. + */ + bool mkdir(SdBaseFile& dir, const char* path) { // NOLINT + return mkdir(&dir, path); + } + /** \deprecated Use: + * bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag); + * \param[in] dirFile An open SdFat instance for the directory containing the + * file to be opened. + * \param[in] path A path with a valid 8.3 DOS name for the file. + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. + * \return true for success or false for failure. + */ + bool open(SdBaseFile& dirFile, // NOLINT + const char* path, uint8_t oflag) { + return open(&dirFile, path, oflag); + } + /** \deprecated Do not use in new apps + * \param[in] dirFile An open SdFat instance for the directory containing the + * file to be opened. + * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. + * \return true for success or false for failure. + */ + bool open(SdBaseFile& dirFile, const char* path) { // NOLINT + return open(dirFile, path, O_RDWR); + } + /** \deprecated Use: + * bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag); + * \param[in] dirFile An open SdFat instance for the directory. + * \param[in] index The \a index of the directory entry for the file to be + * opened. The value for \a index is (directory file position)/32. + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. + * \return true for success or false for failure. + */ + bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT + return open(&dirFile, index, oflag); + } + /** \deprecated Use: bool openRoot(SdVolume* vol); + * \param[in] vol The FAT volume containing the root directory to be opened. + * \return true for success or false for failure. + */ + bool openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT + /** \deprecated Use: int8_t readDir(dir_t* dir); + * \param[out] dir The dir_t struct that will receive the data. + * \return bytes read for success zero for eof or -1 for failure. + */ + int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT + /** \deprecated Use: + * static uint8_t remove(SdBaseFile* dirFile, const char* path); + * \param[in] dirFile The directory that contains the file. + * \param[in] path The name of the file to be removed. + * \return true for success or false for failure. + */ + static bool remove(SdBaseFile& dirFile, const char* path) { // NOLINT + return remove(&dirFile, path); + } +//------------------------------------------------------------------------------ +// rest are private + private: + static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT + static void oldToNew(uint16_t* date, uint16_t* time) { + uint16_t d; + uint16_t t; + oldDateTime_(d, t); + *date = d; + *time = t; + } +#endif // ALLOW_DEPRECATED_FUNCTIONS +}; + +#endif // SdBaseFile_h diff --git a/Marlin/SdFat.cpp b/Marlin/SdFat.cpp new file mode 100644 index 0000000000..494fd48225 --- /dev/null +++ b/Marlin/SdFat.cpp @@ -0,0 +1,329 @@ +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#include "SdFat.h" +#include "SdFatUtil.h" +//------------------------------------------------------------------------------ +/** Change a volume's working directory to root + * + * Changes the volume's working directory to the SD's root directory. + * Optionally set the current working directory to the volume's + * working directory. + * + * \param[in] set_cwd Set the current working directory to this volume's + * working directory if true. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdFat::chdir(bool set_cwd) { + if (set_cwd) SdBaseFile::cwd_ = &vwd_; + vwd_.close(); + return vwd_.openRoot(&vol_); +} +//------------------------------------------------------------------------------ +/** Change a volume's working directory + * + * Changes the volume working directory to the \a path subdirectory. + * Optionally set the current working directory to the volume's + * working directory. + * + * Example: If the volume's working directory is "/DIR", chdir("SUB") + * will change the volume's working directory from "/DIR" to "/DIR/SUB". + * + * If path is "/", the volume's working directory will be changed to the + * root directory + * + * \param[in] path The name of the subdirectory. + * + * \param[in] set_cwd Set the current working directory to this volume's + * working directory if true. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdFat::chdir(const char *path, bool set_cwd) { + SdBaseFile dir; + if (path[0] == '/' && path[1] == '\0') return chdir(set_cwd); + if (!dir.open(&vwd_, path, O_READ)) goto fail; + if (!dir.isDir()) goto fail; + vwd_ = dir; + if (set_cwd) SdBaseFile::cwd_ = &vwd_; + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** Set the current working directory to a volume's working directory. + * + * This is useful with multiple SD cards. + * + * The current working directory is changed to this volume's working directory. + * + * This is like the Windows/DOS \: command. + */ +void SdFat::chvol() { + SdBaseFile::cwd_ = &vwd_; +} +//------------------------------------------------------------------------------ +/** %Print any SD error code and halt. */ +void SdFat::errorHalt() { + errorPrint(); + while (1); +} +//------------------------------------------------------------------------------ +/** %Print msg, any SD error code, and halt. + * + * \param[in] msg Message to print. + */ +void SdFat::errorHalt(char const* msg) { + errorPrint(msg); + while (1); +} +//------------------------------------------------------------------------------ +/** %Print msg, any SD error code, and halt. + * + * \param[in] msg Message in program space (flash memory) to print. + */ +void SdFat::errorHalt_P(PGM_P msg) { + errorPrint_P(msg); + while (1); +} +//------------------------------------------------------------------------------ +/** %Print any SD error code. */ +void SdFat::errorPrint() { + if (!card_.errorCode()) return; + PgmPrint("SD errorCode: 0X"); + Serial.println(card_.errorCode(), HEX); +} +//------------------------------------------------------------------------------ +/** %Print msg, any SD error code. + * + * \param[in] msg Message to print. + */ +void SdFat::errorPrint(char const* msg) { + PgmPrint("error: "); + Serial.println(msg); + errorPrint(); +} +//------------------------------------------------------------------------------ +/** %Print msg, any SD error code. + * + * \param[in] msg Message in program space (flash memory) to print. + */ +void SdFat::errorPrint_P(PGM_P msg) { + PgmPrint("error: "); + SerialPrintln_P(msg); + errorPrint(); +} +//------------------------------------------------------------------------------ +/** + * Test for the existence of a file. + * + * \param[in] name Name of the file to be tested for. + * + * \return true if the file exists else false. + */ +bool SdFat::exists(const char* name) { + return vwd_.exists(name); +} +//------------------------------------------------------------------------------ +/** + * Initialize an SdFat object. + * + * Initializes the SD card, SD volume, and root directory. + * + * \param[in] sckRateID value for SPI SCK rate. See Sd2Card::init(). + * \param[in] chipSelectPin SD chip select pin. See Sd2Card::init(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdFat::init(uint8_t sckRateID, uint8_t chipSelectPin) { + return card_.init(sckRateID, chipSelectPin) && vol_.init(&card_) && chdir(1); +} +//------------------------------------------------------------------------------ +/** %Print error details and halt after SdFat::init() fails. */ +void SdFat::initErrorHalt() { + initErrorPrint(); + while (1); +} +//------------------------------------------------------------------------------ +/**Print message, error details, and halt after SdFat::init() fails. + * + * \param[in] msg Message to print. + */ +void SdFat::initErrorHalt(char const *msg) { + Serial.println(msg); + initErrorHalt(); +} +//------------------------------------------------------------------------------ +/**Print message, error details, and halt after SdFat::init() fails. + * + * \param[in] msg Message in program space (flash memory) to print. + */ +void SdFat::initErrorHalt_P(PGM_P msg) { + SerialPrintln_P(msg); + initErrorHalt(); +} +//------------------------------------------------------------------------------ +/** Print error details after SdFat::init() fails. */ +void SdFat::initErrorPrint() { + if (card_.errorCode()) { + PgmPrintln("Can't access SD card. Do not reformat."); + if (card_.errorCode() == SD_CARD_ERROR_CMD0) { + PgmPrintln("No card, wrong chip select pin, or SPI problem?"); + } + errorPrint(); + } else if (vol_.fatType() == 0) { + PgmPrintln("Invalid format, reformat SD."); + } else if (!vwd_.isOpen()) { + PgmPrintln("Can't open root directory."); + } else { + PgmPrintln("No error found."); + } +} +//------------------------------------------------------------------------------ +/**Print message and error details and halt after SdFat::init() fails. + * + * \param[in] msg Message to print. + */ +void SdFat::initErrorPrint(char const *msg) { + Serial.println(msg); + initErrorPrint(); +} +//------------------------------------------------------------------------------ +/**Print message and error details after SdFat::init() fails. + * + * \param[in] msg Message in program space (flash memory) to print. + */ +void SdFat::initErrorPrint_P(PGM_P msg) { + SerialPrintln_P(msg); + initErrorHalt(); +} +//------------------------------------------------------------------------------ +/** List the directory contents of the volume working directory to Serial. + * + * \param[in] flags The inclusive OR of + * + * LS_DATE - %Print file modification date + * + * LS_SIZE - %Print file size. + * + * LS_R - Recursive list of subdirectories. + */ +void SdFat::ls(uint8_t flags) { + vwd_.ls(&Serial, flags); +} +//------------------------------------------------------------------------------ +/** List the directory contents of the volume working directory to Serial. + * + * \param[in] pr Print stream for list. + * + * \param[in] flags The inclusive OR of + * + * LS_DATE - %Print file modification date + * + * LS_SIZE - %Print file size. + * + * LS_R - Recursive list of subdirectories. + */ +void SdFat::ls(Print* pr, uint8_t flags) { + vwd_.ls(pr, flags); +} +//------------------------------------------------------------------------------ +/** Make a subdirectory in the volume working directory. + * + * \param[in] path A path with a valid 8.3 DOS name for the subdirectory. + * + * \param[in] pFlag Create missing parent directories if true. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdFat::mkdir(const char* path, bool pFlag) { + SdBaseFile sub; + return sub.mkdir(&vwd_, path, pFlag); +} +//------------------------------------------------------------------------------ +/** Remove a file from the volume working directory. +* +* \param[in] path A path with a valid 8.3 DOS name for the file. +* +* \return The value one, true, is returned for success and +* the value zero, false, is returned for failure. +*/ +bool SdFat::remove(const char* path) { + return SdBaseFile::remove(&vwd_, path); +} +//------------------------------------------------------------------------------ +/** Rename a file or subdirectory. + * + * \param[in] oldPath Path name to the file or subdirectory to be renamed. + * + * \param[in] newPath New path name of the file or subdirectory. + * + * The \a newPath object must not exist before the rename call. + * + * The file to be renamed must not be open. The directory entry may be + * moved and file system corruption could occur if the file is accessed by + * a file object that was opened before the rename() call. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdFat::rename(const char *oldPath, const char *newPath) { + SdBaseFile file; + if (!file.open(oldPath, O_READ)) return false; + return file.rename(&vwd_, newPath); +} +//------------------------------------------------------------------------------ +/** Remove a subdirectory from the volume's working directory. + * + * \param[in] path A path with a valid 8.3 DOS name for the subdirectory. + * + * The subdirectory file will be removed only if it is empty. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool SdFat::rmdir(const char* path) { + SdBaseFile sub; + if (!sub.open(path, O_READ)) return false; + return sub.rmdir(); +} +//------------------------------------------------------------------------------ +/** Truncate a file to a specified length. The current file position + * will be maintained if it is less than or equal to \a length otherwise + * it will be set to end of file. + * + * \param[in] path A path with a valid 8.3 DOS name for the file. + * \param[in] length The desired length for the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include file is read only, file is a directory, + * \a length is greater than the current file size or an I/O error occurs. + */ +bool SdFat::truncate(const char* path, uint32_t length) { + SdBaseFile file; + if (!file.open(path, O_WRITE)) return false; + return file.truncate(length); +} diff --git a/Marlin/SdFat.h b/Marlin/SdFat.h index 048fa711ec..1a184d0843 100644 --- a/Marlin/SdFat.h +++ b/Marlin/SdFat.h @@ -21,527 +21,56 @@ #define SdFat_h /** * \file - * SdFile and SdVolume classes + * \brief SdFat class */ -#include -#include "Sd2Card.h" -#include "FatStructs.h" -#include "Print.h" +#include "SdFile.h" +//#include +//#include +//------------------------------------------------------------------------------ +/** SdFat version YYYYMMDD */ +#define SD_FAT_VERSION 20110902 //------------------------------------------------------------------------------ /** - * Allow use of deprecated functions if non-zero + * \class SdFat + * \brief Integration class for the %SdFat library. */ -#define ALLOW_DEPRECATED_FUNCTIONS 1 -//------------------------------------------------------------------------------ -// forward declaration since SdVolume is used in SdFile -class SdVolume; -//============================================================================== -// SdFile class - -// flags for ls() -/** ls() flag to print modify date */ -uint8_t const LS_DATE = 1; -/** ls() flag to print file size */ -uint8_t const LS_SIZE = 2; -/** ls() flag for recursive list of subdirectories */ -uint8_t const LS_R = 4; - -// use the gnu style oflag in open() -/** open() oflag for reading */ -uint8_t const O_READ = 0X01; -/** open() oflag - same as O_READ */ -uint8_t const O_RDONLY = O_READ; -/** open() oflag for write */ -uint8_t const O_WRITE = 0X02; -/** open() oflag - same as O_WRITE */ -uint8_t const O_WRONLY = O_WRITE; -/** open() oflag for reading and writing */ -uint8_t const O_RDWR = (O_READ | O_WRITE); -/** open() oflag mask for access modes */ -uint8_t const O_ACCMODE = (O_READ | O_WRITE); -/** The file offset shall be set to the end of the file prior to each write. */ -uint8_t const O_APPEND = 0X04; -/** synchronous writes - call sync() after each write */ -uint8_t const O_SYNC = 0X08; -/** create the file if nonexistent */ -uint8_t const O_CREAT = 0X10; -/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ -uint8_t const O_EXCL = 0X20; -/** truncate the file to zero length */ -uint8_t const O_TRUNC = 0X40; - -// flags for timestamp -/** set the file's last access date */ -uint8_t const T_ACCESS = 1; -/** set the file's creation date and time */ -uint8_t const T_CREATE = 2; -/** Set the file's write date and time */ -uint8_t const T_WRITE = 4; -// values for type_ -/** This SdFile has not been opened. */ -uint8_t const FAT_FILE_TYPE_CLOSED = 0; -/** SdFile for a file */ -uint8_t const FAT_FILE_TYPE_NORMAL = 1; -/** SdFile for a FAT16 root directory */ -uint8_t const FAT_FILE_TYPE_ROOT16 = 2; -/** SdFile for a FAT32 root directory */ -uint8_t const FAT_FILE_TYPE_ROOT32 = 3; -/** SdFile for a subdirectory */ -uint8_t const FAT_FILE_TYPE_SUBDIR = 4; -/** Test value for directory type */ -uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; - -/** date field for FAT directory entry */ -static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { - return (year - 1980) << 9 | month << 5 | day; -} -/** year part of FAT directory date field */ -static inline uint16_t FAT_YEAR(uint16_t fatDate) { - return 1980 + (fatDate >> 9); -} -/** month part of FAT directory date field */ -static inline uint8_t FAT_MONTH(uint16_t fatDate) { - return (fatDate >> 5) & 0XF; -} -/** day part of FAT directory date field */ -static inline uint8_t FAT_DAY(uint16_t fatDate) { - return fatDate & 0X1F; -} -/** time field for FAT directory entry */ -static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { - return hour << 11 | minute << 5 | second >> 1; -} -/** hour part of FAT directory time field */ -static inline uint8_t FAT_HOUR(uint16_t fatTime) { - return fatTime >> 11; -} -/** minute part of FAT directory time field */ -static inline uint8_t FAT_MINUTE(uint16_t fatTime) { - return(fatTime >> 5) & 0X3F; -} -/** second part of FAT directory time field */ -static inline uint8_t FAT_SECOND(uint16_t fatTime) { - return 2*(fatTime & 0X1F); -} -/** Default date for file timestamps is 1 Jan 2000 */ -uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; -/** Default time for file timestamp is 1 am */ -uint16_t const FAT_DEFAULT_TIME = (1 << 11); -//------------------------------------------------------------------------------ -/** - * \class SdFile - * \brief Access FAT16 and FAT32 files on SD and SDHC cards. - */ -class SdFile : public Print { +class SdFat { public: - /** Create an instance of SdFile. */ - SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} - /** - * writeError is set to true if an error occurs during a write(). - * Set writeError to false before calling print() and/or write() and check - * for true after calls to print() and/or write(). - */ - bool writeError; - /** - * Cancel unbuffered reads for this file. - * See setUnbufferedRead() - */ - void clearUnbufferedRead(void) { - flags_ &= ~F_FILE_UNBUFFERED_READ; - } - uint8_t close(void); - uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - uint8_t createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size); - /** \return The current cluster number for a file or directory. */ - uint32_t curCluster(void) const {return curCluster_;} - /** \return The current position for a file or directory. */ - uint32_t curPosition(void) const {return curPosition_;} - /** - * Set the date/time callback function - * - * \param[in] dateTime The user's call back function. The callback - * function is of the form: - * - * \code - * void dateTime(uint16_t* date, uint16_t* time) { - * uint16_t year; - * uint8_t month, day, hour, minute, second; - * - * // User gets date and time from GPS or real-time clock here - * - * // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); - * - * // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); - * } - * \endcode - * - * Sets the function that is called when a file is created or when - * a file's directory entry is modified by sync(). All timestamps, - * access, creation, and modify, are set when a file is created. - * sync() maintains the last access date and last modify date/time. - * - * See the timestamp() function. - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)) { - dateTime_ = dateTime; - } - /** - * Cancel the date/time callback function. - */ - static void dateTimeCallbackCancel(void) { - // use explicit zero since NULL is not defined for Sanguino - dateTime_ = 0; - } - /** \return Address of the block that contains this file's directory. */ - uint32_t dirBlock(void) const {return dirBlock_;} - uint8_t dirEntry(dir_t* dir); - /** \return Index of this file's directory in the block dirBlock. */ - uint8_t dirIndex(void) const {return dirIndex_;} - static void dirName(const dir_t& dir, char* name); - /** \return The total number of bytes in a file or directory. */ - uint32_t fileSize(void) const {return fileSize_;} - /** \return The first cluster number for a file or directory. */ - uint32_t firstCluster(void) const {return firstCluster_;} - /** \return True if this is a SdFile for a directory else false. */ - uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;} - /** \return True if this is a SdFile for a file else false. */ - uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;} - /** \return True if this is a SdFile for an open file/directory else false. */ - uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;} - /** \return True if this is a SdFile for a subdirectory else false. */ - uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;} - /** \return True if this is a SdFile for the root directory. */ - uint8_t isRoot(void) const { - return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; - } - void ls(uint8_t flags = 0, uint8_t indent = 0); - uint8_t makeDir(SdFile* dir, const char* dirName); - uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag); - uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag); - - uint8_t openRoot(SdVolume* vol); - static void printDirName(const dir_t& dir, uint8_t width); - static void printFatDate(uint16_t fatDate); - static void printFatTime(uint16_t fatTime); - static void printTwoDigits(uint8_t v); - /** - * Read the next byte from a file. - * - * \return For success read returns the next byte in the file as an int. - * If an error occurs or end of file is reached -1 is returned. - */ - int16_t read(void) { - uint8_t b; - return read(&b, 1) == 1 ? b : -1; - } - int16_t read(void* buf, uint16_t nbyte); - int8_t readDir(dir_t* dir); - static uint8_t remove(SdFile* dirFile, const char* fileName); - uint8_t remove(void); - /** Set the file's current position to zero. */ - void rewind(void) { - curPosition_ = curCluster_ = 0; - } - uint8_t rmDir(void); - uint8_t rmRfStar(void); - /** Set the files position to current position + \a pos. See seekSet(). */ - uint8_t seekCur(uint32_t pos) { - return seekSet(curPosition_ + pos); - } - /** - * Set the files current position to end of file. Useful to position - * a file for append. See seekSet(). - */ - uint8_t seekEnd(void) {return seekSet(fileSize_);} - uint8_t seekSet(uint32_t pos); - /** - * Use unbuffered reads to access this file. Used with Wave - * Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. - * - * Not recommended for normal applications. - */ - void setUnbufferedRead(void) { - if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ; - } - uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, - uint8_t hour, uint8_t minute, uint8_t second); - uint8_t sync(void); - /** Type of this SdFile. You should use isFile() or isDir() instead of type() - * if possible. - * - * \return The file or directory type. - */ - uint8_t type(void) const {return type_;} - uint8_t truncate(uint32_t size); - /** \return Unbuffered read flag. */ - uint8_t unbufferedRead(void) const { - return flags_ & F_FILE_UNBUFFERED_READ; - } - /** \return SdVolume that contains this file. */ - SdVolume* volume(void) const {return vol_;} - void write(uint8_t b); - int16_t write(const void* buf, uint16_t nbyte); - void write(const char* str); - void write_P(PGM_P str); - void writeln_P(PGM_P str); -//------------------------------------------------------------------------------ -#if ALLOW_DEPRECATED_FUNCTIONS -// Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: - * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - */ - uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT - return contiguousRange(&bgnBlock, &endBlock); - } - /** \deprecated Use: - * uint8_t SdFile::createContiguous(SdFile* dirFile, - * const char* fileName, uint32_t size) - */ - uint8_t createContiguous(SdFile& dirFile, // NOLINT - const char* fileName, uint32_t size) { - return createContiguous(&dirFile, fileName, size); - } - - /** - * \deprecated Use: - * static void SdFile::dateTimeCallback( - * void (*dateTime)(uint16_t* date, uint16_t* time)); - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT - oldDateTime_ = dateTime; - dateTime_ = dateTime ? oldToNew : 0; - } - /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ - uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT - /** \deprecated Use: - * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); - */ - uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT - return makeDir(&dir, dirName); - } - /** \deprecated Use: - * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, // NOLINT - const char* fileName, uint8_t oflag) { - return open(&dirFile, fileName, oflag); - } - /** \deprecated Do not use in new apps */ - uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT - return open(dirFile, fileName, O_RDWR); - } - /** \deprecated Use: - * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT - return open(&dirFile, index, oflag); - } - /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ - uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT - - /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ - int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT - /** \deprecated Use: - * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); - */ - static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT - return remove(&dirFile, fileName); - } -//------------------------------------------------------------------------------ -// rest are private + SdFat() {} + /** \return a pointer to the Sd2Card object. */ + Sd2Card* card() {return &card_;} + bool chdir(bool set_cwd = false); + bool chdir(const char* path, bool set_cwd = false); + void chvol(); + void errorHalt(); + void errorHalt_P(PGM_P msg); + void errorHalt(char const *msg); + void errorPrint(); + void errorPrint_P(PGM_P msg); + void errorPrint(char const *msg); + bool exists(const char* name); + bool init(uint8_t sckRateID = SPI_FULL_SPEED, + uint8_t chipSelectPin = SD_CHIP_SELECT_PIN); + void initErrorHalt(); + void initErrorHalt(char const *msg); + void initErrorHalt_P(PGM_P msg); + void initErrorPrint(); + void initErrorPrint(char const *msg); + void initErrorPrint_P(PGM_P msg); + void ls(uint8_t flags = 0); + void ls(Print* pr, uint8_t flags = 0); + bool mkdir(const char* path, bool pFlag = true); + bool remove(const char* path); + bool rename(const char *oldPath, const char *newPath); + bool rmdir(const char* path); + bool truncate(const char* path, uint32_t length); + /** \return a pointer to the SdVolume object. */ + SdVolume* vol() {return &vol_;} + /** \return a pointer to the volume working directory. */ + SdBaseFile* vwd() {return &vwd_;} private: - static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT - static void oldToNew(uint16_t* date, uint16_t* time) { - uint16_t d; - uint16_t t; - oldDateTime_(d, t); - *date = d; - *time = t; - } -#endif // ALLOW_DEPRECATED_FUNCTIONS - private: - // bits defined in flags_ - // should be 0XF - static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); - // available bits - static uint8_t const F_UNUSED = 0X30; - // use unbuffered SD read - static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; - // sync of directory entry required - static uint8_t const F_FILE_DIR_DIRTY = 0X80; - -// make sure F_OFLAG is ok -#if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG) -#error flags_ bits conflict -#endif // flags_ bits - - // private data - uint8_t flags_; // See above for definition of flags_ bits - uint8_t type_; // type of file see above for values - uint32_t curCluster_; // cluster for current file position - uint32_t curPosition_; // current file position in bytes from beginning - uint32_t dirBlock_; // SD block that contains directory entry for file - uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF - uint32_t fileSize_; // file size in bytes - uint32_t firstCluster_; // first cluster of file - SdVolume* vol_; // volume where file is located - - // private functions - uint8_t addCluster(void); - uint8_t addDirCluster(void); - dir_t* cacheDirEntry(uint8_t action); - static void (*dateTime_)(uint16_t* date, uint16_t* time); - static uint8_t make83Name(const char* str, uint8_t* name); - uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); - dir_t* readDirCache(void); -}; -//============================================================================== -// SdVolume class -/** - * \brief Cache for an SD data block - */ -union cache_t { - /** Used to access cached file data blocks. */ - uint8_t data[512]; - /** Used to access cached FAT16 entries. */ - uint16_t fat16[256]; - /** Used to access cached FAT32 entries. */ - uint32_t fat32[128]; - /** Used to access cached directory entries. */ - dir_t dir[16]; - /** Used to access a cached MasterBoot Record. */ - mbr_t mbr; - /** Used to access to a cached FAT boot sector. */ - fbs_t fbs; -}; -//------------------------------------------------------------------------------ -/** - * \class SdVolume - * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. - */ -class SdVolume { - public: - /** Create an instance of SdVolume */ - SdVolume(void) :allocSearchStart_(2), fatType_(0) {} - /** Clear the cache and returns a pointer to the cache. Used by the WaveRP - * recorder to do raw write to the SD card. Not for normal apps. - */ - static uint8_t* cacheClear(void) { - cacheFlush(); - cacheBlockNumber_ = 0XFFFFFFFF; - return cacheBuffer_.data; - } - /** - * Initialize a FAT volume. Try partition one first then try super - * floppy format. - * - * \param[in] dev The Sd2Card where the volume is located. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. Reasons for - * failure include not finding a valid partition, not finding a valid - * FAT file system or an I/O error. - */ - uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);} - uint8_t init(Sd2Card* dev, uint8_t part); - - // inline functions that return volume info - /** \return The volume's cluster size in blocks. */ - uint8_t blocksPerCluster(void) const {return blocksPerCluster_;} - /** \return The number of blocks in one FAT. */ - uint32_t blocksPerFat(void) const {return blocksPerFat_;} - /** \return The total number of clusters in the volume. */ - uint32_t clusterCount(void) const {return clusterCount_;} - /** \return The shift count required to multiply by blocksPerCluster. */ - uint8_t clusterSizeShift(void) const {return clusterSizeShift_;} - /** \return The logical block number for the start of file data. */ - uint32_t dataStartBlock(void) const {return dataStartBlock_;} - /** \return The number of FAT structures on the volume. */ - uint8_t fatCount(void) const {return fatCount_;} - /** \return The logical block number for the start of the first FAT. */ - uint32_t fatStartBlock(void) const {return fatStartBlock_;} - /** \return The FAT type of the volume. Values are 12, 16 or 32. */ - uint8_t fatType(void) const {return fatType_;} - /** \return The number of entries in the root directory for FAT16 volumes. */ - uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;} - /** \return The logical block number for the start of the root directory - on FAT16 volumes or the first cluster number on FAT32 volumes. */ - uint32_t rootDirStart(void) const {return rootDirStart_;} - /** return a pointer to the Sd2Card object for this volume */ - static Sd2Card* sdCard(void) {return sdCard_;} -//------------------------------------------------------------------------------ -#if ALLOW_DEPRECATED_FUNCTIONS - // Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ - uint8_t init(Sd2Card& dev) {return init(&dev);} // NOLINT - - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ - uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT - return init(&dev, part); - } -#endif // ALLOW_DEPRECATED_FUNCTIONS -//------------------------------------------------------------------------------ - private: - // Allow SdFile access to SdVolume private data. - friend class SdFile; - - // value for action argument in cacheRawBlock to indicate read from cache - static uint8_t const CACHE_FOR_READ = 0; - // value for action argument in cacheRawBlock to indicate cache dirty - static uint8_t const CACHE_FOR_WRITE = 1; - - static cache_t cacheBuffer_; // 512 byte cache for device blocks - static uint32_t cacheBlockNumber_; // Logical number of block in the cache - static Sd2Card* sdCard_; // Sd2Card object for cache - static uint8_t cacheDirty_; // cacheFlush() will write block if true - static uint32_t cacheMirrorBlock_; // block number for mirror FAT -// - uint32_t allocSearchStart_; // start cluster for alloc search - uint8_t blocksPerCluster_; // cluster size in blocks - uint32_t blocksPerFat_; // FAT size in blocks - uint32_t clusterCount_; // clusters in one FAT - uint8_t clusterSizeShift_; // shift to convert cluster count to block count - uint32_t dataStartBlock_; // first data block number - uint8_t fatCount_; // number of FATs on volume - uint32_t fatStartBlock_; // start block for first FAT - uint8_t fatType_; // volume type (12, 16, OR 32) - uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir - uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 - //---------------------------------------------------------------------------- - uint8_t allocContiguous(uint32_t count, uint32_t* curCluster); - uint8_t blockOfCluster(uint32_t position) const { - return (position >> 9) & (blocksPerCluster_ - 1);} - uint32_t clusterStartBlock(uint32_t cluster) const { - return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} - uint32_t blockNumber(uint32_t cluster, uint32_t position) const { - return clusterStartBlock(cluster) + blockOfCluster(position);} - static uint8_t cacheFlush(void); - static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); - static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;} - static uint8_t cacheZeroBlock(uint32_t blockNumber); - uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const; - uint8_t fatGet(uint32_t cluster, uint32_t* value) const; - uint8_t fatPut(uint32_t cluster, uint32_t value); - uint8_t fatPutEOC(uint32_t cluster) { - return fatPut(cluster, 0x0FFFFFFF); - } - uint8_t freeChain(uint32_t cluster); - uint8_t isEOC(uint32_t cluster) const { - return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); - } - uint8_t readBlock(uint32_t block, uint8_t* dst) { - return sdCard_->readBlock(block, dst);} - uint8_t readData(uint32_t block, uint16_t offset, - uint16_t count, uint8_t* dst) { - return sdCard_->readData(block, offset, count, dst); - } - uint8_t writeBlock(uint32_t block, const uint8_t* dst) { - return sdCard_->writeBlock(block, dst); - } + Sd2Card card_; + SdVolume vol_; + SdBaseFile vwd_; }; #endif // SdFat_h diff --git a/Marlin/SdFatConfig.h b/Marlin/SdFatConfig.h new file mode 100644 index 0000000000..036bdb9c62 --- /dev/null +++ b/Marlin/SdFatConfig.h @@ -0,0 +1,108 @@ +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +/** + * \file + * \brief configuration definitions + */ +#ifndef SdFatConfig_h +#define SdFatConfig_h +#include +//------------------------------------------------------------------------------ +/** + * To use multiple SD cards set USE_MULTIPLE_CARDS nonzero. + * + * Using multiple cards costs 400 - 500 bytes of flash. + * + * Each card requires about 550 bytes of SRAM so use of a Mega is recommended. + */ +#define USE_MULTIPLE_CARDS 0 +//------------------------------------------------------------------------------ +/** + * Call flush for endl if ENDL_CALLS_FLUSH is nonzero + * + * The standard for iostreams is to call flush. This is very costly for + * SdFat. Each call to flush causes 2048 bytes of I/O to the SD. + * + * SdFat has a single 512 byte buffer for SD I/O so it must write the current + * data block to the SD, read the directory block from the SD, update the + * directory entry, write the directory block to the SD and read the data + * block back into the buffer. + * + * The SD flash memory controller is not designed for this many rewrites + * so performance may be reduced by more than a factor of 100. + * + * If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force + * all data to be written to the SD. + */ +#define ENDL_CALLS_FLUSH 0 +//------------------------------------------------------------------------------ +/** + * Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero + */ +#define ALLOW_DEPRECATED_FUNCTIONS 1 +//------------------------------------------------------------------------------ +/** + * Allow FAT12 volumes if FAT12_SUPPORT is nonzero. + * FAT12 has not been well tested. + */ +#define FAT12_SUPPORT 0 +//------------------------------------------------------------------------------ +/** + * SPI init rate for SD initialization commands. Must be 5 (F_CPU/64) + * or 6 (F_CPU/128). + */ +#define SPI_SD_INIT_RATE 5 +//------------------------------------------------------------------------------ +/** + * Set the SS pin high for hardware SPI. If SS is chip select for another SPI + * device this will disable that device during the SD init phase. + */ +#define SET_SPI_SS_HIGH 1 +//------------------------------------------------------------------------------ +/** + * Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos. + * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. + * + * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used + * on Mega Arduinos. Software SPI works well with GPS Shield V1.1 + * but many SD cards will fail with GPS Shield V1.0. + */ +#define MEGA_SOFT_SPI 0 +//------------------------------------------------------------------------------ +/** + * Set USE_SOFTWARE_SPI nonzero to always use software SPI. + */ +#define USE_SOFTWARE_SPI 0 +// define software SPI pins so Mega can use unmodified 168/328 shields +/** Software SPI chip select pin for the SD */ +uint8_t const SOFT_SPI_CS_PIN = 10; +/** Software SPI Master Out Slave In pin */ +uint8_t const SOFT_SPI_MOSI_PIN = 11; +/** Software SPI Master In Slave Out pin */ +uint8_t const SOFT_SPI_MISO_PIN = 12; +/** Software SPI Clock pin */ +uint8_t const SOFT_SPI_SCK_PIN = 13; +//------------------------------------------------------------------------------ +/** + * The __cxa_pure_virtual function is an error handler that is invoked when + * a pure virtual function is called. + */ +#define USE_CXA_PURE_VIRTUAL 1 +#endif // SdFatConfig_h diff --git a/Marlin/FatStructs.h b/Marlin/SdFatStructs.h similarity index 59% rename from Marlin/FatStructs.h rename to Marlin/SdFatStructs.h index f5bdaa5946..4ea82b766c 100644 --- a/Marlin/FatStructs.h +++ b/Marlin/SdFatStructs.h @@ -1,418 +1,604 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#ifndef FatStructs_h -#define FatStructs_h -/** - * \file - * FAT file structures - */ -/* - * mostly from Microsoft document fatgen103.doc - * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx - */ -//------------------------------------------------------------------------------ -/** Value for byte 510 of boot block or MBR */ -uint8_t const BOOTSIG0 = 0X55; -/** Value for byte 511 of boot block or MBR */ -uint8_t const BOOTSIG1 = 0XAA; -//------------------------------------------------------------------------------ -/** - * \struct partitionTable - * \brief MBR partition table entry - * - * A partition table entry for a MBR formatted storage device. - * The MBR partition table has four entries. - */ -struct partitionTable { - /** - * Boot Indicator . Indicates whether the volume is the active - * partition. Legal values include: 0X00. Do not use for booting. - * 0X80 Active partition. - */ - uint8_t boot; - /** - * Head part of Cylinder-head-sector address of the first block in - * the partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t beginHead; - /** - * Sector part of Cylinder-head-sector address of the first block in - * the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned beginSector : 6; - /** High bits cylinder for first block in partition. */ - unsigned beginCylinderHigh : 2; - /** - * Combine beginCylinderLow with beginCylinderHigh. Legal values - * are 0-1023. Only used in old PC BIOS. - */ - uint8_t beginCylinderLow; - /** - * Partition type. See defines that begin with PART_TYPE_ for - * some Microsoft partition types. - */ - uint8_t type; - /** - * head part of cylinder-head-sector address of the last sector in the - * partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t endHead; - /** - * Sector part of cylinder-head-sector address of the last sector in - * the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned endSector : 6; - /** High bits of end cylinder */ - unsigned endCylinderHigh : 2; - /** - * Combine endCylinderLow with endCylinderHigh. Legal values - * are 0-1023. Only used in old PC BIOS. - */ - uint8_t endCylinderLow; - /** Logical block address of the first block in the partition. */ - uint32_t firstSector; - /** Length of the partition, in blocks. */ - uint32_t totalSectors; -}; -/** Type name for partitionTable */ -typedef struct partitionTable part_t; -//------------------------------------------------------------------------------ -/** - * \struct masterBootRecord - * - * \brief Master Boot Record - * - * The first block of a storage device that is formatted with a MBR. - */ -struct masterBootRecord { - /** Code Area for master boot program. */ - uint8_t codeArea[440]; - /** Optional WindowsNT disk signature. May contain more boot code. */ - uint32_t diskSignature; - /** Usually zero but may be more boot code. */ - uint16_t usuallyZero; - /** Partition tables. */ - part_t part[4]; - /** First MBR signature byte. Must be 0X55 */ - uint8_t mbrSig0; - /** Second MBR signature byte. Must be 0XAA */ - uint8_t mbrSig1; -}; -/** Type name for masterBootRecord */ -typedef struct masterBootRecord mbr_t; -//------------------------------------------------------------------------------ -/** - * \struct biosParmBlock - * - * \brief BIOS parameter block - * - * The BIOS parameter block describes the physical layout of a FAT volume. - */ -struct biosParmBlock { - /** - * Count of bytes per sector. This value may take on only the - * following values: 512, 1024, 2048 or 4096 - */ - uint16_t bytesPerSector; - /** - * Number of sectors per allocation unit. This value must be a - * power of 2 that is greater than 0. The legal values are - * 1, 2, 4, 8, 16, 32, 64, and 128. - */ - uint8_t sectorsPerCluster; - /** - * Number of sectors before the first FAT. - * This value must not be zero. - */ - uint16_t reservedSectorCount; - /** The count of FAT data structures on the volume. This field should - * always contain the value 2 for any FAT volume of any type. - */ - uint8_t fatCount; - /** - * For FAT12 and FAT16 volumes, this field contains the count of - * 32-byte directory entries in the root directory. For FAT32 volumes, - * this field must be set to 0. For FAT12 and FAT16 volumes, this - * value should always specify a count that when multiplied by 32 - * results in a multiple of bytesPerSector. FAT16 volumes should - * use the value 512. - */ - uint16_t rootDirEntryCount; - /** - * This field is the old 16-bit total count of sectors on the volume. - * This count includes the count of all sectors in all four regions - * of the volume. This field can be 0; if it is 0, then totalSectors32 - * must be non-zero. For FAT32 volumes, this field must be 0. For - * FAT12 and FAT16 volumes, this field contains the sector count, and - * totalSectors32 is 0 if the total sector count fits - * (is less than 0x10000). - */ - uint16_t totalSectors16; - /** - * This dates back to the old MS-DOS 1.x media determination and is - * no longer usually used for anything. 0xF8 is the standard value - * for fixed (non-removable) media. For removable media, 0xF0 is - * frequently used. Legal values are 0xF0 or 0xF8-0xFF. - */ - uint8_t mediaType; - /** - * Count of sectors occupied by one FAT on FAT12/FAT16 volumes. - * On FAT32 volumes this field must be 0, and sectorsPerFat32 - * contains the FAT size count. - */ - uint16_t sectorsPerFat16; - /** Sectors per track for interrupt 0x13. Not used otherwise. */ - uint16_t sectorsPerTrtack; - /** Number of heads for interrupt 0x13. Not used otherwise. */ - uint16_t headCount; - /** - * Count of hidden sectors preceding the partition that contains this - * FAT volume. This field is generally only relevant for media - * visible on interrupt 0x13. - */ - uint32_t hidddenSectors; - /** - * This field is the new 32-bit total count of sectors on the volume. - * This count includes the count of all sectors in all four regions - * of the volume. This field can be 0; if it is 0, then - * totalSectors16 must be non-zero. - */ - uint32_t totalSectors32; - /** - * Count of sectors occupied by one FAT on FAT32 volumes. - */ - uint32_t sectorsPerFat32; - /** - * This field is only defined for FAT32 media and does not exist on - * FAT12 and FAT16 media. - * Bits 0-3 -- Zero-based number of active FAT. - * Only valid if mirroring is disabled. - * Bits 4-6 -- Reserved. - * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. - * -- 1 means only one FAT is active; it is the one referenced in bits 0-3. - * Bits 8-15 -- Reserved. - */ - uint16_t fat32Flags; - /** - * FAT32 version. High byte is major revision number. - * Low byte is minor revision number. Only 0.0 define. - */ - uint16_t fat32Version; - /** - * Cluster number of the first cluster of the root directory for FAT32. - * This usually 2 but not required to be 2. - */ - uint32_t fat32RootCluster; - /** - * Sector number of FSINFO structure in the reserved area of the - * FAT32 volume. Usually 1. - */ - uint16_t fat32FSInfo; - /** - * If non-zero, indicates the sector number in the reserved area - * of the volume of a copy of the boot record. Usually 6. - * No value other than 6 is recommended. - */ - uint16_t fat32BackBootBlock; - /** - * Reserved for future expansion. Code that formats FAT32 volumes - * should always set all of the bytes of this field to 0. - */ - uint8_t fat32Reserved[12]; -}; -/** Type name for biosParmBlock */ -typedef struct biosParmBlock bpb_t; -//------------------------------------------------------------------------------ -/** - * \struct fat32BootSector - * - * \brief Boot sector for a FAT16 or FAT32 volume. - * - */ -struct fat32BootSector { - /** X86 jmp to boot program */ - uint8_t jmpToBootCode[3]; - /** informational only - don't depend on it */ - char oemName[8]; - /** BIOS Parameter Block */ - bpb_t bpb; - /** for int0x13 use value 0X80 for hard drive */ - uint8_t driveNumber; - /** used by Windows NT - should be zero for FAT */ - uint8_t reserved1; - /** 0X29 if next three fields are valid */ - uint8_t bootSignature; - /** usually generated by combining date and time */ - uint32_t volumeSerialNumber; - /** should match volume label in root dir */ - char volumeLabel[11]; - /** informational only - don't depend on it */ - char fileSystemType[8]; - /** X86 boot code */ - uint8_t bootCode[420]; - /** must be 0X55 */ - uint8_t bootSectorSig0; - /** must be 0XAA */ - uint8_t bootSectorSig1; -}; -//------------------------------------------------------------------------------ -// End Of Chain values for FAT entries -/** FAT16 end of chain value used by Microsoft. */ -uint16_t const FAT16EOC = 0XFFFF; -/** Minimum value for FAT16 EOC. Use to test for EOC. */ -uint16_t const FAT16EOC_MIN = 0XFFF8; -/** FAT32 end of chain value used by Microsoft. */ -uint32_t const FAT32EOC = 0X0FFFFFFF; -/** Minimum value for FAT32 EOC. Use to test for EOC. */ -uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; -/** Mask a for FAT32 entry. Entries are 28 bits. */ -uint32_t const FAT32MASK = 0X0FFFFFFF; - -/** Type name for fat32BootSector */ -typedef struct fat32BootSector fbs_t; -//------------------------------------------------------------------------------ -/** - * \struct directoryEntry - * \brief FAT short directory entry - * - * Short means short 8.3 name, not the entry size. - * - * Date Format. A FAT directory entry date stamp is a 16-bit field that is - * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the - * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the - * 16-bit word): - * - * Bits 9-15: Count of years from 1980, valid value range 0-127 - * inclusive (1980-2107). - * - * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. - * - * Bits 0-4: Day of month, valid value range 1-31 inclusive. - * - * Time Format. A FAT directory entry time stamp is a 16-bit field that has - * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the - * 16-bit word, bit 15 is the MSB of the 16-bit word). - * - * Bits 11-15: Hours, valid value range 0-23 inclusive. - * - * Bits 5-10: Minutes, valid value range 0-59 inclusive. - * - * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). - * - * The valid time range is from Midnight 00:00:00 to 23:59:58. - */ -struct directoryEntry { - /** - * Short 8.3 name. - * The first eight bytes contain the file name with blank fill. - * The last three bytes contain the file extension with blank fill. - */ - uint8_t name[11]; - /** Entry attributes. - * - * The upper two bits of the attribute byte are reserved and should - * always be set to 0 when a file is created and never modified or - * looked at after that. See defines that begin with DIR_ATT_. - */ - uint8_t attributes; - /** - * Reserved for use by Windows NT. Set value to 0 when a file is - * created and never modify or look at it after that. - */ - uint8_t reservedNT; - /** - * The granularity of the seconds part of creationTime is 2 seconds - * so this field is a count of tenths of a second and its valid - * value range is 0-199 inclusive. (WHG note - seems to be hundredths) - */ - uint8_t creationTimeTenths; - /** Time file was created. */ - uint16_t creationTime; - /** Date file was created. */ - uint16_t creationDate; - /** - * Last access date. Note that there is no last access time, only - * a date. This is the date of last read or write. In the case of - * a write, this should be set to the same date as lastWriteDate. - */ - uint16_t lastAccessDate; - /** - * High word of this entry's first cluster number (always 0 for a - * FAT12 or FAT16 volume). - */ - uint16_t firstClusterHigh; - /** Time of last write. File creation is considered a write. */ - uint16_t lastWriteTime; - /** Date of last write. File creation is considered a write. */ - uint16_t lastWriteDate; - /** Low word of this entry's first cluster number. */ - uint16_t firstClusterLow; - /** 32-bit unsigned holding this file's size in bytes. */ - uint32_t fileSize; -}; -//------------------------------------------------------------------------------ -// Definitions for directory entries -// -/** Type name for directoryEntry */ -typedef struct directoryEntry dir_t; -/** escape for name[0] = 0XE5 */ -uint8_t const DIR_NAME_0XE5 = 0X05; -/** name[0] value for entry that is free after being "deleted" */ -uint8_t const DIR_NAME_DELETED = 0XE5; -/** name[0] value for entry that is free and no allocated entries follow */ -uint8_t const DIR_NAME_FREE = 0X00; -/** file is read-only */ -uint8_t const DIR_ATT_READ_ONLY = 0X01; -/** File should hidden in directory listings */ -uint8_t const DIR_ATT_HIDDEN = 0X02; -/** Entry is for a system file */ -uint8_t const DIR_ATT_SYSTEM = 0X04; -/** Directory entry contains the volume label */ -uint8_t const DIR_ATT_VOLUME_ID = 0X08; -/** Entry is for a directory */ -uint8_t const DIR_ATT_DIRECTORY = 0X10; -/** Old DOS archive bit for backup support */ -uint8_t const DIR_ATT_ARCHIVE = 0X20; -/** Test value for long name entry. Test is - (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ -uint8_t const DIR_ATT_LONG_NAME = 0X0F; -/** Test mask for long name entry */ -uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; -/** defined attribute bits */ -uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; -/** Directory entry is part of a long name */ -static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { - return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; -} -/** Mask for file/subdirectory tests */ -uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); -/** Directory entry is for a file */ -static inline uint8_t DIR_IS_FILE(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; -} -/** Directory entry is for a subdirectory */ -static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; -} -/** Directory entry is for a file or subdirectory */ -static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; -} -#endif // FatStructs_h +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdFatStructs_h +#define SdFatStructs_h +/** + * \file + * \brief FAT file structures + */ +/* + * mostly from Microsoft document fatgen103.doc + * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx + */ +//------------------------------------------------------------------------------ +/** Value for byte 510 of boot block or MBR */ +uint8_t const BOOTSIG0 = 0X55; +/** Value for byte 511 of boot block or MBR */ +uint8_t const BOOTSIG1 = 0XAA; +/** Value for bootSignature field int FAT/FAT32 boot sector */ +uint8_t const EXTENDED_BOOT_SIG = 0X29; +//------------------------------------------------------------------------------ +/** + * \struct partitionTable + * \brief MBR partition table entry + * + * A partition table entry for a MBR formatted storage device. + * The MBR partition table has four entries. + */ +struct partitionTable { + /** + * Boot Indicator . Indicates whether the volume is the active + * partition. Legal values include: 0X00. Do not use for booting. + * 0X80 Active partition. + */ + uint8_t boot; + /** + * Head part of Cylinder-head-sector address of the first block in + * the partition. Legal values are 0-255. Only used in old PC BIOS. + */ + uint8_t beginHead; + /** + * Sector part of Cylinder-head-sector address of the first block in + * the partition. Legal values are 1-63. Only used in old PC BIOS. + */ + unsigned beginSector : 6; + /** High bits cylinder for first block in partition. */ + unsigned beginCylinderHigh : 2; + /** + * Combine beginCylinderLow with beginCylinderHigh. Legal values + * are 0-1023. Only used in old PC BIOS. + */ + uint8_t beginCylinderLow; + /** + * Partition type. See defines that begin with PART_TYPE_ for + * some Microsoft partition types. + */ + uint8_t type; + /** + * head part of cylinder-head-sector address of the last sector in the + * partition. Legal values are 0-255. Only used in old PC BIOS. + */ + uint8_t endHead; + /** + * Sector part of cylinder-head-sector address of the last sector in + * the partition. Legal values are 1-63. Only used in old PC BIOS. + */ + unsigned endSector : 6; + /** High bits of end cylinder */ + unsigned endCylinderHigh : 2; + /** + * Combine endCylinderLow with endCylinderHigh. Legal values + * are 0-1023. Only used in old PC BIOS. + */ + uint8_t endCylinderLow; + /** Logical block address of the first block in the partition. */ + uint32_t firstSector; + /** Length of the partition, in blocks. */ + uint32_t totalSectors; +}; +/** Type name for partitionTable */ +typedef struct partitionTable part_t; +//------------------------------------------------------------------------------ +/** + * \struct masterBootRecord + * + * \brief Master Boot Record + * + * The first block of a storage device that is formatted with a MBR. + */ +struct masterBootRecord { + /** Code Area for master boot program. */ + uint8_t codeArea[440]; + /** Optional Windows NT disk signature. May contain boot code. */ + uint32_t diskSignature; + /** Usually zero but may be more boot code. */ + uint16_t usuallyZero; + /** Partition tables. */ + part_t part[4]; + /** First MBR signature byte. Must be 0X55 */ + uint8_t mbrSig0; + /** Second MBR signature byte. Must be 0XAA */ + uint8_t mbrSig1; +}; +/** Type name for masterBootRecord */ +typedef struct masterBootRecord mbr_t; +//------------------------------------------------------------------------------ +/** + * \struct fat_boot + * + * \brief Boot sector for a FAT12/FAT16 volume. + * + */ +struct fat_boot { + /** + * The first three bytes of the boot sector must be valid, + * executable x 86-based CPU instructions. This includes a + * jump instruction that skips the next nonexecutable bytes. + */ + uint8_t jump[3]; + /** + * This is typically a string of characters that identifies + * the operating system that formatted the volume. + */ + char oemId[8]; + /** + * The size of a hardware sector. Valid decimal values for this + * field are 512, 1024, 2048, and 4096. For most disks used in + * the United States, the value of this field is 512. + */ + uint16_t bytesPerSector; + /** + * Number of sectors per allocation unit. This value must be a + * power of 2 that is greater than 0. The legal values are + * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided. + */ + uint8_t sectorsPerCluster; + /** + * The number of sectors preceding the start of the first FAT, + * including the boot sector. The value of this field is always 1. + */ + uint16_t reservedSectorCount; + /** + * The number of copies of the FAT on the volume. + * The value of this field is always 2. + */ + uint8_t fatCount; + /** + * For FAT12 and FAT16 volumes, this field contains the count of + * 32-byte directory entries in the root directory. For FAT32 volumes, + * this field must be set to 0. For FAT12 and FAT16 volumes, this + * value should always specify a count that when multiplied by 32 + * results in a multiple of bytesPerSector. FAT16 volumes should + * use the value 512. + */ + uint16_t rootDirEntryCount; + /** + * This field is the old 16-bit total count of sectors on the volume. + * This count includes the count of all sectors in all four regions + * of the volume. This field can be 0; if it is 0, then totalSectors32 + * must be nonzero. For FAT32 volumes, this field must be 0. For + * FAT12 and FAT16 volumes, this field contains the sector count, and + * totalSectors32 is 0 if the total sector count fits + * (is less than 0x10000). + */ + uint16_t totalSectors16; + /** + * This dates back to the old MS-DOS 1.x media determination and is + * no longer usually used for anything. 0xF8 is the standard value + * for fixed (nonremovable) media. For removable media, 0xF0 is + * frequently used. Legal values are 0xF0 or 0xF8-0xFF. + */ + uint8_t mediaType; + /** + * Count of sectors occupied by one FAT on FAT12/FAT16 volumes. + * On FAT32 volumes this field must be 0, and sectorsPerFat32 + * contains the FAT size count. + */ + uint16_t sectorsPerFat16; + /** Sectors per track for interrupt 0x13. Not used otherwise. */ + uint16_t sectorsPerTrack; + /** Number of heads for interrupt 0x13. Not used otherwise. */ + uint16_t headCount; + /** + * Count of hidden sectors preceding the partition that contains this + * FAT volume. This field is generally only relevant for media + * visible on interrupt 0x13. + */ + uint32_t hidddenSectors; + /** + * This field is the new 32-bit total count of sectors on the volume. + * This count includes the count of all sectors in all four regions + * of the volume. This field can be 0; if it is 0, then + * totalSectors16 must be nonzero. + */ + uint32_t totalSectors32; + /** + * Related to the BIOS physical drive number. Floppy drives are + * identified as 0x00 and physical hard disks are identified as + * 0x80, regardless of the number of physical disk drives. + * Typically, this value is set prior to issuing an INT 13h BIOS + * call to specify the device to access. The value is only + * relevant if the device is a boot device. + */ + uint8_t driveNumber; + /** used by Windows NT - should be zero for FAT */ + uint8_t reserved1; + /** 0X29 if next three fields are valid */ + uint8_t bootSignature; + /** + * A random serial number created when formatting a disk, + * which helps to distinguish between disks. + * Usually generated by combining date and time. + */ + uint32_t volumeSerialNumber; + /** + * A field once used to store the volume label. The volume label + * is now stored as a special file in the root directory. + */ + char volumeLabel[11]; + /** + * A field with a value of either FAT, FAT12 or FAT16, + * depending on the disk format. + */ + char fileSystemType[8]; + /** X86 boot code */ + uint8_t bootCode[448]; + /** must be 0X55 */ + uint8_t bootSectorSig0; + /** must be 0XAA */ + uint8_t bootSectorSig1; +}; +/** Type name for FAT Boot Sector */ +typedef struct fat_boot fat_boot_t; +//------------------------------------------------------------------------------ +/** + * \struct fat32_boot + * + * \brief Boot sector for a FAT32 volume. + * + */ +struct fat32_boot { + /** + * The first three bytes of the boot sector must be valid, + * executable x 86-based CPU instructions. This includes a + * jump instruction that skips the next nonexecutable bytes. + */ + uint8_t jump[3]; + /** + * This is typically a string of characters that identifies + * the operating system that formatted the volume. + */ + char oemId[8]; + /** + * The size of a hardware sector. Valid decimal values for this + * field are 512, 1024, 2048, and 4096. For most disks used in + * the United States, the value of this field is 512. + */ + uint16_t bytesPerSector; + /** + * Number of sectors per allocation unit. This value must be a + * power of 2 that is greater than 0. The legal values are + * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided. + */ + uint8_t sectorsPerCluster; + /** + * The number of sectors preceding the start of the first FAT, + * including the boot sector. Must not be zero + */ + uint16_t reservedSectorCount; + /** + * The number of copies of the FAT on the volume. + * The value of this field is always 2. + */ + uint8_t fatCount; + /** + * FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0. + */ + uint16_t rootDirEntryCount; + /** + * For FAT32 volumes, this field must be 0. + */ + uint16_t totalSectors16; + /** + * This dates back to the old MS-DOS 1.x media determination and is + * no longer usually used for anything. 0xF8 is the standard value + * for fixed (nonremovable) media. For removable media, 0xF0 is + * frequently used. Legal values are 0xF0 or 0xF8-0xFF. + */ + uint8_t mediaType; + /** + * On FAT32 volumes this field must be 0, and sectorsPerFat32 + * contains the FAT size count. + */ + uint16_t sectorsPerFat16; + /** Sectors per track for interrupt 0x13. Not used otherwise. */ + uint16_t sectorsPerTrack; + /** Number of heads for interrupt 0x13. Not used otherwise. */ + uint16_t headCount; + /** + * Count of hidden sectors preceding the partition that contains this + * FAT volume. This field is generally only relevant for media + * visible on interrupt 0x13. + */ + uint32_t hidddenSectors; + /** + * Contains the total number of sectors in the FAT32 volume. + */ + uint32_t totalSectors32; + /** + * Count of sectors occupied by one FAT on FAT32 volumes. + */ + uint32_t sectorsPerFat32; + /** + * This field is only defined for FAT32 media and does not exist on + * FAT12 and FAT16 media. + * Bits 0-3 -- Zero-based number of active FAT. + * Only valid if mirroring is disabled. + * Bits 4-6 -- Reserved. + * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. + * -- 1 means only one FAT is active; it is the one referenced + * in bits 0-3. + * Bits 8-15 -- Reserved. + */ + uint16_t fat32Flags; + /** + * FAT32 version. High byte is major revision number. + * Low byte is minor revision number. Only 0.0 define. + */ + uint16_t fat32Version; + /** + * Cluster number of the first cluster of the root directory for FAT32. + * This usually 2 but not required to be 2. + */ + uint32_t fat32RootCluster; + /** + * Sector number of FSINFO structure in the reserved area of the + * FAT32 volume. Usually 1. + */ + uint16_t fat32FSInfo; + /** + * If nonzero, indicates the sector number in the reserved area + * of the volume of a copy of the boot record. Usually 6. + * No value other than 6 is recommended. + */ + uint16_t fat32BackBootBlock; + /** + * Reserved for future expansion. Code that formats FAT32 volumes + * should always set all of the bytes of this field to 0. + */ + uint8_t fat32Reserved[12]; + /** + * Related to the BIOS physical drive number. Floppy drives are + * identified as 0x00 and physical hard disks are identified as + * 0x80, regardless of the number of physical disk drives. + * Typically, this value is set prior to issuing an INT 13h BIOS + * call to specify the device to access. The value is only + * relevant if the device is a boot device. + */ + uint8_t driveNumber; + /** used by Windows NT - should be zero for FAT */ + uint8_t reserved1; + /** 0X29 if next three fields are valid */ + uint8_t bootSignature; + /** + * A random serial number created when formatting a disk, + * which helps to distinguish between disks. + * Usually generated by combining date and time. + */ + uint32_t volumeSerialNumber; + /** + * A field once used to store the volume label. The volume label + * is now stored as a special file in the root directory. + */ + char volumeLabel[11]; + /** + * A text field with a value of FAT32. + */ + char fileSystemType[8]; + /** X86 boot code */ + uint8_t bootCode[420]; + /** must be 0X55 */ + uint8_t bootSectorSig0; + /** must be 0XAA */ + uint8_t bootSectorSig1; +}; +/** Type name for FAT32 Boot Sector */ +typedef struct fat32_boot fat32_boot_t; +//------------------------------------------------------------------------------ +/** Lead signature for a FSINFO sector */ +uint32_t const FSINFO_LEAD_SIG = 0x41615252; +/** Struct signature for a FSINFO sector */ +uint32_t const FSINFO_STRUCT_SIG = 0x61417272; +/** + * \struct fat32_fsinfo + * + * \brief FSINFO sector for a FAT32 volume. + * + */ +struct fat32_fsinfo { + /** must be 0X52, 0X52, 0X61, 0X41 */ + uint32_t leadSignature; + /** must be zero */ + uint8_t reserved1[480]; + /** must be 0X72, 0X72, 0X41, 0X61 */ + uint32_t structSignature; + /** + * Contains the last known free cluster count on the volume. + * If the value is 0xFFFFFFFF, then the free count is unknown + * and must be computed. Any other value can be used, but is + * not necessarily correct. It should be range checked at least + * to make sure it is <= volume cluster count. + */ + uint32_t freeCount; + /** + * This is a hint for the FAT driver. It indicates the cluster + * number at which the driver should start looking for free clusters. + * If the value is 0xFFFFFFFF, then there is no hint and the driver + * should start looking at cluster 2. + */ + uint32_t nextFree; + /** must be zero */ + uint8_t reserved2[12]; + /** must be 0X00, 0X00, 0X55, 0XAA */ + uint8_t tailSignature[4]; +}; +/** Type name for FAT32 FSINFO Sector */ +typedef struct fat32_fsinfo fat32_fsinfo_t; +//------------------------------------------------------------------------------ +// End Of Chain values for FAT entries +/** FAT12 end of chain value used by Microsoft. */ +uint16_t const FAT12EOC = 0XFFF; +/** Minimum value for FAT12 EOC. Use to test for EOC. */ +uint16_t const FAT12EOC_MIN = 0XFF8; +/** FAT16 end of chain value used by Microsoft. */ +uint16_t const FAT16EOC = 0XFFFF; +/** Minimum value for FAT16 EOC. Use to test for EOC. */ +uint16_t const FAT16EOC_MIN = 0XFFF8; +/** FAT32 end of chain value used by Microsoft. */ +uint32_t const FAT32EOC = 0X0FFFFFFF; +/** Minimum value for FAT32 EOC. Use to test for EOC. */ +uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; +/** Mask a for FAT32 entry. Entries are 28 bits. */ +uint32_t const FAT32MASK = 0X0FFFFFFF; +//------------------------------------------------------------------------------ +/** + * \struct directoryEntry + * \brief FAT short directory entry + * + * Short means short 8.3 name, not the entry size. + * + * Date Format. A FAT directory entry date stamp is a 16-bit field that is + * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the + * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the + * 16-bit word): + * + * Bits 9-15: Count of years from 1980, valid value range 0-127 + * inclusive (1980-2107). + * + * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. + * + * Bits 0-4: Day of month, valid value range 1-31 inclusive. + * + * Time Format. A FAT directory entry time stamp is a 16-bit field that has + * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the + * 16-bit word, bit 15 is the MSB of the 16-bit word). + * + * Bits 11-15: Hours, valid value range 0-23 inclusive. + * + * Bits 5-10: Minutes, valid value range 0-59 inclusive. + * + * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). + * + * The valid time range is from Midnight 00:00:00 to 23:59:58. + */ +struct directoryEntry { + /** Short 8.3 name. + * + * The first eight bytes contain the file name with blank fill. + * The last three bytes contain the file extension with blank fill. + */ + uint8_t name[11]; + /** Entry attributes. + * + * The upper two bits of the attribute byte are reserved and should + * always be set to 0 when a file is created and never modified or + * looked at after that. See defines that begin with DIR_ATT_. + */ + uint8_t attributes; + /** + * Reserved for use by Windows NT. Set value to 0 when a file is + * created and never modify or look at it after that. + */ + uint8_t reservedNT; + /** + * The granularity of the seconds part of creationTime is 2 seconds + * so this field is a count of tenths of a second and its valid + * value range is 0-199 inclusive. (WHG note - seems to be hundredths) + */ + uint8_t creationTimeTenths; + /** Time file was created. */ + uint16_t creationTime; + /** Date file was created. */ + uint16_t creationDate; + /** + * Last access date. Note that there is no last access time, only + * a date. This is the date of last read or write. In the case of + * a write, this should be set to the same date as lastWriteDate. + */ + uint16_t lastAccessDate; + /** + * High word of this entry's first cluster number (always 0 for a + * FAT12 or FAT16 volume). + */ + uint16_t firstClusterHigh; + /** Time of last write. File creation is considered a write. */ + uint16_t lastWriteTime; + /** Date of last write. File creation is considered a write. */ + uint16_t lastWriteDate; + /** Low word of this entry's first cluster number. */ + uint16_t firstClusterLow; + /** 32-bit unsigned holding this file's size in bytes. */ + uint32_t fileSize; +}; +//------------------------------------------------------------------------------ +// Definitions for directory entries +// +/** Type name for directoryEntry */ +typedef struct directoryEntry dir_t; +/** escape for name[0] = 0XE5 */ +uint8_t const DIR_NAME_0XE5 = 0X05; +/** name[0] value for entry that is free after being "deleted" */ +uint8_t const DIR_NAME_DELETED = 0XE5; +/** name[0] value for entry that is free and no allocated entries follow */ +uint8_t const DIR_NAME_FREE = 0X00; +/** file is read-only */ +uint8_t const DIR_ATT_READ_ONLY = 0X01; +/** File should hidden in directory listings */ +uint8_t const DIR_ATT_HIDDEN = 0X02; +/** Entry is for a system file */ +uint8_t const DIR_ATT_SYSTEM = 0X04; +/** Directory entry contains the volume label */ +uint8_t const DIR_ATT_VOLUME_ID = 0X08; +/** Entry is for a directory */ +uint8_t const DIR_ATT_DIRECTORY = 0X10; +/** Old DOS archive bit for backup support */ +uint8_t const DIR_ATT_ARCHIVE = 0X20; +/** Test value for long name entry. Test is + (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ +uint8_t const DIR_ATT_LONG_NAME = 0X0F; +/** Test mask for long name entry */ +uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; +/** defined attribute bits */ +uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; +/** Directory entry is part of a long name + * \param[in] dir Pointer to a directory entry. + * + * \return true if the entry is for part of a long name else false. + */ +static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { + return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; +} +/** Mask for file/subdirectory tests */ +uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); +/** Directory entry is for a file + * \param[in] dir Pointer to a directory entry. + * + * \return true if the entry is for a normal file else false. + */ +static inline uint8_t DIR_IS_FILE(const dir_t* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; +} +/** Directory entry is for a subdirectory + * \param[in] dir Pointer to a directory entry. + * + * \return true if the entry is for a subdirectory else false. + */ +static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; +} +/** Directory entry is for a file or subdirectory + * \param[in] dir Pointer to a directory entry. + * + * \return true if the entry is for a normal file or subdirectory else false. + */ +static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { + return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; +} +#endif // SdFatStructs_h diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp new file mode 100644 index 0000000000..1870980b1d --- /dev/null +++ b/Marlin/SdFatUtil.cpp @@ -0,0 +1,74 @@ +/* Arduino SdFat Library + * Copyright (C) 2008 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#include "SdFatUtil.h" +//------------------------------------------------------------------------------ +/** Amount of free RAM + * \return The number of free bytes. + */ +int SdFatUtil::FreeRam() { + extern int __bss_end; + extern int* __brkval; + int free_memory; + if (reinterpret_cast(__brkval) == 0) { + // if no heap use from end of bss section + free_memory = reinterpret_cast(&free_memory) + - reinterpret_cast(&__bss_end); + } else { + // use from top of stack to heap + free_memory = reinterpret_cast(&free_memory) + - reinterpret_cast(__brkval); + } + return free_memory; +} +//------------------------------------------------------------------------------ +/** %Print a string in flash memory. + * + * \param[in] pr Print object for output. + * \param[in] str Pointer to string stored in flash memory. + */ +void SdFatUtil::print_P(Print* pr, PGM_P str) { + for (uint8_t c; (c = pgm_read_byte(str)); str++) pr->write(c); +} +//------------------------------------------------------------------------------ +/** %Print a string in flash memory followed by a CR/LF. + * + * \param[in] pr Print object for output. + * \param[in] str Pointer to string stored in flash memory. + */ +void SdFatUtil::println_P(Print* pr, PGM_P str) { + print_P(pr, str); + pr->println(); +} +//------------------------------------------------------------------------------ +/** %Print a string in flash memory to Serial. + * + * \param[in] str Pointer to string stored in flash memory. + */ +void SdFatUtil::SerialPrint_P(PGM_P str) { + print_P(&Serial, str); +} +//------------------------------------------------------------------------------ +/** %Print a string in flash memory to Serial followed by a CR/LF. + * + * \param[in] str Pointer to string stored in flash memory. + */ +void SdFatUtil::SerialPrintln_P(PGM_P str) { + println_P(&Serial, str); +} diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index 8bf90483d4..b4112aa2d9 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -21,50 +21,26 @@ #define SdFatUtil_h /** * \file - * Useful utility functions. + * \brief Useful utility functions. */ -#include #include +#if ARDUINO < 100 +#include +#else // ARDUINO +#include +#endif // ARDUINO /** Store and print a string in flash memory.*/ #define PgmPrint(x) SerialPrint_P(PSTR(x)) /** Store and print a string in flash memory followed by a CR/LF.*/ #define PgmPrintln(x) SerialPrintln_P(PSTR(x)) -/** Defined so doxygen works for function definitions. */ -#define NOINLINE __attribute__((noinline)) -//------------------------------------------------------------------------------ -/** Return the number of bytes currently free in RAM. */ -static int FreeRam(void) { - extern int __bss_end; - extern int* __brkval; - int free_memory; - if (reinterpret_cast(__brkval) == 0) { - // if no heap use from end of bss section - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(&__bss_end); - } else { - // use from top of stack to heap - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(__brkval); - } - return free_memory; -} -//------------------------------------------------------------------------------ -/** - * %Print a string in flash memory to the serial port. - * - * \param[in] str Pointer to string stored in flash memory. - */ -static NOINLINE void SerialPrint_P(PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.print(c); -} -//------------------------------------------------------------------------------ -/** - * %Print a string in flash memory followed by a CR/LF. - * - * \param[in] str Pointer to string stored in flash memory. - */ -static NOINLINE void SerialPrintln_P(PGM_P str) { - SerialPrint_P(str); - Serial.println(); + +namespace SdFatUtil { + int FreeRam(); + void print_P(Print* pr, PGM_P str); + void println_P(Print* pr, PGM_P str); + void SerialPrint_P(PGM_P str); + void SerialPrintln_P(PGM_P str); } + +using namespace SdFatUtil; // NOLINT #endif // #define SdFatUtil_h diff --git a/Marlin/SdFatmainpage.h b/Marlin/SdFatmainpage.h deleted file mode 100644 index 73b3b63bd4..0000000000 --- a/Marlin/SdFatmainpage.h +++ /dev/null @@ -1,202 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ - -/** -\mainpage Arduino SdFat Library -
Copyright © 2009 by William Greiman -
- -\section Intro Introduction -The Arduino SdFat Library is a minimal implementation of FAT16 and FAT32 -file systems on SD flash memory cards. Standard SD and high capacity -SDHC cards are supported. - -The SdFat only supports short 8.3 names. - -The main classes in SdFat are Sd2Card, SdVolume, and SdFile. - -The Sd2Card class supports access to standard SD cards and SDHC cards. Most -applications will only need to call the Sd2Card::init() member function. - -The SdVolume class supports FAT16 and FAT32 partitions. Most applications -will only need to call the SdVolume::init() member function. - -The SdFile class provides file access functions such as open(), read(), -remove(), write(), close() and sync(). This class supports access to the root -directory and subdirectories. - -A number of example are provided in the SdFat/examples folder. These were -developed to test SdFat and illustrate its use. - -SdFat was developed for high speed data recording. SdFat was used to implement -an audio record/play class, WaveRP, for the Adafruit Wave Shield. This -application uses special Sd2Card calls to write to contiguous files in raw mode. -These functions reduce write latency so that audio can be recorded with the -small amount of RAM in the Arduino. - -\section SDcard SD\SDHC Cards - -Arduinos access SD cards using the cards SPI protocol. PCs, Macs, and -most consumer devices use the 4-bit parallel SD protocol. A card that -functions well on A PC or Mac may not work well on the Arduino. - -Most cards have good SPI read performance but cards vary widely in SPI -write performance. Write performance is limited by how efficiently the -card manages internal erase/remapping operations. The Arduino cannot -optimize writes to reduce erase operations because of its limit RAM. - -SanDisk cards generally have good write performance. They seem to have -more internal RAM buffering than other cards and therefore can limit -the number of flash erase operations that the Arduino forces due to its -limited RAM. - -\section Hardware Hardware Configuration - -SdFat was developed using an - Adafruit Industries - Wave Shield. - -The hardware interface to the SD card should not use a resistor based level -shifter. SdFat sets the SPI bus frequency to 8 MHz which results in signal -rise times that are too slow for the edge detectors in many newer SD card -controllers when resistor voltage dividers are used. - -The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the -74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield -uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the -74LCX245. - -If you are using a resistor based level shifter and are having problems try -setting the SPI bus frequency to 4 MHz. This can be done by using -card.init(SPI_HALF_SPEED) to initialize the SD card. - -\section comment Bugs and Comments - -If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net. - -\section SdFatClass SdFat Usage - -SdFat uses a slightly restricted form of short names. -Only printable ASCII characters are supported. No characters with code point -values greater than 127 are allowed. Space is not allowed even though space -was allowed in the API of early versions of DOS. - -Short names are limited to 8 characters followed by an optional period (.) -and extension of up to 3 characters. The characters may be any combination -of letters and digits. The following special characters are also allowed: - -$ % ' - _ @ ~ ` ! ( ) { } ^ # & - -Short names are always converted to upper case and their original case -value is lost. - -\note - The Arduino Print class uses character -at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink -function to control when data is written to the SD card. - -\par -An application which writes to a file using \link Print::print() print()\endlink, -\link Print::println() println() \endlink -or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink -at the appropriate time to force data and directory information to be written -to the SD Card. Data and directory information are also written to the SD card -when \link SdFile::close() close() \endlink is called. - -\par -Applications must use care calling \link SdFile::sync() sync() \endlink -since 2048 bytes of I/O is required to update file and -directory information. This includes writing the current data block, reading -the block that contains the directory entry for update, writing the directory -block back and reading back the current data block. - -It is possible to open a file with two or more instances of SdFile. A file may -be corrupted if data is written to the file by more than one instance of SdFile. - -\section HowTo How to format SD Cards as FAT Volumes - -You should use a freshly formatted SD card for best performance. FAT -file systems become slower if many files have been created and deleted. -This is because the directory entry for a deleted file is marked as deleted, -but is not deleted. When a new file is created, these entries must be scanned -before creating the file, a flaw in the FAT design. Also files can become -fragmented which causes reads and writes to be slower. - -Microsoft operating systems support removable media formatted with a -Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector -in block zero. - -Microsoft operating systems expect MBR formatted removable media -to have only one partition. The first partition should be used. - -Microsoft operating systems do not support partitioning SD flash cards. -If you erase an SD card with a program like KillDisk, Most versions of -Windows will format the card as a super floppy. - -The best way to restore an SD card's format is to use SDFormatter -which can be downloaded from: - -http://www.sdcard.org/consumers/formatter/ - -SDFormatter aligns flash erase boundaries with file -system structures which reduces write latency and file system overhead. - -SDFormatter does not have an option for FAT type so it may format -small cards as FAT12. - -After the MBR is restored by SDFormatter you may need to reformat small -cards that have been formatted FAT12 to force the volume type to be FAT16. - -If you reformat the SD card with an OS utility, choose a cluster size that -will result in: - -4084 < CountOfClusters && CountOfClusters < 65525 - -The volume will then be FAT16. - -If you are formatting an SD card on OS X or Linux, be sure to use the first -partition. Format this partition with a cluster count in above range. - -\section References References - -Adafruit Industries: - -http://www.adafruit.com/ - -http://www.ladyada.net/make/waveshield/ - -The Arduino site: - -http://www.arduino.cc/ - -For more information about FAT file systems see: - -http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx - -For information about using SD cards as SPI devices see: - -http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf - -The ATmega328 datasheet: - -http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf - - - */ diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index e7e23d1db7..0496a6ab9f 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -17,1096 +17,18 @@ * along with the Arduino SdFat Library. If not, see * . */ -#include "SdFat.h" -#include -#include -//------------------------------------------------------------------------------ -// callback function for date/time -void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL; - -#if ALLOW_DEPRECATED_FUNCTIONS -// suppress cpplint warnings with NOLINT comment -void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL; // NOLINT -#endif // ALLOW_DEPRECATED_FUNCTIONS -//------------------------------------------------------------------------------ -// add a cluster to a file -uint8_t SdFile::addCluster() { - if (!vol_->allocContiguous(1, &curCluster_)) return false; - - // if first cluster of file link to directory entry - if (firstCluster_ == 0) { - firstCluster_ = curCluster_; - flags_ |= F_FILE_DIR_DIRTY; - } - return true; -} -//------------------------------------------------------------------------------ -// Add a cluster to a directory file and zero the cluster. -// return with first block of cluster in the cache -uint8_t SdFile::addDirCluster(void) { - if (!addCluster()) return false; - - // zero data in cluster insure first cluster is in cache - uint32_t block = vol_->clusterStartBlock(curCluster_); - for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) { - if (!SdVolume::cacheZeroBlock(block + i - 1)) return false; - } - // Increase directory file size by cluster size - fileSize_ += 512UL << vol_->clusterSizeShift_; - return true; -} -//------------------------------------------------------------------------------ -// cache a file's directory entry -// return pointer to cached entry or null for failure -dir_t* SdFile::cacheDirEntry(uint8_t action) { - if (!SdVolume::cacheRawBlock(dirBlock_, action)) return NULL; - return SdVolume::cacheBuffer_.dir + dirIndex_; -} -//------------------------------------------------------------------------------ -/** - * Close a file and force cached data and directory information - * to be written to the storage device. +#include "SdFile.h" +/** Create a file object and open it in the current working directory. * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include no file is open or an I/O error. - */ -uint8_t SdFile::close(void) { - if (!sync())return false; - type_ = FAT_FILE_TYPE_CLOSED; - return true; -} -//------------------------------------------------------------------------------ -/** - * Check for contiguous file and return its raw block range. - * - * \param[out] bgnBlock the first block address for the file. - * \param[out] endBlock the last block address for the file. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include file is not contiguous, file has zero length - * or an I/O error occurred. - */ -uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { - // error if no blocks - if (firstCluster_ == 0) return false; - - for (uint32_t c = firstCluster_; ; c++) { - uint32_t next; - if (!vol_->fatGet(c, &next)) return false; - - // check for contiguous - if (next != (c + 1)) { - // error if not end of chain - if (!vol_->isEOC(next)) return false; - *bgnBlock = vol_->clusterStartBlock(firstCluster_); - *endBlock = vol_->clusterStartBlock(c) - + vol_->blocksPerCluster_ - 1; - return true; - } - } -} -//------------------------------------------------------------------------------ -/** - * Create and open a new contiguous file of a specified size. - * - * \note This function only supports short DOS 8.3 names. - * See open() for more information. - * - * \param[in] dirFile The directory where the file will be created. - * \param[in] fileName A valid DOS 8.3 file name. - * \param[in] size The desired file size. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include \a fileName contains - * an invalid DOS 8.3 file name, the FAT volume has not been initialized, - * a file is already open, the file already exists, the root - * directory is full or an I/O error. - * - */ -uint8_t SdFile::createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size) { - // don't allow zero length file - if (size == 0) return false; - if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) return false; - - // calculate number of clusters needed - uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; - - // allocate clusters - if (!vol_->allocContiguous(count, &firstCluster_)) { - remove(); - return false; - } - fileSize_ = size; - - // insure sync() will update dir entry - flags_ |= F_FILE_DIR_DIRTY; - return sync(); -} -//------------------------------------------------------------------------------ -/** - * Return a files directory entry - * - * \param[out] dir Location for return of the files directory entry. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::dirEntry(dir_t* dir) { - // make sure fields on SD are correct - if (!sync()) return false; - - // read entry - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); - if (!p) return false; - - // copy to caller's struct - memcpy(dir, p, sizeof(dir_t)); - return true; -} -//------------------------------------------------------------------------------ -/** - * Format the name field of \a dir into the 13 byte array - * \a name in standard 8.3 short name format. - * - * \param[in] dir The directory structure containing the name. - * \param[out] name A 13 byte char array for the formatted name. - */ -void SdFile::dirName(const dir_t& dir, char* name) { - uint8_t j = 0; - for (uint8_t i = 0; i < 11; i++) { - if (dir.name[i] == ' ')continue; - if (i == 8) name[j++] = '.'; - name[j++] = dir.name[i]; - } - name[j] = 0; -} -//------------------------------------------------------------------------------ -/** List directory contents to Serial. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - * - * \param[in] indent Amount of space before file name. Used for recursive - * list to indicate subdirectory level. - */ -void SdFile::ls(uint8_t flags, uint8_t indent) { - dir_t* p; - - rewind(); - while ((p = readDirCache())) { - // done if past last used entry - if (p->name[0] == DIR_NAME_FREE) break; - - // skip deleted entry and entries for . and .. - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; - - // only list subdirectories and files - if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; - - // print any indent spaces - for (int8_t i = 0; i < indent; i++) Serial.print(' '); - - // print file name with possible blank fill - printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0); - - // print modify date/time if requested - if (flags & LS_DATE) { - printFatDate(p->lastWriteDate); - Serial.print(' '); - printFatTime(p->lastWriteTime); - } - // print size if requested - if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) { - Serial.print(' '); - Serial.print(p->fileSize); - } - Serial.println(); - - // list subdirectory content if requested - if ((flags & LS_R) && DIR_IS_SUBDIR(p)) { - uint16_t index = curPosition()/32 - 1; - SdFile s; - if (s.open(this, index, O_READ)) s.ls(flags, indent + 2); - seekSet(32 * (index + 1)); - } - } -} -//------------------------------------------------------------------------------ -// format directory name field from a 8.3 name string -uint8_t SdFile::make83Name(const char* str, uint8_t* name) { - uint8_t c; - uint8_t n = 7; // max index for part before dot - uint8_t i = 0; - // blank fill name and extension - while (i < 11) name[i++] = ' '; - i = 0; - while ((c = *str++) != '\0') { - if (c == '.') { - if (n == 10) return false; // only one dot allowed - n = 10; // max index for full 8.3 name - i = 8; // place for extension - } else { - // illegal FAT characters - PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); - uint8_t b; - while ((b = pgm_read_byte(p++))) if (b == c) return false; - // check size and only allow ASCII printable characters - if (i > n || c < 0X21 || c > 0X7E)return false; - // only upper case allowed in 8.3 names - convert lower to upper - name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); - } - } - // must have a file name, extension is optional - return name[0] != ' '; -} -//------------------------------------------------------------------------------ -/** Make a new directory. - * - * \param[in] dir An open SdFat instance for the directory that will containing - * the new directory. - * - * \param[in] dirName A valid 8.3 DOS name for the new directory. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include this SdFile is already open, \a dir is not a - * directory, \a dirName is invalid or already exists in \a dir. - */ -uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { - dir_t d; - - // create a normal file - if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) return false; - - // convert SdFile to directory - flags_ = O_READ; - type_ = FAT_FILE_TYPE_SUBDIR; - - // allocate and zero first cluster - if (!addDirCluster())return false; - - // force entry to SD - if (!sync()) return false; - - // cache entry - should already be in cache due to sync() call - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!p) return false; - - // change directory entry attribute - p->attributes = DIR_ATT_DIRECTORY; - - // make entry for '.' - memcpy(&d, p, sizeof(d)); - for (uint8_t i = 1; i < 11; i++) d.name[i] = ' '; - d.name[0] = '.'; - - // cache block for '.' and '..' - uint32_t block = vol_->clusterStartBlock(firstCluster_); - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false; - - // copy '.' to block - memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d)); - - // make entry for '..' - d.name[1] = '.'; - if (dir->isRoot()) { - d.firstClusterLow = 0; - d.firstClusterHigh = 0; - } else { - d.firstClusterLow = dir->firstCluster_ & 0XFFFF; - d.firstClusterHigh = dir->firstCluster_ >> 16; - } - // copy '..' to block - memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d)); - - // set position after '..' - curPosition_ = 2 * sizeof(d); - - // write first block - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - * Open a file or directory by name. - * - * \param[in] dirFile An open SdFat instance for the directory containing the - * file to be opened. - * - * \param[in] fileName A valid 8.3 DOS name for a file to be opened. + * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. * * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive - * OR of flags from the following list - * - * O_READ - Open for reading. - * - * O_RDONLY - Same as O_READ. - * - * O_WRITE - Open for writing. - * - * O_WRONLY - Same as O_WRITE. - * - * O_RDWR - Open for reading and writing. - * - * O_APPEND - If set, the file offset shall be set to the end of the - * file prior to each write. - * - * O_CREAT - If the file exists, this flag has no effect except as noted - * under O_EXCL below. Otherwise, the file shall be created - * - * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. - * - * O_SYNC - Call sync() after each write. This flag should not be used with - * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. - * These functions do character at a time writes so sync() will be called - * after each byte. - * - * O_TRUNC - If the file exists and is a regular file, and the file is - * successfully opened and is not read only, its length shall be truncated to 0. - * - * \note Directory files must be opened read only. Write and truncation is - * not allowed for directory files. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include this SdFile is already open, \a difFile is not - * a directory, \a fileName is invalid, the file does not exist - * or can't be opened in the access mode specified by oflag. + * OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t). */ -uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { - uint8_t dname[11]; - dir_t* p; - - // error if already open - if (isOpen())return false; - - if (!make83Name(fileName, dname)) return false; - vol_ = dirFile->vol_; - dirFile->rewind(); - - // bool for empty entry found - uint8_t emptyFound = false; - - // search for file - while (dirFile->curPosition_ < dirFile->fileSize_) { - uint8_t index = 0XF & (dirFile->curPosition_ >> 5); - p = dirFile->readDirCache(); - if (p == NULL) return false; - - if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { - // remember first empty slot - if (!emptyFound) { - emptyFound = true; - dirIndex_ = index; - dirBlock_ = SdVolume::cacheBlockNumber_; - } - // done if no entries follow - if (p->name[0] == DIR_NAME_FREE) break; - } else if (!memcmp(dname, p->name, 11)) { - // don't open existing file if O_CREAT and O_EXCL - if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; - - // open found file - return openCachedEntry(0XF & index, oflag); - } - } - // only create file if O_CREAT and O_WRITE - if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false; - - // cache found slot or add cluster if end of file - if (emptyFound) { - p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!p) return false; - } else { - if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false; - - // add and zero cluster for dirFile - first cluster is in cache for write - if (!dirFile->addDirCluster()) return false; - - // use first entry in cluster - dirIndex_ = 0; - p = SdVolume::cacheBuffer_.dir; - } - // initialize as empty file - memset(p, 0, sizeof(dir_t)); - memcpy(p->name, dname, 11); - - // set timestamps - if (dateTime_) { - // call user function - dateTime_(&p->creationDate, &p->creationTime); - } else { - // use default date/time - p->creationDate = FAT_DEFAULT_DATE; - p->creationTime = FAT_DEFAULT_TIME; - } - p->lastAccessDate = p->creationDate; - p->lastWriteDate = p->creationDate; - p->lastWriteTime = p->creationTime; - - // force write of entry to SD - if (!SdVolume::cacheFlush()) return false; - - // open entry in cache - return openCachedEntry(dirIndex_, oflag); +SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) { } //------------------------------------------------------------------------------ -/** - * Open a file by index. - * - * \param[in] dirFile An open SdFat instance for the directory. - * - * \param[in] index The \a index of the directory entry for the file to be - * opened. The value for \a index is (directory file position)/32. - * - * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive - * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. - * - * See open() by fileName for definition of flags and return values. - * - */ -uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { - // error if already open - if (isOpen())return false; - - // don't open existing file if O_CREAT and O_EXCL - user call error - if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false; - - vol_ = dirFile->vol_; - - // seek to location of entry - if (!dirFile->seekSet(32 * index)) return false; - - // read entry into cache - dir_t* p = dirFile->readDirCache(); - if (p == NULL) return false; - - // error if empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_FREE || - p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { - return false; - } - // open cached entry - return openCachedEntry(index & 0XF, oflag); -} -//------------------------------------------------------------------------------ -// open a cached directory entry. Assumes vol_ is initializes -uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { - // location of entry in cache - dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex; - - // write or truncate is an error for a directory or read-only file - if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { - if (oflag & (O_WRITE | O_TRUNC)) return false; - } - // remember location of directory entry on SD - dirIndex_ = dirIndex; - dirBlock_ = SdVolume::cacheBlockNumber_; - - // copy first cluster number for directory fields - firstCluster_ = (uint32_t)p->firstClusterHigh << 16; - firstCluster_ |= p->firstClusterLow; - - // make sure it is a normal file or subdirectory - if (DIR_IS_FILE(p)) { - fileSize_ = p->fileSize; - type_ = FAT_FILE_TYPE_NORMAL; - } else if (DIR_IS_SUBDIR(p)) { - if (!vol_->chainSize(firstCluster_, &fileSize_)) return false; - type_ = FAT_FILE_TYPE_SUBDIR; - } else { - return false; - } - // save open flags for read/write - flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND); - - // set to start of file - curCluster_ = 0; - curPosition_ = 0; - - // truncate file to zero length if requested - if (oflag & O_TRUNC) return truncate(0); - return true; -} -//------------------------------------------------------------------------------ -/** - * Open a volume's root directory. - * - * \param[in] vol The FAT volume containing the root directory to be opened. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the FAT volume has not been initialized - * or it a FAT12 volume. - */ -uint8_t SdFile::openRoot(SdVolume* vol) { - // error if file is already open - if (isOpen()) return false; - - if (vol->fatType() == 16) { - type_ = FAT_FILE_TYPE_ROOT16; - firstCluster_ = 0; - fileSize_ = 32 * vol->rootDirEntryCount(); - } else if (vol->fatType() == 32) { - type_ = FAT_FILE_TYPE_ROOT32; - firstCluster_ = vol->rootDirStart(); - if (!vol->chainSize(firstCluster_, &fileSize_)) return false; - } else { - // volume is not initialized or FAT12 - return false; - } - vol_ = vol; - // read only - flags_ = O_READ; - - // set to start of file - curCluster_ = 0; - curPosition_ = 0; - - // root has no directory entry - dirBlock_ = 0; - dirIndex_ = 0; - return true; -} -//------------------------------------------------------------------------------ -/** %Print the name field of a directory entry in 8.3 format to Serial. - * - * \param[in] dir The directory structure containing the name. - * \param[in] width Blank fill name if length is less than \a width. - */ -void SdFile::printDirName(const dir_t& dir, uint8_t width) { - uint8_t w = 0; - for (uint8_t i = 0; i < 11; i++) { - if (dir.name[i] == ' ')continue; - if (i == 8) { - Serial.print('.'); - w++; - } - Serial.print(dir.name[i]); - w++; - } - if (DIR_IS_SUBDIR(&dir)) { - Serial.print('/'); - w++; - } - while (w < width) { - Serial.print(' '); - w++; - } -} -//------------------------------------------------------------------------------ -/** %Print a directory date field to Serial. - * - * Format is yyyy-mm-dd. - * - * \param[in] fatDate The date field from a directory entry. - */ -void SdFile::printFatDate(uint16_t fatDate) { - Serial.print(FAT_YEAR(fatDate)); - Serial.print('-'); - printTwoDigits(FAT_MONTH(fatDate)); - Serial.print('-'); - printTwoDigits(FAT_DAY(fatDate)); -} -//------------------------------------------------------------------------------ -/** %Print a directory time field to Serial. - * - * Format is hh:mm:ss. - * - * \param[in] fatTime The time field from a directory entry. - */ -void SdFile::printFatTime(uint16_t fatTime) { - printTwoDigits(FAT_HOUR(fatTime)); - Serial.print(':'); - printTwoDigits(FAT_MINUTE(fatTime)); - Serial.print(':'); - printTwoDigits(FAT_SECOND(fatTime)); -} -//------------------------------------------------------------------------------ -/** %Print a value as two digits to Serial. - * - * \param[in] v Value to be printed, 0 <= \a v <= 99 - */ -void SdFile::printTwoDigits(uint8_t v) { - char str[3]; - str[0] = '0' + v/10; - str[1] = '0' + v % 10; - str[2] = 0; - Serial.print(str); -} -//------------------------------------------------------------------------------ -/** - * Read data from a file starting at the current position. - * - * \param[out] buf Pointer to the location that will receive the data. - * - * \param[in] nbyte Maximum number of bytes to read. - * - * \return For success read() returns the number of bytes read. - * A value less than \a nbyte, including zero, will be returned - * if end of file is reached. - * If an error occurs, read() returns -1. Possible errors include - * read() called before a file has been opened, corrupt file system - * or an I/O error occurred. - */ -int16_t SdFile::read(void* buf, uint16_t nbyte) { - uint8_t* dst = reinterpret_cast(buf); - - // error if not open or write only - if (!isOpen() || !(flags_ & O_READ)) return -1; - - // max bytes left in file - if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_; - - // amount left to read - uint16_t toRead = nbyte; - while (toRead > 0) { - uint32_t block; // raw device block number - uint16_t offset = curPosition_ & 0X1FF; // offset in block - if (type_ == FAT_FILE_TYPE_ROOT16) { - block = vol_->rootDirStart() + (curPosition_ >> 9); - } else { - uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); - if (offset == 0 && blockOfCluster == 0) { - // start of new cluster - if (curPosition_ == 0) { - // use first cluster in file - curCluster_ = firstCluster_; - } else { - // get next cluster from FAT - if (!vol_->fatGet(curCluster_, &curCluster_)) return -1; - } - } - block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; - } - uint16_t n = toRead; - - // amount to be read from current block - if (n > (512 - offset)) n = 512 - offset; - - // no buffering needed if n == 512 or user requests no buffering - if ((unbufferedRead() || n == 512) && - block != SdVolume::cacheBlockNumber_) { - if (!vol_->readData(block, offset, n, dst)) return -1; - dst += n; - } else { - // read block to cache and copy data to caller - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1; - uint8_t* src = SdVolume::cacheBuffer_.data + offset; - uint8_t* end = src + n; - while (src != end) *dst++ = *src++; - } - curPosition_ += n; - toRead -= n; - } - return nbyte; -} -//------------------------------------------------------------------------------ -/** - * Read the next directory entry from a directory file. - * - * \param[out] dir The dir_t struct that will receive the data. - * - * \return For success readDir() returns the number of bytes read. - * A value of zero will be returned if end of file is reached. - * If an error occurs, readDir() returns -1. Possible errors include - * readDir() called before a directory has been opened, this is not - * a directory file or an I/O error occurred. - */ -int8_t SdFile::readDir(dir_t* dir) { - int8_t n; - // if not a directory file or miss-positioned return an error - if (!isDir() || (0X1F & curPosition_)) return -1; - - while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) { - // last entry if DIR_NAME_FREE - if (dir->name[0] == DIR_NAME_FREE) break; - // skip empty entries and entry for . and .. - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; - // return if normal file or subdirectory - if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; - } - // error, end of file, or past last entry - return n < 0 ? -1 : 0; -} -//------------------------------------------------------------------------------ -// Read next directory entry into the cache -// Assumes file is correctly positioned -dir_t* SdFile::readDirCache(void) { - // error if not directory - if (!isDir()) return NULL; - - // index of entry in cache - uint8_t i = (curPosition_ >> 5) & 0XF; - - // use read to locate and cache block - if (read() < 0) return NULL; - - // advance to next entry - curPosition_ += 31; - - // return pointer to entry - return (SdVolume::cacheBuffer_.dir + i); -} -//------------------------------------------------------------------------------ -/** - * Remove a file. - * - * The directory entry and all data for the file are deleted. - * - * \note This function should not be used to delete the 8.3 version of a - * file that has a long name. For example if a file has the long name - * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the file read-only, is a directory, - * or an I/O error occurred. - */ -uint8_t SdFile::remove(void) { - // free any clusters - will fail if read-only or directory - if (!truncate(0)) return false; - - // cache directory entry - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) return false; - - // mark entry deleted - d->name[0] = DIR_NAME_DELETED; - - // set this SdFile closed - type_ = FAT_FILE_TYPE_CLOSED; - - // write entry to SD - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - * Remove a file. - * - * The directory entry and all data for the file are deleted. - * - * \param[in] dirFile The directory that contains the file. - * \param[in] fileName The name of the file to be removed. - * - * \note This function should not be used to delete the 8.3 version of a - * file that has a long name. For example if a file has the long name - * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the file is a directory, is read only, - * \a dirFile is not a directory, \a fileName is not found - * or an I/O error occurred. - */ -uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) { - SdFile file; - if (!file.open(dirFile, fileName, O_WRITE)) return false; - return file.remove(); -} -//------------------------------------------------------------------------------ -/** Remove a directory file. - * - * The directory file will be removed only if it is empty and is not the - * root directory. rmDir() follows DOS and Windows and ignores the - * read-only attribute for the directory. - * - * \note This function should not be used to delete the 8.3 version of a - * directory that has a long name. For example if a directory has the - * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include the file is not a directory, is the root - * directory, is not empty, or an I/O error occurred. - */ -uint8_t SdFile::rmDir(void) { - // must be open subdirectory - if (!isSubDir()) return false; - - rewind(); - - // make sure directory is empty - while (curPosition_ < fileSize_) { - dir_t* p = readDirCache(); - if (p == NULL) return false; - // done if past last used entry - if (p->name[0] == DIR_NAME_FREE) break; - // skip empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; - // error not empty - if (DIR_IS_FILE_OR_SUBDIR(p)) return false; - } - // convert empty directory to normal file for remove - type_ = FAT_FILE_TYPE_NORMAL; - flags_ |= O_WRITE; - return remove(); -} -//------------------------------------------------------------------------------ -/** Recursively delete a directory and all contained files. - * - * This is like the Unix/Linux 'rm -rf *' if called with the root directory - * hence the name. - * - * Warning - This will remove all contents of the directory including - * subdirectories. The directory will then be removed if it is not root. - * The read-only attribute for files will be ignored. - * - * \note This function should not be used to delete the 8.3 version of - * a directory that has a long name. See remove() and rmDir(). - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::rmRfStar(void) { - rewind(); - while (curPosition_ < fileSize_) { - SdFile f; - - // remember position - uint16_t index = curPosition_/32; - - dir_t* p = readDirCache(); - if (!p) return false; - - // done if past last entry - if (p->name[0] == DIR_NAME_FREE) break; - - // skip empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; - - // skip if part of long file name or volume label in root - if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; - - if (!f.open(this, index, O_READ)) return false; - if (f.isSubDir()) { - // recursively delete - if (!f.rmRfStar()) return false; - } else { - // ignore read-only - f.flags_ |= O_WRITE; - if (!f.remove()) return false; - } - // position to next entry if required - if (curPosition_ != (32*(index + 1))) { - if (!seekSet(32*(index + 1))) return false; - } - } - // don't try to delete root - if (isRoot()) return true; - return rmDir(); -} -//------------------------------------------------------------------------------ -/** - * Sets a file's position. - * - * \param[in] pos The new position in bytes from the beginning of the file. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::seekSet(uint32_t pos) { - // error if file not open or seek past end of file - if (!isOpen() || pos > fileSize_) return false; - - if (type_ == FAT_FILE_TYPE_ROOT16) { - curPosition_ = pos; - return true; - } - if (pos == 0) { - // set position to start of file - curCluster_ = 0; - curPosition_ = 0; - return true; - } - // calculate cluster index for cur and new position - uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); - uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); - - if (nNew < nCur || curPosition_ == 0) { - // must follow chain from first cluster - curCluster_ = firstCluster_; - } else { - // advance from curPosition - nNew -= nCur; - } - while (nNew--) { - if (!vol_->fatGet(curCluster_, &curCluster_)) return false; - } - curPosition_ = pos; - return true; -} -//------------------------------------------------------------------------------ -/** - * The sync() call causes all modified data and directory fields - * to be written to the storage device. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include a call to sync() before a file has been - * opened or an I/O error. - */ -uint8_t SdFile::sync(void) { - // only allow open files and directories - if (!isOpen()) return false; - - if (flags_ & F_FILE_DIR_DIRTY) { - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) return false; - - // do not set filesize for dir files - if (!isDir()) d->fileSize = fileSize_; - - // update first cluster fields - d->firstClusterLow = firstCluster_ & 0XFFFF; - d->firstClusterHigh = firstCluster_ >> 16; - - // set modify time if user supplied a callback date/time function - if (dateTime_) { - dateTime_(&d->lastWriteDate, &d->lastWriteTime); - d->lastAccessDate = d->lastWriteDate; - } - // clear directory dirty - flags_ &= ~F_FILE_DIR_DIRTY; - } - return SdVolume::cacheFlush(); -} -//------------------------------------------------------------------------------ -/** - * Set a file's timestamps in its directory entry. - * - * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive - * OR of flags from the following list - * - * T_ACCESS - Set the file's last access date. - * - * T_CREATE - Set the file's creation date and time. - * - * T_WRITE - Set the file's last write/modification date and time. - * - * \param[in] year Valid range 1980 - 2107 inclusive. - * - * \param[in] month Valid range 1 - 12 inclusive. - * - * \param[in] day Valid range 1 - 31 inclusive. - * - * \param[in] hour Valid range 0 - 23 inclusive. - * - * \param[in] minute Valid range 0 - 59 inclusive. - * - * \param[in] second Valid range 0 - 59 inclusive - * - * \note It is possible to set an invalid date since there is no check for - * the number of days in a month. - * - * \note - * Modify and access timestamps may be overwritten if a date time callback - * function has been set by dateTimeCallback(). - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { - if (!isOpen() - || year < 1980 - || year > 2107 - || month < 1 - || month > 12 - || day < 1 - || day > 31 - || hour > 23 - || minute > 59 - || second > 59) { - return false; - } - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); - if (!d) return false; - - uint16_t dirDate = FAT_DATE(year, month, day); - uint16_t dirTime = FAT_TIME(hour, minute, second); - if (flags & T_ACCESS) { - d->lastAccessDate = dirDate; - } - if (flags & T_CREATE) { - d->creationDate = dirDate; - d->creationTime = dirTime; - // seems to be units of 1/100 second not 1/10 as Microsoft states - d->creationTimeTenths = second & 1 ? 100 : 0; - } - if (flags & T_WRITE) { - d->lastWriteDate = dirDate; - d->lastWriteTime = dirTime; - } - SdVolume::cacheSetDirty(); - return sync(); -} -//------------------------------------------------------------------------------ -/** - * Truncate a file to a specified length. The current file position - * will be maintained if it is less than or equal to \a length otherwise - * it will be set to end of file. - * - * \param[in] length The desired length for the file. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include file is read only, file is a directory, - * \a length is greater than the current file size or an I/O error occurs. - */ -uint8_t SdFile::truncate(uint32_t length) { -// error if not a normal file or read-only - if (!isFile() || !(flags_ & O_WRITE)) return false; - - // error if length is greater than current size - if (length > fileSize_) return false; - - // fileSize and length are zero - nothing to do - if (fileSize_ == 0) return true; - - // remember position for seek after truncation - uint32_t newPos = curPosition_ > length ? length : curPosition_; - - // position to last cluster in truncated file - if (!seekSet(length)) return false; - - if (length == 0) { - // free all clusters - if (!vol_->freeChain(firstCluster_)) return false; - firstCluster_ = 0; - } else { - uint32_t toFree; - if (!vol_->fatGet(curCluster_, &toFree)) return false; - - if (!vol_->isEOC(toFree)) { - // free extra clusters - if (!vol_->freeChain(toFree)) return false; - - // current cluster is end of chain - if (!vol_->fatPutEOC(curCluster_)) return false; - } - } - fileSize_ = length; - - // need to update directory entry - flags_ |= F_FILE_DIR_DIRTY; - - if (!sync()) return false; - - // set file to correct position - return seekSet(newPos); -} -//------------------------------------------------------------------------------ -/** - * Write data to an open file. +/** Write data to an open file. * * \note Data is moved to the cache but may not be written to the * storage device until sync() is called. @@ -1122,131 +44,38 @@ uint8_t SdFile::truncate(uint32_t length) { * */ int16_t SdFile::write(const void* buf, uint16_t nbyte) { - // convert void* to uint8_t* - must be before goto statements - const uint8_t* src = reinterpret_cast(buf); - - // number of bytes left to write - must be before goto statements - uint16_t nToWrite = nbyte; - - // error if not a normal file or is read-only - if (!isFile() || !(flags_ & O_WRITE)) goto writeErrorReturn; - - // seek to end of file if append flag - if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { - if (!seekEnd()) goto writeErrorReturn; - } - - while (nToWrite > 0) { - uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); - uint16_t blockOffset = curPosition_ & 0X1FF; - if (blockOfCluster == 0 && blockOffset == 0) { - // start of new cluster - if (curCluster_ == 0) { - if (firstCluster_ == 0) { - // allocate first cluster of file - if (!addCluster()) goto writeErrorReturn; - } else { - curCluster_ = firstCluster_; - } - } else { - uint32_t next; - if (!vol_->fatGet(curCluster_, &next)) return false; - if (vol_->isEOC(next)) { - // add cluster if at end of chain - if (!addCluster()) goto writeErrorReturn; - } else { - curCluster_ = next; - } - } - } - // max space in block - uint16_t n = 512 - blockOffset; - - // lesser of space and amount to write - if (n > nToWrite) n = nToWrite; - - // block for data write - uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; - if (n == 512) { - // full block - don't need to use cache - // invalidate cache if block is in cache - if (SdVolume::cacheBlockNumber_ == block) { - SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; - } - if (!vol_->writeBlock(block, src)) goto writeErrorReturn; - src += 512; - } else { - if (blockOffset == 0 && curPosition_ >= fileSize_) { - // start of new block don't need to read into cache - if (!SdVolume::cacheFlush()) goto writeErrorReturn; - SdVolume::cacheBlockNumber_ = block; - SdVolume::cacheSetDirty(); - } else { - // rewrite part of block - if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { - goto writeErrorReturn; - } - } - uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset; - uint8_t* end = dst + n; - while (dst != end) *dst++ = *src++; - } - nToWrite -= n; - curPosition_ += n; - } - if (curPosition_ > fileSize_) { - // update fileSize and insure sync will update dir entry - fileSize_ = curPosition_; - flags_ |= F_FILE_DIR_DIRTY; - } else if (dateTime_ && nbyte) { - // insure sync will update modified date and time - flags_ |= F_FILE_DIR_DIRTY; - } - - if (flags_ & O_SYNC) { - if (!sync()) goto writeErrorReturn; - } - return nbyte; - - writeErrorReturn: - // return for write error - writeError = true; - return -1; + return SdBaseFile::write(buf, nbyte); } //------------------------------------------------------------------------------ -/** - * Write a byte to a file. Required by the Arduino Print class. - * - * Use SdFile::writeError to check for errors. +/** Write a byte to a file. Required by the Arduino Print class. + * \param[in] b the byte to be written. + * Use writeError to check for errors. */ void SdFile::write(uint8_t b) { - write(&b, 1); + SdBaseFile::write(&b, 1); } //------------------------------------------------------------------------------ -/** - * Write a string to a file. Used by the Arduino Print class. - * - * Use SdFile::writeError to check for errors. +/** Write a string to a file. Used by the Arduino Print class. + * \param[in] str Pointer to the string. + * Use writeError to check for errors. */ void SdFile::write(const char* str) { - write(str, strlen(str)); + SdBaseFile::write(str, strlen(str)); } //------------------------------------------------------------------------------ -/** - * Write a PROGMEM string to a file. - * - * Use SdFile::writeError to check for errors. +/** Write a PROGMEM string to a file. + * \param[in] str Pointer to the PROGMEM string. + * Use writeError to check for errors. */ void SdFile::write_P(PGM_P str) { for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c); } //------------------------------------------------------------------------------ -/** - * Write a PROGMEM string followed by CR/LF to a file. - * - * Use SdFile::writeError to check for errors. +/** Write a PROGMEM string followed by CR/LF to a file. + * \param[in] str Pointer to the PROGMEM string. + * Use writeError to check for errors. */ void SdFile::writeln_P(PGM_P str) { write_P(str); - println(); + write_P(PSTR("\r\n")); } diff --git a/Marlin/SdFile.h b/Marlin/SdFile.h new file mode 100644 index 0000000000..d5f8ec0891 --- /dev/null +++ b/Marlin/SdFile.h @@ -0,0 +1,42 @@ +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +/** + * \file + * \brief SdFile class + */ +#include "SdBaseFile.h" +#ifndef SdFile_h +#define SdFile_h +//------------------------------------------------------------------------------ +/** + * \class SdFile + * \brief SdBaseFile with Print. + */ +class SdFile : public SdBaseFile, public Print { + public: + SdFile() {} + SdFile(const char* name, uint8_t oflag); + void write(uint8_t b); + int16_t write(const void* buf, uint16_t nbyte); + void write(const char* str); + void write_P(PGM_P str); + void writeln_P(PGM_P str); +}; +#endif // SdFile_h diff --git a/Marlin/SdInfo.h b/Marlin/SdInfo.h index acde74d974..2a58eb7db4 100644 --- a/Marlin/SdInfo.h +++ b/Marlin/SdInfo.h @@ -26,10 +26,10 @@ // Part 1 // Physical Layer // Simplified Specification -// Version 2.00 -// September 25, 2006 +// Version 3.01 +// May 18, 2010 // -// www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf +// http://www.sdcard.org/developers/tech/sdcard/pls/simplified_specs //------------------------------------------------------------------------------ // SD card commands /** GO_IDLE_STATE - init card in spi mode if CS low */ @@ -40,10 +40,14 @@ uint8_t const CMD8 = 0X08; uint8_t const CMD9 = 0X09; /** SEND_CID - read the card identification information (CID register) */ uint8_t const CMD10 = 0X0A; +/** STOP_TRANSMISSION - end multiple block read sequence */ +uint8_t const CMD12 = 0X0C; /** SEND_STATUS - read the card status register */ uint8_t const CMD13 = 0X0D; -/** READ_BLOCK - read a single data block from the card */ +/** READ_SINGLE_BLOCK - read a single data block from the card */ uint8_t const CMD17 = 0X11; +/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */ +uint8_t const CMD18 = 0X12; /** WRITE_BLOCK - write a single data block to the card */ uint8_t const CMD24 = 0X18; /** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ @@ -83,148 +87,187 @@ uint8_t const DATA_RES_MASK = 0X1F; /** write data accepted token */ uint8_t const DATA_RES_ACCEPTED = 0X05; //------------------------------------------------------------------------------ +/** Card IDentification (CID) register */ typedef struct CID { // byte 0 - uint8_t mid; // Manufacturer ID + /** Manufacturer ID */ + unsigned char mid; // byte 1-2 - char oid[2]; // OEM/Application ID + /** OEM/Application ID */ + char oid[2]; // byte 3-7 - char pnm[5]; // Product name + /** Product name */ + char pnm[5]; // byte 8 - unsigned prv_m : 4; // Product revision n.m - unsigned prv_n : 4; + /** Product revision least significant digit */ + unsigned char prv_m : 4; + /** Product revision most significant digit */ + unsigned char prv_n : 4; // byte 9-12 - uint32_t psn; // Product serial number + /** Product serial number */ + uint32_t psn; // byte 13 - unsigned mdt_year_high : 4; // Manufacturing date - unsigned reserved : 4; + /** Manufacturing date year low digit */ + unsigned char mdt_year_high : 4; + /** not used */ + unsigned char reserved : 4; // byte 14 - unsigned mdt_month : 4; - unsigned mdt_year_low :4; + /** Manufacturing date month */ + unsigned char mdt_month : 4; + /** Manufacturing date year low digit */ + unsigned char mdt_year_low :4; // byte 15 - unsigned always1 : 1; - unsigned crc : 7; + /** not used always 1 */ + unsigned char always1 : 1; + /** CRC7 checksum */ + unsigned char crc : 7; }cid_t; //------------------------------------------------------------------------------ -// CSD for version 1.00 cards +/** CSD for version 1.00 cards */ typedef struct CSDV1 { // byte 0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; + unsigned char reserved1 : 6; + unsigned char csd_ver : 2; // byte 1 - uint8_t taac; + unsigned char taac; // byte 2 - uint8_t nsac; + unsigned char nsac; // byte 3 - uint8_t tran_speed; + unsigned char tran_speed; // byte 4 - uint8_t ccc_high; + unsigned char ccc_high; // byte 5 - unsigned read_bl_len : 4; - unsigned ccc_low : 4; + unsigned char read_bl_len : 4; + unsigned char ccc_low : 4; // byte 6 - unsigned c_size_high : 2; - unsigned reserved2 : 2; - unsigned dsr_imp : 1; - unsigned read_blk_misalign :1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; + unsigned char c_size_high : 2; + unsigned char reserved2 : 2; + unsigned char dsr_imp : 1; + unsigned char read_blk_misalign :1; + unsigned char write_blk_misalign : 1; + unsigned char read_bl_partial : 1; // byte 7 - uint8_t c_size_mid; + unsigned char c_size_mid; // byte 8 - unsigned vdd_r_curr_max : 3; - unsigned vdd_r_curr_min : 3; - unsigned c_size_low :2; + unsigned char vdd_r_curr_max : 3; + unsigned char vdd_r_curr_min : 3; + unsigned char c_size_low :2; // byte 9 - unsigned c_size_mult_high : 2; - unsigned vdd_w_cur_max : 3; - unsigned vdd_w_curr_min : 3; + unsigned char c_size_mult_high : 2; + unsigned char vdd_w_cur_max : 3; + unsigned char vdd_w_curr_min : 3; // byte 10 - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned c_size_mult_low : 1; + unsigned char sector_size_high : 6; + unsigned char erase_blk_en : 1; + unsigned char c_size_mult_low : 1; // byte 11 - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; + unsigned char wp_grp_size : 7; + unsigned char sector_size_low : 1; // byte 12 - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved3 : 2; - unsigned wp_grp_enable : 1; + unsigned char write_bl_len_high : 2; + unsigned char r2w_factor : 3; + unsigned char reserved3 : 2; + unsigned char wp_grp_enable : 1; // byte 13 - unsigned reserved4 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; + unsigned char reserved4 : 5; + unsigned char write_partial : 1; + unsigned char write_bl_len_low : 2; // byte 14 - unsigned reserved5: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; + unsigned char reserved5: 2; + unsigned char file_format : 2; + unsigned char tmp_write_protect : 1; + unsigned char perm_write_protect : 1; + unsigned char copy : 1; + /** Indicates the file format on the card */ + unsigned char file_format_grp : 1; // byte 15 - unsigned always1 : 1; - unsigned crc : 7; + unsigned char always1 : 1; + unsigned char crc : 7; }csd1_t; //------------------------------------------------------------------------------ -// CSD for version 2.00 cards +/** CSD for version 2.00 cards */ typedef struct CSDV2 { // byte 0 - unsigned reserved1 : 6; - unsigned csd_ver : 2; + unsigned char reserved1 : 6; + unsigned char csd_ver : 2; // byte 1 - uint8_t taac; + /** fixed to 0X0E */ + unsigned char taac; // byte 2 - uint8_t nsac; + /** fixed to 0 */ + unsigned char nsac; // byte 3 - uint8_t tran_speed; + unsigned char tran_speed; // byte 4 - uint8_t ccc_high; + unsigned char ccc_high; // byte 5 - unsigned read_bl_len : 4; - unsigned ccc_low : 4; + /** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */ + unsigned char read_bl_len : 4; + unsigned char ccc_low : 4; // byte 6 - unsigned reserved2 : 4; - unsigned dsr_imp : 1; - unsigned read_blk_misalign :1; - unsigned write_blk_misalign : 1; - unsigned read_bl_partial : 1; + /** not used */ + unsigned char reserved2 : 4; + unsigned char dsr_imp : 1; + /** fixed to 0 */ + unsigned char read_blk_misalign :1; + /** fixed to 0 */ + unsigned char write_blk_misalign : 1; + /** fixed to 0 - no partial read */ + unsigned char read_bl_partial : 1; // byte 7 - unsigned reserved3 : 2; - unsigned c_size_high : 6; + /** not used */ + unsigned char reserved3 : 2; + /** high part of card size */ + unsigned char c_size_high : 6; // byte 8 - uint8_t c_size_mid; + /** middle part of card size */ + unsigned char c_size_mid; // byte 9 - uint8_t c_size_low; + /** low part of card size */ + unsigned char c_size_low; // byte 10 - unsigned sector_size_high : 6; - unsigned erase_blk_en : 1; - unsigned reserved4 : 1; + /** sector size is fixed at 64 KB */ + unsigned char sector_size_high : 6; + /** fixed to 1 - erase single is supported */ + unsigned char erase_blk_en : 1; + /** not used */ + unsigned char reserved4 : 1; // byte 11 - unsigned wp_grp_size : 7; - unsigned sector_size_low : 1; + unsigned char wp_grp_size : 7; + /** sector size is fixed at 64 KB */ + unsigned char sector_size_low : 1; // byte 12 - unsigned write_bl_len_high : 2; - unsigned r2w_factor : 3; - unsigned reserved5 : 2; - unsigned wp_grp_enable : 1; + /** write_bl_len fixed for 512 byte blocks */ + unsigned char write_bl_len_high : 2; + /** fixed value of 2 */ + unsigned char r2w_factor : 3; + /** not used */ + unsigned char reserved5 : 2; + /** fixed value of 0 - no write protect groups */ + unsigned char wp_grp_enable : 1; // byte 13 - unsigned reserved6 : 5; - unsigned write_partial : 1; - unsigned write_bl_len_low : 2; + unsigned char reserved6 : 5; + /** always zero - no partial block read*/ + unsigned char write_partial : 1; + /** write_bl_len fixed for 512 byte blocks */ + unsigned char write_bl_len_low : 2; // byte 14 - unsigned reserved7: 2; - unsigned file_format : 2; - unsigned tmp_write_protect : 1; - unsigned perm_write_protect : 1; - unsigned copy : 1; - unsigned file_format_grp : 1; + unsigned char reserved7: 2; + /** Do not use always 0 */ + unsigned char file_format : 2; + unsigned char tmp_write_protect : 1; + unsigned char perm_write_protect : 1; + unsigned char copy : 1; + /** Do not use always 0 */ + unsigned char file_format_grp : 1; // byte 15 - unsigned always1 : 1; - unsigned crc : 7; + /** not used always 1 */ + unsigned char always1 : 1; + /** checksum */ + unsigned char crc : 7; }csd2_t; //------------------------------------------------------------------------------ -// union of old and new style CSD register +/** union of old and new style CSD register */ union csd_t { csd1_t v1; csd2_t v2; diff --git a/Marlin/SdVolume.cpp b/Marlin/SdVolume.cpp index 2fbb8100b9..a14bb627ed 100644 --- a/Marlin/SdVolume.cpp +++ b/Marlin/SdVolume.cpp @@ -17,23 +17,28 @@ * along with the Arduino SdFat Library. If not, see * . */ -#include "SdFat.h" +#include "SdVolume.h" //------------------------------------------------------------------------------ +#if !USE_MULTIPLE_CARDS // raw block cache -// init cacheBlockNumber_to invalid SD block number -uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; -cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card -Sd2Card* SdVolume::sdCard_; // pointer to SD card object -uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true -uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT +uint32_t SdVolume::cacheBlockNumber_; // current block number +cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card +Sd2Card* SdVolume::sdCard_; // pointer to SD card object +bool SdVolume::cacheDirty_; // cacheFlush() will write block if true +uint32_t SdVolume::cacheMirrorBlock_; // mirror block for second FAT +#endif // USE_MULTIPLE_CARDS //------------------------------------------------------------------------------ // find a contiguous group of clusters -uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { +bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { // start of group uint32_t bgnCluster; + // end of group + uint32_t endCluster; + // last cluster of FAT + uint32_t fatEnd = clusterCount_ + 1; // flag to save place to start next search - uint8_t setStart; + bool setStart; // set search start cluster if (*curCluster) { @@ -47,25 +52,22 @@ uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { bgnCluster = allocSearchStart_; // save next search start if one cluster - setStart = 1 == count; + setStart = count == 1; } // end of group - uint32_t endCluster = bgnCluster; - - // last cluster of FAT - uint32_t fatEnd = clusterCount_ + 1; + endCluster = bgnCluster; // search the FAT for free clusters for (uint32_t n = 0;; n++, endCluster++) { // can't find space checked all clusters - if (n >= clusterCount_) return false; + if (n >= clusterCount_) goto fail; // past end - start from beginning of FAT if (endCluster > fatEnd) { bgnCluster = endCluster = 2; } uint32_t f; - if (!fatGet(endCluster, &f)) return false; + if (!fatGet(endCluster, &f)) goto fail; if (f != 0) { // cluster in use try next cluster as bgnCluster @@ -76,16 +78,16 @@ uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { } } // mark end of chain - if (!fatPutEOC(endCluster)) return false; + if (!fatPutEOC(endCluster)) goto fail; // link clusters while (endCluster > bgnCluster) { - if (!fatPut(endCluster - 1, endCluster)) return false; + if (!fatPut(endCluster - 1, endCluster)) goto fail; endCluster--; } if (*curCluster != 0) { // connect chains - if (!fatPut(*curCluster, bgnCluster)) return false; + if (!fatPut(*curCluster, bgnCluster)) goto fail; } // return first cluster number to caller *curCluster = bgnCluster; @@ -94,66 +96,87 @@ uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { if (setStart) allocSearchStart_ = bgnCluster + 1; return true; + + fail: + return false; } //------------------------------------------------------------------------------ -uint8_t SdVolume::cacheFlush(void) { +bool SdVolume::cacheFlush() { if (cacheDirty_) { if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) { - return false; + goto fail; } // mirror FAT tables if (cacheMirrorBlock_) { if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) { - return false; + goto fail; } cacheMirrorBlock_ = 0; } cacheDirty_ = 0; } return true; + + fail: + return false; } //------------------------------------------------------------------------------ -uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) { +bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) { if (cacheBlockNumber_ != blockNumber) { - if (!cacheFlush()) return false; - if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false; + if (!cacheFlush()) goto fail; + if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto fail; cacheBlockNumber_ = blockNumber; } - cacheDirty_ |= action; + if (dirty) cacheDirty_ = true; return true; -} -//------------------------------------------------------------------------------ -// cache a zero block for blockNumber -uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) { - if (!cacheFlush()) return false; - // loop take less flash than memset(cacheBuffer_.data, 0, 512); - for (uint16_t i = 0; i < 512; i++) { - cacheBuffer_.data[i] = 0; - } - cacheBlockNumber_ = blockNumber; - cacheSetDirty(); - return true; + fail: + return false; } //------------------------------------------------------------------------------ // return the size in bytes of a cluster chain -uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { +bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) { uint32_t s = 0; do { - if (!fatGet(cluster, &cluster)) return false; + if (!fatGet(cluster, &cluster)) goto fail; s += 512UL << clusterSizeShift_; } while (!isEOC(cluster)); *size = s; return true; + + fail: + return false; } //------------------------------------------------------------------------------ // Fetch a FAT entry -uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { - if (cluster > (clusterCount_ + 1)) return false; - uint32_t lba = fatStartBlock_; - lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; +bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) { + uint32_t lba; + if (cluster > (clusterCount_ + 1)) goto fail; + if (FAT12_SUPPORT && fatType_ == 12) { + uint16_t index = cluster; + index += index >> 1; + lba = fatStartBlock_ + (index >> 9); + if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail; + index &= 0X1FF; + uint16_t tmp = cacheBuffer_.data[index]; + index++; + if (index == 512) { + if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto fail; + index = 0; + } + tmp |= cacheBuffer_.data[index] << 8; + *value = cluster & 1 ? tmp >> 4 : tmp & 0XFFF; + return true; + } + if (fatType_ == 16) { + lba = fatStartBlock_ + (cluster >> 8); + } else if (fatType_ == 32) { + lba = fatStartBlock_ + (cluster >> 7); + } else { + goto fail; + } if (lba != cacheBlockNumber_) { - if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; + if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail; } if (fatType_ == 16) { *value = cacheBuffer_.fat16[cluster & 0XFF]; @@ -161,56 +184,127 @@ uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; } return true; + + fail: + return false; } //------------------------------------------------------------------------------ // Store a FAT entry -uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) { +bool SdVolume::fatPut(uint32_t cluster, uint32_t value) { + uint32_t lba; // error if reserved cluster - if (cluster < 2) return false; + if (cluster < 2) goto fail; // error if not in FAT - if (cluster > (clusterCount_ + 1)) return false; + if (cluster > (clusterCount_ + 1)) goto fail; - // calculate block address for entry - uint32_t lba = fatStartBlock_; - lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; - - if (lba != cacheBlockNumber_) { - if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false; + if (FAT12_SUPPORT && fatType_ == 12) { + uint16_t index = cluster; + index += index >> 1; + lba = fatStartBlock_ + (index >> 9); + if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail; + // mirror second FAT + if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_; + index &= 0X1FF; + uint8_t tmp = value; + if (cluster & 1) { + tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4; + } + cacheBuffer_.data[index] = tmp; + index++; + if (index == 512) { + lba++; + index = 0; + if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail; + // mirror second FAT + if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_; + } + tmp = value >> 4; + if (!(cluster & 1)) { + tmp = ((cacheBuffer_.data[index] & 0XF0)) | tmp >> 4; + } + cacheBuffer_.data[index] = tmp; + return true; } + if (fatType_ == 16) { + lba = fatStartBlock_ + (cluster >> 8); + } else if (fatType_ == 32) { + lba = fatStartBlock_ + (cluster >> 7); + } else { + goto fail; + } + if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail; // store entry if (fatType_ == 16) { cacheBuffer_.fat16[cluster & 0XFF] = value; } else { cacheBuffer_.fat32[cluster & 0X7F] = value; } - cacheSetDirty(); - // mirror second FAT if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_; return true; + + fail: + return false; } //------------------------------------------------------------------------------ // free a cluster chain -uint8_t SdVolume::freeChain(uint32_t cluster) { +bool SdVolume::freeChain(uint32_t cluster) { + uint32_t next; + // clear free cluster location allocSearchStart_ = 2; do { - uint32_t next; - if (!fatGet(cluster, &next)) return false; + if (!fatGet(cluster, &next)) goto fail; // free cluster - if (!fatPut(cluster, 0)) return false; + if (!fatPut(cluster, 0)) goto fail; cluster = next; } while (!isEOC(cluster)); return true; + + fail: + return false; } //------------------------------------------------------------------------------ -/** - * Initialize a FAT volume. +/** Volume free space in clusters. + * + * \return Count of free clusters for success or -1 if an error occurs. + */ +int32_t SdVolume::freeClusterCount() { + uint32_t free = 0; + uint16_t n; + uint32_t todo = clusterCount_ + 2; + + if (fatType_ == 16) { + n = 256; + } else if (fatType_ == 32) { + n = 128; + } else { + // put FAT12 here + return -1; + } + + for (uint32_t lba = fatStartBlock_; todo; todo -= n, lba++) { + if (!cacheRawBlock(lba, CACHE_FOR_READ)) return -1; + if (todo < n) n = todo; + if (fatType_ == 16) { + for (uint16_t i = 0; i < n; i++) { + if (cacheBuffer_.fat16[i] == 0) free++; + } + } else { + for (uint16_t i = 0; i < n; i++) { + if (cacheBuffer_.fat32[i] == 0) free++; + } + } + } + return free; +} +//------------------------------------------------------------------------------ +/** Initialize a FAT volume. * * \param[in] dev The SD card where the volume is located. * @@ -224,58 +318,66 @@ uint8_t SdVolume::freeChain(uint32_t cluster) { * failure include not finding a valid partition, not finding a valid * FAT file system in the specified partition or an I/O error. */ -uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { +bool SdVolume::init(Sd2Card* dev, uint8_t part) { + uint32_t totalBlocks; uint32_t volumeStartBlock = 0; + fat32_boot_t* fbs; + sdCard_ = dev; + fatType_ = 0; + allocSearchStart_ = 2; + cacheDirty_ = 0; // cacheFlush() will write block if true + cacheMirrorBlock_ = 0; + cacheBlockNumber_ = 0XFFFFFFFF; + // if part == 0 assume super floppy with FAT boot sector in block zero // if part > 0 assume mbr volume with partition table if (part) { - if (part > 4)return false; - if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; + if (part > 4)goto fail; + if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail; part_t* p = &cacheBuffer_.mbr.part[part-1]; if ((p->boot & 0X7F) !=0 || p->totalSectors < 100 || p->firstSector == 0) { // not a valid partition - return false; + goto fail; } volumeStartBlock = p->firstSector; } - if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false; - bpb_t* bpb = &cacheBuffer_.fbs.bpb; - if (bpb->bytesPerSector != 512 || - bpb->fatCount == 0 || - bpb->reservedSectorCount == 0 || - bpb->sectorsPerCluster == 0) { + if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail; + fbs = &cacheBuffer_.fbs32; + if (fbs->bytesPerSector != 512 || + fbs->fatCount == 0 || + fbs->reservedSectorCount == 0 || + fbs->sectorsPerCluster == 0) { // not valid FAT volume - return false; + goto fail; } - fatCount_ = bpb->fatCount; - blocksPerCluster_ = bpb->sectorsPerCluster; - + fatCount_ = fbs->fatCount; + blocksPerCluster_ = fbs->sectorsPerCluster; // determine shift that is same as multiply by blocksPerCluster_ clusterSizeShift_ = 0; while (blocksPerCluster_ != (1 << clusterSizeShift_)) { // error if not power of 2 - if (clusterSizeShift_++ > 7) return false; + if (clusterSizeShift_++ > 7) goto fail; } - blocksPerFat_ = bpb->sectorsPerFat16 ? - bpb->sectorsPerFat16 : bpb->sectorsPerFat32; + blocksPerFat_ = fbs->sectorsPerFat16 ? + fbs->sectorsPerFat16 : fbs->sectorsPerFat32; - fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount; + fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount; // count for FAT16 zero for FAT32 - rootDirEntryCount_ = bpb->rootDirEntryCount; + rootDirEntryCount_ = fbs->rootDirEntryCount; // directory start for FAT16 dataStart for FAT32 - rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_; + rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_; // data start for FAT16 and FAT32 - dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512); + dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511)/512); // total blocks for FAT16 or FAT32 - uint32_t totalBlocks = bpb->totalSectors16 ? - bpb->totalSectors16 : bpb->totalSectors32; + totalBlocks = fbs->totalSectors16 ? + fbs->totalSectors16 : fbs->totalSectors32; // total data blocks clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); @@ -285,11 +387,15 @@ uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { // FAT type is determined by cluster count if (clusterCount_ < 4085) { fatType_ = 12; + if (!FAT12_SUPPORT) goto fail; } else if (clusterCount_ < 65525) { fatType_ = 16; } else { - rootDirStart_ = bpb->fat32RootCluster; + rootDirStart_ = fbs->fat32RootCluster; fatType_ = 32; } return true; + + fail: + return false; } diff --git a/Marlin/SdVolume.h b/Marlin/SdVolume.h new file mode 100644 index 0000000000..0f2e55ab2a --- /dev/null +++ b/Marlin/SdVolume.h @@ -0,0 +1,211 @@ +/* Arduino SdFat Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdVolume_h +#define SdVolume_h +/** + * \file + * \brief SdVolume class + */ +#include "SdFatConfig.h" +#include "Sd2Card.h" +#include "SdFatStructs.h" + +//============================================================================== +// SdVolume class +/** + * \brief Cache for an SD data block + */ +union cache_t { + /** Used to access cached file data blocks. */ + uint8_t data[512]; + /** Used to access cached FAT16 entries. */ + uint16_t fat16[256]; + /** Used to access cached FAT32 entries. */ + uint32_t fat32[128]; + /** Used to access cached directory entries. */ + dir_t dir[16]; + /** Used to access a cached Master Boot Record. */ + mbr_t mbr; + /** Used to access to a cached FAT boot sector. */ + fat_boot_t fbs; + /** Used to access to a cached FAT32 boot sector. */ + fat32_boot_t fbs32; + /** Used to access to a cached FAT32 FSINFO sector. */ + fat32_fsinfo_t fsinfo; +}; +//------------------------------------------------------------------------------ +/** + * \class SdVolume + * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. + */ +class SdVolume { + public: + /** Create an instance of SdVolume */ + SdVolume() : fatType_(0) {} + /** Clear the cache and returns a pointer to the cache. Used by the WaveRP + * recorder to do raw write to the SD card. Not for normal apps. + * \return A pointer to the cache buffer or zero if an error occurs. + */ + cache_t* cacheClear() { + if (!cacheFlush()) return 0; + cacheBlockNumber_ = 0XFFFFFFFF; + return &cacheBuffer_; + } + /** Initialize a FAT volume. Try partition one first then try super + * floppy format. + * + * \param[in] dev The Sd2Card where the volume is located. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. Reasons for + * failure include not finding a valid partition, not finding a valid + * FAT file system or an I/O error. + */ + bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);} + bool init(Sd2Card* dev, uint8_t part); + + // inline functions that return volume info + /** \return The volume's cluster size in blocks. */ + uint8_t blocksPerCluster() const {return blocksPerCluster_;} + /** \return The number of blocks in one FAT. */ + uint32_t blocksPerFat() const {return blocksPerFat_;} + /** \return The total number of clusters in the volume. */ + uint32_t clusterCount() const {return clusterCount_;} + /** \return The shift count required to multiply by blocksPerCluster. */ + uint8_t clusterSizeShift() const {return clusterSizeShift_;} + /** \return The logical block number for the start of file data. */ + uint32_t dataStartBlock() const {return dataStartBlock_;} + /** \return The number of FAT structures on the volume. */ + uint8_t fatCount() const {return fatCount_;} + /** \return The logical block number for the start of the first FAT. */ + uint32_t fatStartBlock() const {return fatStartBlock_;} + /** \return The FAT type of the volume. Values are 12, 16 or 32. */ + uint8_t fatType() const {return fatType_;} + int32_t freeClusterCount(); + /** \return The number of entries in the root directory for FAT16 volumes. */ + uint32_t rootDirEntryCount() const {return rootDirEntryCount_;} + /** \return The logical block number for the start of the root directory + on FAT16 volumes or the first cluster number on FAT32 volumes. */ + uint32_t rootDirStart() const {return rootDirStart_;} + /** Sd2Card object for this volume + * \return pointer to Sd2Card object. + */ + Sd2Card* sdCard() {return sdCard_;} + /** Debug access to FAT table + * + * \param[in] n cluster number. + * \param[out] v value of entry + * \return true for success or false for failure + */ + bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);} +//------------------------------------------------------------------------------ + private: + // Allow SdBaseFile access to SdVolume private data. + friend class SdBaseFile; + + // value for dirty argument in cacheRawBlock to indicate read from cache + static bool const CACHE_FOR_READ = false; + // value for dirty argument in cacheRawBlock to indicate write to cache + static bool const CACHE_FOR_WRITE = true; + +#if USE_MULTIPLE_CARDS + cache_t cacheBuffer_; // 512 byte cache for device blocks + uint32_t cacheBlockNumber_; // Logical number of block in the cache + Sd2Card* sdCard_; // Sd2Card object for cache + bool cacheDirty_; // cacheFlush() will write block if true + uint32_t cacheMirrorBlock_; // block number for mirror FAT +#else // USE_MULTIPLE_CARDS + static cache_t cacheBuffer_; // 512 byte cache for device blocks + static uint32_t cacheBlockNumber_; // Logical number of block in the cache + static Sd2Card* sdCard_; // Sd2Card object for cache + static bool cacheDirty_; // cacheFlush() will write block if true + static uint32_t cacheMirrorBlock_; // block number for mirror FAT +#endif // USE_MULTIPLE_CARDS + uint32_t allocSearchStart_; // start cluster for alloc search + uint8_t blocksPerCluster_; // cluster size in blocks + uint32_t blocksPerFat_; // FAT size in blocks + uint32_t clusterCount_; // clusters in one FAT + uint8_t clusterSizeShift_; // shift to convert cluster count to block count + uint32_t dataStartBlock_; // first data block number + uint8_t fatCount_; // number of FATs on volume + uint32_t fatStartBlock_; // start block for first FAT + uint8_t fatType_; // volume type (12, 16, OR 32) + uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir + uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 + //---------------------------------------------------------------------------- + bool allocContiguous(uint32_t count, uint32_t* curCluster); + uint8_t blockOfCluster(uint32_t position) const { + return (position >> 9) & (blocksPerCluster_ - 1);} + uint32_t clusterStartBlock(uint32_t cluster) const { + return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} + uint32_t blockNumber(uint32_t cluster, uint32_t position) const { + return clusterStartBlock(cluster) + blockOfCluster(position);} + cache_t *cache() {return &cacheBuffer_;} + uint32_t cacheBlockNumber() {return cacheBlockNumber_;} +#if USE_MULTIPLE_CARDS + bool cacheFlush(); + bool cacheRawBlock(uint32_t blockNumber, bool dirty); +#else // USE_MULTIPLE_CARDS + static bool cacheFlush(); + static bool cacheRawBlock(uint32_t blockNumber, bool dirty); +#endif // USE_MULTIPLE_CARDS + // used by SdBaseFile write to assign cache to SD location + void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) { + cacheDirty_ = dirty; + cacheBlockNumber_ = blockNumber; + } + void cacheSetDirty() {cacheDirty_ |= CACHE_FOR_WRITE;} + bool chainSize(uint32_t beginCluster, uint32_t* size); + bool fatGet(uint32_t cluster, uint32_t* value); + bool fatPut(uint32_t cluster, uint32_t value); + bool fatPutEOC(uint32_t cluster) { + return fatPut(cluster, 0x0FFFFFFF); + } + bool freeChain(uint32_t cluster); + bool isEOC(uint32_t cluster) const { + if (FAT12_SUPPORT && fatType_ == 12) return cluster >= FAT12EOC_MIN; + if (fatType_ == 16) return cluster >= FAT16EOC_MIN; + return cluster >= FAT32EOC_MIN; + } + bool readBlock(uint32_t block, uint8_t* dst) { + return sdCard_->readBlock(block, dst);} + bool writeBlock(uint32_t block, const uint8_t* dst) { + return sdCard_->writeBlock(block, dst); + } +//------------------------------------------------------------------------------ + // Deprecated functions - suppress cpplint warnings with NOLINT comment +#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN) + public: + /** \deprecated Use: bool SdVolume::init(Sd2Card* dev); + * \param[in] dev The SD card where the volume is located. + * \return true for success or false for failure. + */ + bool init(Sd2Card& dev) {return init(&dev);} // NOLINT + /** \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol); + * \param[in] dev The SD card where the volume is located. + * \param[in] part The partition to be used. + * \return true for success or false for failure. + */ + bool init(Sd2Card& dev, uint8_t part) { // NOLINT + return init(&dev, part); + } +#endif // ALLOW_DEPRECATED_FUNCTIONS +}; +#endif // SdVolume diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index d75f93a523..04076bfda0 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -3,6 +3,7 @@ #ifdef SDSUPPORT + #include "SdFat.h" class CardReader diff --git a/merging still needs.txt b/merging still needs.txt deleted file mode 100644 index 18e91dcad1..0000000000 --- a/merging still needs.txt +++ /dev/null @@ -1,58 +0,0 @@ -files to compare manually: -planner.cpp -stepper.cpp -temperature.cpp - ---- -things that changed: -* planner.cpp -estimate_acc_distance now works with floats. -in calculate_trapezoid:for_block - long acceleration_rate=(long)((float)acceleration*8.388608) is gone - so is block_>acceleration_rate -void planner_reverse_pass: - some stuff I don't understand right now changed -in planner_forward_pass: - done: BLOCK_BUFFER_SIZE is now necessarily power of 2 (aka 8 16, 32). Inportant to document this somewhere. -no more inline in void plan_discard_current_block() -no more inline in plan_get_current_block() -in plan_buffer_line(...) - the long target[4]; and calculations of thoose should go after the while(block_buffer_tail==..). if the axis_steps_per_unit are changed from the gcode (M92) the calculation for the currently planned buffer move will be corrupt, because Target is calculated with one value, and the stuff afterwards with another. At least this solved the problem I had with the M92 E* changes in the code. Very sure about this, I took me 20min to find this as the solution for the bug I was hunting. -around if(feed_rate!true+return? -done #define K1 0.95 maybe in the configuration.h? -semi-done: PID-C checking needed. Untested but added. ----- - -still needed to finish the merge, before testin! - - manage_heater - ISR - movement planner - -TODO: - -remove traveling at maxpseed -remove Simplelcd - -remove DEBUG_STEPS? - -block_t -pid_dt ->0.1 whats the changes to the PID, checking needed - - ----- -second merge saturday morning: -done: PID_dt->0.1 \ No newline at end of file From 5df5727e939de26c828041ea7083a07c72f475da Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Fri, 18 Nov 2011 22:20:53 +0100 Subject: [PATCH 052/228] removed some debugging comments --- Marlin/Marlin.pde | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index db51361398..18f382c8c2 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -392,15 +392,8 @@ inline void get_command() while( !card.eof() && buflen < BUFSIZE) { int16_t n=card.get(); serial_char = (char)n; -// Serial.print((char)serial_char); -// Serial.print(" "); -// Serial.println((int)serial_count); if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) { -// if(serial_char == '\n' || serial_char == '\r' ) -// Serial.println("newline or :"); -// if(serial_count >= (MAX_CMD_SIZE - 1)) -// Serial.println("too long line"); if(card.eof()){ card.sdprinting = false; SERIAL_PROTOCOLLNPGM("Done printing file"); @@ -420,7 +413,6 @@ inline void get_command() comment_mode = false; //for new command if(!serial_count) { -// Serial.println("empty line"); return; //if empty line } cmdbuffer[bufindw][serial_count] = 0; //terminate string @@ -428,8 +420,7 @@ inline void get_command() fromsd[bufindw] = true; buflen += 1; bufindw = (bufindw + 1)%BUFSIZE; - } - + } serial_count = 0; //clear buffer } else From edb5ea7efa555b59f17655e20e93d9e93499d5d8 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Fri, 18 Nov 2011 22:22:07 +0100 Subject: [PATCH 053/228] the normal config again.. --- Marlin/Configuration.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f1f0c651cf..1e12d4e225 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -4,8 +4,8 @@ // This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 +#define BAUDRATE 250000 +//#define BAUDRATE 115200 //#define BAUDRATE 230400 @@ -277,7 +277,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define ULTIPANEL #ifdef ULTIPANEL - #define NEWPANEL //enable this if you have a click-encoder panel +// #define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT #define ULTRA_LCD #define LCD_WIDTH 20 From ff69e0a772c71226be7d6000c5096c0a850e3a62 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 19 Nov 2011 12:19:53 +0100 Subject: [PATCH 054/228] Changed max/min temp init. Removed second uart from sabguino core --- .../cores/Copy of arduino/HardwareSerial.cpp | 303 ----------- .../cores/Copy of arduino/HardwareSerial.h | 76 --- .../Sanguino/cores/Copy of arduino/Print.cpp | 220 -------- Marlin/Sanguino/cores/Copy of arduino/Print.h | 66 --- .../Sanguino/cores/Copy of arduino/Tone.cpp | 515 ------------------ .../cores/Copy of arduino/WCharacter.h | 168 ------ .../cores/Copy of arduino/WConstants.h | 1 - .../cores/Copy of arduino/WInterrupts.c | 87 --- .../Sanguino/cores/Copy of arduino/WMath.cpp | 60 -- .../Sanguino/cores/Copy of arduino/WProgram.h | 63 --- .../cores/Copy of arduino/WString.cpp | 443 --------------- .../Sanguino/cores/Copy of arduino/WString.h | 112 ---- .../Sanguino/cores/Copy of arduino/binary.h | 515 ------------------ .../Sanguino/cores/Copy of arduino/main.cpp | 14 - .../cores/Copy of arduino/pins_arduino.c | 200 ------- .../cores/Copy of arduino/pins_arduino.h | 65 --- .../Sanguino/cores/Copy of arduino/wiring.c | 289 ---------- .../Sanguino/cores/Copy of arduino/wiring.h | 135 ----- .../cores/Copy of arduino/wiring_analog.c | 116 ---- .../cores/Copy of arduino/wiring_digital.c | 95 ---- .../cores/Copy of arduino/wiring_private.h | 60 -- .../cores/Copy of arduino/wiring_pulse.c | 69 --- .../cores/Copy of arduino/wiring_shift.c | 55 -- .../Sanguino/cores/arduino/HardwareSerial.cpp | 142 +---- Marlin/temperature.cpp | 61 ++- 25 files changed, 68 insertions(+), 3862 deletions(-) delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/Print.cpp delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/Print.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/Tone.cpp delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/WCharacter.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/WConstants.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/WMath.cpp delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/WProgram.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/WString.cpp delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/WString.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/binary.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/main.cpp delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring.c delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_private.h delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c delete mode 100644 Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c diff --git a/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp b/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp deleted file mode 100644 index 4397efb7ee..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - HardwareSerial.cpp - Hardware serial library for Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 23 November 2006 by David A. Mellis - Modified 28 September 2010 by Mark Sproul -*/ - -#include -#include -#include -#include -#include "wiring.h" -#include "wiring_private.h" - -// this next line disables the entire HardwareSerial.cpp, -// this is so I can support Attiny series and any other chip without a uart -#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) - -#include "HardwareSerial.h" - -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which rx_buffer_head is the index of the -// location to which to write the next incoming character and rx_buffer_tail -// is the index of the location from which to read. -#if (RAMEND < 1000) - #define RX_BUFFER_SIZE 32 -#else - #define RX_BUFFER_SIZE 128 -#endif - -struct ring_buffer -{ - unsigned char buffer[RX_BUFFER_SIZE]; - int head; - int tail; -}; - -#if defined(UBRRH) || defined(UBRR0H) - ring_buffer rx_buffer = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR1H) - ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR2H) - ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR3H) - ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; -#endif - -inline void store_char(unsigned char c, ring_buffer *rx_buffer) -{ - int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; - - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if (i != rx_buffer->tail) { - rx_buffer->buffer[rx_buffer->head] = c; - rx_buffer->head = i; - } -} - -#if defined(USART_RX_vect) - SIGNAL(USART_RX_vect) - { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; // atmega8535 - #else - #error UDR not defined - #endif - store_char(c, &rx_buffer); - } -#elif defined(SIG_USART0_RECV) && defined(UDR0) - SIGNAL(SIG_USART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -#elif defined(SIG_UART0_RECV) && defined(UDR0) - SIGNAL(SIG_UART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -//#elif defined(SIG_USART_RECV) -#elif defined(USART0_RX_vect) - // fixed by Mark Sproul this is on the 644/644p - //SIGNAL(SIG_USART_RECV) - SIGNAL(USART0_RX_vect) - { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; // atmega8, atmega32 - #else - #error UDR not defined - #endif - store_char(c, &rx_buffer); - } -#elif defined(SIG_UART_RECV) - // this is for atmega8 - SIGNAL(SIG_UART_RECV) - { - #if defined(UDR0) - unsigned char c = UDR0; // atmega645 - #elif defined(UDR) - unsigned char c = UDR; // atmega8 - #endif - store_char(c, &rx_buffer); - } -#elif defined(USBCON) - #warning No interrupt handler for usart 0 - #warning Serial(0) is on USB interface -#else - #error No interrupt handler for usart 0 -#endif - -//#if defined(SIG_USART1_RECV) -#if defined(USART1_RX_vect) - //SIGNAL(SIG_USART1_RECV) - SIGNAL(USART1_RX_vect) - { - unsigned char c = UDR1; - store_char(c, &rx_buffer1); - } -#elif defined(SIG_USART1_RECV) - #error SIG_USART1_RECV -#endif - -#if defined(USART2_RX_vect) && defined(UDR2) - SIGNAL(USART2_RX_vect) - { - unsigned char c = UDR2; - store_char(c, &rx_buffer2); - } -#elif defined(SIG_USART2_RECV) - #error SIG_USART2_RECV -#endif - -#if defined(USART3_RX_vect) && defined(UDR3) - SIGNAL(USART3_RX_vect) - { - unsigned char c = UDR3; - store_char(c, &rx_buffer3); - } -#elif defined(SIG_USART3_RECV) - #error SIG_USART3_RECV -#endif - - - -// Constructors //////////////////////////////////////////////////////////////// - -HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) -{ - _rx_buffer = rx_buffer; - _ubrrh = ubrrh; - _ubrrl = ubrrl; - _ucsra = ucsra; - _ucsrb = ucsrb; - _udr = udr; - _rxen = rxen; - _txen = txen; - _rxcie = rxcie; - _udre = udre; - _u2x = u2x; -} - -// Public Methods ////////////////////////////////////////////////////////////// - -void HardwareSerial::begin(long baud) -{ - uint16_t baud_setting; - bool use_u2x = true; - -#if F_CPU == 16000000UL - // hardcoded exception for compatibility with the bootloader shipped - // with the Duemilanove and previous boards and the firmware on the 8U2 - // on the Uno and Mega 2560. - if (baud == 57600) { - use_u2x = false; - } -#endif - - if (use_u2x) { - *_ucsra = 1 << _u2x; - baud_setting = (F_CPU / 4 / baud - 1) / 2; - } else { - *_ucsra = 0; - baud_setting = (F_CPU / 8 / baud - 1) / 2; - } - - // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) - *_ubrrh = baud_setting >> 8; - *_ubrrl = baud_setting; - - sbi(*_ucsrb, _rxen); - sbi(*_ucsrb, _txen); - sbi(*_ucsrb, _rxcie); -} - -void HardwareSerial::end() -{ - cbi(*_ucsrb, _rxen); - cbi(*_ucsrb, _txen); - cbi(*_ucsrb, _rxcie); -} - -int HardwareSerial::available(void) -{ - return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; -} - -int HardwareSerial::peek(void) -{ - if (_rx_buffer->head == _rx_buffer->tail) { - return -1; - } else { - return _rx_buffer->buffer[_rx_buffer->tail]; - } -} - -int HardwareSerial::read(void) -{ - // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) { - return -1; - } else { - unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; - return c; - } -} - -void HardwareSerial::flush() -{ - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // don't reverse this or there may be problems if the RX interrupt - // occurs after reading the value of rx_buffer_head but before writing - // the value to rx_buffer_tail; the previous value of rx_buffer_head - // may be written to rx_buffer_tail, making it appear as if the buffer - // were full, not empty. - _rx_buffer->head = _rx_buffer->tail; -} - -void HardwareSerial::write(uint8_t c) -{ - while (!((*_ucsra) & (1 << _udre))) - ; - - *_udr = c; -} - -// Preinstantiate Objects ////////////////////////////////////////////////////// - -#if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); -#elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); -#elif defined(USBCON) - #warning no serial port defined (port 0) -#else - #error no serial port defined (port 0) -#endif - -#if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); -#endif -#if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); -#endif -#if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); -#endif - -#endif // whole file - diff --git a/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h b/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h deleted file mode 100644 index 3efa775f84..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/HardwareSerial.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - HardwareSerial.h - Hardware serial library for Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 28 September 2010 by Mark Sproul -*/ - -#ifndef HardwareSerial_h -#define HardwareSerial_h - -#include - -#include "Stream.h" - -struct ring_buffer; - -class HardwareSerial : public Stream -{ - private: - ring_buffer *_rx_buffer; - volatile uint8_t *_ubrrh; - volatile uint8_t *_ubrrl; - volatile uint8_t *_ucsra; - volatile uint8_t *_ucsrb; - volatile uint8_t *_udr; - uint8_t _rxen; - uint8_t _txen; - uint8_t _rxcie; - uint8_t _udre; - uint8_t _u2x; - public: - HardwareSerial(ring_buffer *rx_buffer, - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); - void begin(long); - void end(); - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual void write(uint8_t); - using Print::write; // pull in write(str) and write(buf, size) from Print -}; - -#if defined(UBRRH) || defined(UBRR0H) - extern HardwareSerial Serial; -#elif defined(USBCON) - #include "usb_api.h" -#endif -#if defined(UBRR1H) - extern HardwareSerial Serial1; -#endif -#if defined(UBRR2H) - extern HardwareSerial Serial2; -#endif -#if defined(UBRR3H) - extern HardwareSerial Serial3; -#endif - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/Print.cpp b/Marlin/Sanguino/cores/Copy of arduino/Print.cpp deleted file mode 100644 index 4ee556dd82..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/Print.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - Print.cpp - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 23 November 2006 by David A. Mellis - */ - -#include -#include -#include -#include -#include "wiring.h" - -#include "Print.h" - -// Public Methods ////////////////////////////////////////////////////////////// - -/* default implementation: may be overridden */ -void Print::write(const char *str) -{ - while (*str) - write(*str++); -} - -/* default implementation: may be overridden */ -void Print::write(const uint8_t *buffer, size_t size) -{ - while (size--) - write(*buffer++); -} - -void Print::print(const String &s) -{ - for (int i = 0; i < s.length(); i++) { - write(s[i]); - } -} - -void Print::print(const char str[]) -{ - write(str); -} - -void Print::print(char c, int base) -{ - print((long) c, base); -} - -void Print::print(unsigned char b, int base) -{ - print((unsigned long) b, base); -} - -void Print::print(int n, int base) -{ - print((long) n, base); -} - -void Print::print(unsigned int n, int base) -{ - print((unsigned long) n, base); -} - -void Print::print(long n, int base) -{ - if (base == 0) { - write(n); - } else if (base == 10) { - if (n < 0) { - print('-'); - n = -n; - } - printNumber(n, 10); - } else { - printNumber(n, base); - } -} - -void Print::print(unsigned long n, int base) -{ - if (base == 0) write(n); - else printNumber(n, base); -} - -void Print::print(double n, int digits) -{ - printFloat(n, digits); -} - -void Print::println(void) -{ - print('\r'); - print('\n'); -} - -void Print::println(const String &s) -{ - print(s); - println(); -} - -void Print::println(const char c[]) -{ - print(c); - println(); -} - -void Print::println(char c, int base) -{ - print(c, base); - println(); -} - -void Print::println(unsigned char b, int base) -{ - print(b, base); - println(); -} - -void Print::println(int n, int base) -{ - print(n, base); - println(); -} - -void Print::println(unsigned int n, int base) -{ - print(n, base); - println(); -} - -void Print::println(long n, int base) -{ - print(n, base); - println(); -} - -void Print::println(unsigned long n, int base) -{ - print(n, base); - println(); -} - -void Print::println(double n, int digits) -{ - print(n, digits); - println(); -} - -// Private Methods ///////////////////////////////////////////////////////////// - -void Print::printNumber(unsigned long n, uint8_t base) -{ - unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. - unsigned long i = 0; - - if (n == 0) { - print('0'); - return; - } - - while (n > 0) { - buf[i++] = n % base; - n /= base; - } - - for (; i > 0; i--) - print((char) (buf[i - 1] < 10 ? - '0' + buf[i - 1] : - 'A' + buf[i - 1] - 10)); -} - -void Print::printFloat(double number, uint8_t digits) -{ - // Handle negative numbers - if (number < 0.0) - { - print('-'); - number = -number; - } - - // Round correctly so that print(1.999, 2) prints as "2.00" - double rounding = 0.5; - for (uint8_t i=0; i 0) - print("."); - - // Extract digits from the remainder one at a time - while (digits-- > 0) - { - remainder *= 10.0; - int toPrint = int(remainder); - print(toPrint); - remainder -= toPrint; - } -} diff --git a/Marlin/Sanguino/cores/Copy of arduino/Print.h b/Marlin/Sanguino/cores/Copy of arduino/Print.h deleted file mode 100644 index b092ae51d1..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/Print.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - Print.h - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef Print_h -#define Print_h - -#include -#include // for size_t - -#include "WString.h" - -#define DEC 10 -#define HEX 16 -#define OCT 8 -#define BIN 2 -#define BYTE 0 - -class Print -{ - private: - void printNumber(unsigned long, uint8_t); - void printFloat(double, uint8_t); - public: - virtual void write(uint8_t) = 0; - virtual void write(const char *str); - virtual void write(const uint8_t *buffer, size_t size); - - void print(const String &); - void print(const char[]); - void print(char, int = BYTE); - void print(unsigned char, int = BYTE); - void print(int, int = DEC); - void print(unsigned int, int = DEC); - void print(long, int = DEC); - void print(unsigned long, int = DEC); - void print(double, int = 2); - - void println(const String &s); - void println(const char[]); - void println(char, int = BYTE); - void println(unsigned char, int = BYTE); - void println(int, int = DEC); - void println(unsigned int, int = DEC); - void println(long, int = DEC); - void println(unsigned long, int = DEC); - void println(double, int = 2); - void println(void); -}; - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/Tone.cpp b/Marlin/Sanguino/cores/Copy of arduino/Tone.cpp deleted file mode 100644 index 827fe49ef4..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/Tone.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* Tone.cpp - - A Tone Generator Library - - Written by Brett Hagman - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Version Modified By Date Comments -------- ----------- -------- -------- -0001 B Hagman 09/08/02 Initial coding -0002 B Hagman 09/08/18 Multiple pins -0003 B Hagman 09/08/18 Moved initialization from constructor to begin() -0004 B Hagman 09/09/26 Fixed problems with ATmega8 -0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers - 09/11/25 Changed pin toggle method to XOR - 09/11/25 Fixed timer0 from being excluded -0006 D Mellis 09/12/29 Replaced objects with functions - -*************************************************/ - -#include -#include -#include -#include - -#if defined(__AVR_ATmega8__) -#define TCCR2A TCCR2 -#define TCCR2B TCCR2 -#define COM2A1 COM21 -#define COM2A0 COM20 -#define OCR2A OCR2 -#define TIMSK2 TIMSK -#define OCIE2A OCIE2 -#define TIMER2_COMPA_vect TIMER2_COMP_vect -#define TIMSK1 TIMSK -#endif - -// timerx_toggle_count: -// > 0 - duration specified -// = 0 - stopped -// < 0 - infinitely (until stop() method called, or new play() called) - -#if !defined(__AVR_ATmega8__) -volatile long timer0_toggle_count; -volatile uint8_t *timer0_pin_port; -volatile uint8_t timer0_pin_mask; -#endif - -volatile long timer1_toggle_count; -volatile uint8_t *timer1_pin_port; -volatile uint8_t timer1_pin_mask; -volatile long timer2_toggle_count; -volatile uint8_t *timer2_pin_port; -volatile uint8_t timer2_pin_mask; - -#if defined(__AVR_ATmega1280__) -volatile long timer3_toggle_count; -volatile uint8_t *timer3_pin_port; -volatile uint8_t timer3_pin_mask; -volatile long timer4_toggle_count; -volatile uint8_t *timer4_pin_port; -volatile uint8_t timer4_pin_mask; -volatile long timer5_toggle_count; -volatile uint8_t *timer5_pin_port; -volatile uint8_t timer5_pin_mask; -#endif - - -#if defined(__AVR_ATmega1280__) - -#define AVAILABLE_TONE_PINS 1 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; - -#elif defined(__AVR_ATmega8__) - -#define AVAILABLE_TONE_PINS 1 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#else - -#define AVAILABLE_TONE_PINS 1 - -// Leave timer 0 to last. -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; - -#endif - - - -static int8_t toneBegin(uint8_t _pin) -{ - int8_t _timer = -1; - - // if we're already using the pin, the timer should be configured. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == _pin) { - return pgm_read_byte(tone_pin_to_timer_PGM + i); - } - } - - // search for an unused timer. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == 255) { - tone_pins[i] = _pin; - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - break; - } - } - - if (_timer != -1) - { - // Set timer specific stuff - // All timers in CTC mode - // 8 bit timers will require changing prescalar values, - // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar - switch (_timer) - { -#if !defined(__AVR_ATmega8__) - case 0: - // 8 bit timer - TCCR0A = 0; - TCCR0B = 0; - bitWrite(TCCR0A, WGM01, 1); - bitWrite(TCCR0B, CS00, 1); - timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer0_pin_mask = digitalPinToBitMask(_pin); - break; -#endif - - case 1: - // 16 bit timer - TCCR1A = 0; - TCCR1B = 0; - bitWrite(TCCR1B, WGM12, 1); - bitWrite(TCCR1B, CS10, 1); - timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer1_pin_mask = digitalPinToBitMask(_pin); - break; - case 2: - // 8 bit timer - TCCR2A = 0; - TCCR2B = 0; - bitWrite(TCCR2A, WGM21, 1); - bitWrite(TCCR2B, CS20, 1); - timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer2_pin_mask = digitalPinToBitMask(_pin); - break; - -#if defined(__AVR_ATmega1280__) - case 3: - // 16 bit timer - TCCR3A = 0; - TCCR3B = 0; - bitWrite(TCCR3B, WGM32, 1); - bitWrite(TCCR3B, CS30, 1); - timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer3_pin_mask = digitalPinToBitMask(_pin); - break; - case 4: - // 16 bit timer - TCCR4A = 0; - TCCR4B = 0; - bitWrite(TCCR4B, WGM42, 1); - bitWrite(TCCR4B, CS40, 1); - timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer4_pin_mask = digitalPinToBitMask(_pin); - break; - case 5: - // 16 bit timer - TCCR5A = 0; - TCCR5B = 0; - bitWrite(TCCR5B, WGM52, 1); - bitWrite(TCCR5B, CS50, 1); - timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer5_pin_mask = digitalPinToBitMask(_pin); - break; -#endif - } - } - - return _timer; -} - - - -// frequency (in hertz) and duration (in milliseconds). - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) -{ - uint8_t prescalarbits = 0b001; - long toggle_count = 0; - uint32_t ocr = 0; - int8_t _timer; - - _timer = toneBegin(_pin); - - if (_timer >= 0) - { - // Set the pinMode as OUTPUT - pinMode(_pin, OUTPUT); - - // if we are using an 8 bit timer, scan through prescalars to find the best fit - if (_timer == 0 || _timer == 2) - { - ocr = F_CPU / frequency / 2 - 1; - prescalarbits = 0b001; // ck/1: same for both timers - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 8 - 1; - prescalarbits = 0b010; // ck/8: same for both timers - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 32 - 1; - prescalarbits = 0b011; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = _timer == 0 ? 0b011 : 0b100; - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 128 - 1; - prescalarbits = 0b101; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 256 - 1; - prescalarbits = _timer == 0 ? 0b100 : 0b110; - if (ocr > 255) - { - // can't do any better than /1024 - ocr = F_CPU / frequency / 2 / 1024 - 1; - prescalarbits = _timer == 0 ? 0b101 : 0b111; - } - } - } - } - -#if !defined(__AVR_ATmega8__) - if (_timer == 0) - TCCR0B = prescalarbits; - else -#endif - TCCR2B = prescalarbits; - } - else - { - // two choices for the 16 bit timers: ck/1 or ck/64 - ocr = F_CPU / frequency / 2 - 1; - - prescalarbits = 0b001; - if (ocr > 0xffff) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = 0b011; - } - - if (_timer == 1) - TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; -#if defined(__AVR_ATmega1280__) - else if (_timer == 3) - TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; - else if (_timer == 4) - TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; - else if (_timer == 5) - TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; -#endif - - } - - - // Calculate the toggle count - if (duration > 0) - { - toggle_count = 2 * frequency * duration / 1000; - } - else - { - toggle_count = -1; - } - - // Set the OCR for the given timer, - // set the toggle count, - // then turn on the interrupts - switch (_timer) - { - -#if !defined(__AVR_ATmega8__) - case 0: - OCR0A = ocr; - timer0_toggle_count = toggle_count; - bitWrite(TIMSK0, OCIE0A, 1); - break; -#endif - - case 1: - OCR1A = ocr; - timer1_toggle_count = toggle_count; - bitWrite(TIMSK1, OCIE1A, 1); - break; - case 2: - OCR2A = ocr; - timer2_toggle_count = toggle_count; - bitWrite(TIMSK2, OCIE2A, 1); - break; - -#if defined(__AVR_ATmega1280__) - case 3: - OCR3A = ocr; - timer3_toggle_count = toggle_count; - bitWrite(TIMSK3, OCIE3A, 1); - break; - case 4: - OCR4A = ocr; - timer4_toggle_count = toggle_count; - bitWrite(TIMSK4, OCIE4A, 1); - break; - case 5: - OCR5A = ocr; - timer5_toggle_count = toggle_count; - bitWrite(TIMSK5, OCIE5A, 1); - break; -#endif - - } - } -} - - -void noTone(uint8_t _pin) -{ - int8_t _timer = -1; - - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { - if (tone_pins[i] == _pin) { - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - tone_pins[i] = 255; - } - } - - switch (_timer) - { -#if defined(__AVR_ATmega8__) - case 1: - bitWrite(TIMSK1, OCIE1A, 0); - break; - case 2: - bitWrite(TIMSK2, OCIE2A, 0); - break; - -#else - case 0: - TIMSK0 = 0; - break; - case 1: - TIMSK1 = 0; - break; - case 2: - TIMSK2 = 0; - break; -#endif - -#if defined(__AVR_ATmega1280__) - case 3: - TIMSK3 = 0; - break; - case 4: - TIMSK4 = 0; - break; - case 5: - TIMSK5 = 0; - break; -#endif - } - - digitalWrite(_pin, 0); -} - -#if 0 -#if !defined(__AVR_ATmega8__) -ISR(TIMER0_COMPA_vect) -{ - if (timer0_toggle_count != 0) - { - // toggle the pin - *timer0_pin_port ^= timer0_pin_mask; - - if (timer0_toggle_count > 0) - timer0_toggle_count--; - } - else - { - TIMSK0 = 0; // disable the interrupt - *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop - } -} -#endif - - -ISR(TIMER1_COMPA_vect) -{ - if (timer1_toggle_count != 0) - { - // toggle the pin - *timer1_pin_port ^= timer1_pin_mask; - - if (timer1_toggle_count > 0) - timer1_toggle_count--; - } - else - { - TIMSK1 = 0; // disable the interrupt - *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop - } -} -#endif - - -ISR(TIMER2_COMPA_vect) -{ - - if (timer2_toggle_count != 0) - { - // toggle the pin - *timer2_pin_port ^= timer2_pin_mask; - - if (timer2_toggle_count > 0) - timer2_toggle_count--; - } - else - { - TIMSK2 = 0; // disable the interrupt - *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop - } -} - - - -//#if defined(__AVR_ATmega1280__) -#if 0 - -ISR(TIMER3_COMPA_vect) -{ - if (timer3_toggle_count != 0) - { - // toggle the pin - *timer3_pin_port ^= timer3_pin_mask; - - if (timer3_toggle_count > 0) - timer3_toggle_count--; - } - else - { - TIMSK3 = 0; // disable the interrupt - *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop - } -} - -ISR(TIMER4_COMPA_vect) -{ - if (timer4_toggle_count != 0) - { - // toggle the pin - *timer4_pin_port ^= timer4_pin_mask; - - if (timer4_toggle_count > 0) - timer4_toggle_count--; - } - else - { - TIMSK4 = 0; // disable the interrupt - *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop - } -} - -ISR(TIMER5_COMPA_vect) -{ - if (timer5_toggle_count != 0) - { - // toggle the pin - *timer5_pin_port ^= timer5_pin_mask; - - if (timer5_toggle_count > 0) - timer5_toggle_count--; - } - else - { - TIMSK5 = 0; // disable the interrupt - *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop - } -} - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/WCharacter.h b/Marlin/Sanguino/cores/Copy of arduino/WCharacter.h deleted file mode 100644 index 79733b50a5..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/WCharacter.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - WCharacter.h - Character utility functions for Wiring & Arduino - Copyright (c) 2010 Hernando Barragan. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef Character_h -#define Character_h - -#include - -// WCharacter.h prototypes -inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); -inline boolean isAlpha(int c) __attribute__((always_inline)); -inline boolean isAscii(int c) __attribute__((always_inline)); -inline boolean isWhitespace(int c) __attribute__((always_inline)); -inline boolean isControl(int c) __attribute__((always_inline)); -inline boolean isDigit(int c) __attribute__((always_inline)); -inline boolean isGraph(int c) __attribute__((always_inline)); -inline boolean isLowerCase(int c) __attribute__((always_inline)); -inline boolean isPrintable(int c) __attribute__((always_inline)); -inline boolean isPunct(int c) __attribute__((always_inline)); -inline boolean isSpace(int c) __attribute__((always_inline)); -inline boolean isUpperCase(int c) __attribute__((always_inline)); -inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); -inline int toAscii(int c) __attribute__((always_inline)); -inline int toLowerCase(int c) __attribute__((always_inline)); -inline int toUpperCase(int c)__attribute__((always_inline)); - - -// Checks for an alphanumeric character. -// It is equivalent to (isalpha(c) || isdigit(c)). -inline boolean isAlphaNumeric(int c) -{ - return ( isalnum(c) == 0 ? false : true); -} - - -// Checks for an alphabetic character. -// It is equivalent to (isupper(c) || islower(c)). -inline boolean isAlpha(int c) -{ - return ( isalpha(c) == 0 ? false : true); -} - - -// Checks whether c is a 7-bit unsigned char value -// that fits into the ASCII character set. -inline boolean isAscii(int c) -{ - return ( isascii (c) == 0 ? false : true); -} - - -// Checks for a blank character, that is, a space or a tab. -inline boolean isWhitespace(int c) -{ - return ( isblank (c) == 0 ? false : true); -} - - -// Checks for a control character. -inline boolean isControl(int c) -{ - return ( iscntrl (c) == 0 ? false : true); -} - - -// Checks for a digit (0 through 9). -inline boolean isDigit(int c) -{ - return ( isdigit (c) == 0 ? false : true); -} - - -// Checks for any printable character except space. -inline boolean isGraph(int c) -{ - return ( isgraph (c) == 0 ? false : true); -} - - -// Checks for a lower-case character. -inline boolean isLowerCase(int c) -{ - return (islower (c) == 0 ? false : true); -} - - -// Checks for any printable character including space. -inline boolean isPrintable(int c) -{ - return ( isprint (c) == 0 ? false : true); -} - - -// Checks for any printable character which is not a space -// or an alphanumeric character. -inline boolean isPunct(int c) -{ - return ( ispunct (c) == 0 ? false : true); -} - - -// Checks for white-space characters. For the avr-libc library, -// these are: space, formfeed ('\f'), newline ('\n'), carriage -// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). -inline boolean isSpace(int c) -{ - return ( isspace (c) == 0 ? false : true); -} - - -// Checks for an uppercase letter. -inline boolean isUpperCase(int c) -{ - return ( isupper (c) == 0 ? false : true); -} - - -// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 -// 8 9 a b c d e f A B C D E F. -inline boolean isHexadecimalDigit(int c) -{ - return ( isxdigit (c) == 0 ? false : true); -} - - -// Converts c to a 7-bit unsigned char value that fits into the -// ASCII character set, by clearing the high-order bits. -inline int toAscii(int c) -{ - return toascii (c); -} - - -// Warning: -// Many people will be unhappy if you use this function. -// This function will convert accented letters into random -// characters. - -// Converts the letter c to lower case, if possible. -inline int toLowerCase(int c) -{ - return tolower (c); -} - - -// Converts the letter c to upper case, if possible. -inline int toUpperCase(int c) -{ - return toupper (c); -} - -#endif \ No newline at end of file diff --git a/Marlin/Sanguino/cores/Copy of arduino/WConstants.h b/Marlin/Sanguino/cores/Copy of arduino/WConstants.h deleted file mode 100644 index 3e19ac44aa..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/WConstants.h +++ /dev/null @@ -1 +0,0 @@ -#include "wiring.h" diff --git a/Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c b/Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c deleted file mode 100644 index 6f3f0b130a..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/WInterrupts.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Wiring project - http://wiring.uniandes.edu.co - - Copyright (c) 2004-05 Hernando Barragan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - Modified 24 November 2006 by David A. Mellis -*/ - -#include -#include -#include -#include -#include - -#include "WConstants.h" -#include "wiring_private.h" - -volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; -// volatile static voidFuncPtr twiIntFunc; - -void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) -{ - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) - { - intFunc[interruptNum] = userFunc; - - //clear the config for the change settings - EICRA &= ~(B00000011 << (interruptNum * 2)); - - //set our mode. - EICRA |= (mode << (interruptNum * 2)); - - // Enable the interrupt. - EIMSK |= (1 << interruptNum); - } -} - -void detachInterrupt(uint8_t interruptNum) -{ - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) - { - // Disable the interrupt. - EIMSK &= ~(1 << interruptNum); - - intFunc[interruptNum] = 0; - } -} - -ISR(INT0_vect) { - if(intFunc[EXTERNAL_INT_0]) - intFunc[EXTERNAL_INT_0](); -} - -ISR(INT1_vect) { - if(intFunc[EXTERNAL_INT_1]) - intFunc[EXTERNAL_INT_1](); -} - -ISR(INT2_vect) { - if(intFunc[EXTERNAL_INT_2]) - intFunc[EXTERNAL_INT_2](); -} - -/* -SIGNAL(SIG_2WIRE_SERIAL) { - if(twiIntFunc) - twiIntFunc(); -} -*/ - diff --git a/Marlin/Sanguino/cores/Copy of arduino/WMath.cpp b/Marlin/Sanguino/cores/Copy of arduino/WMath.cpp deleted file mode 100644 index 2120c4cc10..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/WMath.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Wiring project - http://wiring.org.co - Copyright (c) 2004-06 Hernando Barragan - Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/ - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id$ -*/ - -extern "C" { - #include "stdlib.h" -} - -void randomSeed(unsigned int seed) -{ - if (seed != 0) { - srandom(seed); - } -} - -long random(long howbig) -{ - if (howbig == 0) { - return 0; - } - return random() % howbig; -} - -long random(long howsmall, long howbig) -{ - if (howsmall >= howbig) { - return howsmall; - } - long diff = howbig - howsmall; - return random(diff) + howsmall; -} - -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -unsigned int makeWord(unsigned int w) { return w; } -unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } \ No newline at end of file diff --git a/Marlin/Sanguino/cores/Copy of arduino/WProgram.h b/Marlin/Sanguino/cores/Copy of arduino/WProgram.h deleted file mode 100644 index f73e760bbe..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/WProgram.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef WProgram_h -#define WProgram_h - -#include -#include -#include - -#include - -#include "wiring.h" - -#ifdef __cplusplus -#include "WCharacter.h" -#include "WString.h" -#include "HardwareSerial.h" - -uint16_t makeWord(uint16_t w); -uint16_t makeWord(byte h, byte l); - -#define word(...) makeWord(__VA_ARGS__) - -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); -void noTone(uint8_t _pin); - -// WMath prototypes -long random(long); -long random(long, long); -void randomSeed(unsigned int); -long map(long, long, long, long, long); - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -const static uint8_t A0 = 54; -const static uint8_t A1 = 55; -const static uint8_t A2 = 56; -const static uint8_t A3 = 57; -const static uint8_t A4 = 58; -const static uint8_t A5 = 59; -const static uint8_t A6 = 60; -const static uint8_t A7 = 61; -const static uint8_t A8 = 62; -const static uint8_t A9 = 63; -const static uint8_t A10 = 64; -const static uint8_t A11 = 65; -const static uint8_t A12 = 66; -const static uint8_t A13 = 67; -const static uint8_t A14 = 68; -const static uint8_t A15 = 69; -#else -const static uint8_t A0 = 14; -const static uint8_t A1 = 15; -const static uint8_t A2 = 16; -const static uint8_t A3 = 17; -const static uint8_t A4 = 18; -const static uint8_t A5 = 19; -const static uint8_t A6 = 20; -const static uint8_t A7 = 21; -#endif - -#endif - -#endif \ No newline at end of file diff --git a/Marlin/Sanguino/cores/Copy of arduino/WString.cpp b/Marlin/Sanguino/cores/Copy of arduino/WString.cpp deleted file mode 100644 index db5a441dc2..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/WString.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/* - WString.cpp - String library for Wiring & Arduino - Copyright (c) 2009-10 Hernando Barragan. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include "WProgram.h" -#include "WString.h" - - -String::String( const char *value ) -{ - if ( value == NULL ) - value = ""; - getBuffer( _length = strlen( value ) ); - if ( _buffer != NULL ) - strcpy( _buffer, value ); -} - -String::String( const String &value ) -{ - getBuffer( _length = value._length ); - if ( _buffer != NULL ) - strcpy( _buffer, value._buffer ); -} - -String::String( const char value ) -{ - _length = 1; - getBuffer(1); - if ( _buffer != NULL ) { - _buffer[0] = value; - _buffer[1] = 0; - } -} - -String::String( const unsigned char value ) -{ - _length = 1; - getBuffer(1); - if ( _buffer != NULL) { - _buffer[0] = value; - _buffer[1] = 0; - } -} - -String::String( const int value, const int base ) -{ - char buf[33]; - itoa((signed long)value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); -} - -String::String( const unsigned int value, const int base ) -{ - char buf[33]; - ultoa((unsigned long)value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); -} - -String::String( const long value, const int base ) -{ - char buf[33]; - ltoa(value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); -} - -String::String( const unsigned long value, const int base ) -{ - char buf[33]; - ultoa(value, buf, 10); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); -} - -char String::charAt( unsigned int loc ) const -{ - return operator[]( loc ); -} - -void String::setCharAt( unsigned int loc, const char aChar ) -{ - if(_buffer == NULL) return; - if(_length > loc) { - _buffer[loc] = aChar; - } -} - -int String::compareTo( const String &s2 ) const -{ - return strcmp( _buffer, s2._buffer ); -} - -const String & String::concat( const String &s2 ) -{ - return (*this) += s2; -} - -const String & String::operator=( const String &rhs ) -{ - if ( this == &rhs ) - return *this; - - if ( rhs._length > _length ) - { - free(_buffer); - getBuffer( rhs._length ); - } - - if ( _buffer != NULL ) { - _length = rhs._length; - strcpy( _buffer, rhs._buffer ); - } - return *this; -} - -//const String & String::operator+=( const char aChar ) -//{ -// if ( _length == _capacity ) -// doubleBuffer(); -// -// _buffer[ _length++ ] = aChar; -// _buffer[ _length ] = '\0'; -// return *this; -//} - -const String & String::operator+=( const String &other ) -{ - _length += other._length; - if ( _length > _capacity ) - { - char *temp = (char *)realloc(_buffer, _length + 1); - if ( temp != NULL ) { - _buffer = temp; - _capacity = _length; - } else { - _length -= other._length; - return *this; - } - } - strcat( _buffer, other._buffer ); - return *this; -} - - -int String::operator==( const String &rhs ) const -{ - return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 ); -} - -int String::operator!=( const String &rhs ) const -{ - return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 ); -} - -int String::operator<( const String &rhs ) const -{ - return strcmp( _buffer, rhs._buffer ) < 0; -} - -int String::operator>( const String &rhs ) const -{ - return strcmp( _buffer, rhs._buffer ) > 0; -} - -int String::operator<=( const String &rhs ) const -{ - return strcmp( _buffer, rhs._buffer ) <= 0; -} - -int String::operator>=( const String & rhs ) const -{ - return strcmp( _buffer, rhs._buffer ) >= 0; -} - -char & String::operator[]( unsigned int index ) -{ - static char dummy_writable_char; - if (index >= _length || !_buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return _buffer[ index ]; -} - -char String::operator[]( unsigned int index ) const -{ - // need to check for valid index, to do later - return _buffer[ index ]; -} - -boolean String::endsWith( const String &s2 ) const -{ - if ( _length < s2._length ) - return 0; - - return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0; -} - -boolean String::equals( const String &s2 ) const -{ - return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 ); -} - -boolean String::equalsIgnoreCase( const String &s2 ) const -{ - if ( this == &s2 ) - return true; //1; - else if ( _length != s2._length ) - return false; //0; - - return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0; -} - -String String::replace( char findChar, char replaceChar ) -{ - if ( _buffer == NULL ) return *this; - String theReturn = _buffer; - char* temp = theReturn._buffer; - while( (temp = strchr( temp, findChar )) != 0 ) - *temp = replaceChar; - - return theReturn; -} - -String String::replace( const String& match, const String& replace ) -{ - if ( _buffer == NULL ) return *this; - String temp = _buffer, newString; - - int loc; - while ( (loc = temp.indexOf( match )) != -1 ) - { - newString += temp.substring( 0, loc ); - newString += replace; - temp = temp.substring( loc + match._length ); - } - newString += temp; - return newString; -} - -int String::indexOf( char temp ) const -{ - return indexOf( temp, 0 ); -} - -int String::indexOf( char ch, unsigned int fromIndex ) const -{ - if ( fromIndex >= _length ) - return -1; - - const char* temp = strchr( &_buffer[fromIndex], ch ); - if ( temp == NULL ) - return -1; - - return temp - _buffer; -} - -int String::indexOf( const String &s2 ) const -{ - return indexOf( s2, 0 ); -} - -int String::indexOf( const String &s2, unsigned int fromIndex ) const -{ - if ( fromIndex >= _length ) - return -1; - - const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer ); - - if ( theFind == NULL ) - return -1; - - return theFind - _buffer; // pointer subtraction -} - -int String::lastIndexOf( char theChar ) const -{ - return lastIndexOf( theChar, _length - 1 ); -} - -int String::lastIndexOf( char ch, unsigned int fromIndex ) const -{ - if ( fromIndex >= _length ) - return -1; - - char tempchar = _buffer[fromIndex + 1]; - _buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( _buffer, ch ); - _buffer[fromIndex + 1] = tempchar; - - if ( temp == NULL ) - return -1; - - return temp - _buffer; -} - -int String::lastIndexOf( const String &s2 ) const -{ - return lastIndexOf( s2, _length - s2._length ); -} - -int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const -{ - // check for empty strings - if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length ) - return -1; - - // matching first character - char temp = s2[ 0 ]; - - for ( int i = fromIndex; i >= 0; i-- ) - { - if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) ) - return i; - } - return -1; -} - -boolean String::startsWith( const String &s2 ) const -{ - if ( _length < s2._length ) - return 0; - - return startsWith( s2, 0 ); -} - -boolean String::startsWith( const String &s2, unsigned int offset ) const -{ - if ( offset > _length - s2._length ) - return 0; - - return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0; -} - -String String::substring( unsigned int left ) const -{ - return substring( left, _length ); -} - -String String::substring( unsigned int left, unsigned int right ) const -{ - if ( left > right ) - { - int temp = right; - right = left; - left = temp; - } - - if ( right > _length ) - { - right = _length; - } - - char temp = _buffer[ right ]; // save the replaced character - _buffer[ right ] = '\0'; - String outPut = ( _buffer + left ); // pointer arithmetic - _buffer[ right ] = temp; //restore character - return outPut; -} - -String String::toLowerCase() const -{ - String temp = _buffer; - - for ( unsigned int i = 0; i < _length; i++ ) - temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] ); - return temp; -} - -String String::toUpperCase() const -{ - String temp = _buffer; - - for ( unsigned int i = 0; i < _length; i++ ) - temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] ); - return temp; -} - -String String::trim() const -{ - if ( _buffer == NULL ) return *this; - String temp = _buffer; - unsigned int i,j; - - for ( i = 0; i < _length; i++ ) - { - if ( !isspace(_buffer[i]) ) - break; - } - - for ( j = temp._length - 1; j > i; j-- ) - { - if ( !isspace(_buffer[j]) ) - break; - } - - return temp.substring( i, j + 1); -} - -void String::getBytes(unsigned char *buf, unsigned int bufsize) -{ - if (!bufsize || !buf) return; - unsigned int len = bufsize - 1; - if (len > _length) len = _length; - strncpy((char *)buf, _buffer, len); - buf[len] = 0; -} - -void String::toCharArray(char *buf, unsigned int bufsize) -{ - if (!bufsize || !buf) return; - unsigned int len = bufsize - 1; - if (len > _length) len = _length; - strncpy(buf, _buffer, len); - buf[len] = 0; -} - - -long String::toInt() { - return atol(_buffer); -} diff --git a/Marlin/Sanguino/cores/Copy of arduino/WString.h b/Marlin/Sanguino/cores/Copy of arduino/WString.h deleted file mode 100644 index cadddb9476..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/WString.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - WString.h - String library for Wiring & Arduino - Copyright (c) 2009-10 Hernando Barragan. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef String_h -#define String_h - -//#include "WProgram.h" -#include -#include -#include - -class String -{ - public: - // constructors - String( const char *value = "" ); - String( const String &value ); - String( const char ); - String( const unsigned char ); - String( const int, const int base=10); - String( const unsigned int, const int base=10 ); - String( const long, const int base=10 ); - String( const unsigned long, const int base=10 ); - ~String() { free(_buffer); _length = _capacity = 0;} //added _length = _capacity = 0; - - // operators - const String & operator = ( const String &rhs ); - const String & operator +=( const String &rhs ); - //const String & operator +=( const char ); - int operator ==( const String &rhs ) const; - int operator !=( const String &rhs ) const; - int operator < ( const String &rhs ) const; - int operator > ( const String &rhs ) const; - int operator <=( const String &rhs ) const; - int operator >=( const String &rhs ) const; - char operator []( unsigned int index ) const; - char& operator []( unsigned int index ); - //operator const char *() const { return _buffer; } - - // general methods - char charAt( unsigned int index ) const; - int compareTo( const String &anotherString ) const; - unsigned char endsWith( const String &suffix ) const; - unsigned char equals( const String &anObject ) const; - unsigned char equalsIgnoreCase( const String &anotherString ) const; - int indexOf( char ch ) const; - int indexOf( char ch, unsigned int fromIndex ) const; - int indexOf( const String &str ) const; - int indexOf( const String &str, unsigned int fromIndex ) const; - int lastIndexOf( char ch ) const; - int lastIndexOf( char ch, unsigned int fromIndex ) const; - int lastIndexOf( const String &str ) const; - int lastIndexOf( const String &str, unsigned int fromIndex ) const; - const unsigned int length( ) const { return _length; } - void setCharAt(unsigned int index, const char ch); - unsigned char startsWith( const String &prefix ) const; - unsigned char startsWith( const String &prefix, unsigned int toffset ) const; - String substring( unsigned int beginIndex ) const; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - String toLowerCase( ) const; - String toUpperCase( ) const; - String trim( ) const; - void getBytes(unsigned char *buf, unsigned int bufsize); - void toCharArray(char *buf, unsigned int bufsize); - long toInt( ); - const String& concat( const String &str ); - String replace( char oldChar, char newChar ); - String replace( const String& match, const String& replace ); - friend String operator + ( String lhs, const String &rhs ); - - protected: - char *_buffer; // the actual char array - unsigned int _capacity; // the array length minus one (for the '\0') - unsigned int _length; // the String length (not counting the '\0') - - void getBuffer(unsigned int maxStrLen); - - private: - -}; - -// allocate buffer space -inline void String::getBuffer(unsigned int maxStrLen) -{ - _capacity = maxStrLen; - _buffer = (char *) malloc(_capacity + 1); - if (_buffer == NULL) _length = _capacity = 0; -} - -inline String operator+( String lhs, const String &rhs ) -{ - return lhs += rhs; -} - - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/binary.h b/Marlin/Sanguino/cores/Copy of arduino/binary.h deleted file mode 100644 index af1498033a..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/binary.h +++ /dev/null @@ -1,515 +0,0 @@ -#ifndef Binary_h -#define Binary_h - -#define B0 0 -#define B00 0 -#define B000 0 -#define B0000 0 -#define B00000 0 -#define B000000 0 -#define B0000000 0 -#define B00000000 0 -#define B1 1 -#define B01 1 -#define B001 1 -#define B0001 1 -#define B00001 1 -#define B000001 1 -#define B0000001 1 -#define B00000001 1 -#define B10 2 -#define B010 2 -#define B0010 2 -#define B00010 2 -#define B000010 2 -#define B0000010 2 -#define B00000010 2 -#define B11 3 -#define B011 3 -#define B0011 3 -#define B00011 3 -#define B000011 3 -#define B0000011 3 -#define B00000011 3 -#define B100 4 -#define B0100 4 -#define B00100 4 -#define B000100 4 -#define B0000100 4 -#define B00000100 4 -#define B101 5 -#define B0101 5 -#define B00101 5 -#define B000101 5 -#define B0000101 5 -#define B00000101 5 -#define B110 6 -#define B0110 6 -#define B00110 6 -#define B000110 6 -#define B0000110 6 -#define B00000110 6 -#define B111 7 -#define B0111 7 -#define B00111 7 -#define B000111 7 -#define B0000111 7 -#define B00000111 7 -#define B1000 8 -#define B01000 8 -#define B001000 8 -#define B0001000 8 -#define B00001000 8 -#define B1001 9 -#define B01001 9 -#define B001001 9 -#define B0001001 9 -#define B00001001 9 -#define B1010 10 -#define B01010 10 -#define B001010 10 -#define B0001010 10 -#define B00001010 10 -#define B1011 11 -#define B01011 11 -#define B001011 11 -#define B0001011 11 -#define B00001011 11 -#define B1100 12 -#define B01100 12 -#define B001100 12 -#define B0001100 12 -#define B00001100 12 -#define B1101 13 -#define B01101 13 -#define B001101 13 -#define B0001101 13 -#define B00001101 13 -#define B1110 14 -#define B01110 14 -#define B001110 14 -#define B0001110 14 -#define B00001110 14 -#define B1111 15 -#define B01111 15 -#define B001111 15 -#define B0001111 15 -#define B00001111 15 -#define B10000 16 -#define B010000 16 -#define B0010000 16 -#define B00010000 16 -#define B10001 17 -#define B010001 17 -#define B0010001 17 -#define B00010001 17 -#define B10010 18 -#define B010010 18 -#define B0010010 18 -#define B00010010 18 -#define B10011 19 -#define B010011 19 -#define B0010011 19 -#define B00010011 19 -#define B10100 20 -#define B010100 20 -#define B0010100 20 -#define B00010100 20 -#define B10101 21 -#define B010101 21 -#define B0010101 21 -#define B00010101 21 -#define B10110 22 -#define B010110 22 -#define B0010110 22 -#define B00010110 22 -#define B10111 23 -#define B010111 23 -#define B0010111 23 -#define B00010111 23 -#define B11000 24 -#define B011000 24 -#define B0011000 24 -#define B00011000 24 -#define B11001 25 -#define B011001 25 -#define B0011001 25 -#define B00011001 25 -#define B11010 26 -#define B011010 26 -#define B0011010 26 -#define B00011010 26 -#define B11011 27 -#define B011011 27 -#define B0011011 27 -#define B00011011 27 -#define B11100 28 -#define B011100 28 -#define B0011100 28 -#define B00011100 28 -#define B11101 29 -#define B011101 29 -#define B0011101 29 -#define B00011101 29 -#define B11110 30 -#define B011110 30 -#define B0011110 30 -#define B00011110 30 -#define B11111 31 -#define B011111 31 -#define B0011111 31 -#define B00011111 31 -#define B100000 32 -#define B0100000 32 -#define B00100000 32 -#define B100001 33 -#define B0100001 33 -#define B00100001 33 -#define B100010 34 -#define B0100010 34 -#define B00100010 34 -#define B100011 35 -#define B0100011 35 -#define B00100011 35 -#define B100100 36 -#define B0100100 36 -#define B00100100 36 -#define B100101 37 -#define B0100101 37 -#define B00100101 37 -#define B100110 38 -#define B0100110 38 -#define B00100110 38 -#define B100111 39 -#define B0100111 39 -#define B00100111 39 -#define B101000 40 -#define B0101000 40 -#define B00101000 40 -#define B101001 41 -#define B0101001 41 -#define B00101001 41 -#define B101010 42 -#define B0101010 42 -#define B00101010 42 -#define B101011 43 -#define B0101011 43 -#define B00101011 43 -#define B101100 44 -#define B0101100 44 -#define B00101100 44 -#define B101101 45 -#define B0101101 45 -#define B00101101 45 -#define B101110 46 -#define B0101110 46 -#define B00101110 46 -#define B101111 47 -#define B0101111 47 -#define B00101111 47 -#define B110000 48 -#define B0110000 48 -#define B00110000 48 -#define B110001 49 -#define B0110001 49 -#define B00110001 49 -#define B110010 50 -#define B0110010 50 -#define B00110010 50 -#define B110011 51 -#define B0110011 51 -#define B00110011 51 -#define B110100 52 -#define B0110100 52 -#define B00110100 52 -#define B110101 53 -#define B0110101 53 -#define B00110101 53 -#define B110110 54 -#define B0110110 54 -#define B00110110 54 -#define B110111 55 -#define B0110111 55 -#define B00110111 55 -#define B111000 56 -#define B0111000 56 -#define B00111000 56 -#define B111001 57 -#define B0111001 57 -#define B00111001 57 -#define B111010 58 -#define B0111010 58 -#define B00111010 58 -#define B111011 59 -#define B0111011 59 -#define B00111011 59 -#define B111100 60 -#define B0111100 60 -#define B00111100 60 -#define B111101 61 -#define B0111101 61 -#define B00111101 61 -#define B111110 62 -#define B0111110 62 -#define B00111110 62 -#define B111111 63 -#define B0111111 63 -#define B00111111 63 -#define B1000000 64 -#define B01000000 64 -#define B1000001 65 -#define B01000001 65 -#define B1000010 66 -#define B01000010 66 -#define B1000011 67 -#define B01000011 67 -#define B1000100 68 -#define B01000100 68 -#define B1000101 69 -#define B01000101 69 -#define B1000110 70 -#define B01000110 70 -#define B1000111 71 -#define B01000111 71 -#define B1001000 72 -#define B01001000 72 -#define B1001001 73 -#define B01001001 73 -#define B1001010 74 -#define B01001010 74 -#define B1001011 75 -#define B01001011 75 -#define B1001100 76 -#define B01001100 76 -#define B1001101 77 -#define B01001101 77 -#define B1001110 78 -#define B01001110 78 -#define B1001111 79 -#define B01001111 79 -#define B1010000 80 -#define B01010000 80 -#define B1010001 81 -#define B01010001 81 -#define B1010010 82 -#define B01010010 82 -#define B1010011 83 -#define B01010011 83 -#define B1010100 84 -#define B01010100 84 -#define B1010101 85 -#define B01010101 85 -#define B1010110 86 -#define B01010110 86 -#define B1010111 87 -#define B01010111 87 -#define B1011000 88 -#define B01011000 88 -#define B1011001 89 -#define B01011001 89 -#define B1011010 90 -#define B01011010 90 -#define B1011011 91 -#define B01011011 91 -#define B1011100 92 -#define B01011100 92 -#define B1011101 93 -#define B01011101 93 -#define B1011110 94 -#define B01011110 94 -#define B1011111 95 -#define B01011111 95 -#define B1100000 96 -#define B01100000 96 -#define B1100001 97 -#define B01100001 97 -#define B1100010 98 -#define B01100010 98 -#define B1100011 99 -#define B01100011 99 -#define B1100100 100 -#define B01100100 100 -#define B1100101 101 -#define B01100101 101 -#define B1100110 102 -#define B01100110 102 -#define B1100111 103 -#define B01100111 103 -#define B1101000 104 -#define B01101000 104 -#define B1101001 105 -#define B01101001 105 -#define B1101010 106 -#define B01101010 106 -#define B1101011 107 -#define B01101011 107 -#define B1101100 108 -#define B01101100 108 -#define B1101101 109 -#define B01101101 109 -#define B1101110 110 -#define B01101110 110 -#define B1101111 111 -#define B01101111 111 -#define B1110000 112 -#define B01110000 112 -#define B1110001 113 -#define B01110001 113 -#define B1110010 114 -#define B01110010 114 -#define B1110011 115 -#define B01110011 115 -#define B1110100 116 -#define B01110100 116 -#define B1110101 117 -#define B01110101 117 -#define B1110110 118 -#define B01110110 118 -#define B1110111 119 -#define B01110111 119 -#define B1111000 120 -#define B01111000 120 -#define B1111001 121 -#define B01111001 121 -#define B1111010 122 -#define B01111010 122 -#define B1111011 123 -#define B01111011 123 -#define B1111100 124 -#define B01111100 124 -#define B1111101 125 -#define B01111101 125 -#define B1111110 126 -#define B01111110 126 -#define B1111111 127 -#define B01111111 127 -#define B10000000 128 -#define B10000001 129 -#define B10000010 130 -#define B10000011 131 -#define B10000100 132 -#define B10000101 133 -#define B10000110 134 -#define B10000111 135 -#define B10001000 136 -#define B10001001 137 -#define B10001010 138 -#define B10001011 139 -#define B10001100 140 -#define B10001101 141 -#define B10001110 142 -#define B10001111 143 -#define B10010000 144 -#define B10010001 145 -#define B10010010 146 -#define B10010011 147 -#define B10010100 148 -#define B10010101 149 -#define B10010110 150 -#define B10010111 151 -#define B10011000 152 -#define B10011001 153 -#define B10011010 154 -#define B10011011 155 -#define B10011100 156 -#define B10011101 157 -#define B10011110 158 -#define B10011111 159 -#define B10100000 160 -#define B10100001 161 -#define B10100010 162 -#define B10100011 163 -#define B10100100 164 -#define B10100101 165 -#define B10100110 166 -#define B10100111 167 -#define B10101000 168 -#define B10101001 169 -#define B10101010 170 -#define B10101011 171 -#define B10101100 172 -#define B10101101 173 -#define B10101110 174 -#define B10101111 175 -#define B10110000 176 -#define B10110001 177 -#define B10110010 178 -#define B10110011 179 -#define B10110100 180 -#define B10110101 181 -#define B10110110 182 -#define B10110111 183 -#define B10111000 184 -#define B10111001 185 -#define B10111010 186 -#define B10111011 187 -#define B10111100 188 -#define B10111101 189 -#define B10111110 190 -#define B10111111 191 -#define B11000000 192 -#define B11000001 193 -#define B11000010 194 -#define B11000011 195 -#define B11000100 196 -#define B11000101 197 -#define B11000110 198 -#define B11000111 199 -#define B11001000 200 -#define B11001001 201 -#define B11001010 202 -#define B11001011 203 -#define B11001100 204 -#define B11001101 205 -#define B11001110 206 -#define B11001111 207 -#define B11010000 208 -#define B11010001 209 -#define B11010010 210 -#define B11010011 211 -#define B11010100 212 -#define B11010101 213 -#define B11010110 214 -#define B11010111 215 -#define B11011000 216 -#define B11011001 217 -#define B11011010 218 -#define B11011011 219 -#define B11011100 220 -#define B11011101 221 -#define B11011110 222 -#define B11011111 223 -#define B11100000 224 -#define B11100001 225 -#define B11100010 226 -#define B11100011 227 -#define B11100100 228 -#define B11100101 229 -#define B11100110 230 -#define B11100111 231 -#define B11101000 232 -#define B11101001 233 -#define B11101010 234 -#define B11101011 235 -#define B11101100 236 -#define B11101101 237 -#define B11101110 238 -#define B11101111 239 -#define B11110000 240 -#define B11110001 241 -#define B11110010 242 -#define B11110011 243 -#define B11110100 244 -#define B11110101 245 -#define B11110110 246 -#define B11110111 247 -#define B11111000 248 -#define B11111001 249 -#define B11111010 250 -#define B11111011 251 -#define B11111100 252 -#define B11111101 253 -#define B11111110 254 -#define B11111111 255 - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/main.cpp b/Marlin/Sanguino/cores/Copy of arduino/main.cpp deleted file mode 100644 index cc6e81d906..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/main.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -int main(void) -{ - init(); - - setup(); - - for (;;) - loop(); - - return 0; -} - diff --git a/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c b/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c deleted file mode 100644 index ccb88fe989..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - pins_arduino.c - pin definitions for the Arduino board - Part of Arduino / Wiring Lite - - Copyright (c) 2005 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: pins_arduino.c 254 2007-04-20 23:17:38Z mellis $ -*/ - -#include -#include "wiring_private.h" -#include "pins_arduino.h" - -// On the Sanguino board, digital pins are also used -// for the analog output (software PWM). Analog input -// pins are a separate set. - -// ATMEL ATMEGA644P / SANGUINO -// -// +---\/---+ -// INT0 (D 0) PB0 1| |40 PA0 (AI 0 / D31) -// INT1 (D 1) PB1 2| |39 PA1 (AI 1 / D30) -// INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) -// PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) -// PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) -// MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) -// MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) -// SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) -// RST 9| |32 AREF -// VCC 10| |31 GND -// GND 11| |30 AVCC -// XTAL2 12| |29 PC7 (D 23) -// XTAL1 13| |28 PC6 (D 22) -// RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI -// TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO -// RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS -// TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK -// PWM (D 12) PD4 18| |23 PC1 (D 17) SDA -// PWM (D 13) PD5 19| |22 PC0 (D 16) SCL -// PWM (D 14) PD6 20| |21 PD7 (D 15) PWM -// +--------+ -// - -#define PA 1 -#define PB 2 -#define PC 3 -#define PD 4 - -// these arrays map port names (e.g. port B) to the -// appropriate addresses for various functions (e.g. reading -// and writing) -const uint8_t PROGMEM port_to_mode_PGM[] = -{ - NOT_A_PORT, - &DDRA, - &DDRB, - &DDRC, - &DDRD, -}; - -const uint8_t PROGMEM port_to_output_PGM[] = -{ - NOT_A_PORT, - &PORTA, - &PORTB, - &PORTC, - &PORTD, -}; - -const uint8_t PROGMEM port_to_input_PGM[] = -{ - NOT_A_PORT, - &PINA, - &PINB, - &PINC, - &PIND, -}; - -const uint8_t PROGMEM digital_pin_to_port_PGM[] = -{ - PB, /* 0 */ - PB, - PB, - PB, - PB, - PB, - PB, - PB, - PD, /* 8 */ - PD, - PD, - PD, - PD, - PD, - PD, - PD, - PC, /* 16 */ - PC, - PC, - PC, - PC, - PC, - PC, - PC, - PA, /* 24 */ - PA, - PA, - PA, - PA, - PA, - PA, - PA /* 31 */ -}; - -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = -{ - _BV(0), /* 0, port B */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), - _BV(6), - _BV(7), - _BV(0), /* 8, port D */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), - _BV(6), - _BV(7), - _BV(0), /* 16, port C */ - _BV(1), - _BV(2), - _BV(3), - _BV(4), - _BV(5), - _BV(6), - _BV(7), - _BV(7), /* 24, port A */ - _BV(6), - _BV(5), - _BV(4), - _BV(3), - _BV(2), - _BV(1), - _BV(0) -}; - -const uint8_t PROGMEM digital_pin_to_timer_PGM[] = -{ - NOT_ON_TIMER, /* 0 - PB0 */ - NOT_ON_TIMER, /* 1 - PB1 */ - NOT_ON_TIMER, /* 2 - PB2 */ - TIMER0A, /* 3 - PB3 */ - TIMER0B, /* 4 - PB4 */ - NOT_ON_TIMER, /* 5 - PB5 */ - NOT_ON_TIMER, /* 6 - PB6 */ - NOT_ON_TIMER, /* 7 - PB7 */ - NOT_ON_TIMER, /* 8 - PD0 */ - NOT_ON_TIMER, /* 9 - PD1 */ - NOT_ON_TIMER, /* 10 - PD2 */ - NOT_ON_TIMER, /* 11 - PD3 */ - TIMER1B, /* 12 - PD4 */ - TIMER1A, /* 13 - PD5 */ - TIMER2B, /* 14 - PD6 */ - TIMER2A, /* 15 - PD7 */ - NOT_ON_TIMER, /* 16 - PC0 */ - NOT_ON_TIMER, /* 17 - PC1 */ - NOT_ON_TIMER, /* 18 - PC2 */ - NOT_ON_TIMER, /* 19 - PC3 */ - NOT_ON_TIMER, /* 20 - PC4 */ - NOT_ON_TIMER, /* 21 - PC5 */ - NOT_ON_TIMER, /* 22 - PC6 */ - NOT_ON_TIMER, /* 23 - PC7 */ - NOT_ON_TIMER, /* 24 - PA0 */ - NOT_ON_TIMER, /* 25 - PA1 */ - NOT_ON_TIMER, /* 26 - PA2 */ - NOT_ON_TIMER, /* 27 - PA3 */ - NOT_ON_TIMER, /* 28 - PA4 */ - NOT_ON_TIMER, /* 29 - PA5 */ - NOT_ON_TIMER, /* 30 - PA6 */ - NOT_ON_TIMER /* 31 - PA7 */ -}; diff --git a/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h b/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h deleted file mode 100644 index e0b7add867..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/pins_arduino.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - pins_arduino.h - Pin definition functions for Arduino - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2007 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ -*/ - -#ifndef Pins_Arduino_h -#define Pins_Arduino_h - -#include - -#define NOT_A_PIN 0 -#define NOT_A_PORT 0 - -#define NOT_ON_TIMER 0 -#define TIMER0A 1 -#define TIMER0B 2 -#define TIMER1A 3 -#define TIMER1B 4 -#define TIMER2 5 -#define TIMER2A 6 -#define TIMER2B 7 - -extern const uint8_t PROGMEM port_to_mode_PGM[]; -extern const uint8_t PROGMEM port_to_input_PGM[]; -extern const uint8_t PROGMEM port_to_output_PGM[]; - -extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; - -extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; - -// Get the bit location within the hardware port of the given virtual pin. -// This comes from the pins_*.c file for the active board configuration. -// -// These perform slightly better as macros compared to inline functions -// -#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) -#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) -#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) -#define analogInPinToBit(P) (P) -#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_output_PGM + (P))) ) -#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_input_PGM + (P))) ) -#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_mode_PGM + (P))) ) - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring.c b/Marlin/Sanguino/cores/Copy of arduino/wiring.c deleted file mode 100644 index b90d07e592..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/wiring.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - wiring.c - Partial implementation of the Wiring API for the ATmega8. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id$ -*/ - -#include "wiring_private.h" - -// the prescaler is set so that timer0 ticks every 64 clock cycles, and the -// the overflow handler is called every 256 ticks. -#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) - -// the whole number of milliseconds per timer0 overflow -#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) - -// the fractional number of milliseconds per timer0 overflow. we shift right -// by three to fit these numbers into a byte. (for the clock speeds we care -// about - 8 and 16 MHz - this doesn't lose precision.) -#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) -#define FRACT_MAX (1000 >> 3) - -volatile unsigned long timer0_overflow_count = 0; -volatile unsigned long timer0_millis = 0; -static unsigned char timer0_fract = 0; - -SIGNAL(TIMER0_OVF_vect) -{ - // copy these to local variables so they can be stored in registers - // (volatile variables must be read from memory on every access) - unsigned long m = timer0_millis; - unsigned char f = timer0_fract; - - m += MILLIS_INC; - f += FRACT_INC; - if (f >= FRACT_MAX) { - f -= FRACT_MAX; - m += 1; - } - - timer0_fract = f; - timer0_millis = m; - timer0_overflow_count++; -} - -unsigned long millis() -{ - unsigned long m; - uint8_t oldSREG = SREG; - - // disable interrupts while we read timer0_millis or we might get an - // inconsistent value (e.g. in the middle of a write to timer0_millis) - cli(); - m = timer0_millis; - SREG = oldSREG; - - return m; -} - -unsigned long micros() { - unsigned long m; - uint8_t oldSREG = SREG, t; - - cli(); - m = timer0_overflow_count; -#if defined(TCNT0) - t = TCNT0; -#elif defined(TCNT0L) - t = TCNT0L; -#else - #error TIMER 0 not defined -#endif - - -#ifdef TIFR0 - if ((TIFR0 & _BV(TOV0)) && (t < 255)) - m++; -#else - if ((TIFR & _BV(TOV0)) && (t < 255)) - m++; -#endif - - SREG = oldSREG; - - return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); -} - -void delay(unsigned long ms) -{ - uint16_t start = (uint16_t)micros(); - - while (ms > 0) { - if (((uint16_t)micros() - start) >= 1000) { - ms--; - start += 1000; - } - } -} - -/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ -void delayMicroseconds(unsigned int us) -{ - // calling avrlib's delay_us() function with low values (e.g. 1 or - // 2 microseconds) gives delays longer than desired. - //delay_us(us); - -#if F_CPU >= 16000000L - // for the 16 MHz clock on most Arduino boards - - // for a one-microsecond delay, simply return. the overhead - // of the function call yields a delay of approximately 1 1/8 us. - if (--us == 0) - return; - - // the following loop takes a quarter of a microsecond (4 cycles) - // per iteration, so execute it four times for each microsecond of - // delay requested. - us <<= 2; - - // account for the time taken in the preceeding commands. - us -= 2; -#else - // for the 8 MHz internal clock on the ATmega168 - - // for a one- or two-microsecond delay, simply return. the overhead of - // the function calls takes more than two microseconds. can't just - // subtract two, since us is unsigned; we'd overflow. - if (--us == 0) - return; - if (--us == 0) - return; - - // the following loop takes half of a microsecond (4 cycles) - // per iteration, so execute it twice for each microsecond of - // delay requested. - us <<= 1; - - // partially compensate for the time taken by the preceeding commands. - // we can't subtract any more than this or we'd overflow w/ small delays. - us--; -#endif - - // busy wait - __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles - "brne 1b" : "=w" (us) : "0" (us) // 2 cycles - ); -} - -void init() -{ - // this needs to be called before setup() or some functions won't - // work there - sei(); - - // on the ATmega168, timer 0 is also used for fast hardware pwm - // (using phase-correct PWM would mean that timer 0 overflowed half as often - // resulting in different millis() behavior on the ATmega8 and ATmega168) -#if defined(TCCR0A) && defined(WGM01) - sbi(TCCR0A, WGM01); - sbi(TCCR0A, WGM00); -#endif - - // set timer 0 prescale factor to 64 -#if defined(__AVR_ATmega128__) - // CPU specific: different values for the ATmega128 - sbi(TCCR0, CS02); -#elif defined(TCCR0) && defined(CS01) && defined(CS00) - // this combination is for the standard atmega8 - sbi(TCCR0, CS01); - sbi(TCCR0, CS00); -#elif defined(TCCR0B) && defined(CS01) && defined(CS00) - // this combination is for the standard 168/328/1280/2560 - sbi(TCCR0B, CS01); - sbi(TCCR0B, CS00); -#elif defined(TCCR0A) && defined(CS01) && defined(CS00) - // this combination is for the __AVR_ATmega645__ series - sbi(TCCR0A, CS01); - sbi(TCCR0A, CS00); -#else - #error Timer 0 prescale factor 64 not set correctly -#endif - - // enable timer 0 overflow interrupt -#if defined(TIMSK) && defined(TOIE0) - sbi(TIMSK, TOIE0); -#elif defined(TIMSK0) && defined(TOIE0) - sbi(TIMSK0, TOIE0); -#else - #error Timer 0 overflow interrupt not set correctly -#endif - - // timers 1 and 2 are used for phase-correct hardware pwm - // this is better for motors as it ensures an even waveform - // note, however, that fast pwm mode can achieve a frequency of up - // 8 MHz (with a 16 MHz clock) at 50% duty cycle - - TCCR1B = 0; - - // set timer 1 prescale factor to 64 -#if defined(TCCR1B) && defined(CS11) && defined(CS10) - sbi(TCCR1B, CS11); - sbi(TCCR1B, CS10); -#elif defined(TCCR1) && defined(CS11) && defined(CS10) - sbi(TCCR1, CS11); - sbi(TCCR1, CS10); -#endif - // put timer 1 in 8-bit phase correct pwm mode -#if defined(TCCR1A) && defined(WGM10) - sbi(TCCR1A, WGM10); -#elif defined(TCCR1) - #warning this needs to be finished -#endif - - // set timer 2 prescale factor to 64 -#if defined(TCCR2) && defined(CS22) - sbi(TCCR2, CS22); -#elif defined(TCCR2B) && defined(CS22) - sbi(TCCR2B, CS22); -#else - #warning Timer 2 not finished (may not be present on this CPU) -#endif - - // configure timer 2 for phase correct pwm (8-bit) -#if defined(TCCR2) && defined(WGM20) - sbi(TCCR2, WGM20); -#elif defined(TCCR2A) && defined(WGM20) - sbi(TCCR2A, WGM20); -#else - #warning Timer 2 not finished (may not be present on this CPU) -#endif - -#if defined(TCCR3B) && defined(CS31) && defined(WGM30) - sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64 - sbi(TCCR3B, CS30); - sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode -#endif - -#if defined(TCCR4B) && defined(CS41) && defined(WGM40) - sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64 - sbi(TCCR4B, CS40); - sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode -#endif - -#if defined(TCCR5B) && defined(CS51) && defined(WGM50) - sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64 - sbi(TCCR5B, CS50); - sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode -#endif - -#if defined(ADCSRA) - // set a2d prescale factor to 128 - // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. - // XXX: this will not work properly for other clock speeds, and - // this code should use F_CPU to determine the prescale factor. - sbi(ADCSRA, ADPS2); - sbi(ADCSRA, ADPS1); - sbi(ADCSRA, ADPS0); - - // enable a2d conversions - sbi(ADCSRA, ADEN); -#endif - - // the bootloader connects pins 0 and 1 to the USART; disconnect them - // here so they can be used as normal digital i/o; they will be - // reconnected in Serial.begin() -#if defined(UCSRB) - UCSRB = 0; -#elif defined(UCSR0B) - UCSR0B = 0; -#endif -} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring.h b/Marlin/Sanguino/cores/Copy of arduino/wiring.h deleted file mode 100644 index e29959b865..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/wiring.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - wiring.h - Partial implementation of the Wiring API for the ATmega8. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id$ -*/ - -#ifndef Wiring_h -#define Wiring_h - -#include -#include -#include "binary.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#define HIGH 0x1 -#define LOW 0x0 - -#define INPUT 0x0 -#define OUTPUT 0x1 - -#define true 0x1 -#define false 0x0 - -#define PI 3.1415926535897932384626433832795 -#define HALF_PI 1.5707963267948966192313216916398 -#define TWO_PI 6.283185307179586476925286766559 -#define DEG_TO_RAD 0.017453292519943295769236907684886 -#define RAD_TO_DEG 57.295779513082320876798154814105 - -#define SERIAL 0x0 -#define DISPLAY 0x1 - -#define LSBFIRST 0 -#define MSBFIRST 1 - -#define CHANGE 1 -#define FALLING 2 -#define RISING 3 - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#define INTERNAL1V1 2 -#define INTERNAL2V56 3 -#else -#define INTERNAL 3 -#endif -#define DEFAULT 1 -#define EXTERNAL 0 - -// undefine stdlib's abs if encountered -#ifdef abs -#undef abs -#endif - -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) -#define abs(x) ((x)>0?(x):-(x)) -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) -#define radians(deg) ((deg)*DEG_TO_RAD) -#define degrees(rad) ((rad)*RAD_TO_DEG) -#define sq(x) ((x)*(x)) - -#define interrupts() sei() -#define noInterrupts() cli() - -#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) -#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) -#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) - -#define lowByte(w) ((uint8_t) ((w) & 0xff)) -#define highByte(w) ((uint8_t) ((w) >> 8)) - -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) - - -typedef unsigned int word; - -#define bit(b) (1UL << (b)) - -typedef uint8_t boolean; -typedef uint8_t byte; - -void init(void); - -void pinMode(uint8_t, uint8_t); -void digitalWrite(uint8_t, uint8_t); -int digitalRead(uint8_t); -int analogRead(uint8_t); -void analogReference(uint8_t mode); -void analogWrite(uint8_t, int); - -unsigned long millis(void); -unsigned long micros(void); -void delay(unsigned long); -void delayMicroseconds(unsigned int us); -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); - -void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); - -void attachInterrupt(uint8_t, void (*)(void), int mode); -void detachInterrupt(uint8_t); - -void setup(void); -void loop(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c deleted file mode 100644 index b98bb1a196..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/wiring_analog.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - wiring_analog.c - analog input and output - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" -#include "pins_arduino.h" - -uint8_t analog_reference = DEFAULT; - -void analogReference(uint8_t mode) -{ - // can't actually set the register here because the default setting - // will connect AVCC and the AREF pin, which would cause a short if - // there's something connected to AREF. - analog_reference = mode; -} - -int analogRead(uint8_t pin) -{ - uint8_t low, high, ch = analogInPinToBit(pin); - - // set the analog reference (high two bits of ADMUX) and select the - // channel (low 4 bits). this also sets ADLAR (left-adjust result) - // to 0 (the default). - // the final AND is to clear the pos/neg reference bits - ADMUX = ((analog_reference << 6) | (pin & 0x0f)) & B11000111; - - // without a delay, we seem to read from the wrong channel - //delay(1); - - // start the conversion - sbi(ADCSRA, ADSC); - - // ADSC is cleared when the conversion finishes - while (bit_is_set(ADCSRA, ADSC)); - - // we have to read ADCL first; doing so locks both ADCL - // and ADCH until ADCH is read. reading ADCL second would - // cause the results of each conversion to be discarded, - // as ADCL and ADCH would be locked when it completed. - low = ADCL; - high = ADCH; - - // combine the two bytes - return (high << 8) | low; -} - -// Right now, PWM output only works on the pins with -// hardware support. These are defined in the appropriate -// pins_*.c file. For the rest of the pins, we default -// to digital output. -void analogWrite(uint8_t pin, int val) -{ - // We need to make sure the PWM output is enabled for those pins - // that support it, as we turn it off when digitally reading or - // writing with them. Also, make sure the pin is in output mode - // for consistenty with Wiring, which doesn't require a pinMode - // call for the analog output pins. - pinMode(pin, OUTPUT); - - if (digitalPinToTimer(pin) == TIMER1A) { - // connect pwm to pin on timer 1, channel A - sbi(TCCR1A, COM1A1); - // set pwm duty - OCR1A = val; - } else if (digitalPinToTimer(pin) == TIMER1B) { - // connect pwm to pin on timer 1, channel B - sbi(TCCR1A, COM1B1); - // set pwm duty - OCR1B = val; - } else if (digitalPinToTimer(pin) == TIMER0A) { - // connect pwm to pin on timer 0, channel A - sbi(TCCR0A, COM0A1); - // set pwm duty - OCR0A = val; - } else if (digitalPinToTimer(pin) == TIMER0B) { - // connect pwm to pin on timer 0, channel B - sbi(TCCR0A, COM0B1); - // set pwm duty - OCR0B = val; - } else if (digitalPinToTimer(pin) == TIMER2A) { - // connect pwm to pin on timer 2, channel A - sbi(TCCR2A, COM2A1); - // set pwm duty - OCR2A = val; - } else if (digitalPinToTimer(pin) == TIMER2B) { - // connect pwm to pin on timer 2, channel B - sbi(TCCR2A, COM2B1); - // set pwm duty - OCR2B = val; - } else if (val < 128) - //fail semi-intelligently - digitalWrite(pin, LOW); - else - digitalWrite(pin, HIGH); -} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c deleted file mode 100644 index 3d4b4ebd1c..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/wiring_digital.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - wiring_digital.c - digital input and output functions - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" -#include "pins_arduino.h" - -void pinMode(uint8_t pin, uint8_t mode) -{ - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *reg; - - if (port == NOT_A_PIN) return; - - // JWS: can I let the optimizer do this? - reg = portModeRegister(port); - - if (mode == INPUT) *reg &= ~bit; - else *reg |= bit; -} - -// Forcing this inline keeps the callers from having to push their own stuff -// on the stack. It is a good performance win and only takes 1 more byte per -// user than calling. (It will take more bytes on the 168.) -// -// But shouldn't this be moved into pinMode? Seems silly to check and do on -// each digitalread or write. -// -static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); -static inline void turnOffPWM(uint8_t timer) -{ - if (timer == TIMER0A) cbi(TCCR0A, COM0A1); - if (timer == TIMER0B) cbi(TCCR0A, COM0B1); - if (timer == TIMER1A) cbi(TCCR1A, COM1A1); - if (timer == TIMER1B) cbi(TCCR1A, COM1B1); - if (timer == TIMER2A) cbi(TCCR2A, COM2A1); - if (timer == TIMER2B) cbi(TCCR2A, COM2B1); -} - -void digitalWrite(uint8_t pin, uint8_t val) -{ - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *out; - - if (port == NOT_A_PIN) return; - - // If the pin that support PWM output, we need to turn it off - // before doing a digital write. - if (timer != NOT_ON_TIMER) turnOffPWM(timer); - - out = portOutputRegister(port); - - if (val == LOW) *out &= ~bit; - else *out |= bit; -} - -int digitalRead(uint8_t pin) -{ - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - - if (port == NOT_A_PIN) return LOW; - - // If the pin that support PWM output, we need to turn it off - // before getting a digital reading. - if (timer != NOT_ON_TIMER) turnOffPWM(timer); - - if (*portInputRegister(port) & bit) return HIGH; - - return LOW; -} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_private.h b/Marlin/Sanguino/cores/Copy of arduino/wiring_private.h deleted file mode 100644 index 14394a0b61..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/wiring_private.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - wiring_private.h - Internal header file. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ -*/ - -#ifndef WiringPrivate_h -#define WiringPrivate_h - -#include -#include -#include -#include -#include -#include - -#include "wiring.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -#ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#endif -#ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) -#endif - -#define EXTERNAL_INT_0 0 -#define EXTERNAL_INT_1 1 -#define EXTERNAL_INT_2 2 - -#define EXTERNAL_NUM_INTERRUPTS 3 - -typedef void (*voidFuncPtr)(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c deleted file mode 100644 index 0d968865d2..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/wiring_pulse.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - wiring_pulse.c - pulseIn() function - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" -#include "pins_arduino.h" - -/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH - * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds - * to 3 minutes in length, but must be called at least a few dozen microseconds - * before the start of the pulse. */ -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) -{ - // cache the port and bit of the pin in order to speed up the - // pulse width measuring loop and achieve finer resolution. calling - // digitalRead() instead yields much coarser resolution. - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - uint8_t stateMask = (state ? bit : 0); - unsigned long width = 0; // keep initialization out of time critical area - - // convert the timeout from microseconds to a number of times through - // the initial loop; it takes 16 clock cycles per iteration. - unsigned long numloops = 0; - unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; - - // wait for any previous pulse to end - while ((*portInputRegister(port) & bit) == stateMask) - if (numloops++ == maxloops) - return 0; - - // wait for the pulse to start - while ((*portInputRegister(port) & bit) != stateMask) - if (numloops++ == maxloops) - return 0; - - // wait for the pulse to stop - while ((*portInputRegister(port) & bit) == stateMask) { - if (numloops++ == maxloops) - return 0; - width++; - } - - // convert the reading to microseconds. The loop has been determined - // to be 20 clock cycles long and have about 16 clocks between the edge - // and the start of the loop. There will be some error introduced by - // the interrupt handlers. - return clockCyclesToMicroseconds(width * 21 + 16); -} diff --git a/Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c b/Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c deleted file mode 100644 index cfe786758c..0000000000 --- a/Marlin/Sanguino/cores/Copy of arduino/wiring_shift.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - wiring_shift.c - shiftOut() function - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 David A. Mellis - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" - -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { - uint8_t value = 0; - uint8_t i; - - for (i = 0; i < 8; ++i) { - digitalWrite(clockPin, HIGH); - if (bitOrder == LSBFIRST) - value |= digitalRead(dataPin) << i; - else - value |= digitalRead(dataPin) << (7 - i); - digitalWrite(clockPin, LOW); - } - return value; -} - -void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) -{ - uint8_t i; - - for (i = 0; i < 8; i++) { - if (bitOrder == LSBFIRST) - digitalWrite(dataPin, !!(val & (1 << i))); - else - digitalWrite(dataPin, !!(val & (1 << (7 - i)))); - - digitalWrite(clockPin, HIGH); - digitalWrite(clockPin, LOW); - } -} diff --git a/Marlin/Sanguino/cores/arduino/HardwareSerial.cpp b/Marlin/Sanguino/cores/arduino/HardwareSerial.cpp index 4397efb7ee..d4931b4a41 100644 --- a/Marlin/Sanguino/cores/arduino/HardwareSerial.cpp +++ b/Marlin/Sanguino/cores/arduino/HardwareSerial.cpp @@ -37,11 +37,7 @@ // using a ring buffer (I think), in which rx_buffer_head is the index of the // location to which to write the next incoming character and rx_buffer_tail // is the index of the location from which to read. -#if (RAMEND < 1000) - #define RX_BUFFER_SIZE 32 -#else - #define RX_BUFFER_SIZE 128 -#endif +#define RX_BUFFER_SIZE 128 struct ring_buffer { @@ -50,22 +46,11 @@ struct ring_buffer int tail; }; -#if defined(UBRRH) || defined(UBRR0H) - ring_buffer rx_buffer = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR1H) - ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR2H) - ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; -#endif -#if defined(UBRR3H) - ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; -#endif +ring_buffer rx_buffer = { { 0 }, 0, 0 }; inline void store_char(unsigned char c, ring_buffer *rx_buffer) { - int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + int i = (unsigned int)(rx_buffer->head + 1) & (RX_BUFFER_SIZE -1); // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the @@ -77,95 +62,13 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) } } -#if defined(USART_RX_vect) - SIGNAL(USART_RX_vect) - { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; // atmega8535 - #else - #error UDR not defined - #endif - store_char(c, &rx_buffer); - } -#elif defined(SIG_USART0_RECV) && defined(UDR0) - SIGNAL(SIG_USART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -#elif defined(SIG_UART0_RECV) && defined(UDR0) - SIGNAL(SIG_UART0_RECV) - { - unsigned char c = UDR0; - store_char(c, &rx_buffer); - } -//#elif defined(SIG_USART_RECV) -#elif defined(USART0_RX_vect) - // fixed by Mark Sproul this is on the 644/644p - //SIGNAL(SIG_USART_RECV) - SIGNAL(USART0_RX_vect) - { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; // atmega8, atmega32 - #else - #error UDR not defined - #endif - store_char(c, &rx_buffer); - } -#elif defined(SIG_UART_RECV) - // this is for atmega8 - SIGNAL(SIG_UART_RECV) - { - #if defined(UDR0) - unsigned char c = UDR0; // atmega645 - #elif defined(UDR) - unsigned char c = UDR; // atmega8 - #endif - store_char(c, &rx_buffer); - } -#elif defined(USBCON) - #warning No interrupt handler for usart 0 - #warning Serial(0) is on USB interface -#else - #error No interrupt handler for usart 0 -#endif - -//#if defined(SIG_USART1_RECV) -#if defined(USART1_RX_vect) - //SIGNAL(SIG_USART1_RECV) - SIGNAL(USART1_RX_vect) - { - unsigned char c = UDR1; - store_char(c, &rx_buffer1); - } -#elif defined(SIG_USART1_RECV) - #error SIG_USART1_RECV -#endif - -#if defined(USART2_RX_vect) && defined(UDR2) - SIGNAL(USART2_RX_vect) - { - unsigned char c = UDR2; - store_char(c, &rx_buffer2); - } -#elif defined(SIG_USART2_RECV) - #error SIG_USART2_RECV -#endif - -#if defined(USART3_RX_vect) && defined(UDR3) - SIGNAL(USART3_RX_vect) - { - unsigned char c = UDR3; - store_char(c, &rx_buffer3); - } -#elif defined(SIG_USART3_RECV) - #error SIG_USART3_RECV -#endif - +// fixed by Mark Sproul this is on the 644/644p +//SIGNAL(SIG_USART_RECV) +SIGNAL(USART0_RX_vect) +{ + unsigned char c = UDR0; + store_char(c, &rx_buffer); +} // Constructors //////////////////////////////////////////////////////////////// @@ -231,7 +134,7 @@ void HardwareSerial::end() int HardwareSerial::available(void) { - return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; + return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) & (RX_BUFFER_SIZE-1); } int HardwareSerial::peek(void) @@ -250,7 +153,7 @@ int HardwareSerial::read(void) return -1; } else { unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) & (RX_BUFFER_SIZE-1); return c; } } @@ -278,26 +181,7 @@ void HardwareSerial::write(uint8_t c) } // Preinstantiate Objects ////////////////////////////////////////////////////// - -#if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); -#elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); -#elif defined(USBCON) - #warning no serial port defined (port 0) -#else - #error no serial port defined (port 0) -#endif - -#if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); -#endif -#if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); -#endif -#if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); -#endif +HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); #endif // whole file diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 42064104b4..b08a800f68 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -89,25 +89,50 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; static unsigned long watchmillis = 0; #endif //WATCHPERIOD +// Init min and max temp with extreme values to prevent false errors during startup #ifdef HEATER_0_MINTEMP - static int minttemp_0 = temp2analog(HEATER_0_MINTEMP); + #ifdef HEATER_0_USES_AD595 + static int minttemp_0 = 0; + #else + static int minttemp_0 = 16383; + #endif #endif //MINTEMP #ifdef HEATER_0_MAXTEMP - static int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); + #ifdef HEATER_0_USES_AD595 + static int maxttemp_0 = 0; + #else + static int maxttemp_0 = 16383; + #endif #endif //MAXTEMP #ifdef HEATER_1_MINTEMP - static int minttemp_1 = temp2analog(HEATER_1_MINTEMP); + #ifdef HEATER_1_USES_AD595 + static int minttemp_1 = 0; + #else + static int minttemp_1 = 16383; + #endif #endif //MINTEMP #ifdef HEATER_1_MAXTEMP - static int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); + #ifdef HEATER_1_USES_AD595 + static int maxttemp_1 = 0; + #else + static int maxttemp_1 = 16383; + #endif #endif //MAXTEMP #ifdef BED_MINTEMP - static int bed_minttemp = temp2analog(BED_MINTEMP); + #ifdef BED_USES_AD595 + static int bed_minttemp = 0; + #else + static int bed_minttemp = 16383; + #endif #endif //BED_MINTEMP #ifdef BED_MAXTEMP - static int bed_maxttemp = temp2analog(BED_MAXTEMP); + #ifdef BED_USES_AD595 + static int bed_maxttemp = 0; + #else + static int bed_maxttemp = 16383; + #endif #endif //BED_MAXTEMP //=========================================================================== @@ -350,6 +375,30 @@ void tp_init() // Interleave temperature interrupt with millies interrupt OCR0B = 128; TIMSK0 |= (1< Date: Sat, 19 Nov 2011 13:13:34 +0100 Subject: [PATCH 055/228] overworked cardreader for folder support; not finished yet. --- Marlin/Marlin.pde | 5 +- Marlin/SdFat.cpp | 329 ------------------------------------------ Marlin/SdFat.h | 76 ---------- Marlin/cardreader.h | 25 ++-- Marlin/cardreader.pde | 193 +++++++++++++++++-------- 5 files changed, 154 insertions(+), 474 deletions(-) delete mode 100644 Marlin/SdFat.cpp delete mode 100644 Marlin/SdFat.h diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 8dc8d0822e..34d50e3c46 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -176,6 +176,7 @@ static unsigned long stoptime=0; //=============================ROUTINES============================= //=========================================================================== +void get_arc_coordinates(); extern "C"{ extern unsigned int __bss_end; @@ -588,7 +589,7 @@ inline void process_commands() starpos = (strchr(strchr_pointer + 4,'*')); if(starpos!=NULL) *(starpos-1)='\0'; - card.selectFile(strchr_pointer + 4); + card.openFile(strchr_pointer + 4,true); break; case 24: //M24 - Start SD print card.startFileprint(); @@ -613,7 +614,7 @@ inline void process_commands() strchr_pointer = strchr(npos,' ') + 1; *(starpos-1) = '\0'; } - card.startFilewrite(strchr_pointer+4); + card.openFile(strchr_pointer+4,false); break; case 29: //M29 - Stop SD write diff --git a/Marlin/SdFat.cpp b/Marlin/SdFat.cpp deleted file mode 100644 index 494fd48225..0000000000 --- a/Marlin/SdFat.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#include "SdFat.h" -#include "SdFatUtil.h" -//------------------------------------------------------------------------------ -/** Change a volume's working directory to root - * - * Changes the volume's working directory to the SD's root directory. - * Optionally set the current working directory to the volume's - * working directory. - * - * \param[in] set_cwd Set the current working directory to this volume's - * working directory if true. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool SdFat::chdir(bool set_cwd) { - if (set_cwd) SdBaseFile::cwd_ = &vwd_; - vwd_.close(); - return vwd_.openRoot(&vol_); -} -//------------------------------------------------------------------------------ -/** Change a volume's working directory - * - * Changes the volume working directory to the \a path subdirectory. - * Optionally set the current working directory to the volume's - * working directory. - * - * Example: If the volume's working directory is "/DIR", chdir("SUB") - * will change the volume's working directory from "/DIR" to "/DIR/SUB". - * - * If path is "/", the volume's working directory will be changed to the - * root directory - * - * \param[in] path The name of the subdirectory. - * - * \param[in] set_cwd Set the current working directory to this volume's - * working directory if true. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool SdFat::chdir(const char *path, bool set_cwd) { - SdBaseFile dir; - if (path[0] == '/' && path[1] == '\0') return chdir(set_cwd); - if (!dir.open(&vwd_, path, O_READ)) goto fail; - if (!dir.isDir()) goto fail; - vwd_ = dir; - if (set_cwd) SdBaseFile::cwd_ = &vwd_; - return true; - - fail: - return false; -} -//------------------------------------------------------------------------------ -/** Set the current working directory to a volume's working directory. - * - * This is useful with multiple SD cards. - * - * The current working directory is changed to this volume's working directory. - * - * This is like the Windows/DOS \: command. - */ -void SdFat::chvol() { - SdBaseFile::cwd_ = &vwd_; -} -//------------------------------------------------------------------------------ -/** %Print any SD error code and halt. */ -void SdFat::errorHalt() { - errorPrint(); - while (1); -} -//------------------------------------------------------------------------------ -/** %Print msg, any SD error code, and halt. - * - * \param[in] msg Message to print. - */ -void SdFat::errorHalt(char const* msg) { - errorPrint(msg); - while (1); -} -//------------------------------------------------------------------------------ -/** %Print msg, any SD error code, and halt. - * - * \param[in] msg Message in program space (flash memory) to print. - */ -void SdFat::errorHalt_P(PGM_P msg) { - errorPrint_P(msg); - while (1); -} -//------------------------------------------------------------------------------ -/** %Print any SD error code. */ -void SdFat::errorPrint() { - if (!card_.errorCode()) return; - PgmPrint("SD errorCode: 0X"); - Serial.println(card_.errorCode(), HEX); -} -//------------------------------------------------------------------------------ -/** %Print msg, any SD error code. - * - * \param[in] msg Message to print. - */ -void SdFat::errorPrint(char const* msg) { - PgmPrint("error: "); - Serial.println(msg); - errorPrint(); -} -//------------------------------------------------------------------------------ -/** %Print msg, any SD error code. - * - * \param[in] msg Message in program space (flash memory) to print. - */ -void SdFat::errorPrint_P(PGM_P msg) { - PgmPrint("error: "); - SerialPrintln_P(msg); - errorPrint(); -} -//------------------------------------------------------------------------------ -/** - * Test for the existence of a file. - * - * \param[in] name Name of the file to be tested for. - * - * \return true if the file exists else false. - */ -bool SdFat::exists(const char* name) { - return vwd_.exists(name); -} -//------------------------------------------------------------------------------ -/** - * Initialize an SdFat object. - * - * Initializes the SD card, SD volume, and root directory. - * - * \param[in] sckRateID value for SPI SCK rate. See Sd2Card::init(). - * \param[in] chipSelectPin SD chip select pin. See Sd2Card::init(). - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool SdFat::init(uint8_t sckRateID, uint8_t chipSelectPin) { - return card_.init(sckRateID, chipSelectPin) && vol_.init(&card_) && chdir(1); -} -//------------------------------------------------------------------------------ -/** %Print error details and halt after SdFat::init() fails. */ -void SdFat::initErrorHalt() { - initErrorPrint(); - while (1); -} -//------------------------------------------------------------------------------ -/**Print message, error details, and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ -void SdFat::initErrorHalt(char const *msg) { - Serial.println(msg); - initErrorHalt(); -} -//------------------------------------------------------------------------------ -/**Print message, error details, and halt after SdFat::init() fails. - * - * \param[in] msg Message in program space (flash memory) to print. - */ -void SdFat::initErrorHalt_P(PGM_P msg) { - SerialPrintln_P(msg); - initErrorHalt(); -} -//------------------------------------------------------------------------------ -/** Print error details after SdFat::init() fails. */ -void SdFat::initErrorPrint() { - if (card_.errorCode()) { - PgmPrintln("Can't access SD card. Do not reformat."); - if (card_.errorCode() == SD_CARD_ERROR_CMD0) { - PgmPrintln("No card, wrong chip select pin, or SPI problem?"); - } - errorPrint(); - } else if (vol_.fatType() == 0) { - PgmPrintln("Invalid format, reformat SD."); - } else if (!vwd_.isOpen()) { - PgmPrintln("Can't open root directory."); - } else { - PgmPrintln("No error found."); - } -} -//------------------------------------------------------------------------------ -/**Print message and error details and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ -void SdFat::initErrorPrint(char const *msg) { - Serial.println(msg); - initErrorPrint(); -} -//------------------------------------------------------------------------------ -/**Print message and error details after SdFat::init() fails. - * - * \param[in] msg Message in program space (flash memory) to print. - */ -void SdFat::initErrorPrint_P(PGM_P msg) { - SerialPrintln_P(msg); - initErrorHalt(); -} -//------------------------------------------------------------------------------ -/** List the directory contents of the volume working directory to Serial. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ -void SdFat::ls(uint8_t flags) { - vwd_.ls(&Serial, flags); -} -//------------------------------------------------------------------------------ -/** List the directory contents of the volume working directory to Serial. - * - * \param[in] pr Print stream for list. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ -void SdFat::ls(Print* pr, uint8_t flags) { - vwd_.ls(pr, flags); -} -//------------------------------------------------------------------------------ -/** Make a subdirectory in the volume working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for the subdirectory. - * - * \param[in] pFlag Create missing parent directories if true. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool SdFat::mkdir(const char* path, bool pFlag) { - SdBaseFile sub; - return sub.mkdir(&vwd_, path, pFlag); -} -//------------------------------------------------------------------------------ -/** Remove a file from the volume working directory. -* -* \param[in] path A path with a valid 8.3 DOS name for the file. -* -* \return The value one, true, is returned for success and -* the value zero, false, is returned for failure. -*/ -bool SdFat::remove(const char* path) { - return SdBaseFile::remove(&vwd_, path); -} -//------------------------------------------------------------------------------ -/** Rename a file or subdirectory. - * - * \param[in] oldPath Path name to the file or subdirectory to be renamed. - * - * \param[in] newPath New path name of the file or subdirectory. - * - * The \a newPath object must not exist before the rename call. - * - * The file to be renamed must not be open. The directory entry may be - * moved and file system corruption could occur if the file is accessed by - * a file object that was opened before the rename() call. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool SdFat::rename(const char *oldPath, const char *newPath) { - SdBaseFile file; - if (!file.open(oldPath, O_READ)) return false; - return file.rename(&vwd_, newPath); -} -//------------------------------------------------------------------------------ -/** Remove a subdirectory from the volume's working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for the subdirectory. - * - * The subdirectory file will be removed only if it is empty. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool SdFat::rmdir(const char* path) { - SdBaseFile sub; - if (!sub.open(path, O_READ)) return false; - return sub.rmdir(); -} -//------------------------------------------------------------------------------ -/** Truncate a file to a specified length. The current file position - * will be maintained if it is less than or equal to \a length otherwise - * it will be set to end of file. - * - * \param[in] path A path with a valid 8.3 DOS name for the file. - * \param[in] length The desired length for the file. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - * Reasons for failure include file is read only, file is a directory, - * \a length is greater than the current file size or an I/O error occurs. - */ -bool SdFat::truncate(const char* path, uint32_t length) { - SdBaseFile file; - if (!file.open(path, O_WRITE)) return false; - return file.truncate(length); -} diff --git a/Marlin/SdFat.h b/Marlin/SdFat.h deleted file mode 100644 index 1a184d0843..0000000000 --- a/Marlin/SdFat.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFat_h -#define SdFat_h -/** - * \file - * \brief SdFat class - */ -#include "SdFile.h" -//#include -//#include -//------------------------------------------------------------------------------ -/** SdFat version YYYYMMDD */ -#define SD_FAT_VERSION 20110902 -//------------------------------------------------------------------------------ -/** - * \class SdFat - * \brief Integration class for the %SdFat library. - */ -class SdFat { - public: - SdFat() {} - /** \return a pointer to the Sd2Card object. */ - Sd2Card* card() {return &card_;} - bool chdir(bool set_cwd = false); - bool chdir(const char* path, bool set_cwd = false); - void chvol(); - void errorHalt(); - void errorHalt_P(PGM_P msg); - void errorHalt(char const *msg); - void errorPrint(); - void errorPrint_P(PGM_P msg); - void errorPrint(char const *msg); - bool exists(const char* name); - bool init(uint8_t sckRateID = SPI_FULL_SPEED, - uint8_t chipSelectPin = SD_CHIP_SELECT_PIN); - void initErrorHalt(); - void initErrorHalt(char const *msg); - void initErrorHalt_P(PGM_P msg); - void initErrorPrint(); - void initErrorPrint(char const *msg); - void initErrorPrint_P(PGM_P msg); - void ls(uint8_t flags = 0); - void ls(Print* pr, uint8_t flags = 0); - bool mkdir(const char* path, bool pFlag = true); - bool remove(const char* path); - bool rename(const char *oldPath, const char *newPath); - bool rmdir(const char* path); - bool truncate(const char* path, uint32_t length); - /** \return a pointer to the SdVolume object. */ - SdVolume* vol() {return &vol_;} - /** \return a pointer to the volume working directory. */ - SdBaseFile* vwd() {return &vwd_;} - private: - Sd2Card card_; - SdVolume vol_; - SdBaseFile vwd_; -}; -#endif // SdFat_h diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 04076bfda0..d96715807f 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -3,9 +3,8 @@ #ifdef SDSUPPORT - -#include "SdFat.h" - +#include "SdFile.h" +enum LsAction {LS_SerialPrint,LS_Count,LS_GetFilename}; class CardReader { public: @@ -17,20 +16,22 @@ public: //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset void checkautostart(bool x); - + void openFile(char* name,bool read); void closefile(); void release(); void startFileprint(); - void startFilewrite(char *name); + //void startFilewrite(char *name); void pauseSDPrint(); void getStatus(); - - void selectFile(char* name); + void cd(char * absolutPath); + //void selectFile(char* name); void getfilename(const uint8_t nr); - uint8_t getnrfilenames(); + uint16_t getnrfilenames(); - inline void ls() {root.ls();}; + void ls(); + void lsDive(char *prepend,SdFile parent); + inline bool eof() { return sdpos>=filesize ;}; inline int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; inline void setIndex(long index) {sdpos = index;file.seekSet(index);}; @@ -42,7 +43,7 @@ public: bool cardOK ; char filename[11]; private: - SdFile root; + SdFile root,*curDir; Sd2Card card; SdVolume volume; SdFile file; @@ -52,6 +53,10 @@ private: uint32_t sdpos ; bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. + + LsAction lsAction; //stored for recursion. + int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. + char* diveDirName; }; diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 605af11bf5..77a8f692bf 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -20,6 +20,106 @@ CardReader::CardReader() autostart_atmillis=millis()+5000; } +char *createFilename(char *buffer,const dir_t &p) //buffer>12characters +{ + char *pos=buffer; + for (uint8_t i = 0; i < 11; i++) + { + if (p.name[i] == ' ')continue; + if (i == 8) + { + *pos++='.'; + } + *pos++=p.name[i]; + } + *pos++=0; + return buffer; +} + +// bool SdFat::chdir(bool set_cwd) { +// if (set_cwd) SdBaseFile::cwd_ = &vwd_; +// vwd_.close(); +// return vwd_.openRoot(&vol_); +// } +void CardReader::lsDive(char *prepend,SdFile parent) +{ + dir_t p; + uint8_t cnt=0; + + while (parent.readDir(p) > 0) + { + if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) + { + + char path[13*2]; + char lfilename[13]; + createFilename(lfilename,p); + + path[0]=0; + if(strlen(prepend)==0) //avoid leading / if already in prepend + { + strcat(path,"/"); + } + strcat(path,prepend); + strcat(path,lfilename); + strcat(path,"/"); + + Serial.print(path); + + SdFile dir; + if(!dir.open(parent,lfilename, O_READ)) + { + if(lsAction==LS_SerialPrint) + { + SERIAL_ECHO_START; + SERIAL_ECHOLN("Cannot open subdir"); + SERIAL_ECHOLN(lfilename); + } + } + lsDive(path,dir); + //close done automatically by destructor of SdFile + + + } + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + + + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + //if(cnt++!=nr) continue; + createFilename(filename,p); + if(lsAction==LS_SerialPrint) + { + SERIAL_PROTOCOL(prepend); + SERIAL_PROTOCOLLN(filename); + } + else if(lsAction==LS_Count) + { + nrFiles++; + } + else if(lsAction==LS_GetFilename) + { + if(cnt==nrFiles) + return; + cnt++; + + } + } +} + +void CardReader::ls() +{ + lsAction=LS_SerialPrint; + if(lsAction==LS_Count) + nrFiles=0; + + root.rewind(); + lsDive("",root); +} + + void CardReader::initsd() { cardOK = false; @@ -48,6 +148,7 @@ void CardReader::initsd() SERIAL_ECHO_START; SERIAL_ECHOLNPGM("SD card ok"); } + curDir=&root; #endif //SDSS } void CardReader::release() @@ -73,13 +174,20 @@ void CardReader::pauseSDPrint() } } -void CardReader::selectFile(char* name) + + +void CardReader::openFile(char* name,bool read) { - if(cardOK){ - sdprinting = false; - file.close(); - - if (file.open(&root, name, O_READ)) { + if(!cardOK) + return; + + + file.close(); + sdprinting = false; + if(read) + { + if (file.open(&root, name, O_READ)) + { filesize = file.fileSize(); SERIAL_PROTOCOLPGM("File opened:"); SERIAL_PROTOCOL(name); @@ -89,32 +197,27 @@ void CardReader::selectFile(char* name) SERIAL_PROTOCOLLNPGM("File selected"); } - else{ + else + { SERIAL_PROTOCOLLNPGM("file.open failed"); } } -} - -void CardReader::startFilewrite(char *name) -{ - if(cardOK) - { - - file.close(); - sdprinting = false; - + else + { //write if (!file.open(&root, name, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) { SERIAL_PROTOCOLPGM("open failed, File: "); SERIAL_PROTOCOL(name); SERIAL_PROTOCOLLNPGM("."); } - else{ + else + { saving = true; SERIAL_PROTOCOLPGM("Writing to file: "); SERIAL_PROTOCOLLN(name); } } + } void CardReader::getStatus() @@ -212,49 +315,25 @@ void CardReader::closefile() void CardReader::getfilename(const uint8_t nr) { - - dir_t p; - root.rewind(); - uint8_t cnt=0; - filename[0]='\0'; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - if(cnt++!=nr) continue; - //Serial.println((char*)p.name); - uint8_t writepos=0; - for (int8_t i = 0; i < 11; i++) - { - if (p.name[i] == ' ') continue; - if (i == 8) { - filename[writepos++]='.'; - } - filename[writepos++]=p.name[i]; - } - filename[writepos++]=0; - } + lsAction=LS_GetFilename; + nrFiles=nr; + curDir->rewind(); + lsDive("",*curDir); + } -uint8_t CardReader::getnrfilenames() +uint16_t CardReader::getnrfilenames() { - dir_t p; - root.rewind(); - uint8_t cnt=0; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - cnt++; - } - return cnt; + lsAction=LS_Count; + nrFiles=0; + curDir->rewind(); + lsDive("",*curDir); + return nrFiles; } +void CardReader::cd(char * absolutPath) +{ + +} #endif //SDSUPPORT \ No newline at end of file From 869cee74e6cdca8caccd281daf2f45cc8e1944b7 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 14:34:27 +0100 Subject: [PATCH 056/228] host-based sd card printing seems now to work with folders --- Marlin/cardreader.pde | 101 ++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 77a8f692bf..4c869e4276 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -64,7 +64,7 @@ void CardReader::lsDive(char *prepend,SdFile parent) strcat(path,lfilename); strcat(path,"/"); - Serial.print(path); + //Serial.print(path); SdFile dir; if(!dir.open(parent,lfilename, O_READ)) @@ -81,30 +81,33 @@ void CardReader::lsDive(char *prepend,SdFile parent) } - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - - - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - //if(cnt++!=nr) continue; - createFilename(filename,p); - if(lsAction==LS_SerialPrint) + else { - SERIAL_PROTOCOL(prepend); - SERIAL_PROTOCOLLN(filename); - } - else if(lsAction==LS_Count) - { - nrFiles++; - } - else if(lsAction==LS_GetFilename) - { - if(cnt==nrFiles) - return; - cnt++; + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + //if(cnt++!=nr) continue; + createFilename(filename,p); + if(lsAction==LS_SerialPrint) + { + SERIAL_PROTOCOL(prepend); + SERIAL_PROTOCOLLN(filename); + } + else if(lsAction==LS_Count) + { + nrFiles++; + } + else if(lsAction==LS_GetFilename) + { + if(cnt==nrFiles) + return; + cnt++; + + } } } } @@ -180,17 +183,57 @@ void CardReader::openFile(char* name,bool read) { if(!cardOK) return; - - file.close(); sdprinting = false; + + + SdFile myDir; + curDir=&root; + char *fname=name; + + char *dirname_start,*dirname_end; + dirname_start=strchr(name,'/')+1; + while(dirname_start!=NULL) + { + dirname_end=strchr(dirname_start,'/'); + //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); + //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); + if(dirname_end!=NULL && dirname_end>dirname_start) + { + char subdirname[13]; + strncpy(subdirname, dirname_start, dirname_end-dirname_start); + subdirname[dirname_end-dirname_start]=0; + SERIAL_ECHOLN(subdirname); + if(!myDir.open(curDir,subdirname,O_READ)) + { + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(subdirname); + SERIAL_PROTOCOLLNPGM("."); + return; + } + else + SERIAL_ECHOLN("dive ok"); + + curDir=&myDir; + dirname_start=dirname_end+1; + } + else // the reminder after all /fsa/fdsa/ is the filename + { + fname=dirname_start; + //SERIAL_ECHOLN("remaider"); + //SERIAL_ECHOLN(fname); + break; + } + + } + if(read) { - if (file.open(&root, name, O_READ)) + if (file.open(curDir, fname, O_READ)) { filesize = file.fileSize(); SERIAL_PROTOCOLPGM("File opened:"); - SERIAL_PROTOCOL(name); + SERIAL_PROTOCOL(fname); SERIAL_PROTOCOLPGM(" Size:"); SERIAL_PROTOCOLLN(filesize); sdpos = 0; @@ -204,10 +247,10 @@ void CardReader::openFile(char* name,bool read) } else { //write - if (!file.open(&root, name, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) { SERIAL_PROTOCOLPGM("open failed, File: "); - SERIAL_PROTOCOL(name); + SERIAL_PROTOCOL(fname); SERIAL_PROTOCOLLNPGM("."); } else From 70650c331da1fca53eafc5616dabdb4e9c4a6693 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 14:50:31 +0100 Subject: [PATCH 057/228] corrected the ultimaker default values, the previous had a calculation error: see: http://groups.google.com/group/ultimaker/browse_thread/thread/91906788639703cf --- Marlin/Configuration.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 9bcddc8723..800bb9b32f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -204,7 +204,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,760*1.1} // default steps per unit for ultimaker +#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 200000} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. @@ -274,7 +274,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define ULTIPANEL #ifdef ULTIPANEL -// #define NEWPANEL //enable this if you have a click-encoder panel + //#define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT #define ULTRA_LCD #define LCD_WIDTH 20 From f0154de5b3d1fea9d9ca62265c739e039576249c Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 15:36:49 +0100 Subject: [PATCH 058/228] found bug that disabled printing from root. --- Marlin/cardreader.pde | 64 +++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 4c869e4276..2771668a46 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -192,41 +192,43 @@ void CardReader::openFile(char* name,bool read) char *fname=name; char *dirname_start,*dirname_end; - dirname_start=strchr(name,'/')+1; - while(dirname_start!=NULL) + if(name[0]=='/') { - dirname_end=strchr(dirname_start,'/'); - //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); - //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); - if(dirname_end!=NULL && dirname_end>dirname_start) + dirname_start=strchr(name,'/')+1; + while(dirname_start>0) { - char subdirname[13]; - strncpy(subdirname, dirname_start, dirname_end-dirname_start); - subdirname[dirname_end-dirname_start]=0; - SERIAL_ECHOLN(subdirname); - if(!myDir.open(curDir,subdirname,O_READ)) + dirname_end=strchr(dirname_start,'/'); + //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); + //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); + if(dirname_end>0 && dirname_end>dirname_start) { - SERIAL_PROTOCOLPGM("open failed, File: "); - SERIAL_PROTOCOL(subdirname); - SERIAL_PROTOCOLLNPGM("."); - return; + char subdirname[13]; + strncpy(subdirname, dirname_start, dirname_end-dirname_start); + subdirname[dirname_end-dirname_start]=0; + SERIAL_ECHOLN(subdirname); + if(!myDir.open(curDir,subdirname,O_READ)) + { + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(subdirname); + SERIAL_PROTOCOLLNPGM("."); + return; + } + else + ;//SERIAL_ECHOLN("dive ok"); + + curDir=&myDir; + dirname_start=dirname_end+1; } - else - SERIAL_ECHOLN("dive ok"); - - curDir=&myDir; - dirname_start=dirname_end+1; + else // the reminder after all /fsa/fdsa/ is the filename + { + fname=dirname_start; + //SERIAL_ECHOLN("remaider"); + //SERIAL_ECHOLN(fname); + break; + } + } - else // the reminder after all /fsa/fdsa/ is the filename - { - fname=dirname_start; - //SERIAL_ECHOLN("remaider"); - //SERIAL_ECHOLN(fname); - break; - } - } - if(read) { if (file.open(curDir, fname, O_READ)) @@ -242,7 +244,9 @@ void CardReader::openFile(char* name,bool read) } else { - SERIAL_PROTOCOLLNPGM("file.open failed"); + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLLNPGM("."); } } else From 8a08b8e07e0bd84c1778eca7f3f32fafff5c3af5 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 15:37:10 +0100 Subject: [PATCH 059/228] trying to get autotemp to work. --- Marlin/Marlin.pde | 10 ++++++++++ Marlin/planner.cpp | 20 +++++++++++++------- Marlin/planner.h | 8 +++++++- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 34d50e3c46..c0fc8675c1 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -695,7 +695,17 @@ inline void process_commands() case 109: {// M109 - Wait for extruder heater to reach target. LCD_MESSAGEPGM("Heating..."); + autotemp_enabled=false; if (code_seen('S')) setTargetHotend0(code_value()); + #ifdef AUTOTEMP + if (code_seen('S')) autotemp_min=code_value(); + if (code_seen('T')) autotemp_max=code_value(); + if (code_seen('F')) + { + autotemp_factor=code_value(); + autotemp_enabled=true; + } + #endif setWatch(); codenum = millis(); diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index c27d586017..0a226c66f7 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -87,7 +87,10 @@ static float previous_speed[4]; // Speed of previous path line segment static float previous_nominal_speed; // Nominal speed of previous path line segment #ifdef AUTOTEMP -float high_e_speed=0; + float autotemp_max=250; + float autotemp_min=210; + float autotemp_factor=1; + bool autotemp_enabled=false; #endif @@ -379,26 +382,29 @@ block_t *plan_get_current_block() { #ifdef AUTOTEMP void getHighESpeed() { - if(degTargetHotend0()+2high) { high=se; } block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); } - high_e_speed=high*axis_steps_per_unit[E_AXIS]/(1000000.0); //so it is independent of the esteps/mm. before - float g=AUTOTEMP_MIN+high_e_speed*AUTOTEMP_FACTOR; - float t=constrain(AUTOTEMP_MIN,g,AUTOTEMP_MAX); + float g=autotemp_min+high*autotemp_factor; + float t=constrain(autotemp_min,g,autotemp_max); setTargetHotend0(t); SERIAL_ECHO_START; - SERIAL_ECHOPAIR("highe",high_e_speed); + SERIAL_ECHOPAIR("highe",high); SERIAL_ECHOPAIR(" t",t); SERIAL_ECHOLN(""); } diff --git a/Marlin/planner.h b/Marlin/planner.h index be1587d6b8..ec497d5064 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -92,7 +92,13 @@ extern float max_xy_jerk; //speed than can be stopped at once, if i understand c extern float max_z_jerk; extern float mintravelfeedrate; extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + + #ifdef AUTOTEMP -extern float high_e_speed; + extern bool autotemp_enabled; + extern float autotemp_max; + extern float autotemp_min; + extern float autotemp_factor; #endif + #endif From 6841a10446f27ab18e573d1d5b5e6e0da7566552 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 19 Nov 2011 16:16:26 +0100 Subject: [PATCH 060/228] Fixed max/min temperature bug --- Marlin/temperature.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index b08a800f68..857814732b 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -99,9 +99,9 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; #endif //MINTEMP #ifdef HEATER_0_MAXTEMP #ifdef HEATER_0_USES_AD595 - static int maxttemp_0 = 0; - #else static int maxttemp_0 = 16383; + #else + static int maxttemp_0 = 0; #endif #endif //MAXTEMP @@ -114,9 +114,9 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; #endif //MINTEMP #ifdef HEATER_1_MAXTEMP #ifdef HEATER_1_USES_AD595 - static int maxttemp_1 = 0; - #else static int maxttemp_1 = 16383; + #else + static int maxttemp_1 = 0; #endif #endif //MAXTEMP @@ -129,9 +129,9 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; #endif //BED_MINTEMP #ifdef BED_MAXTEMP #ifdef BED_USES_AD595 - static int bed_maxttemp = 0; - #else static int bed_maxttemp = 16383; + #else + static int bed_maxttemp = 0; #endif #endif //BED_MAXTEMP @@ -377,7 +377,7 @@ void tp_init() TIMSK0 |= (1< Date: Sat, 19 Nov 2011 17:07:44 +0100 Subject: [PATCH 061/228] autotemp working, default=disabled. --- Marlin/Configuration.h | 7 +++---- Marlin/planner.cpp | 20 +++++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 800bb9b32f..f9a1367024 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -297,11 +297,10 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //automatic temperature: just for testing, this is very dangerous, keep disabled! // not working yet. -//Erik: the settings currently depend dramatically on skeinforge39 or 41. //#define AUTOTEMP -#define AUTOTEMP_MIN 190 -#define AUTOTEMP_MAX 260 -#define AUTOTEMP_FACTOR 1000. //current target temperature= min+largest buffered espeeds)*FACTOR +#ifdef AUTOTEMP + #define AUTOTEMP_OLDWEIGHT 0.98 +#endif const int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 0a226c66f7..b7f98b6d1d 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -382,6 +382,7 @@ block_t *plan_get_current_block() { #ifdef AUTOTEMP void getHighESpeed() { + static float oldt=0; if(!autotemp_enabled) return; if(degTargetHotend0()+2autotemp_max) + t=autotemp_max; + if(oldt>t) + { + t=AUTOTEMP_OLDWEIGHT*oldt+(1-AUTOTEMP_OLDWEIGHT)*t; + } + oldt=t; setTargetHotend0(t); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR("highe",high); - SERIAL_ECHOPAIR(" t",t); - SERIAL_ECHOLN(""); +// SERIAL_ECHO_START; +// SERIAL_ECHOPAIR("highe",high); +// SERIAL_ECHOPAIR(" t",t); +// SERIAL_ECHOLN(""); } #endif From 2a6afee83292e5b741cb99ca4b7b30b7acfe7529 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 17:09:33 +0100 Subject: [PATCH 062/228] make it compile without autotemp --- Marlin/Marlin.pde | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index c0fc8675c1..f619854da3 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -694,8 +694,10 @@ inline void process_commands() break; case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGEPGM("Heating..."); - autotemp_enabled=false; + LCD_MESSAGEPGM("Heating..."); + #ifdef AUTOTEMP + autotemp_enabled=false; + #endif if (code_seen('S')) setTargetHotend0(code_value()); #ifdef AUTOTEMP if (code_seen('S')) autotemp_min=code_value(); From 537b5c155dd0e35080528bcaba088d0d177aa2bd Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 19 Nov 2011 17:23:28 +0100 Subject: [PATCH 063/228] Fixed arc flowrate. --- Marlin/motion_control.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index c2fce52c71..ff3f8c2f2d 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -123,7 +123,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 arc_target[axis_1] = center_axis1 + r_axis1; arc_target[axis_linear] += linear_per_segment; arc_target[E_AXIS] += extruder_per_segment; - plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], target[E_AXIS], feed_rate); + plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate); } // Ensure last segment arrives at target location. From 7a2d1f5aeb85225a7d71e8b95982e36c5fb17722 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 18:22:22 +0100 Subject: [PATCH 064/228] add M17, so the enable stepper button works in repg. --- Marlin/Marlin.pde | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index f619854da3..021a921f7a 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -70,6 +70,8 @@ // M114 - Display current position //Custom M Codes +// M17 - Enable/Power all stepper motors +// M18 - Disaable all stepper motors; same as M84 // M20 - List SD card // M21 - Init SD card // M22 - Release SD card @@ -569,6 +571,13 @@ inline void process_commands() switch( (int)code_value() ) { + case 17: + LCD_MESSAGEPGM("No move."); + enable_x(); + enable_y(); + enable_z(); + enable_e(); + break; #ifdef SDSUPPORT case 20: // M20 - list SD card From 5ad1d19384ba3ea8a1e6c33babc63de1d28acf31 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 20:18:54 +0100 Subject: [PATCH 065/228] make it compile without sd_support --- Marlin/cardreader.h | 14 +++++++------- Marlin/cardreader.pde | 6 +----- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index d96715807f..653f59452e 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -20,17 +20,15 @@ public: void closefile(); void release(); void startFileprint(); - //void startFilewrite(char *name); void pauseSDPrint(); void getStatus(); - void cd(char * absolutPath); - //void selectFile(char* name); + void getfilename(const uint8_t nr); uint16_t getnrfilenames(); void ls(); - void lsDive(char *prepend,SdFile parent); + inline bool eof() { return sdpos>=filesize ;}; inline int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; @@ -57,10 +55,13 @@ private: LsAction lsAction; //stored for recursion. int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. char* diveDirName; + void lsDive(char *prepend,SdFile parent); }; #else + +#define dir_t bool class CardReader { public: @@ -71,6 +72,7 @@ public: inline static void checkautostart(bool x) {}; + inline static void openFile(char* name,bool read){}; inline static void closefile() {}; inline static void release(){}; inline static void startFileprint(){}; @@ -87,9 +89,7 @@ public: inline static bool eof() {return true;}; inline static char get() {return 0;}; inline static void setIndex(){}; + inline uint8_t percentDone(){return 0;}; }; #endif //SDSUPPORT - - - #endif \ No newline at end of file diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 2771668a46..bab87834ec 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -1,5 +1,5 @@ -#ifdef SDSUPPORT #include "cardreader.h" +#ifdef SDSUPPORT CardReader::CardReader() { @@ -378,9 +378,5 @@ uint16_t CardReader::getnrfilenames() return nrFiles; } -void CardReader::cd(char * absolutPath) -{ - -} #endif //SDSUPPORT \ No newline at end of file From 8a1e719a3fd064c0ac0e64ce22d7e6fcd797d342 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 20:52:43 +0100 Subject: [PATCH 066/228] overworked config file --- Marlin/Configuration.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f9a1367024..31884782d2 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -90,6 +90,9 @@ #define PIDTEMP #ifdef PIDTEMP + #if MOTHERBOARD == 62 + #error Sanguinololu does not support PID, sorry. Please disable it. + #endif //#define PID_DEBUG // Sends debug data to the serial port. //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % @@ -195,7 +198,6 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -//note: on bernhards ultimaker 200 200 12 are working well. #define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) #define AXIS_RELATIVE_MODES {false, false, false, false} @@ -205,7 +207,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the // default settings #define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker -//#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} +//#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} //sells mendel with v9 extruder #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 200000} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. @@ -239,7 +241,8 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define EEPROM_CHITCHAT -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// 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 @@ -272,7 +275,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the //#define ULTRA_LCD //general lcd support, also 16x2 //#define SDSUPPORT // Enable SD Card Support in Hardware Console -#define ULTIPANEL +//#define ULTIPANEL #ifdef ULTIPANEL //#define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT @@ -295,8 +298,13 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the #define N_ARC_CORRECTION 25 -//automatic temperature: just for testing, this is very dangerous, keep disabled! -// not working yet. +//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode. +//The maximum buffered steps/sec of the extruder motor are called "se". +//You enter the autotemp mode by a M109 S T F +// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp +// you exit the value by any M109 without F* +// Also, if the temperature is set to a value Date: Sat, 19 Nov 2011 21:01:07 +0100 Subject: [PATCH 067/228] update mcode documentation --- Marlin/Marlin.pde | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 021a921f7a..d942047b76 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -71,7 +71,7 @@ //Custom M Codes // M17 - Enable/Power all stepper motors -// M18 - Disaable all stepper motors; same as M84 +// M18 - Disable all stepper motors; same as M84 // M20 - List SD card // M21 - Init SD card // M22 - Release SD card @@ -92,7 +92,9 @@ // 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 +// 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 From 915ef2d4a136df67f468917c725d032919e189d4 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 19 Nov 2011 21:32:47 +0100 Subject: [PATCH 068/228] Added software endstops --- Marlin/Marlin.pde | 12 ++++++++++++ Marlin/planner.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index f619854da3..aee00ac4a5 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1024,6 +1024,18 @@ inline void get_arc_coordinates() void prepare_move() { + if (min_software_endstops) { + if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0; + if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0; + if (destination[Z_AXIS] < 0) destination[Z_AXIS] = 0.0; + } + + if (max_software_endstops) { + if (destination[X_AXIS] > X_MAX_LENGTH) destination[X_AXIS] = X_MAX_LENGTH; + if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH; + if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; + } + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0); for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; diff --git a/Marlin/planner.h b/Marlin/planner.h index ec497d5064..52a6fba813 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -31,7 +31,7 @@ typedef struct { // Fields used by the bresenham algorithm for tracing the line long steps_x, steps_y, steps_z, steps_e; // Step count along each axis - long step_event_count; // The number of step events required to complete this block + unsigned long step_event_count; // The number of step events required to complete this block long accelerate_until; // The index of the step event on which to stop acceleration long decelerate_after; // The index of the step event on which to start decelerating long acceleration_rate; // The acceleration rate used for acceleration calculation From 61e0740bf03523b861915f5d272851999e934b20 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 22:04:37 +0100 Subject: [PATCH 069/228] overworked readme --- README.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 117 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 699ebdd64a..e79c142d20 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ This RepRap firmware is a mashup between T F you enter the autotemp mode. +You can leave it by calling M109 without any F. +If active, the maximal extruder stepper rate of all buffered moves will be calculated, and named "maxerate" [steps/sec]. +The wanted temperature then will be set to t=tempmin+factor*maxerate, while being limited between tempmin and tempmax. +If the target temperature is set manually or by gcode to a value less then tempmin, it will be kept without change. +Ideally, your gcode can be completely free of temperature controls, apart from a M109 S T F in the start.gcode, and a M109 S0 in the end.gcode. + +EEPROM: +If you know your PID values, the acceleration and max-velocities of your unique machine, you can set them, and finally store them in the EEPROM. +After each reboot, it will magically load them from EEPROM, independent what your Configuration.h says. + +LCD Menu: +If your hardware supports it, you can build yourself a LCD-CardReader+Click+encoder combination. It will enable you to realtime tune temperatures, +accelerations, velocities, flow rates, select and print files from the SD card, preheat, disable the steppers, and do other fancy stuff. +One working hardware is documented here: http://www.thingiverse.com/thing:12663 +Also, with just a 20x4 or 16x2 display, useful data is shown. + +SD card folders: +If you have an SD card reader attached to your controller, also folders work now. Listing the files in pronterface will show "/path/subpath/file.g". +You can write to file in a subfolder by specifying a similar text using small letters in the path. +Also, backup copies of various operating systems are hidden, as well as files not ending with ".g". + +Endstop trigger reporting: +If an endstop is hit while moving towards the endstop, the location at which the firmware thinks that the endstop was triggered is outputed on the serial port. +This is useful, because the user gets a warning message. +However, also tools like QTMarlin can use this for finding acceptable combinations of velocity+acceleration. + +Coding paradigm: +Not relevant from a user side, but Marlin was split into thematic junks, and has tried to partially enforced private variables. +This is intended to make it clearer, what interacts which what, and leads to a higher level of modularization. +We think that this is a useful prestep for porting this firmware to e.g. an ARM platform in the future. +A lot of RAM (with enabled LCD ~2200 bytes) was saved by storing char []="some message" in Program memory. +In the serial communication, a #define based level of abstraction was enforced, so that it is clear that +some transfer is information (usually beginning with "echo:"), an error "error:", or just normal protocol, +necessary for backwards compatibility. + +Interrupt based temperature measurements: +An interrupt is used to manage ADC conversions, and enforce checking for critical temperatures. +This leads to less blocking in the heater management routine. + +======================================================================================== +Non-standard M-Codes, different to an old version of sprinter: + +G2 - CW ARC +G3 - CCW ARC + +General: +M17 - Enable/Power all stepper motors +M18 - Disable all stepper motors; same as M84 +M30 - Print 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 +M114 - Output current position to serial port +M119 - Output Endstop status to serial port +Movement variables: +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 +M220 - set build speed factor override percentage S:factor in percent ; aka "realtime tuneing in the gcode" +M301 - Set PID parameters P I and D +M400 - Finish all moves + +Advance: +M200 - Set filament diameter for advance +M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk + +EEPROM: +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. +======================================================================================== + + Configuring and compilation -Install the latest arduino software IDE/toolset (currently 0022) +Install the arduino software IDE/toolset v22 http://www.arduino.cc/en/Main/Software Install Ultimaker's RepG 25 build http://software.ultimaker.com -(or alternatively install Kliment's printrun/pronterface https://github.com/kliment/Printrun_) +For SD handling and as better substitute (apart from stl manipulation) download +the very nice Kliment's printrun/pronterface https://github.com/kliment/Printrun Copy the Ultimaker Marlin firmware - https:/github.com/bkubicek/Marlin + https://github.com/ErikZalm/Marlin/tree/Marlin_v1 (Use the download button) Start the arduino IDE. -Select Tools -> Board -> Arduino Mega 2560 +Select Tools -> Board -> Arduino Mega 2560 or your microcontroller Select the correct serial port in Tools ->Serial Port Open Marlin.pde From 827cd7270378102c7c1ce7ecbb8a41fcd6fa0ed4 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 09:00:19 +0100 Subject: [PATCH 070/228] format readme. --- README.md | 61 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index e79c142d20..83bf8093f5 100644 --- a/README.md +++ b/README.md @@ -14,26 +14,26 @@ Lampmaker, Bradley Feldman, and others... Features: - - Interrupt based movement with real linear acceleration - - High steprate - - Look ahead (Keep the speed high when possible. High cornering speed) - - Interrupt based temperature protection - - preliminary support for Matthew Roberts advance algorithm - For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html - - Full endstop support - - SD Card support - - SD Card folders (works in pronterface) - - LCD support (ideally 20x4) - - LCD menu system for autonomous SD card printing, controlled by an click-encoder. - - EEPROM storage of e.g. max-velocity, max-acceleration, and similar variables - - many small but handy things originating from bkubicek's fork. - - Arc support - - Temperature oversampling - - Dynamic Temperature setpointing aka "AutoTemp" - - Support for QTMarlin, a very beta GUI for PID-tuning and velocity-acceleration testing. https://github.com/bkubicek/QTMarlin - - Endstop trigger reporting to the host software. - - Updated sdcardlib - - Heater power reporting. Useful for PID monitoring. +* Interrupt based movement with real linear acceleration +* High steprate +* Look ahead (Keep the speed high when possible. High cornering speed) +* Interrupt based temperature protection +* preliminary support for Matthew Roberts advance algorithm +* For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html +* Full endstop support +* SD Card support +* SD Card folders (works in pronterface) +* LCD support (ideally 20x4) +* LCD menu system for autonomous SD card printing, controlled by an click-encoder. +* EEPROM storage of e.g. max-velocity, max-acceleration, and similar variables +* many small but handy things originating from bkubicek's fork. +* Arc support +* Temperature oversampling +* Dynamic Temperature setpointing aka "AutoTemp" +* Support for QTMarlin, a very beta GUI for PID-tuning and velocity-acceleration testing. https://github.com/bkubicek/QTMarlin +* Endstop trigger reporting to the host software. +* Updated sdcardlib +* Heater power reporting. Useful for PID monitoring. This firmware is optimized for Ultimaker's gen6 electronics (including the Ultimaker 1.5.x daughterboard and Arduino Mega 2560). @@ -42,15 +42,18 @@ The default baudrate is 250000. This baudrate has less jitter and hence errors t ======================================================================================== Differences and additions to the already good Sprinter firmware: +================================================================ Look-ahead: +----------- Marlin has look-ahead. While sprinter has to break and re-accelerate at each corner, lookahead will only decelerate and accelerate to a velocity, so that the change in vectorial velocity magnitude is less than the xy_jerk_velocity. This is only possible, if some future moves are already processed, hence the name. It leads to less over-deposition at corners, especially at flat angles. -Arc support: +Arc support: +------------ Splic3r can find curves that, although broken into segments, were ment to describe an arc. Marlin is able to print those arcs. The advantage is the firmware can choose the resolution, and can perform the arc with nearly constant velocity, resulting in a nice finish. @@ -60,10 +63,12 @@ Temperature Oversampling: To reduce noise and make the PID-differential term more useful, 16 ADC conversion results are averaged. AutoTemp: +--------- If your gcode contains a wide spread of extruder velocities, or you realtime change the building speed, the temperature should be changed accordingly. Usually, higher speed requires higher temperature. This can now be performed by the AutoTemp function By calling M109 S T F you enter the autotemp mode. + You can leave it by calling M109 without any F. If active, the maximal extruder stepper rate of all buffered moves will be calculated, and named "maxerate" [steps/sec]. The wanted temperature then will be set to t=tempmin+factor*maxerate, while being limited between tempmin and tempmax. @@ -71,26 +76,31 @@ If the target temperature is set manually or by gcode to a value less then tempm Ideally, your gcode can be completely free of temperature controls, apart from a M109 S T F in the start.gcode, and a M109 S0 in the end.gcode. EEPROM: +------- If you know your PID values, the acceleration and max-velocities of your unique machine, you can set them, and finally store them in the EEPROM. After each reboot, it will magically load them from EEPROM, independent what your Configuration.h says. LCD Menu: +--------- If your hardware supports it, you can build yourself a LCD-CardReader+Click+encoder combination. It will enable you to realtime tune temperatures, accelerations, velocities, flow rates, select and print files from the SD card, preheat, disable the steppers, and do other fancy stuff. One working hardware is documented here: http://www.thingiverse.com/thing:12663 Also, with just a 20x4 or 16x2 display, useful data is shown. SD card folders: +---------------- If you have an SD card reader attached to your controller, also folders work now. Listing the files in pronterface will show "/path/subpath/file.g". You can write to file in a subfolder by specifying a similar text using small letters in the path. Also, backup copies of various operating systems are hidden, as well as files not ending with ".g". Endstop trigger reporting: +-------------------------- If an endstop is hit while moving towards the endstop, the location at which the firmware thinks that the endstop was triggered is outputed on the serial port. This is useful, because the user gets a warning message. However, also tools like QTMarlin can use this for finding acceptable combinations of velocity+acceleration. Coding paradigm: +---------------- Not relevant from a user side, but Marlin was split into thematic junks, and has tried to partially enforced private variables. This is intended to make it clearer, what interacts which what, and leads to a higher level of modularization. We think that this is a useful prestep for porting this firmware to e.g. an ARM platform in the future. @@ -100,12 +110,13 @@ some transfer is information (usually beginning with "echo:"), an error "error:" necessary for backwards compatibility. Interrupt based temperature measurements: +----------------------------------------- An interrupt is used to manage ADC conversions, and enforce checking for critical temperatures. This leads to less blocking in the heater management routine. ======================================================================================== Non-standard M-Codes, different to an old version of sprinter: - +============================================================== G2 - CW ARC G3 - CCW ARC @@ -135,10 +146,8 @@ 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. ======================================================================================== - - - -Configuring and compilation +Configuring and compilation: +============================ Install the arduino software IDE/toolset v22 From 4258841241d9d18e00f1f362cca90d288e6a896f Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 09:03:42 +0100 Subject: [PATCH 071/228] format --- README.md | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 83bf8093f5..5c2b44c3dd 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ -WARNING: THIS IN A PROCESS OF HEAVY OVERWORKING. + +WARNING: +-------- +THIS IN A PROCESS OF HEAVY OVERWORKING. DO NOT USE THIS ON YOUR MACHINE UNTIL FURTHER NOTICE!!! -=========================================== - +Quick Information +=================== This RepRap firmware is a mashup between Sprinter, grbl and many original parts. Derived from Sprinter and Grbl by Erik van der Zalm. @@ -14,33 +17,32 @@ Lampmaker, Bradley Feldman, and others... Features: -* Interrupt based movement with real linear acceleration -* High steprate -* Look ahead (Keep the speed high when possible. High cornering speed) -* Interrupt based temperature protection -* preliminary support for Matthew Roberts advance algorithm -* For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html -* Full endstop support -* SD Card support -* SD Card folders (works in pronterface) -* LCD support (ideally 20x4) -* LCD menu system for autonomous SD card printing, controlled by an click-encoder. -* EEPROM storage of e.g. max-velocity, max-acceleration, and similar variables -* many small but handy things originating from bkubicek's fork. -* Arc support -* Temperature oversampling -* Dynamic Temperature setpointing aka "AutoTemp" -* Support for QTMarlin, a very beta GUI for PID-tuning and velocity-acceleration testing. https://github.com/bkubicek/QTMarlin -* Endstop trigger reporting to the host software. -* Updated sdcardlib -* Heater power reporting. Useful for PID monitoring. +* Interrupt based movement with real linear acceleration +* High steprate +* Look ahead (Keep the speed high when possible. High cornering speed) +* Interrupt based temperature protection +* preliminary support for Matthew Roberts advance algorithm +* For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html +* Full endstop support +* SD Card support +* SD Card folders (works in pronterface) +* LCD support (ideally 20x4) +* LCD menu system for autonomous SD card printing, controlled by an click-encoder. +* EEPROM storage of e.g. max-velocity, max-acceleration, and similar variables +* many small but handy things originating from bkubicek's fork. +* Arc support +* Temperature oversampling +* Dynamic Temperature setpointing aka "AutoTemp" +* Support for QTMarlin, a very beta GUI for PID-tuning and velocity-acceleration testing. https://github.com/bkubicek/QTMarlin +* Endstop trigger reporting to the host software. +* Updated sdcardlib +* Heater power reporting. Useful for PID monitoring. This firmware is optimized for Ultimaker's gen6 electronics (including the Ultimaker 1.5.x daughterboard and Arduino Mega 2560). The default baudrate is 250000. This baudrate has less jitter and hence errors than the usual 115200 baud, but is less supported by drivers and host-environments. -======================================================================================== Differences and additions to the already good Sprinter firmware: ================================================================ @@ -114,7 +116,6 @@ Interrupt based temperature measurements: An interrupt is used to manage ADC conversions, and enforce checking for critical temperatures. This leads to less blocking in the heater management routine. -======================================================================================== Non-standard M-Codes, different to an old version of sprinter: ============================================================== G2 - CW ARC From 4687c56f532c99a1481af36ee26d52c47034323b Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 09:06:05 +0100 Subject: [PATCH 072/228] format --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c2b44c3dd..3a13d92072 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Lampmaker, Bradley Feldman, and others... Features: + * Interrupt based movement with real linear acceleration * High steprate * Look ahead (Keep the speed high when possible. High cornering speed) @@ -146,7 +147,7 @@ EEPROM: 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. -======================================================================================== + Configuring and compilation: ============================ From 6dba34ab0ed5b5f89b70ebe71086200606319bd8 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 09:09:11 +0100 Subject: [PATCH 073/228] even more format. --- README.md | 85 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 3a13d92072..16c1a632f0 100644 --- a/README.md +++ b/README.md @@ -47,26 +47,26 @@ The default baudrate is 250000. This baudrate has less jitter and hence errors t Differences and additions to the already good Sprinter firmware: ================================================================ -Look-ahead: ------------ +*Look-ahead:* + Marlin has look-ahead. While sprinter has to break and re-accelerate at each corner, lookahead will only decelerate and accelerate to a velocity, so that the change in vectorial velocity magnitude is less than the xy_jerk_velocity. This is only possible, if some future moves are already processed, hence the name. It leads to less over-deposition at corners, especially at flat angles. -Arc support: ------------- +*Arc support:* Splic3r can find curves that, although broken into segments, were ment to describe an arc. Marlin is able to print those arcs. The advantage is the firmware can choose the resolution, and can perform the arc with nearly constant velocity, resulting in a nice finish. Also, less serial communication is needed. -Temperature Oversampling: +*Temperature Oversampling:* + To reduce noise and make the PID-differential term more useful, 16 ADC conversion results are averaged. -AutoTemp: ---------- +*AutoTemp:* + If your gcode contains a wide spread of extruder velocities, or you realtime change the building speed, the temperature should be changed accordingly. Usually, higher speed requires higher temperature. This can now be performed by the AutoTemp function @@ -78,32 +78,32 @@ The wanted temperature then will be set to t=tempmin+factor*maxerate, while bein If the target temperature is set manually or by gcode to a value less then tempmin, it will be kept without change. Ideally, your gcode can be completely free of temperature controls, apart from a M109 S T F in the start.gcode, and a M109 S0 in the end.gcode. -EEPROM: -------- +*EEPROM:* + If you know your PID values, the acceleration and max-velocities of your unique machine, you can set them, and finally store them in the EEPROM. After each reboot, it will magically load them from EEPROM, independent what your Configuration.h says. -LCD Menu: ---------- +*LCD Menu:* + If your hardware supports it, you can build yourself a LCD-CardReader+Click+encoder combination. It will enable you to realtime tune temperatures, accelerations, velocities, flow rates, select and print files from the SD card, preheat, disable the steppers, and do other fancy stuff. One working hardware is documented here: http://www.thingiverse.com/thing:12663 Also, with just a 20x4 or 16x2 display, useful data is shown. -SD card folders: ----------------- +*SD card folders:* + If you have an SD card reader attached to your controller, also folders work now. Listing the files in pronterface will show "/path/subpath/file.g". You can write to file in a subfolder by specifying a similar text using small letters in the path. Also, backup copies of various operating systems are hidden, as well as files not ending with ".g". -Endstop trigger reporting: --------------------------- +*Endstop trigger reporting:* + If an endstop is hit while moving towards the endstop, the location at which the firmware thinks that the endstop was triggered is outputed on the serial port. This is useful, because the user gets a warning message. However, also tools like QTMarlin can use this for finding acceptable combinations of velocity+acceleration. -Coding paradigm: ----------------- +*Coding paradigm:* + Not relevant from a user side, but Marlin was split into thematic junks, and has tried to partially enforced private variables. This is intended to make it clearer, what interacts which what, and leads to a higher level of modularization. We think that this is a useful prestep for porting this firmware to e.g. an ARM platform in the future. @@ -112,41 +112,46 @@ In the serial communication, a #define based level of abstraction was enforced, some transfer is information (usually beginning with "echo:"), an error "error:", or just normal protocol, necessary for backwards compatibility. -Interrupt based temperature measurements: ------------------------------------------ +*Interrupt based temperature measurements:* + An interrupt is used to manage ADC conversions, and enforce checking for critical temperatures. This leads to less blocking in the heater management routine. + Non-standard M-Codes, different to an old version of sprinter: ============================================================== -G2 - CW ARC -G3 - CCW ARC +* G2 - CW ARC +* G3 - CCW ARC General: -M17 - Enable/Power all stepper motors -M18 - Disable all stepper motors; same as M84 -M30 - Print 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 -M114 - Output current position to serial port -M119 - Output Endstop status to serial port + +* M17 - Enable/Power all stepper motors +* M18 - Disable all stepper motors; same as M84 +* M30 - Print 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 +* M114 - Output current position to serial port +* M119 - Output Endstop status to serial port + Movement variables: -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 -M220 - set build speed factor override percentage S:factor in percent ; aka "realtime tuneing in the gcode" -M301 - Set PID parameters P I and D -M400 - Finish all moves + +* 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 +* M220 - set build speed factor override percentage S:factor in percent ; aka "realtime tuneing in the gcode" +* M301 - Set PID parameters P I and D +* M400 - Finish all moves Advance: -M200 - Set filament diameter for advance -M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk + +* M200 - Set filament diameter for advance +* M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk EEPROM: -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. +* 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. Configuring and compilation: ============================ From d8e7e2f72e28d2df29f3f8b23215419e21b0727b Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 11:55:06 +0100 Subject: [PATCH 074/228] more readme --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 16c1a632f0..5b1ead2039 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ This is only possible, if some future moves are already processed, hence the nam It leads to less over-deposition at corners, especially at flat angles. *Arc support:* + Splic3r can find curves that, although broken into segments, were ment to describe an arc. Marlin is able to print those arcs. The advantage is the firmware can choose the resolution, and can perform the arc with nearly constant velocity, resulting in a nice finish. @@ -120,13 +121,15 @@ This leads to less blocking in the heater management routine. Non-standard M-Codes, different to an old version of sprinter: ============================================================== +Movement: + * G2 - CW ARC * G3 - CCW ARC General: -* M17 - Enable/Power all stepper motors -* M18 - Disable all stepper motors; same as M84 +* M17 - Enable/Power all stepper motors. Compatibility to ReplicatorG. +* M18 - Disable all stepper motors; same as M84.Compatibility to ReplicatorG. * M30 - Print time since last M109 or SD card start to serial * M42 - Change pin status via gcode * M80 - Turn on Power Supply @@ -139,9 +142,9 @@ Movement variables: * 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 -* M220 - set build speed factor override percentage S:factor in percent ; aka "realtime tuneing in the gcode" +* M220 - set build speed mulitplying S:factor in percent ; aka "realtime tuneing in the gcode". So you can slow down if you have islands in one height-range, and speed up otherwise. * M301 - Set PID parameters P I and D -* M400 - Finish all moves +* M400 - Finish all buffered moves. Advance: From cd2268f10a88de393a565c887c8891c7f7979a97 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 11:55:33 +0100 Subject: [PATCH 075/228] code cleanup in ultralcd. --- Marlin/ultralcd.h | 49 +++++++ Marlin/ultralcd.pde | 326 +++++++++----------------------------------- 2 files changed, 112 insertions(+), 263 deletions(-) diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 6bae43dccb..d3496bec98 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -72,6 +72,55 @@ int8_t lastlineoffset; bool linechanging; + + private: + inline void updateActiveLines(const uint8_t &maxlines,volatile int &encoderpos) + { + if(linechanging) return; // an item is changint its value, do not switch lines hence + lastlineoffset=lineoffset; + int curencoderpos=encoderpos; + force_lcd_update=false; + if( (abs(curencoderpos-lastencoderpos)(LCD_HEIGHT-1+1)*lcdslow) + { + lineoffset++; + curencoderpos=(LCD_HEIGHT-1)*lcdslow; + if(lineoffset>(maxlines+1-LCD_HEIGHT)) + lineoffset=maxlines+1-LCD_HEIGHT; + if(curencoderpos>maxlines*lcdslow) + curencoderpos=maxlines*lcdslow; + force_lcd_update=true; + } + lastencoderpos=encoderpos=curencoderpos; + activeline=curencoderpos/lcdslow; + if(activeline<0) activeline=0; + if(activeline>LCD_HEIGHT-1) activeline=LCD_HEIGHT-1; + if(activeline>maxlines) + { + activeline=maxlines; + curencoderpos=maxlines*lcdslow; + } + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + } + } + + inline void clearIfNecessary() + { + if(lastlineoffset!=lineoffset ||force_lcd_update) + { + force_lcd_update=true; + lcd.clear(); + } + } }; //conversion routines, could need some overworking diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index c4ea234883..aa30a3dd0e 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -279,7 +279,6 @@ MainMenu::MainMenu() linechanging=false; } - void MainMenu::showStatus() { #if LCD_HEIGHT==4 @@ -426,131 +425,46 @@ void MainMenu::showStatus() enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; +//any action must not contain a ',' character anywhere, or this breaks: +#define MENUITEM(repaint_action, click_action) \ + {\ + if(force_lcd_update) { lcd.setCursor(0,line); repaint_action; } \ + if((activeline==line) && CLICKED) {click_action} \ + } + void MainMenu::showPrepare() { uint8_t line=0; - if(lastlineoffset!=lineoffset) - { - force_lcd_update=true; - clear(); - } + clearIfNecessary(); for(int8_t i=lineoffset;i3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(ItemP_disstep+1-LCD_HEIGHT)) - lineoffset=ItemP_disstep+1-LCD_HEIGHT; - force_lcd_update=true; - } - //encoderpos=encoderpos%LCD_HEIGHT; - lastencoderpos=encoderpos; - activeline=encoderpos/lcdslow; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - } + updateActiveLines(ItemP_disstep,encoderpos); } enum { ItemC_exit, ItemC_nozzle, @@ -563,31 +477,35 @@ enum { ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe }; +//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};}\ +// } +// + + void MainMenu::showControl() { uint8_t line=0; - if((lastlineoffset!=lineoffset)||force_lcd_update) - { - force_lcd_update=true; - clear(); - } + clearIfNecessary(); for(int8_t i=lineoffset;i3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(ItemC_failsafe+1-LCD_HEIGHT)) - lineoffset=ItemC_failsafe+1-LCD_HEIGHT; - force_lcd_update=true; - } - //encoderpos=encoderpos%LCD_HEIGHT; - lastencoderpos=encoderpos; - activeline=encoderpos/lcdslow; - if(activeline>3) activeline=3; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - } + updateActiveLines(ItemC_failsafe,encoderpos); } @@ -1175,14 +1065,11 @@ void MainMenu::showSD() #ifdef SDSUPPORT uint8_t line=0; - if(lastlineoffset!=lineoffset) - { - force_lcd_update=true; - } + clearIfNecessary(); static uint8_t nrfiles=0; if(force_lcd_update) { - clear(); + clear(); if(card.cardOK) { nrfiles=card.getnrfilenames(); @@ -1192,7 +1079,6 @@ void MainMenu::showSD() nrfiles=0; lineoffset=0; } - //Serial.print("Nr files:"); Serial.println((int)nrfiles); } for(int8_t i=lineoffset;i3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(1+nrfiles+1-LCD_HEIGHT)) - lineoffset=1+nrfiles+1-LCD_HEIGHT; - force_lcd_update=true; - - } - lastencoderpos=encoderpos; - activeline=encoderpos; - if(activeline>3) - { - activeline=3; - } - if(activeline<0) - { - activeline=0; - } - if(activeline>1+nrfiles) activeline=1+nrfiles; - if(lineoffset>1+nrfiles) lineoffset=1+nrfiles; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - - } + updateActiveLines(1+nrfiles,encoderpos); #endif } enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file }; void MainMenu::showMainMenu() { - //if(int(encoderpos/lcdslow)!=int(lastencoderpos/lcdslow)) - // force_lcd_update=true; + #ifndef ULTIPANEL force_lcd_update=false; #endif - //Serial.println((int)activeline); - if(force_lcd_update) - clear(); + + clearIfNecessary(); for(int8_t line=0;line=LCD_HEIGHT) - activeline=LCD_HEIGHT-1; - if((encoderpos!=lastencoderpos)||force_lcd_update) - { - lcd.setCursor(0,activeline);lcd.print(activeline?' ':' '); - if(encoderpos<0) encoderpos=0; - if(encoderpos>3*lcdslow) - encoderpos=3*lcdslow; - activeline=abs(encoderpos/lcdslow)%LCD_HEIGHT; - if(activeline<0) - activeline=0; - if(activeline>=LCD_HEIGHT) - activeline=LCD_HEIGHT-1; - lastencoderpos=encoderpos; - lcd.setCursor(0,activeline);lcd.print(activeline?'>':'\003'); - } + updateActiveLines(3,encoderpos); } void MainMenu::update() @@ -1433,20 +1235,18 @@ void MainMenu::update() if(CARDINSERTED) { card.initsd(); - lcd_status("Card inserted"); + LCD_MESSAGEPGM("Card inserted"); } else { card.release(); - lcd_status("Card removed"); + LCD_MESSAGEPGM("Card removed"); } } #endif if(status!=oldstatus) { - //Serial.println(status); - //clear(); force_lcd_update=true; encoderpos=0; lineoffset=0; From 2e43f9c80987576441f66040afd20b456ed44636 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 20 Nov 2011 13:14:58 +0100 Subject: [PATCH 076/228] Changed min max temperature code. --- Marlin/Configuration.h | 2 +- Marlin/temperature.cpp | 154 ++++++++++++++++++++--------------------- 2 files changed, 76 insertions(+), 80 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 31884782d2..da5372021e 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -80,7 +80,7 @@ // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. #define HEATER_0_MAXTEMP 275 -//#define_HEATER_1_MAXTEMP 275 +//#define HEATER_1_MAXTEMP 275 //#define BED_MAXTEMP 150 diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 857814732b..f5df6f617b 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -90,50 +90,12 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; #endif //WATCHPERIOD // Init min and max temp with extreme values to prevent false errors during startup -#ifdef HEATER_0_MINTEMP - #ifdef HEATER_0_USES_AD595 - static int minttemp_0 = 0; - #else - static int minttemp_0 = 16383; - #endif -#endif //MINTEMP -#ifdef HEATER_0_MAXTEMP - #ifdef HEATER_0_USES_AD595 - static int maxttemp_0 = 16383; - #else - static int maxttemp_0 = 0; - #endif -#endif //MAXTEMP - -#ifdef HEATER_1_MINTEMP - #ifdef HEATER_1_USES_AD595 - static int minttemp_1 = 0; - #else - static int minttemp_1 = 16383; - #endif -#endif //MINTEMP -#ifdef HEATER_1_MAXTEMP - #ifdef HEATER_1_USES_AD595 - static int maxttemp_1 = 16383; - #else - static int maxttemp_1 = 0; - #endif -#endif //MAXTEMP - -#ifdef BED_MINTEMP - #ifdef BED_USES_AD595 - static int bed_minttemp = 0; - #else - static int bed_minttemp = 16383; - #endif -#endif //BED_MINTEMP -#ifdef BED_MAXTEMP - #ifdef BED_USES_AD595 - static int bed_maxttemp = 16383; - #else - static int bed_maxttemp = 0; - #endif -#endif //BED_MAXTEMP + static int minttemp_0 = 0; + static int maxttemp_0 = 16383; + static int minttemp_1 = 0; + static int maxttemp_1 = 16383; + static int bed_minttemp = 0; + static int bed_maxttemp = 16383; //=========================================================================== //=============================functions ============================ @@ -198,18 +160,28 @@ void manage_heater() //SERIAL_ECHOLN(" PIDDEBUG Input "< minttemp_0) && (current_raw[TEMPSENSOR_HOTEND_0] < maxttemp_0)) { + analogWrite(HEATER_0_PIN, pid_output); + } + else { + analogWrite(HEATER_0_PIN, 0); + } #endif //PIDTEMP #ifndef PIDTEMP - if(current_raw[0] >= target_raw[0]) - { + // Check if temperature is within the correct range + if((current_raw[TEMPSENSOR_HOTEND_0] > minttemp_0) && (current_raw[TEMPSENSOR_HOTEND_0] < maxttemp_0)) { + if(current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) { + WRITE(HEATER_0_PIN,LOW); + } + else { + WRITE(HEATER_0_PIN,HIGH); + } + } + else { WRITE(HEATER_0_PIN,LOW); - } - else - { - WRITE(HEATER_0_PIN,HIGH); - } + } #endif if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) @@ -217,14 +189,20 @@ void manage_heater() previous_millis_bed_heater = millis(); #if TEMP_1_PIN > -1 - if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) - { + // Check if temperature is within the correct range + if((current_raw[TEMPSENSOR_BED] > bed_minttemp) && (current_raw[TEMPSENSOR_BED] < bed_maxttemp)) { + if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) + { + WRITE(HEATER_1_PIN,LOW); + } + else + { + WRITE(HEATER_1_PIN,HIGH); + } + } + else { WRITE(HEATER_1_PIN,LOW); - } - else - { - WRITE(HEATER_1_PIN,HIGH); - } + } #endif } @@ -370,6 +348,34 @@ void tp_init() // Set analog inputs ADCSRA = 1< -1) + #if TEMP_0_PIN < 8 + DIDR0 |= 1 << TEMP_0_PIN; + #else + DIDR2 |= 1<<(TEMP_0_PIN - 8); + ADCSRB = 1< -1) + #if TEMP_1_PIN < 8 + DIDR0 |= 1< -1) + #if TEMP_2_PIN < 8 + DIDR0 |= 1 << TEMP_2_PIN; + #else + DIDR2 = 1<<(TEMP_2_PIN - 8); + ADCSRB = 1< -1) - #if TEMP_0_PIN < 8 - DIDR0 = 1 << TEMP_0_PIN; - #else - DIDR2 = 1<<(TEMP_0_PIN - 8); + #if TEMP_0_PIN > 7 ADCSRB = 1< -1) - #if TEMP_1_PIN < 7 - DIDR0 = 1< 7 ADCSRB = 1< -1) - #if TEMP_2_PIN < 7 - DIDR0 = 1 << TEMP_2_PIN; - #else - DIDR2 = 1<<(TEMP_2_PIN - 8); + #if TEMP_2_PIN > 7 ADCSRB = 1< -1) if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); + digitalWrite(HEATER_0_PIN, 0); SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MAXTEMP triggered !!"); kill(); @@ -567,11 +564,10 @@ ISR(TIMER0_COMPB_vect) #if (HEATER_1_PIN > -1) if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { target_raw[TEMPSENSOR_HOTEND_1] = 0; - if(current_raw[2] >= maxttemp_1) { - analogWrite(HEATER_2_PIN, 0); + digitalWrite(HEATER_2_PIN, 0); SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MAXTEMP triggered !!"); - kill() + kill(); } #endif #endif //MAXTEMP @@ -580,7 +576,7 @@ ISR(TIMER0_COMPB_vect) #if (HEATER_0_PIN > -1) if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { target_raw[TEMPSENSOR_HOTEND_0] = 0; - analogWrite(HEATER_0_PIN, 0); + digitalWrite(HEATER_0_PIN, 0); SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MINTEMP triggered !!"); kill(); @@ -592,7 +588,7 @@ ISR(TIMER0_COMPB_vect) #if (HEATER_2_PIN > -1) if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { target_raw[TEMPSENSOR_HOTEND_1] = 0; - analogWrite(HEATER_2_PIN, 0); + digitalWrite(HEATER_2_PIN, 0); SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MINTEMP triggered !!"); kill(); @@ -604,7 +600,7 @@ ISR(TIMER0_COMPB_vect) #if (HEATER_1_PIN > -1) if(current_raw[1] <= bed_minttemp) { target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); + digitalWrite(HEATER_1_PIN, 0); SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Temperatur heated bed switched off. MINTEMP triggered !!"); kill(); @@ -616,7 +612,7 @@ ISR(TIMER0_COMPB_vect) #if (HEATER_1_PIN > -1) if(current_raw[1] >= bed_maxttemp) { target_raw[1] = 0; - WRITE(HEATER_1_PIN, 0); + digitalWrite(HEATER_1_PIN, 0); SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); kill(); From 85c8a87e7087ca1a639947e17f6a71ac8a5f8140 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 20 Nov 2011 13:31:07 +0100 Subject: [PATCH 077/228] Small changes to README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 16c1a632f0..22b3c9a0fd 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This RepRap firmware is a mashup between \hardware\Sanguino + Install Ultimaker's RepG 25 build http://software.ultimaker.com For SD handling and as better substitute (apart from stl manipulation) download From b21d5193f25e3e388ddc3787aba7f0086a1abad7 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 14:43:47 +0100 Subject: [PATCH 078/228] made ultralcd compatible with folders. --- Marlin/cardreader.h | 6 +- Marlin/cardreader.pde | 115 +++++++---- Marlin/ultralcd.h | 6 +- Marlin/ultralcd.pde | 461 +++++++++++++++++++++++++----------------- 4 files changed, 366 insertions(+), 222 deletions(-) diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 653f59452e..44ebf0e2c1 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -28,7 +28,8 @@ public: void ls(); - + void chdir(const char * relpath); + void updir(); inline bool eof() { return sdpos>=filesize ;}; inline int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; @@ -40,8 +41,9 @@ public: bool sdprinting ; bool cardOK ; char filename[11]; + bool filenameIsDir; private: - SdFile root,*curDir; + SdFile root,*curDir,workDir,workDirParent,workDirParentParent; Sd2Card card; SdVolume volume; SdFile file; diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index bab87834ec..c0dbc58e47 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -1,4 +1,5 @@ #include "cardreader.h" +//#include #ifdef SDSUPPORT CardReader::CardReader() @@ -36,11 +37,7 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters return buffer; } -// bool SdFat::chdir(bool set_cwd) { -// if (set_cwd) SdBaseFile::cwd_ = &vwd_; -// vwd_.close(); -// return vwd_.openRoot(&vol_); -// } + void CardReader::lsDive(char *prepend,SdFile parent) { dir_t p; @@ -85,11 +82,19 @@ void CardReader::lsDive(char *prepend,SdFile parent) { if (p.name[0] == DIR_NAME_FREE) break; if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if ( p.name[0] == '.') + { + if ( p.name[1] != '.') + continue; + } if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + filenameIsDir=DIR_IS_SUBDIR(&p); - - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; + if(!filenameIsDir) + { + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + } //if(cnt++!=nr) continue; createFilename(filename,p); if(lsAction==LS_SerialPrint) @@ -126,33 +131,35 @@ void CardReader::ls() void CardReader::initsd() { cardOK = false; - #if SDSS >- 1 - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)) - { - //if (!card.init(SPI_HALF_SPEED,SDSS)) - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("SD init fail"); - } - else if (!volume.init(&card)) - { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("volume.init failed"); - } - else if (!root.openRoot(&volume)) - { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("openRoot failed"); - } - else - { - cardOK = true; - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("SD card ok"); - } - curDir=&root; - #endif //SDSS + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)) + { + //if (!card.init(SPI_HALF_SPEED,SDSS)) + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("SD init fail"); + } + else if (!volume.init(&card)) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("volume.init failed"); + } + else if (!root.openRoot(&volume)) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("openRoot failed"); + } + else + { + cardOK = true; + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("SD card ok"); + } + curDir=&root; + if(!workDir.openRoot(&volume)) + { + SERIAL_ECHOLNPGM("workDir open failed"); + } } void CardReader::release() { @@ -229,6 +236,10 @@ void CardReader::openFile(char* name,bool read) } } + else //relative path + { + curDir=&workDir; + } if(read) { if (file.open(curDir, fname, O_READ)) @@ -362,6 +373,7 @@ void CardReader::closefile() void CardReader::getfilename(const uint8_t nr) { + curDir=&workDir; lsAction=LS_GetFilename; nrFiles=nr; curDir->rewind(); @@ -371,12 +383,45 @@ void CardReader::getfilename(const uint8_t nr) uint16_t CardReader::getnrfilenames() { + curDir=&workDir; lsAction=LS_Count; nrFiles=0; curDir->rewind(); lsDive("",*curDir); + //SERIAL_ECHOLN(nrFiles); return nrFiles; } +void CardReader::chdir(const char * relpath) +{ + SdFile newfile; + SdFile *parent=&root; + + if(workDir.isOpen()) + parent=&workDir; + + if(!newfile.open(*parent,relpath, O_READ)) + { + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Cannot enter subdir:"); + SERIAL_ECHOLN(relpath); + } + else + { + workDirParentParent=workDirParent; + workDirParent=*parent; + + workDir=newfile; + } +} + +void CardReader::updir() +{ + if(!workDir.isRoot()) + { + workDir=workDirParent; + workDirParent=workDirParentParent; + } +} #endif //SDSUPPORT \ No newline at end of file diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index d3496bec98..6222c70c25 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -51,13 +51,13 @@ #define blocktime 500 #define lcdslow 5 - enum MainStatus{Main_Status, Main_Menu, Main_Prepare, Main_Control, Main_SD}; + enum MainStatus{Main_Status, Main_Menu, Main_Prepare, Main_Control, Main_SD,Sub_TempControl,Sub_MotionControl}; class MainMenu{ public: MainMenu(); void update(); - uint8_t activeline; + int8_t activeline; MainStatus status; uint8_t displayStartingRow; @@ -65,6 +65,8 @@ void showMainMenu(); void showPrepare(); void showControl(); + void showControlMotion(); + void showControlTemp(); void showSD(); bool force_lcd_update; int lastencoderpos; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index aa30a3dd0e..57f63c1061 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -114,11 +114,13 @@ void lcd_init() }; byte uplevel[8]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris + byte folder [8]={0x00, 0x1c, 0x1f, 0x11, 0x11, 0x1f, 0x00, 0x00}; //thanks joris lcd.begin(LCD_WIDTH, LCD_HEIGHT); lcd.createChar(1,Degree); lcd.createChar(2,Thermometer); lcd.createChar(3,uplevel); lcd.createChar(4,refresh); + lcd.createChar(5,folder); LCD_MESSAGEPGM("UltiMarlin ready."); } @@ -224,6 +226,7 @@ void buttons_check() buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 #endif + //manage encoder rotation char enc=0; if(buttons&EN_A) enc|=(1<<0); @@ -311,22 +314,22 @@ void MainMenu::showStatus() oldtargetHotEnd0=ttHotEnd0; } #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - static int oldtBed=-1; - static int oldtargetBed=-1; - int tBed=intround(degBed()); - if((tBed!=oldtBed)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(tBed)); - olddegHotEnd0=tBed; - } - int targetBed=intround(degTargetBed()); - if((targetBed!=oldtargetBed)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(targetBed)); - oldtargetBed=targetBed; - } + static int oldtBed=-1; + static int oldtargetBed=-1; + int tBed=intround(degBed()); + if((tBed!=oldtBed)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(tBed)); + oldtBed=tBed; + } + int targetBed=intround(degTargetBed()); + if((targetBed!=oldtargetBed)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(targetBed)); + oldtargetBed=targetBed; + } #endif //starttime=2; static uint16_t oldtime=0; @@ -421,6 +424,7 @@ void MainMenu::showStatus() } #endif + force_lcd_update=false; } enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; @@ -466,16 +470,7 @@ void MainMenu::showPrepare() } updateActiveLines(ItemP_disstep,encoderpos); } -enum { - ItemC_exit, ItemC_nozzle, - ItemC_PID_P,ItemC_PID_I,ItemC_PID_D,ItemC_PID_C, - ItemC_fan, - ItemC_acc, ItemC_xyjerk, - ItemC_vmaxx, ItemC_vmaxy, ItemC_vmaxz, ItemC_vmaxe, - ItemC_vtravmin,ItemC_vmin, - ItemC_amaxx, ItemC_amaxy, ItemC_amaxz, ItemC_amaxe, - ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe -}; + //does not work // #define MENUCHANGEITEM(repaint_action, enter_action, accept_action, change_action) \ @@ -494,19 +489,23 @@ enum { // } // - -void MainMenu::showControl() +enum { + ItemCT_exit, ItemCT_nozzle, ItemCT_fan, + ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C +}; + +void MainMenu::showControlTemp() { - uint8_t line=0; + uint8_t line=0; clearIfNecessary(); for(int8_t i=lineoffset;i990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); - } - } - }break; - case ItemC_xyjerk: //max_xy_jerk - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: "); - lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_xy_jerk; - } - else - { - max_xy_jerk= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_PID_P: + case ItemCT_PID_P: { if(force_lcd_update) { @@ -678,7 +610,7 @@ void MainMenu::showControl() } } }break; - case ItemC_PID_I: + case ItemCT_PID_I: { if(force_lcd_update) { @@ -712,7 +644,7 @@ void MainMenu::showControl() } } }break; - case ItemC_PID_D: + case ItemCT_PID_D: { if(force_lcd_update) { @@ -745,11 +677,9 @@ void MainMenu::showControl() lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); } } - }break; - - - - case ItemC_PID_C: + }break; + case ItemCT_PID_C: + #ifdef PID_ADD_EXTRUSION_RATE { if(force_lcd_update) { @@ -782,20 +712,50 @@ void MainMenu::showControl() lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); } } - }break; - case ItemC_vmaxx: - case ItemC_vmaxy: - case ItemC_vmaxz: - case ItemC_vmaxe: - { + } + #endif + break; + default: + break; + } + line++; + } + #ifdef PID_ADD_EXTRUSION_RATE + updateActiveLines(ItemCT_PID_C,encoderpos); + #else + updateActiveLines(ItemCT_PID_D,encoderpos); + #endif +} + + +enum { + ItemCM_exit, + ItemCM_acc, ItemCM_xyjerk, + ItemCM_vmaxx, ItemCM_vmaxy, ItemCM_vmaxz, ItemCM_vmaxe, + ItemCM_vtravmin,ItemCM_vmin, + ItemCM_amaxx, ItemCM_amaxy, ItemCM_amaxz, ItemCM_amaxe, + ItemCM_aret,ItemCM_esteps +}; + + + +void MainMenu::showControlMotion() +{ + uint8_t line=0; + clearIfNecessary(); + for(int8_t i=lineoffset;i990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + } + } + }break; + case ItemCM_xyjerk: //max_xy_jerk + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: "); + lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_xy_jerk; + } + else + { + max_xy_jerk= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemCM_vmaxx: + case ItemCM_vmaxy: + case ItemCM_vmaxz: + case ItemCM_vmaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Vmax "); + if(i==ItemCM_vmaxx)lcdprintPGM("x:"); + if(i==ItemCM_vmaxy)lcdprintPGM("y:"); + if(i==ItemCM_vmaxz)lcdprintPGM("z:"); + if(i==ItemCM_vmaxe)lcdprintPGM("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx])); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_feedrate[i-ItemCM_vmaxx]; + } + else + { + max_feedrate[i-ItemCM_vmaxx]= encoderpos; encoderpos=activeline*lcdslow; } @@ -825,7 +860,7 @@ void MainMenu::showControl() } }break; - case ItemC_vmin: + case ItemCM_vmin: { if(force_lcd_update) { @@ -859,7 +894,7 @@ void MainMenu::showControl() } } }break; - case ItemC_vtravmin: + case ItemCM_vtravmin: { if(force_lcd_update) { @@ -894,19 +929,19 @@ void MainMenu::showControl() } }break; - case ItemC_amaxx: - case ItemC_amaxy: - case ItemC_amaxz: - case ItemC_amaxe: + case ItemCM_amaxx: + case ItemCM_amaxy: + case ItemCM_amaxz: + case ItemCM_amaxe: { if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(" Amax "); - if(i==ItemC_amaxx)lcdprintPGM("x:"); - if(i==ItemC_amaxy)lcdprintPGM("y:"); - if(i==ItemC_amaxz)lcdprintPGM("z:"); - if(i==ItemC_amaxe)lcdprintPGM("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcdprintPGM("00"); + if(i==ItemCM_amaxx)lcdprintPGM("x:"); + if(i==ItemCM_amaxy)lcdprintPGM("y:"); + if(i==ItemCM_amaxz)lcdprintPGM("z:"); + if(i==ItemCM_amaxe)lcdprintPGM("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));lcdprintPGM("00"); } if((activeline==line) ) @@ -916,11 +951,11 @@ void MainMenu::showControl() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100; + encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100; } else { - max_acceleration_units_per_sq_second[i-ItemC_amaxx]= encoderpos*100; + max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100; encoderpos=activeline*lcdslow; } BLOCK; @@ -934,7 +969,7 @@ void MainMenu::showControl() } } }break; - case ItemC_aret://float retract_acceleration = 7000; + case ItemCM_aret://float retract_acceleration = 7000; { if(force_lcd_update) { @@ -968,7 +1003,7 @@ void MainMenu::showControl() } } }break; - case ItemC_esteps://axis_steps_per_unit[i] = code_value(); + case ItemCM_esteps://axis_steps_per_unit[i] = code_value(); { if(force_lcd_update) { @@ -1005,6 +1040,37 @@ void MainMenu::showControl() } } }break; + default: + break; + } + line++; + } + updateActiveLines(ItemCM_esteps,encoderpos); +} + + +enum { + ItemC_exit,ItemC_temp,ItemC_move, + ItemC_store, ItemC_load,ItemC_failsafe +}; + +void MainMenu::showControl() +{ + uint8_t line=0; + clearIfNecessary(); + for(int8_t i=lineoffset;i Date: Sun, 20 Nov 2011 14:50:08 +0100 Subject: [PATCH 079/228] Added endstop reporting --- Marlin/Marlin.pde | 24 ++++--- Marlin/planner.cpp | 1 + Marlin/stepper.cpp | 159 ++++++++++++++++++++++----------------------- Marlin/stepper.h | 100 ++++++++++++++-------------- 4 files changed, 138 insertions(+), 146 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 754dc3618c..8ee1656935 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -465,24 +465,22 @@ inline bool code_seen(char code) destination[LETTER##_AXIS] = 1.5 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ feedrate = homing_feedrate[LETTER##_AXIS]; \ prepare_move(); \ - st_synchronize();\ \ current_position[LETTER##_AXIS] = 0;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ destination[LETTER##_AXIS] = -5 * LETTER##_HOME_DIR;\ prepare_move(); \ - st_synchronize();\ \ destination[LETTER##_AXIS] = 10 * LETTER##_HOME_DIR;\ feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ prepare_move(); \ - st_synchronize();\ \ current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? 0 : LETTER##_MAX_LENGTH;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ feedrate = 0.0;\ st_synchronize();\ + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ endstops_hit_on_purpose();\ } @@ -680,7 +678,7 @@ inline void process_commands() case 140: // M140 set bed temp if (code_seen('S')) setTargetBed(code_value()); break; - case 105: // M105 + case 105 : // M105 //SERIAL_ECHOLN(freeMemory()); //test watchdog: //delay(20000); @@ -817,7 +815,7 @@ inline void process_commands() axis_relative_modes[3] = true; break; case 18: //compatibility - case 84: + case 84: // M84 if(code_seen('S')){ stepper_inactive_time = code_value() * 1000; } @@ -854,14 +852,14 @@ inline void process_commands() SERIAL_PROTOCOL(current_position[Z_AXIS]); SERIAL_PROTOCOLPGM("E:"); SERIAL_PROTOCOL(current_position[E_AXIS]); - #ifdef DEBUG_STEPS - SERIAL_PROTOCOLPGM(" Count X:"); - SERIAL_PROTOCOL(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); - SERIAL_PROTOCOLPGM("Y:"); - SERIAL_PROTOCOL(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); - SERIAL_PROTOCOLPGM("Z:"); - SERIAL_PROTOCOL(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); - #endif + + SERIAL_PROTOCOLPGM(" 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 119: // M119 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index b7f98b6d1d..a59945da89 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -754,6 +754,7 @@ void plan_set_position(const float &x, const float &y, const float &z, const flo position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]); previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. previous_speed[0] = 0.0; previous_speed[1] = 0.0; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index b08e61ae45..771bccfd4b 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -66,14 +66,12 @@ static char step_loops; volatile long endstops_trigsteps[3]={0,0,0}; volatile long endstops_stepsTotal,endstops_stepsDone; -static volatile bool endstops_hit=false; +static volatile bool endstop_x_hit=false; +static volatile bool endstop_y_hit=false; +static volatile bool endstop_z_hit=false; -// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. -// for debugging purposes only, should be disabled by default -#ifdef DEBUG_STEPS - volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; - volatile int count_direction[NUM_AXIS] = { 1, 1, 1, 1}; -#endif +volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; +volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; //=========================================================================== //=============================functions ============================ @@ -155,49 +153,32 @@ asm volatile ( \ #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<step_event_count; - endstops_stepsDone=stepstaken; - endstops_trigsteps[0]=current_block->steps_x; - endstops_trigsteps[1]=current_block->steps_y; - endstops_trigsteps[2]=current_block->steps_z; - - endstops_hit=true; -} - void checkHitEndstops() { - if( !endstops_hit) - return; - float endstops_triggerpos[3]={0,0,0}; - float ratiodone=endstops_stepsDone/float(endstops_stepsTotal); //ratio of current_block thas was performed - - endstops_triggerpos[0]=current_position[0]-(endstops_trigsteps[0]*ratiodone)/float(axis_steps_per_unit[0]); - endstops_triggerpos[1]=current_position[1]-(endstops_trigsteps[1]*ratiodone)/float(axis_steps_per_unit[1]); - endstops_triggerpos[2]=current_position[2]-(endstops_trigsteps[2]*ratiodone)/float(axis_steps_per_unit[2]); - SERIAL_ECHO_START; - SERIAL_ECHOPGM("endstops hit: "); - SERIAL_ECHOPAIR(" X:",endstops_triggerpos[0]); - SERIAL_ECHOPAIR(" Y:",endstops_triggerpos[1]); - SERIAL_ECHOPAIR(" Z:",endstops_triggerpos[2]); - SERIAL_ECHOLN(""); - endstops_hit=false; + if( endstop_x_hit || endstop_y_hit || endstop_z_hit) { + SERIAL_ECHO_START; + SERIAL_ECHOPGM("endstops hit: "); + if(endstop_x_hit) { + SERIAL_ECHOPAIR(" X:",(float)endstops_trigsteps[X_AXIS]/axis_steps_per_unit[X_AXIS]); + } + if(endstop_y_hit) { + SERIAL_ECHOPAIR(" Y:",(float)endstops_trigsteps[Y_AXIS]/axis_steps_per_unit[Y_AXIS]); + } + if(endstop_z_hit) { + SERIAL_ECHOPAIR(" Z:",(float)endstops_trigsteps[Z_AXIS]/axis_steps_per_unit[Z_AXIS]); + } + SERIAL_ECHOLN(""); + endstop_x_hit=false; + endstop_y_hit=false; + endstop_z_hit=false; + } } void endstops_hit_on_purpose() { - endstops_hit=false; + endstop_x_hit=false; + endstop_y_hit=false; + endstop_z_hit=false; } // __________________________ @@ -312,24 +293,22 @@ ISR(TIMER1_COMPA_vect) // Set direction en check limit switches if ((out_bits & (1< -1 - if(READ(X_MIN_PIN) != ENDSTOPS_INVERTING) { - // endstops_triggered(step_events_completed); + if((READ(X_MIN_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x > 0)) { + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; step_events_completed = current_block->step_event_count; } #endif } else { // +direction WRITE(X_DIR_PIN,!INVERT_X_DIR); - #ifdef DEBUG_STEPS - count_direction[X_AXIS]=1; - #endif + count_direction[X_AXIS]=1; #if X_MAX_PIN > -1 - if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x >0)){ - // endstops_triggered(step_events_completed); + if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x > 0)){ + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; step_events_completed = current_block->step_event_count; } #endif @@ -337,24 +316,22 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 - if(READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) { -// endstops_triggered(step_events_completed); + if((READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y > 0)) { + endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; + endstop_y_hit=true; step_events_completed = current_block->step_event_count; } #endif } else { // +direction WRITE(Y_DIR_PIN,!INVERT_Y_DIR); - #ifdef DEBUG_STEPS - count_direction[Y_AXIS]=1; - #endif + count_direction[Y_AXIS]=1; #if Y_MAX_PIN > -1 - if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y >0)){ - // endstops_triggered(step_events_completed); + if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y > 0)){ + endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; + endstop_y_hit=true; step_events_completed = current_block->step_event_count; } #endif @@ -362,34 +339,36 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 - if(READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) { - // endstops_triggered(step_events_completed); + if((READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z > 0)) { + endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; + endstop_z_hit=true; step_events_completed = current_block->step_event_count; } #endif } else { // +direction WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - #ifdef DEBUG_STEPS count_direction[Z_AXIS]=1; - #endif #if Z_MAX_PIN > -1 - if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z >0)){ - // endstops_triggered(step_events_completed); + if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z > 0)){ + endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; + endstop_z_hit=true; step_events_completed = current_block->step_event_count; } #endif } #ifndef ADVANCE - if ((out_bits & (1<step_event_count; WRITE(X_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[X_AXIS]+=count_direction[X_AXIS]; - #endif + count_position[X_AXIS]+=count_direction[X_AXIS]; } counter_y += current_block->steps_y; @@ -432,9 +409,7 @@ ISR(TIMER1_COMPA_vect) WRITE(Y_STEP_PIN, HIGH); counter_y -= current_block->step_event_count; WRITE(Y_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Y_AXIS]+=count_direction[Y_AXIS]; - #endif + count_position[Y_AXIS]+=count_direction[Y_AXIS]; } counter_z += current_block->steps_z; @@ -442,9 +417,7 @@ ISR(TIMER1_COMPA_vect) WRITE(Z_STEP_PIN, HIGH); counter_z -= current_block->step_event_count; WRITE(Z_STEP_PIN, LOW); - #ifdef DEBUG_STEPS - count_position[Z_AXIS]+=count_direction[Z_AXIS]; - #endif + count_position[Z_AXIS]+=count_direction[Z_AXIS]; } #ifndef ADVANCE @@ -453,6 +426,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E_STEP_PIN, HIGH); counter_e -= current_block->step_event_count; WRITE(E_STEP_PIN, LOW); + count_position[E_AXIS]+=count_direction[E_AXIS]; } #endif //!ADVANCE step_events_completed += 1; @@ -669,3 +643,22 @@ void st_synchronize() LCD_STATUS; } } + +void st_set_position(const long &x, const long &y, const long &z, const long &e) +{ + CRITICAL_SECTION_START; + count_position[X_AXIS] = x; + count_position[Y_AXIS] = y; + count_position[Z_AXIS] = z; + count_position[E_AXIS] = e; + CRITICAL_SECTION_END; +} + +long st_get_position(char axis) +{ + long count_pos; + CRITICAL_SECTION_START; + count_pos = count_position[axis]; + CRITICAL_SECTION_END; + return count_pos; +} diff --git a/Marlin/stepper.h b/Marlin/stepper.h index ecbc713e36..eb07fa9ce5 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -1,51 +1,51 @@ -/* - stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -#ifndef stepper_h -#define stepper_h - -#include "planner.h" - -// Initialize and start the stepper motor subsystem -void st_init(); - -// Block until all buffered steps are executed -void st_synchronize(); - -// The stepper subsystem goes to sleep when it runs out of things to execute. Call this -// to notify the subsystem that it is time to go to work. -void st_wake_up(); - -// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. -// for debugging purposes only, should be disabled by default -#ifdef DEBUG_STEPS - extern volatile long count_position[NUM_AXIS]; - extern volatile int count_direction[NUM_AXIS]; -#endif - -void checkHitEndstops(); //call from somwhere to create an serial error message with the locations the endstops where hit, in case they were triggered -void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after homeing and before a routine call of checkHitEndstops(); - - - -extern block_t *current_block; // A pointer to the block currently being traced - - +/* + stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +#ifndef stepper_h +#define stepper_h + +#include "planner.h" + +// Initialize and start the stepper motor subsystem +void st_init(); + +// Block until all buffered steps are executed +void st_synchronize(); + +// Set current position in steps +void st_set_position(const long &x, const long &y, const long &z, const long &e); + +// Get current position in steps +long st_get_position(char axis); + +// The stepper subsystem goes to sleep when it runs out of things to execute. Call this +// to notify the subsystem that it is time to go to work. +void st_wake_up(); + + +void checkHitEndstops(); //call from somwhere to create an serial error message with the locations the endstops where hit, in case they were triggered +void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after homeing and before a routine call of checkHitEndstops(); + + + +extern block_t *current_block; // A pointer to the block currently being traced + + #endif From 959d82e81e3a8185992a4c8edeff171fed9f01ca Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 20 Nov 2011 15:03:35 +0100 Subject: [PATCH 080/228] Small temperature disable bug. --- Marlin/temperature.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index f5df6f617b..04353b566d 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -430,21 +430,21 @@ void disable_heater() #if TEMP_0_PIN > -1 target_raw[0]=0; #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); + digitalWrite(HEATER_0_PIN,LOW); #endif #endif #if TEMP_1_PIN > -1 target_raw[1]=0; #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); + digitalWrite(HEATER_1_PIN,LOW); #endif #endif #if TEMP_2_PIN > -1 target_raw[2]=0; #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); + digitalWrite(HEATER_2_PIN,LOW); #endif #endif } From 379ea642e181ee072a80d361dfb043e7f3318103 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 16:05:42 +0100 Subject: [PATCH 081/228] make tuneing sub-menu. --- Marlin/cardreader.pde | 4 +- Marlin/planner.cpp | 4 + Marlin/planner.h | 1 + Marlin/ultralcd.h | 13 ++- Marlin/ultralcd.pde | 231 ++++++++++++++++++++++++++++++++++++------ 5 files changed, 216 insertions(+), 37 deletions(-) diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index c0dbc58e47..eec10f199f 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -252,10 +252,11 @@ void CardReader::openFile(char* name,bool read) sdpos = 0; SERIAL_PROTOCOLLNPGM("File selected"); + LCD_MESSAGE(fname); } else { - SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOLPGM("open failed, File: "); SERIAL_PROTOCOL(fname); SERIAL_PROTOCOLLNPGM("."); } @@ -273,6 +274,7 @@ void CardReader::openFile(char* name,bool read) saving = true; SERIAL_PROTOCOLPGM("Writing to file: "); SERIAL_PROTOCOLLN(name); + LCD_MESSAGE(fname); } } diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index a59945da89..214226e2c7 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -762,3 +762,7 @@ void plan_set_position(const float &x, const float &y, const float &z, const flo previous_speed[3] = 0.0; } +uint8_t movesplanned() +{ + return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); +} diff --git a/Marlin/planner.h b/Marlin/planner.h index 52a6fba813..511f532d7e 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -80,6 +80,7 @@ void plan_discard_current_block(); block_t *plan_get_current_block(); void check_axes_activity(); +uint8_t movesplanned(); extern unsigned long minsegmenttime; extern float max_feedrate[4]; // set the max speeds diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 6222c70c25..8b7d3ce83a 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -64,6 +64,7 @@ void showStatus(); void showMainMenu(); void showPrepare(); + void showTune(); void showControl(); void showControlMotion(); void showControlTemp(); @@ -75,6 +76,8 @@ bool linechanging; + bool tune; + private: inline void updateActiveLines(const uint8_t &maxlines,volatile int &encoderpos) { @@ -89,8 +92,7 @@ { lineoffset--; if(lineoffset<0) lineoffset=0; - curencoderpos=lcdslow-1; - force_lcd_update=true; + curencoderpos=lcdslow-1; } if(curencoderpos>(LCD_HEIGHT-1+1)*lcdslow) { @@ -100,9 +102,9 @@ lineoffset=maxlines+1-LCD_HEIGHT; if(curencoderpos>maxlines*lcdslow) curencoderpos=maxlines*lcdslow; - force_lcd_update=true; } - lastencoderpos=encoderpos=curencoderpos; + lastencoderpos=encoderpos=curencoderpos; + int lastactiveline=activeline; activeline=curencoderpos/lcdslow; if(activeline<0) activeline=0; if(activeline>LCD_HEIGHT-1) activeline=LCD_HEIGHT-1; @@ -111,6 +113,8 @@ activeline=maxlines; curencoderpos=maxlines*lcdslow; } + if(lastactiveline!=activeline ||lastlineoffset!=lineoffset) + force_lcd_update=true; lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); } } @@ -126,7 +130,6 @@ }; //conversion routines, could need some overworking - char *fillto(int8_t n,char *c); char *ftostr51(const float &x); char *ftostr31(const float &x); char *ftostr3(const float &x); diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 57f63c1061..e2a75df10a 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -65,6 +65,7 @@ inline int intround(const float &x){return int(0.5+x);} void lcd_status(const char* message) { strncpy(messagetext,message,LCD_WIDTH); + messagetext[strlen(message)]=0; } void lcd_statuspgm(const char* message) @@ -79,6 +80,7 @@ void lcd_statuspgm(const char* message) cnt++; ch=pgm_read_byte(++message); } + *target=0; } inline void clear() @@ -280,6 +282,7 @@ MainMenu::MainMenu() #endif lcd_init(); linechanging=false; + tune=false; } void MainMenu::showStatus() @@ -373,7 +376,11 @@ void MainMenu::showStatus() if(messagetext[0]!='\0') { lcd.setCursor(0,LCD_HEIGHT-1); - lcd.print(fillto(LCD_WIDTH,messagetext)); + lcd.print(messagetext); + uint8_t n=strlen(messagetext); + for(int8_t i=0;i400) encoderpos=400; + feedmultiply = encoderpos; + feedmultiplychanged=true; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemT_nozzle: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:"); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(degTargetHotend0()); + } + else + { + setTargetHotend0(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemT_fan: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + } + + if((activeline==line) ) + { + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=fanpwm; + } + else + { + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemT_flow://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Flow:"); + lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)axis_steps_per_unit[3]; + } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + } + }break; + default: + break; + } + line++; + } + updateActiveLines(ItemT_fan,encoderpos); +} //does not work // #define MENUCHANGEITEM(repaint_action, enter_action, accept_action, change_action) \ @@ -510,7 +680,7 @@ void MainMenu::showControlTemp() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:"); - lcd.setCursor(13,line);lcd.print(ftostr3(intround(degHotend0()))); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); } if((activeline==line) ) @@ -520,7 +690,7 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=intround(degHotend0()); + encoderpos=intround(degTargetHotend0()); } else { @@ -558,10 +728,7 @@ void MainMenu::showControlTemp() } else { - fanpwm = constrain(encoderpos,0,255); - encoderpos=fanpwm; - analogWrite(FAN_PIN, fanpwm); - + encoderpos=activeline*lcdslow; beepshort(); } BLOCK; @@ -1246,7 +1413,22 @@ void MainMenu::showMainMenu() #ifndef ULTIPANEL force_lcd_update=false; #endif - + if(tune) + { + if(!(movesplanned() ||card.sdprinting)) + { + force_lcd_update=true; + tune=false; + } + } + else + { + if(movesplanned() ||card.sdprinting) + { + force_lcd_update=true; + tune=true; + } + } clearIfNecessary(); for(int8_t line=0;line Date: Sun, 20 Nov 2011 16:37:01 +0100 Subject: [PATCH 082/228] less lcd flickering --- Marlin/ultralcd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 8b7d3ce83a..85a8df74c5 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -113,7 +113,7 @@ activeline=maxlines; curencoderpos=maxlines*lcdslow; } - if(lastactiveline!=activeline ||lastlineoffset!=lineoffset) + if(lastlineoffset!=lineoffset) force_lcd_update=true; lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); } From 5535e51bf678a367aa6e5d53068f5d20b1c15e0c Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sun, 20 Nov 2011 17:04:57 +0100 Subject: [PATCH 083/228] Yes, thats the beta. --- Marlin/Marlin.pde | 2 +- Marlin/planner.h | 2 +- README.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 8ee1656935..1a2fadc5a0 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -41,7 +41,7 @@ #include "watchdog.h" -#define VERSION_STRING "1.0.0 Alpha 1" +#define VERSION_STRING "1.0.0 Beta 1" diff --git a/Marlin/planner.h b/Marlin/planner.h index 511f532d7e..95ca548c5f 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -80,7 +80,7 @@ void plan_discard_current_block(); block_t *plan_get_current_block(); void check_axes_activity(); -uint8_t movesplanned(); +uint8_t movesplanned(); //return the nr of buffered moves extern unsigned long minsegmenttime; extern float max_feedrate[4]; // set the max speeds diff --git a/README.md b/README.md index 988bf9a6e6..b6d22ab482 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ WARNING: -------- -THIS IN A PROCESS OF HEAVY OVERWORKING. -DO NOT USE THIS ON YOUR MACHINE UNTIL FURTHER NOTICE!!! +THIS IS THE BETA 1 FOR MARLIN 1.0.0 Quick Information =================== @@ -150,6 +149,7 @@ Advance: * M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk EEPROM: + * 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. From 0db97b9c7f4cb26e4a767c9aa2a4b8be4007e209 Mon Sep 17 00:00:00 2001 From: ErikZalm Date: Mon, 21 Nov 2011 22:40:47 +0100 Subject: [PATCH 084/228] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index b6d22ab482..0beb13fe58 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - WARNING: -------- THIS IS THE BETA 1 FOR MARLIN 1.0.0 @@ -54,7 +53,7 @@ It leads to less over-deposition at corners, especially at flat angles. *Arc support:* -Splic3r can find curves that, although broken into segments, were ment to describe an arc. +Slic3r can find curves that, although broken into segments, were ment to describe an arc. Marlin is able to print those arcs. The advantage is the firmware can choose the resolution, and can perform the arc with nearly constant velocity, resulting in a nice finish. Also, less serial communication is needed. From c0f8c9fd7213d30708071b3d3e94ddc898aa92ac Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 25 Nov 2011 13:43:06 +0100 Subject: [PATCH 085/228] Seperate ENDSTOP_INVERTING for X Y and Z Added simple endstop filter. Corrected M114 count display. --- Marlin/Configuration.h | 4 +++- Marlin/Marlin.pde | 25 ++++++++++++++++--------- Marlin/planner.cpp | 7 +++++++ Marlin/planner.h | 2 +- Marlin/stepper.cpp | 39 +++++++++++++++++++++++++++++++++------ Marlin/stepper.h | 3 ++- 6 files changed, 62 insertions(+), 18 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index da5372021e..f8bb40e12e 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -157,7 +157,9 @@ // Endstop Settings #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 1a2fadc5a0..61078eee7c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -556,12 +556,19 @@ inline void process_commands() relative_mode = true; break; case 92: // G92 - if(!code_seen(axis_codes[E_AXIS])) + if(!code_seen(axis_codes[E_AXIS])) st_synchronize(); for(int8_t i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) current_position[i] = code_value(); + if(code_seen(axis_codes[i])) { + current_position[i] = code_value(); + if(i == E_AXIS) { + plan_set_e_position(current_position[E_AXIS]); + } + else { + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + } + } } - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); break; } } @@ -865,27 +872,27 @@ inline void process_commands() case 119: // M119 #if (X_MIN_PIN > -1) SERIAL_PROTOCOLPGM("x_min:"); - SERIAL_PROTOCOL(((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); + SERIAL_PROTOCOL(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (X_MAX_PIN > -1) SERIAL_PROTOCOLPGM("x_max:"); - SERIAL_PROTOCOL(((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); + SERIAL_PROTOCOL(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MIN_PIN > -1) SERIAL_PROTOCOLPGM("y_min:"); - SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); + SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MAX_PIN > -1) SERIAL_PROTOCOLPGM("y_max:"); - SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); + SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MIN_PIN > -1) SERIAL_PROTOCOLPGM("z_min:"); - SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); + SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MAX_PIN > -1) SERIAL_PROTOCOLPGM("z_max:"); - SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ")); + SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); #endif SERIAL_PROTOCOLLN(""); break; diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 214226e2c7..8a27a2cc25 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -762,7 +762,14 @@ void plan_set_position(const float &x, const float &y, const float &z, const flo previous_speed[3] = 0.0; } +void plan_set_e_position(const float &e) +{ + position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + st_set_e_position(position[E_AXIS]); +} + uint8_t movesplanned() { return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); } + diff --git a/Marlin/planner.h b/Marlin/planner.h index 95ca548c5f..9aa121acae 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -70,7 +70,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // Set position. Used for G92 instructions. void plan_set_position(const float &x, const float &y, const float &z, const float &e); - +void plan_set_e_position(const float &e); // Called when the current block is no longer needed. Discards the block and makes the memory // availible for new blocks. diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 771bccfd4b..ad1fda9e09 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -70,6 +70,13 @@ static volatile bool endstop_x_hit=false; static volatile bool endstop_y_hit=false; static volatile bool endstop_z_hit=false; +static bool old_x_min_endstop=false; +static bool old_x_max_endstop=false; +static bool old_y_min_endstop=false; +static bool old_y_max_endstop=false; +static bool old_z_min_endstop=false; +static bool old_z_max_endstop=false; + volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; @@ -260,6 +267,7 @@ ISR(TIMER1_COMPA_vect) SERIAL_ERROR_START SERIAL_ERROR(*(unsigned short *)OCR1A); SERIAL_ERRORLNPGM(" ISR overtaking itself."); + OCR1A = 0x30000; return; } // The busy-flag is used to avoid reentering this interrupt @@ -295,22 +303,26 @@ ISR(TIMER1_COMPA_vect) WRITE(X_DIR_PIN, INVERT_X_DIR); count_direction[X_AXIS]=-1; #if X_MIN_PIN > -1 - if((READ(X_MIN_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x > 0)) { + bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); + if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; endstop_x_hit=true; step_events_completed = current_block->step_event_count; } + old_x_min_endstop = x_min_endstop; #endif } else { // +direction WRITE(X_DIR_PIN,!INVERT_X_DIR); count_direction[X_AXIS]=1; #if X_MAX_PIN > -1 - if((READ(X_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_x > 0)){ + bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING); + if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; endstop_x_hit=true; step_events_completed = current_block->step_event_count; } + old_x_max_endstop = x_max_endstop; #endif } @@ -318,22 +330,26 @@ ISR(TIMER1_COMPA_vect) WRITE(Y_DIR_PIN,INVERT_Y_DIR); count_direction[Y_AXIS]=-1; #if Y_MIN_PIN > -1 - if((READ(Y_MIN_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y > 0)) { + bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING); + if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstop_y_hit=true; step_events_completed = current_block->step_event_count; } + old_y_min_endstop = y_min_endstop; #endif } else { // +direction WRITE(Y_DIR_PIN,!INVERT_Y_DIR); count_direction[Y_AXIS]=1; #if Y_MAX_PIN > -1 - if((READ(Y_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_y > 0)){ + bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING); + if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstop_y_hit=true; step_events_completed = current_block->step_event_count; } + old_y_max_endstop = y_max_endstop; #endif } @@ -341,22 +357,26 @@ ISR(TIMER1_COMPA_vect) WRITE(Z_DIR_PIN,INVERT_Z_DIR); count_direction[Z_AXIS]=-1; #if Z_MIN_PIN > -1 - if((READ(Z_MIN_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z > 0)) { + bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING); + if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_z_hit=true; step_events_completed = current_block->step_event_count; } + old_z_min_endstop = z_min_endstop; #endif } else { // +direction WRITE(Z_DIR_PIN,!INVERT_Z_DIR); count_direction[Z_AXIS]=1; #if Z_MAX_PIN > -1 - if((READ(Z_MAX_PIN) != ENDSTOPS_INVERTING) && (current_block->steps_z > 0)){ + bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING); + if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_z_hit=true; step_events_completed = current_block->step_event_count; } + old_z_max_endstop = z_max_endstop; #endif } @@ -654,6 +674,13 @@ void st_set_position(const long &x, const long &y, const long &z, const long &e) CRITICAL_SECTION_END; } +void st_set_e_position(const long &e) +{ + CRITICAL_SECTION_START; + count_position[E_AXIS] = e; + CRITICAL_SECTION_END; +} + long st_get_position(char axis) { long count_pos; diff --git a/Marlin/stepper.h b/Marlin/stepper.h index eb07fa9ce5..468838486d 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -31,6 +31,7 @@ void st_synchronize(); // Set current position in steps void st_set_position(const long &x, const long &y, const long &z, const long &e); +void st_set_e_position(const long &e); // Get current position in steps long st_get_position(char axis); @@ -48,4 +49,4 @@ void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after home extern block_t *current_block; // A pointer to the block currently being traced -#endif +#endif From 0e0e4945d8ad060aa50552a0b27369c18442c2d0 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 25 Nov 2011 13:59:58 +0100 Subject: [PATCH 086/228] Removed ISR overtaken message from ISR routine --- Marlin/Marlin.pde | 1 + Marlin/stepper.cpp | 18 +++++++++++++++--- Marlin/stepper.h | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 61078eee7c..edba13f35f 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -289,6 +289,7 @@ void loop() manage_heater(); manage_inactivity(1); checkHitEndstops(); + checkStepperErrors(); LCD_STATUS; } diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index ad1fda9e09..2a3b8d8caf 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -77,6 +77,9 @@ static bool old_y_max_endstop=false; static bool old_z_min_endstop=false; static bool old_z_max_endstop=false; +static bool bussy_error=false; +unsigned char OCR1A_error=12345; + volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; @@ -160,6 +163,16 @@ asm volatile ( \ #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< Date: Fri, 25 Nov 2011 15:32:50 +0100 Subject: [PATCH 087/228] Small nominal speed improvement. --- Marlin/stepper.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 2a3b8d8caf..19f5bd9d0f 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -78,7 +78,8 @@ static bool old_z_min_endstop=false; static bool old_z_max_endstop=false; static bool bussy_error=false; -unsigned char OCR1A_error=12345; +unsigned short OCR1A_error=12345; +unsigned short OCR1A_nominal; volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; @@ -270,6 +271,7 @@ inline void trapezoid_generator_reset() { acc_step_rate = current_block->initial_rate; acceleration_time = calc_timer(acc_step_rate); OCR1A = acceleration_time; + OCR1A_nominal = calc_timer(current_block->nominal_rate); } // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. @@ -477,11 +479,11 @@ ISR(TIMER1_COMPA_vect) // step_rate to timer interval timer = calc_timer(acc_step_rate); + OCR1A = timer; + acceleration_time += timer; #ifdef ADVANCE advance += advance_rate; #endif - acceleration_time += timer; - OCR1A = timer; } else if (step_events_completed > current_block->decelerate_after) { MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); @@ -499,17 +501,16 @@ ISR(TIMER1_COMPA_vect) // step_rate to timer interval timer = calc_timer(step_rate); + OCR1A = timer; + deceleration_time += timer; #ifdef ADVANCE advance -= advance_rate; if(advance < final_advance) advance = final_advance; #endif //ADVANCE - deceleration_time += timer; - OCR1A = timer; } else { - timer = calc_timer(current_block->nominal_rate); - OCR1A = timer; + OCR1A = OCR1A_nominal; } // If current block is finished, reset pointer From 6ac9b2e7614766a38276d143592ba0b6e8f31271 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 25 Nov 2011 19:34:36 +0100 Subject: [PATCH 088/228] Fixed residency time bug. (Thanks to Sound :-) ) --- Marlin/Marlin.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index edba13f35f..c55d7b7dac 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -737,7 +737,7 @@ inline void process_commands() 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((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) || + while((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0())) || (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) ) { From cdf0bd4e635508ba622e0a333ddf5ffbde90cfa3 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 25 Nov 2011 20:07:30 +0100 Subject: [PATCH 089/228] Fixed config bug when EEPROM was disabled --- Marlin/EEPROMwrite.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 3d8a0b2b9e..be3210fc95 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -102,6 +102,7 @@ inline void RetrieveSettings(bool def=false) SERIAL_ECHOLNPGM("Stored settings retreived:"); } else + #endif { float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; float tmp2[]=DEFAULT_MAX_FEEDRATE; @@ -173,8 +174,6 @@ inline void RetrieveSettings(bool def=false) SERIAL_ECHOLN(""); #endif #endif - - #endif //EEPROM_SETTINGS } #endif From 27654bfe697ee08a83f4f39567357827ef77fd1f Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 25 Nov 2011 22:10:06 +0100 Subject: [PATCH 090/228] Fixed variable (removed 0x) --- Marlin/stepper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 19f5bd9d0f..cae5b61cd5 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -281,7 +281,7 @@ ISR(TIMER1_COMPA_vect) if(busy){ OCR1A_error = OCR1A; bussy_error = true; - OCR1A = 0x30000; + OCR1A = 30000; return; } // The busy-flag is used to avoid reentering this interrupt From 235051253a504fa6f4866bda604f2612df7aad0e Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 25 Nov 2011 22:14:29 +0100 Subject: [PATCH 091/228] overworked lcd+eeprom to have only mm/sec and PID including pid_dt --- Marlin/EEPROMwrite.h | 22 +++++++++++----------- Marlin/ultralcd.pde | 24 ++++++++++++------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index be3210fc95..3d559c0269 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -136,10 +136,10 @@ inline void RetrieveSettings(bool def=false) SERIAL_ECHO_START; SERIAL_ECHOLNPGM("Maximum feedrates (mm/s):"); SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M203 X",max_feedrate[0]/60); - SERIAL_ECHOPAIR(" Y",max_feedrate[1]/60 ); - SERIAL_ECHOPAIR(" Z", max_feedrate[2]/60 ); - SERIAL_ECHOPAIR(" E", max_feedrate[3]/60); + SERIAL_ECHOPAIR(" M203 X",max_feedrate[0]); + SERIAL_ECHOPAIR(" Y",max_feedrate[1] ); + SERIAL_ECHOPAIR(" Z", max_feedrate[2] ); + SERIAL_ECHOPAIR(" E", max_feedrate[3]); SERIAL_ECHOLN(""); SERIAL_ECHO_START; SERIAL_ECHOLNPGM("Maximum Acceleration (mm/s2):"); @@ -158,19 +158,19 @@ inline void RetrieveSettings(bool def=false) SERIAL_ECHO_START; SERIAL_ECHOLNPGM("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M205 S",minimumfeedrate/60 ); - SERIAL_ECHOPAIR(" T" ,mintravelfeedrate/60 ); + SERIAL_ECHOPAIR(" M205 S",minimumfeedrate ); + SERIAL_ECHOPAIR(" T" ,mintravelfeedrate ); SERIAL_ECHOPAIR(" B" ,minsegmenttime ); - SERIAL_ECHOPAIR(" X" ,max_xy_jerk/60 ); - SERIAL_ECHOPAIR(" Z" ,max_z_jerk/60); + SERIAL_ECHOPAIR(" X" ,max_xy_jerk ); + SERIAL_ECHOPAIR(" Z" ,max_z_jerk); SERIAL_ECHOLN(""); #ifdef PIDTEMP SERIAL_ECHO_START; SERIAL_ECHOLNPGM("PID settings:"); SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M301 P",Kp ); - SERIAL_ECHOPAIR(" I" ,Ki ); - SERIAL_ECHOPAIR(" D" ,Kd); + SERIAL_ECHOPAIR(" M301 P",Kp); + SERIAL_ECHOPAIR(" I" ,Ki/PID_dT); + SERIAL_ECHOPAIR(" D" ,Kd*PID_dT); SERIAL_ECHOLN(""); #endif #endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index e2a75df10a..e6a16a408e 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -758,11 +758,11 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Kp/5; + encoderpos=(int)Kp; } else { - Kp= encoderpos*5; + Kp= encoderpos; encoderpos=activeline*lcdslow; } @@ -772,8 +772,8 @@ void MainMenu::showControlTemp() if(linechanging) { if(encoderpos<1) encoderpos=1; - if(encoderpos>9990/5) encoderpos=9990/5; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); } } }break; @@ -782,7 +782,7 @@ void MainMenu::showControlTemp() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(" PID-I: "); - lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); + lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT)); } if((activeline==line) ) @@ -792,11 +792,11 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(Ki*10); + encoderpos=(int)(Ki*10/PID_dT); } else { - Ki= encoderpos/10.; + Ki= encoderpos/10.*PID_dT; encoderpos=activeline*lcdslow; } @@ -816,7 +816,7 @@ void MainMenu::showControlTemp() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(" PID-D: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kd)); + lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT)); } if((activeline==line) ) @@ -826,11 +826,11 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Kd/5; + encoderpos=(int)(Kd/5./PID_dT); } else { - Kd= encoderpos*5; + Kd= encoderpos; encoderpos=activeline*lcdslow; } @@ -840,8 +840,8 @@ void MainMenu::showControlTemp() if(linechanging) { if(encoderpos<0) encoderpos=0; - if(encoderpos>9990/5) encoderpos=9990/5; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); } } }break; From b58787a3672111d487bbc53049329a92792a161d Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 25 Nov 2011 22:32:26 +0100 Subject: [PATCH 092/228] now velocities are also set in mm/sec in gcode. --- Marlin/Marlin.pde | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index c55d7b7dac..6cc7d6c032 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -913,7 +913,7 @@ inline void process_commands() #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()*60 ; + if(code_seen(axis_codes[i])) max_feedrate[i] = code_value(); } break; case 204: // M204 acclereration S normal moves T filmanent only moves @@ -924,11 +924,11 @@ inline void process_commands() 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()*60 ; - if(code_seen('T')) mintravelfeedrate = code_value()*60 ; + 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()*60 ; - if(code_seen('Z')) max_z_jerk = code_value()*60 ; + if(code_seen('X')) max_xy_jerk = code_value() ; + if(code_seen('Z')) max_z_jerk = code_value()s ; } break; case 220: // M220 S- set speed factor override percentage From 57e163e98999b45b9fff814dfee20d2ea01947f1 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 25 Nov 2011 22:34:12 +0100 Subject: [PATCH 093/228] typo --- Marlin/Marlin.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 6cc7d6c032..381d6aa9b4 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -928,7 +928,7 @@ inline void process_commands() 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()s ; + if(code_seen('Z')) max_z_jerk = code_value() ; } break; case 220: // M220 S- set speed factor override percentage From a6823a84e18f7738cafe309c21b55a110ea51d6d Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 25 Nov 2011 22:36:33 +0100 Subject: [PATCH 094/228] another typo --- Marlin/stepper.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index cae5b61cd5..0c3f0ee1bd 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -77,7 +77,7 @@ static bool old_y_max_endstop=false; static bool old_z_min_endstop=false; static bool old_z_max_endstop=false; -static bool bussy_error=false; +static bool busy_error=false; unsigned short OCR1A_error=12345; unsigned short OCR1A_nominal; @@ -166,11 +166,11 @@ asm volatile ( \ void checkStepperErrors() { - if(bussy_error) { + if(busy_error) { SERIAL_ERROR_START SERIAL_ERROR(OCR1A_error); SERIAL_ERRORLNPGM(" ISR overtaking itself."); - bussy_error = false; + busy_error = false; } } @@ -280,7 +280,7 @@ ISR(TIMER1_COMPA_vect) { if(busy){ OCR1A_error = OCR1A; - bussy_error = true; + busy_error = true; OCR1A = 30000; return; } // The busy-flag is used to avoid reentering this interrupt From c54a80782418a65b6bb7137850ac2129b9f4f7c5 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 25 Nov 2011 23:37:08 +0100 Subject: [PATCH 095/228] overworked ultralcd a bit --- Marlin/cardreader.h | 1 + Marlin/ultralcd.pde | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 44ebf0e2c1..18086e5768 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -35,6 +35,7 @@ public: inline int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; inline void setIndex(long index) {sdpos = index;file.seekSet(index);}; inline uint8_t percentDone(){if(!sdprinting) return 0; if(filesize) return sdpos*100/filesize; else return 0;}; + inline char* getWorkDirName(){workDir.getFilename(filename);return filename;}; public: bool saving; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index e6a16a408e..47396e4c17 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -456,7 +456,7 @@ void MainMenu::showPrepare() switch(i) { case ItemP_exit: - MENUITEM( lcdprintPGM(" Prepare") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemP_home: MENUITEM( lcdprintPGM(" Auto Home") , BLOCK;enquecommand("G28 X-105 Y-105 Z0");beepshort(); ) ; @@ -493,7 +493,7 @@ void MainMenu::showTune() switch(i) { case ItemT_exit: - MENUITEM( lcdprintPGM(" Tune") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemT_speed: { @@ -673,7 +673,7 @@ void MainMenu::showControlTemp() switch(i) { case ItemCT_exit: - MENUITEM( lcdprintPGM(" Temperature") , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Control \003") , BLOCK;status=Main_Control;beepshort(); ) ; break; case ItemCT_nozzle: { @@ -915,7 +915,7 @@ void MainMenu::showControlMotion() switch(i) { case ItemCM_exit: - MENUITEM( lcdprintPGM(" Motion") , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Control \003") , BLOCK;status=Main_Control;beepshort(); ) ; break; case ItemCM_acc: { @@ -1230,7 +1230,7 @@ void MainMenu::showControl() switch(i) { case ItemC_exit: - MENUITEM( lcdprintPGM(" Control \x7E") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemC_temp: MENUITEM( lcdprintPGM(" Temperature \x7E") , BLOCK;status=Sub_TempControl;beepshort(); ) ; @@ -1317,7 +1317,7 @@ void MainMenu::showSD() switch(i) { case 0: - MENUITEM( lcdprintPGM(" File") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; break; // case 1: // { @@ -1348,7 +1348,7 @@ void MainMenu::showSD() // } // }break; case 1: - MENUITEM( lcdprintPGM(" ..") , BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ; + MENUITEM( lcd.print(" ");card.getWorkDirName();if(card.filename[0]=='/') lcdprintPGM("\004Refresh");else {lcd.print("\005");lcd.print(card.filename);lcd.print("/..");} , BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ; break; default: @@ -1435,10 +1435,10 @@ void MainMenu::showMainMenu() switch(line) { case ItemM_watch: - MENUITEM( lcdprintPGM(" Watch") , BLOCK;status=Main_Status;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Watch \003") , BLOCK;status=Main_Status;beepshort(); ) ; break; case ItemM_prepare: - MENUITEM( if(!tune) lcdprintPGM(" Prepare \x7E");else lcdprintPGM(" Tune \x7E"); , BLOCK;status=Main_Prepare;beepshort(); ) ; + MENUITEM( if(!tune) lcdprintPGM(" Prepare \x7E");else lcdprintPGM(" Tune \x7E"); , BLOCK;status=Main_Prepare;beepshort(); ) ; break; case ItemM_control: From 191f36b4933be2686a51dd62dbe532ee90f38ab5 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 25 Nov 2011 23:59:30 +0100 Subject: [PATCH 096/228] slowdown --- Marlin/planner.cpp | 2 +- Marlin/ultralcd.pde | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 8a27a2cc25..bb2e2a672a 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -530,7 +530,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); - if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5)) feed_rate = feed_rate / ((BLOCK_BUFFER_SIZE * 0.5)/moves_queued); + if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5)) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); #endif /* diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 47396e4c17..91bb43d431 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1435,7 +1435,7 @@ void MainMenu::showMainMenu() switch(line) { case ItemM_watch: - MENUITEM( lcdprintPGM(" Watch \003") , BLOCK;status=Main_Status;beepshort(); ) ; + MENUITEM( lcdprintPGM(" Watch \003") , BLOCK;status=Main_Status;beepshort(); ) ; break; case ItemM_prepare: MENUITEM( if(!tune) lcdprintPGM(" Prepare \x7E");else lcdprintPGM(" Tune \x7E"); , BLOCK;status=Main_Prepare;beepshort(); ) ; From 74d0032e258dd66009a81f4d0e70eaee987be192 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sat, 26 Nov 2011 09:03:12 +0100 Subject: [PATCH 097/228] cooldown blocking selectable by #define. --- Marlin/Configuration.h | 5 +++++ Marlin/Marlin.pde | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f8bb40e12e..4dea777cf9 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -84,6 +84,11 @@ //#define BED_MAXTEMP 150 +// Wait for Cooldown +// This defines if the M109 call should not block if it is cooling down. +// example: From a current temp of 220, you set M109 S200. +// if CooldownNoWait is defined M109 will not wait for the cooldown to finish +#define CooldownNoWait true // PID settings: // Uncomment the following line to enable PID support. diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 381d6aa9b4..60ec2b22e5 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -517,7 +517,10 @@ inline void process_commands() 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 + while(millis() < codenum ){ manage_heater(); } @@ -579,7 +582,7 @@ inline void process_commands() switch( (int)code_value() ) { - case 17: + case 17: LCD_MESSAGEPGM("No move."); enable_x(); enable_y(); @@ -740,7 +743,7 @@ inline void process_commands() while((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0())) || (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else - while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()) ) { + while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()&&(CooldownNoWait==false)) ) { #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down From 4d6a5c29df87270b13c6ec7b5adb58c1aa29e3a8 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sat, 26 Nov 2011 11:50:23 +0100 Subject: [PATCH 098/228] disable steppers as routine in stepper.cpp --- Marlin/Marlin.pde | 8 ++------ Marlin/stepper.cpp | 10 ++++++++++ Marlin/stepper.h | 2 ++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 60ec2b22e5..d94f810c1d 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -641,6 +641,7 @@ inline void process_commands() //processed in write to file routine above //card,saving = false; break; + #endif //SDSUPPORT case 30: //M30 take time since the start of the SD print or an M109 command @@ -832,12 +833,7 @@ inline void process_commands() } else { - st_synchronize(); - LCD_MESSAGEPGM("Free move."); - disable_x(); - disable_y(); - disable_z(); - disable_e(); + finishAndDisableSteppers(); } break; case 85: // M85 diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 0c3f0ee1bd..491b6e7f2b 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -702,3 +702,13 @@ long st_get_position(char axis) CRITICAL_SECTION_END; return count_pos; } + +void finishAndDisableSteppers() +{ + st_synchronize(); + LCD_MESSAGEPGM("Released."); + disable_x(); + disable_y(); + disable_z(); + disable_e(); +} diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 97f72bf2ed..73b7efb1cd 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -46,6 +46,8 @@ void endstops_hit_on_purpose(); //avoid creation of the message, i.e. after home void checkStepperErrors(); //Print errors detected by the stepper +void finishAndDisableSteppers(); + extern block_t *current_block; // A pointer to the block currently being traced From 6d6f323535c8523341359ff3747516c86906969c Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sat, 26 Nov 2011 11:51:38 +0100 Subject: [PATCH 099/228] make an option if sd-card stop should release the steppers. --- Marlin/Configuration.h | 1 + Marlin/cardreader.h | 3 ++- Marlin/cardreader.pde | 11 +++++++++++ Marlin/ultralcd.pde | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 4dea777cf9..17a8854638 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -281,6 +281,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 //#define SDSUPPORT // Enable SD Card Support in Hardware Console +#define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? //#define ULTIPANEL #ifdef ULTIPANEL diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 18086e5768..4530e4e206 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -2,7 +2,7 @@ #define __CARDREADERH #ifdef SDSUPPORT - + #include "SdFile.h" enum LsAction {LS_SerialPrint,LS_Count,LS_GetFilename}; class CardReader @@ -22,6 +22,7 @@ public: void startFileprint(); void pauseSDPrint(); void getStatus(); + void printingHasFinished(); void getfilename(const uint8_t nr); uint16_t getnrfilenames(); diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index eec10f199f..03f3f46386 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -2,6 +2,8 @@ //#include #ifdef SDSUPPORT +#include "Configuration.h" + CardReader::CardReader() { filesize = 0; @@ -426,4 +428,13 @@ void CardReader::updir() } } + +void CardReader::printingHasFinished() +{ + sdprinting = false; + if(SD_FINISHED_STEPPERRELEASE) + { + finishAndDisableSteppers(); + } +} #endif //SDSUPPORT \ No newline at end of file diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 91bb43d431..a90a6c66dd 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1471,7 +1471,7 @@ void MainMenu::showMainMenu() #endif if((activeline==line)&&CLICKED) { - card.sdprinting = false; + card.printingHasFinished(); BLOCK; status=Main_SD; beepshort(); From a0dc66f7bfab6815c4a64a1fbf02dd82d1d75d11 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sat, 26 Nov 2011 12:04:06 +0100 Subject: [PATCH 100/228] Home retract distance configureable per axis. --- Marlin/Configuration.h | 5 +++++ Marlin/Marlin.pde | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 17a8854638..7bd94f6403 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -207,6 +207,11 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E #define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) +//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again: +#define X_HOME_RETRACT_MM 5 +#define Y_HOME_RETRACT_MM 5 +#define Z_HOME_RETRACT_MM 1 + #define AXIS_RELATIVE_MODES {false, false, false, false} #define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index d94f810c1d..d765d222b6 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -469,10 +469,10 @@ inline bool code_seen(char code) \ current_position[LETTER##_AXIS] = 0;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ - destination[LETTER##_AXIS] = -5 * LETTER##_HOME_DIR;\ + destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ prepare_move(); \ \ - destination[LETTER##_AXIS] = 10 * LETTER##_HOME_DIR;\ + destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ prepare_move(); \ \ From aad4b75b94094142ece357b1bbcc25a080bbd9ac Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 26 Nov 2011 17:33:25 +0100 Subject: [PATCH 101/228] First parts 2nd extruder --- Marlin/Configuration.h | 1 + Marlin/Marlin.pde | 122 ++++++++++++++++++++++++++--------------- Marlin/planner.cpp | 2 + Marlin/planner.h | 1 + Marlin/temperature.h | 21 +++++++ 5 files changed, 104 insertions(+), 43 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 7bd94f6403..3a1983956d 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -8,6 +8,7 @@ //#define BAUDRATE 115200 //#define BAUDRATE 230400 +#define EXTRUDERS 1 // Frequency limit // See nophead's blog for more info diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index d765d222b6..836f5aa9ab 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -174,7 +174,7 @@ static unsigned long stepper_inactive_time = 0; static unsigned long starttime=0; static unsigned long stoptime=0; - +static uint8_t tmp_extruder; //=========================================================================== //=============================ROUTINES============================= @@ -641,7 +641,6 @@ inline void process_commands() //processed in write to file routine above //card,saving = false; break; - #endif //SDSUPPORT case 30: //M30 take time since the start of the SD print or an M109 command @@ -684,19 +683,36 @@ inline void process_commands() } break; case 104: // M104 - if (code_seen('S')) setTargetHotend0(code_value()); + tmp_extruder = active_extruder; + if(code_seen('T')) { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHO("M104 Invalid extruder "); + SERIAL_ECHOLN(tmp_extruder); + 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 - //SERIAL_ECHOLN(freeMemory()); - //test watchdog: - //delay(20000); - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + tmp_extruder = active_extruder; + if(code_seen('T')) { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHO("M105 Invalid extruder "); + SERIAL_ECHOLN(tmp_extruder); + break; + } + } + #if (TEMP_0_PIN > -1) || (TEMP_2_PIN > -1) SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL( degHotend0()); + SERIAL_PROTOCOL( degHotend(tmp_extruder)); #if TEMP_1_PIN > -1 SERIAL_PROTOCOLPGM(" B:"); SERIAL_PROTOCOL(degBed()); @@ -715,41 +731,51 @@ inline void process_commands() break; case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGEPGM("Heating..."); - #ifdef AUTOTEMP - autotemp_enabled=false; - #endif - if (code_seen('S')) setTargetHotend0(code_value()); - #ifdef AUTOTEMP - if (code_seen('S')) autotemp_min=code_value(); - if (code_seen('T')) autotemp_max=code_value(); - if (code_seen('F')) - { - autotemp_factor=code_value(); - autotemp_enabled=true; - } - #endif - - setWatch(); - codenum = millis(); + tmp_extruder = active_extruder; + if(code_seen('T')) { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHO("M109 Invalid extruder "); + SERIAL_ECHOLN(tmp_extruder); + break; + } + } + LCD_MESSAGEPGM("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('G')) 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 = isHeatingHotend0(); // true if heating, false if cooling + /* 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((target_direction ? (isHeatingHotend0()) : (isCoolingHotend0())) || - (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { - #else - while ( target_direction ? (isHeatingHotend0()) : (isCoolingHotend0()&&(CooldownNoWait==false)) ) { - #endif //TEMP_RESIDENCY_TIME + #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((target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder))) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + #else + while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { + #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOLLN( degHotend0() ); + SERIAL_PROTOCOLLN( degHotend(tmp_extruder) ); codenum = millis(); } manage_heater(); @@ -757,9 +783,9 @@ inline void process_commands() #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 && !isHeatingHotend0()) || - (residencyStart == -1 && !target_direction && !isCoolingHotend0()) || - (residencyStart > -1 && labs(degHotend0() - degTargetHotend0()) > TEMP_HYSTERESIS) ) + if ((residencyStart == -1 && target_direction && !isHeatingHotend(tmp_extruder)) || + (residencyStart == -1 && !target_direction && !isCoolingHotend(tmp_extruder)) || + (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) ) { residencyStart = millis(); } @@ -943,8 +969,6 @@ inline void process_commands() #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; @@ -989,6 +1013,18 @@ inline void process_commands() } } + 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("Invalid extruder"); + } + else { + active_extruder = tmp_extruder; + } + } else { SERIAL_ECHO_START; diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index bb2e2a672a..0f9b1eb9ee 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -81,6 +81,8 @@ float max_z_jerk; float mintravelfeedrate; unsigned long axis_steps_per_sqr_second[NUM_AXIS]; +uint8_t active_extruder = 0; + // The current position of the tool in absolute steps long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode static float previous_speed[4]; // Speed of previous path line segment diff --git a/Marlin/planner.h b/Marlin/planner.h index 9aa121acae..57c59a0b0f 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -94,6 +94,7 @@ extern float max_z_jerk; extern float mintravelfeedrate; extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; +extern uint8_t active_extruder; #ifdef AUTOTEMP extern bool autotemp_enabled; diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 0f0de985f4..e832eb6236 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -62,9 +62,18 @@ extern float Kp,Ki,Kd,Kc; inline float degHotend0(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);}; inline float degHotend1(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]);}; inline float degBed() { return analog2tempBed(current_raw[TEMPSENSOR_BED]);}; +inline float degHotend(uint8_t extruder){ + if(extruder == 0) return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + if(extruder == 1) return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]); +}; inline float degTargetHotend0() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);}; inline float degTargetHotend1() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);}; +inline float degTargetHotend(uint8_t extruder){ + if(extruder == 0) return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]); + if(extruder == 1) return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]); +}; + inline float degTargetBed() { return analog2tempBed(target_raw[TEMPSENSOR_BED]);}; inline void setTargetHotend0(const float &celsius) @@ -75,14 +84,26 @@ inline void setTargetHotend0(const float &celsius) #endif //PIDTEMP }; inline void setTargetHotend1(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; +inline float setTargetHotend(const float &celcius, uint8_t extruder){ + if(extruder == 0) setTargetHotend0(celcius); + if(extruder == 1) setTargetHotend1(celcius); +}; inline void setTargetBed(const float &celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; inline bool isHeatingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; inline bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; +inline float isHeatingHotend(uint8_t extruder){ + if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]; + if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1]; +}; inline bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; inline bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];}; inline bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; +inline float isCoolingHotend(uint8_t extruder){ + if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0]; + if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1]; +}; inline bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; void disable_heater(); From f8e170a44bca32500c6c809b8a61f2721a4a13bf Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 27 Nov 2011 14:57:12 +0100 Subject: [PATCH 102/228] planner optimization by inline functions --- Marlin/planner.cpp | 23 +++++++---------------- Marlin/planner.h | 29 ++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index bb2e2a672a..2367e313a0 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -93,13 +93,17 @@ static float previous_nominal_speed; // Nominal speed of previous path line segm bool autotemp_enabled=false; #endif + +//=========================================================================== +//=================semi-private variables, used in inline functions ===== +//=========================================================================== +block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +volatile unsigned char block_buffer_head; // Index of the next block to be pushed +volatile unsigned char block_buffer_tail; // Index of the block to process now //=========================================================================== //=============================private variables ============================ //=========================================================================== -static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions -static volatile unsigned char block_buffer_head; // Index of the next block to be pushed -static volatile unsigned char block_buffer_tail; // Index of the block to process now // Used for the frequency limit static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations @@ -364,20 +368,7 @@ void plan_init() { } -void plan_discard_current_block() { - if (block_buffer_head != block_buffer_tail) { - block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); - } -} -block_t *plan_get_current_block() { - if (block_buffer_head == block_buffer_tail) { - return(NULL); - } - block_t *block = &block_buffer[block_buffer_tail]; - block->busy = true; - return(block); -} #ifdef AUTOTEMP void getHighESpeed() diff --git a/Marlin/planner.h b/Marlin/planner.h index 9aa121acae..7bae9a1c92 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -72,12 +72,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa void plan_set_position(const float &x, const float &y, const float &z, const float &e); void plan_set_e_position(const float &e); -// Called when the current block is no longer needed. Discards the block and makes the memory -// availible for new blocks. -void plan_discard_current_block(); -// Gets the current block. Returns NULL if buffer empty -block_t *plan_get_current_block(); void check_axes_activity(); uint8_t movesplanned(); //return the nr of buffered moves @@ -102,4 +97,28 @@ extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; extern float autotemp_factor; #endif + +/////semi-private stuff +#include + +extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed +extern volatile unsigned char block_buffer_tail; +// Called when the current block is no longer needed. Discards the block and makes the memory +// availible for new blocks. +inline void plan_discard_current_block() { + if (block_buffer_head != block_buffer_tail) { + block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); + } +} + +// Gets the current block. Returns NULL if buffer empty +inline block_t *plan_get_current_block() { + if (block_buffer_head == block_buffer_tail) { + return(NULL); + } + block_t *block = &block_buffer[block_buffer_tail]; + block->busy = true; + return(block); +} #endif From 26a1de1e448cd254f6d69a2a7098c290933d269e Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 27 Nov 2011 16:04:58 +0100 Subject: [PATCH 103/228] force inline --- Marlin/EEPROMwrite.h | 4 ++-- Marlin/Marlin.h | 4 +++- Marlin/cardreader.h | 48 ++++++++++++++++++++++---------------------- Marlin/planner.cpp | 8 +++++--- Marlin/planner.h | 7 +++++-- Marlin/temperature.h | 30 +++++++++++++-------------- Marlin/ultralcd.h | 6 +++--- Marlin/watchdog.h | 4 ++-- 8 files changed, 59 insertions(+), 52 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 3d559c0269..08b344af63 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -38,7 +38,7 @@ template int EEPROM_readAnything(int &ee, T& value) // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. #define EEPROM_VERSION "V04" -inline void StoreSettings() +FORCE_INLINE void StoreSettings() { #ifdef EEPROM_SETTINGS char ver[4]= "000"; @@ -71,7 +71,7 @@ inline void StoreSettings() #endif //EEPROM_SETTINGS } -inline void RetrieveSettings(bool def=false) +FORCE_INLINE void RetrieveSettings(bool def=false) { // if def=true, the default values will be used #ifdef EEPROM_SETTINGS int i=EEPROM_OFFSET; diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index acfc3c2fa6..20032a685c 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -8,6 +8,8 @@ #include #include "Configuration.h" + +#define FORCE_INLINE __attribute__((always_inline)) inline //#define SERIAL_ECHO(x) Serial << "echo: " << x; //#define SERIAL_ECHOLN(x) Serial << "echo: "<=filesize ;}; - inline int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; - inline void setIndex(long index) {sdpos = index;file.seekSet(index);}; - inline uint8_t percentDone(){if(!sdprinting) return 0; if(filesize) return sdpos*100/filesize; else return 0;}; - inline char* getWorkDirName(){workDir.getFilename(filename);return filename;}; + FORCE_INLINE bool eof() { return sdpos>=filesize ;}; + FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; + FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);}; + FORCE_INLINE uint8_t percentDone(){if(!sdprinting) return 0; if(filesize) return sdpos*100/filesize; else return 0;}; + FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;}; public: bool saving; @@ -69,31 +69,31 @@ private: class CardReader { public: - inline CardReader(){}; + FORCE_INLINE CardReader(){}; - inline static void initsd(){}; - inline static void write_command(char *buf){}; + FORCE_INLINE static void initsd(){}; + FORCE_INLINE static void write_command(char *buf){}; - inline static void checkautostart(bool x) {}; + FORCE_INLINE static void checkautostart(bool x) {}; - inline static void openFile(char* name,bool read){}; - inline static void closefile() {}; - inline static void release(){}; - inline static void startFileprint(){}; - inline static void startFilewrite(char *name){}; - inline static void pauseSDPrint(){}; - inline static void getStatus(){}; + FORCE_INLINE static void openFile(char* name,bool read){}; + FORCE_INLINE static void closefile() {}; + FORCE_INLINE static void release(){}; + FORCE_INLINE static void startFileprint(){}; + FORCE_INLINE static void startFilewrite(char *name){}; + FORCE_INLINE static void pauseSDPrint(){}; + FORCE_INLINE static void getStatus(){}; - inline static void selectFile(char* name){}; - inline static void getfilename(const uint8_t nr){}; - inline static uint8_t getnrfilenames(){return 0;}; + FORCE_INLINE static void selectFile(char* name){}; + FORCE_INLINE static void getfilename(const uint8_t nr){}; + FORCE_INLINE static uint8_t getnrfilenames(){return 0;}; - inline static void ls() {}; - inline static bool eof() {return true;}; - inline static char get() {return 0;}; - inline static void setIndex(){}; - inline uint8_t percentDone(){return 0;}; + FORCE_INLINE static void ls() {}; + FORCE_INLINE static bool eof() {return true;}; + FORCE_INLINE static char get() {return 0;}; + FORCE_INLINE static void setIndex(){}; + FORCE_INLINE uint8_t percentDone(){return 0;}; }; #endif //SDSUPPORT #endif \ No newline at end of file diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 2367e313a0..2c2ba3f77b 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -132,7 +132,8 @@ static int8_t prev_block_index(int8_t block_index) { // Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the // given acceleration: -inline float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { +FORCE_INLINE float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) +{ if (acceleration!=0) { return((target_rate*target_rate-initial_rate*initial_rate)/ (2.0*acceleration)); @@ -147,7 +148,8 @@ inline float estimate_acceleration_distance(float initial_rate, float target_rat // a total travel of distance. This can be used to compute the intersection point between acceleration and // deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) -inline float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { +FORCE_INLINE float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) +{ if (acceleration!=0) { return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ (4.0*acceleration) ); @@ -211,7 +213,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exi // Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the // acceleration within the allotted distance. -inline float max_allowable_speed(float acceleration, float target_velocity, float distance) { +FORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) { return sqrt(target_velocity*target_velocity-2*acceleration*distance); } diff --git a/Marlin/planner.h b/Marlin/planner.h index 7bae9a1c92..e17580dad7 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -25,6 +25,7 @@ #define planner_h #include "Configuration.h" +#include "Marlin.h" // This struct is used when buffering the setup for each linear movement "nominal" values are as specified in // the source g-code and may never actually be reached if acceleration management is active. @@ -106,14 +107,16 @@ extern volatile unsigned char block_buffer_head; // Index of the next extern volatile unsigned char block_buffer_tail; // Called when the current block is no longer needed. Discards the block and makes the memory // availible for new blocks. -inline void plan_discard_current_block() { +FORCE_INLINE void plan_discard_current_block() +{ if (block_buffer_head != block_buffer_tail) { block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1); } } // Gets the current block. Returns NULL if buffer empty -inline block_t *plan_get_current_block() { +FORCE_INLINE block_t *plan_get_current_block() +{ if (block_buffer_head == block_buffer_tail) { return(NULL); } diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 0f0de985f4..9057c1c90b 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -59,31 +59,31 @@ extern float Kp,Ki,Kd,Kc; //inline so that there is no performance decrease. //deg=degreeCelsius -inline float degHotend0(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);}; -inline float degHotend1(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]);}; -inline float degBed() { return analog2tempBed(current_raw[TEMPSENSOR_BED]);}; +FORCE_INLINE float degHotend0(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);}; +FORCE_INLINE float degHotend1(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]);}; +FORCE_INLINE float degBed() { return analog2tempBed(current_raw[TEMPSENSOR_BED]);}; -inline float degTargetHotend0() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);}; -inline float degTargetHotend1() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);}; -inline float degTargetBed() { return analog2tempBed(target_raw[TEMPSENSOR_BED]);}; +FORCE_INLINE float degTargetHotend0() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);}; +FORCE_INLINE float degTargetHotend1() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);}; +FORCE_INLINE float degTargetBed() { return analog2tempBed(target_raw[TEMPSENSOR_BED]);}; -inline void setTargetHotend0(const float &celsius) +FORCE_INLINE void setTargetHotend0(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius); #ifdef PIDTEMP pid_setpoint = celsius; #endif //PIDTEMP }; -inline void setTargetHotend1(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; -inline void setTargetBed(const float &celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; +FORCE_INLINE void setTargetHotend1(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; +FORCE_INLINE void setTargetBed(const float &celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; -inline bool isHeatingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; -inline bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; -inline bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; +FORCE_INLINE bool isHeatingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; +FORCE_INLINE bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; +FORCE_INLINE bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; -inline bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];}; -inline bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; -inline bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; +FORCE_INLINE bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];}; +FORCE_INLINE bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; +FORCE_INLINE bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; void disable_heater(); void setWatch(); diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 85a8df74c5..887dc04f25 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -79,7 +79,7 @@ bool tune; private: - inline void updateActiveLines(const uint8_t &maxlines,volatile int &encoderpos) + FORCE_INLINE void updateActiveLines(const uint8_t &maxlines,volatile int &encoderpos) { if(linechanging) return; // an item is changint its value, do not switch lines hence lastlineoffset=lineoffset; @@ -119,7 +119,7 @@ } } - inline void clearIfNecessary() + FORCE_INLINE void clearIfNecessary() { if(lastlineoffset!=lineoffset ||force_lcd_update) { @@ -143,7 +143,7 @@ #define LCD_STATUS #define LCD_MESSAGE(x) #define LCD_MESSAGEPGM(x) - inline void lcd_status() {}; + FORCE_INLINE void lcd_status() {}; #endif #ifndef ULTIPANEL diff --git a/Marlin/watchdog.h b/Marlin/watchdog.h index 44ee9de35d..1d41488271 100644 --- a/Marlin/watchdog.h +++ b/Marlin/watchdog.h @@ -9,8 +9,8 @@ void wd_reset(); #else - inline void wd_init() {}; - inline void wd_reset() {}; + FORCE_INLINE void wd_init() {}; + FORCE_INLINE void wd_reset() {}; #endif #endif From b128d25f27142381c3f035d1754e28c4a4bb1bf1 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 27 Nov 2011 16:45:00 +0100 Subject: [PATCH 104/228] overlooked some inlines.. --- Marlin/stepper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 491b6e7f2b..03ea11be76 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -224,7 +224,7 @@ void st_wake_up() { ENABLE_STEPPER_DRIVER_INTERRUPT(); } -inline unsigned short calc_timer(unsigned short step_rate) { +FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { unsigned short timer; if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; @@ -261,7 +261,7 @@ inline unsigned short calc_timer(unsigned short step_rate) { // Initializes the trapezoid generator from the current block. Called whenever a new // block begins. -inline void trapezoid_generator_reset() { +FORCE_INLINE void trapezoid_generator_reset() { #ifdef ADVANCE advance = current_block->initial_advance; final_advance = current_block->final_advance; From 6aecf80278c8b3e5eab716592f314554efbca0ea Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 27 Nov 2011 16:45:19 +0100 Subject: [PATCH 105/228] add autotemp support to the lcd --- Marlin/ultralcd.pde | 143 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 2 deletions(-) diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index a90a6c66dd..a4bb640b70 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -660,7 +660,12 @@ void MainMenu::showTune() // enum { - ItemCT_exit, ItemCT_nozzle, ItemCT_fan, + ItemCT_exit,ItemCT_nozzle, +#ifdef AUTOTEMP + ItemCT_autotempactive, + ItemCT_autotempmin,ItemCT_autotempmax,ItemCT_autotempfact, +#endif + ItemCT_fan, ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C }; @@ -708,7 +713,128 @@ void MainMenu::showControlTemp() } } }break; - + #ifdef AUTOTEMP + case ItemCT_autotempmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002 Min:"); + lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(autotemp_max); + } + else + { + autotemp_max=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemCT_autotempmax: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002 Max:"); + lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(autotemp_max); + } + else + { + autotemp_max=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemCT_autotempfact: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002 Fact:"); + lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(autotemp_factor*100); + } + else + { + autotemp_max=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>99) encoderpos=99; + lcd.setCursor(13,line);lcd.print(ftostr32(encoderpos/100.)); + } + } + }break; + case ItemCT_autotempactive: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Autotemp:"); + lcd.setCursor(13,line); + if(autotemp_enabled) + lcdprintPGM("On"); + else + lcdprintPGM("Off"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + autotemp_enabled=!autotemp_enabled; + BLOCK; + } + } + }break; + #endif //autotemp case ItemCT_fan: { if(force_lcd_update) @@ -1620,6 +1746,19 @@ char *ftostr31(const float &x) return conv; } +char *ftostr32(const float &x) +{ + int xx=x*100; + conv[0]=(xx>=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/100)%10+'0'; + conv[2]='.'; + conv[3]=(xx/10)%10+'0'; + conv[4]=(xx)%10+'0'; + conv[6]=0; + return conv; +} + char *itostr31(const int &xx) { conv[0]=(xx>=0)?'+':'-'; From d2f034ba84192093bcbe96eae1bd835e407bed79 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 27 Nov 2011 16:53:11 +0100 Subject: [PATCH 106/228] lcd message from gcode, m117 --- Marlin/Marlin.pde | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index d765d222b6..9cf499809c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -94,6 +94,7 @@ // 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. @@ -850,6 +851,9 @@ inline void process_commands() case 115: // M115 SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); break; + case 117: // M117 display message + LCD_MESSAGE(cmdbuffer[bufindr]+5); + break; case 114: // M114 SERIAL_PROTOCOLPGM("X:"); SERIAL_PROTOCOL(current_position[X_AXIS]); From 2d9a7156555e0cdd969b44cc7c4d3c8a18875cfe Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 27 Nov 2011 17:27:17 +0100 Subject: [PATCH 107/228] first naive attempt to have a offset in the homeing procedure. Does not enable to move into regions not allowed by endstops. --- Marlin/Marlin.h | 1 + Marlin/Marlin.pde | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 20032a685c..69a0cf3e20 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -112,5 +112,6 @@ void prepare_arc_move(char isclockwise); extern float homing_feedrate[]; extern bool axis_relative_modes[]; extern float current_position[NUM_AXIS] ; +extern float add_homeing[3]; #endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 9cf499809c..6a07cf9891 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -104,6 +104,7 @@ // 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 +// M206 - set additional homeing offset // M220 - set speed factor override percentage S:factor in percent // M301 - Set PID parameters P I and D // M400 - Finish all moves @@ -131,7 +132,7 @@ volatile int feedmultiply=100; //100->1 200->2 int saved_feedmultiply; volatile bool feedmultiplychanged=false; float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; - +float add_homeing[3]={0,0,0}; //=========================================================================== //=============================private variables============================= @@ -536,19 +537,23 @@ inline void process_commands() } feedrate = 0.0; home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); - + if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { HOMEAXIS(X); + current_position[0]=code_value()+add_homeing[0]; } if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { HOMEAXIS(Y); + current_position[1]=code_value()+add_homeing[1]; } if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { HOMEAXIS(Z); + current_position[2]=code_value()+add_homeing[2]; } + feedrate = saved_feedrate; feedmultiply = saved_feedmultiply; previous_millis_cmd = millis(); @@ -565,7 +570,7 @@ inline void process_commands() st_synchronize(); for(int8_t i=0; i < NUM_AXIS; i++) { if(code_seen(axis_codes[i])) { - current_position[i] = code_value(); + current_position[i] = code_value()+add_homeing[i]; if(i == E_AXIS) { plan_set_e_position(current_position[E_AXIS]); } @@ -934,6 +939,12 @@ inline void process_commands() if(code_seen('Z')) max_z_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; case 220: // M220 S- set speed factor override percentage { if(code_seen('S')) From f75f426dfae5190d3e637b247030d3a244968c2a Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 27 Nov 2011 21:12:55 +0100 Subject: [PATCH 108/228] Removed interrupt nesting in the stepper ISR. Add serial checkRx in stepper ISR. Copied HardwareSerial to MarlinSerial (Needed for checkRx). --- Marlin/Configuration.h | 2 +- Marlin/EEPROMwrite.h | 1 + Marlin/Marlin.h | 10 +- Marlin/Marlin.pde | 25 +- Marlin/MarlinSerial.cpp | 213 ++++++ Marlin/MarlinSerial.h | 66 ++ Marlin/Sd2Card.cpp | 1283 +++++++++++++++++++------------------ Marlin/SdBaseFile.cpp | 10 +- Marlin/SdBaseFile.h | 2 + Marlin/SdFatUtil.cpp | 4 +- Marlin/SdFatUtil.h | 92 +-- Marlin/motion_control.cpp | 6 +- Marlin/motion_control.h | 2 +- Marlin/planner.cpp | 6 +- Marlin/planner.h | 2 +- Marlin/stepper.cpp | 37 +- 16 files changed, 1007 insertions(+), 754 deletions(-) create mode 100644 Marlin/MarlinSerial.cpp create mode 100644 Marlin/MarlinSerial.h diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 3a1983956d..558044e280 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -232,7 +232,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. #define DEFAULT_MINSEGMENTTIME 20000 // Obsolete delete this -#define DEFAULT_XYJERK 30.0 // (mm/sec) +#define DEFAULT_XYJERK 20.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 3d559c0269..c298c97350 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -4,6 +4,7 @@ #include "Marlin.h" #include "planner.h" #include "temperature.h" + #include template int EEPROM_writeAnything(int &ee, const T& value) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index acfc3c2fa6..57f403dffd 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -3,10 +3,12 @@ // Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. // Licence: GPL +#define HardwareSerial_h // trick to disable the standard HWserial #include #include "fastio.h" #include #include "Configuration.h" +#include "MarlinSerial.h" //#define SERIAL_ECHO(x) Serial << "echo: " << x; //#define SERIAL_ECHOLN(x) Serial << "echo: "< 0 && buflen < BUFSIZE) { - serial_char = Serial.read(); + while( MSerial.available() > 0 && buflen < BUFSIZE) { + serial_char = MSerial.read(); if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) { if(!serial_count) return; //if empty line @@ -1039,7 +1032,7 @@ inline void process_commands() void FlushSerialRequestResend() { //char cmdbuffer[bufindr][100]="Resend:"; - Serial.flush(); + MSerial.flush(); SERIAL_PROTOCOLPGM("Resend:"); SERIAL_PROTOCOLLN(gcode_LastN + 1); ClearToSend(); @@ -1088,7 +1081,7 @@ void prepare_move() if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; } - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0); + 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]; } @@ -1098,7 +1091,7 @@ 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); + 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 @@ -1108,10 +1101,6 @@ void prepare_arc_move(char isclockwise) { } } - - - - void manage_inactivity(byte debug) { if( (millis()-previous_millis_cmd) > max_inactive_time ) diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp new file mode 100644 index 0000000000..fade8b293f --- /dev/null +++ b/Marlin/MarlinSerial.cpp @@ -0,0 +1,213 @@ +/* + HardwareSerial.cpp - Hardware serial library for Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 23 November 2006 by David A. Mellis + Modified 28 September 2010 by Mark Sproul +*/ + +#include +#include +#include +#include +#include "wiring.h" +#include "wiring_private.h" + +// this next line disables the entire HardwareSerial.cpp, +// this is so I can support Attiny series and any other chip without a uart +#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) + +#include "MarlinSerial.h" + +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which rx_buffer_head is the index of the +// location to which to write the next incoming character and rx_buffer_tail +// is the index of the location from which to read. +#define RX_BUFFER_SIZE 128 + +struct ring_buffer +{ + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; +}; + +#if defined(UBRRH) || defined(UBRR0H) + ring_buffer rx_buffer = { { 0 }, 0, 0 }; +#endif + + +inline void store_char(unsigned char c, ring_buffer *rx_buffer) +{ + int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != rx_buffer->tail) { + rx_buffer->buffer[rx_buffer->head] = c; + rx_buffer->head = i; + } +} + + +//#elif defined(SIG_USART_RECV) +#if defined(USART0_RX_vect) + // fixed by Mark Sproul this is on the 644/644p + //SIGNAL(SIG_USART_RECV) + SIGNAL(USART0_RX_vect) + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; // atmega8, atmega32 + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } +#endif + +// Constructors //////////////////////////////////////////////////////////////// + +MarlinSerial::MarlinSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) +{ + _rx_buffer = rx_buffer; + _ubrrh = ubrrh; + _ubrrl = ubrrl; + _ucsra = ucsra; + _ucsrb = ucsrb; + _udr = udr; + _rxen = rxen; + _txen = txen; + _rxcie = rxcie; + _udre = udre; + _u2x = u2x; +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void MarlinSerial::begin(long baud) +{ + uint16_t baud_setting; + bool use_u2x = true; + +#if F_CPU == 16000000UL + // hardcoded exception for compatibility with the bootloader shipped + // with the Duemilanove and previous boards and the firmware on the 8U2 + // on the Uno and Mega 2560. + if (baud == 57600) { + use_u2x = false; + } +#endif + + if (use_u2x) { + *_ucsra = 1 << _u2x; + baud_setting = (F_CPU / 4 / baud - 1) / 2; + } else { + *_ucsra = 0; + baud_setting = (F_CPU / 8 / baud - 1) / 2; + } + + // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) + *_ubrrh = baud_setting >> 8; + *_ubrrl = baud_setting; + + sbi(*_ucsrb, _rxen); + sbi(*_ucsrb, _txen); + sbi(*_ucsrb, _rxcie); +} + +void MarlinSerial::end() +{ + cbi(*_ucsrb, _rxen); + cbi(*_ucsrb, _txen); + cbi(*_ucsrb, _rxcie); +} + +int MarlinSerial::available(void) +{ + return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; +} + +int MarlinSerial::peek(void) +{ + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + return _rx_buffer->buffer[_rx_buffer->tail]; + } +} + +int MarlinSerial::read(void) +{ + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer->head == _rx_buffer->tail) { + return -1; + } else { + unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; + _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + return c; + } +} + +void MarlinSerial::flush() +{ + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // don't reverse this or there may be problems if the RX interrupt + // occurs after reading the value of rx_buffer_head but before writing + // the value to rx_buffer_tail; the previous value of rx_buffer_head + // may be written to rx_buffer_tail, making it appear as if the buffer + // were full, not empty. + _rx_buffer->head = _rx_buffer->tail; +} + +void MarlinSerial::write(uint8_t c) +{ + while (!((*_ucsra) & (1 << _udre))) + ; + + *_udr = c; +} + +void MarlinSerial::checkRx() +{ + if((UCSR0A & (1< + +#include "Stream.h" + +struct ring_buffer; + +class MarlinSerial : public Stream +{ + private: + ring_buffer *_rx_buffer; + volatile uint8_t *_ubrrh; + volatile uint8_t *_ubrrl; + volatile uint8_t *_ucsra; + volatile uint8_t *_ucsrb; + volatile uint8_t *_udr; + uint8_t _rxen; + uint8_t _txen; + uint8_t _rxcie; + uint8_t _udre; + uint8_t _u2x; + public: + MarlinSerial(ring_buffer *rx_buffer, + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *udr, + uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); + void begin(long); + void end(); + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual void write(uint8_t); + virtual void checkRx(void); + using Print::write; // pull in write(str) and write(buf, size) from Print +}; + +#if defined(UBRRH) || defined(UBRR0H) + extern MarlinSerial MSerial; +#endif + +#endif diff --git a/Marlin/Sd2Card.cpp b/Marlin/Sd2Card.cpp index ab060c121e..4ca641ef9b 100644 --- a/Marlin/Sd2Card.cpp +++ b/Marlin/Sd2Card.cpp @@ -1,642 +1,643 @@ -/* Arduino Sd2Card Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino Sd2Card Library - * - * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see - * . - */ -#if ARDUINO < 100 -#include -#else // ARDUINO -#include -#endif // ARDUINO -#include "Sd2Card.h" -//------------------------------------------------------------------------------ -#ifndef SOFTWARE_SPI -// functions for hardware SPI -//------------------------------------------------------------------------------ -// make sure SPCR rate is in expected bits -#if (SPR0 != 0 || SPR1 != 1) -#error unexpected SPCR bits -#endif -/** - * Initialize hardware SPI - * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6] - */ -static void spiInit(uint8_t spiRate) { - // See avr processor documentation - SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1); - SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X; -} -//------------------------------------------------------------------------------ -/** SPI receive a byte */ -static uint8_t spiRec() { - SPDR = 0XFF; - while (!(SPSR & (1 << SPIF))); - return SPDR; -} -//------------------------------------------------------------------------------ -/** SPI read data - only one call so force inline */ -static inline __attribute__((always_inline)) - void spiRead(uint8_t* buf, uint16_t nbyte) { - if (nbyte-- == 0) return; - SPDR = 0XFF; - for (uint16_t i = 0; i < nbyte; i++) { - while (!(SPSR & (1 << SPIF))); - buf[i] = SPDR; - SPDR = 0XFF; - } - while (!(SPSR & (1 << SPIF))); - buf[nbyte] = SPDR; -} -//------------------------------------------------------------------------------ -/** SPI send a byte */ -static void spiSend(uint8_t b) { - SPDR = b; - while (!(SPSR & (1 << SPIF))); -} -//------------------------------------------------------------------------------ -/** SPI send block - only one call so force inline */ -static inline __attribute__((always_inline)) - void spiSendBlock(uint8_t token, const uint8_t* buf) { - SPDR = token; - for (uint16_t i = 0; i < 512; i += 2) { - while (!(SPSR & (1 << SPIF))); - SPDR = buf[i]; - while (!(SPSR & (1 << SPIF))); - SPDR = buf[i + 1]; - } - while (!(SPSR & (1 << SPIF))); -} -//------------------------------------------------------------------------------ -#else // SOFTWARE_SPI -//------------------------------------------------------------------------------ -/** nop to tune soft SPI timing */ -#define nop asm volatile ("nop\n\t") -//------------------------------------------------------------------------------ -/** Soft SPI receive byte */ -static uint8_t spiRec() { - uint8_t data = 0; - // no interrupts during byte receive - about 8 us - cli(); - // output pin high - like sending 0XFF - fastDigitalWrite(SPI_MOSI_PIN, HIGH); - - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, HIGH); - - // adjust so SCK is nice - nop; - nop; - - data <<= 1; - - if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; - - fastDigitalWrite(SPI_SCK_PIN, LOW); - } - // enable interrupts - sei(); - return data; -} -//------------------------------------------------------------------------------ -/** Soft SPI read data */ -static void spiRead(uint8_t* buf, uint16_t nbyte) { - for (uint16_t i = 0; i < nbyte; i++) { - buf[i] = spiRec(); - } -} -//------------------------------------------------------------------------------ -/** Soft SPI send byte */ -static void spiSend(uint8_t data) { - // no interrupts during byte send - about 8 us - cli(); - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, LOW); - - fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); - - data <<= 1; - - fastDigitalWrite(SPI_SCK_PIN, HIGH); - } - // hold SCK high for a few ns - nop; - nop; - nop; - nop; - - fastDigitalWrite(SPI_SCK_PIN, LOW); - // enable interrupts - sei(); -} -//------------------------------------------------------------------------------ -/** Soft SPI send block */ - void spiSendBlock(uint8_t token, const uint8_t* buf) { - spiSend(token); - for (uint16_t i = 0; i < 512; i++) { - spiSend(buf[i]); - } -} -#endif // SOFTWARE_SPI -//------------------------------------------------------------------------------ -// send command and return error code. Return zero for OK -uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { - // select card - chipSelectLow(); - - // wait up to 300 ms if busy - waitNotBusy(300); - - // send command - spiSend(cmd | 0x40); - - // send argument - for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); - - // send CRC - uint8_t crc = 0XFF; - if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 - if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA - spiSend(crc); - - // skip stuff byte for stop read - if (cmd == CMD12) spiRec(); - - // wait for response - for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); - return status_; -} -//------------------------------------------------------------------------------ -/** - * Determine the size of an SD flash memory card. - * - * \return The number of 512 byte data blocks in the card - * or zero if an error occurs. - */ -uint32_t Sd2Card::cardSize() { - csd_t csd; - if (!readCSD(&csd)) return 0; - if (csd.v1.csd_ver == 0) { - uint8_t read_bl_len = csd.v1.read_bl_len; - uint16_t c_size = (csd.v1.c_size_high << 10) - | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; - uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) - | csd.v1.c_size_mult_low; - return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); - } else if (csd.v2.csd_ver == 1) { - uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) - | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; - return (c_size + 1) << 10; - } else { - error(SD_CARD_ERROR_BAD_CSD); - return 0; - } -} -//------------------------------------------------------------------------------ -void Sd2Card::chipSelectHigh() { - digitalWrite(chipSelectPin_, HIGH); -} -//------------------------------------------------------------------------------ -void Sd2Card::chipSelectLow() { -#ifndef SOFTWARE_SPI - spiInit(spiRate_); -#endif // SOFTWARE_SPI - digitalWrite(chipSelectPin_, LOW); -} -//------------------------------------------------------------------------------ -/** Erase a range of blocks. - * - * \param[in] firstBlock The address of the first block in the range. - * \param[in] lastBlock The address of the last block in the range. - * - * \note This function requests the SD card to do a flash erase for a - * range of blocks. The data on the card after an erase operation is - * either 0 or 1, depends on the card vendor. The card must support - * single block erase. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { - csd_t csd; - if (!readCSD(&csd)) goto fail; - // check for single block erase - if (!csd.v1.erase_blk_en) { - // erase size mask - uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; - if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { - // error card can't erase specified area - error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); - goto fail; - } - } - if (type_ != SD_CARD_TYPE_SDHC) { - firstBlock <<= 9; - lastBlock <<= 9; - } - if (cardCommand(CMD32, firstBlock) - || cardCommand(CMD33, lastBlock) - || cardCommand(CMD38, 0)) { - error(SD_CARD_ERROR_ERASE); - goto fail; - } - if (!waitNotBusy(SD_ERASE_TIMEOUT)) { - error(SD_CARD_ERROR_ERASE_TIMEOUT); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Determine if card supports single block erase. - * - * \return The value one, true, is returned if single block erase is supported. - * The value zero, false, is returned if single block erase is not supported. - */ -bool Sd2Card::eraseSingleBlockEnable() { - csd_t csd; - return readCSD(&csd) ? csd.v1.erase_blk_en : false; -} -//------------------------------------------------------------------------------ -/** - * Initialize an SD flash memory card. - * - * \param[in] sckRateID SPI clock rate selector. See setSckRate(). - * \param[in] chipSelectPin SD chip select pin number. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. The reason for failure - * can be determined by calling errorCode() and errorData(). - */ -bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { - errorCode_ = type_ = 0; - chipSelectPin_ = chipSelectPin; - // 16-bit init start time allows over a minute - uint16_t t0 = (uint16_t)millis(); - uint32_t arg; - - // set pin modes - pinMode(chipSelectPin_, OUTPUT); - chipSelectHigh(); - pinMode(SPI_MISO_PIN, INPUT); - pinMode(SPI_MOSI_PIN, OUTPUT); - pinMode(SPI_SCK_PIN, OUTPUT); - -#ifndef SOFTWARE_SPI - // SS must be in output mode even it is not chip select - pinMode(SS_PIN, OUTPUT); - // set SS high - may be chip select for another SPI device -#if SET_SPI_SS_HIGH - digitalWrite(SS_PIN, HIGH); -#endif // SET_SPI_SS_HIGH - // set SCK rate for initialization commands - spiRate_ = SPI_SD_INIT_RATE; - spiInit(spiRate_); -#endif // SOFTWARE_SPI - - // must supply min of 74 clock cycles with CS high. - for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); - - // command to go idle in SPI mode - while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_CMD0); - goto fail; - } - } - // check SD version - if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { - type(SD_CARD_TYPE_SD1); - } else { - // only need last byte of r7 response - for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); - if (status_ != 0XAA) { - error(SD_CARD_ERROR_CMD8); - goto fail; - } - type(SD_CARD_TYPE_SD2); - } - // initialize card and send host supports SDHC if SD2 - arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; - - while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { - // check for timeout - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_ACMD41); - goto fail; - } - } - // if SD2 read OCR register to check for SDHC card - if (type() == SD_CARD_TYPE_SD2) { - if (cardCommand(CMD58, 0)) { - error(SD_CARD_ERROR_CMD58); - goto fail; - } - if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); - // discard rest of ocr - contains allowed voltage range - for (uint8_t i = 0; i < 3; i++) spiRec(); - } - chipSelectHigh(); - -#ifndef SOFTWARE_SPI - return setSckRate(sckRateID); -#else // SOFTWARE_SPI - return true; -#endif // SOFTWARE_SPI - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - * Read a 512 byte block from an SD card. - * - * \param[in] blockNumber Logical block to be read. - * \param[out] dst Pointer to the location that will receive the data. - - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) { - // use address if not SDHC card - if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD17, blockNumber)) { - error(SD_CARD_ERROR_CMD17); - goto fail; - } - return readData(dst, 512); - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Read one data block in a multiple block read sequence - * - * \param[in] dst Pointer to the location for the data to be read. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readData(uint8_t *dst) { - chipSelectLow(); - return readData(dst, 512); -} -//------------------------------------------------------------------------------ -bool Sd2Card::readData(uint8_t* dst, uint16_t count) { - // wait for start block token - uint16_t t0 = millis(); - while ((status_ = spiRec()) == 0XFF) { - if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) { - error(SD_CARD_ERROR_READ_TIMEOUT); - goto fail; - } - } - if (status_ != DATA_START_BLOCK) { - error(SD_CARD_ERROR_READ); - goto fail; - } - // transfer data - spiRead(dst, count); - - // discard CRC - spiRec(); - spiRec(); - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** read CID or CSR register */ -bool Sd2Card::readRegister(uint8_t cmd, void* buf) { - uint8_t* dst = reinterpret_cast(buf); - if (cardCommand(cmd, 0)) { - error(SD_CARD_ERROR_READ_REG); - goto fail; - } - return readData(dst, 16); - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Start a read multiple blocks sequence. - * - * \param[in] blockNumber Address of first block in sequence. - * - * \note This function is used with readData() and readStop() for optimized - * multiple block reads. SPI chipSelect must be low for the entire sequence. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readStart(uint32_t blockNumber) { - if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD18, blockNumber)) { - error(SD_CARD_ERROR_CMD18); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** End a read multiple blocks sequence. - * -* \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readStop() { - chipSelectLow(); - if (cardCommand(CMD12, 0)) { - error(SD_CARD_ERROR_CMD12); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - * Set the SPI clock rate. - * - * \param[in] sckRateID A value in the range [0, 6]. - * - * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum - * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 - * for \a scsRateID = 6. - * - * \return The value one, true, is returned for success and the value zero, - * false, is returned for an invalid value of \a sckRateID. - */ -bool Sd2Card::setSckRate(uint8_t sckRateID) { - if (sckRateID > 6) { - error(SD_CARD_ERROR_SCK_RATE); - return false; - } - spiRate_ = sckRateID; - return true; -} -//------------------------------------------------------------------------------ -// wait for card to go not busy -bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) { - uint16_t t0 = millis(); - while (spiRec() != 0XFF) { - if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail; - } - return true; - - fail: - return false; -} -//------------------------------------------------------------------------------ -/** - * Writes a 512 byte block to an SD card. - * - * \param[in] blockNumber Logical block to be written. - * \param[in] src Pointer to the location of the data to be written. - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD24, blockNumber)) { - error(SD_CARD_ERROR_CMD24); - goto fail; - } - if (!writeData(DATA_START_BLOCK, src)) goto fail; - - // wait for flash programming to complete - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_TIMEOUT); - goto fail; - } - // response is r2 so get and check two bytes for nonzero - if (cardCommand(CMD13, 0) || spiRec()) { - error(SD_CARD_ERROR_WRITE_PROGRAMMING); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Write one data block in a multiple block write sequence - * \param[in] src Pointer to the location of the data to be written. - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeData(const uint8_t* src) { - chipSelectLow(); - // wait for previous write to finish - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail; - chipSelectHigh(); - return true; - - fail: - error(SD_CARD_ERROR_WRITE_MULTIPLE); - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -// send one block of data for write block or write multiple blocks -bool Sd2Card::writeData(uint8_t token, const uint8_t* src) { - spiSendBlock(token, src); - - spiSend(0xff); // dummy crc - spiSend(0xff); // dummy crc - - status_ = spiRec(); - if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { - error(SD_CARD_ERROR_WRITE); - goto fail; - } - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Start a write multiple blocks sequence. - * - * \param[in] blockNumber Address of first block in sequence. - * \param[in] eraseCount The number of blocks to be pre-erased. - * - * \note This function is used with writeData() and writeStop() - * for optimized multiple block writes. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { - // send pre-erase count - if (cardAcmd(ACMD23, eraseCount)) { - error(SD_CARD_ERROR_ACMD23); - goto fail; - } - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD25, blockNumber)) { - error(SD_CARD_ERROR_CMD25); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** End a write multiple blocks sequence. - * -* \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeStop() { - chipSelectLow(); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - spiSend(STOP_TRAN_TOKEN); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - chipSelectHigh(); - return true; - - fail: - error(SD_CARD_ERROR_STOP_TRAN); - chipSelectHigh(); - return false; +/* Arduino Sd2Card Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino Sd2Card Library + * + * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see + * . + */ +#if ARDUINO < 100 +#define HardwareSerial_h // trick to disable the standard HWserial +#include +#else // ARDUINO +#include +#endif // ARDUINO +#include "Sd2Card.h" +//------------------------------------------------------------------------------ +#ifndef SOFTWARE_SPI +// functions for hardware SPI +//------------------------------------------------------------------------------ +// make sure SPCR rate is in expected bits +#if (SPR0 != 0 || SPR1 != 1) +#error unexpected SPCR bits +#endif +/** + * Initialize hardware SPI + * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6] + */ +static void spiInit(uint8_t spiRate) { + // See avr processor documentation + SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1); + SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X; +} +//------------------------------------------------------------------------------ +/** SPI receive a byte */ +static uint8_t spiRec() { + SPDR = 0XFF; + while (!(SPSR & (1 << SPIF))); + return SPDR; +} +//------------------------------------------------------------------------------ +/** SPI read data - only one call so force inline */ +static inline __attribute__((always_inline)) + void spiRead(uint8_t* buf, uint16_t nbyte) { + if (nbyte-- == 0) return; + SPDR = 0XFF; + for (uint16_t i = 0; i < nbyte; i++) { + while (!(SPSR & (1 << SPIF))); + buf[i] = SPDR; + SPDR = 0XFF; + } + while (!(SPSR & (1 << SPIF))); + buf[nbyte] = SPDR; +} +//------------------------------------------------------------------------------ +/** SPI send a byte */ +static void spiSend(uint8_t b) { + SPDR = b; + while (!(SPSR & (1 << SPIF))); +} +//------------------------------------------------------------------------------ +/** SPI send block - only one call so force inline */ +static inline __attribute__((always_inline)) + void spiSendBlock(uint8_t token, const uint8_t* buf) { + SPDR = token; + for (uint16_t i = 0; i < 512; i += 2) { + while (!(SPSR & (1 << SPIF))); + SPDR = buf[i]; + while (!(SPSR & (1 << SPIF))); + SPDR = buf[i + 1]; + } + while (!(SPSR & (1 << SPIF))); +} +//------------------------------------------------------------------------------ +#else // SOFTWARE_SPI +//------------------------------------------------------------------------------ +/** nop to tune soft SPI timing */ +#define nop asm volatile ("nop\n\t") +//------------------------------------------------------------------------------ +/** Soft SPI receive byte */ +static uint8_t spiRec() { + uint8_t data = 0; + // no interrupts during byte receive - about 8 us + cli(); + // output pin high - like sending 0XFF + fastDigitalWrite(SPI_MOSI_PIN, HIGH); + + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, HIGH); + + // adjust so SCK is nice + nop; + nop; + + data <<= 1; + + if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; + + fastDigitalWrite(SPI_SCK_PIN, LOW); + } + // enable interrupts + sei(); + return data; +} +//------------------------------------------------------------------------------ +/** Soft SPI read data */ +static void spiRead(uint8_t* buf, uint16_t nbyte) { + for (uint16_t i = 0; i < nbyte; i++) { + buf[i] = spiRec(); + } +} +//------------------------------------------------------------------------------ +/** Soft SPI send byte */ +static void spiSend(uint8_t data) { + // no interrupts during byte send - about 8 us + cli(); + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, LOW); + + fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); + + data <<= 1; + + fastDigitalWrite(SPI_SCK_PIN, HIGH); + } + // hold SCK high for a few ns + nop; + nop; + nop; + nop; + + fastDigitalWrite(SPI_SCK_PIN, LOW); + // enable interrupts + sei(); +} +//------------------------------------------------------------------------------ +/** Soft SPI send block */ + void spiSendBlock(uint8_t token, const uint8_t* buf) { + spiSend(token); + for (uint16_t i = 0; i < 512; i++) { + spiSend(buf[i]); + } +} +#endif // SOFTWARE_SPI +//------------------------------------------------------------------------------ +// send command and return error code. Return zero for OK +uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { + // select card + chipSelectLow(); + + // wait up to 300 ms if busy + waitNotBusy(300); + + // send command + spiSend(cmd | 0x40); + + // send argument + for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); + + // send CRC + uint8_t crc = 0XFF; + if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 + if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA + spiSend(crc); + + // skip stuff byte for stop read + if (cmd == CMD12) spiRec(); + + // wait for response + for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); + return status_; +} +//------------------------------------------------------------------------------ +/** + * Determine the size of an SD flash memory card. + * + * \return The number of 512 byte data blocks in the card + * or zero if an error occurs. + */ +uint32_t Sd2Card::cardSize() { + csd_t csd; + if (!readCSD(&csd)) return 0; + if (csd.v1.csd_ver == 0) { + uint8_t read_bl_len = csd.v1.read_bl_len; + uint16_t c_size = (csd.v1.c_size_high << 10) + | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; + uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) + | csd.v1.c_size_mult_low; + return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); + } else if (csd.v2.csd_ver == 1) { + uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) + | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; + return (c_size + 1) << 10; + } else { + error(SD_CARD_ERROR_BAD_CSD); + return 0; + } +} +//------------------------------------------------------------------------------ +void Sd2Card::chipSelectHigh() { + digitalWrite(chipSelectPin_, HIGH); +} +//------------------------------------------------------------------------------ +void Sd2Card::chipSelectLow() { +#ifndef SOFTWARE_SPI + spiInit(spiRate_); +#endif // SOFTWARE_SPI + digitalWrite(chipSelectPin_, LOW); +} +//------------------------------------------------------------------------------ +/** Erase a range of blocks. + * + * \param[in] firstBlock The address of the first block in the range. + * \param[in] lastBlock The address of the last block in the range. + * + * \note This function requests the SD card to do a flash erase for a + * range of blocks. The data on the card after an erase operation is + * either 0 or 1, depends on the card vendor. The card must support + * single block erase. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { + csd_t csd; + if (!readCSD(&csd)) goto fail; + // check for single block erase + if (!csd.v1.erase_blk_en) { + // erase size mask + uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; + if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { + // error card can't erase specified area + error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); + goto fail; + } + } + if (type_ != SD_CARD_TYPE_SDHC) { + firstBlock <<= 9; + lastBlock <<= 9; + } + if (cardCommand(CMD32, firstBlock) + || cardCommand(CMD33, lastBlock) + || cardCommand(CMD38, 0)) { + error(SD_CARD_ERROR_ERASE); + goto fail; + } + if (!waitNotBusy(SD_ERASE_TIMEOUT)) { + error(SD_CARD_ERROR_ERASE_TIMEOUT); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Determine if card supports single block erase. + * + * \return The value one, true, is returned if single block erase is supported. + * The value zero, false, is returned if single block erase is not supported. + */ +bool Sd2Card::eraseSingleBlockEnable() { + csd_t csd; + return readCSD(&csd) ? csd.v1.erase_blk_en : false; +} +//------------------------------------------------------------------------------ +/** + * Initialize an SD flash memory card. + * + * \param[in] sckRateID SPI clock rate selector. See setSckRate(). + * \param[in] chipSelectPin SD chip select pin number. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. The reason for failure + * can be determined by calling errorCode() and errorData(). + */ +bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { + errorCode_ = type_ = 0; + chipSelectPin_ = chipSelectPin; + // 16-bit init start time allows over a minute + uint16_t t0 = (uint16_t)millis(); + uint32_t arg; + + // set pin modes + pinMode(chipSelectPin_, OUTPUT); + chipSelectHigh(); + pinMode(SPI_MISO_PIN, INPUT); + pinMode(SPI_MOSI_PIN, OUTPUT); + pinMode(SPI_SCK_PIN, OUTPUT); + +#ifndef SOFTWARE_SPI + // SS must be in output mode even it is not chip select + pinMode(SS_PIN, OUTPUT); + // set SS high - may be chip select for another SPI device +#if SET_SPI_SS_HIGH + digitalWrite(SS_PIN, HIGH); +#endif // SET_SPI_SS_HIGH + // set SCK rate for initialization commands + spiRate_ = SPI_SD_INIT_RATE; + spiInit(spiRate_); +#endif // SOFTWARE_SPI + + // must supply min of 74 clock cycles with CS high. + for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); + + // command to go idle in SPI mode + while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { + if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_CMD0); + goto fail; + } + } + // check SD version + if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { + type(SD_CARD_TYPE_SD1); + } else { + // only need last byte of r7 response + for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); + if (status_ != 0XAA) { + error(SD_CARD_ERROR_CMD8); + goto fail; + } + type(SD_CARD_TYPE_SD2); + } + // initialize card and send host supports SDHC if SD2 + arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; + + while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { + // check for timeout + if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_ACMD41); + goto fail; + } + } + // if SD2 read OCR register to check for SDHC card + if (type() == SD_CARD_TYPE_SD2) { + if (cardCommand(CMD58, 0)) { + error(SD_CARD_ERROR_CMD58); + goto fail; + } + if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); + // discard rest of ocr - contains allowed voltage range + for (uint8_t i = 0; i < 3; i++) spiRec(); + } + chipSelectHigh(); + +#ifndef SOFTWARE_SPI + return setSckRate(sckRateID); +#else // SOFTWARE_SPI + return true; +#endif // SOFTWARE_SPI + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + * Read a 512 byte block from an SD card. + * + * \param[in] blockNumber Logical block to be read. + * \param[out] dst Pointer to the location that will receive the data. + + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) { + // use address if not SDHC card + if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD17, blockNumber)) { + error(SD_CARD_ERROR_CMD17); + goto fail; + } + return readData(dst, 512); + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Read one data block in a multiple block read sequence + * + * \param[in] dst Pointer to the location for the data to be read. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readData(uint8_t *dst) { + chipSelectLow(); + return readData(dst, 512); +} +//------------------------------------------------------------------------------ +bool Sd2Card::readData(uint8_t* dst, uint16_t count) { + // wait for start block token + uint16_t t0 = millis(); + while ((status_ = spiRec()) == 0XFF) { + if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) { + error(SD_CARD_ERROR_READ_TIMEOUT); + goto fail; + } + } + if (status_ != DATA_START_BLOCK) { + error(SD_CARD_ERROR_READ); + goto fail; + } + // transfer data + spiRead(dst, count); + + // discard CRC + spiRec(); + spiRec(); + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** read CID or CSR register */ +bool Sd2Card::readRegister(uint8_t cmd, void* buf) { + uint8_t* dst = reinterpret_cast(buf); + if (cardCommand(cmd, 0)) { + error(SD_CARD_ERROR_READ_REG); + goto fail; + } + return readData(dst, 16); + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Start a read multiple blocks sequence. + * + * \param[in] blockNumber Address of first block in sequence. + * + * \note This function is used with readData() and readStop() for optimized + * multiple block reads. SPI chipSelect must be low for the entire sequence. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readStart(uint32_t blockNumber) { + if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD18, blockNumber)) { + error(SD_CARD_ERROR_CMD18); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** End a read multiple blocks sequence. + * +* \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readStop() { + chipSelectLow(); + if (cardCommand(CMD12, 0)) { + error(SD_CARD_ERROR_CMD12); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + * Set the SPI clock rate. + * + * \param[in] sckRateID A value in the range [0, 6]. + * + * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum + * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 + * for \a scsRateID = 6. + * + * \return The value one, true, is returned for success and the value zero, + * false, is returned for an invalid value of \a sckRateID. + */ +bool Sd2Card::setSckRate(uint8_t sckRateID) { + if (sckRateID > 6) { + error(SD_CARD_ERROR_SCK_RATE); + return false; + } + spiRate_ = sckRateID; + return true; +} +//------------------------------------------------------------------------------ +// wait for card to go not busy +bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) { + uint16_t t0 = millis(); + while (spiRec() != 0XFF) { + if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail; + } + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** + * Writes a 512 byte block to an SD card. + * + * \param[in] blockNumber Logical block to be written. + * \param[in] src Pointer to the location of the data to be written. + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD24, blockNumber)) { + error(SD_CARD_ERROR_CMD24); + goto fail; + } + if (!writeData(DATA_START_BLOCK, src)) goto fail; + + // wait for flash programming to complete + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + error(SD_CARD_ERROR_WRITE_TIMEOUT); + goto fail; + } + // response is r2 so get and check two bytes for nonzero + if (cardCommand(CMD13, 0) || spiRec()) { + error(SD_CARD_ERROR_WRITE_PROGRAMMING); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Write one data block in a multiple block write sequence + * \param[in] src Pointer to the location of the data to be written. + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeData(const uint8_t* src) { + chipSelectLow(); + // wait for previous write to finish + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail; + chipSelectHigh(); + return true; + + fail: + error(SD_CARD_ERROR_WRITE_MULTIPLE); + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +// send one block of data for write block or write multiple blocks +bool Sd2Card::writeData(uint8_t token, const uint8_t* src) { + spiSendBlock(token, src); + + spiSend(0xff); // dummy crc + spiSend(0xff); // dummy crc + + status_ = spiRec(); + if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { + error(SD_CARD_ERROR_WRITE); + goto fail; + } + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Start a write multiple blocks sequence. + * + * \param[in] blockNumber Address of first block in sequence. + * \param[in] eraseCount The number of blocks to be pre-erased. + * + * \note This function is used with writeData() and writeStop() + * for optimized multiple block writes. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { + // send pre-erase count + if (cardAcmd(ACMD23, eraseCount)) { + error(SD_CARD_ERROR_ACMD23); + goto fail; + } + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD25, blockNumber)) { + error(SD_CARD_ERROR_CMD25); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** End a write multiple blocks sequence. + * +* \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeStop() { + chipSelectLow(); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + spiSend(STOP_TRAN_TOKEN); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + chipSelectHigh(); + return true; + + fail: + error(SD_CARD_ERROR_STOP_TRAN); + chipSelectHigh(); + return false; } diff --git a/Marlin/SdBaseFile.cpp b/Marlin/SdBaseFile.cpp index dda44ec3ca..a485199b36 100644 --- a/Marlin/SdBaseFile.cpp +++ b/Marlin/SdBaseFile.cpp @@ -306,7 +306,7 @@ void SdBaseFile::getpos(fpos_t* pos) { * LS_R - Recursive list of subdirectories. */ void SdBaseFile::ls(uint8_t flags) { - ls(&Serial, flags, 0); + ls(&MSerial, flags, 0); } //------------------------------------------------------------------------------ /** List directory contents. @@ -949,7 +949,7 @@ int SdBaseFile::peek() { */ void SdBaseFile::printDirName(const dir_t& dir, uint8_t width, bool printSlash) { - printDirName(&Serial, dir, width, printSlash); + printDirName(&MSerial, dir, width, printSlash); } //------------------------------------------------------------------------------ /** %Print the name field of a directory entry in 8.3 format. @@ -993,7 +993,7 @@ static void print2u(Print* pr, uint8_t v) { * \param[in] fatDate The date field from a directory entry. */ void SdBaseFile::printFatDate(uint16_t fatDate) { - printFatDate(&Serial, fatDate); + printFatDate(&MSerial, fatDate); } //------------------------------------------------------------------------------ /** %Print a directory date field. @@ -1018,7 +1018,7 @@ void SdBaseFile::printFatDate(Print* pr, uint16_t fatDate) { * \param[in] fatTime The time field from a directory entry. */ void SdBaseFile::printFatTime(uint16_t fatTime) { - printFatTime(&Serial, fatTime); + printFatTime(&MSerial, fatTime); } //------------------------------------------------------------------------------ /** %Print a directory time field. @@ -1044,7 +1044,7 @@ void SdBaseFile::printFatTime(Print* pr, uint16_t fatTime) { bool SdBaseFile::printName() { char name[13]; if (!getFilename(name)) return false; - Serial.print(name); + MSerial.print(name); return true; } //------------------------------------------------------------------------------ diff --git a/Marlin/SdBaseFile.h b/Marlin/SdBaseFile.h index 9363401c96..e02ec3c7a5 100644 --- a/Marlin/SdBaseFile.h +++ b/Marlin/SdBaseFile.h @@ -25,7 +25,9 @@ */ #include #if ARDUINO < 100 +#define HardwareSerial_h // trick to disable the standard HWserial #include +#include "MarlinSerial.h" #else // ARDUINO #include #endif // ARDUINO diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp index 1870980b1d..7f82a7083b 100644 --- a/Marlin/SdFatUtil.cpp +++ b/Marlin/SdFatUtil.cpp @@ -62,7 +62,7 @@ void SdFatUtil::println_P(Print* pr, PGM_P str) { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::SerialPrint_P(PGM_P str) { - print_P(&Serial, str); + print_P(&MSerial, str); } //------------------------------------------------------------------------------ /** %Print a string in flash memory to Serial followed by a CR/LF. @@ -70,5 +70,5 @@ void SdFatUtil::SerialPrint_P(PGM_P str) { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::SerialPrintln_P(PGM_P str) { - println_P(&Serial, str); + println_P(&MSerial, str); } diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index b4112aa2d9..c49e77df85 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -1,46 +1,48 @@ -/* Arduino SdFat Library - * Copyright (C) 2008 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFatUtil_h -#define SdFatUtil_h -/** - * \file - * \brief Useful utility functions. - */ -#include -#if ARDUINO < 100 -#include -#else // ARDUINO -#include -#endif // ARDUINO -/** Store and print a string in flash memory.*/ -#define PgmPrint(x) SerialPrint_P(PSTR(x)) -/** Store and print a string in flash memory followed by a CR/LF.*/ -#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) - -namespace SdFatUtil { - int FreeRam(); - void print_P(Print* pr, PGM_P str); - void println_P(Print* pr, PGM_P str); - void SerialPrint_P(PGM_P str); - void SerialPrintln_P(PGM_P str); -} - -using namespace SdFatUtil; // NOLINT +/* Arduino SdFat Library + * Copyright (C) 2008 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdFatUtil_h +#define SdFatUtil_h +/** + * \file + * \brief Useful utility functions. + */ +#include +#if ARDUINO < 100 +#define HardwareSerial_h // trick to disable the standard HWserial +#include +#include "MarlinSerial.h" +#else // ARDUINO +#include +#endif // ARDUINO +/** Store and print a string in flash memory.*/ +#define PgmPrint(x) SerialPrint_P(PSTR(x)) +/** Store and print a string in flash memory followed by a CR/LF.*/ +#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) + +namespace SdFatUtil { + int FreeRam(); + void print_P(Print* pr, PGM_P str); + void println_P(Print* pr, PGM_P str); + void SerialPrint_P(PGM_P str); + void SerialPrintln_P(PGM_P str); +} + +using namespace SdFatUtil; // NOLINT #endif // #define SdFatUtil_h diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index ff3f8c2f2d..8ecc1a0445 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -27,7 +27,7 @@ // The arc is approximated by generating a huge number of tiny, linear segments. The length of each // segment is configured in settings.mm_per_arc_segment. void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, - uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise) + uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder) { // int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); // plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc @@ -123,11 +123,11 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 arc_target[axis_1] = center_axis1 + r_axis1; arc_target[axis_linear] += linear_per_segment; arc_target[E_AXIS] += extruder_per_segment; - plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate); + plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, extruder); } // Ensure last segment arrives at target location. - plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate); + plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, extruder); // plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled); } diff --git a/Marlin/motion_control.h b/Marlin/motion_control.h index 9bcff4bf4c..ca50f8098f 100644 --- a/Marlin/motion_control.h +++ b/Marlin/motion_control.h @@ -27,6 +27,6 @@ // the direction of helical travel, radius == circle radius, isclockwise boolean. Used // for vector transformation direction. void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1, - unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise); + unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise, uint8_t extruder); #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 0f9b1eb9ee..47286983b8 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -451,7 +451,7 @@ float junction_deviation = 0.1; // Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in // mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration // calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate) +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder) { // Calculate the buffer head after we push this byte int next_buffer_head = next_block_index(block_buffer_head); @@ -527,12 +527,12 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa else { if(feed_rate 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); #endif /* diff --git a/Marlin/planner.h b/Marlin/planner.h index 57c59a0b0f..8ef8fec17f 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -66,7 +66,7 @@ void plan_init(); // Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in // millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate); +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder); // Set position. Used for G92 instructions. void plan_set_position(const float &x, const float &y, const float &z, const float &e); diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 491b6e7f2b..34c7153c64 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -52,7 +52,7 @@ static long counter_x, // Counter variables for the bresenham line tracer counter_y, counter_z, counter_e; -static unsigned long step_events_completed; // The number of step events executed in the current block +volatile static unsigned long step_events_completed; // The number of step events executed in the current block #ifdef ADVANCE static long advance_rate, advance, final_advance = 0; static short old_advance = 0; @@ -63,6 +63,7 @@ static long acceleration_time, deceleration_time; //static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; static unsigned short acc_step_rate; // needed for deccelaration start point static char step_loops; +static unsigned short OCR1A_nominal; volatile long endstops_trigsteps[3]={0,0,0}; volatile long endstops_stepsTotal,endstops_stepsDone; @@ -77,10 +78,6 @@ static bool old_y_max_endstop=false; static bool old_z_min_endstop=false; static bool old_z_max_endstop=false; -static bool busy_error=false; -unsigned short OCR1A_error=12345; -unsigned short OCR1A_nominal; - volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; @@ -164,15 +161,6 @@ asm volatile ( \ #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<>3); } - if(timer < 100) { timer = 100; Serial.print("Steprate to high : "); Serial.println(step_rate); }//(20kHz this should never happen) + if(timer < 100) { timer = 100; MSerial.print("Steprate to high : "); MSerial.println(step_rate); }//(20kHz this should never happen) return timer; } @@ -277,17 +265,7 @@ inline void trapezoid_generator_reset() { // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. // It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. ISR(TIMER1_COMPA_vect) -{ - if(busy){ - OCR1A_error = OCR1A; - busy_error = true; - OCR1A = 30000; - return; - } // The busy-flag is used to avoid reentering this interrupt - - busy = true; - sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) - +{ // If there is no current block, attempt to pop one from the buffer if (current_block == NULL) { // Anything in the buffer? @@ -304,7 +282,7 @@ ISR(TIMER1_COMPA_vect) // #endif } else { -// DISABLE_STEPPER_DRIVER_INTERRUPT(); + OCR1A=2000; // 1kHz. } } @@ -404,8 +382,8 @@ ISR(TIMER1_COMPA_vect) count_direction[E_AXIS]=-1; } #endif //!ADVANCE - for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) + MSerial.checkRx(); /* counter_e += current_block->steps_e; if (counter_e > 0) { @@ -470,6 +448,7 @@ ISR(TIMER1_COMPA_vect) unsigned short timer; unsigned short step_rate; if (step_events_completed <= current_block->accelerate_until) { + MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); acc_step_rate += current_block->initial_rate; @@ -519,8 +498,6 @@ ISR(TIMER1_COMPA_vect) plan_discard_current_block(); } } - cli(); // disable interrupts - busy=false; } #ifdef ADVANCE From dd5296ad4d35fdea84b12e4cfd68691c1288ec3a Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 28 Nov 2011 17:42:49 +0100 Subject: [PATCH 109/228] Fixed temperature reading bug. (When using the lower and upper adc input bank) --- Marlin/temperature.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 04353b566d..77aa6485ba 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -464,6 +464,8 @@ ISR(TIMER0_COMPB_vect) #if (TEMP_0_PIN > -1) #if TEMP_0_PIN > 7 ADCSRB = 1< -1) #if TEMP_1_PIN > 7 ADCSRB = 1< -1) #if TEMP_2_PIN > 7 ADCSRB = 1< Date: Mon, 28 Nov 2011 19:13:40 +0100 Subject: [PATCH 110/228] get rid of indirect ringbuffer calls, made some inlines, removed virtual and streaming class requirements. --- Marlin/MarlinSerial.cpp | 242 +++++++++++++++++++++++++++++++++------- Marlin/MarlinSerial.h | 95 ++++++++++++++-- Marlin/SdBaseFile.cpp | 116 +++++++------------ Marlin/SdBaseFile.h | 13 +-- Marlin/SdFatUtil.cpp | 14 +-- Marlin/SdFatUtil.h | 94 ++++++++-------- 6 files changed, 386 insertions(+), 188 deletions(-) diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index fade8b293f..34ae6d7676 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -33,35 +33,25 @@ #include "MarlinSerial.h" -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which rx_buffer_head is the index of the -// location to which to write the next incoming character and rx_buffer_tail -// is the index of the location from which to read. -#define RX_BUFFER_SIZE 128 -struct ring_buffer -{ - unsigned char buffer[RX_BUFFER_SIZE]; - int head; - int tail; -}; + #if defined(UBRRH) || defined(UBRR0H) ring_buffer rx_buffer = { { 0 }, 0, 0 }; #endif -inline void store_char(unsigned char c, ring_buffer *rx_buffer) +inline void store_char(unsigned char c) { - int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the // current location of the tail), we're about to overflow the buffer // and so we don't write the character or advance the head. - if (i != rx_buffer->tail) { - rx_buffer->buffer[rx_buffer->head] = c; - rx_buffer->head = i; + if (i != rx_buffer.tail) { + rx_buffer.buffer[rx_buffer.head] = c; + rx_buffer.head = i; } } @@ -79,19 +69,18 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) #else #error UDR not defined #endif - store_char(c, &rx_buffer); + store_char(c); } #endif // Constructors //////////////////////////////////////////////////////////////// -MarlinSerial::MarlinSerial(ring_buffer *rx_buffer, +MarlinSerial::MarlinSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) { - _rx_buffer = rx_buffer; _ubrrh = ubrrh; _ubrrl = ubrrl; _ucsra = ucsra; @@ -144,28 +133,25 @@ void MarlinSerial::end() cbi(*_ucsrb, _rxcie); } -int MarlinSerial::available(void) -{ - return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; -} + int MarlinSerial::peek(void) { - if (_rx_buffer->head == _rx_buffer->tail) { + if (rx_buffer.head == rx_buffer.tail) { return -1; } else { - return _rx_buffer->buffer[_rx_buffer->tail]; + return rx_buffer.buffer[rx_buffer.tail]; } } int MarlinSerial::read(void) { // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) { + if (rx_buffer.head == rx_buffer.tail) { return -1; } else { - unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + unsigned char c = rx_buffer.buffer[rx_buffer.tail]; + rx_buffer.tail = (unsigned int)(rx_buffer.tail + 1) % RX_BUFFER_SIZE; return c; } } @@ -181,29 +167,207 @@ void MarlinSerial::flush() // the value to rx_buffer_tail; the previous value of rx_buffer_head // may be written to rx_buffer_tail, making it appear as if the buffer // were full, not empty. - _rx_buffer->head = _rx_buffer->tail; + rx_buffer.head = rx_buffer.tail; } -void MarlinSerial::write(uint8_t c) -{ - while (!((*_ucsra) & (1 << _udre))) - ; - *_udr = c; + + +/// imports from print.h +/* default implementation: may be overridden */ +void MarlinSerial::write(const char *str) +{ + while (*str) + write(*str++); } -void MarlinSerial::checkRx() +/* default implementation: may be overridden */ +void MarlinSerial::write(const uint8_t *buffer, size_t size) { - if((UCSR0A & (1< 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) + print((char) (buf[i - 1] < 10 ? + '0' + buf[i - 1] : + 'A' + buf[i - 1] - 10)); +} + +void MarlinSerial::printFloat(double number, uint8_t digits) +{ + // Handle negative numbers + if (number < 0.0) + { + print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i=0; i 0) + print("."); + + // Extract digits from the remainder one at a time + while (digits-- > 0) + { + remainder *= 10.0; + int toPrint = int(remainder); + print(toPrint); + remainder -= toPrint; + } +} + // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(UBRR0H) && defined(UBRR0L) - MarlinSerial MSerial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); + MarlinSerial MSerial( &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); #else #error no serial port defined (port 0) #endif diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 79454492a6..3c7381ad13 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -23,15 +23,30 @@ #define MarlinSerial_h #include +#include -#include "Stream.h" -struct ring_buffer; +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which rx_buffer_head is the index of the +// location to which to write the next incoming character and rx_buffer_tail +// is the index of the location from which to read. +#define RX_BUFFER_SIZE 128 -class MarlinSerial : public Stream + +struct ring_buffer +{ + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; +}; + +#if defined(UBRRH) || defined(UBRR0H) + extern ring_buffer rx_buffer; +#endif + +class MarlinSerial //: public Stream { private: - ring_buffer *_rx_buffer; volatile uint8_t *_ubrrh; volatile uint8_t *_ubrrl; volatile uint8_t *_ucsra; @@ -43,20 +58,76 @@ class MarlinSerial : public Stream uint8_t _udre; uint8_t _u2x; public: - MarlinSerial(ring_buffer *rx_buffer, + MarlinSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); void begin(long); void end(); - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual void write(uint8_t); - virtual void checkRx(void); - using Print::write; // pull in write(str) and write(buf, size) from Print + inline int available(void) + { + return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE; + } + int peek(void); + int read(void); + void flush(void); + inline void write(uint8_t c) + { + while (!((*_ucsra) & (1 << _udre))) + ; + + *_udr = c; + } + + + inline void checkRx(void) + { + if((UCSR0A & (1<. */ + +#define SERIAL MSerial #include "SdBaseFile.h" //------------------------------------------------------------------------------ // pointer to cwd directory @@ -294,20 +296,7 @@ void SdBaseFile::getpos(fpos_t* pos) { pos->position = curPosition_; pos->cluster = curCluster_; } -//------------------------------------------------------------------------------ -/** List directory contents to Serial. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ -void SdBaseFile::ls(uint8_t flags) { - ls(&MSerial, flags, 0); -} + //------------------------------------------------------------------------------ /** List directory contents. * @@ -324,14 +313,14 @@ void SdBaseFile::ls(uint8_t flags) { * \param[in] indent Amount of space before file name. Used for recursive * list to indicate subdirectory level. */ -void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) { +void SdBaseFile::ls(uint8_t flags, uint8_t indent) { rewind(); int8_t status; - while ((status = lsPrintNext(pr, flags, indent))) { + while ((status = lsPrintNext( flags, indent))) { if (status > 1 && (flags & LS_R)) { uint16_t index = curPosition()/32 - 1; SdBaseFile s; - if (s.open(this, index, O_READ)) s.ls(pr, flags, indent + 2); + if (s.open(this, index, O_READ)) s.ls( flags, indent + 2); seekSet(32 * (index + 1)); } } @@ -339,7 +328,7 @@ void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) { //------------------------------------------------------------------------------ // saves 32 bytes on stack for ls recursion // return 0 - EOF, 1 - normal file, or 2 - directory -int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) { +int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) { dir_t dir; uint8_t w = 0; @@ -352,38 +341,38 @@ int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) { && DIR_IS_FILE_OR_SUBDIR(&dir)) break; } // indent for dir level - for (uint8_t i = 0; i < indent; i++) pr->write(' '); + for (uint8_t i = 0; i < indent; i++) MSerial.write(' '); // print name for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - pr->write('.'); + MSerial.write('.'); w++; } - pr->write(dir.name[i]); + MSerial.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir)) { - pr->write('/'); + MSerial.write('/'); w++; } if (flags & (LS_DATE | LS_SIZE)) { - while (w++ < 14) pr->write(' '); + while (w++ < 14) MSerial.write(' '); } // print modify date/time if requested if (flags & LS_DATE) { - pr->write(' '); - printFatDate(pr, dir.lastWriteDate); - pr->write(' '); - printFatTime(pr, dir.lastWriteTime); + MSerial.write(' '); + printFatDate( dir.lastWriteDate); + MSerial.write(' '); + printFatTime( dir.lastWriteTime); } // print size if requested if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) { - pr->write(' '); - pr->print(dir.fileSize); + MSerial.write(' '); + MSerial.print(dir.fileSize); } - pr->println(); + MSerial.println(); return DIR_IS_FILE(&dir) ? 1 : 2; } //------------------------------------------------------------------------------ @@ -940,17 +929,7 @@ int SdBaseFile::peek() { if (c >= 0) setpos(&pos); return c; } -//------------------------------------------------------------------------------ -/** %Print the name field of a directory entry in 8.3 format to Serial. - * - * \param[in] dir The directory structure containing the name. - * \param[in] width Blank fill name if length is less than \a width. - * \param[in] printSlash Print '/' after directory names if true. - */ -void SdBaseFile::printDirName(const dir_t& dir, - uint8_t width, bool printSlash) { - printDirName(&MSerial, dir, width, printSlash); -} + //------------------------------------------------------------------------------ /** %Print the name field of a directory entry in 8.3 format. * \param[in] pr Print stream for output. @@ -958,32 +937,32 @@ void SdBaseFile::printDirName(const dir_t& dir, * \param[in] width Blank fill name if length is less than \a width. * \param[in] printSlash Print '/' after directory names if true. */ -void SdBaseFile::printDirName(Print* pr, const dir_t& dir, +void SdBaseFile::printDirName(const dir_t& dir, uint8_t width, bool printSlash) { uint8_t w = 0; for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - pr->write('.'); + MSerial.write('.'); w++; } - pr->write(dir.name[i]); + MSerial.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir) && printSlash) { - pr->write('/'); + MSerial.write('/'); w++; } while (w < width) { - pr->write(' '); + MSerial.write(' '); w++; } } //------------------------------------------------------------------------------ // print uint8_t with width 2 -static void print2u(Print* pr, uint8_t v) { - if (v < 10) pr->write('0'); - pr->print(v, DEC); +static void print2u( uint8_t v) { + if (v < 10) MSerial.write('0'); + MSerial.print(v, DEC); } //------------------------------------------------------------------------------ /** %Print a directory date field to Serial. @@ -992,9 +971,7 @@ static void print2u(Print* pr, uint8_t v) { * * \param[in] fatDate The date field from a directory entry. */ -void SdBaseFile::printFatDate(uint16_t fatDate) { - printFatDate(&MSerial, fatDate); -} + //------------------------------------------------------------------------------ /** %Print a directory date field. * @@ -1003,23 +980,14 @@ void SdBaseFile::printFatDate(uint16_t fatDate) { * \param[in] pr Print stream for output. * \param[in] fatDate The date field from a directory entry. */ -void SdBaseFile::printFatDate(Print* pr, uint16_t fatDate) { - pr->print(FAT_YEAR(fatDate)); - pr->write('-'); - print2u(pr, FAT_MONTH(fatDate)); - pr->write('-'); - print2u(pr, FAT_DAY(fatDate)); -} -//------------------------------------------------------------------------------ -/** %Print a directory time field to Serial. - * - * Format is hh:mm:ss. - * - * \param[in] fatTime The time field from a directory entry. - */ -void SdBaseFile::printFatTime(uint16_t fatTime) { - printFatTime(&MSerial, fatTime); +void SdBaseFile::printFatDate(uint16_t fatDate) { + MSerial.print(FAT_YEAR(fatDate)); + MSerial.write('-'); + print2u( FAT_MONTH(fatDate)); + MSerial.write('-'); + print2u( FAT_DAY(fatDate)); } + //------------------------------------------------------------------------------ /** %Print a directory time field. * @@ -1028,12 +996,12 @@ void SdBaseFile::printFatTime(uint16_t fatTime) { * \param[in] pr Print stream for output. * \param[in] fatTime The time field from a directory entry. */ -void SdBaseFile::printFatTime(Print* pr, uint16_t fatTime) { - print2u(pr, FAT_HOUR(fatTime)); - pr->write(':'); - print2u(pr, FAT_MINUTE(fatTime)); - pr->write(':'); - print2u(pr, FAT_SECOND(fatTime)); +void SdBaseFile::printFatTime( uint16_t fatTime) { + print2u( FAT_HOUR(fatTime)); + MSerial.write(':'); + print2u( FAT_MINUTE(fatTime)); + MSerial.write(':'); + print2u( FAT_SECOND(fatTime)); } //------------------------------------------------------------------------------ /** Print a file's name to Serial diff --git a/Marlin/SdBaseFile.h b/Marlin/SdBaseFile.h index e02ec3c7a5..e184acd968 100644 --- a/Marlin/SdBaseFile.h +++ b/Marlin/SdBaseFile.h @@ -270,8 +270,7 @@ class SdBaseFile { bool isRoot() const { return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32; } - void ls(Print* pr, uint8_t flags = 0, uint8_t indent = 0); - void ls(uint8_t flags = 0); + void ls( uint8_t flags = 0, uint8_t indent = 0); bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true); // alias for backward compactability bool makeDir(SdBaseFile* dir, const char* path) { @@ -284,9 +283,7 @@ class SdBaseFile { bool openRoot(SdVolume* vol); int peek(); static void printFatDate(uint16_t fatDate); - static void printFatDate(Print* pr, uint16_t fatDate); - static void printFatTime(uint16_t fatTime); - static void printFatTime(Print* pr, uint16_t fatTime); + static void printFatTime( uint16_t fatTime); bool printName(); int16_t read(); int16_t read(void* buf, uint16_t nbyte); @@ -359,7 +356,7 @@ class SdBaseFile { bool addCluster(); bool addDirCluster(); dir_t* cacheDirEntry(uint8_t action); - int8_t lsPrintNext(Print *pr, uint8_t flags, uint8_t indent); + int8_t lsPrintNext( uint8_t flags, uint8_t indent); static bool make83Name(const char* str, uint8_t* name, const char** ptr); bool mkdir(SdBaseFile* parent, const uint8_t dname[11]); bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag); @@ -367,9 +364,7 @@ class SdBaseFile { dir_t* readDirCache(); //------------------------------------------------------------------------------ // to be deleted - static void printDirName(const dir_t& dir, - uint8_t width, bool printSlash); - static void printDirName(Print* pr, const dir_t& dir, + static void printDirName( const dir_t& dir, uint8_t width, bool printSlash); //------------------------------------------------------------------------------ // Deprecated functions - suppress cpplint warnings with NOLINT comment diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp index 7f82a7083b..0bf86f2956 100644 --- a/Marlin/SdFatUtil.cpp +++ b/Marlin/SdFatUtil.cpp @@ -43,8 +43,8 @@ int SdFatUtil::FreeRam() { * \param[in] pr Print object for output. * \param[in] str Pointer to string stored in flash memory. */ -void SdFatUtil::print_P(Print* pr, PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) pr->write(c); +void SdFatUtil::print_P( PGM_P str) { + for (uint8_t c; (c = pgm_read_byte(str)); str++) MSerial.write(c); } //------------------------------------------------------------------------------ /** %Print a string in flash memory followed by a CR/LF. @@ -52,9 +52,9 @@ void SdFatUtil::print_P(Print* pr, PGM_P str) { * \param[in] pr Print object for output. * \param[in] str Pointer to string stored in flash memory. */ -void SdFatUtil::println_P(Print* pr, PGM_P str) { - print_P(pr, str); - pr->println(); +void SdFatUtil::println_P( PGM_P str) { + print_P( str); + MSerial.println(); } //------------------------------------------------------------------------------ /** %Print a string in flash memory to Serial. @@ -62,7 +62,7 @@ void SdFatUtil::println_P(Print* pr, PGM_P str) { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::SerialPrint_P(PGM_P str) { - print_P(&MSerial, str); + print_P(str); } //------------------------------------------------------------------------------ /** %Print a string in flash memory to Serial followed by a CR/LF. @@ -70,5 +70,5 @@ void SdFatUtil::SerialPrint_P(PGM_P str) { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::SerialPrintln_P(PGM_P str) { - println_P(&MSerial, str); + println_P( str); } diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index c49e77df85..6e3cb4936f 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -1,48 +1,48 @@ -/* Arduino SdFat Library - * Copyright (C) 2008 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library 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 Library 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 the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFatUtil_h -#define SdFatUtil_h -/** - * \file - * \brief Useful utility functions. - */ -#include -#if ARDUINO < 100 -#define HardwareSerial_h // trick to disable the standard HWserial -#include -#include "MarlinSerial.h" -#else // ARDUINO -#include -#endif // ARDUINO -/** Store and print a string in flash memory.*/ -#define PgmPrint(x) SerialPrint_P(PSTR(x)) -/** Store and print a string in flash memory followed by a CR/LF.*/ -#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) - -namespace SdFatUtil { - int FreeRam(); - void print_P(Print* pr, PGM_P str); - void println_P(Print* pr, PGM_P str); - void SerialPrint_P(PGM_P str); - void SerialPrintln_P(PGM_P str); -} - -using namespace SdFatUtil; // NOLINT +/* Arduino SdFat Library + * Copyright (C) 2008 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library 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 Library 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 the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdFatUtil_h +#define SdFatUtil_h +/** + * \file + * \brief Useful utility functions. + */ +#include +#if ARDUINO < 100 +#define HardwareSerial_h // trick to disable the standard HWserial +#include +#include "MarlinSerial.h" +#else // ARDUINO +#include +#endif // ARDUINO +/** Store and print a string in flash memory.*/ +#define PgmPrint(x) SerialPrint_P(PSTR(x)) +/** Store and print a string in flash memory followed by a CR/LF.*/ +#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) + +namespace SdFatUtil { + int FreeRam(); + void print_P( PGM_P str); + void println_P( PGM_P str); + void SerialPrint_P(PGM_P str); + void SerialPrintln_P(PGM_P str); +} + +using namespace SdFatUtil; // NOLINT #endif // #define SdFatUtil_h From b9ad0bb2ce7f6d92375de204536b46cce7bc930a Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 28 Nov 2011 19:28:38 +0100 Subject: [PATCH 111/228] removed unecessary indirect register adressing in serial. --- Marlin/MarlinSerial.cpp | 45 +++++++++++++++-------------------------- Marlin/MarlinSerial.h | 22 ++++---------------- 2 files changed, 20 insertions(+), 47 deletions(-) diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index 34ae6d7676..fb34ab19bb 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -75,22 +75,9 @@ inline void store_char(unsigned char c) // Constructors //////////////////////////////////////////////////////////////// -MarlinSerial::MarlinSerial( - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) +MarlinSerial::MarlinSerial() { - _ubrrh = ubrrh; - _ubrrl = ubrrl; - _ucsra = ucsra; - _ucsrb = ucsrb; - _udr = udr; - _rxen = rxen; - _txen = txen; - _rxcie = rxcie; - _udre = udre; - _u2x = u2x; + } // Public Methods ////////////////////////////////////////////////////////////// @@ -98,39 +85,39 @@ MarlinSerial::MarlinSerial( void MarlinSerial::begin(long baud) { uint16_t baud_setting; - bool use_u2x = true; + bool useU2X0 = true; #if F_CPU == 16000000UL // hardcoded exception for compatibility with the bootloader shipped // with the Duemilanove and previous boards and the firmware on the 8U2 // on the Uno and Mega 2560. if (baud == 57600) { - use_u2x = false; + useU2X0 = false; } #endif - if (use_u2x) { - *_ucsra = 1 << _u2x; + if (useU2X0) { + UCSR0A = 1 << U2X0; baud_setting = (F_CPU / 4 / baud - 1) / 2; } else { - *_ucsra = 0; + UCSR0A = 0; baud_setting = (F_CPU / 8 / baud - 1) / 2; } // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) - *_ubrrh = baud_setting >> 8; - *_ubrrl = baud_setting; + UBRR0H = baud_setting >> 8; + UBRR0L = baud_setting; - sbi(*_ucsrb, _rxen); - sbi(*_ucsrb, _txen); - sbi(*_ucsrb, _rxcie); + sbi(UCSR0B, RXEN0); + sbi(UCSR0B, TXEN0); + sbi(UCSR0B, RXCIE0); } void MarlinSerial::end() { - cbi(*_ucsrb, _rxen); - cbi(*_ucsrb, _txen); - cbi(*_ucsrb, _rxcie); + cbi(UCSR0B, RXEN0); + cbi(UCSR0B, TXEN0); + cbi(UCSR0B, RXCIE0); } @@ -367,7 +354,7 @@ void MarlinSerial::printFloat(double number, uint8_t digits) // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(UBRR0H) && defined(UBRR0L) - MarlinSerial MSerial( &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); + MarlinSerial MSerial; #else #error no serial port defined (port 0) #endif diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 3c7381ad13..30c0f5a344 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -46,23 +46,9 @@ struct ring_buffer class MarlinSerial //: public Stream { - private: - volatile uint8_t *_ubrrh; - volatile uint8_t *_ubrrl; - volatile uint8_t *_ucsra; - volatile uint8_t *_ucsrb; - volatile uint8_t *_udr; - uint8_t _rxen; - uint8_t _txen; - uint8_t _rxcie; - uint8_t _udre; - uint8_t _u2x; + public: - MarlinSerial( - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *udr, - uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); + MarlinSerial(); void begin(long); void end(); inline int available(void) @@ -74,10 +60,10 @@ class MarlinSerial //: public Stream void flush(void); inline void write(uint8_t c) { - while (!((*_ucsra) & (1 << _udre))) + while (!((UCSR0A) & (1 << UDRE0))) ; - *_udr = c; + UDR0 = c; } From 85da81e67349ab815985b5651aecfb7943201b3c Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 28 Nov 2011 19:34:42 +0100 Subject: [PATCH 112/228] inlineing of small functions in serial --- Marlin/MarlinSerial.cpp | 28 +--------------------------- Marlin/MarlinSerial.h | 36 +++++++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index fb34ab19bb..6cf47eafe3 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -161,31 +161,9 @@ void MarlinSerial::flush() /// imports from print.h -/* default implementation: may be overridden */ -void MarlinSerial::write(const char *str) -{ - while (*str) - write(*str++); -} -/* default implementation: may be overridden */ -void MarlinSerial::write(const uint8_t *buffer, size_t size) -{ - while (size--) - write(*buffer++); -} -void MarlinSerial::print(const String &s) -{ - for (int i = 0; i < s.length(); i++) { - write(s[i]); - } -} -void MarlinSerial::print(const char str[]) -{ - write(str); -} void MarlinSerial::print(char c, int base) { @@ -353,11 +331,7 @@ void MarlinSerial::printFloat(double number, uint8_t digits) // Preinstantiate Objects ////////////////////////////////////////////////////// -#if defined(UBRR0H) && defined(UBRR0L) - MarlinSerial MSerial; -#else - #error no serial port defined (port 0) -#endif +MarlinSerial MSerial; #endif // whole file diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 30c0f5a344..9ff07912b9 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -51,13 +51,15 @@ class MarlinSerial //: public Stream MarlinSerial(); void begin(long); void end(); + int peek(void); + int read(void); + void flush(void); + inline int available(void) { return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE; } - int peek(void); - int read(void); - void flush(void); + inline void write(uint8_t c) { while (!((UCSR0A) & (1 << UDRE0))) @@ -91,11 +93,31 @@ class MarlinSerial //: public Stream public: - void write(const char *str); - void write( const uint8_t *buffer, size_t size); - void print(const String &); - void print(const char[]); + inline void write(const char *str) + { + while (*str) + write(*str++); + } + + + inline void write(const uint8_t *buffer, size_t size) + { + while (size--) + write(*buffer++); + } + + inline void print(const String &s) + { + for (int i = 0; i < s.length(); i++) { + write(s[i]); + } + } + + inline void print(const char *str) + { + write(str); + } void print(char, int = BYTE); void print(unsigned char, int = BYTE); void print(int, int = DEC); From 98805c922892edc2d6fbb2ea39574d7cde1b492f Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 28 Nov 2011 20:51:01 +0100 Subject: [PATCH 113/228] Added M88 command. (Request from Action68) --- Marlin/Marlin.pde | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 4c1535bf58..a803ba375d 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -866,6 +866,16 @@ inline void process_commands() axis_steps_per_unit[i] = code_value(); } break; + case 88: //M88 + if(code_seen('S')) { + stepper_inactive_time = code_value() * 1000; + } + else { + st_synchronize() + LCD_MESSAGEPGM("Free Move"); + disable_e(); + } + break; case 115: // M115 SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); break; From 7216a128566c173ebd2d799498bf53af182e9acf Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 28 Nov 2011 21:17:06 +0100 Subject: [PATCH 114/228] Disabled M88 for boards that don't have seperate enable pins. --- Marlin/Marlin.pde | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index a803ba375d..191f70b646 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -867,14 +867,19 @@ inline void process_commands() } break; case 88: //M88 - if(code_seen('S')) { - stepper_inactive_time = code_value() * 1000; - } - else { - st_synchronize() - LCD_MESSAGEPGM("Free Move"); - disable_e(); - } + #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS + if(code_seen('S')) { + stepper_inactive_time = code_value() * 1000; + } + else { + st_synchronize() + LCD_MESSAGEPGM("Free Move"); + disable_e(); + } + #else + SERIAL_ECHO_START; + SERIAL_ECHOLN("M88 not supported"); + #endif break; case 115: // M115 SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); From 6d95644c0d7dcb17b9723374b92aaceed11c6548 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 28 Nov 2011 21:49:54 +0100 Subject: [PATCH 115/228] Moved M88 into M84. (M84 E) --- Marlin/Marlin.pde | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 191f70b646..86f5626599 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -852,7 +852,18 @@ inline void process_commands() } else { - finishAndDisableSteppers(); + #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS + if(code_seen('E')) { + st_synchronize() + LCD_MESSAGEPGM("Free Move"); + disable_e(); + } + else { + finishAndDisableSteppers(); + } + #else + finishAndDisableSteppers(); + #endif } break; case 85: // M85 @@ -866,21 +877,6 @@ inline void process_commands() axis_steps_per_unit[i] = code_value(); } break; - case 88: //M88 - #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS - if(code_seen('S')) { - stepper_inactive_time = code_value() * 1000; - } - else { - st_synchronize() - LCD_MESSAGEPGM("Free Move"); - disable_e(); - } - #else - SERIAL_ECHO_START; - SERIAL_ECHOLN("M88 not supported"); - #endif - break; case 115: // M115 SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); break; From b19c8b74b9b5a5359c8cf508cca17480003e189e Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 28 Nov 2011 21:51:44 +0100 Subject: [PATCH 116/228] force inline --- Marlin/MarlinSerial.cpp | 3 ++- Marlin/MarlinSerial.h | 16 +++++++++------- Marlin/temperature.h | 16 ++++++++-------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index 6cf47eafe3..d1ec0fec97 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -32,6 +32,7 @@ #if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) #include "MarlinSerial.h" +#include "Marlin.h" @@ -41,7 +42,7 @@ #endif -inline void store_char(unsigned char c) +FORCE_INLINE void store_char(unsigned char c) { int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE; diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 9ff07912b9..6bc9ffb26a 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -24,6 +24,8 @@ #include #include +#define FORCE_INLINE __attribute__((always_inline)) inline + // Define constants and variables for buffering incoming serial data. We're @@ -55,12 +57,12 @@ class MarlinSerial //: public Stream int read(void); void flush(void); - inline int available(void) + FORCE_INLINE int available(void) { return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE; } - inline void write(uint8_t c) + FORCE_INLINE void write(uint8_t c) { while (!((UCSR0A) & (1 << UDRE0))) ; @@ -69,7 +71,7 @@ class MarlinSerial //: public Stream } - inline void checkRx(void) + FORCE_INLINE void checkRx(void) { if((UCSR0A & (1< current_raw[TEMPSENSOR_HOTEND_0];}; FORCE_INLINE bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; -inline float isHeatingHotend(uint8_t extruder){ +FORCE_INLINE float isHeatingHotend(uint8_t extruder){ if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]; if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1]; }; -inline bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; +FORCE_INLINE bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; FORCE_INLINE bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];}; FORCE_INLINE bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; -inline float isCoolingHotend(uint8_t extruder){ +FORCE_INLINE float isCoolingHotend(uint8_t extruder){ if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0]; if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1]; }; -inline bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; +FORCE_INLINE bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; void disable_heater(); void setWatch(); From 8cb29921a0b897aaa700ea8312330c294e4b640a Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 28 Nov 2011 22:09:17 +0100 Subject: [PATCH 117/228] possible stepper release after sd printing --- Marlin/Marlin.pde | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 32e0b812d9..11bdec4729 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -395,7 +395,6 @@ inline void get_command() if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) { if(card.eof()){ - card.sdprinting = false; SERIAL_PROTOCOLLNPGM("Done printing file"); stoptime=millis(); char time[30]; @@ -407,7 +406,9 @@ inline void get_command() SERIAL_ECHO_START; SERIAL_ECHOLN(time); LCD_MESSAGE(time); + card.printingHasFinished(); card.checkautostart(true); + } if(serial_char=='\n') comment_mode = false; //for new command @@ -860,7 +861,7 @@ inline void process_commands() { #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS if(code_seen('E')) { - st_synchronize() + st_synchronize(); LCD_MESSAGEPGM("Free Move"); disable_e(); } From e4ab0e598226e6d5fbca46dc7762af4ab6a83e6b Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 28 Nov 2011 22:11:17 +0100 Subject: [PATCH 118/228] more inlines --- Marlin/Marlin.pde | 16 ++++++++-------- Marlin/temperature.h | 2 +- Marlin/ultralcd.pde | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 11bdec4729..3c6791336f 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -289,7 +289,7 @@ void loop() } -inline void get_command() +FORCE_INLINE void get_command() { while( MSerial.available() > 0 && buflen < BUFSIZE) { serial_char = MSerial.read(); @@ -436,20 +436,20 @@ inline void get_command() } -inline float code_value() +FORCE_INLINE float code_value() { return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); } -inline long code_value_long() +FORCE_INLINE long code_value_long() { return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); } -inline bool code_seen(char code_string[]) //Return True if the string was found +FORCE_INLINE bool code_seen(char code_string[]) //Return True if the string was found { return (strstr(cmdbuffer[bufindr], code_string) != NULL); } -inline bool code_seen(char code) +FORCE_INLINE bool code_seen(char code) { strchr_pointer = strchr(cmdbuffer[bufindr], code); return (strchr_pointer != NULL); //Return True if a character was found @@ -481,7 +481,7 @@ inline bool code_seen(char code) endstops_hit_on_purpose();\ } -inline void process_commands() +FORCE_INLINE void process_commands() { unsigned long codenum; //throw away variable char *starpos = NULL; @@ -1075,7 +1075,7 @@ void ClearToSend() SERIAL_PROTOCOLLNPGM("ok"); } -inline void get_coordinates() +FORCE_INLINE void get_coordinates() { 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]; @@ -1087,7 +1087,7 @@ inline void get_coordinates() } } -inline void get_arc_coordinates() +FORCE_INLINE void get_arc_coordinates() { get_coordinates(); if(code_seen('I')) offset[0] = code_value(); diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 13a0e0c1f5..a12ef03109 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -69,7 +69,7 @@ FORCE_INLINE float degHotend(uint8_t extruder){ FORCE_INLINE float degTargetHotend0() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);}; FORCE_INLINE float degTargetHotend1() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);}; -inline float degTargetHotend(uint8_t extruder){ +FORCE_INLINE float degTargetHotend(uint8_t extruder){ if(extruder == 0) return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]); if(extruder == 1) return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]); }; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index a4bb640b70..4ca93aa0c7 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -60,7 +60,7 @@ void lcdProgMemprint(const char *str) //=============================functions ============================ //=========================================================================== -inline int intround(const float &x){return int(0.5+x);} +FORCE_INLINE int intround(const float &x){return int(0.5+x);} void lcd_status(const char* message) { @@ -83,7 +83,7 @@ void lcd_statuspgm(const char* message) *target=0; } -inline void clear() +FORCE_INLINE void clear() { lcd.clear(); } From d00b7e558745608a95075ba1c3202a30c69d1438 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 28 Nov 2011 22:45:40 +0100 Subject: [PATCH 119/228] repaired compiliation in windows --- Marlin/MarlinSerial.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index d1ec0fec97..854c4a824b 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "wiring.h" #include "wiring_private.h" From 716e89b87c15085d781379f9ffdfd376da415c6b Mon Sep 17 00:00:00 2001 From: Bernhard Date: Tue, 29 Nov 2011 22:06:31 +0100 Subject: [PATCH 120/228] first homing move diagonal towards home switches. --- Marlin/Marlin.pde | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 3c6791336f..7c0d31011c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -532,6 +532,19 @@ FORCE_INLINE void process_commands() feedrate = 0.0; home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); + if( code_seen(axis_codes[0]) && code_seen(axis_codes[1]) ) //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] Date: Wed, 30 Nov 2011 08:32:28 +0100 Subject: [PATCH 121/228] made it compile if arduino decides to include files in a differnt order. DEC HEX and stuff now defined in MarlinSerial.h --- Marlin/MarlinSerial.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 6bc9ffb26a..9fc9f0070a 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -24,8 +24,17 @@ #include #include +#include #define FORCE_INLINE __attribute__((always_inline)) inline +#include "WString.h" + +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 +#define BYTE 0 + // Define constants and variables for buffering incoming serial data. We're From 59205ac5fcf9fb00ca2748ffe0bddd1a47b239fe Mon Sep 17 00:00:00 2001 From: Bernhard Date: Wed, 30 Nov 2011 08:51:46 +0100 Subject: [PATCH 122/228] preliminiary implementation for the early heating finish. Might be replaced by something more clever, e.g. by erik, and does not yet support the second extruder or the bed. its kind of not so cool, because you need 6 more ints. Maybe isheating() should use the degrees directly, as it is not used in time-critical anyways. Then it would be much easier. to have the offsets without additional variables. --- Marlin/Configuration.h | 2 ++ Marlin/temperature.cpp | 2 ++ Marlin/temperature.h | 6 ++++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 558044e280..483b8cf837 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -91,6 +91,8 @@ // if CooldownNoWait is defined M109 will not wait for the cooldown to finish #define CooldownNoWait true +// Heating is finished if a temperature close to this degree shift is reached +#define HEATING_EARLY_FINISH_DEG_OFFSET 1 //Degree // PID settings: // Uncomment the following line to enable PID support. diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 77aa6485ba..93364f8cb0 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -43,6 +43,8 @@ //=========================================================================== int target_raw[3] = {0, 0, 0}; int current_raw[3] = {0, 0, 0}; +int heatingtarget_raw[3]= {0, 0, 0}; + #ifdef PIDTEMP diff --git a/Marlin/temperature.h b/Marlin/temperature.h index a12ef03109..ba1043b6da 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -41,6 +41,7 @@ int temp2analogBed(int celsius); float analog2temp(int raw); float analog2tempBed(int raw); extern int target_raw[3]; +extern int heatingtarget_raw[3]; extern int current_raw[3]; extern float Kp,Ki,Kd,Kc; @@ -79,6 +80,7 @@ FORCE_INLINE float degTargetBed() { return analog2tempBed(target_raw[TEMPSENSO FORCE_INLINE void setTargetHotend0(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius); + heatingtarget_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius-HEATING_EARLY_FINISH_DEG_OFFSET); #ifdef PIDTEMP pid_setpoint = celsius; #endif //PIDTEMP @@ -90,10 +92,10 @@ FORCE_INLINE float setTargetHotend(const float &celcius, uint8_t extruder){ }; FORCE_INLINE void setTargetBed(const float &celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; -FORCE_INLINE bool isHeatingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; +FORCE_INLINE bool isHeatingHotend0() {return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; FORCE_INLINE bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; FORCE_INLINE float isHeatingHotend(uint8_t extruder){ - if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]; + if(extruder == 0) return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]; if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1]; }; FORCE_INLINE bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; From 9c57453168f88907c5e5b40c3aa7c23ce5d9a01f Mon Sep 17 00:00:00 2001 From: Bernhard Date: Wed, 30 Nov 2011 08:57:30 +0100 Subject: [PATCH 123/228] removed stream.h referenece from marlinserial. --- Marlin/MarlinSerial.h | 2 +- Marlin/SdFile.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 9fc9f0070a..051070fde8 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -23,7 +23,7 @@ #define MarlinSerial_h #include -#include +//#include #include #define FORCE_INLINE __attribute__((always_inline)) inline diff --git a/Marlin/SdFile.h b/Marlin/SdFile.h index d5f8ec0891..e59bb8abe5 100644 --- a/Marlin/SdFile.h +++ b/Marlin/SdFile.h @@ -22,6 +22,7 @@ * \brief SdFile class */ #include "SdBaseFile.h" +#include #ifndef SdFile_h #define SdFile_h //------------------------------------------------------------------------------ From b0c3871750d55ab66f5233f7c318375aa1b61e43 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Wed, 30 Nov 2011 09:07:56 +0100 Subject: [PATCH 124/228] more fixing of the sanguino math round problem --- Marlin/Marlin.h | 1 + Marlin/Marlin.pde | 3 ++- Marlin/MarlinSerial.h | 2 +- Marlin/Sanguino/cores/arduino/wiring.h | 1 + Marlin/Sanguino/cores/arduino/wiring_private.h | 2 +- Marlin/pins.h | 1 + Marlin/planner.h | 2 +- 7 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 464d7ebf56..574a85ec53 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -4,6 +4,7 @@ // Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. // Licence: GPL #define HardwareSerial_h // trick to disable the standard HWserial +#include #include #include "fastio.h" #include diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 7c0d31011c..06fd097766 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -25,8 +25,8 @@ http://reprap.org/pipermail/reprap-dev/2011-May/003323.html */ +#include #include - #include "EEPROMwrite.h" #include "fastio.h" #include "Configuration.h" @@ -39,6 +39,7 @@ #include "motion_control.h" #include "cardreader.h" #include "watchdog.h" +#include #define VERSION_STRING "1.0.0 Beta 1" diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 051070fde8..76d5a35a1f 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -21,7 +21,7 @@ #ifndef MarlinSerial_h #define MarlinSerial_h - +#include #include //#include #include diff --git a/Marlin/Sanguino/cores/arduino/wiring.h b/Marlin/Sanguino/cores/arduino/wiring.h index e29959b865..0a93678053 100644 --- a/Marlin/Sanguino/cores/arduino/wiring.h +++ b/Marlin/Sanguino/cores/arduino/wiring.h @@ -25,6 +25,7 @@ #ifndef Wiring_h #define Wiring_h +#include #include #include #include "binary.h" diff --git a/Marlin/Sanguino/cores/arduino/wiring_private.h b/Marlin/Sanguino/cores/arduino/wiring_private.h index 11f6f00f28..56c471353d 100644 --- a/Marlin/Sanguino/cores/arduino/wiring_private.h +++ b/Marlin/Sanguino/cores/arduino/wiring_private.h @@ -24,7 +24,7 @@ #ifndef WiringPrivate_h #define WiringPrivate_h - +#include #include #include #include diff --git a/Marlin/pins.h b/Marlin/pins.h index fbb4f194c9..60dd6e5148 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -427,6 +427,7 @@ #define TX_ENABLE_PIN 12 #define RX_ENABLE_PIN 13 + #endif /**************************************************************************************** diff --git a/Marlin/planner.h b/Marlin/planner.h index 741c6f9022..05bef3a230 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -23,7 +23,7 @@ #ifndef planner_h #define planner_h - +#include #include "Configuration.h" #include "Marlin.h" From 0bc9daa4f7636858cdcff66e847cc414b18bb51b Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 1 Dec 2011 16:38:01 +0100 Subject: [PATCH 125/228] make it compile with arduino 1.0 ; function is still untested. --- Marlin/Marlin.h | 7 +- Marlin/MarlinSerial.cpp | 6 +- Marlin/Sd2Card.cpp | 1284 +++++++++++++++++++-------------------- Marlin/SdBaseFile.h | 4 +- Marlin/SdFatUtil.h | 5 +- Marlin/SdFile.cpp | 7 +- Marlin/SdFile.h | 7 +- Marlin/planner.h | 6 +- 8 files changed, 675 insertions(+), 651 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 574a85ec53..8afc87bc99 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -5,7 +5,12 @@ // Licence: GPL #define HardwareSerial_h // trick to disable the standard HWserial #include -#include +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + #include "fastio.h" #include #include "Configuration.h" diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index 854c4a824b..54db90732e 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -25,7 +25,11 @@ #include #include #include -#include "wiring.h" +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "wiring.h" +#endif #include "wiring_private.h" // this next line disables the entire HardwareSerial.cpp, diff --git a/Marlin/Sd2Card.cpp b/Marlin/Sd2Card.cpp index 4ca641ef9b..d7f018e4b9 100644 --- a/Marlin/Sd2Card.cpp +++ b/Marlin/Sd2Card.cpp @@ -1,643 +1,643 @@ -/* Arduino Sd2Card Library - * Copyright (C) 2009 by William Greiman - * - * This file is part of the Arduino Sd2Card Library - * - * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see - * . - */ -#if ARDUINO < 100 -#define HardwareSerial_h // trick to disable the standard HWserial -#include -#else // ARDUINO -#include -#endif // ARDUINO -#include "Sd2Card.h" -//------------------------------------------------------------------------------ -#ifndef SOFTWARE_SPI -// functions for hardware SPI -//------------------------------------------------------------------------------ -// make sure SPCR rate is in expected bits -#if (SPR0 != 0 || SPR1 != 1) -#error unexpected SPCR bits -#endif -/** - * Initialize hardware SPI - * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6] - */ -static void spiInit(uint8_t spiRate) { - // See avr processor documentation - SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1); - SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X; -} -//------------------------------------------------------------------------------ -/** SPI receive a byte */ -static uint8_t spiRec() { - SPDR = 0XFF; - while (!(SPSR & (1 << SPIF))); - return SPDR; -} -//------------------------------------------------------------------------------ -/** SPI read data - only one call so force inline */ -static inline __attribute__((always_inline)) - void spiRead(uint8_t* buf, uint16_t nbyte) { - if (nbyte-- == 0) return; - SPDR = 0XFF; - for (uint16_t i = 0; i < nbyte; i++) { - while (!(SPSR & (1 << SPIF))); - buf[i] = SPDR; - SPDR = 0XFF; - } - while (!(SPSR & (1 << SPIF))); - buf[nbyte] = SPDR; -} -//------------------------------------------------------------------------------ -/** SPI send a byte */ -static void spiSend(uint8_t b) { - SPDR = b; - while (!(SPSR & (1 << SPIF))); -} -//------------------------------------------------------------------------------ -/** SPI send block - only one call so force inline */ -static inline __attribute__((always_inline)) - void spiSendBlock(uint8_t token, const uint8_t* buf) { - SPDR = token; - for (uint16_t i = 0; i < 512; i += 2) { - while (!(SPSR & (1 << SPIF))); - SPDR = buf[i]; - while (!(SPSR & (1 << SPIF))); - SPDR = buf[i + 1]; - } - while (!(SPSR & (1 << SPIF))); -} -//------------------------------------------------------------------------------ -#else // SOFTWARE_SPI -//------------------------------------------------------------------------------ -/** nop to tune soft SPI timing */ -#define nop asm volatile ("nop\n\t") -//------------------------------------------------------------------------------ -/** Soft SPI receive byte */ -static uint8_t spiRec() { - uint8_t data = 0; - // no interrupts during byte receive - about 8 us - cli(); - // output pin high - like sending 0XFF - fastDigitalWrite(SPI_MOSI_PIN, HIGH); - - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, HIGH); - - // adjust so SCK is nice - nop; - nop; - - data <<= 1; - - if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; - - fastDigitalWrite(SPI_SCK_PIN, LOW); - } - // enable interrupts - sei(); - return data; -} -//------------------------------------------------------------------------------ -/** Soft SPI read data */ -static void spiRead(uint8_t* buf, uint16_t nbyte) { - for (uint16_t i = 0; i < nbyte; i++) { - buf[i] = spiRec(); - } -} -//------------------------------------------------------------------------------ -/** Soft SPI send byte */ -static void spiSend(uint8_t data) { - // no interrupts during byte send - about 8 us - cli(); - for (uint8_t i = 0; i < 8; i++) { - fastDigitalWrite(SPI_SCK_PIN, LOW); - - fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); - - data <<= 1; - - fastDigitalWrite(SPI_SCK_PIN, HIGH); - } - // hold SCK high for a few ns - nop; - nop; - nop; - nop; - - fastDigitalWrite(SPI_SCK_PIN, LOW); - // enable interrupts - sei(); -} -//------------------------------------------------------------------------------ -/** Soft SPI send block */ - void spiSendBlock(uint8_t token, const uint8_t* buf) { - spiSend(token); - for (uint16_t i = 0; i < 512; i++) { - spiSend(buf[i]); - } -} -#endif // SOFTWARE_SPI -//------------------------------------------------------------------------------ -// send command and return error code. Return zero for OK -uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { - // select card - chipSelectLow(); - - // wait up to 300 ms if busy - waitNotBusy(300); - - // send command - spiSend(cmd | 0x40); - - // send argument - for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); - - // send CRC - uint8_t crc = 0XFF; - if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 - if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA - spiSend(crc); - - // skip stuff byte for stop read - if (cmd == CMD12) spiRec(); - - // wait for response - for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); - return status_; -} -//------------------------------------------------------------------------------ -/** - * Determine the size of an SD flash memory card. - * - * \return The number of 512 byte data blocks in the card - * or zero if an error occurs. - */ -uint32_t Sd2Card::cardSize() { - csd_t csd; - if (!readCSD(&csd)) return 0; - if (csd.v1.csd_ver == 0) { - uint8_t read_bl_len = csd.v1.read_bl_len; - uint16_t c_size = (csd.v1.c_size_high << 10) - | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; - uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) - | csd.v1.c_size_mult_low; - return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); - } else if (csd.v2.csd_ver == 1) { - uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) - | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; - return (c_size + 1) << 10; - } else { - error(SD_CARD_ERROR_BAD_CSD); - return 0; - } -} -//------------------------------------------------------------------------------ -void Sd2Card::chipSelectHigh() { - digitalWrite(chipSelectPin_, HIGH); -} -//------------------------------------------------------------------------------ -void Sd2Card::chipSelectLow() { -#ifndef SOFTWARE_SPI - spiInit(spiRate_); -#endif // SOFTWARE_SPI - digitalWrite(chipSelectPin_, LOW); -} -//------------------------------------------------------------------------------ -/** Erase a range of blocks. - * - * \param[in] firstBlock The address of the first block in the range. - * \param[in] lastBlock The address of the last block in the range. - * - * \note This function requests the SD card to do a flash erase for a - * range of blocks. The data on the card after an erase operation is - * either 0 or 1, depends on the card vendor. The card must support - * single block erase. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { - csd_t csd; - if (!readCSD(&csd)) goto fail; - // check for single block erase - if (!csd.v1.erase_blk_en) { - // erase size mask - uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; - if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { - // error card can't erase specified area - error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); - goto fail; - } - } - if (type_ != SD_CARD_TYPE_SDHC) { - firstBlock <<= 9; - lastBlock <<= 9; - } - if (cardCommand(CMD32, firstBlock) - || cardCommand(CMD33, lastBlock) - || cardCommand(CMD38, 0)) { - error(SD_CARD_ERROR_ERASE); - goto fail; - } - if (!waitNotBusy(SD_ERASE_TIMEOUT)) { - error(SD_CARD_ERROR_ERASE_TIMEOUT); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Determine if card supports single block erase. - * - * \return The value one, true, is returned if single block erase is supported. - * The value zero, false, is returned if single block erase is not supported. - */ -bool Sd2Card::eraseSingleBlockEnable() { - csd_t csd; - return readCSD(&csd) ? csd.v1.erase_blk_en : false; -} -//------------------------------------------------------------------------------ -/** - * Initialize an SD flash memory card. - * - * \param[in] sckRateID SPI clock rate selector. See setSckRate(). - * \param[in] chipSelectPin SD chip select pin number. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. The reason for failure - * can be determined by calling errorCode() and errorData(). - */ -bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { - errorCode_ = type_ = 0; - chipSelectPin_ = chipSelectPin; - // 16-bit init start time allows over a minute - uint16_t t0 = (uint16_t)millis(); - uint32_t arg; - - // set pin modes - pinMode(chipSelectPin_, OUTPUT); - chipSelectHigh(); - pinMode(SPI_MISO_PIN, INPUT); - pinMode(SPI_MOSI_PIN, OUTPUT); - pinMode(SPI_SCK_PIN, OUTPUT); - -#ifndef SOFTWARE_SPI - // SS must be in output mode even it is not chip select - pinMode(SS_PIN, OUTPUT); - // set SS high - may be chip select for another SPI device -#if SET_SPI_SS_HIGH - digitalWrite(SS_PIN, HIGH); -#endif // SET_SPI_SS_HIGH - // set SCK rate for initialization commands - spiRate_ = SPI_SD_INIT_RATE; - spiInit(spiRate_); -#endif // SOFTWARE_SPI - - // must supply min of 74 clock cycles with CS high. - for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); - - // command to go idle in SPI mode - while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_CMD0); - goto fail; - } - } - // check SD version - if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { - type(SD_CARD_TYPE_SD1); - } else { - // only need last byte of r7 response - for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); - if (status_ != 0XAA) { - error(SD_CARD_ERROR_CMD8); - goto fail; - } - type(SD_CARD_TYPE_SD2); - } - // initialize card and send host supports SDHC if SD2 - arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; - - while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { - // check for timeout - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_ACMD41); - goto fail; - } - } - // if SD2 read OCR register to check for SDHC card - if (type() == SD_CARD_TYPE_SD2) { - if (cardCommand(CMD58, 0)) { - error(SD_CARD_ERROR_CMD58); - goto fail; - } - if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); - // discard rest of ocr - contains allowed voltage range - for (uint8_t i = 0; i < 3; i++) spiRec(); - } - chipSelectHigh(); - -#ifndef SOFTWARE_SPI - return setSckRate(sckRateID); -#else // SOFTWARE_SPI - return true; -#endif // SOFTWARE_SPI - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - * Read a 512 byte block from an SD card. - * - * \param[in] blockNumber Logical block to be read. - * \param[out] dst Pointer to the location that will receive the data. - - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) { - // use address if not SDHC card - if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD17, blockNumber)) { - error(SD_CARD_ERROR_CMD17); - goto fail; - } - return readData(dst, 512); - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Read one data block in a multiple block read sequence - * - * \param[in] dst Pointer to the location for the data to be read. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readData(uint8_t *dst) { - chipSelectLow(); - return readData(dst, 512); -} -//------------------------------------------------------------------------------ -bool Sd2Card::readData(uint8_t* dst, uint16_t count) { - // wait for start block token - uint16_t t0 = millis(); - while ((status_ = spiRec()) == 0XFF) { - if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) { - error(SD_CARD_ERROR_READ_TIMEOUT); - goto fail; - } - } - if (status_ != DATA_START_BLOCK) { - error(SD_CARD_ERROR_READ); - goto fail; - } - // transfer data - spiRead(dst, count); - - // discard CRC - spiRec(); - spiRec(); - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** read CID or CSR register */ -bool Sd2Card::readRegister(uint8_t cmd, void* buf) { - uint8_t* dst = reinterpret_cast(buf); - if (cardCommand(cmd, 0)) { - error(SD_CARD_ERROR_READ_REG); - goto fail; - } - return readData(dst, 16); - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Start a read multiple blocks sequence. - * - * \param[in] blockNumber Address of first block in sequence. - * - * \note This function is used with readData() and readStop() for optimized - * multiple block reads. SPI chipSelect must be low for the entire sequence. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readStart(uint32_t blockNumber) { - if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD18, blockNumber)) { - error(SD_CARD_ERROR_CMD18); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** End a read multiple blocks sequence. - * -* \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::readStop() { - chipSelectLow(); - if (cardCommand(CMD12, 0)) { - error(SD_CARD_ERROR_CMD12); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** - * Set the SPI clock rate. - * - * \param[in] sckRateID A value in the range [0, 6]. - * - * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum - * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 - * for \a scsRateID = 6. - * - * \return The value one, true, is returned for success and the value zero, - * false, is returned for an invalid value of \a sckRateID. - */ -bool Sd2Card::setSckRate(uint8_t sckRateID) { - if (sckRateID > 6) { - error(SD_CARD_ERROR_SCK_RATE); - return false; - } - spiRate_ = sckRateID; - return true; -} -//------------------------------------------------------------------------------ -// wait for card to go not busy -bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) { - uint16_t t0 = millis(); - while (spiRec() != 0XFF) { - if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail; - } - return true; - - fail: - return false; -} -//------------------------------------------------------------------------------ -/** - * Writes a 512 byte block to an SD card. - * - * \param[in] blockNumber Logical block to be written. - * \param[in] src Pointer to the location of the data to be written. - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD24, blockNumber)) { - error(SD_CARD_ERROR_CMD24); - goto fail; - } - if (!writeData(DATA_START_BLOCK, src)) goto fail; - - // wait for flash programming to complete - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_TIMEOUT); - goto fail; - } - // response is r2 so get and check two bytes for nonzero - if (cardCommand(CMD13, 0) || spiRec()) { - error(SD_CARD_ERROR_WRITE_PROGRAMMING); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Write one data block in a multiple block write sequence - * \param[in] src Pointer to the location of the data to be written. - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeData(const uint8_t* src) { - chipSelectLow(); - // wait for previous write to finish - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail; - chipSelectHigh(); - return true; - - fail: - error(SD_CARD_ERROR_WRITE_MULTIPLE); - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -// send one block of data for write block or write multiple blocks -bool Sd2Card::writeData(uint8_t token, const uint8_t* src) { - spiSendBlock(token, src); - - spiSend(0xff); // dummy crc - spiSend(0xff); // dummy crc - - status_ = spiRec(); - if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { - error(SD_CARD_ERROR_WRITE); - goto fail; - } - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** Start a write multiple blocks sequence. - * - * \param[in] blockNumber Address of first block in sequence. - * \param[in] eraseCount The number of blocks to be pre-erased. - * - * \note This function is used with writeData() and writeStop() - * for optimized multiple block writes. - * - * \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { - // send pre-erase count - if (cardAcmd(ACMD23, eraseCount)) { - error(SD_CARD_ERROR_ACMD23); - goto fail; - } - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; - if (cardCommand(CMD25, blockNumber)) { - error(SD_CARD_ERROR_CMD25); - goto fail; - } - chipSelectHigh(); - return true; - - fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** End a write multiple blocks sequence. - * -* \return The value one, true, is returned for success and - * the value zero, false, is returned for failure. - */ -bool Sd2Card::writeStop() { - chipSelectLow(); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - spiSend(STOP_TRAN_TOKEN); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; - chipSelectHigh(); - return true; - - fail: - error(SD_CARD_ERROR_STOP_TRAN); - chipSelectHigh(); - return false; +/* Arduino Sd2Card Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino Sd2Card Library + * + * This Library 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 Library 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 the Arduino Sd2Card Library. If not, see + * . + */ +#define HardwareSerial_h // trick to disable the standard HWserial +#if ARDUINO < 100 +#include +#else // ARDUINO +#include +#endif // ARDUINO +#include "Sd2Card.h" +//------------------------------------------------------------------------------ +#ifndef SOFTWARE_SPI +// functions for hardware SPI +//------------------------------------------------------------------------------ +// make sure SPCR rate is in expected bits +#if (SPR0 != 0 || SPR1 != 1) +#error unexpected SPCR bits +#endif +/** + * Initialize hardware SPI + * Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6] + */ +static void spiInit(uint8_t spiRate) { + // See avr processor documentation + SPCR = (1 << SPE) | (1 << MSTR) | (spiRate >> 1); + SPSR = spiRate & 1 || spiRate == 6 ? 0 : 1 << SPI2X; +} +//------------------------------------------------------------------------------ +/** SPI receive a byte */ +static uint8_t spiRec() { + SPDR = 0XFF; + while (!(SPSR & (1 << SPIF))); + return SPDR; +} +//------------------------------------------------------------------------------ +/** SPI read data - only one call so force inline */ +static inline __attribute__((always_inline)) + void spiRead(uint8_t* buf, uint16_t nbyte) { + if (nbyte-- == 0) return; + SPDR = 0XFF; + for (uint16_t i = 0; i < nbyte; i++) { + while (!(SPSR & (1 << SPIF))); + buf[i] = SPDR; + SPDR = 0XFF; + } + while (!(SPSR & (1 << SPIF))); + buf[nbyte] = SPDR; +} +//------------------------------------------------------------------------------ +/** SPI send a byte */ +static void spiSend(uint8_t b) { + SPDR = b; + while (!(SPSR & (1 << SPIF))); +} +//------------------------------------------------------------------------------ +/** SPI send block - only one call so force inline */ +static inline __attribute__((always_inline)) + void spiSendBlock(uint8_t token, const uint8_t* buf) { + SPDR = token; + for (uint16_t i = 0; i < 512; i += 2) { + while (!(SPSR & (1 << SPIF))); + SPDR = buf[i]; + while (!(SPSR & (1 << SPIF))); + SPDR = buf[i + 1]; + } + while (!(SPSR & (1 << SPIF))); +} +//------------------------------------------------------------------------------ +#else // SOFTWARE_SPI +//------------------------------------------------------------------------------ +/** nop to tune soft SPI timing */ +#define nop asm volatile ("nop\n\t") +//------------------------------------------------------------------------------ +/** Soft SPI receive byte */ +static uint8_t spiRec() { + uint8_t data = 0; + // no interrupts during byte receive - about 8 us + cli(); + // output pin high - like sending 0XFF + fastDigitalWrite(SPI_MOSI_PIN, HIGH); + + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, HIGH); + + // adjust so SCK is nice + nop; + nop; + + data <<= 1; + + if (fastDigitalRead(SPI_MISO_PIN)) data |= 1; + + fastDigitalWrite(SPI_SCK_PIN, LOW); + } + // enable interrupts + sei(); + return data; +} +//------------------------------------------------------------------------------ +/** Soft SPI read data */ +static void spiRead(uint8_t* buf, uint16_t nbyte) { + for (uint16_t i = 0; i < nbyte; i++) { + buf[i] = spiRec(); + } +} +//------------------------------------------------------------------------------ +/** Soft SPI send byte */ +static void spiSend(uint8_t data) { + // no interrupts during byte send - about 8 us + cli(); + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, LOW); + + fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); + + data <<= 1; + + fastDigitalWrite(SPI_SCK_PIN, HIGH); + } + // hold SCK high for a few ns + nop; + nop; + nop; + nop; + + fastDigitalWrite(SPI_SCK_PIN, LOW); + // enable interrupts + sei(); +} +//------------------------------------------------------------------------------ +/** Soft SPI send block */ + void spiSendBlock(uint8_t token, const uint8_t* buf) { + spiSend(token); + for (uint16_t i = 0; i < 512; i++) { + spiSend(buf[i]); + } +} +#endif // SOFTWARE_SPI +//------------------------------------------------------------------------------ +// send command and return error code. Return zero for OK +uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { + // select card + chipSelectLow(); + + // wait up to 300 ms if busy + waitNotBusy(300); + + // send command + spiSend(cmd | 0x40); + + // send argument + for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); + + // send CRC + uint8_t crc = 0XFF; + if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0 + if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA + spiSend(crc); + + // skip stuff byte for stop read + if (cmd == CMD12) spiRec(); + + // wait for response + for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); + return status_; +} +//------------------------------------------------------------------------------ +/** + * Determine the size of an SD flash memory card. + * + * \return The number of 512 byte data blocks in the card + * or zero if an error occurs. + */ +uint32_t Sd2Card::cardSize() { + csd_t csd; + if (!readCSD(&csd)) return 0; + if (csd.v1.csd_ver == 0) { + uint8_t read_bl_len = csd.v1.read_bl_len; + uint16_t c_size = (csd.v1.c_size_high << 10) + | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; + uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) + | csd.v1.c_size_mult_low; + return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); + } else if (csd.v2.csd_ver == 1) { + uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) + | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; + return (c_size + 1) << 10; + } else { + error(SD_CARD_ERROR_BAD_CSD); + return 0; + } +} +//------------------------------------------------------------------------------ +void Sd2Card::chipSelectHigh() { + digitalWrite(chipSelectPin_, HIGH); +} +//------------------------------------------------------------------------------ +void Sd2Card::chipSelectLow() { +#ifndef SOFTWARE_SPI + spiInit(spiRate_); +#endif // SOFTWARE_SPI + digitalWrite(chipSelectPin_, LOW); +} +//------------------------------------------------------------------------------ +/** Erase a range of blocks. + * + * \param[in] firstBlock The address of the first block in the range. + * \param[in] lastBlock The address of the last block in the range. + * + * \note This function requests the SD card to do a flash erase for a + * range of blocks. The data on the card after an erase operation is + * either 0 or 1, depends on the card vendor. The card must support + * single block erase. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { + csd_t csd; + if (!readCSD(&csd)) goto fail; + // check for single block erase + if (!csd.v1.erase_blk_en) { + // erase size mask + uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; + if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { + // error card can't erase specified area + error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); + goto fail; + } + } + if (type_ != SD_CARD_TYPE_SDHC) { + firstBlock <<= 9; + lastBlock <<= 9; + } + if (cardCommand(CMD32, firstBlock) + || cardCommand(CMD33, lastBlock) + || cardCommand(CMD38, 0)) { + error(SD_CARD_ERROR_ERASE); + goto fail; + } + if (!waitNotBusy(SD_ERASE_TIMEOUT)) { + error(SD_CARD_ERROR_ERASE_TIMEOUT); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Determine if card supports single block erase. + * + * \return The value one, true, is returned if single block erase is supported. + * The value zero, false, is returned if single block erase is not supported. + */ +bool Sd2Card::eraseSingleBlockEnable() { + csd_t csd; + return readCSD(&csd) ? csd.v1.erase_blk_en : false; +} +//------------------------------------------------------------------------------ +/** + * Initialize an SD flash memory card. + * + * \param[in] sckRateID SPI clock rate selector. See setSckRate(). + * \param[in] chipSelectPin SD chip select pin number. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. The reason for failure + * can be determined by calling errorCode() and errorData(). + */ +bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { + errorCode_ = type_ = 0; + chipSelectPin_ = chipSelectPin; + // 16-bit init start time allows over a minute + uint16_t t0 = (uint16_t)millis(); + uint32_t arg; + + // set pin modes + pinMode(chipSelectPin_, OUTPUT); + chipSelectHigh(); + pinMode(SPI_MISO_PIN, INPUT); + pinMode(SPI_MOSI_PIN, OUTPUT); + pinMode(SPI_SCK_PIN, OUTPUT); + +#ifndef SOFTWARE_SPI + // SS must be in output mode even it is not chip select + pinMode(SS_PIN, OUTPUT); + // set SS high - may be chip select for another SPI device +#if SET_SPI_SS_HIGH + digitalWrite(SS_PIN, HIGH); +#endif // SET_SPI_SS_HIGH + // set SCK rate for initialization commands + spiRate_ = SPI_SD_INIT_RATE; + spiInit(spiRate_); +#endif // SOFTWARE_SPI + + // must supply min of 74 clock cycles with CS high. + for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); + + // command to go idle in SPI mode + while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { + if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_CMD0); + goto fail; + } + } + // check SD version + if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { + type(SD_CARD_TYPE_SD1); + } else { + // only need last byte of r7 response + for (uint8_t i = 0; i < 4; i++) status_ = spiRec(); + if (status_ != 0XAA) { + error(SD_CARD_ERROR_CMD8); + goto fail; + } + type(SD_CARD_TYPE_SD2); + } + // initialize card and send host supports SDHC if SD2 + arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; + + while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { + // check for timeout + if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_ACMD41); + goto fail; + } + } + // if SD2 read OCR register to check for SDHC card + if (type() == SD_CARD_TYPE_SD2) { + if (cardCommand(CMD58, 0)) { + error(SD_CARD_ERROR_CMD58); + goto fail; + } + if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC); + // discard rest of ocr - contains allowed voltage range + for (uint8_t i = 0; i < 3; i++) spiRec(); + } + chipSelectHigh(); + +#ifndef SOFTWARE_SPI + return setSckRate(sckRateID); +#else // SOFTWARE_SPI + return true; +#endif // SOFTWARE_SPI + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + * Read a 512 byte block from an SD card. + * + * \param[in] blockNumber Logical block to be read. + * \param[out] dst Pointer to the location that will receive the data. + + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) { + // use address if not SDHC card + if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD17, blockNumber)) { + error(SD_CARD_ERROR_CMD17); + goto fail; + } + return readData(dst, 512); + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Read one data block in a multiple block read sequence + * + * \param[in] dst Pointer to the location for the data to be read. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readData(uint8_t *dst) { + chipSelectLow(); + return readData(dst, 512); +} +//------------------------------------------------------------------------------ +bool Sd2Card::readData(uint8_t* dst, uint16_t count) { + // wait for start block token + uint16_t t0 = millis(); + while ((status_ = spiRec()) == 0XFF) { + if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) { + error(SD_CARD_ERROR_READ_TIMEOUT); + goto fail; + } + } + if (status_ != DATA_START_BLOCK) { + error(SD_CARD_ERROR_READ); + goto fail; + } + // transfer data + spiRead(dst, count); + + // discard CRC + spiRec(); + spiRec(); + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** read CID or CSR register */ +bool Sd2Card::readRegister(uint8_t cmd, void* buf) { + uint8_t* dst = reinterpret_cast(buf); + if (cardCommand(cmd, 0)) { + error(SD_CARD_ERROR_READ_REG); + goto fail; + } + return readData(dst, 16); + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Start a read multiple blocks sequence. + * + * \param[in] blockNumber Address of first block in sequence. + * + * \note This function is used with readData() and readStop() for optimized + * multiple block reads. SPI chipSelect must be low for the entire sequence. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readStart(uint32_t blockNumber) { + if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD18, blockNumber)) { + error(SD_CARD_ERROR_CMD18); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** End a read multiple blocks sequence. + * +* \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::readStop() { + chipSelectLow(); + if (cardCommand(CMD12, 0)) { + error(SD_CARD_ERROR_CMD12); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + * Set the SPI clock rate. + * + * \param[in] sckRateID A value in the range [0, 6]. + * + * The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum + * SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 + * for \a scsRateID = 6. + * + * \return The value one, true, is returned for success and the value zero, + * false, is returned for an invalid value of \a sckRateID. + */ +bool Sd2Card::setSckRate(uint8_t sckRateID) { + if (sckRateID > 6) { + error(SD_CARD_ERROR_SCK_RATE); + return false; + } + spiRate_ = sckRateID; + return true; +} +//------------------------------------------------------------------------------ +// wait for card to go not busy +bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) { + uint16_t t0 = millis(); + while (spiRec() != 0XFF) { + if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail; + } + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +/** + * Writes a 512 byte block to an SD card. + * + * \param[in] blockNumber Logical block to be written. + * \param[in] src Pointer to the location of the data to be written. + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) { + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD24, blockNumber)) { + error(SD_CARD_ERROR_CMD24); + goto fail; + } + if (!writeData(DATA_START_BLOCK, src)) goto fail; + + // wait for flash programming to complete + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + error(SD_CARD_ERROR_WRITE_TIMEOUT); + goto fail; + } + // response is r2 so get and check two bytes for nonzero + if (cardCommand(CMD13, 0) || spiRec()) { + error(SD_CARD_ERROR_WRITE_PROGRAMMING); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Write one data block in a multiple block write sequence + * \param[in] src Pointer to the location of the data to be written. + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeData(const uint8_t* src) { + chipSelectLow(); + // wait for previous write to finish + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail; + chipSelectHigh(); + return true; + + fail: + error(SD_CARD_ERROR_WRITE_MULTIPLE); + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +// send one block of data for write block or write multiple blocks +bool Sd2Card::writeData(uint8_t token, const uint8_t* src) { + spiSendBlock(token, src); + + spiSend(0xff); // dummy crc + spiSend(0xff); // dummy crc + + status_ = spiRec(); + if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { + error(SD_CARD_ERROR_WRITE); + goto fail; + } + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Start a write multiple blocks sequence. + * + * \param[in] blockNumber Address of first block in sequence. + * \param[in] eraseCount The number of blocks to be pre-erased. + * + * \note This function is used with writeData() and writeStop() + * for optimized multiple block writes. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { + // send pre-erase count + if (cardAcmd(ACMD23, eraseCount)) { + error(SD_CARD_ERROR_ACMD23); + goto fail; + } + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; + if (cardCommand(CMD25, blockNumber)) { + error(SD_CARD_ERROR_CMD25); + goto fail; + } + chipSelectHigh(); + return true; + + fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** End a write multiple blocks sequence. + * +* \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +bool Sd2Card::writeStop() { + chipSelectLow(); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + spiSend(STOP_TRAN_TOKEN); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail; + chipSelectHigh(); + return true; + + fail: + error(SD_CARD_ERROR_STOP_TRAN); + chipSelectHigh(); + return false; } diff --git a/Marlin/SdBaseFile.h b/Marlin/SdBaseFile.h index e184acd968..f5c5e4de3f 100644 --- a/Marlin/SdBaseFile.h +++ b/Marlin/SdBaseFile.h @@ -24,13 +24,13 @@ * \brief SdBaseFile class */ #include -#if ARDUINO < 100 #define HardwareSerial_h // trick to disable the standard HWserial +#if ARDUINO < 100 #include -#include "MarlinSerial.h" #else // ARDUINO #include #endif // ARDUINO +#include "MarlinSerial.h" #include "SdFatConfig.h" #include "SdVolume.h" //------------------------------------------------------------------------------ diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index 6e3cb4936f..fc7a17e5bc 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -24,13 +24,14 @@ * \brief Useful utility functions. */ #include -#if ARDUINO < 100 + #define HardwareSerial_h // trick to disable the standard HWserial +#if ARDUINO < 100 #include -#include "MarlinSerial.h" #else // ARDUINO #include #endif // ARDUINO +#include "MarlinSerial.h" /** Store and print a string in flash memory.*/ #define PgmPrint(x) SerialPrint_P(PSTR(x)) /** Store and print a string in flash memory followed by a CR/LF.*/ diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index 0496a6ab9f..68f14b1933 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -51,7 +51,12 @@ int16_t SdFile::write(const void* buf, uint16_t nbyte) { * \param[in] b the byte to be written. * Use writeError to check for errors. */ -void SdFile::write(uint8_t b) { +#if ARDUINO >= 100 + size_t SdFile::write(uint8_t b) +#else + void SdFile::write(uint8_t b) +#endif +{ SdBaseFile::write(&b, 1); } //------------------------------------------------------------------------------ diff --git a/Marlin/SdFile.h b/Marlin/SdFile.h index e59bb8abe5..931486285b 100644 --- a/Marlin/SdFile.h +++ b/Marlin/SdFile.h @@ -34,7 +34,12 @@ class SdFile : public SdBaseFile, public Print { public: SdFile() {} SdFile(const char* name, uint8_t oflag); - void write(uint8_t b); + #if ARDUINO >= 100 + size_t write(uint8_t b); +#else + void write(uint8_t b); +#endif + int16_t write(const void* buf, uint16_t nbyte); void write(const char* str); void write_P(PGM_P str); diff --git a/Marlin/planner.h b/Marlin/planner.h index 05bef3a230..703bbe9fd9 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -101,7 +101,11 @@ extern uint8_t active_extruder; /////semi-private stuff -#include +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed From 6b86f1568607acc39dccea40647374f6f373f3e7 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Fri, 2 Dec 2011 17:45:05 +0100 Subject: [PATCH 126/228] More 2nd extruder implementation. (Not usable) Advance (not tested) --- Marlin/Configuration.h | 4 +-- Marlin/planner.cpp | 15 ++++++++--- Marlin/planner.h | 9 ++++--- Marlin/stepper.cpp | 59 +++++++++++++++++++++++------------------- 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 483b8cf837..066e610058 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -223,11 +223,11 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} //sells mendel with v9 extruder -#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 200000} // (mm/sec) +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. #define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts +#define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts #define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate #define DEFAULT_MINTRAVELFEEDRATE 0.0 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index f26ae101b2..1674fcc7d9 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -489,12 +489,21 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa if (target[Z_AXIS] < position[Z_AXIS]) { block->direction_bits |= (1<direction_bits |= (1<active_extruder = extruder; + //enable active axes if(block->steps_x != 0) enable_x(); if(block->steps_y != 0) enable_y(); if(block->steps_z != 0) enable_z(); - if(block->steps_e != 0) enable_e(); - + if(extruder == 0) { + if(block->steps_e != 0) enable_e(); + } + #if (EXTRUDERS > 1) + if(extruder == 1) { + if(block->steps_e != 0) enable_e1(); + } + #endif + float delta_mm[4]; delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; @@ -713,7 +722,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa else { long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (block->speed_e * block->speed_e * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; + (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; block->advance = advance; if(acc_dist == 0) { block->advance_rate = 0; diff --git a/Marlin/planner.h b/Marlin/planner.h index 703bbe9fd9..53ac3d8447 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -37,11 +37,12 @@ typedef struct { long decelerate_after; // The index of the step event on which to start decelerating long acceleration_rate; // The acceleration rate used for acceleration calculation unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) + unsigned char active_extruder; // Selects the active extruder #ifdef ADVANCE -// long advance_rate; -// volatile long initial_advance; -// volatile long final_advance; -// float advance; + long advance_rate; + volatile long initial_advance; + volatile long final_advance; + float advance; #endif // Fields used by the motion planner to manage acceleration diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index fcc0aceecd..0eabc753d7 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -383,8 +383,9 @@ ISR(TIMER1_COMPA_vect) } #endif //!ADVANCE for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) - MSerial.checkRx(); - /* + MSerial.checkRx(); // Check for serial chars. + + #ifdef ADVANCE counter_e += current_block->steps_e; if (counter_e > 0) { counter_e -= current_block->step_event_count; @@ -399,15 +400,11 @@ ISR(TIMER1_COMPA_vect) CRITICAL_SECTION_END; } } - */ - /* // Do E steps + advance steps - CRITICAL_SECTION_START; e_steps += ((advance >> 16) - old_advance); - CRITICAL_SECTION_END; old_advance = advance >> 16; - */ - + #endif //ADVANCE + counter_x += current_block->steps_x; if (counter_x > 0) { WRITE(X_STEP_PIN, HIGH); @@ -461,7 +458,9 @@ ISR(TIMER1_COMPA_vect) OCR1A = timer; acceleration_time += timer; #ifdef ADVANCE - advance += advance_rate; + for(int8_t i=0; i < step_loops; i++) { + advance += advance_rate; + } #endif } else if (step_events_completed > current_block->decelerate_after) { @@ -483,7 +482,9 @@ ISR(TIMER1_COMPA_vect) OCR1A = timer; deceleration_time += timer; #ifdef ADVANCE - advance -= advance_rate; + for(int8_t i=0; i < step_loops; i++) { + advance -= advance_rate; + } if(advance < final_advance) advance = final_advance; #endif //ADVANCE @@ -491,7 +492,7 @@ ISR(TIMER1_COMPA_vect) else { OCR1A = OCR1A_nominal; } - + // If current block is finished, reset pointer if (step_events_completed >= current_block->step_event_count) { current_block = NULL; @@ -506,22 +507,24 @@ ISR(TIMER1_COMPA_vect) // Timer 0 is shared with millies ISR(TIMER0_COMPA_vect) { - // Critical section needed because Timer 1 interrupt has higher priority. - // The pin set functions are placed on trategic position to comply with the stepper driver timing. - WRITE(E_STEP_PIN, LOW); - // Set E direction (Depends on E direction + advance) - if (e_steps < 0) { - WRITE(E_DIR_PIN,INVERT_E_DIR); - e_steps++; - WRITE(E_STEP_PIN, HIGH); - } - if (e_steps > 0) { - WRITE(E_DIR_PIN,!INVERT_E_DIR); - e_steps--; - WRITE(E_STEP_PIN, HIGH); - } - old_OCR0A += 25; // 10kHz interrupt + old_OCR0A += 25; // ~10kHz interrupt OCR0A = old_OCR0A; + // Set E direction (Depends on E direction + advance) + for(unsigned char i=0; i<4;) { + WRITE(E_STEP_PIN, LOW); + if (e_steps == 0) break; + i++; + if (e_steps < 0) { + WRITE(E_DIR_PIN,INVERT_E_DIR); + e_steps++; + WRITE(E_STEP_PIN, HIGH); + } + if (e_steps > 0) { + WRITE(E_DIR_PIN,!INVERT_E_DIR); + e_steps--; + WRITE(E_STEP_PIN, HIGH); + } + } } #endif // ADVANCE @@ -638,6 +641,10 @@ void st_init() ENABLE_STEPPER_DRIVER_INTERRUPT(); #ifdef ADVANCE + #if defined(TCCR0A) && defined(WGM01) + TCCR0A &= ~(1< Date: Sun, 4 Dec 2011 09:02:09 +0100 Subject: [PATCH 127/228] make QUICKHOME configureable --- Marlin/Configuration.h | 1 + Marlin/Marlin.pde | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 066e610058..6f40bbb733 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -214,6 +214,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define X_HOME_RETRACT_MM 5 #define Y_HOME_RETRACT_MM 5 #define Z_HOME_RETRACT_MM 1 +#define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially. #define AXIS_RELATIVE_MODES {false, false, false, false} diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 06fd097766..39f42f0ac6 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -532,7 +532,7 @@ FORCE_INLINE void process_commands() } feedrate = 0.0; home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); - + #ifdef QUICK_HOME if( code_seen(axis_codes[0]) && code_seen(axis_codes[1]) ) //first diagonal move { current_position[X_AXIS] = 0; current_position[Y_AXIS] = 0; @@ -545,6 +545,7 @@ FORCE_INLINE void process_commands() prepare_move(); current_position[X_AXIS] = 0; current_position[Y_AXIS] = 0; } + #endif if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { From dfd240b260cb50fb2a1403211c51e497ef81e9c9 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 4 Dec 2011 09:48:53 +0100 Subject: [PATCH 128/228] overworked autotemp, removed one layer of nesting from the ultralcd. --- Marlin/Marlin.pde | 1 + Marlin/cardreader.pde | 1 + Marlin/planner.cpp | 2 +- Marlin/temperature.h | 10 + Marlin/ultralcd.pde | 887 ++++++++++++++++++++++-------------------- 5 files changed, 470 insertions(+), 431 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 39f42f0ac6..b0e375fd36 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -670,6 +670,7 @@ FORCE_INLINE void process_commands() SERIAL_ECHO_START; SERIAL_ECHOLN(time); LCD_MESSAGE(time); + autotempShutdown(); } break; case 42: //M42 -Change pin status via gcode diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 03f3f46386..d355ea3ef3 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -436,5 +436,6 @@ void CardReader::printingHasFinished() { finishAndDisableSteppers(); } + autotempShutdown(); } #endif //SDSUPPORT \ No newline at end of file diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 1674fcc7d9..bef74a2e89 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -91,7 +91,7 @@ static float previous_nominal_speed; // Nominal speed of previous path line segm #ifdef AUTOTEMP float autotemp_max=250; float autotemp_min=210; - float autotemp_factor=1; + float autotemp_factor=0.1; bool autotemp_enabled=false; #endif diff --git a/Marlin/temperature.h b/Marlin/temperature.h index ba1043b6da..e9395e008c 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -108,6 +108,16 @@ FORCE_INLINE float isCoolingHotend(uint8_t extruder){ }; FORCE_INLINE bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; +FORCE_INLINE void autotempShutdown(){ + #ifdef AUTOTEMP + if(autotemp_enabled) + { + autotemp_enabled=false; + if(degTargetHotend0()>autotemp_min) + setTargetHotend0(0); + } + #endif +} void disable_heater(); void setWatch(); void updatePID(); diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 4ca93aa0c7..54ea809df5 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -503,31 +503,32 @@ void MainMenu::showTune() lcd.setCursor(13,line);lcd.print(ftostr3(feedmultiply)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); { - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=feedmultiply; - } - else - { - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<1) encoderpos=1; - if(encoderpos>400) encoderpos=400; - feedmultiply = encoderpos; - feedmultiplychanged=true; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=feedmultiply; } + else + { + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>400) encoderpos=400; + feedmultiply = encoderpos; + feedmultiplychanged=true; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemT_nozzle: { @@ -537,29 +538,29 @@ void MainMenu::showTune() lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(degTargetHotend0()); - } - else - { - setTargetHotend0(encoderpos); - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=intround(degTargetHotend0()); } + else + { + setTargetHotend0(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); } }break; @@ -571,31 +572,32 @@ void MainMenu::showTune() lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); { - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=fanpwm; - } - else - { - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=fanpwm; } + else + { + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemT_flow://axis_steps_per_unit[i] = code_value(); { @@ -605,34 +607,35 @@ void MainMenu::showTune() lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)axis_steps_per_unit[3]; - } - else - { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); - position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + encoderpos=(int)axis_steps_per_unit[3]; } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + }break; default: break; @@ -688,30 +691,31 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(degTargetHotend0()); - } - else - { - setTargetHotend0(encoderpos); - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=intround(degTargetHotend0()); } + else + { + setTargetHotend0(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; #ifdef AUTOTEMP case ItemCT_autotempmin: @@ -719,33 +723,34 @@ void MainMenu::showControlTemp() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(" \002 Min:"); - lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); + lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_min)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(autotemp_max); - } - else - { - autotemp_max=encoderpos; - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=intround(autotemp_min); } + else + { + autotemp_min=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemCT_autotempmax: { @@ -755,30 +760,31 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(autotemp_max); - } - else - { - autotemp_max=encoderpos; - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=intround(autotemp_max); } + else + { + autotemp_max=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemCT_autotempfact: { @@ -788,30 +794,31 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(autotemp_factor*100); - } - else - { - autotemp_max=encoderpos; - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>99) encoderpos=99; - lcd.setCursor(13,line);lcd.print(ftostr32(encoderpos/100.)); + encoderpos=intround(autotemp_factor*100); } + else + { + autotemp_max=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>99) encoderpos=99; + lcd.setCursor(13,line);lcd.print(ftostr32(encoderpos/100.)); + } + }break; case ItemCT_autotempactive: { @@ -819,20 +826,26 @@ void MainMenu::showControlTemp() { lcd.setCursor(0,line);lcdprintPGM(" Autotemp:"); lcd.setCursor(13,line); - if(autotemp_enabled) - lcdprintPGM("On"); - else - lcdprintPGM("Off"); + if(autotemp_enabled) + lcdprintPGM("On"); + else + lcdprintPGM("Off"); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - autotemp_enabled=!autotemp_enabled; - BLOCK; - } + autotemp_enabled=!autotemp_enabled; + lcd.setCursor(13,line); + if(autotemp_enabled) + lcdprintPGM("On "); + else + lcdprintPGM("Off"); + BLOCK; } + }break; #endif //autotemp case ItemCT_fan: @@ -843,31 +856,32 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); { - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=fanpwm; - } - else - { - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=fanpwm; } + else + { + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemCT_PID_P: { @@ -877,31 +891,32 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(itostr4(Kp)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kp; - } - else - { - Kp= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<1) encoderpos=1; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + encoderpos=(int)Kp; } + else + { + Kp= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + }break; case ItemCT_PID_I: { @@ -911,31 +926,32 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(Ki*10/PID_dT); - } - else - { - Ki= encoderpos/10.*PID_dT; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); + encoderpos=(int)(Ki*10/PID_dT); } + else + { + Ki= encoderpos/10.*PID_dT; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); + } + }break; case ItemCT_PID_D: { @@ -945,31 +961,33 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(Kd/5./PID_dT); - } - else - { - Kd= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + encoderpos=(int)(Kd/5./PID_dT); } + else + { + Kd= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + }break; case ItemCT_PID_C: #ifdef PID_ADD_EXTRUSION_RATE @@ -980,31 +998,32 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(itostr3(Kc)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kc; - } - else - { - Kc= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=(int)Kc; } + else + { + Kc= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } #endif break; @@ -1051,30 +1070,31 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcdprintPGM("00"); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)acceleration/100; - } - else - { - acceleration= encoderpos*100; - encoderpos=activeline*lcdslow; - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<5) encoderpos=5; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + encoderpos=(int)acceleration/100; } + else + { + acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + } + }break; case ItemCM_xyjerk: //max_xy_jerk { @@ -1084,31 +1104,32 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_xy_jerk; - } - else - { - max_xy_jerk= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=(int)max_xy_jerk; } + else + { + max_xy_jerk= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemCM_vmaxx: @@ -1126,31 +1147,32 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx])); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_feedrate[i-ItemCM_vmaxx]; - } - else - { - max_feedrate[i-ItemCM_vmaxx]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=(int)max_feedrate[i-ItemCM_vmaxx]; } + else + { + max_feedrate[i-ItemCM_vmaxx]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemCM_vmin: @@ -1161,31 +1183,32 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(minimumfeedrate); - } - else - { - minimumfeedrate= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=(int)(minimumfeedrate); } + else + { + minimumfeedrate= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemCM_vtravmin: { @@ -1195,31 +1218,32 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate)); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)mintravelfeedrate; - } - else - { - mintravelfeedrate= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + encoderpos=(int)mintravelfeedrate; } + else + { + mintravelfeedrate= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; case ItemCM_amaxx: @@ -1237,30 +1261,31 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));lcdprintPGM("00"); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100; - } - else - { - max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100; - encoderpos=activeline*lcdslow; - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100; } + else + { + max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + } + }break; case ItemCM_aret://float retract_acceleration = 7000; { @@ -1270,31 +1295,32 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00"); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)retract_acceleration/100; - } - else - { - retract_acceleration= encoderpos*100; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<10) encoderpos=10; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + encoderpos=(int)retract_acceleration/100; } + else + { + retract_acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<10) encoderpos=10; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + } + }break; case ItemCM_esteps://axis_steps_per_unit[i] = code_value(); { @@ -1304,34 +1330,35 @@ void MainMenu::showControlMotion() lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); } - if((activeline==line) ) + if((activeline!=line) ) + break; + + if(CLICKED) { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)axis_steps_per_unit[3]; - } - else - { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); - position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } + linechanging=!linechanging; if(linechanging) { - if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + encoderpos=(int)axis_steps_per_unit[3]; } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + }break; default: break; From 7714b98da74b0b84cb620474fd8e4cb19d15bfc0 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 4 Dec 2011 12:40:18 +0100 Subject: [PATCH 129/228] solved some compiler warnings that are now visible in arduino 1.0. Found a couple of unused variables, that I commented. Tried to solve the program memory warning message, and failed. --- Marlin/Marlin.h | 21 +++++++++++++++------ Marlin/Marlin.pde | 3 ++- Marlin/MarlinSerial.cpp | 1 + Marlin/MarlinSerial.h | 2 +- Marlin/cardreader.h | 2 +- Marlin/cardreader.pde | 2 +- Marlin/planner.cpp | 23 +++++++++++++---------- Marlin/stepper.cpp | 7 ++++--- Marlin/stepper.h | 2 +- Marlin/temperature.cpp | 19 ++++++++++++++----- Marlin/temperature.h | 8 +++++--- Marlin/ultralcd.h | 5 ++--- Marlin/ultralcd.pde | 6 +++--- 13 files changed, 63 insertions(+), 38 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 8afc87bc99..910cf46ad3 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -16,7 +16,6 @@ #include "Configuration.h" #include "MarlinSerial.h" - #define FORCE_INLINE __attribute__((always_inline)) inline //#define SERIAL_ECHO(x) Serial << "echo: " << x; //#define SERIAL_ECHOLN(x) Serial << "echo: "< #include #include diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 76d5a35a1f..0fe0c52274 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -120,7 +120,7 @@ class MarlinSerial //: public Stream FORCE_INLINE void print(const String &s) { - for (int i = 0; i < s.length(); i++) { + for (int i = 0; i < (int)s.length(); i++) { write(s[i]); } } diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index c8ef9dbb43..70244a8774 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -59,7 +59,7 @@ private: LsAction lsAction; //stored for recursion. int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. char* diveDirName; - void lsDive(char *prepend,SdFile parent); + void lsDive(const char *prepend,SdFile parent); }; diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index d355ea3ef3..1eb19ba00c 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -40,7 +40,7 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters } -void CardReader::lsDive(char *prepend,SdFile parent) +void CardReader::lsDive(const char *prepend,SdFile parent) { dir_t p; uint8_t cnt=0; diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index bef74a2e89..61f27fc228 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -107,10 +107,12 @@ volatile unsigned char block_buffer_tail; // Index of the block to pro //=============================private variables ============================ //=========================================================================== -// Used for the frequency limit -static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations -static long x_segment_time[3]={0,0,0}; // Segment times (in us). Used for speed calculations -static long y_segment_time[3]={0,0,0}; +#ifdef XY_FREQUENCY_LIMIT + // Used for the frequency limit + static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations + static long x_segment_time[3]={0,0,0}; // Segment times (in us). Used for speed calculations + static long y_segment_time[3]={0,0,0}; +#endif // Returns the index of the next block in the ring buffer // NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. @@ -255,7 +257,7 @@ void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *n // planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This // implements the reverse pass. void planner_reverse_pass() { - char block_index = block_buffer_head; + uint8_t block_index = block_buffer_head; if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); block_t *block[3] = { NULL, NULL, NULL }; @@ -294,7 +296,7 @@ void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *n // planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This // implements the forward pass. void planner_forward_pass() { - char block_index = block_buffer_tail; + uint8_t block_index = block_buffer_tail; block_t *block[3] = { NULL, NULL, NULL }; while(block_index != block_buffer_head) { @@ -384,7 +386,7 @@ void getHighESpeed() return; //do nothing float high=0; - char block_index = block_buffer_tail; + uint8_t block_index = block_buffer_tail; while(block_index != block_buffer_head) { float se=block_buffer[block_index].steps_e/float(block_buffer[block_index].step_event_count)*block_buffer[block_index].nominal_rate; @@ -423,7 +425,7 @@ void check_axes_activity() { block_t *block; if(block_buffer_tail != block_buffer_head) { - char block_index = block_buffer_tail; + uint8_t block_index = block_buffer_tail; while(block_index != block_buffer_head) { block = &block_buffer[block_index]; if(block->steps_x != 0) x_active++; @@ -519,8 +521,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 - // segment time im micro seconds - long segment_time = lround(1000000.0/inverse_second); + if (block->steps_e == 0) { @@ -538,6 +539,8 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa #endif /* + // segment time im micro seconds + long segment_time = lround(1000000.0/inverse_second); if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { if (segment_timeaccelerate_until) { + if (step_events_completed <= (unsigned long int)current_block->accelerate_until) { MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); acc_step_rate += current_block->initial_rate; @@ -463,7 +464,7 @@ ISR(TIMER1_COMPA_vect) } #endif } - else if (step_events_completed > current_block->decelerate_after) { + else if (step_events_completed > (unsigned long int)current_block->decelerate_after) { MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); if(step_rate > acc_step_rate) { // Check step_rate stays positive @@ -678,7 +679,7 @@ void st_set_e_position(const long &e) CRITICAL_SECTION_END; } -long st_get_position(char axis) +long st_get_position(uint8_t axis) { long count_pos; CRITICAL_SECTION_START; diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 73b7efb1cd..e11f5e5a92 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -34,7 +34,7 @@ void st_set_position(const long &x, const long &y, const long &z, const long &e) void st_set_e_position(const long &e); // Get current position in steps -long st_get_position(char axis); +long st_get_position(uint8_t axis); // The stepper subsystem goes to sleep when it runs out of things to execute. Call this // to notify the subsystem that it is time to go to work. diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 93364f8cb0..ac5aeaa3e5 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -67,7 +67,8 @@ int heatingtarget_raw[3]= {0, 0, 0}; //=========================================================================== static bool temp_meas_ready = false; -static unsigned long previous_millis_heater, previous_millis_bed_heater; +static unsigned long previous_millis_bed_heater; +//static unsigned long previous_millis_heater; #ifdef PIDTEMP //static cannot be external: @@ -80,8 +81,8 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; static float pid_error; static float temp_iState_min; static float temp_iState_max; - static float pid_input; - static float pid_output; + // static float pid_input; + // static float pid_output; static bool pid_reset; #endif //PIDTEMP @@ -94,8 +95,8 @@ static unsigned long previous_millis_heater, previous_millis_bed_heater; // Init min and max temp with extreme values to prevent false errors during startup static int minttemp_0 = 0; static int maxttemp_0 = 16383; - static int minttemp_1 = 0; - static int maxttemp_1 = 16383; + //static int minttemp_1 = 0; + //static int maxttemp_1 = 16383; static int bed_minttemp = 0; static int bed_maxttemp = 16383; @@ -268,7 +269,10 @@ int temp2analogBed(int celsius) { return (1023 * OVERSAMPLENR) - raw; #elif defined BED_USES_AD595 return lround(celsius * (1024.0 * OVERSAMPLENR/ (5.0 * 100.0) ) ); + #else + #warning No heater-type defined for the bed. #endif + return 0; } // Derived from RepRap FiveD extruder::getTemperature() @@ -296,6 +300,8 @@ float analog2temp(int raw) { return celsius; #elif defined HEATER_0_USES_AD595 return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #else + #error PLEASE DEFINE HEATER TYPE #endif } @@ -328,7 +334,10 @@ float analog2tempBed(int raw) { #elif defined BED_USES_AD595 return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + #else + #warning No heater-type defined for the bed. #endif + return 0; } void tp_init() diff --git a/Marlin/temperature.h b/Marlin/temperature.h index e9395e008c..623f890bb0 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -86,7 +86,7 @@ FORCE_INLINE void setTargetHotend0(const float &celsius) #endif //PIDTEMP }; FORCE_INLINE void setTargetHotend1(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; -FORCE_INLINE float setTargetHotend(const float &celcius, uint8_t extruder){ +FORCE_INLINE void setTargetHotend(const float &celcius, uint8_t extruder){ if(extruder == 0) setTargetHotend0(celcius); if(extruder == 1) setTargetHotend1(celcius); }; @@ -94,17 +94,19 @@ FORCE_INLINE void setTargetBed(const float &celsius) { target_raw[TEMPSENSO FORCE_INLINE bool isHeatingHotend0() {return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; FORCE_INLINE bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; -FORCE_INLINE float isHeatingHotend(uint8_t extruder){ +FORCE_INLINE bool isHeatingHotend(uint8_t extruder){ if(extruder == 0) return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]; if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1]; + return false; }; FORCE_INLINE bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; FORCE_INLINE bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];}; FORCE_INLINE bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; -FORCE_INLINE float isCoolingHotend(uint8_t extruder){ +FORCE_INLINE bool isCoolingHotend(uint8_t extruder){ if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0]; if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1]; + return false; }; FORCE_INLINE bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 887dc04f25..93fa4895d7 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -1,7 +1,7 @@ #ifndef __ULTRALCDH #define __ULTRALCDH #include "Configuration.h" - +#include "Marlin.h" #ifdef ULTRA_LCD void lcd_status(); @@ -104,7 +104,6 @@ curencoderpos=maxlines*lcdslow; } lastencoderpos=encoderpos=curencoderpos; - int lastactiveline=activeline; activeline=curencoderpos/lcdslow; if(activeline<0) activeline=0; if(activeline>LCD_HEIGHT-1) activeline=LCD_HEIGHT-1; @@ -137,7 +136,7 @@ #define LCD_MESSAGE(x) lcd_status(x); - #define LCD_MESSAGEPGM(x) lcd_statuspgm(PSTR(x)); + #define LCD_MESSAGEPGM(x) lcd_statuspgm(MYPGM(x)); #define LCD_STATUS lcd_status() #else //no lcd #define LCD_STATUS diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 54ea809df5..65ba86f109 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -53,7 +53,7 @@ void lcdProgMemprint(const char *str) ch=pgm_read_byte(++str); } } -#define lcdprintPGM(x) lcdProgMemprint(PSTR(x)) +#define lcdprintPGM(x) lcdProgMemprint(MYPGM(x)) //=========================================================================== @@ -159,8 +159,8 @@ void lcd_status() { #ifdef ULTIPANEL static uint8_t oldbuttons=0; - static long previous_millis_buttons=0; - static long previous_lcdinit=0; + //static long previous_millis_buttons=0; + //static long previous_lcdinit=0; // buttons_check(); // Done in temperature interrupt //previous_millis_buttons=millis(); From af22e9cd38c9684bd64cc7307137abe9efbba6d0 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 4 Dec 2011 19:54:07 +0100 Subject: [PATCH 130/228] Some advance modifications --- Marlin/Configuration.h | 4 ++-- Marlin/planner.cpp | 12 +++++++++--- Marlin/stepper.cpp | 43 +++++++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 066e610058..08bf6ea9e2 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -278,8 +278,8 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #ifdef ADVANCE #define EXTRUDER_ADVANCE_K .3 - #define D_FILAMENT 1.7 - #define STEPS_MM_E 65 + #define D_FILAMENT 2.85 + #define STEPS_MM_E 836 #define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 1674fcc7d9..7a7a35db4d 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -198,7 +198,6 @@ void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exi // block->accelerate_until = accelerate_steps; // block->decelerate_after = accelerate_steps+plateau_steps; - CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section if(block->busy == false) { // Don't update variables if block is busy. block->accelerate_until = accelerate_steps; @@ -482,7 +481,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // Bail if this is a zero-length block if (block->step_event_count <=dropsegments) { return; }; - // Compute direction bits for this block + // Compute direction bits for this block block->direction_bits = 0; if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<direction_bits |= (1<nominal_rate, block->acceleration_st); float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUTION_AREA * EXTRUTION_AREA / 3600.0)*65536; + (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUTION_AREA * EXTRUTION_AREA)*256; block->advance = advance; if(acc_dist == 0) { block->advance_rate = 0; @@ -731,6 +730,13 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa block->advance_rate = advance / (float)acc_dist; } } + /* + SERIAL_ECHO_START; + SERIAL_ECHOPGM("advance :"); + SERIAL_ECHO(block->advance/256.0); + SERIAL_ECHOPGM("advance rate :"); + SERIAL_ECHOLN(block->advance_rate/256.0); + */ #endif // ADVANCE diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 0eabc753d7..bcad026fbe 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -55,9 +55,9 @@ static long counter_x, // Counter variables for the bresenham line tracer volatile static unsigned long step_events_completed; // The number of step events executed in the current block #ifdef ADVANCE static long advance_rate, advance, final_advance = 0; - static short old_advance = 0; + static long old_advance = 0; #endif -static short e_steps; +static long e_steps; static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. static long acceleration_time, deceleration_time; //static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; @@ -253,6 +253,9 @@ FORCE_INLINE void trapezoid_generator_reset() { #ifdef ADVANCE advance = current_block->initial_advance; final_advance = current_block->final_advance; + // Do E steps + advance steps + e_steps += ((advance >>8) - old_advance); + old_advance = advance >>8; #endif deceleration_time = 0; // step_rate to timer interval @@ -260,6 +263,17 @@ FORCE_INLINE void trapezoid_generator_reset() { acceleration_time = calc_timer(acc_step_rate); OCR1A = acceleration_time; OCR1A_nominal = calc_timer(current_block->nominal_rate); + +// SERIAL_ECHO_START; +// SERIAL_ECHOPGM("advance :"); +// SERIAL_ECHO(current_block->advance/256.0); +// SERIAL_ECHOPGM("advance rate :"); +// SERIAL_ECHO(current_block->advance_rate/256.0); +// SERIAL_ECHOPGM("initial advance :"); +// SERIAL_ECHO(current_block->initial_advance/256.0); +// SERIAL_ECHOPGM("final advance :"); +// SERIAL_ECHOLN(current_block->final_advance/256.0); + } // "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. @@ -382,6 +396,9 @@ ISR(TIMER1_COMPA_vect) count_direction[E_AXIS]=-1; } #endif //!ADVANCE + + + for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) MSerial.checkRx(); // Check for serial chars. @@ -390,19 +407,12 @@ ISR(TIMER1_COMPA_vect) if (counter_e > 0) { counter_e -= current_block->step_event_count; if ((out_bits & (1<> 16) - old_advance); - old_advance = advance >> 16; #endif //ADVANCE counter_x += current_block->steps_x; @@ -461,6 +471,11 @@ ISR(TIMER1_COMPA_vect) for(int8_t i=0; i < step_loops; i++) { advance += advance_rate; } + //if(advance > current_block->advance) advance = current_block->advance; + // Do E steps + advance steps + e_steps += ((advance >>8) - old_advance); + old_advance = advance >>8; + #endif } else if (step_events_completed > current_block->decelerate_after) { @@ -485,8 +500,10 @@ ISR(TIMER1_COMPA_vect) for(int8_t i=0; i < step_loops; i++) { advance -= advance_rate; } - if(advance < final_advance) - advance = final_advance; + if(advance < final_advance) advance = final_advance; + // Do E steps + advance steps + e_steps += ((advance >>8) - old_advance); + old_advance = advance >>8; #endif //ADVANCE } else { @@ -507,7 +524,7 @@ ISR(TIMER1_COMPA_vect) // Timer 0 is shared with millies ISR(TIMER0_COMPA_vect) { - old_OCR0A += 25; // ~10kHz interrupt + old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz) OCR0A = old_OCR0A; // Set E direction (Depends on E direction + advance) for(unsigned char i=0; i<4;) { @@ -519,7 +536,7 @@ ISR(TIMER1_COMPA_vect) e_steps++; WRITE(E_STEP_PIN, HIGH); } - if (e_steps > 0) { + else if (e_steps > 0) { WRITE(E_DIR_PIN,!INVERT_E_DIR); e_steps--; WRITE(E_STEP_PIN, HIGH); From b99c49ec3b2f03e302926f5665dee7172df2deff Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 4 Dec 2011 20:17:21 +0100 Subject: [PATCH 131/228] Add option to only check endstop when homing --- Marlin/Configuration.h | 1 + Marlin/Marlin.pde | 5 ++ Marlin/stepper.cpp | 136 ++++++++++++++++++++++++----------------- Marlin/stepper.h | 2 + 4 files changed, 89 insertions(+), 55 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f288aba970..e8b960f788 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -170,6 +170,7 @@ const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false +//#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 016702ee36..0a51b1edb8 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -528,6 +528,8 @@ FORCE_INLINE void process_commands() saved_feedmultiply = feedmultiply; feedmultiply = 100; + enable_endstops(true); + for(int8_t i=0; i < NUM_AXIS; i++) { destination[i] = current_position[i]; } @@ -563,6 +565,9 @@ FORCE_INLINE void process_commands() HOMEAXIS(Z); current_position[2]=code_value()+add_homeing[2]; } + #ifdef ENDSTOPS_ONLY_FOR_HOMING + enable_endstops(false); + #endif feedrate = saved_feedrate; feedmultiply = saved_feedmultiply; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index e25d179df8..1f688ff90c 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -79,6 +79,8 @@ static bool old_y_max_endstop=false; static bool old_z_min_endstop=false; static bool old_z_max_endstop=false; +static bool check_endstops = true; + volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0}; volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; @@ -191,6 +193,11 @@ void endstops_hit_on_purpose() endstop_z_hit=false; } +void enable_endstops(bool check) +{ + check_endstops = check; +} + // __________________________ // /| |\ _________________ ^ // / | | \ /| |\ | @@ -309,82 +316,94 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 - bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); - if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { - endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; - } - old_x_min_endstop = x_min_endstop; - #endif + if(check_endstops) { + #if X_MIN_PIN > -1 + bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); + if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; + step_events_completed = current_block->step_event_count; + } + old_x_min_endstop = x_min_endstop; + #endif + } } else { // +direction WRITE(X_DIR_PIN,!INVERT_X_DIR); count_direction[X_AXIS]=1; - #if X_MAX_PIN > -1 - bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING); - if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ - endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; - } - old_x_max_endstop = x_max_endstop; - #endif + if(check_endstops) { + #if X_MAX_PIN > -1 + bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING); + if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; + step_events_completed = current_block->step_event_count; + } + old_x_max_endstop = x_max_endstop; + #endif + } } if ((out_bits & (1< -1 - bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING); - if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { - endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; - endstop_y_hit=true; - step_events_completed = current_block->step_event_count; - } - old_y_min_endstop = y_min_endstop; - #endif + if(check_endstops) { + #if Y_MIN_PIN > -1 + bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING); + if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { + endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; + endstop_y_hit=true; + step_events_completed = current_block->step_event_count; + } + old_y_min_endstop = y_min_endstop; + #endif + } } else { // +direction WRITE(Y_DIR_PIN,!INVERT_Y_DIR); count_direction[Y_AXIS]=1; - #if Y_MAX_PIN > -1 - bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING); - if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ - endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; - endstop_y_hit=true; - step_events_completed = current_block->step_event_count; - } - old_y_max_endstop = y_max_endstop; - #endif + if(check_endstops) { + #if Y_MAX_PIN > -1 + bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING); + if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ + endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; + endstop_y_hit=true; + step_events_completed = current_block->step_event_count; + } + old_y_max_endstop = y_max_endstop; + #endif + } } if ((out_bits & (1< -1 - bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING); - if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { - endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; - endstop_z_hit=true; - step_events_completed = current_block->step_event_count; - } - old_z_min_endstop = z_min_endstop; - #endif + if(check_endstops) { + #if Z_MIN_PIN > -1 + bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING); + if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { + endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; + endstop_z_hit=true; + step_events_completed = current_block->step_event_count; + } + old_z_min_endstop = z_min_endstop; + #endif + } } else { // +direction WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - count_direction[Z_AXIS]=1; - #if Z_MAX_PIN > -1 - bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING); - if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { - endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; - endstop_z_hit=true; - step_events_completed = current_block->step_event_count; - } - old_z_max_endstop = z_max_endstop; - #endif + count_direction[Z_AXIS]=1; + if(check_endstops) { + #if Z_MAX_PIN > -1 + bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING); + if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { + endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; + endstop_z_hit=true; + step_events_completed = current_block->step_event_count; + } + old_z_max_endstop = z_max_endstop; + #endif + } } #ifndef ADVANCE @@ -666,6 +685,13 @@ void st_init() e_steps = 0; TIMSK0 |= (1< Date: Sun, 4 Dec 2011 21:03:02 +0100 Subject: [PATCH 132/228] Update endstops only for homing. (use less resources when not used) --- Marlin/stepper.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 1f688ff90c..9cf8ddd176 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -87,7 +87,12 @@ volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; //=========================================================================== //=============================functions ============================ //=========================================================================== - + +#ifdef ENDSTOPS_ONLY_FOR_HOMING + #define CHECK_ENDSTOPS if(check_endstops) +#else + #define CHECK_ENDSTOPS +#endif // intRes = intIn1 * intIn2 >> 16 // uses: @@ -316,7 +321,8 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { @@ -331,7 +337,8 @@ ISR(TIMER1_COMPA_vect) else { // +direction WRITE(X_DIR_PIN,!INVERT_X_DIR); count_direction[X_AXIS]=1; - if(check_endstops) { + CHECK_ENDSTOPS + { #if X_MAX_PIN > -1 bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING); if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ @@ -347,7 +354,8 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING); if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { @@ -362,7 +370,8 @@ ISR(TIMER1_COMPA_vect) else { // +direction WRITE(Y_DIR_PIN,!INVERT_Y_DIR); count_direction[Y_AXIS]=1; - if(check_endstops) { + CHECK_ENDSTOPS + { #if Y_MAX_PIN > -1 bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING); if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ @@ -378,7 +387,8 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING); if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { @@ -393,7 +403,8 @@ ISR(TIMER1_COMPA_vect) else { // +direction WRITE(Z_DIR_PIN,!INVERT_Z_DIR); count_direction[Z_AXIS]=1; - if(check_endstops) { + CHECK_ENDSTOPS + { #if Z_MAX_PIN > -1 bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING); if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { From cf50ba140fdc1c3ef3e21fa7a83a6cc036d61967 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 4 Dec 2011 22:26:42 +0100 Subject: [PATCH 133/228] added M503 to display eeprom storage, and renamed eeprom routings. This version is compatible with the qtmarlin eeprom-tab. --- Marlin/EEPROMwrite.h | 111 +++++++++++++++++++++++-------------------- Marlin/Marlin.pde | 14 ++++-- Marlin/ultralcd.pde | 6 +-- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 1099d08864..8680a5fdc8 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -39,7 +39,7 @@ template int EEPROM_readAnything(int &ee, T& value) // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. #define EEPROM_VERSION "V04" -FORCE_INLINE void StoreSettings() +inline void EEPROM_StoreSettings() { #ifdef EEPROM_SETTINGS char ver[4]= "000"; @@ -72,7 +72,64 @@ FORCE_INLINE void StoreSettings() #endif //EEPROM_SETTINGS } -FORCE_INLINE void RetrieveSettings(bool def=false) + +inline void EEPROM_printSettings() +{ // if def=true, the default values will be used + #ifdef EEPROM_SETTINGS + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Steps per unit:"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M92 X",axis_steps_per_unit[0]); + SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[1]); + SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[2]); + SERIAL_ECHOPAIR(" E",axis_steps_per_unit[3]); + SERIAL_ECHOLN(""); + + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Maximum feedrates (mm/s):"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M203 X",max_feedrate[0]); + SERIAL_ECHOPAIR(" Y",max_feedrate[1] ); + SERIAL_ECHOPAIR(" Z", max_feedrate[2] ); + SERIAL_ECHOPAIR(" E", max_feedrate[3]); + SERIAL_ECHOLN(""); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Maximum Acceleration (mm/s2):"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M201 X" ,max_acceleration_units_per_sq_second[0] ); + SERIAL_ECHOPAIR(" Y" , max_acceleration_units_per_sq_second[1] ); + SERIAL_ECHOPAIR(" Z" ,max_acceleration_units_per_sq_second[2] ); + SERIAL_ECHOPAIR(" E" ,max_acceleration_units_per_sq_second[3]); + SERIAL_ECHOLN(""); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Acceleration: S=acceleration, T=retract acceleration"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M204 S",acceleration ); + SERIAL_ECHOPAIR(" T" ,retract_acceleration); + SERIAL_ECHOLN(""); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M205 S",minimumfeedrate ); + SERIAL_ECHOPAIR(" T" ,mintravelfeedrate ); + SERIAL_ECHOPAIR(" B" ,minsegmenttime ); + SERIAL_ECHOPAIR(" X" ,max_xy_jerk ); + SERIAL_ECHOPAIR(" Z" ,max_z_jerk); + SERIAL_ECHOLN(""); + #ifdef PIDTEMP + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("PID settings:"); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M301 P",Kp); + SERIAL_ECHOPAIR(" I" ,Ki/PID_dT); + SERIAL_ECHOPAIR(" D" ,Kd*PID_dT); + SERIAL_ECHOLN(""); + #endif + #endif +} + + +inline void EEPROM_RetrieveSettings(bool def=false) { // if def=true, the default values will be used #ifdef EEPROM_SETTINGS int i=EEPROM_OFFSET; @@ -125,55 +182,7 @@ FORCE_INLINE void RetrieveSettings(bool def=false) SERIAL_ECHOLN("Using Default settings:"); } #ifdef EEPROM_CHITCHAT - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("Steps per unit:"); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M92 X",axis_steps_per_unit[0]); - SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[1]); - SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[2]); - SERIAL_ECHOPAIR(" E",axis_steps_per_unit[3]); - SERIAL_ECHOLN(""); - - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("Maximum feedrates (mm/s):"); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M203 X",max_feedrate[0]); - SERIAL_ECHOPAIR(" Y",max_feedrate[1] ); - SERIAL_ECHOPAIR(" Z", max_feedrate[2] ); - SERIAL_ECHOPAIR(" E", max_feedrate[3]); - SERIAL_ECHOLN(""); - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("Maximum Acceleration (mm/s2):"); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M201 X" ,max_acceleration_units_per_sq_second[0] ); - SERIAL_ECHOPAIR(" Y" , max_acceleration_units_per_sq_second[1] ); - SERIAL_ECHOPAIR(" Z" ,max_acceleration_units_per_sq_second[2] ); - SERIAL_ECHOPAIR(" E" ,max_acceleration_units_per_sq_second[3]); - SERIAL_ECHOLN(""); - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("Acceleration: S=acceleration, T=retract acceleration"); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M204 S",acceleration ); - SERIAL_ECHOPAIR(" T" ,retract_acceleration); - SERIAL_ECHOLN(""); - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M205 S",minimumfeedrate ); - SERIAL_ECHOPAIR(" T" ,mintravelfeedrate ); - SERIAL_ECHOPAIR(" B" ,minsegmenttime ); - SERIAL_ECHOPAIR(" X" ,max_xy_jerk ); - SERIAL_ECHOPAIR(" Z" ,max_z_jerk); - SERIAL_ECHOLN(""); - #ifdef PIDTEMP - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("PID settings:"); - SERIAL_ECHO_START; - SERIAL_ECHOPAIR(" M301 P",Kp); - SERIAL_ECHOPAIR(" I" ,Ki/PID_dT); - SERIAL_ECHOPAIR(" D" ,Kd*PID_dT); - SERIAL_ECHOLN(""); - #endif + EEPROM_printSettings(); #endif } diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 016702ee36..9985471b72 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -112,6 +112,7 @@ // 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) //Stepper Movement Variables @@ -236,7 +237,7 @@ void setup() fromsd[i] = false; } - RetrieveSettings(); // loads data from EEPROM if available + EEPROM_RetrieveSettings(); // loads data from EEPROM if available for(int8_t i=0; i < NUM_AXIS; i++) { @@ -1034,17 +1035,22 @@ FORCE_INLINE void process_commands() break; case 500: // Store settings in EEPROM { - StoreSettings(); + EEPROM_StoreSettings(); } break; case 501: // Read settings from EEPROM { - RetrieveSettings(); + EEPROM_RetrieveSettings(); } break; case 502: // Revert to default settings { - RetrieveSettings(true); + EEPROM_RetrieveSettings(true); + } + break; + case 503: // print settings currently in memory + { + EEPROM_printSettings(); } break; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 65ba86f109..88f8f32fb3 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1402,7 +1402,7 @@ void MainMenu::showControl() //enquecommand("M84"); beepshort(); BLOCK; - StoreSettings(); + EEPROM_StoreSettings(); } }break; case ItemC_load: @@ -1416,7 +1416,7 @@ void MainMenu::showControl() //enquecommand("M84"); beepshort(); BLOCK; - RetrieveSettings(); + EEPROM_RetrieveSettings(); } }break; case ItemC_failsafe: @@ -1430,7 +1430,7 @@ void MainMenu::showControl() //enquecommand("M84"); beepshort(); BLOCK; - RetrieveSettings(true); + EEPROM_RetrieveSettings(true); } }break; default: From 4fd75dc813fd40ea91323c04323055fbbe077d52 Mon Sep 17 00:00:00 2001 From: Denis B Date: Mon, 5 Dec 2011 23:33:33 -0500 Subject: [PATCH 134/228] Working version of multiple extruders (up to 3) - The temperature control is pretty much complete (not sure what to do w/ autotemp though) Changed the pins assignment to clearly separate bed and extruder heaters and temp sensors, changed a bit how termistor tables are handled. - The steppers control is rudimentary (only chanages what pins it uses depending on the active_extruder var, but that's enough for switching extruder in the start.gcode in the the profiles) - Tested only w/ RAMPS 1.4 --- Marlin/Configuration.h | 72 +++--- Marlin/Marlin.h | 32 ++- Marlin/Marlin.pde | 107 +++++---- Marlin/cardreader.pde | 2 +- Marlin/fastio.h | 16 +- Marlin/pins.h | 179 ++++++++------ Marlin/planner.cpp | 20 +- Marlin/planner.h | 2 - Marlin/stepper.cpp | 61 +++-- Marlin/temperature.cpp | 494 +++++++++++++++++++++----------------- Marlin/temperature.h | 119 +++++---- Marlin/thermistortables.h | 147 +++++------- 12 files changed, 703 insertions(+), 548 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index e8b960f788..346db503fd 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -4,11 +4,11 @@ // This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 +//#define BAUDRATE 250000 +#define BAUDRATE 115200 //#define BAUDRATE 230400 -#define EXTRUDERS 1 +#define EXTRUDERS 2 // Frequency limit // See nophead's blog for more info @@ -32,7 +32,7 @@ // Sanguinololu 1.2 and above = 62 // Ultimaker = 7, // Teensylu = 8 -#define MOTHERBOARD 7 +#define MOTHERBOARD 33 //=========================================================================== //=============================Thermal Settings ============================ @@ -46,17 +46,16 @@ // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 -//#define THERMISTORHEATER_0 3 -//#define THERMISTORHEATER_1 3 -//#define THERMISTORBED 3 - -//#define HEATER_0_USES_THERMISTOR -//#define HEATER_1_USES_THERMISTOR -#define HEATER_0_USES_AD595 +#define THERMISTORHEATER_0 1 +#define THERMISTORHEATER_1 1 +#define HEATER_0_USES_THERMISTOR +#define HEATER_1_USES_THERMISTOR +//#define HEATER_0_USES_AD595 //#define HEATER_1_USES_AD595 // Select one of these only to define how the bed temp is read. -//#define BED_USES_THERMISTOR +#define THERMISTORBED 1 +#define BED_USES_THERMISTOR //#define BED_USES_AD595 #define BED_CHECK_INTERVAL 5000 //ms @@ -68,13 +67,13 @@ //#define WATCHPERIOD 5000 //5 seconds // Actual temperature must be close to target for this long before M109 returns success -//#define TEMP_RESIDENCY_TIME 20 // (seconds) -//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one +#define TEMP_RESIDENCY_TIME 30 // (seconds) +#define TEMP_HYSTERESIS 3 // (C°) range of +/- temperatures considered "close" to the target one //// The minimal temperature defines the temperature below which the heater will not be enabled #define HEATER_0_MINTEMP 5 //#define HEATER_1_MINTEMP 5 -//#define BED_MINTEMP 5 +#define BED_MINTEMP 5 // When temperature exceeds max temp, your heater will be switched off. @@ -82,7 +81,7 @@ // You should use MINTEMP for thermistor short/failure protection. #define HEATER_0_MAXTEMP 275 //#define HEATER_1_MAXTEMP 275 -//#define BED_MAXTEMP 150 +#define BED_MAXTEMP 150 // Wait for Cooldown @@ -131,9 +130,14 @@ // #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) // Ultitmaker - #define DEFAULT_Kp 22.2 - #define DEFAULT_Ki (1.25*PID_dT) - #define DEFAULT_Kd (99/PID_dT) +// #define DEFAULT_Kp 22.2 +// #define DEFAULT_Ki (1.25*PID_dT) +// #define DEFAULT_Kd (99/PID_dT) + +// Makergear + #define DEFAULT_Kp 7.0 + #define DEFAULT_Ki 0.1 + #define DEFAULT_Kd 12 // Mendel Parts V9 on 12V // #define DEFAULT_Kp 63.0 @@ -152,7 +156,7 @@ // if Kc is choosen well, the additional required power due to increased melting should be compensated. #define PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (3) //heatingpower=Kc*(e_speed) + #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) #endif #endif // PIDTEMP @@ -164,10 +168,11 @@ // Endstop Settings #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors + // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false //#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing @@ -176,24 +181,26 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define X_ENABLE_ON 0 #define Y_ENABLE_ON 0 #define Z_ENABLE_ON 0 -#define E_ENABLE_ON 0 +#define E_ENABLE_ON 0 // For all extruders // Disables axis when it's not being used. #define DISABLE_X false #define DISABLE_Y false -#define DISABLE_Z false -#define DISABLE_E false +#define DISABLE_Z true +#define DISABLE_E false // For all extruders // Inverting axis direction //#define INVERT_X_DIR false // for Mendel set to false, for Orca set to true //#define INVERT_Y_DIR true // for Mendel set to true, for Orca set to false //#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true -//#define INVERT_E_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +//#define INVERT_E*_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false, used for all extruders -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_X_DIR false // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false #define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false //// ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -209,7 +216,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) +#define HOMING_FEEDRATE {30*60, 30*60, 2*60, 0} // set the homing speeds (mm/min) //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again: #define X_HOME_RETRACT_MM 5 @@ -223,8 +230,9 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker +//#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} //sells mendel with v9 extruder +#define DEFAULT_AXIS_STEPS_PER_UNIT {80.3232, 80.8900, 2284.7651, 757.2218} // SAE Prusa w/ Wade extruder #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. @@ -290,7 +298,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 -//#define SDSUPPORT // Enable SD Card Support in Hardware Console +#define SDSUPPORT // Enable SD Card Support in Hardware Console #define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? //#define ULTIPANEL diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 910cf46ad3..626f61b6c8 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -57,6 +57,8 @@ const prog_char echomagic[] PROGMEM ="echo:"; #define SERIAL_ECHOPAIR(name,value) {SERIAL_ECHOPGM(name);SERIAL_ECHO(value);} +// Macro for getting current active extruder +#define ACTIVE_EXTRUDER (active_extruder) //things to write to serial from Programmemory. saves 400 to 2k of RAM. #define SerialprintPGM(x) serialprintPGM(MYPGM(x)) @@ -100,14 +102,31 @@ void manage_inactivity(byte debug); #define disable_z() ; #endif -#if E_ENABLE_PIN > -1 - #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) - #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) +#if defined(E0_ENABLE_PIN) && (E0_ENABLE_PIN > -1) + #define enable_e0() WRITE(E0_ENABLE_PIN, E_ENABLE_ON) + #define disable_e0() WRITE(E0_ENABLE_PIN,!E_ENABLE_ON) #else - #define enable_e() ; - #define disable_e() ; + #define enable_e0() /* nothing */ + #define disable_e0() /* nothing */ #endif +#if (EXTRUDERS > 1) && defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1) + #define enable_e1() WRITE(E1_ENABLE_PIN, E_ENABLE_ON) + #define disable_e1() WRITE(E1_ENABLE_PIN,!E_ENABLE_ON) +#else + #define enable_e1() /* nothing */ + #define disable_e1() /* nothing */ +#endif + +#if (EXTRUDERS > 2) && defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1) + #define enable_e2() WRITE(E2_ENABLE_PIN, E_ENABLE_ON) + #define disable_e2() WRITE(E2_ENABLE_PIN,!E_ENABLE_ON) +#else + #define enable_e2() /* nothing */ + #define disable_e2() /* nothing */ +#endif + + enum AxisEnum {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, E_AXIS=3}; @@ -131,4 +150,7 @@ extern bool axis_relative_modes[]; extern float current_position[NUM_AXIS] ; extern float add_homeing[3]; +// Handling multiple extruders pins +extern uint8_t active_extruder; + #endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 226a7d35df..9b765ebd05 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -119,7 +119,6 @@ //=========================================================================== //=============================imported variables============================ //=========================================================================== -extern float HeaterPower; //=========================================================================== @@ -133,8 +132,10 @@ bool axis_relative_modes[] = AXIS_RELATIVE_MODES; volatile int feedmultiply=100; //100->1 200->2 int saved_feedmultiply; volatile bool feedmultiplychanged=false; -float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; +float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 }; float add_homeing[3]={0,0,0}; +uint8_t active_extruder = 0; + //=========================================================================== //=============================private variables============================= @@ -601,7 +602,6 @@ FORCE_INLINE void process_commands() else if(code_seen('M')) { - switch( (int)code_value() ) { case 17: @@ -609,10 +609,12 @@ FORCE_INLINE void process_commands() enable_x(); enable_y(); enable_z(); - enable_e(); + enable_e0(); + enable_e1(); + enable_e2(); break; - #ifdef SDSUPPORT +#ifdef SDSUPPORT case 20: // M20 - list SD card SERIAL_PROTOCOLLNPGM("Begin file list"); card.ls(); @@ -641,9 +643,8 @@ FORCE_INLINE void process_commands() card.pauseSDPrint(); break; case 26: //M26 - Set SD index - if(card.cardOK && code_seen('S')){ + if(card.cardOK && code_seen('S')) { card.setIndex(code_value_long()); - } break; case 27: //M27 - Get SD status @@ -657,16 +658,15 @@ FORCE_INLINE void process_commands() *(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; - #endif //SDSUPPORT +#endif //SDSUPPORT case 30: //M30 take time since the start of the SD print or an M109 command - { + { stoptime=millis(); char time[30]; unsigned long t=(stoptime-starttime)/1000; @@ -678,8 +678,8 @@ FORCE_INLINE void process_commands() SERIAL_ECHOLN(time); LCD_MESSAGE(time); autotempShutdown(); - } - break; + } + break; case 42: //M42 -Change pin status via gcode if (code_seen('S')) { @@ -723,7 +723,7 @@ FORCE_INLINE void process_commands() if (code_seen('S')) setTargetBed(code_value()); break; case 105 : // M105 - tmp_extruder = active_extruder; + tmp_extruder = ACTIVE_EXTRUDER; if(code_seen('T')) { tmp_extruder = code_value(); if(tmp_extruder >= EXTRUDERS) { @@ -733,21 +733,16 @@ FORCE_INLINE void process_commands() break; } } - #if (TEMP_0_PIN > -1) || (TEMP_2_PIN > -1) + #if (TEMP_0_PIN > -1) SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL( degHotend(tmp_extruder)); - #if TEMP_1_PIN > -1 + SERIAL_PROTOCOL(degHotend(tmp_extruder)); + #if TEMP_BED_PIN > -1 SERIAL_PROTOCOLPGM(" B:"); SERIAL_PROTOCOL(degBed()); - #endif //TEMP_1_PIN + #endif //TEMP_BED_PIN #else SERIAL_ERROR_START; SERIAL_ERRORLNPGM("No thermistors - no temp"); - #endif - #ifdef PIDTEMP - SERIAL_PROTOCOLPGM(" @:"); - SERIAL_PROTOCOL( HeaterPower); - #endif SERIAL_PROTOCOLLN(""); return; @@ -790,19 +785,31 @@ FORCE_INLINE void process_commands() 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((target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder))) || - (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + while((residencyStart == -1) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else - while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { + while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000 ) - { //Print Temp Reading every 1 second while heating up/cooling down - SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOLLN( degHotend(tmp_extruder) ); - codenum = millis(); - } - manage_heater(); - LCD_STATUS; + if( (millis() - codenum) > 1000 ) + { //Print Temp Reading and remaining time every 1 second while heating up/cooling down + SERIAL_PROTOCOLPGM("T:"); + SERIAL_PROTOCOLLN( degHotend(tmp_extruder) ); + SERIAL_PROTOCOLPGM(" E:"); + SERIAL_PROTOCOLLN( (int)tmp_extruder ); + SERIAL_PROTOCOLPGM(" W:"); + if(residencyStart > -1) + { + codenum = TEMP_RESIDENCY_TIME - ((millis() - residencyStart) / 1000); + SERIAL_PROTOCOLLN( codenum ); + } + else + { + SERIAL_PROTOCOLLN( "?" ); + } + codenum = millis(); + } + manage_heater(); + 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 */ @@ -818,8 +825,8 @@ FORCE_INLINE void process_commands() starttime=millis(); } break; - case 190: // M190 - Wait bed for heater to reach target. - #if TEMP_1_PIN > -1 + case 190: // M190 - Wait for bed heater to reach target. + #if TEMP_BED_PIN > -1 LCD_MESSAGEPGM("Bed Heating."); if (code_seen('S')) setTargetBed(code_value()); codenum = millis(); @@ -827,13 +834,13 @@ FORCE_INLINE void process_commands() { if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { - float tt=degHotend0(); + float tt=degHotend(ACTIVE_EXTRUDER); SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOLLN(tt ); - SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL(tt ); + SERIAL_PROTOCOL(tt); + SERIAL_PROTOCOLPGM(" E:"); + SERIAL_PROTOCOLLN( (int)tmp_extruder ); SERIAL_PROTOCOLPGM(" B:"); - SERIAL_PROTOCOLLN(degBed() ); + SERIAL_PROTOCOLLN(degBed()); codenum = millis(); } manage_heater(); @@ -886,7 +893,9 @@ FORCE_INLINE void process_commands() if(code_seen('E')) { st_synchronize(); LCD_MESSAGEPGM("Free Move"); - disable_e(); + disable_e0(); + disable_e1(); + disable_e2(); } else { finishAndDisableSteppers(); @@ -1061,7 +1070,9 @@ FORCE_INLINE void process_commands() } } - else if(code_seen('T')) { + + else if(code_seen('T')) + { tmp_extruder = code_value(); if(tmp_extruder >= EXTRUDERS) { SERIAL_ECHO_START; @@ -1071,8 +1082,12 @@ FORCE_INLINE void process_commands() } else { active_extruder = tmp_extruder; + SERIAL_ECHO_START; + SERIAL_ECHO("Active Extruder: "); + SERIAL_PROTOCOLLN((int)active_extruder); } } + else { SERIAL_ECHO_START; @@ -1167,7 +1182,9 @@ void manage_inactivity(byte debug) disable_x(); disable_y(); disable_z(); - disable_e(); + disable_e0(); + disable_e1(); + disable_e2(); } check_axes_activity(); } @@ -1179,7 +1196,9 @@ void kill() disable_x(); disable_y(); disable_z(); - disable_e(); + disable_e0(); + disable_e1(); + disable_e2(); if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); SERIAL_ERROR_START; diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 1eb19ba00c..4d3eac789d 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -438,4 +438,4 @@ void CardReader::printingHasFinished() } autotempShutdown(); } -#endif //SDSUPPORT \ No newline at end of file +#endif //SDSUPPORT diff --git a/Marlin/fastio.h b/Marlin/fastio.h index 7fd42a6c8e..634571e3a1 100644 --- a/Marlin/fastio.h +++ b/Marlin/fastio.h @@ -44,9 +44,23 @@ // why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html /// Read a pin wrapper -#define READ(IO) _READ(IO) +#define READ(IO) _READ(IO) /// Write to a pin wrapper #define WRITE(IO, v) _WRITE(IO, v) +#if EXTRUDERS > 2 + #define WRITE_E_STEP(v) { if(ACTIVE_EXTRUDER == 2) { WRITE(E2_STEP_PIN, v); } else { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}} + #define NORM_E_DIR() { if(ACTIVE_EXTRUDER == 2) { WRITE(E2_DIR_PIN, INVERT_E2_DIR); } else { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}} + #define REV_E_DIR() { if(ACTIVE_EXTRUDER == 2) { WRITE(E2_DIR_PIN, !INVERT_E2_DIR); } else { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}} +#elif EXTRUDERS > 1 + #define WRITE_E_STEP(v) { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }} + #define NORM_E_DIR() { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }} + #define REV_E_DIR() { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }} +#else + #define WRITE_E_STEP(v) WRITE(E0_STEP_PIN, v) + #define NORM_E_DIR() WRITE(E0_DIR_PIN, INVERT_E0_DIR) + #define REV_E_DIR() WRITE(E0_DIR_PIN, !INVERT_E0_DIR) +#endif + /// toggle a pin wrapper #define TOGGLE(IO) _TOGGLE(IO) diff --git a/Marlin/pins.h b/Marlin/pins.h index 60dd6e5148..2c2bc91445 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -47,9 +47,9 @@ #define Z_MIN_PIN 17 #define Z_MAX_PIN 16 -#define E_STEP_PIN 11 -#define E_DIR_PIN 12 -#define E_ENABLE_PIN -1 +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 #define SDPOWER -1 #define SDSS -1 @@ -59,9 +59,13 @@ #define KILL_PIN -1 #define HEATER_0_PIN 6 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! #define HEATER_1_PIN -1 #define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 #endif @@ -120,9 +124,9 @@ #define Z_MIN_PIN 2 #define Z_MAX_PIN 1 -#define E_STEP_PIN 12 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN 3 +#define E0_STEP_PIN 12 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN 3 #define SDPOWER -1 #define SDSS -1 @@ -132,9 +136,13 @@ #define KILL_PIN -1 #define HEATER_0_PIN 14 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 #define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 /* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ @@ -171,9 +179,9 @@ #define Z_MIN_PIN 30 #define Z_MAX_PIN 31 -#define E_STEP_PIN 17 -#define E_DIR_PIN 16 -#define E_ENABLE_PIN -1 +#define E0_STEP_PIN 17 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN -1 #define SDPOWER -1 #define SDSS 4 @@ -194,11 +202,13 @@ #define KILL_PIN -1 #define HEATER_0_PIN -1 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 #define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - - +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 #endif @@ -230,37 +240,43 @@ #define X_DIR_PIN 55 #define X_ENABLE_PIN 38 #define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 //Max endstops default to disabled "-1", set to commented value to enable. +#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. #define Y_STEP_PIN 60 #define Y_DIR_PIN 61 #define Y_ENABLE_PIN 56 #define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 //15 +#define Y_MAX_PIN 15 //15 #define Z_STEP_PIN 46 #define Z_DIR_PIN 48 #define Z_ENABLE_PIN 62 #define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 +#define Z_MAX_PIN 19 //19 -#define E_STEP_PIN 26 -#define E_DIR_PIN 28 -#define E_ENABLE_PIN 24 +#define E0_STEP_PIN 26 +#define E0_DIR_PIN 28 +#define E0_ENABLE_PIN 24 + +#define E1_STEP_PIN 36 +#define E1_DIR_PIN 34 +#define E1_ENABLE_PIN 30 #define SDPOWER -1 #define SDSS 53 #define LED_PIN 13 -#define FAN_PIN 9 +#define FAN_PIN 4 #define PS_ON_PIN 12 #define KILL_PIN -1 -#define HEATER_0_PIN 10 -#define HEATER_1_PIN 8 -#define HEATER_2_PIN -1 +#define HEATER_0_PIN 10 // EXTRUDER 1 +#define HEATER_1_PIN 9 // EXTRUDER 2 +#define HEATER_2_PIN -1 // EXTRUDER 2 #define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 14 // ANALOG NUMBERING +#define TEMP_1_PIN 15 // ANALOG NUMBERING #define TEMP_2_PIN -1 // ANALOG NUMBERING +#define HEATER_BED_PIN 8 // BED +#define TEMP_BED_PIN 14 // ANALOG NUMBERING #else // RAMPS_V_1_1 or RAMPS_V_1_2 as default @@ -283,9 +299,9 @@ #define Z_MIN_PIN 18 #define Z_MAX_PIN -1 //19 -#define E_STEP_PIN 32 -#define E_DIR_PIN 34 -#define E_ENABLE_PIN 30 +#define E0_STEP_PIN 32 +#define E0_DIR_PIN 34 +#define E0_ENABLE_PIN 30 #define SDPOWER 48 #define SDSS 53 @@ -297,18 +313,19 @@ #ifdef RAMPS_V_1_0 // RAMPS_V_1_0 #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_1_PIN -1 // RAMPS 1.0 + #define HEATER_BED_PIN -1 // RAMPS 1.0 #define FAN_PIN 11 // RAMPS 1.0 - #else // RAMPS_V_1_1 or RAMPS_V_1_2 #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_1_PIN 8 // RAMPS 1.1 + #define HEATER_BED_PIN 8 // RAMPS 1.1 #define FAN_PIN 9 // RAMPS 1.1 #endif +#define HEATER_1_PIN -1 #define HEATER_2_PIN -1 #define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! #endif // SPI for Max6675 Thermocouple @@ -353,9 +370,9 @@ #define Z_MIN_PIN 4 #define Z_MAX_PIN -1 -#define E_STEP_PIN 11 -#define E_DIR_PIN 12 -#define E_ENABLE_PIN -1 +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 #define SDPOWER -1 #define SDSS -1 @@ -365,9 +382,13 @@ #define KILL_PIN -1 #define HEATER_0_PIN 6 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! #define HEATER_1_PIN -1 #define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 #endif @@ -404,19 +425,21 @@ #define Z_MAX_PIN -1 //extruder pins - #define E_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_2_PIN -1 + #define HEATER_1_PIN -1 + #define HEATER_2_PIN -1 + #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 #define SDPOWER -1 #define SDSS 17 #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_2_PIN -1 #define FAN_PIN -1 //changed @ rkoeppl 20110410 #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 //our pin for debugging. @@ -459,8 +482,8 @@ #define Z_MIN_PIN 20 #define Z_MAX_PIN -1 -#define E_STEP_PIN 1 -#define E_DIR_PIN 0 +#define E0_STEP_PIN 1 +#define E0_DIR_PIN 0 #define LED_PIN -1 @@ -470,31 +493,33 @@ #define KILL_PIN -1 #define HEATER_0_PIN 13 // (extruder) +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_1_PIN 12 // (bed) +#define HEATER_BED_PIN 12 // (bed) #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 -#define E_ENABLE_PIN 14 +#define E0_ENABLE_PIN 14 #else -#define HEATER_1_PIN 14 // (bed) +#define HEATER_BED_PIN 14 // (bed) #define X_ENABLE_PIN -1 #define Y_ENABLE_PIN -1 #define Z_ENABLE_PIN -1 -#define E_ENABLE_PIN -1 +#define E0_ENABLE_PIN -1 #endif #define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_1_PIN -1 #define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) #define SDPOWER -1 #define SDSS 31 -#define HEATER_2_PIN -1 #endif @@ -529,8 +554,8 @@ #define Z_MAX_PIN 32 #define Z_ENABLE_PIN 35 -#define HEATER_1_PIN 4 -#define TEMP_1_PIN 11 +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 11 #define EXTRUDER_0_STEP_PIN 43 #define EXTRUDER_0_DIR_PIN 45 @@ -543,14 +568,14 @@ #define EXTRUDER_1_ENABLE_PIN 51 #define EXTRUDER_1_HEATER_PIN 3 #define EXTRUDER_1_TEMPERATURE_PIN 10 -#define HEATER_2_PIN 51 -#define TEMP_2_PIN 3 +#define HEATER_1_PIN 51 +#define TEMP_1_PIN 3 -#define E_STEP_PIN EXTRUDER_0_STEP_PIN -#define E_DIR_PIN EXTRUDER_0_DIR_PIN -#define E_ENABLE_PIN EXTRUDER_0_ENABLE_PIN +#define E0_STEP_PIN EXTRUDER_0_STEP_PIN +#define E0_DIR_PIN EXTRUDER_0_DIR_PIN +#define E0_ENABLE_PIN EXTRUDER_0_ENABLE_PIN #define SDPOWER -1 #define SDSS 53 @@ -655,20 +680,22 @@ #define Z_MIN_PIN 15 #define Z_MAX_PIN -1 -#define E_STEP_PIN 6 -#define E_DIR_PIN 7 -#define E_ENABLE_PIN 19 +#define E0_STEP_PIN 6 +#define E0_DIR_PIN 7 +#define E0_ENABLE_PIN 19 #define HEATER_0_PIN 21 // Extruder -#define HEATER_1_PIN 20 // Bed +#define HEATER_1_PIN -1 #define HEATER_2_PIN -1 +#define HEATER_BED_PIN 20 // Bed #define FAN_PIN 22 // Fan #define TEMP_0_PIN 7 // Extruder -#define TEMP_1_PIN 6 // Bed +#define TEMP_1_PIN -1 #define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // Bed #define SDPOWER -1 #define SDSS 8 @@ -690,6 +717,22 @@ #endif //List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN, LED_PIN, PS_ON_PIN, HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, FAN_PIN, TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN} - +#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN +#if EXTRUDERS == 3 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN +#elif EXTRUDERS == 2 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS -1 +#elif EXTRUDERS == 1 + #define _E1_PINS -1 + #define _E2_PINS -1 +#else + #error Unsupported number of extruders +#endif +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ + HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ + HEATER_BED_PIN, FAN_PIN, \ + _E0_PINS, _E1_PINS, _E2_PINS, \ + TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index a8f41d3532..d2179301f2 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -56,9 +56,9 @@ //#include //#include -#include "Marlin.h" #include "Configuration.h" #include "pins.h" +#include "Marlin.h" #include "fastio.h" #include "planner.h" #include "stepper.h" @@ -81,8 +81,6 @@ float max_z_jerk; float mintravelfeedrate; unsigned long axis_steps_per_sqr_second[NUM_AXIS]; -uint8_t active_extruder = 0; - // The current position of the tool in absolute steps long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode static float previous_speed[4]; // Speed of previous path line segment @@ -95,7 +93,6 @@ static float previous_nominal_speed; // Nominal speed of previous path line segm bool autotemp_enabled=false; #endif - //=========================================================================== //=================semi-private variables, used in inline functions ===== //=========================================================================== @@ -437,7 +434,7 @@ void check_axes_activity() { if((DISABLE_X) && (x_active == 0)) disable_x(); if((DISABLE_Y) && (y_active == 0)) disable_y(); if((DISABLE_Z) && (z_active == 0)) disable_z(); - if((DISABLE_E) && (e_active == 0)) disable_e(); + if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } } @@ -496,15 +493,10 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa if(block->steps_x != 0) enable_x(); if(block->steps_y != 0) enable_y(); if(block->steps_z != 0) enable_z(); - if(extruder == 0) { - if(block->steps_e != 0) enable_e(); - } - #if (EXTRUDERS > 1) - if(extruder == 1) { - if(block->steps_e != 0) enable_e1(); - } - #endif - + + // Enable all + if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } + float delta_mm[4]; delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; diff --git a/Marlin/planner.h b/Marlin/planner.h index 53ac3d8447..66bd9025c3 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -91,8 +91,6 @@ extern float max_z_jerk; extern float mintravelfeedrate; extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; -extern uint8_t active_extruder; - #ifdef AUTOTEMP extern bool autotemp_enabled; extern float autotemp_max; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 9cf8ddd176..465ab89ddf 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -24,9 +24,9 @@ #include "stepper.h" #include "Configuration.h" +#include "pins.h" #include "Marlin.h" #include "planner.h" -#include "pins.h" #include "fastio.h" #include "temperature.h" #include "ultralcd.h" @@ -41,7 +41,6 @@ block_t *current_block; // A pointer to the block currently being traced - //=========================================================================== //=============================private variables ============================ //=========================================================================== @@ -419,11 +418,11 @@ ISR(TIMER1_COMPA_vect) #ifndef ADVANCE if ((out_bits & (1<steps_e; if (counter_e > 0) { - WRITE(E_STEP_PIN, HIGH); + WRITE_E_STEP(HIGH); counter_e -= current_block->step_event_count; - WRITE(E_STEP_PIN, LOW); + WRITE_E_STEP(LOW); count_position[E_AXIS]+=count_direction[E_AXIS]; } #endif //!ADVANCE @@ -559,18 +558,18 @@ ISR(TIMER1_COMPA_vect) OCR0A = old_OCR0A; // Set E direction (Depends on E direction + advance) for(unsigned char i=0; i<4;) { - WRITE(E_STEP_PIN, LOW); + WRITE_E_STEP(LOW); if (e_steps == 0) break; i++; if (e_steps < 0) { - WRITE(E_DIR_PIN,INVERT_E_DIR); + WRITE_E_DIR(INVERT_E_DIR); e_steps++; - WRITE(E_STEP_PIN, HIGH); + WRITE_E_STEP(HIGH); } else if (e_steps > 0) { - WRITE(E_DIR_PIN,!INVERT_E_DIR); + WRITE_E_DIR(!INVERT_E_DIR); e_steps--; - WRITE(E_STEP_PIN, HIGH); + WRITE_E_STEP(HIGH); } } } @@ -578,7 +577,7 @@ ISR(TIMER1_COMPA_vect) void st_init() { - //Initialize Dir Pins + //Initialize Dir Pins #if X_DIR_PIN > -1 SET_OUTPUT(X_DIR_PIN); #endif @@ -588,8 +587,14 @@ void st_init() #if Z_DIR_PIN > -1 SET_OUTPUT(Z_DIR_PIN); #endif - #if E_DIR_PIN > -1 - SET_OUTPUT(E_DIR_PIN); + #if E0_DIR_PIN > -1 + SET_OUTPUT(E0_DIR_PIN); + #endif + #if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1) + SET_OUTPUT(E1_DIR_PIN); + #endif + #if defined(E2_DIR_PIN) && (E2_DIR_PIN > -1) + SET_OUTPUT(E2_DIR_PIN); #endif //Initialize Enable Pins - steppers default to disabled. @@ -606,9 +611,17 @@ void st_init() SET_OUTPUT(Z_ENABLE_PIN); if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); #endif - #if (E_ENABLE_PIN > -1) - SET_OUTPUT(E_ENABLE_PIN); - if(!E_ENABLE_ON) WRITE(E_ENABLE_PIN,HIGH); + #if (E0_ENABLE_PIN > -1) + SET_OUTPUT(E0_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E0_ENABLE_PIN,HIGH); + #endif + #if defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1) + SET_OUTPUT(E1_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E1_ENABLE_PIN,HIGH); + #endif + #if defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1) + SET_OUTPUT(E2_ENABLE_PIN); + if(!E_ENABLE_ON) WRITE(E2_ENABLE_PIN,HIGH); #endif //endstops and pullups @@ -669,8 +682,14 @@ void st_init() #if (Z_STEP_PIN > -1) SET_OUTPUT(Z_STEP_PIN); #endif - #if (E_STEP_PIN > -1) - SET_OUTPUT(E_STEP_PIN); + #if (E0_STEP_PIN > -1) + SET_OUTPUT(E0_STEP_PIN); + #endif + #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) + SET_OUTPUT(E1_STEP_PIN); + #endif + #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) + SET_OUTPUT(E2_STEP_PIN); #endif // waveform generation = 0100 = CTC @@ -749,5 +768,7 @@ void finishAndDisableSteppers() disable_x(); disable_y(); disable_z(); - disable_e(); + disable_e0(); + disable_e1(); + disable_e2(); } diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index ac5aeaa3e5..72b8959791 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -41,17 +41,14 @@ //=========================================================================== //=============================public variables============================ //=========================================================================== -int target_raw[3] = {0, 0, 0}; -int current_raw[3] = {0, 0, 0}; -int heatingtarget_raw[3]= {0, 0, 0}; - +int target_raw[EXTRUDERS] = { 0 }; +int target_raw_bed = 0; +int current_raw[EXTRUDERS] = { 0 }; +int current_raw_bed = 0; #ifdef PIDTEMP - - // probably used external - float HeaterPower; - float pid_setpoint = 0.0; - + // used external + float pid_setpoint[EXTRUDERS] = { 0.0 }; float Kp=DEFAULT_Kp; float Ki=DEFAULT_Ki; @@ -72,42 +69,74 @@ static unsigned long previous_millis_bed_heater; #ifdef PIDTEMP //static cannot be external: - static float temp_iState = 0; - static float temp_dState = 0; - static float pTerm; - static float iTerm; - static float dTerm; + static float temp_iState[EXTRUDERS] = { 0 }; + static float temp_dState[EXTRUDERS] = { 0 }; + static float pTerm[EXTRUDERS]; + static float iTerm[EXTRUDERS]; + static float dTerm[EXTRUDERS]; //int output; - static float pid_error; - static float temp_iState_min; - static float temp_iState_max; - // static float pid_input; - // static float pid_output; - static bool pid_reset; - + static float pid_error[EXTRUDERS]; + static float temp_iState_min[EXTRUDERS]; + static float temp_iState_max[EXTRUDERS]; + // static float pid_input[EXTRUDERS]; + // static float pid_output[EXTRUDERS]; + static bool pid_reset[EXTRUDERS]; #endif //PIDTEMP #ifdef WATCHPERIOD - static int watch_raw[3] = {-1000,-1000,-1000}; + static int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all static unsigned long watchmillis = 0; #endif //WATCHPERIOD // Init min and max temp with extreme values to prevent false errors during startup - static int minttemp_0 = 0; - static int maxttemp_0 = 16383; - //static int minttemp_1 = 0; - //static int maxttemp_1 = 16383; + static int minttemp[EXTRUDERS] = { 0 }; + static int maxttemp[EXTRUDERS] = { 16383 }; // the first value used for all static int bed_minttemp = 0; static int bed_maxttemp = 16383; + static int heater_pin_map[EXTRUDERS] = { HEATER_0_PIN +#if EXTRUDERS > 1 + , HEATER_1_PIN +#endif +#if EXTRUDERS > 2 + , HEATER_2_PIN +#endif +#if EXTRUDERS > 3 + #error Unsupported number of extruders +#endif + }; + static void *heater_ttbl_map[EXTRUDERS] = { (void *)heater_0_temptable +#if EXTRUDERS > 1 + , (void *)heater_1_temptable +#endif +#if EXTRUDERS > 2 + , (void *)heater_2_temptable +#endif +#if EXTRUDERS > 3 + #error Unsupported number of extruders +#endif + }; + static int heater_ttbllen_map[EXTRUDERS] = { heater_0_temptable_len +#if EXTRUDERS > 1 + , heater_1_temptable_len +#endif +#if EXTRUDERS > 2 + , heater_2_temptable_len +#endif +#if EXTRUDERS > 3 + #error Unsupported number of extruders +#endif + }; //=========================================================================== -//=============================functions ============================ +//============================= functions ============================ //=========================================================================== void updatePID() { #ifdef PIDTEMP - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; + for(int e = 0; e < EXTRUDERS; e++) { + temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; + } #endif } @@ -119,92 +148,85 @@ void manage_heater() float pid_input; float pid_output; + if(temp_meas_ready != true) //better readability return; CRITICAL_SECTION_START; - temp_meas_ready = false; + temp_meas_ready = false; CRITICAL_SECTION_END; + for(int e = 0; e < EXTRUDERS; e++) + { + #ifdef PIDTEMP - pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); + pid_input = analog2temp(current_raw[e], e); #ifndef PID_OPENLOOP - pid_error = pid_setpoint - pid_input; - if(pid_error > 10){ + pid_error[e] = pid_setpoint[e] - pid_input; + if(pid_error[e] > 10) { pid_output = PID_MAX; - pid_reset = true; + pid_reset[e] = true; } - else if(pid_error < -10) { + else if(pid_error[e] < -10) { pid_output = 0; - pid_reset = true; + pid_reset[e] = true; } else { - if(pid_reset == true) { - temp_iState = 0.0; - pid_reset = false; + if(pid_reset[e] == true) { + temp_iState[e] = 0.0; + pid_reset[e] = false; } - pTerm = Kp * pid_error; - temp_iState += pid_error; - temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); - iTerm = Ki * temp_iState; + pTerm[e] = Kp * pid_error[e]; + temp_iState[e] += pid_error[e]; + temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]); + iTerm[e] = Ki * temp_iState[e]; //K1 defined in Configuration.h in the PID settings #define K2 (1.0-K1) - dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); - temp_dState = pid_input; -// #ifdef PID_ADD_EXTRUSION_RATE -// pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high -// #endif - pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); - + dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]); + temp_dState[e] = pid_input; + pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX); } #endif //PID_OPENLOOP #ifdef PID_DEBUG - //SERIAL_ECHOLN(" PIDDEBUG Input "< minttemp_0) && (current_raw[TEMPSENSOR_HOTEND_0] < maxttemp_0)) { - analogWrite(HEATER_0_PIN, pid_output); + #else /* PID off */ + pid_output = 0; + if(current_raw[e] < target_raw[e]) { + pid_output = PID_MAX; } - else { - analogWrite(HEATER_0_PIN, 0); - } - #endif //PIDTEMP - - #ifndef PIDTEMP - // Check if temperature is within the correct range - if((current_raw[TEMPSENSOR_HOTEND_0] > minttemp_0) && (current_raw[TEMPSENSOR_HOTEND_0] < maxttemp_0)) { - if(current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) { - WRITE(HEATER_0_PIN,LOW); - } - else { - WRITE(HEATER_0_PIN,HIGH); - } - } - else { - WRITE(HEATER_0_PIN,LOW); - } #endif + + // Check if temperature is within the correct range + if((current_raw[e] > minttemp[e]) && (current_raw[e] < maxttemp[e])) + { + analogWrite(heater_pin_map[e], pid_output); + } + else { + analogWrite(heater_pin_map[e], 0); + } + + } // End extruder for loop if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) return; previous_millis_bed_heater = millis(); - #if TEMP_1_PIN > -1 + #if TEMP_BED_PIN > -1 // Check if temperature is within the correct range - if((current_raw[TEMPSENSOR_BED] > bed_minttemp) && (current_raw[TEMPSENSOR_BED] < bed_maxttemp)) { - if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) + if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) { + if(current_raw_bed >= target_raw_bed) { - WRITE(HEATER_1_PIN,LOW); + WRITE(HEATER_BED_PIN,LOW); } else { - WRITE(HEATER_1_PIN,HIGH); + WRITE(HEATER_BED_PIN,HIGH); } } else { - WRITE(HEATER_1_PIN,LOW); + WRITE(HEATER_BED_PIN,LOW); } #endif } @@ -214,30 +236,38 @@ void manage_heater() // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. -int temp2analog(int celsius) { - #ifdef HEATER_0_USES_THERMISTOR +int temp2analog(int celsius, uint8_t e) { + if(e >= EXTRUDERS) + { + SERIAL_ERROR_START; + SERIAL_ERROR((int)e); + SERIAL_ERRORLNPGM(" - Invalid extruder number!"); + kill(); + } + if(heater_ttbl_map[e] != 0) + { int raw = 0; byte i; + short (*tt)[][2] = (short (*)[][2])(heater_ttbl_map[e]); - for (i=1; i= EXTRUDERS) + { + SERIAL_ERROR_START; + SERIAL_ERROR((int)e); + SERIAL_ERRORLNPGM(" - Invalid extruder number !"); + kill(); + } + if(heater_ttbl_map[e] != 0) + { float celsius = 0; byte i; + short (*tt)[][2] = (short (*)[][2])(heater_ttbl_map[e]); + raw = (1023 * OVERSAMPLENR) - raw; - for (i=1; i raw) + if (PGM_RD_W((*tt)[i][0]) > raw) { - celsius = PGM_RD_W(heater_0_temptable[i-1][1]) + - (raw - PGM_RD_W(heater_0_temptable[i-1][0])) * - (float)(PGM_RD_W(heater_0_temptable[i][1]) - PGM_RD_W(heater_0_temptable[i-1][1])) / - (float)(PGM_RD_W(heater_0_temptable[i][0]) - PGM_RD_W(heater_0_temptable[i-1][0])); + celsius = PGM_RD_W((*tt)[i-1][1]) + + (raw - PGM_RD_W((*tt)[i-1][0])) * + (float)(PGM_RD_W((*tt)[i][1]) - PGM_RD_W((*tt)[i-1][1])) / + (float)(PGM_RD_W((*tt)[i][0]) - PGM_RD_W((*tt)[i-1][0])); break; } } // Overflow: Set to last value in the table - if (i == NUMTEMPS_HEATER_0) celsius = PGM_RD_W(heater_0_temptable[i-1][1]); + if (i == heater_ttbllen_map[e]) celsius = PGM_RD_W((*tt)[i-1][1]); return celsius; - #elif defined HEATER_0_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; - #else - #error PLEASE DEFINE HEATER TYPE - #endif + } + return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; } // Derived from RepRap FiveD extruder::getTemperature() @@ -314,7 +350,7 @@ float analog2tempBed(int raw) { raw = (1023 * OVERSAMPLENR) - raw; - for (i=1; i raw) { @@ -328,7 +364,7 @@ float analog2tempBed(int raw) { } // Overflow: Set to last value in the table - if (i == BNUMTEMPS) celsius = PGM_RD_W(bedtemptable[i-1][1]); + if (i == bedtemptable_len) celsius = PGM_RD_W(bedtemptable[i-1][1]); return celsius; @@ -342,6 +378,19 @@ float analog2tempBed(int raw) { void tp_init() { + // Finish init of mult extruder arrays + for(int e = 0; e < EXTRUDERS; e++) { + // populate with the first value +#ifdef WATCHPERIOD + watch_raw[e] = watch_raw[0]; +#endif + maxttemp[e] = maxttemp[0]; +#ifdef PIDTEMP + temp_iState_min[e] = 0.0; + temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; +#endif //PIDTEMP + } + #if (HEATER_0_PIN > -1) SET_OUTPUT(HEATER_0_PIN); #endif @@ -351,11 +400,12 @@ void tp_init() #if (HEATER_2_PIN > -1) SET_OUTPUT(HEATER_2_PIN); #endif - - #ifdef PIDTEMP - temp_iState_min = 0.0; - temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; - #endif //PIDTEMP + #if (HEATER_BED_PIN > -1) + SET_OUTPUT(HEATER_BED_PIN); + #endif + #if (FAN_PIN > -1) + SET_OUTPUT(FAN_PIN); + #endif // Set analog inputs ADCSRA = 1< -1) + #if TEMP_BED_PIN < 8 + DIDR0 |= 1< 1) && defined(HEATER_1_MINTEMP) + minttemp[1] = temp2analog(HEATER_1_MINTEMP, 1); +#endif // MINTEMP 1 +#if (EXTRUDERS > 1) && defined(HEATER_1_MAXTEMP) + maxttemp[1] = temp2analog(HEATER_1_MAXTEMP, 1); +#endif //MAXTEMP 1 + +#if (EXTRUDERS > 2) && defined(HEATER_2_MINTEMP) + minttemp[2] = temp2analog(HEATER_2_MINTEMP, 2); +#endif //MINTEMP 2 +#if (EXTRUDERS > 2) && defined(HEATER_2_MAXTEMP) + maxttemp[2] = temp2analog(HEATER_2_MAXTEMP, 2); +#endif //MAXTEMP 2 #ifdef BED_MINTEMP - bed_minttemp = temp2analog(BED_MINTEMP); + bed_minttemp = temp2analogBed(BED_MINTEMP); #endif //BED_MINTEMP #ifdef BED_MAXTEMP - bed_maxttemp = temp2analog(BED_MAXTEMP); + bed_maxttemp = temp2analogBed(BED_MAXTEMP); #endif //BED_MAXTEMP } @@ -423,15 +488,16 @@ void tp_init() void setWatch() { #ifdef WATCHPERIOD - if(isHeatingHotend0()) + int t = 0; + for (int e = 0; e < EXTRUDERS; e++) { - watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + if(isHeatingHotend(e)) + { + t = max(t,millis()); + watch_raw[e] = current_raw[e]; + } } - else - { - watchmillis = 0; - } + watchmillis = t; #endif } @@ -458,6 +524,13 @@ void disable_heater() digitalWrite(HEATER_2_PIN,LOW); #endif #endif + + #if TEMP_BED_PIN > -1 + target_raw_bed=0; + #if HEATER_BED_PIN > -1 + digitalWrite(HEATER_BED_PIN,LOW); + #endif + #endif } // Timer 0 is shared with millies @@ -468,6 +541,7 @@ ISR(TIMER0_COMPB_vect) static unsigned long raw_temp_0_value = 0; static unsigned long raw_temp_1_value = 0; static unsigned long raw_temp_2_value = 0; + static unsigned long raw_temp_bed_value = 0; static unsigned char temp_state = 0; switch(temp_state) { @@ -492,7 +566,26 @@ ISR(TIMER0_COMPB_vect) #endif temp_state = 2; break; - case 2: // Prepare TEMP_1 + case 2: // Prepare TEMP_BED + #if (TEMP_BED_PIN > -1) + #if TEMP_BED_PIN > 7 + ADCSRB = 1< -1) + raw_temp_bed_value += ADC; + #endif + temp_state = 4; + break; + case 4: // Prepare TEMP_1 #if (TEMP_1_PIN > -1) #if TEMP_1_PIN > 7 ADCSRB = 1< -1) raw_temp_1_value += ADC; #endif - temp_state = 4; + temp_state = 6; break; - case 4: // Prepare TEMP_2 + case 6: // Prepare TEMP_2 #if (TEMP_2_PIN > -1) #if TEMP_2_PIN > 7 ADCSRB = 1< -1) raw_temp_2_value += ADC; #endif @@ -541,24 +634,34 @@ ISR(TIMER0_COMPB_vect) break; } - if(temp_count >= 16) // 6 ms * 16 = 96ms. + if(temp_count >= 16) // 8 ms * 16 = 128ms. { #ifdef HEATER_0_USES_AD595 current_raw[0] = raw_temp_0_value; #else current_raw[0] = 16383 - raw_temp_0_value; #endif - + +#if EXTRUDERS > 1 #ifdef HEATER_1_USES_AD595 + current_raw[1] = raw_temp_1_value; + #else + current_raw[1] = 16383 - raw_temp_1_value; + #endif +#endif + +#if EXTRUDERS > 2 + #ifdef HEATER_2_USES_AD595 current_raw[2] = raw_temp_2_value; #else current_raw[2] = 16383 - raw_temp_2_value; #endif +#endif #ifdef BED_USES_AD595 - current_raw[1] = raw_temp_1_value; + current_raw_bed = raw_temp_bed_value; #else - current_raw[1] = 16383 - raw_temp_1_value; + current_raw_bed = 16383 - raw_temp_bed_value; #endif temp_meas_ready = true; @@ -566,77 +669,36 @@ ISR(TIMER0_COMPB_vect) raw_temp_0_value = 0; raw_temp_1_value = 0; raw_temp_2_value = 0; - #ifdef HEATER_0_MAXTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - digitalWrite(HEATER_0_PIN, 0); + raw_temp_bed_value = 0; + + for(int e = 0; e < EXTRUDERS; e++) { + if(current_raw[e] >= maxttemp[e]) { + target_raw[e] = 0; + digitalWrite(heater_pin_map[e], 0); SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MAXTEMP triggered !!"); + SERIAL_ERRORLN((int)e); + SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !"); kill(); - } - #endif - #endif - #ifdef HEATER_1_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - digitalWrite(HEATER_2_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MAXTEMP triggered !!"); - kill(); - } - #endif - #endif //MAXTEMP + } + if(current_raw[e] <= minttemp[e]) { + target_raw[e] = 0; + digitalWrite(heater_pin_map[e], 0); + SERIAL_ERROR_START; + SERIAL_ERRORLN(e); + SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); + kill(); + } + } - #ifdef HEATER_0_MINTEMP - #if (HEATER_0_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) { - target_raw[TEMPSENSOR_HOTEND_0] = 0; - digitalWrite(HEATER_0_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 0 switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif - - #ifdef HEATER_1_MINTEMP - #if (HEATER_2_PIN > -1) - if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) { - target_raw[TEMPSENSOR_HOTEND_1] = 0; - digitalWrite(HEATER_2_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature extruder 1 switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif //MAXTEMP - - #ifdef BED_MINTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] <= bed_minttemp) { - target_raw[1] = 0; - digitalWrite(HEATER_1_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperatur heated bed switched off. MINTEMP triggered !!"); - kill(); - } - #endif - #endif - - #ifdef BED_MAXTEMP - #if (HEATER_1_PIN > -1) - if(current_raw[1] >= bed_maxttemp) { - target_raw[1] = 0; - digitalWrite(HEATER_1_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); - kill(); - } - #endif - #endif +#if defined(BED_MAXTEMP) && (HEATER_BED_PIN > -1) + if(current_raw_bed >= bed_maxttemp) { + target_raw_bed = 0; + digitalWrite(HEATER_BED_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); + kill(); + } +#endif } } - diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 623f890bb0..15bc8a8352 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -31,95 +31,110 @@ void tp_init(); //initialise the heating void manage_heater(); //it is critical that this is called periodically. - -enum TempSensor {TEMPSENSOR_HOTEND_0=0,TEMPSENSOR_BED=1, TEMPSENSOR_HOTEND_1=2}; - //low leven conversion routines // do not use this routines and variables outsie of temperature.cpp -int temp2analog(int celsius); +int temp2analog(int celsius, uint8_t e); int temp2analogBed(int celsius); -float analog2temp(int raw); +float analog2temp(int raw, uint8_t e); float analog2tempBed(int raw); -extern int target_raw[3]; -extern int heatingtarget_raw[3]; -extern int current_raw[3]; +extern int target_raw[EXTRUDERS]; +extern int heatingtarget_raw[EXTRUDERS]; +extern int current_raw[EXTRUDERS]; +extern int target_raw_bed; +extern int current_raw_bed; extern float Kp,Ki,Kd,Kc; #ifdef PIDTEMP - extern float pid_setpoint ; + extern float pid_setpoint[EXTRUDERS]; #endif #ifdef WATCHPERIOD - extern int watch_raw[3] ; + extern int watch_raw[EXTRUDERS] ; extern unsigned long watchmillis; #endif - //high level conversion routines, for use outside of temperature.cpp //inline so that there is no performance decrease. //deg=degreeCelsius -FORCE_INLINE float degHotend0(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);}; -FORCE_INLINE float degHotend1(){ return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]);}; -FORCE_INLINE float degBed() { return analog2tempBed(current_raw[TEMPSENSOR_BED]);}; -FORCE_INLINE float degHotend(uint8_t extruder){ - if(extruder == 0) return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]); - if(extruder == 1) return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]); +FORCE_INLINE float degHotend(uint8_t extruder) { + return analog2temp(current_raw[extruder], extruder); }; -FORCE_INLINE float degTargetHotend0() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);}; -FORCE_INLINE float degTargetHotend1() { return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);}; -FORCE_INLINE float degTargetHotend(uint8_t extruder){ - if(extruder == 0) return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]); - if(extruder == 1) return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]); +FORCE_INLINE float degBed() { + return analog2tempBed(current_raw_bed); }; -FORCE_INLINE float degTargetBed() { return analog2tempBed(target_raw[TEMPSENSOR_BED]);}; - -FORCE_INLINE void setTargetHotend0(const float &celsius) -{ - target_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius); - heatingtarget_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius-HEATING_EARLY_FINISH_DEG_OFFSET); - #ifdef PIDTEMP - pid_setpoint = celsius; - #endif //PIDTEMP +FORCE_INLINE float degTargetHotend(uint8_t extruder) { + return analog2temp(target_raw[extruder], extruder); +}; + +FORCE_INLINE float degTargetBed() { + return analog2tempBed(target_raw_bed); +}; + +FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) { + target_raw[extruder] = temp2analog(celsius, extruder); +#ifdef PIDTEMP + pid_setpoint[extruder] = celsius; +#endif //PIDTEMP +}; + +FORCE_INLINE void setTargetBed(const float &celsius) { + target_raw_bed = temp2analogBed(celsius); }; -FORCE_INLINE void setTargetHotend1(const float &celsius) { target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);}; -FORCE_INLINE void setTargetHotend(const float &celcius, uint8_t extruder){ - if(extruder == 0) setTargetHotend0(celcius); - if(extruder == 1) setTargetHotend1(celcius); -}; -FORCE_INLINE void setTargetBed(const float &celsius) { target_raw[TEMPSENSOR_BED ]=temp2analogBed(celsius);}; -FORCE_INLINE bool isHeatingHotend0() {return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];}; -FORCE_INLINE bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];}; FORCE_INLINE bool isHeatingHotend(uint8_t extruder){ - if(extruder == 0) return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]; - if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1]; - return false; + return target_raw[extruder] > current_raw[extruder]; }; -FORCE_INLINE bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];}; -FORCE_INLINE bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];}; -FORCE_INLINE bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];}; -FORCE_INLINE bool isCoolingHotend(uint8_t extruder){ - if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0]; - if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1]; - return false; +FORCE_INLINE bool isHeatingBed() { + return target_raw_bed > current_raw_bed; }; -FORCE_INLINE bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];}; + +FORCE_INLINE bool isCoolingHotend(uint8_t extruder) { + return target_raw[extruder] < current_raw[extruder]; +}; + +FORCE_INLINE bool isCoolingBed() { + return target_raw_bed < current_raw_bed; +}; + +#define degHotend0() degHotend(0) +#define degTargetHotend0() degTargetHotend(0) +#define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0) +#define isHeatingHotend0() isHeatingHotend(0) +#define isCoolingHotend0() isCoolingHotend(0) +#if EXTRUDERS > 1 +#define degHotend1() degHotend(1) +#define degTargetHotend1() degTargetHotend(1) +#define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1) +#define isHeatingHotend1() isHeatingHotend(1) +#define isCoolingHotend1() isCoolingHotend(1) +#endif +#if EXTRUDERS > 2 +#define degHotend2() degHotend(2) +#define degTargetHotend2() degTargetHotend(2) +#define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2) +#define isHeatingHotend2() isHeatingHotend(2) +#define isCoolingHotend2() isCoolingHotend(2) +#endif +#if EXTRUDERS > 3 +#error Invalid number of extruders +#endif FORCE_INLINE void autotempShutdown(){ #ifdef AUTOTEMP if(autotemp_enabled) { autotemp_enabled=false; - if(degTargetHotend0()>autotemp_min) - setTargetHotend0(0); + if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min) + setTargetHotend(0,ACTIVE_EXTRUDER); } #endif } + void disable_heater(); void setWatch(); void updatePID(); diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 22d9f02487..30f5b62ac7 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -5,10 +5,9 @@ #define OVERSAMPLENR 16 -#if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORBED == 1) //100k bed thermistor +#if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor -#define NUMTEMPS_1 61 -const short temptable_1[NUMTEMPS_1][2] PROGMEM = { +const short temptable_1[][2] PROGMEM = { { 23*OVERSAMPLENR , 300 }, { 25*OVERSAMPLENR , 295 }, { 27*OVERSAMPLENR , 290 }, @@ -72,9 +71,8 @@ const short temptable_1[NUMTEMPS_1][2] PROGMEM = { { 1008*OVERSAMPLENR , 0 } //safety }; #endif -#if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORBED == 2) //200k bed thermistor -#define NUMTEMPS_2 21 -const short temptable_2[NUMTEMPS_2][2] PROGMEM = { +#if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor +const short temptable_2[][2] PROGMEM = { {1*OVERSAMPLENR, 848}, {54*OVERSAMPLENR, 275}, {107*OVERSAMPLENR, 228}, @@ -99,9 +97,8 @@ const short temptable_2[NUMTEMPS_2][2] PROGMEM = { }; #endif -#if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORBED == 3) //mendel-parts -#define NUMTEMPS_3 28 -const short temptable_3[NUMTEMPS_3][2] PROGMEM = { +#if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts +const short temptable_3[][2] PROGMEM = { {1*OVERSAMPLENR,864}, {21*OVERSAMPLENR,300}, {25*OVERSAMPLENR,290}, @@ -133,10 +130,8 @@ const short temptable_3[NUMTEMPS_3][2] PROGMEM = { }; #endif -#if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORBED == 4) //10k thermistor - -#define NUMTEMPS_4 20 -const short temptable_4[NUMTEMPS_4][2] PROGMEM = { +#if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor +const short temptable_4[][2] PROGMEM = { {1*OVERSAMPLENR, 430}, {54*OVERSAMPLENR, 137}, {107*OVERSAMPLENR, 107}, @@ -160,10 +155,8 @@ const short temptable_4[NUMTEMPS_4][2] PROGMEM = { }; #endif -#if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) - -#define NUMTEMPS_5 61 -const short temptable_5[NUMTEMPS_5][2] PROGMEM = { +#if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) +const short temptable_5[][2] PROGMEM = { {1*OVERSAMPLENR, 713}, {18*OVERSAMPLENR, 316}, {35*OVERSAMPLENR, 266}, @@ -228,9 +221,8 @@ const short temptable_5[NUMTEMPS_5][2] PROGMEM = { }; #endif -#if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor -#define NUMTEMPS_6 36 -const short temptable_6[NUMTEMPS_6][2] PROGMEM = { +#if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor +const short temptable_6[][2] PROGMEM = { {28*OVERSAMPLENR, 250}, {31*OVERSAMPLENR, 245}, {35*OVERSAMPLENR, 240}, @@ -270,9 +262,8 @@ const short temptable_6[NUMTEMPS_6][2] PROGMEM = { }; #endif -#if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 -#define NUMTEMPS_7 54 -const short temptable_7[NUMTEMPS_7][2] PROGMEM = { +#if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 +const short temptable_7[][2] PROGMEM = { {46*OVERSAMPLENR, 270}, {50*OVERSAMPLENR, 265}, {54*OVERSAMPLENR, 260}, @@ -330,82 +321,52 @@ const short temptable_7[NUMTEMPS_7][2] PROGMEM = { }; #endif +#define _TT_NAME(_N) temptable_ ## _N +#define TT_NAME(_N) _TT_NAME(_N) - -#if THERMISTORHEATER_0 == 1 -#define NUMTEMPS_HEATER_0 NUMTEMPS_1 -#define heater_0_temptable temptable_1 -#elif THERMISTORHEATER_0 == 2 -#define NUMTEMPS_HEATER_0 NUMTEMPS_2 -#define heater_0_temptable temptable_2 -#elif THERMISTORHEATER_0 == 3 -#define NUMTEMPS_HEATER_0 NUMTEMPS_3 -#define heater_0_temptable temptable_3 -#elif THERMISTORHEATER_0 == 4 -#define NUMTEMPS_HEATER_0 NUMTEMPS_4 -#define heater_0_temptable temptable_4 -#elif THERMISTORHEATER_0 == 5 -#define NUMTEMPS_HEATER_0 NUMTEMPS_5 -#define heater_0_temptable temptable_5 -#elif THERMISTORHEATER_0 == 6 -#define NUMTEMPS_HEATER_0 NUMTEMPS_6 -#define heater_0_temptable temptable_6 -#elif THERMISTORHEATER_0 == 7 -#define NUMTEMPS_HEATER_0 NUMTEMPS_7 -#define heater_0_temptable temptable_7 -#elif defined HEATER_0_USES_THERMISTOR -#error No heater 0 thermistor table specified +#ifdef THERMISTORHEATER_0 + #define heater_0_temptable TT_NAME(THERMISTORHEATER_0) + #define heater_0_temptable_len (sizeof(heater_0_temptable)/sizeof(*heater_0_temptable)) +#else +#ifdef HEATER_0_USES_THERMISTOR + #error No heater 0 thermistor table specified +#else // HEATER_0_USES_THERMISTOR + #define heater_0_temptable 0 + #define heater_0_temptable_len 0 +#endif // HEATER_0_USES_THERMISTOR #endif -#if THERMISTORHEATER_1 == 1 -#define NUMTEMPS_HEATER_1 NUMTEMPS_1 -#define heater_1_temptable temptable_1 -#elif THERMISTORHEATER_1 == 2 -#define NUMTEMPS_HEATER_1 NUMTEMPS_2 -#define heater_1_temptable temptable_2 -#elif THERMISTORHEATER_1 == 3 -#define NUMTEMPS_HEATER_1 NUMTEMPS_3 -#define heater_1_temptable temptable_3 -#elif THERMISTORHEATER_1 == 4 -#define NUMTEMPS_HEATER_1 NUMTEMPS_4 -#define heater_1_temptable temptable_4 -#elif THERMISTORHEATER_1 == 5 -#define NUMTEMPS_HEATER_1 NUMTEMPS_5 -#define heater_1_temptable temptable_5 -#elif THERMISTORHEATER_1 == 6 -#define NUMTEMPS_HEATER_1 NUMTEMPS_6 -#define heater_1_temptable temptable_6 -#elif THERMISTORHEATER_1 == 7 -#define NUMTEMPS_HEATER_1 NUMTEMPS_7 -#define heater_1_temptable temptable_7 -#elif defined HEATER_1_USES_THERMISTOR -#error No heater 1 thermistor table specified +#ifdef THERMISTORHEATER_1 + #define heater_1_temptable TT_NAME(THERMISTORHEATER_1) + #define heater_1_temptable_len (sizeof(heater_1_temptable)/sizeof(*heater_1_temptable)) +#else +#ifdef HEATER_1_USES_THERMISTOR + #error No heater 1 thermistor table specified +#else // HEATER_1_USES_THERMISTOR + #define heater_1_temptable 0 + #define heater_1_temptable_len 0 +#endif // HEATER_1_USES_THERMISTOR #endif +#ifdef THERMISTORHEATER_2 + #define heater_2_temptable TT_NAME(THERMISTORHEATER_2) + #define heater_2_temptable_len (sizeof(heater_2_temptable)/sizeof(*heater_2_temptable)) +#else +#ifdef HEATER_2_USES_THERMISTOR + #error No heater 2 thermistor table specified +#else // HEATER_2_USES_THERMISTOR + #define heater_2_temptable 0 + #define heater_2_temptable_len 0 +#endif // HEATER_2_USES_THERMISTOR +#endif -#if THERMISTORBED == 1 -#define BNUMTEMPS NUMTEMPS_1 -#define bedtemptable temptable_1 -#elif THERMISTORBED == 2 -#define BNUMTEMPS NUMTEMPS_2 -#define bedtemptable temptable_2 -#elif THERMISTORBED == 3 -#define BNUMTEMPS NUMTEMPS_3 -#define bedtemptable temptable_3 -#elif THERMISTORBED == 4 -#define BNUMTEMPS NUMTEMPS_4 -#define bedtemptable temptable_4 -#elif THERMISTORBED == 5 -#define BNUMTEMPS NUMTEMPS_5 -#define bedtemptable temptable_5 -#elif THERMISTORBED == 6 -#define BNUMTEMPS NUMTEMPS_6 -#define bedtemptable temptable_6 -#elif THERMISTORBED == 7 -#define BNUMTEMPS NUMTEMPS_7 -#define bedtemptable temptable_7 -#elif defined BED_USES_THERMISTOR -#error No bed thermistor table specified +#ifdef THERMISTORBED + #define bedtemptable TT_NAME(THERMISTORBED) + #define bedtemptable_len (sizeof(bedtemptable)/sizeof(*bedtemptable)) +#else +#ifdef BED_USES_THERMISTOR + #error No bed thermistor table specified +#endif // BED_USES_THERMISTOR #endif #endif //THERMISTORTABLES_H_ From 43f5c3e82b99210bb9dbda5937bd442485da04b1 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Wed, 7 Dec 2011 19:55:17 +0100 Subject: [PATCH 135/228] Merge branch 'Marlin_v1', remote-tracking branch 'origin/Marlin_v1' into Marlin_v1 From 460b788d78c81a63cf49e910a65bcc306ce94c55 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Wed, 7 Dec 2011 20:54:34 +0100 Subject: [PATCH 136/228] repaired homing position setting. --- Marlin/Marlin.pde | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 226a7d35df..d0b5a09253 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -539,33 +539,52 @@ FORCE_INLINE void process_commands() #ifdef QUICK_HOME if( code_seen(axis_codes[0]) && code_seen(axis_codes[1]) ) //first diagonal move { - current_position[X_AXIS] = 0; current_position[Y_AXIS] = 0; + 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]; + 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] Date: Wed, 7 Dec 2011 20:56:47 +0100 Subject: [PATCH 137/228] moved to more dominant location. --- Marlin/Marlin.h | 1 + Marlin/Marlin.pde | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 910cf46ad3..73ffd421af 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -4,6 +4,7 @@ // Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. // Licence: GPL #define HardwareSerial_h // trick to disable the standard HWserial +#include #include #if ARDUINO >= 100 #include "Arduino.h" diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index d0b5a09253..ac42c15846 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -27,6 +27,8 @@ #include #include +#include + #include "EEPROMwrite.h" #include "fastio.h" #include "Configuration.h" @@ -39,7 +41,7 @@ #include "motion_control.h" #include "cardreader.h" #include "watchdog.h" -#include + #define VERSION_STRING "1.0.0 Beta 1" From 754d2d69b2e39d4a5ce0cae66974af289f4d5c8e Mon Sep 17 00:00:00 2001 From: Bernhard Date: Wed, 7 Dec 2011 23:08:13 +0100 Subject: [PATCH 138/228] z homing sound fix, for now until the actual cause is found.. --- Marlin/stepper.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 9cf8ddd176..e993d73037 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -706,6 +706,10 @@ void st_init() sei(); } +#define TEMPORARY_Z_HOME_SOUND_FIX +#ifdef TEMPORARY_Z_HOME_SOUND_FIX + #include +#endif // Block until all buffered steps are executed void st_synchronize() { @@ -713,6 +717,10 @@ void st_synchronize() manage_heater(); manage_inactivity(1); LCD_STATUS; + #ifdef TEMPORARY_Z_HOME_SOUND_FIX + _delay_ms(200); + _delay_ms(200); + #endif } } From bae1e422f615d585081078e88103af6742ded8c4 Mon Sep 17 00:00:00 2001 From: Keegi Date: Thu, 8 Dec 2011 12:25:32 +0200 Subject: [PATCH 139/228] Fix M201 not saving settings in all places, so the changes did not get written into EEPROM --- Marlin/Marlin.pde | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index ac42c15846..9deac79669 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -984,7 +984,11 @@ FORCE_INLINE void process_commands() case 201: // M201 for(int8_t i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[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 From 61c943b4bfdb80ca8145cb66d16169a8891bdb94 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 12:32:31 +0100 Subject: [PATCH 140/228] fixed the st_synchronize. it would have continued if there is only the last move of the buffer being stepped. --- Marlin/planner.h | 10 ++++++++++ Marlin/stepper.cpp | 15 +++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Marlin/planner.h b/Marlin/planner.h index 53ac3d8447..b1e028f005 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -130,4 +130,14 @@ FORCE_INLINE block_t *plan_get_current_block() block->busy = true; return(block); } + +// Gets the current block. Returns NULL if buffer empty +FORCE_INLINE bool blocks_queued() +{ + if (block_buffer_head == block_buffer_tail) { + return false; + } + else + return true; +} #endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index e993d73037..2ef077346c 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -706,22 +706,17 @@ void st_init() sei(); } -#define TEMPORARY_Z_HOME_SOUND_FIX -#ifdef TEMPORARY_Z_HOME_SOUND_FIX - #include -#endif + +#include // Block until all buffered steps are executed void st_synchronize() { - while(plan_get_current_block()) { + while(current_block!=0 || blocks_queued()) { manage_heater(); manage_inactivity(1); LCD_STATUS; - #ifdef TEMPORARY_Z_HOME_SOUND_FIX - _delay_ms(200); - _delay_ms(200); - #endif - } + //_delay_ms(1); + } } void st_set_position(const long &x, const long &y, const long &z, const long &e) From cc4a9cdb69081f4498a5268a682c8d9674f66bcb Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 12:33:00 +0100 Subject: [PATCH 141/228] added autostart procedure trigger to the ultralcd menu --- Marlin/cardreader.h | 1 + Marlin/cardreader.pde | 6 ++++-- Marlin/ultralcd.pde | 15 ++++++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 70244a8774..70f0d2c1d9 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -44,6 +44,7 @@ public: bool cardOK ; char filename[11]; bool filenameIsDir; + int lastnr; //last number of the autostart; private: SdFile root,*curDir,workDir,workDirParent,workDirParentParent; Sd2Card card; diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 1eb19ba00c..8355f6aeda 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -14,6 +14,7 @@ CardReader::CardReader() autostart_atmillis=0; autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. + lastnr=0; //power to SD reader #if SDPOWER > -1 SET_OUTPUT(SDPOWER); @@ -334,7 +335,7 @@ void CardReader::checkautostart(bool force) if(!cardOK) //fail return; } - static int lastnr=0; + char autoname[30]; sprintf(autoname,"auto%i.g",lastnr); for(int8_t i=0;i<(int)strlen(autoname);i++) @@ -434,7 +435,8 @@ void CardReader::printingHasFinished() sdprinting = false; if(SD_FINISHED_STEPPERRELEASE) { - finishAndDisableSteppers(); + //finishAndDisableSteppers(); + enquecommand("M84"); } autotempShutdown(); } diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 88f8f32fb3..e89474ed28 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -437,7 +437,7 @@ void MainMenu::showStatus() force_lcd_update=false; } -enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; +enum {ItemP_exit, ItemP_autostart,ItemP_disstep,ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude}; //any action must not contain a ',' character anywhere, or this breaks: #define MENUITEM(repaint_action, click_action) \ @@ -458,6 +458,12 @@ void MainMenu::showPrepare() case ItemP_exit: MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; break; + case ItemP_autostart: + MENUITEM( lcdprintPGM(" Autostart") , BLOCK;card.lastnr=0;card.checkautostart(true);beepshort(); ) ; + break; + case ItemP_disstep: + MENUITEM( lcdprintPGM(" Disable Steppers") , BLOCK;enquecommand("M84");beepshort(); ) ; + break; case ItemP_home: MENUITEM( lcdprintPGM(" Auto Home") , BLOCK;enquecommand("G28 X-105 Y-105 Z0");beepshort(); ) ; break; @@ -470,15 +476,14 @@ void MainMenu::showPrepare() case ItemP_extrude: MENUITEM( lcdprintPGM(" Extrude") , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ; break; - case ItemP_disstep: - MENUITEM( lcdprintPGM(" Disable Steppers") , BLOCK;enquecommand("M84");beepshort(); ) ; - break; + + default: break; } line++; } - updateActiveLines(ItemP_disstep,encoderpos); + updateActiveLines(ItemP_extrude,encoderpos); } enum {ItemT_exit,ItemT_speed,ItemT_flow,ItemT_nozzle,ItemT_fan}; From 5b4625f79c9f5176168fd101b1cae74e829f6d93 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 12:51:08 +0100 Subject: [PATCH 142/228] added a partial release option to "m84" aka "stepper release". If you do tiny layers, you might want to keep the z-axis powered to not loose height positioning after homeing. --- Marlin/Configuration.h | 1 + Marlin/Marlin.pde | 24 ++++++++++++++---------- Marlin/cardreader.pde | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index e8b960f788..febc3bcca6 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -292,6 +292,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //#define ULTRA_LCD //general lcd support, also 16x2 //#define SDSUPPORT // Enable SD Card Support in Hardware Console #define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? +#define SD_FINISHED_RELEASECOMMAND "M84 X Y E" // no z because of layer shift. //#define ULTIPANEL #ifdef ULTIPANEL diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index ac42c15846..f3182a7d05 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -903,18 +903,22 @@ FORCE_INLINE void process_commands() } else { - #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS - if(code_seen('E')) { + 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) + { + finishAndDisableSteppers(); + } + else + { st_synchronize(); - LCD_MESSAGEPGM("Free Move"); - disable_e(); + if(code_seen('X')) disable_x(); + if(code_seen('Y')) disable_y(); + if(code_seen('Z')) disable_z(); + #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS + if(code_seen('E')) disable_e(); + #endif + LCD_MESSAGEPGM("Partial Release"); } - else { - finishAndDisableSteppers(); - } - #else - finishAndDisableSteppers(); - #endif } break; case 85: // M85 diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 8355f6aeda..6ad04068e4 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -436,7 +436,7 @@ void CardReader::printingHasFinished() if(SD_FINISHED_STEPPERRELEASE) { //finishAndDisableSteppers(); - enquecommand("M84"); + enquecommand(SD_FINISHED_RELEASECOMMAND); } autotempShutdown(); } From 1ec0c3b68a250ef5d947509122777ed5ba43a91f Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 13:39:00 +0100 Subject: [PATCH 143/228] extruder runout prevention. --- Marlin/Configuration.h | 8 ++++++++ Marlin/Marlin.pde | 24 ++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index febc3bcca6..222fb3aded 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -156,6 +156,14 @@ #endif #endif // PIDTEMP +// extruder run-out prevention. +//if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded +//#define EXTRUDER_RUNOUT_PREVENT +#define EXTRUDER_RUNOUT_MINTEMP 190 +#define EXTRUDER_RUNOUT_SECONDS 60 +#define EXTRUDER_RUNOUT_EXTRUDE 10 //mm filament +#define EXTRUDER_RUNOUT_SPEED 20 //extrusion speed + //=========================================================================== //=============================Mechanical Settings=========================== diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index f3182a7d05..e80628e8bb 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -499,19 +499,16 @@ FORCE_INLINE void process_commands() case 1: // G1 get_coordinates(); // For X Y Z E F prepare_move(); - previous_millis_cmd = millis(); //ClearToSend(); return; //break; case 2: // G2 - CW ARC get_arc_coordinates(); prepare_arc_move(true); - previous_millis_cmd = millis(); return; case 3: // G3 - CCW ARC get_arc_coordinates(); prepare_arc_move(false); - previous_millis_cmd = millis(); return; case 4: // G4 dwell LCD_MESSAGEPGM("DWELL..."); @@ -521,7 +518,7 @@ FORCE_INLINE void process_commands() st_synchronize(); codenum += millis(); // keep track of when we started waiting - + previous_millis_cmd = millis(); while(millis() < codenum ){ manage_heater(); } @@ -837,6 +834,7 @@ FORCE_INLINE void process_commands() } LCD_MESSAGEPGM("Heating done."); starttime=millis(); + previous_millis_cmd = millis(); } break; case 190: // M190 - Wait bed for heater to reach target. @@ -860,6 +858,7 @@ FORCE_INLINE void process_commands() manage_heater(); } LCD_MESSAGEPGM("Bed done."); + previous_millis_cmd = millis(); #endif break; @@ -1149,6 +1148,7 @@ FORCE_INLINE void get_arc_coordinates() void prepare_move() { + if (min_software_endstops) { if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0; if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0; @@ -1165,6 +1165,7 @@ void prepare_move() for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } + previous_millis_cmd = millis(); } void prepare_arc_move(char isclockwise) { @@ -1179,6 +1180,7 @@ void prepare_arc_move(char isclockwise) { for(int8_t i=0; i < NUM_AXIS; i++) { current_position[i] = destination[i]; } + previous_millis_cmd = millis(); } void manage_inactivity(byte debug) @@ -1194,6 +1196,20 @@ void manage_inactivity(byte debug) disable_z(); disable_e(); } + #ifdef EXTRUDER_RUNOUT_PREVENT + if( (millis()-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) + if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) + { + enable_e(); + 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_SPEED*feedmultiply/60/100.0, active_extruder); + current_position[E_AXIS]=oldepos; + destination[E_AXIS]=oldedes; + plan_set_e_position(oldepos); + previous_millis_cmd=millis(); + } + #endif check_axes_activity(); } From 87fd249c4311fc3de7e1872f742b5ae3b632e85b Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 13:56:28 +0100 Subject: [PATCH 144/228] made runout prevention independent of tempeorarily set esteps --- Marlin/Configuration.h | 5 +++-- Marlin/Marlin.pde | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 222fb3aded..9574e09823 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -161,8 +161,9 @@ //#define EXTRUDER_RUNOUT_PREVENT #define EXTRUDER_RUNOUT_MINTEMP 190 #define EXTRUDER_RUNOUT_SECONDS 60 -#define EXTRUDER_RUNOUT_EXTRUDE 10 //mm filament -#define EXTRUDER_RUNOUT_SPEED 20 //extrusion speed +#define EXTRUDER_RUNOUT_ESTEPS 14 //mm filament +#define EXTRUDER_RUNOUT_EXTRUDE 100 //mm filament +#define EXTRUDER_RUNOUT_SPEED 1500 //extrusion speed //=========================================================================== diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index e80628e8bb..30d65d3d9d 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1203,7 +1203,9 @@ void manage_inactivity(byte debug) enable_e(); 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_SPEED*feedmultiply/60/100.0, active_extruder); + 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*feedmultiply/60/100.0*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); From aa4f9a64746f213cafce7cf58414d47619824a2b Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 14:07:32 +0100 Subject: [PATCH 145/228] better values. --- Marlin/Configuration.h | 8 ++++---- Marlin/Marlin.pde | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 9574e09823..47ad0b7320 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -160,10 +160,10 @@ //if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded //#define EXTRUDER_RUNOUT_PREVENT #define EXTRUDER_RUNOUT_MINTEMP 190 -#define EXTRUDER_RUNOUT_SECONDS 60 -#define EXTRUDER_RUNOUT_ESTEPS 14 //mm filament -#define EXTRUDER_RUNOUT_EXTRUDE 100 //mm filament -#define EXTRUDER_RUNOUT_SPEED 1500 //extrusion speed +#define EXTRUDER_RUNOUT_SECONDS 60. +#define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament +#define EXTRUDER_RUNOUT_EXTRUDE 50. //mm filament +#define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed //=========================================================================== diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 30d65d3d9d..b3291cb0be 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1205,7 +1205,7 @@ void manage_inactivity(byte debug) 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*feedmultiply/60/100.0*EXTRUDER_RUNOUT_ESTEPS/axis_steps_per_unit[E_AXIS], active_extruder); + 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); From 2bc5e7ec9efeeb2c72b1448565ce3c5481248f3b Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 15:09:52 +0100 Subject: [PATCH 146/228] prevent too long extrudes, or too cold extrudes --- Marlin/Configuration.h | 13 ++++++++++--- Marlin/Marlin.pde | 27 +++++++++++++++++++-------- Marlin/planner.cpp | 28 ++++++++++++++++++++++++++-- Marlin/planner.h | 2 ++ 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 47ad0b7320..2b60c3602a 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -20,9 +20,6 @@ // if unwanted behavior is observed on a user's machine when running at very slow speeds. #define MINIMUM_PLANNER_SPEED 2.0 // (mm/sec) -// If defined the movements slow down when the look ahead buffer is only half full -#define SLOWDOWN - // BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration //// The following define selects which electronics board you have. Please choose the one that matches your setup @@ -248,7 +245,12 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define DEFAULT_XYJERK 20.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) +// If defined the movements slow down when the look ahead buffer is only half full +#define SLOWDOWN +//default stepper release if idle +#define DEFAULT_STEPPER_DEACTIVE_TIME 60 +#define DEFAULT_STEPPER_DEACTIVE_COMMAND "M84 X Y E" //z stays powered //=========================================================================== @@ -338,6 +340,11 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define AUTOTEMP_OLDWEIGHT 0.98 #endif +//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit +//can be software-disabled for whatever purposes by +#define PREVENT_DANGEROUS_EXTRUDE +#define EXTRUDE_MINTEMP 190 +#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. const int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index b3291cb0be..c6251927e6 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -110,6 +110,7 @@ // M206 - set additional homeing offset // M220 - set speed factor override percentage S:factor in percent // M301 - Set PID parameters P I and D +// M302 - Allow cold extrudes // M400 - Finish all moves // M500 - stores paramters in EEPROM // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). @@ -176,7 +177,8 @@ const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 //Inactivity shutdown variables static unsigned long previous_millis_cmd = 0; static unsigned long max_inactive_time = 0; -static unsigned long stepper_inactive_time = 0; +static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000; +static unsigned long last_stepperdisabled_time=30*1000; //first release check after 30 seconds static unsigned long starttime=0; static unsigned long stoptime=0; @@ -1057,6 +1059,12 @@ FORCE_INLINE void process_commands() } break; #endif //PIDTEMP + + case 302: // finish all moves + { + allow_cold_extrudes(true); + } + break; case 400: // finish all moves { st_synchronize(); @@ -1188,14 +1196,17 @@ void manage_inactivity(byte debug) if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); - if( (millis()-previous_millis_cmd) > stepper_inactive_time ) - if(stepper_inactive_time) - { - disable_x(); - disable_y(); - disable_z(); - disable_e(); + if(stepper_inactive_time) + if( (millis()-last_stepperdisabled_time) > stepper_inactive_time ) + { + if(previous_millis_cmd>last_stepperdisabled_time) + last_stepperdisabled_time=previous_millis_cmd; + else + { + enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); + last_stepperdisabled_time=millis(); } + } #ifdef EXTRUDER_RUNOUT_PREVENT if( (millis()-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index a8f41d3532..df255443dc 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -106,7 +106,9 @@ volatile unsigned char block_buffer_tail; // Index of the block to pro //=========================================================================== //=============================private variables ============================ //=========================================================================== - +#ifdef PREVENT_DANGEROUS_EXTRUDE + bool allow_cold_extrude=false; +#endif #ifdef XY_FREQUENCY_LIMIT // Used for the frequency limit static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations @@ -465,7 +467,23 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + + #ifdef PREVENT_DANGEROUS_EXTRUDE + if(target[E_AXIS]!=position[E_AXIS]) + if(degHotend(active_extruder)axis_steps_per_unit[E_AXIS]*EXTRUDE_MAXLENGTH) + { + position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM(" too long extrusion prevented"); + } + #endif // Prepare to set up new block block_t *block = &block_buffer[block_buffer_head]; @@ -786,3 +804,9 @@ uint8_t movesplanned() return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); } +void allow_cold_extrudes(bool allow) +{ + #ifdef PREVENT_DANGEROUS_EXTRUDE + allow_cold_extrude=allow; + #endif +} \ No newline at end of file diff --git a/Marlin/planner.h b/Marlin/planner.h index b1e028f005..b2d1c6c6cb 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -140,4 +140,6 @@ FORCE_INLINE bool blocks_queued() else return true; } + +void allow_cold_extrudes(bool allow); #endif From dde4b40fa9e312bb6cb76b7fe9c8e0f8a2e28caf Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 15:37:24 +0100 Subject: [PATCH 147/228] disable steppers in runout prevention --- Marlin/Marlin.pde | 1 + 1 file changed, 1 insertion(+) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index c6251927e6..05924b93a4 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1221,6 +1221,7 @@ void manage_inactivity(byte debug) destination[E_AXIS]=oldedes; plan_set_e_position(oldepos); previous_millis_cmd=millis(); + enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); } #endif check_axes_activity(); From b1d84d879b7ddb6119ce7c8a5ce2c8df9986636e Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 16:13:58 +0100 Subject: [PATCH 148/228] st_synchronize back to normal.. --- Marlin/stepper.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 2ef077346c..33c7e154c1 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -707,15 +707,13 @@ void st_init() } -#include // Block until all buffered steps are executed void st_synchronize() { - while(current_block!=0 || blocks_queued()) { + while( blocks_queued()) { manage_heater(); manage_inactivity(1); LCD_STATUS; - //_delay_ms(1); } } From 88ee053af0a7d71cea23cbc1adf5b101e0b1a7fa Mon Sep 17 00:00:00 2001 From: Bernhard Date: Fri, 9 Dec 2011 17:06:56 +0100 Subject: [PATCH 149/228] heating up santity, formarly knows as "watchdog", but renamed due to the existance of the real watchdog, works now. --- Marlin/Configuration.h | 10 +++++----- Marlin/temperature.cpp | 19 ++++++++++++++++--- Marlin/temperature.h | 8 ++++---- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 2b60c3602a..e2fe8403e7 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -58,11 +58,11 @@ #define BED_CHECK_INTERVAL 5000 //ms -//// Experimental watchdog and minimal temp -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 -/// CURRENTLY NOT IMPLEMENTED AND UNUSEABLE -//#define WATCHPERIOD 5000 //5 seconds +//// Heating sanity check: +// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. +// It can be reset with another M104/M109 +//#define WATCHPERIOD 20000 //20 seconds // Actual temperature must be close to target for this long before M109 returns success //#define TEMP_RESIDENCY_TIME 20 // (seconds) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index ac5aeaa3e5..785da6c926 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -88,7 +88,7 @@ static unsigned long previous_millis_bed_heater; #endif //PIDTEMP #ifdef WATCHPERIOD - static int watch_raw[3] = {-1000,-1000,-1000}; + static int watch_oldtemp[3] = {0,0,0}; static unsigned long watchmillis = 0; #endif //WATCHPERIOD @@ -186,7 +186,20 @@ void manage_heater() WRITE(HEATER_0_PIN,LOW); } #endif - + + #ifdef WATCHPERIOD + if(watchmillis && millis() - watchmillis > WATCHPERIOD){ + if(watch_oldtemp[TEMPSENSOR_HOTEND_0] >= degHotend(active_extruder)){ + setTargetHotend(0,active_extruder); + LCD_MESSAGEPGM("Heating failed"); + SERIAL_ECHO_START; + SERIAL_ECHOLN("Heating failed"); + }else{ + watchmillis = 0; + } + } + #endif + if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) return; previous_millis_bed_heater = millis(); @@ -426,7 +439,7 @@ void setWatch() if(isHeatingHotend0()) { watchmillis = max(1,millis()); - watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0]; + watch_oldtemp[TEMPSENSOR_HOTEND_0] = degHotend(0); } else { diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 623f890bb0..fae27f734c 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -49,10 +49,10 @@ extern float Kp,Ki,Kd,Kc; extern float pid_setpoint ; #endif -#ifdef WATCHPERIOD - extern int watch_raw[3] ; - extern unsigned long watchmillis; -#endif +// #ifdef WATCHPERIOD +// extern int watch_raw[3] ; +// extern unsigned long watchmillis; +// #endif From 01001b89d200111f95be0d7ce87aa16e91ddf998 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 11 Dec 2011 15:42:56 +0100 Subject: [PATCH 150/228] repaired nozzle runout prevention to not collide with automatic stepper disabeling. --- Marlin/Configuration.h | 3 +-- Marlin/Marlin.pde | 12 +++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index e2fe8403e7..dc8c799f5b 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -157,9 +157,8 @@ //if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded //#define EXTRUDER_RUNOUT_PREVENT #define EXTRUDER_RUNOUT_MINTEMP 190 -#define EXTRUDER_RUNOUT_SECONDS 60. +#define EXTRUDER_RUNOUT_SECONDS 30. #define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament -#define EXTRUDER_RUNOUT_EXTRUDE 50. //mm filament #define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 538920da2f..0a8a80c4ce 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -235,7 +235,9 @@ void setup() SERIAL_PROTOCOLLNPGM("start"); SERIAL_ECHO_START; SERIAL_ECHOPGM("Free Memory:"); - SERIAL_ECHOLN(freeMemory()); + SERIAL_ECHO(freeMemory()); + SERIAL_ECHOPGM(" PlannerBufferBytes:"); + SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE); for(int8_t i = 0; i < BUFSIZE; i++) { fromsd[i] = false; @@ -1207,7 +1209,8 @@ void manage_inactivity(byte debug) last_stepperdisabled_time=previous_millis_cmd; else { - enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); + if( (X_ENABLE_ON && (READ(X_ENABLE_PIN)!=0)) || (!X_ENABLE_ON && READ(X_ENABLE_PIN)==0) ) + enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); last_stepperdisabled_time=millis(); } } @@ -1215,6 +1218,7 @@ void manage_inactivity(byte debug) if( (millis()-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) { + bool oldstatus=READ(E_ENABLE_PIN); enable_e(); float oldepos=current_position[E_AXIS]; float oldedes=destination[E_AXIS]; @@ -1225,7 +1229,9 @@ void manage_inactivity(byte debug) destination[E_AXIS]=oldedes; plan_set_e_position(oldepos); previous_millis_cmd=millis(); - enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); + //enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); + st_synchronize(); + WRITE(E_ENABLE_PIN,oldstatus); } #endif check_axes_activity(); From 82c99625facf9711dc974759f3ed31320abd90d2 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 11 Dec 2011 22:10:06 +0100 Subject: [PATCH 151/228] instant stop of sd prints from the panel. --- Marlin/cardreader.pde | 1 + Marlin/stepper.cpp | 9 +++++++++ Marlin/stepper.h | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 6ad04068e4..735a1cdcd8 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -432,6 +432,7 @@ void CardReader::updir() void CardReader::printingHasFinished() { + quickStop(); sdprinting = false; if(SD_FINISHED_STEPPERRELEASE) { diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 33c7e154c1..51a9fe0719 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -752,3 +752,12 @@ void finishAndDisableSteppers() disable_z(); disable_e(); } + +void quickStop() +{ + DISABLE_STEPPER_DRIVER_INTERRUPT(); + while(blocks_queued()) + plan_discard_current_block(); + ENABLE_STEPPER_DRIVER_INTERRUPT(); +} + diff --git a/Marlin/stepper.h b/Marlin/stepper.h index fd388ca68b..37ce3b5469 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -52,5 +52,5 @@ void finishAndDisableSteppers(); extern block_t *current_block; // A pointer to the block currently being traced - +void quickStop(); #endif From 06411d5c9e39bda41be21d56cec0f4cc21e2e612 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 11 Dec 2011 22:18:50 +0100 Subject: [PATCH 152/228] ultralcd can now also stop the wait loop for the hot-end m109 heating when stopping sd prints. --- Marlin/Marlin.h | 1 + Marlin/Marlin.pde | 3 ++- Marlin/cardreader.pde | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 73ffd421af..8f98244089 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -131,5 +131,6 @@ extern float homing_feedrate[]; extern bool axis_relative_modes[]; extern float current_position[NUM_AXIS] ; extern float add_homeing[3]; +extern bool stop_heating_wait; #endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 0a8a80c4ce..4d031ea788 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -138,7 +138,7 @@ int saved_feedmultiply; volatile bool feedmultiplychanged=false; float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; float add_homeing[3]={0,0,0}; - +bool stop_heating_wait=false; //=========================================================================== //=============================private variables============================= //=========================================================================== @@ -825,6 +825,7 @@ FORCE_INLINE void process_commands() } manage_heater(); LCD_STATUS; + if(stop_heating_wait) break; #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 */ diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 735a1cdcd8..2cf44e6cd3 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -434,6 +434,7 @@ void CardReader::printingHasFinished() { quickStop(); sdprinting = false; + stop_heating_wait=true; if(SD_FINISHED_STEPPERRELEASE) { //finishAndDisableSteppers(); From 3320a5b37d9125d29dba6108a2846257c3d3b470 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 11 Dec 2011 22:25:52 +0100 Subject: [PATCH 153/228] make autotemp compatile for use without pid --- Marlin/temperature.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Marlin/temperature.h b/Marlin/temperature.h index fae27f734c..2580947e7e 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -23,6 +23,7 @@ #include "Marlin.h" #include "fastio.h" +#include "planner.h" #ifdef PID_ADD_EXTRUSION_RATE #include "stepper.h" #endif From e017228569511382298c2ff9a347a78542351cd6 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 12 Dec 2011 19:34:37 +0100 Subject: [PATCH 154/228] Merged multiple extruder support. Soft PWM. (Sanguinololu can also have PID temperature control) Interrupt save WRITE for addresses > 0x0FF --- Marlin/Configuration.h | 95 +- Marlin/Marlin.h | 2 - Marlin/Marlin.pde | 46 +- Marlin/fastio.h | 5153 ++++++++++++++++++++-------------------- Marlin/pins.h | 1473 ++++++------ Marlin/planner.cpp | 4 +- Marlin/stepper.cpp | 80 +- Marlin/stepper.h | 15 + Marlin/temperature.cpp | 105 +- Marlin/temperature.h | 285 +-- Marlin/ultralcd.pde | 3680 ++++++++++++++-------------- 11 files changed, 5525 insertions(+), 5413 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 346db503fd..d4e23bd162 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -4,11 +4,11 @@ // This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 +#define BAUDRATE 250000 +//#define BAUDRATE 115200 //#define BAUDRATE 230400 -#define EXTRUDERS 2 +#define EXTRUDERS 1 // Frequency limit // See nophead's blog for more info @@ -32,7 +32,7 @@ // Sanguinololu 1.2 and above = 62 // Ultimaker = 7, // Teensylu = 8 -#define MOTHERBOARD 33 +#define MOTHERBOARD 7 //=========================================================================== //=============================Thermal Settings ============================ @@ -46,16 +46,21 @@ // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 -#define THERMISTORHEATER_0 1 -#define THERMISTORHEATER_1 1 -#define HEATER_0_USES_THERMISTOR -#define HEATER_1_USES_THERMISTOR -//#define HEATER_0_USES_AD595 + +//#define THERMISTORHEATER_0 3 +//#define THERMISTORHEATER_1 1 +//#define THERMISTORHEATER_2 1 + +//#define HEATER_0_USES_THERMISTOR +//#define HEATER_1_USES_THERMISTOR +//#define HEATER_2_USES_THERMISTOR +#define HEATER_0_USES_AD595 //#define HEATER_1_USES_AD595 +//#define HEATER_2_USES_AD595 // Select one of these only to define how the bed temp is read. -#define THERMISTORBED 1 -#define BED_USES_THERMISTOR +//#define THERMISTORBED 1 +//#define BED_USES_THERMISTOR //#define BED_USES_AD595 #define BED_CHECK_INTERVAL 5000 //ms @@ -73,7 +78,8 @@ //// The minimal temperature defines the temperature below which the heater will not be enabled #define HEATER_0_MINTEMP 5 //#define HEATER_1_MINTEMP 5 -#define BED_MINTEMP 5 +//#define HEATER_2_MINTEMP 5 +//#define BED_MINTEMP 5 // When temperature exceeds max temp, your heater will be switched off. @@ -81,7 +87,8 @@ // You should use MINTEMP for thermistor short/failure protection. #define HEATER_0_MAXTEMP 275 //#define HEATER_1_MAXTEMP 275 -#define BED_MAXTEMP 150 +//#define HEATER_2_MAXTEMP 275 +//#define BED_MAXTEMP 150 // Wait for Cooldown @@ -92,21 +99,17 @@ // Heating is finished if a temperature close to this degree shift is reached #define HEATING_EARLY_FINISH_DEG_OFFSET 1 //Degree + // PID settings: // Uncomment the following line to enable PID support. - #define PIDTEMP +#define PID_MAX 255 // limits current to nozzle; 255=full current #ifdef PIDTEMP - #if MOTHERBOARD == 62 - #error Sanguinololu does not support PID, sorry. Please disable it. - #endif //#define PID_DEBUG // Sends debug data to the serial port. //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - - #define PID_MAX 255 // limits current to nozzle; 255=full current #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term #define K1 0.95 //smoothing factor withing the PID - #define PID_dT 0.1 //sampling period of the PID + #define PID_dT 0.128 //sampling period of the PID //To develop some PID settings for your machine, you can initiall follow // the Ziegler-Nichols method. @@ -130,14 +133,14 @@ // #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) // Ultitmaker -// #define DEFAULT_Kp 22.2 -// #define DEFAULT_Ki (1.25*PID_dT) -// #define DEFAULT_Kd (99/PID_dT) + #define DEFAULT_Kp 22.2 + #define DEFAULT_Ki (1.25*PID_dT) + #define DEFAULT_Kd (99/PID_dT) // Makergear - #define DEFAULT_Kp 7.0 - #define DEFAULT_Ki 0.1 - #define DEFAULT_Kd 12 +// #define DEFAULT_Kp 7.0 +// #define DEFAULT_Ki 0.1 +// #define DEFAULT_Kd 12 // Mendel Parts V9 on 12V // #define DEFAULT_Kp 63.0 @@ -170,12 +173,12 @@ #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. -const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. -const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false -//#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing +#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 @@ -186,7 +189,7 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t // Disables axis when it's not being used. #define DISABLE_X false #define DISABLE_Y false -#define DISABLE_Z true +#define DISABLE_Z false #define DISABLE_E false // For all extruders // Inverting axis direction @@ -195,11 +198,11 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t //#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true //#define INVERT_E*_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false, used for all extruders -#define INVERT_X_DIR false // for Mendel set to false, for Orca set to true +#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false #define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true #define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false #define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false //// ENDSTOP SETTINGS: @@ -208,15 +211,15 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define Y_HOME_DIR -1 #define Z_HOME_DIR -1 -#define min_software_endstops false //If true, axis won't move to coordinates less than zero. -#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 210 -#define Y_MAX_LENGTH 210 -#define Z_MAX_LENGTH 210 +#define min_software_endstops true //If true, axis won't move to coordinates less than zero. +#define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. +#define X_MAX_LENGTH 205 +#define Y_MAX_LENGTH 205 +#define Z_MAX_LENGTH 200 //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {30*60, 30*60, 2*60, 0} // set the homing speeds (mm/min) +#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again: #define X_HOME_RETRACT_MM 5 @@ -230,9 +233,9 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t // default settings -//#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker -//#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 67} //sells mendel with v9 extruder -#define DEFAULT_AXIS_STEPS_PER_UNIT {80.3232, 80.8900, 2284.7651, 757.2218} // SAE Prusa w/ Wade extruder +#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker +//#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 360} //sells mendel with v9 extruder +//#define DEFAULT_AXIS_STEPS_PER_UNIT {80.3232, 80.8900, 2284.7651, 757.2218} // SAE Prusa w/ Wade extruder #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. @@ -283,10 +286,10 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t // hooke's law says: force = k * distance // bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant // so: v ^ 2 is proportional to number of steps we advance the extruder -//#define ADVANCE +#define ADVANCE #ifdef ADVANCE - #define EXTRUDER_ADVANCE_K .3 + #define EXTRUDER_ADVANCE_K .0 #define D_FILAMENT 2.85 #define STEPS_MM_E 836 @@ -298,10 +301,10 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 -#define SDSUPPORT // Enable SD Card Support in Hardware Console +//#define SDSUPPORT // Enable SD Card Support in Hardware Console #define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? -//#define ULTIPANEL +#define ULTIPANEL #ifdef ULTIPANEL //#define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 626f61b6c8..d4654a3862 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -57,8 +57,6 @@ const prog_char echomagic[] PROGMEM ="echo:"; #define SERIAL_ECHOPAIR(name,value) {SERIAL_ECHOPGM(name);SERIAL_ECHO(value);} -// Macro for getting current active extruder -#define ACTIVE_EXTRUDER (active_extruder) //things to write to serial from Programmemory. saves 400 to 2k of RAM. #define SerialprintPGM(x) serialprintPGM(MYPGM(x)) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 9b765ebd05..183002fe25 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -465,16 +465,16 @@ FORCE_INLINE bool code_seen(char code) plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \ destination[LETTER##_AXIS] = 1.5 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ feedrate = homing_feedrate[LETTER##_AXIS]; \ - prepare_move(); \ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ current_position[LETTER##_AXIS] = 0;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ - prepare_move(); \ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ - prepare_move(); \ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? 0 : LETTER##_MAX_LENGTH;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ @@ -541,6 +541,7 @@ FORCE_INLINE void process_commands() if( code_seen(axis_codes[0]) && code_seen(axis_codes[1]) ) //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; @@ -723,7 +724,7 @@ FORCE_INLINE void process_commands() if (code_seen('S')) setTargetBed(code_value()); break; case 105 : // M105 - tmp_extruder = ACTIVE_EXTRUDER; + tmp_extruder = active_extruder; if(code_seen('T')) { tmp_extruder = code_value(); if(tmp_extruder >= EXTRUDERS) { @@ -743,6 +744,10 @@ FORCE_INLINE void process_commands() #else SERIAL_ERROR_START; SERIAL_ERRORLNPGM("No thermistors - no temp"); + #endif + #ifdef PIDTEMP + SERIAL_PROTOCOLPGM(" @:"); + SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); #endif SERIAL_PROTOCOLLN(""); return; @@ -788,24 +793,26 @@ FORCE_INLINE void process_commands() while((residencyStart == -1) || (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else - while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { + while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { #endif //TEMP_RESIDENCY_TIME if( (millis() - codenum) > 1000 ) { //Print Temp Reading and remaining time every 1 second while heating up/cooling down SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOLLN( degHotend(tmp_extruder) ); + SERIAL_PROTOCOL( degHotend(tmp_extruder) ); SERIAL_PROTOCOLPGM(" E:"); SERIAL_PROTOCOLLN( (int)tmp_extruder ); - SERIAL_PROTOCOLPGM(" W:"); - if(residencyStart > -1) - { - codenum = TEMP_RESIDENCY_TIME - ((millis() - residencyStart) / 1000); - SERIAL_PROTOCOLLN( codenum ); - } - else - { - SERIAL_PROTOCOLLN( "?" ); - } + #ifdef TEMP_RESIDENCY_TIME + SERIAL_PROTOCOLPGM(" W:"); + if(residencyStart > -1) + { + codenum = TEMP_RESIDENCY_TIME - ((millis() - residencyStart) / 1000); + SERIAL_PROTOCOLLN( codenum ); + } + else + { + SERIAL_PROTOCOLLN( "?" ); + } + #endif codenum = millis(); } manage_heater(); @@ -834,11 +841,11 @@ FORCE_INLINE void process_commands() { if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { - float tt=degHotend(ACTIVE_EXTRUDER); + float tt=degHotend(active_extruder); SERIAL_PROTOCOLPGM("T:"); SERIAL_PROTOCOL(tt); SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOLLN( (int)tmp_extruder ); + SERIAL_PROTOCOLLN( (int)active_extruder ); SERIAL_PROTOCOLPGM(" B:"); SERIAL_PROTOCOLLN(degBed()); codenum = millis(); @@ -1191,6 +1198,7 @@ void manage_inactivity(byte debug) void kill() { + cli(); // Stop interrupts disable_heater(); disable_x(); @@ -1207,4 +1215,4 @@ void kill() while(1); // Wait for reset } - + diff --git a/Marlin/fastio.h b/Marlin/fastio.h index 634571e3a1..5188a0681a 100644 --- a/Marlin/fastio.h +++ b/Marlin/fastio.h @@ -1,2573 +1,2582 @@ -/* - This code contibuted by Triffid_Hunter and modified by Kliment - why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html -*/ - -#ifndef _ARDUINO_H -#define _ARDUINO_H - -#include - -/* - utility functions -*/ - -#ifndef MASK -/// MASKING- returns \f$2^PIN\f$ - #define MASK(PIN) (1 << PIN) -#endif - -/* - magic I/O routines - - now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0); -*/ - -/// Read a pin -#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) -/// write to a pin -#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) -//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) -/// toggle a pin -#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) - -/// set pin as input -#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0) -/// set pin as output -#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0) - -/// check if pin is an input -#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0) -/// check if pin is an output -#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0) - -// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html - -/// Read a pin wrapper -#define READ(IO) _READ(IO) -/// Write to a pin wrapper -#define WRITE(IO, v) _WRITE(IO, v) -#if EXTRUDERS > 2 - #define WRITE_E_STEP(v) { if(ACTIVE_EXTRUDER == 2) { WRITE(E2_STEP_PIN, v); } else { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}} - #define NORM_E_DIR() { if(ACTIVE_EXTRUDER == 2) { WRITE(E2_DIR_PIN, INVERT_E2_DIR); } else { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}} - #define REV_E_DIR() { if(ACTIVE_EXTRUDER == 2) { WRITE(E2_DIR_PIN, !INVERT_E2_DIR); } else { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}} -#elif EXTRUDERS > 1 - #define WRITE_E_STEP(v) { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }} - #define NORM_E_DIR() { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }} - #define REV_E_DIR() { if(ACTIVE_EXTRUDER == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }} -#else - #define WRITE_E_STEP(v) WRITE(E0_STEP_PIN, v) - #define NORM_E_DIR() WRITE(E0_DIR_PIN, INVERT_E0_DIR) - #define REV_E_DIR() WRITE(E0_DIR_PIN, !INVERT_E0_DIR) -#endif - -/// toggle a pin wrapper -#define TOGGLE(IO) _TOGGLE(IO) - -/// set pin as input wrapper -#define SET_INPUT(IO) _SET_INPUT(IO) -/// set pin as output wrapper -#define SET_OUTPUT(IO) _SET_OUTPUT(IO) - -/// check if pin is an input wrapper -#define GET_INPUT(IO) _GET_INPUT(IO) -/// check if pin is an output wrapper -#define GET_OUTPUT(IO) _GET_OUTPUT(IO) - -/* - ports and functions - - added as necessary or if I feel like it- not a comprehensive list! -*/ - -#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) -// UART -#define RXD DIO0 -#define TXD DIO1 - -// SPI -#define SCK DIO13 -#define MISO DIO12 -#define MOSI DIO11 -#define SS DIO10 - -// TWI (I2C) -#define SCL AIO5 -#define SDA AIO4 - -// timers and PWM -#define OC0A DIO6 -#define OC0B DIO5 -#define OC1A DIO9 -#define OC1B DIO10 -#define OC2A DIO11 -#define OC2B DIO3 - -#define DEBUG_LED AIO5 - -/* -pins -*/ - -#define DIO0_PIN PIND0 -#define DIO0_RPORT PIND -#define DIO0_WPORT PORTD -#define DIO0_DDR DDRD -#define DIO0_PWM NULL - -#define DIO1_PIN PIND1 -#define DIO1_RPORT PIND -#define DIO1_WPORT PORTD -#define DIO1_DDR DDRD -#define DIO1_PWM NULL - -#define DIO2_PIN PIND2 -#define DIO2_RPORT PIND -#define DIO2_WPORT PORTD -#define DIO2_DDR DDRD -#define DIO2_PWM NULL - -#define DIO3_PIN PIND3 -#define DIO3_RPORT PIND -#define DIO3_WPORT PORTD -#define DIO3_DDR DDRD -#define DIO3_PWM &OCR2B - -#define DIO4_PIN PIND4 -#define DIO4_RPORT PIND -#define DIO4_WPORT PORTD -#define DIO4_DDR DDRD -#define DIO4_PWM NULL - -#define DIO5_PIN PIND5 -#define DIO5_RPORT PIND -#define DIO5_WPORT PORTD -#define DIO5_DDR DDRD -#define DIO5_PWM &OCR0B - -#define DIO6_PIN PIND6 -#define DIO6_RPORT PIND -#define DIO6_WPORT PORTD -#define DIO6_DDR DDRD -#define DIO6_PWM &OCR0A - -#define DIO7_PIN PIND7 -#define DIO7_RPORT PIND -#define DIO7_WPORT PORTD -#define DIO7_DDR DDRD -#define DIO7_PWM NULL - -#define DIO8_PIN PINB0 -#define DIO8_RPORT PINB -#define DIO8_WPORT PORTB -#define DIO8_DDR DDRB -#define DIO8_PWM NULL - -#define DIO9_PIN PINB1 -#define DIO9_RPORT PINB -#define DIO9_WPORT PORTB -#define DIO9_DDR DDRB -#define DIO9_PWM NULL - -#define DIO10_PIN PINB2 -#define DIO10_RPORT PINB -#define DIO10_WPORT PORTB -#define DIO10_DDR DDRB -#define DIO10_PWM NULL - -#define DIO11_PIN PINB3 -#define DIO11_RPORT PINB -#define DIO11_WPORT PORTB -#define DIO11_DDR DDRB -#define DIO11_PWM &OCR2A - -#define DIO12_PIN PINB4 -#define DIO12_RPORT PINB -#define DIO12_WPORT PORTB -#define DIO12_DDR DDRB -#define DIO12_PWM NULL - -#define DIO13_PIN PINB5 -#define DIO13_RPORT PINB -#define DIO13_WPORT PORTB -#define DIO13_DDR DDRB -#define DIO13_PWM NULL - - -#define DIO14_PIN PINC0 -#define DIO14_RPORT PINC -#define DIO14_WPORT PORTC -#define DIO14_DDR DDRC -#define DIO14_PWM NULL - -#define DIO15_PIN PINC1 -#define DIO15_RPORT PINC -#define DIO15_WPORT PORTC -#define DIO15_DDR DDRC -#define DIO15_PWM NULL - -#define DIO16_PIN PINC2 -#define DIO16_RPORT PINC -#define DIO16_WPORT PORTC -#define DIO16_DDR DDRC -#define DIO16_PWM NULL - -#define DIO17_PIN PINC3 -#define DIO17_RPORT PINC -#define DIO17_WPORT PORTC -#define DIO17_DDR DDRC -#define DIO17_PWM NULL - -#define DIO18_PIN PINC4 -#define DIO18_RPORT PINC -#define DIO18_WPORT PORTC -#define DIO18_DDR DDRC -#define DIO18_PWM NULL - -#define DIO19_PIN PINC5 -#define DIO19_RPORT PINC -#define DIO19_WPORT PORTC -#define DIO19_DDR DDRC -#define DIO19_PWM NULL - -#define DIO20_PIN PINC6 -#define DIO20_RPORT PINC -#define DIO20_WPORT PORTC -#define DIO20_DDR DDRC -#define DIO20_PWM NULL - -#define DIO21_PIN PINC7 -#define DIO21_RPORT PINC -#define DIO21_WPORT PORTC -#define DIO21_DDR DDRC -#define DIO21_PWM NULL - - - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_DDR DDRB -#define PB0_PWM NULL - -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_DDR DDRB -#define PB1_PWM NULL - -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_DDR DDRB -#define PB2_PWM NULL - -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_DDR DDRB -#define PB3_PWM &OCR2A - -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_DDR DDRB -#define PB4_PWM NULL - -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_DDR DDRB -#define PB5_PWM NULL - -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_DDR DDRB -#define PB6_PWM NULL - -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_DDR DDRB -#define PB7_PWM NULL - - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_DDR DDRC -#define PC0_PWM NULL - -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_DDR DDRC -#define PC1_PWM NULL - -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_DDR DDRC -#define PC2_PWM NULL - -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_DDR DDRC -#define PC3_PWM NULL - -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_DDR DDRC -#define PC4_PWM NULL - -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_DDR DDRC -#define PC5_PWM NULL - -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_DDR DDRC -#define PC6_PWM NULL - -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_DDR DDRC -#define PC7_PWM NULL - - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_DDR DDRD -#define PD0_PWM NULL - -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_DDR DDRD -#define PD1_PWM NULL - -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_DDR DDRD -#define PD2_PWM NULL - -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_DDR DDRD -#define PD3_PWM &OCR2B - -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_DDR DDRD -#define PD4_PWM NULL - -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_DDR DDRD -#define PD5_PWM &OCR0B - -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_DDR DDRD -#define PD6_PWM &OCR0A - -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_DDR DDRD -#define PD7_PWM NULL -#endif /* _AVR_ATmega{168,328,328P}__ */ - -#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) -// UART -#define RXD DIO8 -#define TXD DIO9 -#define RXD0 DIO8 -#define TXD0 DIO9 - -#define RXD1 DIO10 -#define TXD1 DIO11 - -// SPI -#define SCK DIO7 -#define MISO DIO6 -#define MOSI DIO5 -#define SS DIO4 - -// TWI (I2C) -#define SCL DIO16 -#define SDA DIO17 - -// timers and PWM -#define OC0A DIO3 -#define OC0B DIO4 -#define OC1A DIO13 -#define OC1B DIO12 -#define OC2A DIO15 -#define OC2B DIO14 - -#define DEBUG_LED DIO0 -/* -pins -*/ - -#define DIO0_PIN PINB0 -#define DIO0_RPORT PINB -#define DIO0_WPORT PORTB -#define DIO0_DDR DDRB -#define DIO0_PWM NULL - -#define DIO1_PIN PINB1 -#define DIO1_RPORT PINB -#define DIO1_WPORT PORTB -#define DIO1_DDR DDRB -#define DIO1_PWM NULL - -#define DIO2_PIN PINB2 -#define DIO2_RPORT PINB -#define DIO2_WPORT PORTB -#define DIO2_DDR DDRB -#define DIO2_PWM NULL - -#define DIO3_PIN PINB3 -#define DIO3_RPORT PINB -#define DIO3_WPORT PORTB -#define DIO3_DDR DDRB -#define DIO3_PWM &OCR0A - -#define DIO4_PIN PINB4 -#define DIO4_RPORT PINB -#define DIO4_WPORT PORTB -#define DIO4_DDR DDRB -#define DIO4_PWM &OCR0B - -#define DIO5_PIN PINB5 -#define DIO5_RPORT PINB -#define DIO5_WPORT PORTB -#define DIO5_DDR DDRB -#define DIO5_PWM NULL - -#define DIO6_PIN PINB6 -#define DIO6_RPORT PINB -#define DIO6_WPORT PORTB -#define DIO6_DDR DDRB -#define DIO6_PWM NULL - -#define DIO7_PIN PINB7 -#define DIO7_RPORT PINB -#define DIO7_WPORT PORTB -#define DIO7_DDR DDRB -#define DIO7_PWM NULL - -#define DIO8_PIN PIND0 -#define DIO8_RPORT PIND -#define DIO8_WPORT PORTD -#define DIO8_DDR DDRD -#define DIO8_PWM NULL - -#define DIO9_PIN PIND1 -#define DIO9_RPORT PIND -#define DIO9_WPORT PORTD -#define DIO9_DDR DDRD -#define DIO9_PWM NULL - -#define DIO10_PIN PIND2 -#define DIO10_RPORT PIND -#define DIO10_WPORT PORTD -#define DIO10_DDR DDRD -#define DIO10_PWM NULL - -#define DIO11_PIN PIND3 -#define DIO11_RPORT PIND -#define DIO11_WPORT PORTD -#define DIO11_DDR DDRD -#define DIO11_PWM NULL - -#define DIO12_PIN PIND4 -#define DIO12_RPORT PIND -#define DIO12_WPORT PORTD -#define DIO12_DDR DDRD -#define DIO12_PWM NULL - -#define DIO13_PIN PIND5 -#define DIO13_RPORT PIND -#define DIO13_WPORT PORTD -#define DIO13_DDR DDRD -#define DIO13_PWM NULL - -#define DIO14_PIN PIND6 -#define DIO14_RPORT PIND -#define DIO14_WPORT PORTD -#define DIO14_DDR DDRD -#define DIO14_PWM &OCR2B - -#define DIO15_PIN PIND7 -#define DIO15_RPORT PIND -#define DIO15_WPORT PORTD -#define DIO15_DDR DDRD -#define DIO15_PWM &OCR2A - -#define DIO16_PIN PINC0 -#define DIO16_RPORT PINC -#define DIO16_WPORT PORTC -#define DIO16_DDR DDRC -#define DIO16_PWM NULL - -#define DIO17_PIN PINC1 -#define DIO17_RPORT PINC -#define DIO17_WPORT PORTC -#define DIO17_DDR DDRC -#define DIO17_PWM NULL - -#define DIO18_PIN PINC2 -#define DIO18_RPORT PINC -#define DIO18_WPORT PORTC -#define DIO18_DDR DDRC -#define DIO18_PWM NULL - -#define DIO19_PIN PINC3 -#define DIO19_RPORT PINC -#define DIO19_WPORT PORTC -#define DIO19_DDR DDRC -#define DIO19_PWM NULL - -#define DIO20_PIN PINC4 -#define DIO20_RPORT PINC -#define DIO20_WPORT PORTC -#define DIO20_DDR DDRC -#define DIO20_PWM NULL - -#define DIO21_PIN PINC5 -#define DIO21_RPORT PINC -#define DIO21_WPORT PORTC -#define DIO21_DDR DDRC -#define DIO21_PWM NULL - -#define DIO22_PIN PINC6 -#define DIO22_RPORT PINC -#define DIO22_WPORT PORTC -#define DIO22_DDR DDRC -#define DIO22_PWM NULL - -#define DIO23_PIN PINC7 -#define DIO23_RPORT PINC -#define DIO23_WPORT PORTC -#define DIO23_DDR DDRC -#define DIO23_PWM NULL - -#define DIO24_PIN PINA7 -#define DIO24_RPORT PINA -#define DIO24_WPORT PORTA -#define DIO24_DDR DDRA -#define DIO24_PWM NULL - -#define DIO25_PIN PINA6 -#define DIO25_RPORT PINA -#define DIO25_WPORT PORTA -#define DIO25_DDR DDRA -#define DIO25_PWM NULL - -#define DIO26_PIN PINA5 -#define DIO26_RPORT PINA -#define DIO26_WPORT PORTA -#define DIO26_DDR DDRA -#define DIO26_PWM NULL - -#define DIO27_PIN PINA4 -#define DIO27_RPORT PINA -#define DIO27_WPORT PORTA -#define DIO27_DDR DDRA -#define DIO27_PWM NULL - -#define DIO28_PIN PINA3 -#define DIO28_RPORT PINA -#define DIO28_WPORT PORTA -#define DIO28_DDR DDRA -#define DIO28_PWM NULL - -#define DIO29_PIN PINA2 -#define DIO29_RPORT PINA -#define DIO29_WPORT PORTA -#define DIO29_DDR DDRA -#define DIO29_PWM NULL - -#define DIO30_PIN PINA1 -#define DIO30_RPORT PINA -#define DIO30_WPORT PORTA -#define DIO30_DDR DDRA -#define DIO30_PWM NULL - -#define DIO31_PIN PINA0 -#define DIO31_RPORT PINA -#define DIO31_WPORT PORTA -#define DIO31_DDR DDRA -#define DIO31_PWM NULL - -#define AIO0_PIN PINA0 -#define AIO0_RPORT PINA -#define AIO0_WPORT PORTA -#define AIO0_DDR DDRA -#define AIO0_PWM NULL - -#define AIO1_PIN PINA1 -#define AIO1_RPORT PINA -#define AIO1_WPORT PORTA -#define AIO1_DDR DDRA -#define AIO1_PWM NULL - -#define AIO2_PIN PINA2 -#define AIO2_RPORT PINA -#define AIO2_WPORT PORTA -#define AIO2_DDR DDRA -#define AIO2_PWM NULL - -#define AIO3_PIN PINA3 -#define AIO3_RPORT PINA -#define AIO3_WPORT PORTA -#define AIO3_DDR DDRA -#define AIO3_PWM NULL - -#define AIO4_PIN PINA4 -#define AIO4_RPORT PINA -#define AIO4_WPORT PORTA -#define AIO4_DDR DDRA -#define AIO4_PWM NULL - -#define AIO5_PIN PINA5 -#define AIO5_RPORT PINA -#define AIO5_WPORT PORTA -#define AIO5_DDR DDRA -#define AIO5_PWM NULL - -#define AIO6_PIN PINA6 -#define AIO6_RPORT PINA -#define AIO6_WPORT PORTA -#define AIO6_DDR DDRA -#define AIO6_PWM NULL - -#define AIO7_PIN PINA7 -#define AIO7_RPORT PINA -#define AIO7_WPORT PORTA -#define AIO7_DDR DDRA -#define AIO7_PWM NULL - - - -#undef PA0 -#define PA0_PIN PINA0 -#define PA0_RPORT PINA -#define PA0_WPORT PORTA -#define PA0_DDR DDRA -#define PA0_PWM NULL - -#undef PA1 -#define PA1_PIN PINA1 -#define PA1_RPORT PINA -#define PA1_WPORT PORTA -#define PA1_DDR DDRA -#define PA1_PWM NULL - -#undef PA2 -#define PA2_PIN PINA2 -#define PA2_RPORT PINA -#define PA2_WPORT PORTA -#define PA2_DDR DDRA -#define PA2_PWM NULL - -#undef PA3 -#define PA3_PIN PINA3 -#define PA3_RPORT PINA -#define PA3_WPORT PORTA -#define PA3_DDR DDRA -#define PA3_PWM NULL - -#undef PA4 -#define PA4_PIN PINA4 -#define PA4_RPORT PINA -#define PA4_WPORT PORTA -#define PA4_DDR DDRA -#define PA4_PWM NULL - -#undef PA5 -#define PA5_PIN PINA5 -#define PA5_RPORT PINA -#define PA5_WPORT PORTA -#define PA5_DDR DDRA -#define PA5_PWM NULL - -#undef PA6 -#define PA6_PIN PINA6 -#define PA6_RPORT PINA -#define PA6_WPORT PORTA -#define PA6_DDR DDRA -#define PA6_PWM NULL - -#undef PA7 -#define PA7_PIN PINA7 -#define PA7_RPORT PINA -#define PA7_WPORT PORTA -#define PA7_DDR DDRA -#define PA7_PWM NULL - - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_DDR DDRB -#define PB0_PWM NULL - -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_DDR DDRB -#define PB1_PWM NULL - -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_DDR DDRB -#define PB2_PWM NULL - -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_DDR DDRB -#define PB3_PWM &OCR0A - -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_DDR DDRB -#define PB4_PWM &OCR0B - -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_DDR DDRB -#define PB5_PWM NULL - -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_DDR DDRB -#define PB6_PWM NULL - -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_DDR DDRB -#define PB7_PWM NULL - - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_DDR DDRC -#define PC0_PWM NULL - -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_DDR DDRC -#define PC1_PWM NULL - -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_DDR DDRC -#define PC2_PWM NULL - -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_DDR DDRC -#define PC3_PWM NULL - -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_DDR DDRC -#define PC4_PWM NULL - -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_DDR DDRC -#define PC5_PWM NULL - -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_DDR DDRC -#define PC6_PWM NULL - -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_DDR DDRC -#define PC7_PWM NULL - - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_DDR DDRD -#define PD0_PWM NULL - -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_DDR DDRD -#define PD1_PWM NULL - -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_DDR DDRD -#define PD2_PWM NULL - -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_DDR DDRD -#define PD3_PWM NULL - -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_DDR DDRD -#define PD4_PWM NULL - -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_DDR DDRD -#define PD5_PWM NULL - -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_DDR DDRD -#define PD6_PWM &OCR2B - -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_DDR DDRD -#define PD7_PWM &OCR2A -#endif /* _AVR_ATmega{644,644P,644PA}__ */ - -#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) -// UART -#define RXD DIO0 -#define TXD DIO1 - -// SPI -#define SCK DIO52 -#define MISO DIO50 -#define MOSI DIO51 -#define SS DIO53 - -// TWI (I2C) -#define SCL DIO21 -#define SDA DIO20 - -// timers and PWM -#define OC0A DIO13 -#define OC0B DIO4 -#define OC1A DIO11 -#define OC1B DIO12 -#define OC2A DIO10 -#define OC2B DIO9 -#define OC3A DIO5 -#define OC3B DIO2 -#define OC3C DIO3 -#define OC4A DIO6 -#define OC4B DIO7 -#define OC4C DIO8 -#define OC5A DIO46 -#define OC5B DIO45 -#define OC5C DIO44 - -// change for your board -#define DEBUG_LED DIO21 - -/* -pins -*/ -#define DIO0_PIN PINE0 -#define DIO0_RPORT PINE -#define DIO0_WPORT PORTE -#define DIO0_DDR DDRE -#define DIO0_PWM NULL - -#define DIO1_PIN PINE1 -#define DIO1_RPORT PINE -#define DIO1_WPORT PORTE -#define DIO1_DDR DDRE -#define DIO1_PWM NULL - -#define DIO2_PIN PINE4 -#define DIO2_RPORT PINE -#define DIO2_WPORT PORTE -#define DIO2_DDR DDRE -#define DIO2_PWM &OCR3BL - -#define DIO3_PIN PINE5 -#define DIO3_RPORT PINE -#define DIO3_WPORT PORTE -#define DIO3_DDR DDRE -#define DIO3_PWM &OCR3CL - -#define DIO4_PIN PING5 -#define DIO4_RPORT PING -#define DIO4_WPORT PORTG -#define DIO4_DDR DDRG -#define DIO4_PWM &OCR0B - -#define DIO5_PIN PINE3 -#define DIO5_RPORT PINE -#define DIO5_WPORT PORTE -#define DIO5_DDR DDRE -#define DIO5_PWM &OCR3AL - -#define DIO6_PIN PINH3 -#define DIO6_RPORT PINH -#define DIO6_WPORT PORTH -#define DIO6_DDR DDRH -#define DIO6_PWM &OCR4AL - -#define DIO7_PIN PINH4 -#define DIO7_RPORT PINH -#define DIO7_WPORT PORTH -#define DIO7_DDR DDRH -#define DIO7_PWM &OCR4BL - -#define DIO8_PIN PINH5 -#define DIO8_RPORT PINH -#define DIO8_WPORT PORTH -#define DIO8_DDR DDRH -#define DIO8_PWM &OCR4CL - -#define DIO9_PIN PINH6 -#define DIO9_RPORT PINH -#define DIO9_WPORT PORTH -#define DIO9_DDR DDRH -#define DIO9_PWM &OCR2B - -#define DIO10_PIN PINB4 -#define DIO10_RPORT PINB -#define DIO10_WPORT PORTB -#define DIO10_DDR DDRB -#define DIO10_PWM &OCR2A - -#define DIO11_PIN PINB5 -#define DIO11_RPORT PINB -#define DIO11_WPORT PORTB -#define DIO11_DDR DDRB -#define DIO11_PWM NULL - -#define DIO12_PIN PINB6 -#define DIO12_RPORT PINB -#define DIO12_WPORT PORTB -#define DIO12_DDR DDRB -#define DIO12_PWM NULL - -#define DIO13_PIN PINB7 -#define DIO13_RPORT PINB -#define DIO13_WPORT PORTB -#define DIO13_DDR DDRB -#define DIO13_PWM &OCR0A - -#define DIO14_PIN PINJ1 -#define DIO14_RPORT PINJ -#define DIO14_WPORT PORTJ -#define DIO14_DDR DDRJ -#define DIO14_PWM NULL - -#define DIO15_PIN PINJ0 -#define DIO15_RPORT PINJ -#define DIO15_WPORT PORTJ -#define DIO15_DDR DDRJ -#define DIO15_PWM NULL - -#define DIO16_PIN PINH1 -#define DIO16_RPORT PINH -#define DIO16_WPORT PORTH -#define DIO16_DDR DDRH -#define DIO16_PWM NULL - -#define DIO17_PIN PINH0 -#define DIO17_RPORT PINH -#define DIO17_WPORT PORTH -#define DIO17_DDR DDRH -#define DIO17_PWM NULL - -#define DIO18_PIN PIND3 -#define DIO18_RPORT PIND -#define DIO18_WPORT PORTD -#define DIO18_DDR DDRD -#define DIO18_PWM NULL - -#define DIO19_PIN PIND2 -#define DIO19_RPORT PIND -#define DIO19_WPORT PORTD -#define DIO19_DDR DDRD -#define DIO19_PWM NULL - -#define DIO20_PIN PIND1 -#define DIO20_RPORT PIND -#define DIO20_WPORT PORTD -#define DIO20_DDR DDRD -#define DIO20_PWM NULL - -#define DIO21_PIN PIND0 -#define DIO21_RPORT PIND -#define DIO21_WPORT PORTD -#define DIO21_DDR DDRD -#define DIO21_PWM NULL - -#define DIO22_PIN PINA0 -#define DIO22_RPORT PINA -#define DIO22_WPORT PORTA -#define DIO22_DDR DDRA -#define DIO22_PWM NULL - -#define DIO23_PIN PINA1 -#define DIO23_RPORT PINA -#define DIO23_WPORT PORTA -#define DIO23_DDR DDRA -#define DIO23_PWM NULL - -#define DIO24_PIN PINA2 -#define DIO24_RPORT PINA -#define DIO24_WPORT PORTA -#define DIO24_DDR DDRA -#define DIO24_PWM NULL - -#define DIO25_PIN PINA3 -#define DIO25_RPORT PINA -#define DIO25_WPORT PORTA -#define DIO25_DDR DDRA -#define DIO25_PWM NULL - -#define DIO26_PIN PINA4 -#define DIO26_RPORT PINA -#define DIO26_WPORT PORTA -#define DIO26_DDR DDRA -#define DIO26_PWM NULL - -#define DIO27_PIN PINA5 -#define DIO27_RPORT PINA -#define DIO27_WPORT PORTA -#define DIO27_DDR DDRA -#define DIO27_PWM NULL - -#define DIO28_PIN PINA6 -#define DIO28_RPORT PINA -#define DIO28_WPORT PORTA -#define DIO28_DDR DDRA -#define DIO28_PWM NULL - -#define DIO29_PIN PINA7 -#define DIO29_RPORT PINA -#define DIO29_WPORT PORTA -#define DIO29_DDR DDRA -#define DIO29_PWM NULL - -#define DIO30_PIN PINC7 -#define DIO30_RPORT PINC -#define DIO30_WPORT PORTC -#define DIO30_DDR DDRC -#define DIO30_PWM NULL - -#define DIO31_PIN PINC6 -#define DIO31_RPORT PINC -#define DIO31_WPORT PORTC -#define DIO31_DDR DDRC -#define DIO31_PWM NULL - -#define DIO32_PIN PINC5 -#define DIO32_RPORT PINC -#define DIO32_WPORT PORTC -#define DIO32_DDR DDRC -#define DIO32_PWM NULL - -#define DIO33_PIN PINC4 -#define DIO33_RPORT PINC -#define DIO33_WPORT PORTC -#define DIO33_DDR DDRC -#define DIO33_PWM NULL - -#define DIO34_PIN PINC3 -#define DIO34_RPORT PINC -#define DIO34_WPORT PORTC -#define DIO34_DDR DDRC -#define DIO34_PWM NULL - -#define DIO35_PIN PINC2 -#define DIO35_RPORT PINC -#define DIO35_WPORT PORTC -#define DIO35_DDR DDRC -#define DIO35_PWM NULL - -#define DIO36_PIN PINC1 -#define DIO36_RPORT PINC -#define DIO36_WPORT PORTC -#define DIO36_DDR DDRC -#define DIO36_PWM NULL - -#define DIO37_PIN PINC0 -#define DIO37_RPORT PINC -#define DIO37_WPORT PORTC -#define DIO37_DDR DDRC -#define DIO37_PWM NULL - -#define DIO38_PIN PIND7 -#define DIO38_RPORT PIND -#define DIO38_WPORT PORTD -#define DIO38_DDR DDRD -#define DIO38_PWM NULL - -#define DIO39_PIN PING2 -#define DIO39_RPORT PING -#define DIO39_WPORT PORTG -#define DIO39_DDR DDRG -#define DIO39_PWM NULL - -#define DIO40_PIN PING1 -#define DIO40_RPORT PING -#define DIO40_WPORT PORTG -#define DIO40_DDR DDRG -#define DIO40_PWM NULL - -#define DIO41_PIN PING0 -#define DIO41_RPORT PING -#define DIO41_WPORT PORTG -#define DIO41_DDR DDRG -#define DIO41_PWM NULL - -#define DIO42_PIN PINL7 -#define DIO42_RPORT PINL -#define DIO42_WPORT PORTL -#define DIO42_DDR DDRL -#define DIO42_PWM NULL - -#define DIO43_PIN PINL6 -#define DIO43_RPORT PINL -#define DIO43_WPORT PORTL -#define DIO43_DDR DDRL -#define DIO43_PWM NULL - -#define DIO44_PIN PINL5 -#define DIO44_RPORT PINL -#define DIO44_WPORT PORTL -#define DIO44_DDR DDRL -#define DIO44_PWM &OCR5CL - -#define DIO45_PIN PINL4 -#define DIO45_RPORT PINL -#define DIO45_WPORT PORTL -#define DIO45_DDR DDRL -#define DIO45_PWM &OCR5BL - -#define DIO46_PIN PINL3 -#define DIO46_RPORT PINL -#define DIO46_WPORT PORTL -#define DIO46_DDR DDRL -#define DIO46_PWM &OCR5AL - -#define DIO47_PIN PINL2 -#define DIO47_RPORT PINL -#define DIO47_WPORT PORTL -#define DIO47_DDR DDRL -#define DIO47_PWM NULL - -#define DIO48_PIN PINL1 -#define DIO48_RPORT PINL -#define DIO48_WPORT PORTL -#define DIO48_DDR DDRL -#define DIO48_PWM NULL - -#define DIO49_PIN PINL0 -#define DIO49_RPORT PINL -#define DIO49_WPORT PORTL -#define DIO49_DDR DDRL -#define DIO49_PWM NULL - -#define DIO50_PIN PINB3 -#define DIO50_RPORT PINB -#define DIO50_WPORT PORTB -#define DIO50_DDR DDRB -#define DIO50_PWM NULL - -#define DIO51_PIN PINB2 -#define DIO51_RPORT PINB -#define DIO51_WPORT PORTB -#define DIO51_DDR DDRB -#define DIO51_PWM NULL - -#define DIO52_PIN PINB1 -#define DIO52_RPORT PINB -#define DIO52_WPORT PORTB -#define DIO52_DDR DDRB -#define DIO52_PWM NULL - -#define DIO53_PIN PINB0 -#define DIO53_RPORT PINB -#define DIO53_WPORT PORTB -#define DIO53_DDR DDRB -#define DIO53_PWM NULL - -#define DIO54_PIN PINF0 -#define DIO54_RPORT PINF -#define DIO54_WPORT PORTF -#define DIO54_DDR DDRF -#define DIO54_PWM NULL - -#define DIO55_PIN PINF1 -#define DIO55_RPORT PINF -#define DIO55_WPORT PORTF -#define DIO55_DDR DDRF -#define DIO55_PWM NULL - -#define DIO56_PIN PINF2 -#define DIO56_RPORT PINF -#define DIO56_WPORT PORTF -#define DIO56_DDR DDRF -#define DIO56_PWM NULL - -#define DIO57_PIN PINF3 -#define DIO57_RPORT PINF -#define DIO57_WPORT PORTF -#define DIO57_DDR DDRF -#define DIO57_PWM NULL - -#define DIO58_PIN PINF4 -#define DIO58_RPORT PINF -#define DIO58_WPORT PORTF -#define DIO58_DDR DDRF -#define DIO58_PWM NULL - -#define DIO59_PIN PINF5 -#define DIO59_RPORT PINF -#define DIO59_WPORT PORTF -#define DIO59_DDR DDRF -#define DIO59_PWM NULL - -#define DIO60_PIN PINF6 -#define DIO60_RPORT PINF -#define DIO60_WPORT PORTF -#define DIO60_DDR DDRF -#define DIO60_PWM NULL - -#define DIO61_PIN PINF7 -#define DIO61_RPORT PINF -#define DIO61_WPORT PORTF -#define DIO61_DDR DDRF -#define DIO61_PWM NULL - -#define DIO62_PIN PINK0 -#define DIO62_RPORT PINK -#define DIO62_WPORT PORTK -#define DIO62_DDR DDRK -#define DIO62_PWM NULL - -#define DIO63_PIN PINK1 -#define DIO63_RPORT PINK -#define DIO63_WPORT PORTK -#define DIO63_DDR DDRK -#define DIO63_PWM NULL - -#define DIO64_PIN PINK2 -#define DIO64_RPORT PINK -#define DIO64_WPORT PORTK -#define DIO64_DDR DDRK -#define DIO64_PWM NULL - -#define DIO65_PIN PINK3 -#define DIO65_RPORT PINK -#define DIO65_WPORT PORTK -#define DIO65_DDR DDRK -#define DIO65_PWM NULL - -#define DIO66_PIN PINK4 -#define DIO66_RPORT PINK -#define DIO66_WPORT PORTK -#define DIO66_DDR DDRK -#define DIO66_PWM NULL - -#define DIO67_PIN PINK5 -#define DIO67_RPORT PINK -#define DIO67_WPORT PORTK -#define DIO67_DDR DDRK -#define DIO67_PWM NULL - -#define DIO68_PIN PINK6 -#define DIO68_RPORT PINK -#define DIO68_WPORT PORTK -#define DIO68_DDR DDRK -#define DIO68_PWM NULL - -#define DIO69_PIN PINK7 -#define DIO69_RPORT PINK -#define DIO69_WPORT PORTK -#define DIO69_DDR DDRK -#define DIO69_PWM NULL - - - -#undef PA0 -#define PA0_PIN PINA0 -#define PA0_RPORT PINA -#define PA0_WPORT PORTA -#define PA0_DDR DDRA -#define PA0_PWM NULL -#undef PA1 -#define PA1_PIN PINA1 -#define PA1_RPORT PINA -#define PA1_WPORT PORTA -#define PA1_DDR DDRA -#define PA1_PWM NULL -#undef PA2 -#define PA2_PIN PINA2 -#define PA2_RPORT PINA -#define PA2_WPORT PORTA -#define PA2_DDR DDRA -#define PA2_PWM NULL -#undef PA3 -#define PA3_PIN PINA3 -#define PA3_RPORT PINA -#define PA3_WPORT PORTA -#define PA3_DDR DDRA -#define PA3_PWM NULL -#undef PA4 -#define PA4_PIN PINA4 -#define PA4_RPORT PINA -#define PA4_WPORT PORTA -#define PA4_DDR DDRA -#define PA4_PWM NULL -#undef PA5 -#define PA5_PIN PINA5 -#define PA5_RPORT PINA -#define PA5_WPORT PORTA -#define PA5_DDR DDRA -#define PA5_PWM NULL -#undef PA6 -#define PA6_PIN PINA6 -#define PA6_RPORT PINA -#define PA6_WPORT PORTA -#define PA6_DDR DDRA -#define PA6_PWM NULL -#undef PA7 -#define PA7_PIN PINA7 -#define PA7_RPORT PINA -#define PA7_WPORT PORTA -#define PA7_DDR DDRA -#define PA7_PWM NULL - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_DDR DDRB -#define PB0_PWM NULL -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_DDR DDRB -#define PB1_PWM NULL -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_DDR DDRB -#define PB2_PWM NULL -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_DDR DDRB -#define PB3_PWM NULL -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_DDR DDRB -#define PB4_PWM &OCR2A -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_DDR DDRB -#define PB5_PWM NULL -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_DDR DDRB -#define PB6_PWM NULL -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_DDR DDRB -#define PB7_PWM &OCR0A - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_DDR DDRC -#define PC0_PWM NULL -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_DDR DDRC -#define PC1_PWM NULL -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_DDR DDRC -#define PC2_PWM NULL -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_DDR DDRC -#define PC3_PWM NULL -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_DDR DDRC -#define PC4_PWM NULL -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_DDR DDRC -#define PC5_PWM NULL -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_DDR DDRC -#define PC6_PWM NULL -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_DDR DDRC -#define PC7_PWM NULL - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_DDR DDRD -#define PD0_PWM NULL -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_DDR DDRD -#define PD1_PWM NULL -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_DDR DDRD -#define PD2_PWM NULL -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_DDR DDRD -#define PD3_PWM NULL -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_DDR DDRD -#define PD4_PWM NULL -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_DDR DDRD -#define PD5_PWM NULL -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_DDR DDRD -#define PD6_PWM NULL -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_DDR DDRD -#define PD7_PWM NULL - -#undef PE0 -#define PE0_PIN PINE0 -#define PE0_RPORT PINE -#define PE0_WPORT PORTE -#define PE0_DDR DDRE -#define PE0_PWM NULL -#undef PE1 -#define PE1_PIN PINE1 -#define PE1_RPORT PINE -#define PE1_WPORT PORTE -#define PE1_DDR DDRE -#define PE1_PWM NULL -#undef PE2 -#define PE2_PIN PINE2 -#define PE2_RPORT PINE -#define PE2_WPORT PORTE -#define PE2_DDR DDRE -#define PE2_PWM NULL -#undef PE3 -#define PE3_PIN PINE3 -#define PE3_RPORT PINE -#define PE3_WPORT PORTE -#define PE3_DDR DDRE -#define PE3_PWM &OCR3AL -#undef PE4 -#define PE4_PIN PINE4 -#define PE4_RPORT PINE -#define PE4_WPORT PORTE -#define PE4_DDR DDRE -#define PE4_PWM &OCR3BL -#undef PE5 -#define PE5_PIN PINE5 -#define PE5_RPORT PINE -#define PE5_WPORT PORTE -#define PE5_DDR DDRE -#define PE5_PWM &OCR3CL -#undef PE6 -#define PE6_PIN PINE6 -#define PE6_RPORT PINE -#define PE6_WPORT PORTE -#define PE6_DDR DDRE -#define PE6_PWM NULL -#undef PE7 -#define PE7_PIN PINE7 -#define PE7_RPORT PINE -#define PE7_WPORT PORTE -#define PE7_DDR DDRE -#define PE7_PWM NULL - -#undef PF0 -#define PF0_PIN PINF0 -#define PF0_RPORT PINF -#define PF0_WPORT PORTF -#define PF0_DDR DDRF -#define PF0_PWM NULL -#undef PF1 -#define PF1_PIN PINF1 -#define PF1_RPORT PINF -#define PF1_WPORT PORTF -#define PF1_DDR DDRF -#define PF1_PWM NULL -#undef PF2 -#define PF2_PIN PINF2 -#define PF2_RPORT PINF -#define PF2_WPORT PORTF -#define PF2_DDR DDRF -#define PF2_PWM NULL -#undef PF3 -#define PF3_PIN PINF3 -#define PF3_RPORT PINF -#define PF3_WPORT PORTF -#define PF3_DDR DDRF -#define PF3_PWM NULL -#undef PF4 -#define PF4_PIN PINF4 -#define PF4_RPORT PINF -#define PF4_WPORT PORTF -#define PF4_DDR DDRF -#define PF4_PWM NULL -#undef PF5 -#define PF5_PIN PINF5 -#define PF5_RPORT PINF -#define PF5_WPORT PORTF -#define PF5_DDR DDRF -#define PF5_PWM NULL -#undef PF6 -#define PF6_PIN PINF6 -#define PF6_RPORT PINF -#define PF6_WPORT PORTF -#define PF6_DDR DDRF -#define PF6_PWM NULL -#undef PF7 -#define PF7_PIN PINF7 -#define PF7_RPORT PINF -#define PF7_WPORT PORTF -#define PF7_DDR DDRF -#define PF7_PWM NULL - -#undef PG0 -#define PG0_PIN PING0 -#define PG0_RPORT PING -#define PG0_WPORT PORTG -#define PG0_DDR DDRG -#define PG0_PWM NULL -#undef PG1 -#define PG1_PIN PING1 -#define PG1_RPORT PING -#define PG1_WPORT PORTG -#define PG1_DDR DDRG -#define PG1_PWM NULL -#undef PG2 -#define PG2_PIN PING2 -#define PG2_RPORT PING -#define PG2_WPORT PORTG -#define PG2_DDR DDRG -#define PG2_PWM NULL -#undef PG3 -#define PG3_PIN PING3 -#define PG3_RPORT PING -#define PG3_WPORT PORTG -#define PG3_DDR DDRG -#define PG3_PWM NULL -#undef PG4 -#define PG4_PIN PING4 -#define PG4_RPORT PING -#define PG4_WPORT PORTG -#define PG4_DDR DDRG -#define PG4_PWM NULL -#undef PG5 -#define PG5_PIN PING5 -#define PG5_RPORT PING -#define PG5_WPORT PORTG -#define PG5_DDR DDRG -#define PG5_PWM &OCR0B -#undef PG6 -#define PG6_PIN PING6 -#define PG6_RPORT PING -#define PG6_WPORT PORTG -#define PG6_DDR DDRG -#define PG6_PWM NULL -#undef PG7 -#define PG7_PIN PING7 -#define PG7_RPORT PING -#define PG7_WPORT PORTG -#define PG7_DDR DDRG -#define PG7_PWM NULL - -#undef PH0 -#define PH0_PIN PINH0 -#define PH0_RPORT PINH -#define PH0_WPORT PORTH -#define PH0_DDR DDRH -#define PH0_PWM NULL -#undef PH1 -#define PH1_PIN PINH1 -#define PH1_RPORT PINH -#define PH1_WPORT PORTH -#define PH1_DDR DDRH -#define PH1_PWM NULL -#undef PH2 -#define PH2_PIN PINH2 -#define PH2_RPORT PINH -#define PH2_WPORT PORTH -#define PH2_DDR DDRH -#define PH2_PWM NULL -#undef PH3 -#define PH3_PIN PINH3 -#define PH3_RPORT PINH -#define PH3_WPORT PORTH -#define PH3_DDR DDRH -#define PH3_PWM &OCR4AL -#undef PH4 -#define PH4_PIN PINH4 -#define PH4_RPORT PINH -#define PH4_WPORT PORTH -#define PH4_DDR DDRH -#define PH4_PWM &OCR4BL -#undef PH5 -#define PH5_PIN PINH5 -#define PH5_RPORT PINH -#define PH5_WPORT PORTH -#define PH5_DDR DDRH -#define PH5_PWM &OCR4CL -#undef PH6 -#define PH6_PIN PINH6 -#define PH6_RPORT PINH -#define PH6_WPORT PORTH -#define PH6_DDR DDRH -#define PH6_PWM &OCR2B -#undef PH7 -#define PH7_PIN PINH7 -#define PH7_RPORT PINH -#define PH7_WPORT PORTH -#define PH7_DDR DDRH -#define PH7_PWM NULL - -#undef PJ0 -#define PJ0_PIN PINJ0 -#define PJ0_RPORT PINJ -#define PJ0_WPORT PORTJ -#define PJ0_DDR DDRJ -#define PJ0_PWM NULL -#undef PJ1 -#define PJ1_PIN PINJ1 -#define PJ1_RPORT PINJ -#define PJ1_WPORT PORTJ -#define PJ1_DDR DDRJ -#define PJ1_PWM NULL -#undef PJ2 -#define PJ2_PIN PINJ2 -#define PJ2_RPORT PINJ -#define PJ2_WPORT PORTJ -#define PJ2_DDR DDRJ -#define PJ2_PWM NULL -#undef PJ3 -#define PJ3_PIN PINJ3 -#define PJ3_RPORT PINJ -#define PJ3_WPORT PORTJ -#define PJ3_DDR DDRJ -#define PJ3_PWM NULL -#undef PJ4 -#define PJ4_PIN PINJ4 -#define PJ4_RPORT PINJ -#define PJ4_WPORT PORTJ -#define PJ4_DDR DDRJ -#define PJ4_PWM NULL -#undef PJ5 -#define PJ5_PIN PINJ5 -#define PJ5_RPORT PINJ -#define PJ5_WPORT PORTJ -#define PJ5_DDR DDRJ -#define PJ5_PWM NULL -#undef PJ6 -#define PJ6_PIN PINJ6 -#define PJ6_RPORT PINJ -#define PJ6_WPORT PORTJ -#define PJ6_DDR DDRJ -#define PJ6_PWM NULL -#undef PJ7 -#define PJ7_PIN PINJ7 -#define PJ7_RPORT PINJ -#define PJ7_WPORT PORTJ -#define PJ7_DDR DDRJ -#define PJ7_PWM NULL - -#undef PK0 -#define PK0_PIN PINK0 -#define PK0_RPORT PINK -#define PK0_WPORT PORTK -#define PK0_DDR DDRK -#define PK0_PWM NULL -#undef PK1 -#define PK1_PIN PINK1 -#define PK1_RPORT PINK -#define PK1_WPORT PORTK -#define PK1_DDR DDRK -#define PK1_PWM NULL -#undef PK2 -#define PK2_PIN PINK2 -#define PK2_RPORT PINK -#define PK2_WPORT PORTK -#define PK2_DDR DDRK -#define PK2_PWM NULL -#undef PK3 -#define PK3_PIN PINK3 -#define PK3_RPORT PINK -#define PK3_WPORT PORTK -#define PK3_DDR DDRK -#define PK3_PWM NULL -#undef PK4 -#define PK4_PIN PINK4 -#define PK4_RPORT PINK -#define PK4_WPORT PORTK -#define PK4_DDR DDRK -#define PK4_PWM NULL -#undef PK5 -#define PK5_PIN PINK5 -#define PK5_RPORT PINK -#define PK5_WPORT PORTK -#define PK5_DDR DDRK -#define PK5_PWM NULL -#undef PK6 -#define PK6_PIN PINK6 -#define PK6_RPORT PINK -#define PK6_WPORT PORTK -#define PK6_DDR DDRK -#define PK6_PWM NULL -#undef PK7 -#define PK7_PIN PINK7 -#define PK7_RPORT PINK -#define PK7_WPORT PORTK -#define PK7_DDR DDRK -#define PK7_PWM NULL - -#undef PL0 -#define PL0_PIN PINL0 -#define PL0_RPORT PINL -#define PL0_WPORT PORTL -#define PL0_DDR DDRL -#define PL0_PWM NULL -#undef PL1 -#define PL1_PIN PINL1 -#define PL1_RPORT PINL -#define PL1_WPORT PORTL -#define PL1_DDR DDRL -#define PL1_PWM NULL -#undef PL2 -#define PL2_PIN PINL2 -#define PL2_RPORT PINL -#define PL2_WPORT PORTL -#define PL2_DDR DDRL -#define PL2_PWM NULL -#undef PL3 -#define PL3_PIN PINL3 -#define PL3_RPORT PINL -#define PL3_WPORT PORTL -#define PL3_DDR DDRL -#define PL3_PWM &OCR5AL -#undef PL4 -#define PL4_PIN PINL4 -#define PL4_RPORT PINL -#define PL4_WPORT PORTL -#define PL4_DDR DDRL -#define PL4_PWM &OCR5BL -#undef PL5 -#define PL5_PIN PINL5 -#define PL5_RPORT PINL -#define PL5_WPORT PORTL -#define PL5_DDR DDRL -#define PL5_PWM &OCR5CL -#undef PL6 -#define PL6_PIN PINL6 -#define PL6_RPORT PINL -#define PL6_WPORT PORTL -#define PL6_DDR DDRL -#define PL6_PWM NULL -#undef PL7 -#define PL7_PIN PINL7 -#define PL7_RPORT PINL -#define PL7_WPORT PORTL -#define PL7_DDR DDRL -#define PL7_PWM NULL - -#endif - -#if defined (__AVR_AT90USB1287__) -// SPI -#define SCK DIO9 -#define MISO DIO11 -#define MOSI DIO10 -#define SS DIO8 - -// change for your board -#define DEBUG_LED DIO31 /* led D5 red */ - -/* -pins -*/ -#define DIO0_PIN PINA0 -#define DIO0_RPORT PINA -#define DIO0_WPORT PORTA -#define DIO0_PWM NULL -#define DIO0_DDR DDRA - -#define DIO1_PIN PINA1 -#define DIO1_RPORT PINA -#define DIO1_WPORT PORTA -#define DIO1_PWM NULL -#define DIO1_DDR DDRA - -#define DIO2_PIN PINA2 -#define DIO2_RPORT PINA -#define DIO2_WPORT PORTA -#define DIO2_PWM NULL -#define DIO2_DDR DDRA - -#define DIO3_PIN PINA3 -#define DIO3_RPORT PINA -#define DIO3_WPORT PORTA -#define DIO3_PWM NULL -#define DIO3_DDR DDRA - -#define DIO4_PIN PINA4 -#define DIO4_RPORT PINA -#define DIO4_WPORT PORTA -#define DIO4_PWM NULL -#define DIO4_DDR DDRA - -#define DIO5_PIN PINA5 -#define DIO5_RPORT PINA -#define DIO5_WPORT PORTA -#define DIO5_PWM NULL -#define DIO5_DDR DDRA - -#define DIO6_PIN PINA6 -#define DIO6_RPORT PINA -#define DIO6_WPORT PORTA -#define DIO6_PWM NULL -#define DIO6_DDR DDRA - -#define DIO7_PIN PINA7 -#define DIO7_RPORT PINA -#define DIO7_WPORT PORTA -#define DIO7_PWM NULL -#define DIO7_DDR DDRA - -#define DIO8_PIN PINB0 -#define DIO8_RPORT PINB -#define DIO8_WPORT PORTB -#define DIO8_PWM NULL -#define DIO8_DDR DDRB - -#define DIO9_PIN PINB1 -#define DIO9_RPORT PINB -#define DIO9_WPORT PORTB -#define DIO9_PWM NULL -#define DIO9_DDR DDRB - -#define DIO10_PIN PINB2 -#define DIO10_RPORT PINB -#define DIO10_WPORT PORTB -#define DIO10_PWM NULL -#define DIO10_DDR DDRB - -#define DIO11_PIN PINB3 -#define DIO11_RPORT PINB -#define DIO11_WPORT PORTB -#define DIO11_PWM NULL -#define DIO11_DDR DDRB - -#define DIO12_PIN PINB4 -#define DIO12_RPORT PINB -#define DIO12_WPORT PORTB -#define DIO12_PWM NULL -#define DIO12_DDR DDRB - -#define DIO13_PIN PINB5 -#define DIO13_RPORT PINB -#define DIO13_WPORT PORTB -#define DIO13_PWM NULL -#define DIO13_DDR DDRB - -#define DIO14_PIN PINB6 -#define DIO14_RPORT PINB -#define DIO14_WPORT PORTB -#define DIO14_PWM NULL -#define DIO14_DDR DDRB - -#define DIO15_PIN PINB7 -#define DIO15_RPORT PINB -#define DIO15_WPORT PORTB -#define DIO15_PWM NULL -#define DIO15_DDR DDRB - -#define DIO16_PIN PINC0 -#define DIO16_RPORT PINC -#define DIO16_WPORT PORTC -#define DIO16_PWM NULL -#define DIO16_DDR DDRC - -#define DIO17_PIN PINC1 -#define DIO17_RPORT PINC -#define DIO17_WPORT PORTC -#define DIO17_PWM NULL -#define DIO17_DDR DDRC - -#define DIO18_PIN PINC2 -#define DIO18_RPORT PINC -#define DIO18_WPORT PORTC -#define DIO18_PWM NULL -#define DIO18_DDR DDRC - -#define DIO19_PIN PINC3 -#define DIO19_RPORT PINC -#define DIO19_WPORT PORTC -#define DIO19_PWM NULL -#define DIO19_DDR DDRC - -#define DIO20_PIN PINC4 -#define DIO20_RPORT PINC -#define DIO20_WPORT PORTC -#define DIO20_PWM NULL -#define DIO20_DDR DDRC - -#define DIO21_PIN PINC5 -#define DIO21_RPORT PINC -#define DIO21_WPORT PORTC -#define DIO21_PWM NULL -#define DIO21_DDR DDRC - -#define DIO22_PIN PINC6 -#define DIO22_RPORT PINC -#define DIO22_WPORT PORTC -#define DIO22_PWM NULL -#define DIO22_DDR DDRC - -#define DIO23_PIN PINC7 -#define DIO23_RPORT PINC -#define DIO23_WPORT PORTC -#define DIO23_PWM NULL -#define DIO23_DDR DDRC - -#define DIO24_PIN PIND0 -#define DIO24_RPORT PIND -#define DIO24_WPORT PORTD -#define DIO24_PWM NULL -#define DIO24_DDR DDRD - -#define DIO25_PIN PIND1 -#define DIO25_RPORT PIND -#define DIO25_WPORT PORTD -#define DIO25_PWM NULL -#define DIO25_DDR DDRD - -#define DIO26_PIN PIND2 -#define DIO26_RPORT PIND -#define DIO26_WPORT PORTD -#define DIO26_PWM NULL -#define DIO26_DDR DDRD - -#define DIO27_PIN PIND3 -#define DIO27_RPORT PIND -#define DIO27_WPORT PORTD -#define DIO27_PWM NULL -#define DIO27_DDR DDRD - -#define DIO28_PIN PIND4 -#define DIO28_RPORT PIND -#define DIO28_WPORT PORTD -#define DIO28_PWM NULL -#define DIO28_DDR DDRD - -#define DIO29_PIN PIND5 -#define DIO29_RPORT PIND -#define DIO29_WPORT PORTD -#define DIO29_PWM NULL -#define DIO29_DDR DDRD - -#define DIO30_PIN PIND6 -#define DIO30_RPORT PIND -#define DIO30_WPORT PORTD -#define DIO30_PWM NULL -#define DIO30_DDR DDRD - -#define DIO31_PIN PIND7 -#define DIO31_RPORT PIND -#define DIO31_WPORT PORTD -#define DIO31_PWM NULL -#define DIO31_DDR DDRD - - -#define DIO32_PIN PINE0 -#define DIO32_RPORT PINE -#define DIO32_WPORT PORTE -#define DIO32_PWM NULL -#define DIO32_DDR DDRE - -#define DIO33_PIN PINE1 -#define DIO33_RPORT PINE -#define DIO33_WPORT PORTE -#define DIO33_PWM NULL -#define DIO33_DDR DDRE - -#define DIO34_PIN PINE2 -#define DIO34_RPORT PINE -#define DIO34_WPORT PORTE -#define DIO34_PWM NULL -#define DIO34_DDR DDRE - -#define DIO35_PIN PINE3 -#define DIO35_RPORT PINE -#define DIO35_WPORT PORTE -#define DIO35_PWM NULL -#define DIO35_DDR DDRE - -#define DIO36_PIN PINE4 -#define DIO36_RPORT PINE -#define DIO36_WPORT PORTE -#define DIO36_PWM NULL -#define DIO36_DDR DDRE - -#define DIO37_PIN PINE5 -#define DIO37_RPORT PINE -#define DIO37_WPORT PORTE -#define DIO37_PWM NULL -#define DIO37_DDR DDRE - -#define DIO38_PIN PINE6 -#define DIO38_RPORT PINE -#define DIO38_WPORT PORTE -#define DIO38_PWM NULL -#define DIO38_DDR DDRE - -#define DIO39_PIN PINE7 -#define DIO39_RPORT PINE -#define DIO39_WPORT PORTE -#define DIO39_PWM NULL -#define DIO39_DDR DDRE - -#define AIO0_PIN PINF0 -#define AIO0_RPORT PINF -#define AIO0_WPORT PORTF -#define AIO0_PWM NULL -#define AIO0_DDR DDRF - -#define AIO1_PIN PINF1 -#define AIO1_RPORT PINF -#define AIO1_WPORT PORTF -#define AIO1_PWM NULL -#define AIO1_DDR DDRF - -#define AIO2_PIN PINF2 -#define AIO2_RPORT PINF -#define AIO2_WPORT PORTF -#define AIO2_PWM NULL -#define AIO2_DDR DDRF - -#define AIO3_PIN PINF3 -#define AIO3_RPORT PINF -#define AIO3_WPORT PORTF -#define AIO3_PWM NULL -#define AIO3_DDR DDRF - -#define AIO4_PIN PINF4 -#define AIO4_RPORT PINF -#define AIO4_WPORT PORTF -#define AIO4_PWM NULL -#define AIO4_DDR DDRF - -#define AIO5_PIN PINF5 -#define AIO5_RPORT PINF -#define AIO5_WPORT PORTF -#define AIO5_PWM NULL -#define AIO5_DDR DDRF - -#define AIO6_PIN PINF6 -#define AIO6_RPORT PINF -#define AIO6_WPORT PORTF -#define AIO6_PWM NULL -#define AIO6_DDR DDRF - -#define AIO7_PIN PINF7 -#define AIO7_RPORT PINF -#define AIO7_WPORT PORTF -#define AIO7_PWM NULL -#define AIO7_DDR DDRF - -#define DIO40_PIN PINF0 -#define DIO40_RPORT PINF -#define DIO40_WPORT PORTF -#define DIO40_PWM NULL -#define DIO40_DDR DDRF - -#define DIO41_PIN PINF1 -#define DIO41_RPORT PINF -#define DIO41_WPORT PORTF -#define DIO41_PWM NULL -#define DIO41_DDR DDRF - -#define DIO42_PIN PINF2 -#define DIO42_RPORT PINF -#define DIO42_WPORT PORTF -#define DIO42_PWM NULL -#define DIO42_DDR DDRF - -#define DIO43_PIN PINF3 -#define DIO43_RPORT PINF -#define DIO43_WPORT PORTF -#define DIO43_PWM NULL -#define DIO43_DDR DDRF - -#define DIO44_PIN PINF4 -#define DIO44_RPORT PINF -#define DIO44_WPORT PORTF -#define DIO44_PWM NULL -#define DIO44_DDR DDRF - -#define DIO45_PIN PINF5 -#define DIO45_RPORT PINF -#define DIO45_WPORT PORTF -#define DIO45_PWM NULL -#define DIO45_DDR DDRF - -#define DIO46_PIN PINF6 -#define DIO46_RPORT PINF -#define DIO46_WPORT PORTF -#define DIO46_PWM NULL -#define DIO46_DDR DDRF - -#define DIO47_PIN PINF7 -#define DIO47_RPORT PINF -#define DIO47_WPORT PORTF -#define DIO47_PWM NULL -#define DIO47_DDR DDRF - - - -#undef PA0 -#define PA0_PIN PINA0 -#define PA0_RPORT PINA -#define PA0_WPORT PORTA -#define PA0_PWM NULL -#define PA0_DDR DDRA -#undef PA1 -#define PA1_PIN PINA1 -#define PA1_RPORT PINA -#define PA1_WPORT PORTA -#define PA1_PWM NULL -#define PA1_DDR DDRA -#undef PA2 -#define PA2_PIN PINA2 -#define PA2_RPORT PINA -#define PA2_WPORT PORTA -#define PA2_PWM NULL -#define PA2_DDR DDRA -#undef PA3 -#define PA3_PIN PINA3 -#define PA3_RPORT PINA -#define PA3_WPORT PORTA -#define PA3_PWM NULL -#define PA3_DDR DDRA -#undef PA4 -#define PA4_PIN PINA4 -#define PA4_RPORT PINA -#define PA4_WPORT PORTA -#define PA4_PWM NULL -#define PA4_DDR DDRA -#undef PA5 -#define PA5_PIN PINA5 -#define PA5_RPORT PINA -#define PA5_WPORT PORTA -#define PA5_PWM NULL -#define PA5_DDR DDRA -#undef PA6 -#define PA6_PIN PINA6 -#define PA6_RPORT PINA -#define PA6_WPORT PORTA -#define PA6_PWM NULL -#define PA6_DDR DDRA -#undef PA7 -#define PA7_PIN PINA7 -#define PA7_RPORT PINA -#define PA7_WPORT PORTA -#define PA7_PWM NULL -#define PA7_DDR DDRA - -#undef PB0 -#define PB0_PIN PINB0 -#define PB0_RPORT PINB -#define PB0_WPORT PORTB -#define PB0_PWM NULL -#define PB0_DDR DDRB -#undef PB1 -#define PB1_PIN PINB1 -#define PB1_RPORT PINB -#define PB1_WPORT PORTB -#define PB1_PWM NULL -#define PB1_DDR DDRB -#undef PB2 -#define PB2_PIN PINB2 -#define PB2_RPORT PINB -#define PB2_WPORT PORTB -#define PB2_PWM NULL -#define PB2_DDR DDRB -#undef PB3 -#define PB3_PIN PINB3 -#define PB3_RPORT PINB -#define PB3_WPORT PORTB -#define PB3_PWM NULL -#define PB3_DDR DDRB -#undef PB4 -#define PB4_PIN PINB4 -#define PB4_RPORT PINB -#define PB4_WPORT PORTB -#define PB4_PWM NULL -#define PB4_DDR DDRB -#undef PB5 -#define PB5_PIN PINB5 -#define PB5_RPORT PINB -#define PB5_WPORT PORTB -#define PB5_PWM NULL -#define PB5_DDR DDRB -#undef PB6 -#define PB6_PIN PINB6 -#define PB6_RPORT PINB -#define PB6_WPORT PORTB -#define PB6_PWM NULL -#define PB6_DDR DDRB -#undef PB7 -#define PB7_PIN PINB7 -#define PB7_RPORT PINB -#define PB7_WPORT PORTB -#define PB7_PWM NULL -#define PB7_DDR DDRB - -#undef PC0 -#define PC0_PIN PINC0 -#define PC0_RPORT PINC -#define PC0_WPORT PORTC -#define PC0_PWM NULL -#define PC0_DDR DDRC -#undef PC1 -#define PC1_PIN PINC1 -#define PC1_RPORT PINC -#define PC1_WPORT PORTC -#define PC1_PWM NULL -#define PC1_DDR DDRC -#undef PC2 -#define PC2_PIN PINC2 -#define PC2_RPORT PINC -#define PC2_WPORT PORTC -#define PC2_PWM NULL -#define PC2_DDR DDRC -#undef PC3 -#define PC3_PIN PINC3 -#define PC3_RPORT PINC -#define PC3_WPORT PORTC -#define PC3_PWM NULL -#define PC3_DDR DDRC -#undef PC4 -#define PC4_PIN PINC4 -#define PC4_RPORT PINC -#define PC4_WPORT PORTC -#define PC4_PWM NULL -#define PC4_DDR DDRC -#undef PC5 -#define PC5_PIN PINC5 -#define PC5_RPORT PINC -#define PC5_WPORT PORTC -#define PC5_PWM NULL -#define PC5_DDR DDRC -#undef PC6 -#define PC6_PIN PINC6 -#define PC6_RPORT PINC -#define PC6_WPORT PORTC -#define PC6_PWM NULL -#define PC6_DDR DDRC -#undef PC7 -#define PC7_PIN PINC7 -#define PC7_RPORT PINC -#define PC7_WPORT PORTC -#define PC7_PWM NULL -#define PC7_DDR DDRC - -#undef PD0 -#define PD0_PIN PIND0 -#define PD0_RPORT PIND -#define PD0_WPORT PORTD -#define PD0_PWM NULL -#define PD0_DDR DDRD -#undef PD1 -#define PD1_PIN PIND1 -#define PD1_RPORT PIND -#define PD1_WPORT PORTD -#define PD1_PWM NULL -#define PD1_DDR DDRD -#undef PD2 -#define PD2_PIN PIND2 -#define PD2_RPORT PIND -#define PD2_WPORT PORTD -#define PD2_PWM NULL -#define PD2_DDR DDRD -#undef PD3 -#define PD3_PIN PIND3 -#define PD3_RPORT PIND -#define PD3_WPORT PORTD -#define PD3_PWM NULL -#define PD3_DDR DDRD -#undef PD4 -#define PD4_PIN PIND4 -#define PD4_RPORT PIND -#define PD4_WPORT PORTD -#define PD4_PWM NULL -#define PD4_DDR DDRD -#undef PD5 -#define PD5_PIN PIND5 -#define PD5_RPORT PIND -#define PD5_WPORT PORTD -#define PD5_PWM NULL -#define PD5_DDR DDRD -#undef PD6 -#define PD6_PIN PIND6 -#define PD6_RPORT PIND -#define PD6_WPORT PORTD -#define PD6_PWM NULL -#define PD6_DDR DDRD -#undef PD7 -#define PD7_PIN PIND7 -#define PD7_RPORT PIND -#define PD7_WPORT PORTD -#define PD7_PWM NULL -#define PD7_DDR DDRD - -#undef PE0 -#define PE0_PIN PINE0 -#define PE0_RPORT PINE -#define PE0_WPORT PORTE -#define PE0_PWM NULL -#define PE0_DDR DDRE -#undef PE1 -#define PE1_PIN PINE1 -#define PE1_RPORT PINE -#define PE1_WPORT PORTE -#define PE1_PWM NULL -#define PE1_DDR DDRE -#undef PE2 -#define PE2_PIN PINE2 -#define PE2_RPORT PINE -#define PE2_WPORT PORTE -#define PE2_PWM NULL -#define PE2_DDR DDRE -#undef PE3 -#define PE3_PIN PINE3 -#define PE3_RPORT PINE -#define PE3_WPORT PORTE -#define PE3_PWM NULL -#define PE3_DDR DDRE -#undef PE4 -#define PE4_PIN PINE4 -#define PE4_RPORT PINE -#define PE4_WPORT PORTE -#define PE4_PWM NULL -#define PE4_DDR DDRE -#undef PE5 -#define PE5_PIN PINE5 -#define PE5_RPORT PINE -#define PE5_WPORT PORTE -#define PE5_PWM NULL -#define PE5_DDR DDRE -#undef PE6 -#define PE6_PIN PINE6 -#define PE6_RPORT PINE -#define PE6_WPORT PORTE -#define PE6_PWM NULL -#define PE6_DDR DDRE -#undef PE7 -#define PE7_PIN PINE7 -#define PE7_RPORT PINE -#define PE7_WPORT PORTE -#define PE7_PWM NULL -#define PE7_DDR DDRE - -#undef PF0 -#define PF0_PIN PINF0 -#define PF0_RPORT PINF -#define PF0_WPORT PORTF -#define PF0_PWM NULL -#define PF0_DDR DDRF -#undef PF1 -#define PF1_PIN PINF1 -#define PF1_RPORT PINF -#define PF1_WPORT PORTF -#define PF1_PWM NULL -#define PF1_DDR DDRF -#undef PF2 -#define PF2_PIN PINF2 -#define PF2_RPORT PINF -#define PF2_WPORT PORTF -#define PF2_PWM NULL -#define PF2_DDR DDRF -#undef PF3 -#define PF3_PIN PINF3 -#define PF3_RPORT PINF -#define PF3_WPORT PORTF -#define PF3_PWM NULL -#define PF3_DDR DDRF -#undef PF4 -#define PF4_PIN PINF4 -#define PF4_RPORT PINF -#define PF4_WPORT PORTF -#define PF4_PWM NULL -#define PF4_DDR DDRF -#undef PF5 -#define PF5_PIN PINF5 -#define PF5_RPORT PINF -#define PF5_WPORT PORTF -#define PF5_PWM NULL -#define PF5_DDR DDRF -#undef PF6 -#define PF6_PIN PINF6 -#define PF6_RPORT PINF -#define PF6_WPORT PORTF -#define PF6_PWM NULL -#define PF6_DDR DDRF -#undef PF7 -#define PF7_PIN PINF7 -#define PF7_RPORT PINF -#define PF7_WPORT PORTF -#define PF7_PWM NULL -#define PF7_DDR DDRF -#endif - -#ifndef DIO0_PIN -#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request -#endif - +/* + This code contibuted by Triffid_Hunter and modified by Kliment + why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html +*/ + +#ifndef _ARDUINO_H +#define _ARDUINO_H + +#include + +/* + utility functions +*/ + +#ifndef MASK +/// MASKING- returns \f$2^PIN\f$ +#define MASK(PIN) (1 << PIN) +#endif + +/* + magic I/O routines + now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0); +*/ + +/// Read a pin +#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) +/// write to a pin +// On some boards pins > 0x100 are used. These are not converted to atomic actions. An critical section is needed. + +#define _WRITE_NC(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) + +#define _WRITE_C(IO, v) do { if (v) { \ + CRITICAL_SECTION_START; \ + {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); }\ + CRITICAL_SECTION_END; \ + }\ + else {\ + CRITICAL_SECTION_START; \ + {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }\ + CRITICAL_SECTION_END; \ + }\ + }\ + while (0) + +#define _WRITE(IO, v) do { if (&(DIO ## IO ## _RPORT) >= (uint8_t *)0x100) {_WRITE_C(IO, v); } else {_WRITE_NC(IO, v); }; } while (0) + +/// toggle a pin +#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) + +/// set pin as input +#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0) +/// set pin as output +#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0) + +/// check if pin is an input +#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0) +/// check if pin is an output +#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0) + +/// check if pin is an timer +#define _GET_TIMER(IO) ((DIO ## IO ## _PWM) + +// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html + +/// Read a pin wrapper +#define READ(IO) _READ(IO) +/// Write to a pin wrapper +#define WRITE(IO, v) _WRITE(IO, v) + +/// toggle a pin wrapper +#define TOGGLE(IO) _TOGGLE(IO) + +/// set pin as input wrapper +#define SET_INPUT(IO) _SET_INPUT(IO) +/// set pin as output wrapper +#define SET_OUTPUT(IO) _SET_OUTPUT(IO) + +/// check if pin is an input wrapper +#define GET_INPUT(IO) _GET_INPUT(IO) +/// check if pin is an output wrapper +#define GET_OUTPUT(IO) _GET_OUTPUT(IO) + +/// check if pin is an timer wrapper +#define GET_TIMER(IO) _GET_TIMER(IO) + +/* + ports and functions + + added as necessary or if I feel like it- not a comprehensive list! +*/ + +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO13 +#define MISO DIO12 +#define MOSI DIO11 +#define SS DIO10 + +// TWI (I2C) +#define SCL AIO5 +#define SDA AIO4 + +// timers and PWM +#define OC0A DIO6 +#define OC0B DIO5 +#define OC1A DIO9 +#define OC1B DIO10 +#define OC2A DIO11 +#define OC2B DIO3 + +#define DEBUG_LED AIO5 + +/* +pins +*/ + +#define DIO0_PIN PIND0 +#define DIO0_RPORT PIND +#define DIO0_WPORT PORTD +#define DIO0_DDR DDRD +#define DIO0_PWM NULL + +#define DIO1_PIN PIND1 +#define DIO1_RPORT PIND +#define DIO1_WPORT PORTD +#define DIO1_DDR DDRD +#define DIO1_PWM NULL + +#define DIO2_PIN PIND2 +#define DIO2_RPORT PIND +#define DIO2_WPORT PORTD +#define DIO2_DDR DDRD +#define DIO2_PWM NULL + +#define DIO3_PIN PIND3 +#define DIO3_RPORT PIND +#define DIO3_WPORT PORTD +#define DIO3_DDR DDRD +#define DIO3_PWM &OCR2B + +#define DIO4_PIN PIND4 +#define DIO4_RPORT PIND +#define DIO4_WPORT PORTD +#define DIO4_DDR DDRD +#define DIO4_PWM NULL + +#define DIO5_PIN PIND5 +#define DIO5_RPORT PIND +#define DIO5_WPORT PORTD +#define DIO5_DDR DDRD +#define DIO5_PWM &OCR0B + +#define DIO6_PIN PIND6 +#define DIO6_RPORT PIND +#define DIO6_WPORT PORTD +#define DIO6_DDR DDRD +#define DIO6_PWM &OCR0A + +#define DIO7_PIN PIND7 +#define DIO7_RPORT PIND +#define DIO7_WPORT PORTD +#define DIO7_DDR DDRD +#define DIO7_PWM NULL + +#define DIO8_PIN PINB0 +#define DIO8_RPORT PINB +#define DIO8_WPORT PORTB +#define DIO8_DDR DDRB +#define DIO8_PWM NULL + +#define DIO9_PIN PINB1 +#define DIO9_RPORT PINB +#define DIO9_WPORT PORTB +#define DIO9_DDR DDRB +#define DIO9_PWM NULL + +#define DIO10_PIN PINB2 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_DDR DDRB +#define DIO10_PWM NULL + +#define DIO11_PIN PINB3 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_DDR DDRB +#define DIO11_PWM &OCR2A + +#define DIO12_PIN PINB4 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_DDR DDRB +#define DIO12_PWM NULL + +#define DIO13_PIN PINB5 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_DDR DDRB +#define DIO13_PWM NULL + + +#define DIO14_PIN PINC0 +#define DIO14_RPORT PINC +#define DIO14_WPORT PORTC +#define DIO14_DDR DDRC +#define DIO14_PWM NULL + +#define DIO15_PIN PINC1 +#define DIO15_RPORT PINC +#define DIO15_WPORT PORTC +#define DIO15_DDR DDRC +#define DIO15_PWM NULL + +#define DIO16_PIN PINC2 +#define DIO16_RPORT PINC +#define DIO16_WPORT PORTC +#define DIO16_DDR DDRC +#define DIO16_PWM NULL + +#define DIO17_PIN PINC3 +#define DIO17_RPORT PINC +#define DIO17_WPORT PORTC +#define DIO17_DDR DDRC +#define DIO17_PWM NULL + +#define DIO18_PIN PINC4 +#define DIO18_RPORT PINC +#define DIO18_WPORT PORTC +#define DIO18_DDR DDRC +#define DIO18_PWM NULL + +#define DIO19_PIN PINC5 +#define DIO19_RPORT PINC +#define DIO19_WPORT PORTC +#define DIO19_DDR DDRC +#define DIO19_PWM NULL + +#define DIO20_PIN PINC6 +#define DIO20_RPORT PINC +#define DIO20_WPORT PORTC +#define DIO20_DDR DDRC +#define DIO20_PWM NULL + +#define DIO21_PIN PINC7 +#define DIO21_RPORT PINC +#define DIO21_WPORT PORTC +#define DIO21_DDR DDRC +#define DIO21_PWM NULL + + + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB0_PWM NULL + +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB1_PWM NULL + +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB2_PWM NULL + +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB3_PWM &OCR2A + +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB4_PWM NULL + +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB5_PWM NULL + +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB6_PWM NULL + +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB +#define PB7_PWM NULL + + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC0_PWM NULL + +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC1_PWM NULL + +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC2_PWM NULL + +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC3_PWM NULL + +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC4_PWM NULL + +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC5_PWM NULL + +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC6_PWM NULL + +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC +#define PC7_PWM NULL + + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD0_PWM NULL + +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD1_PWM NULL + +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD2_PWM NULL + +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD3_PWM &OCR2B + +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD4_PWM NULL + +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD5_PWM &OCR0B + +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD6_PWM &OCR0A + +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD +#define PD7_PWM NULL +#endif /* _AVR_ATmega{168,328,328P}__ */ + +#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) +// UART +#define RXD DIO8 +#define TXD DIO9 +#define RXD0 DIO8 +#define TXD0 DIO9 + +#define RXD1 DIO10 +#define TXD1 DIO11 + +// SPI +#define SCK DIO7 +#define MISO DIO6 +#define MOSI DIO5 +#define SS DIO4 + +// TWI (I2C) +#define SCL DIO16 +#define SDA DIO17 + +// timers and PWM +#define OC0A DIO3 +#define OC0B DIO4 +#define OC1A DIO13 +#define OC1B DIO12 +#define OC2A DIO15 +#define OC2B DIO14 + +#define DEBUG_LED DIO0 +/* +pins +*/ + +#define DIO0_PIN PINB0 +#define DIO0_RPORT PINB +#define DIO0_WPORT PORTB +#define DIO0_DDR DDRB +#define DIO0_PWM NULL + +#define DIO1_PIN PINB1 +#define DIO1_RPORT PINB +#define DIO1_WPORT PORTB +#define DIO1_DDR DDRB +#define DIO1_PWM NULL + +#define DIO2_PIN PINB2 +#define DIO2_RPORT PINB +#define DIO2_WPORT PORTB +#define DIO2_DDR DDRB +#define DIO2_PWM NULL + +#define DIO3_PIN PINB3 +#define DIO3_RPORT PINB +#define DIO3_WPORT PORTB +#define DIO3_DDR DDRB +#define DIO3_PWM OCR0A + +#define DIO4_PIN PINB4 +#define DIO4_RPORT PINB +#define DIO4_WPORT PORTB +#define DIO4_DDR DDRB +#define DIO4_PWM OCR0B + +#define DIO5_PIN PINB5 +#define DIO5_RPORT PINB +#define DIO5_WPORT PORTB +#define DIO5_DDR DDRB +#define DIO5_PWM NULL + +#define DIO6_PIN PINB6 +#define DIO6_RPORT PINB +#define DIO6_WPORT PORTB +#define DIO6_DDR DDRB +#define DIO6_PWM NULL + +#define DIO7_PIN PINB7 +#define DIO7_RPORT PINB +#define DIO7_WPORT PORTB +#define DIO7_DDR DDRB +#define DIO7_PWM NULL + +#define DIO8_PIN PIND0 +#define DIO8_RPORT PIND +#define DIO8_WPORT PORTD +#define DIO8_DDR DDRD +#define DIO8_PWM NULL + +#define DIO9_PIN PIND1 +#define DIO9_RPORT PIND +#define DIO9_WPORT PORTD +#define DIO9_DDR DDRD +#define DIO9_PWM NULL + +#define DIO10_PIN PIND2 +#define DIO10_RPORT PIND +#define DIO10_WPORT PORTD +#define DIO10_DDR DDRD +#define DIO10_PWM NULL + +#define DIO11_PIN PIND3 +#define DIO11_RPORT PIND +#define DIO11_WPORT PORTD +#define DIO11_DDR DDRD +#define DIO11_PWM NULL + +#define DIO12_PIN PIND4 +#define DIO12_RPORT PIND +#define DIO12_WPORT PORTD +#define DIO12_DDR DDRD +#define DIO12_PWM OCR1B + +#define DIO13_PIN PIND5 +#define DIO13_RPORT PIND +#define DIO13_WPORT PORTD +#define DIO13_DDR DDRD +#define DIO13_PWM OCR1A + +#define DIO14_PIN PIND6 +#define DIO14_RPORT PIND +#define DIO14_WPORT PORTD +#define DIO14_DDR DDRD +#define DIO14_PWM OCR2B + +#define DIO15_PIN PIND7 +#define DIO15_RPORT PIND +#define DIO15_WPORT PORTD +#define DIO15_DDR DDRD +#define DIO15_PWM OCR2A + +#define DIO16_PIN PINC0 +#define DIO16_RPORT PINC +#define DIO16_WPORT PORTC +#define DIO16_DDR DDRC +#define DIO16_PWM NULL + +#define DIO17_PIN PINC1 +#define DIO17_RPORT PINC +#define DIO17_WPORT PORTC +#define DIO17_DDR DDRC +#define DIO17_PWM NULL + +#define DIO18_PIN PINC2 +#define DIO18_RPORT PINC +#define DIO18_WPORT PORTC +#define DIO18_DDR DDRC +#define DIO18_PWM NULL + +#define DIO19_PIN PINC3 +#define DIO19_RPORT PINC +#define DIO19_WPORT PORTC +#define DIO19_DDR DDRC +#define DIO19_PWM NULL + +#define DIO20_PIN PINC4 +#define DIO20_RPORT PINC +#define DIO20_WPORT PORTC +#define DIO20_DDR DDRC +#define DIO20_PWM NULL + +#define DIO21_PIN PINC5 +#define DIO21_RPORT PINC +#define DIO21_WPORT PORTC +#define DIO21_DDR DDRC +#define DIO21_PWM NULL + +#define DIO22_PIN PINC6 +#define DIO22_RPORT PINC +#define DIO22_WPORT PORTC +#define DIO22_DDR DDRC +#define DIO22_PWM NULL + +#define DIO23_PIN PINC7 +#define DIO23_RPORT PINC +#define DIO23_WPORT PORTC +#define DIO23_DDR DDRC +#define DIO23_PWM NULL + +#define DIO24_PIN PINA7 +#define DIO24_RPORT PINA +#define DIO24_WPORT PORTA +#define DIO24_DDR DDRA +#define DIO24_PWM NULL + +#define DIO25_PIN PINA6 +#define DIO25_RPORT PINA +#define DIO25_WPORT PORTA +#define DIO25_DDR DDRA +#define DIO25_PWM NULL + +#define DIO26_PIN PINA5 +#define DIO26_RPORT PINA +#define DIO26_WPORT PORTA +#define DIO26_DDR DDRA +#define DIO26_PWM NULL + +#define DIO27_PIN PINA4 +#define DIO27_RPORT PINA +#define DIO27_WPORT PORTA +#define DIO27_DDR DDRA +#define DIO27_PWM NULL + +#define DIO28_PIN PINA3 +#define DIO28_RPORT PINA +#define DIO28_WPORT PORTA +#define DIO28_DDR DDRA +#define DIO28_PWM NULL + +#define DIO29_PIN PINA2 +#define DIO29_RPORT PINA +#define DIO29_WPORT PORTA +#define DIO29_DDR DDRA +#define DIO29_PWM NULL + +#define DIO30_PIN PINA1 +#define DIO30_RPORT PINA +#define DIO30_WPORT PORTA +#define DIO30_DDR DDRA +#define DIO30_PWM NULL + +#define DIO31_PIN PINA0 +#define DIO31_RPORT PINA +#define DIO31_WPORT PORTA +#define DIO31_DDR DDRA +#define DIO31_PWM NULL + +#define AIO0_PIN PINA0 +#define AIO0_RPORT PINA +#define AIO0_WPORT PORTA +#define AIO0_DDR DDRA +#define AIO0_PWM NULL + +#define AIO1_PIN PINA1 +#define AIO1_RPORT PINA +#define AIO1_WPORT PORTA +#define AIO1_DDR DDRA +#define AIO1_PWM NULL + +#define AIO2_PIN PINA2 +#define AIO2_RPORT PINA +#define AIO2_WPORT PORTA +#define AIO2_DDR DDRA +#define AIO2_PWM NULL + +#define AIO3_PIN PINA3 +#define AIO3_RPORT PINA +#define AIO3_WPORT PORTA +#define AIO3_DDR DDRA +#define AIO3_PWM NULL + +#define AIO4_PIN PINA4 +#define AIO4_RPORT PINA +#define AIO4_WPORT PORTA +#define AIO4_DDR DDRA +#define AIO4_PWM NULL + +#define AIO5_PIN PINA5 +#define AIO5_RPORT PINA +#define AIO5_WPORT PORTA +#define AIO5_DDR DDRA +#define AIO5_PWM NULL + +#define AIO6_PIN PINA6 +#define AIO6_RPORT PINA +#define AIO6_WPORT PORTA +#define AIO6_DDR DDRA +#define AIO6_PWM NULL + +#define AIO7_PIN PINA7 +#define AIO7_RPORT PINA +#define AIO7_WPORT PORTA +#define AIO7_DDR DDRA +#define AIO7_PWM NULL + + + +#undef PA0 +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_DDR DDRA +#define PA0_PWM NULL + +#undef PA1 +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_DDR DDRA +#define PA1_PWM NULL + +#undef PA2 +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_DDR DDRA +#define PA2_PWM NULL + +#undef PA3 +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_DDR DDRA +#define PA3_PWM NULL + +#undef PA4 +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_DDR DDRA +#define PA4_PWM NULL + +#undef PA5 +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_DDR DDRA +#define PA5_PWM NULL + +#undef PA6 +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_DDR DDRA +#define PA6_PWM NULL + +#undef PA7 +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_DDR DDRA +#define PA7_PWM NULL + + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB0_PWM NULL + +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB1_PWM NULL + +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB2_PWM NULL + +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB3_PWM OCR0A + +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB4_PWM OCR0B + +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB5_PWM NULL + +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB6_PWM NULL + +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB +#define PB7_PWM NULL + + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC0_PWM NULL + +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC1_PWM NULL + +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC2_PWM NULL + +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC3_PWM NULL + +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC4_PWM NULL + +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC5_PWM NULL + +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC6_PWM NULL + +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC +#define PC7_PWM NULL + + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD0_PWM NULL + +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD1_PWM NULL + +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD2_PWM NULL + +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD3_PWM NULL + +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD4_PWM NULL + +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD5_PWM NULL + +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD6_PWM OCR2B + +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD +#define PD7_PWM OCR2A +#endif /* _AVR_ATmega{644,644P,644PA}__ */ + +#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__) +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO52 +#define MISO DIO50 +#define MOSI DIO51 +#define SS DIO53 + +// TWI (I2C) +#define SCL DIO21 +#define SDA DIO20 + +// timers and PWM +#define OC0A DIO13 +#define OC0B DIO4 +#define OC1A DIO11 +#define OC1B DIO12 +#define OC2A DIO10 +#define OC2B DIO9 +#define OC3A DIO5 +#define OC3B DIO2 +#define OC3C DIO3 +#define OC4A DIO6 +#define OC4B DIO7 +#define OC4C DIO8 +#define OC5A DIO46 +#define OC5B DIO45 +#define OC5C DIO44 + +// change for your board +#define DEBUG_LED DIO21 + +/* +pins +*/ +#define DIO0_PIN PINE0 +#define DIO0_RPORT PINE +#define DIO0_WPORT PORTE +#define DIO0_DDR DDRE +#define DIO0_PWM NULL + +#define DIO1_PIN PINE1 +#define DIO1_RPORT PINE +#define DIO1_WPORT PORTE +#define DIO1_DDR DDRE +#define DIO1_PWM NULL + +#define DIO2_PIN PINE4 +#define DIO2_RPORT PINE +#define DIO2_WPORT PORTE +#define DIO2_DDR DDRE +#define DIO2_PWM &OCR3BL + +#define DIO3_PIN PINE5 +#define DIO3_RPORT PINE +#define DIO3_WPORT PORTE +#define DIO3_DDR DDRE +#define DIO3_PWM &OCR3CL + +#define DIO4_PIN PING5 +#define DIO4_RPORT PING +#define DIO4_WPORT PORTG +#define DIO4_DDR DDRG +#define DIO4_PWM &OCR0B + +#define DIO5_PIN PINE3 +#define DIO5_RPORT PINE +#define DIO5_WPORT PORTE +#define DIO5_DDR DDRE +#define DIO5_PWM &OCR3AL + +#define DIO6_PIN PINH3 +#define DIO6_RPORT PINH +#define DIO6_WPORT PORTH +#define DIO6_DDR DDRH +#define DIO6_PWM &OCR4AL + +#define DIO7_PIN PINH4 +#define DIO7_RPORT PINH +#define DIO7_WPORT PORTH +#define DIO7_DDR DDRH +#define DIO7_PWM &OCR4BL + +#define DIO8_PIN PINH5 +#define DIO8_RPORT PINH +#define DIO8_WPORT PORTH +#define DIO8_DDR DDRH +#define DIO8_PWM &OCR4CL + +#define DIO9_PIN PINH6 +#define DIO9_RPORT PINH +#define DIO9_WPORT PORTH +#define DIO9_DDR DDRH +#define DIO9_PWM &OCR2B + +#define DIO10_PIN PINB4 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_DDR DDRB +#define DIO10_PWM &OCR2A + +#define DIO11_PIN PINB5 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_DDR DDRB +#define DIO11_PWM NULL + +#define DIO12_PIN PINB6 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_DDR DDRB +#define DIO12_PWM NULL + +#define DIO13_PIN PINB7 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_DDR DDRB +#define DIO13_PWM &OCR0A + +#define DIO14_PIN PINJ1 +#define DIO14_RPORT PINJ +#define DIO14_WPORT PORTJ +#define DIO14_DDR DDRJ +#define DIO14_PWM NULL + +#define DIO15_PIN PINJ0 +#define DIO15_RPORT PINJ +#define DIO15_WPORT PORTJ +#define DIO15_DDR DDRJ +#define DIO15_PWM NULL + +#define DIO16_PIN PINH1 +#define DIO16_RPORT PINH +#define DIO16_WPORT PORTH +#define DIO16_DDR DDRH +#define DIO16_PWM NULL + +#define DIO17_PIN PINH0 +#define DIO17_RPORT PINH +#define DIO17_WPORT PORTH +#define DIO17_DDR DDRH +#define DIO17_PWM NULL + +#define DIO18_PIN PIND3 +#define DIO18_RPORT PIND +#define DIO18_WPORT PORTD +#define DIO18_DDR DDRD +#define DIO18_PWM NULL + +#define DIO19_PIN PIND2 +#define DIO19_RPORT PIND +#define DIO19_WPORT PORTD +#define DIO19_DDR DDRD +#define DIO19_PWM NULL + +#define DIO20_PIN PIND1 +#define DIO20_RPORT PIND +#define DIO20_WPORT PORTD +#define DIO20_DDR DDRD +#define DIO20_PWM NULL + +#define DIO21_PIN PIND0 +#define DIO21_RPORT PIND +#define DIO21_WPORT PORTD +#define DIO21_DDR DDRD +#define DIO21_PWM NULL + +#define DIO22_PIN PINA0 +#define DIO22_RPORT PINA +#define DIO22_WPORT PORTA +#define DIO22_DDR DDRA +#define DIO22_PWM NULL + +#define DIO23_PIN PINA1 +#define DIO23_RPORT PINA +#define DIO23_WPORT PORTA +#define DIO23_DDR DDRA +#define DIO23_PWM NULL + +#define DIO24_PIN PINA2 +#define DIO24_RPORT PINA +#define DIO24_WPORT PORTA +#define DIO24_DDR DDRA +#define DIO24_PWM NULL + +#define DIO25_PIN PINA3 +#define DIO25_RPORT PINA +#define DIO25_WPORT PORTA +#define DIO25_DDR DDRA +#define DIO25_PWM NULL + +#define DIO26_PIN PINA4 +#define DIO26_RPORT PINA +#define DIO26_WPORT PORTA +#define DIO26_DDR DDRA +#define DIO26_PWM NULL + +#define DIO27_PIN PINA5 +#define DIO27_RPORT PINA +#define DIO27_WPORT PORTA +#define DIO27_DDR DDRA +#define DIO27_PWM NULL + +#define DIO28_PIN PINA6 +#define DIO28_RPORT PINA +#define DIO28_WPORT PORTA +#define DIO28_DDR DDRA +#define DIO28_PWM NULL + +#define DIO29_PIN PINA7 +#define DIO29_RPORT PINA +#define DIO29_WPORT PORTA +#define DIO29_DDR DDRA +#define DIO29_PWM NULL + +#define DIO30_PIN PINC7 +#define DIO30_RPORT PINC +#define DIO30_WPORT PORTC +#define DIO30_DDR DDRC +#define DIO30_PWM NULL + +#define DIO31_PIN PINC6 +#define DIO31_RPORT PINC +#define DIO31_WPORT PORTC +#define DIO31_DDR DDRC +#define DIO31_PWM NULL + +#define DIO32_PIN PINC5 +#define DIO32_RPORT PINC +#define DIO32_WPORT PORTC +#define DIO32_DDR DDRC +#define DIO32_PWM NULL + +#define DIO33_PIN PINC4 +#define DIO33_RPORT PINC +#define DIO33_WPORT PORTC +#define DIO33_DDR DDRC +#define DIO33_PWM NULL + +#define DIO34_PIN PINC3 +#define DIO34_RPORT PINC +#define DIO34_WPORT PORTC +#define DIO34_DDR DDRC +#define DIO34_PWM NULL + +#define DIO35_PIN PINC2 +#define DIO35_RPORT PINC +#define DIO35_WPORT PORTC +#define DIO35_DDR DDRC +#define DIO35_PWM NULL + +#define DIO36_PIN PINC1 +#define DIO36_RPORT PINC +#define DIO36_WPORT PORTC +#define DIO36_DDR DDRC +#define DIO36_PWM NULL + +#define DIO37_PIN PINC0 +#define DIO37_RPORT PINC +#define DIO37_WPORT PORTC +#define DIO37_DDR DDRC +#define DIO37_PWM NULL + +#define DIO38_PIN PIND7 +#define DIO38_RPORT PIND +#define DIO38_WPORT PORTD +#define DIO38_DDR DDRD +#define DIO38_PWM NULL + +#define DIO39_PIN PING2 +#define DIO39_RPORT PING +#define DIO39_WPORT PORTG +#define DIO39_DDR DDRG +#define DIO39_PWM NULL + +#define DIO40_PIN PING1 +#define DIO40_RPORT PING +#define DIO40_WPORT PORTG +#define DIO40_DDR DDRG +#define DIO40_PWM NULL + +#define DIO41_PIN PING0 +#define DIO41_RPORT PING +#define DIO41_WPORT PORTG +#define DIO41_DDR DDRG +#define DIO41_PWM NULL + +#define DIO42_PIN PINL7 +#define DIO42_RPORT PINL +#define DIO42_WPORT PORTL +#define DIO42_DDR DDRL +#define DIO42_PWM NULL + +#define DIO43_PIN PINL6 +#define DIO43_RPORT PINL +#define DIO43_WPORT PORTL +#define DIO43_DDR DDRL +#define DIO43_PWM NULL + +#define DIO44_PIN PINL5 +#define DIO44_RPORT PINL +#define DIO44_WPORT PORTL +#define DIO44_DDR DDRL +#define DIO44_PWM &OCR5CL + +#define DIO45_PIN PINL4 +#define DIO45_RPORT PINL +#define DIO45_WPORT PORTL +#define DIO45_DDR DDRL +#define DIO45_PWM &OCR5BL + +#define DIO46_PIN PINL3 +#define DIO46_RPORT PINL +#define DIO46_WPORT PORTL +#define DIO46_DDR DDRL +#define DIO46_PWM &OCR5AL + +#define DIO47_PIN PINL2 +#define DIO47_RPORT PINL +#define DIO47_WPORT PORTL +#define DIO47_DDR DDRL +#define DIO47_PWM NULL + +#define DIO48_PIN PINL1 +#define DIO48_RPORT PINL +#define DIO48_WPORT PORTL +#define DIO48_DDR DDRL +#define DIO48_PWM NULL + +#define DIO49_PIN PINL0 +#define DIO49_RPORT PINL +#define DIO49_WPORT PORTL +#define DIO49_DDR DDRL +#define DIO49_PWM NULL + +#define DIO50_PIN PINB3 +#define DIO50_RPORT PINB +#define DIO50_WPORT PORTB +#define DIO50_DDR DDRB +#define DIO50_PWM NULL + +#define DIO51_PIN PINB2 +#define DIO51_RPORT PINB +#define DIO51_WPORT PORTB +#define DIO51_DDR DDRB +#define DIO51_PWM NULL + +#define DIO52_PIN PINB1 +#define DIO52_RPORT PINB +#define DIO52_WPORT PORTB +#define DIO52_DDR DDRB +#define DIO52_PWM NULL + +#define DIO53_PIN PINB0 +#define DIO53_RPORT PINB +#define DIO53_WPORT PORTB +#define DIO53_DDR DDRB +#define DIO53_PWM NULL + +#define DIO54_PIN PINF0 +#define DIO54_RPORT PINF +#define DIO54_WPORT PORTF +#define DIO54_DDR DDRF +#define DIO54_PWM NULL + +#define DIO55_PIN PINF1 +#define DIO55_RPORT PINF +#define DIO55_WPORT PORTF +#define DIO55_DDR DDRF +#define DIO55_PWM NULL + +#define DIO56_PIN PINF2 +#define DIO56_RPORT PINF +#define DIO56_WPORT PORTF +#define DIO56_DDR DDRF +#define DIO56_PWM NULL + +#define DIO57_PIN PINF3 +#define DIO57_RPORT PINF +#define DIO57_WPORT PORTF +#define DIO57_DDR DDRF +#define DIO57_PWM NULL + +#define DIO58_PIN PINF4 +#define DIO58_RPORT PINF +#define DIO58_WPORT PORTF +#define DIO58_DDR DDRF +#define DIO58_PWM NULL + +#define DIO59_PIN PINF5 +#define DIO59_RPORT PINF +#define DIO59_WPORT PORTF +#define DIO59_DDR DDRF +#define DIO59_PWM NULL + +#define DIO60_PIN PINF6 +#define DIO60_RPORT PINF +#define DIO60_WPORT PORTF +#define DIO60_DDR DDRF +#define DIO60_PWM NULL + +#define DIO61_PIN PINF7 +#define DIO61_RPORT PINF +#define DIO61_WPORT PORTF +#define DIO61_DDR DDRF +#define DIO61_PWM NULL + +#define DIO62_PIN PINK0 +#define DIO62_RPORT PINK +#define DIO62_WPORT PORTK +#define DIO62_DDR DDRK +#define DIO62_PWM NULL + +#define DIO63_PIN PINK1 +#define DIO63_RPORT PINK +#define DIO63_WPORT PORTK +#define DIO63_DDR DDRK +#define DIO63_PWM NULL + +#define DIO64_PIN PINK2 +#define DIO64_RPORT PINK +#define DIO64_WPORT PORTK +#define DIO64_DDR DDRK +#define DIO64_PWM NULL + +#define DIO65_PIN PINK3 +#define DIO65_RPORT PINK +#define DIO65_WPORT PORTK +#define DIO65_DDR DDRK +#define DIO65_PWM NULL + +#define DIO66_PIN PINK4 +#define DIO66_RPORT PINK +#define DIO66_WPORT PORTK +#define DIO66_DDR DDRK +#define DIO66_PWM NULL + +#define DIO67_PIN PINK5 +#define DIO67_RPORT PINK +#define DIO67_WPORT PORTK +#define DIO67_DDR DDRK +#define DIO67_PWM NULL + +#define DIO68_PIN PINK6 +#define DIO68_RPORT PINK +#define DIO68_WPORT PORTK +#define DIO68_DDR DDRK +#define DIO68_PWM NULL + +#define DIO69_PIN PINK7 +#define DIO69_RPORT PINK +#define DIO69_WPORT PORTK +#define DIO69_DDR DDRK +#define DIO69_PWM NULL + + + +#undef PA0 +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_DDR DDRA +#define PA0_PWM NULL +#undef PA1 +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_DDR DDRA +#define PA1_PWM NULL +#undef PA2 +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_DDR DDRA +#define PA2_PWM NULL +#undef PA3 +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_DDR DDRA +#define PA3_PWM NULL +#undef PA4 +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_DDR DDRA +#define PA4_PWM NULL +#undef PA5 +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_DDR DDRA +#define PA5_PWM NULL +#undef PA6 +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_DDR DDRA +#define PA6_PWM NULL +#undef PA7 +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_DDR DDRA +#define PA7_PWM NULL + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB0_PWM NULL +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB1_PWM NULL +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB2_PWM NULL +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB3_PWM NULL +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB4_PWM &OCR2A +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB5_PWM NULL +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB6_PWM NULL +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB +#define PB7_PWM &OCR0A + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC0_PWM NULL +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC1_PWM NULL +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC2_PWM NULL +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC3_PWM NULL +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC4_PWM NULL +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC5_PWM NULL +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC6_PWM NULL +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC +#define PC7_PWM NULL + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD0_PWM NULL +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD1_PWM NULL +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD2_PWM NULL +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD3_PWM NULL +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD4_PWM NULL +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD5_PWM NULL +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD6_PWM NULL +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD +#define PD7_PWM NULL + +#undef PE0 +#define PE0_PIN PINE0 +#define PE0_RPORT PINE +#define PE0_WPORT PORTE +#define PE0_DDR DDRE +#define PE0_PWM NULL +#undef PE1 +#define PE1_PIN PINE1 +#define PE1_RPORT PINE +#define PE1_WPORT PORTE +#define PE1_DDR DDRE +#define PE1_PWM NULL +#undef PE2 +#define PE2_PIN PINE2 +#define PE2_RPORT PINE +#define PE2_WPORT PORTE +#define PE2_DDR DDRE +#define PE2_PWM NULL +#undef PE3 +#define PE3_PIN PINE3 +#define PE3_RPORT PINE +#define PE3_WPORT PORTE +#define PE3_DDR DDRE +#define PE3_PWM &OCR3AL +#undef PE4 +#define PE4_PIN PINE4 +#define PE4_RPORT PINE +#define PE4_WPORT PORTE +#define PE4_DDR DDRE +#define PE4_PWM &OCR3BL +#undef PE5 +#define PE5_PIN PINE5 +#define PE5_RPORT PINE +#define PE5_WPORT PORTE +#define PE5_DDR DDRE +#define PE5_PWM &OCR3CL +#undef PE6 +#define PE6_PIN PINE6 +#define PE6_RPORT PINE +#define PE6_WPORT PORTE +#define PE6_DDR DDRE +#define PE6_PWM NULL +#undef PE7 +#define PE7_PIN PINE7 +#define PE7_RPORT PINE +#define PE7_WPORT PORTE +#define PE7_DDR DDRE +#define PE7_PWM NULL + +#undef PF0 +#define PF0_PIN PINF0 +#define PF0_RPORT PINF +#define PF0_WPORT PORTF +#define PF0_DDR DDRF +#define PF0_PWM NULL +#undef PF1 +#define PF1_PIN PINF1 +#define PF1_RPORT PINF +#define PF1_WPORT PORTF +#define PF1_DDR DDRF +#define PF1_PWM NULL +#undef PF2 +#define PF2_PIN PINF2 +#define PF2_RPORT PINF +#define PF2_WPORT PORTF +#define PF2_DDR DDRF +#define PF2_PWM NULL +#undef PF3 +#define PF3_PIN PINF3 +#define PF3_RPORT PINF +#define PF3_WPORT PORTF +#define PF3_DDR DDRF +#define PF3_PWM NULL +#undef PF4 +#define PF4_PIN PINF4 +#define PF4_RPORT PINF +#define PF4_WPORT PORTF +#define PF4_DDR DDRF +#define PF4_PWM NULL +#undef PF5 +#define PF5_PIN PINF5 +#define PF5_RPORT PINF +#define PF5_WPORT PORTF +#define PF5_DDR DDRF +#define PF5_PWM NULL +#undef PF6 +#define PF6_PIN PINF6 +#define PF6_RPORT PINF +#define PF6_WPORT PORTF +#define PF6_DDR DDRF +#define PF6_PWM NULL +#undef PF7 +#define PF7_PIN PINF7 +#define PF7_RPORT PINF +#define PF7_WPORT PORTF +#define PF7_DDR DDRF +#define PF7_PWM NULL + +#undef PG0 +#define PG0_PIN PING0 +#define PG0_RPORT PING +#define PG0_WPORT PORTG +#define PG0_DDR DDRG +#define PG0_PWM NULL +#undef PG1 +#define PG1_PIN PING1 +#define PG1_RPORT PING +#define PG1_WPORT PORTG +#define PG1_DDR DDRG +#define PG1_PWM NULL +#undef PG2 +#define PG2_PIN PING2 +#define PG2_RPORT PING +#define PG2_WPORT PORTG +#define PG2_DDR DDRG +#define PG2_PWM NULL +#undef PG3 +#define PG3_PIN PING3 +#define PG3_RPORT PING +#define PG3_WPORT PORTG +#define PG3_DDR DDRG +#define PG3_PWM NULL +#undef PG4 +#define PG4_PIN PING4 +#define PG4_RPORT PING +#define PG4_WPORT PORTG +#define PG4_DDR DDRG +#define PG4_PWM NULL +#undef PG5 +#define PG5_PIN PING5 +#define PG5_RPORT PING +#define PG5_WPORT PORTG +#define PG5_DDR DDRG +#define PG5_PWM &OCR0B +#undef PG6 +#define PG6_PIN PING6 +#define PG6_RPORT PING +#define PG6_WPORT PORTG +#define PG6_DDR DDRG +#define PG6_PWM NULL +#undef PG7 +#define PG7_PIN PING7 +#define PG7_RPORT PING +#define PG7_WPORT PORTG +#define PG7_DDR DDRG +#define PG7_PWM NULL + +#undef PH0 +#define PH0_PIN PINH0 +#define PH0_RPORT PINH +#define PH0_WPORT PORTH +#define PH0_DDR DDRH +#define PH0_PWM NULL +#undef PH1 +#define PH1_PIN PINH1 +#define PH1_RPORT PINH +#define PH1_WPORT PORTH +#define PH1_DDR DDRH +#define PH1_PWM NULL +#undef PH2 +#define PH2_PIN PINH2 +#define PH2_RPORT PINH +#define PH2_WPORT PORTH +#define PH2_DDR DDRH +#define PH2_PWM NULL +#undef PH3 +#define PH3_PIN PINH3 +#define PH3_RPORT PINH +#define PH3_WPORT PORTH +#define PH3_DDR DDRH +#define PH3_PWM &OCR4AL +#undef PH4 +#define PH4_PIN PINH4 +#define PH4_RPORT PINH +#define PH4_WPORT PORTH +#define PH4_DDR DDRH +#define PH4_PWM &OCR4BL +#undef PH5 +#define PH5_PIN PINH5 +#define PH5_RPORT PINH +#define PH5_WPORT PORTH +#define PH5_DDR DDRH +#define PH5_PWM &OCR4CL +#undef PH6 +#define PH6_PIN PINH6 +#define PH6_RPORT PINH +#define PH6_WPORT PORTH +#define PH6_DDR DDRH +#define PH6_PWM &OCR2B +#undef PH7 +#define PH7_PIN PINH7 +#define PH7_RPORT PINH +#define PH7_WPORT PORTH +#define PH7_DDR DDRH +#define PH7_PWM NULL + +#undef PJ0 +#define PJ0_PIN PINJ0 +#define PJ0_RPORT PINJ +#define PJ0_WPORT PORTJ +#define PJ0_DDR DDRJ +#define PJ0_PWM NULL +#undef PJ1 +#define PJ1_PIN PINJ1 +#define PJ1_RPORT PINJ +#define PJ1_WPORT PORTJ +#define PJ1_DDR DDRJ +#define PJ1_PWM NULL +#undef PJ2 +#define PJ2_PIN PINJ2 +#define PJ2_RPORT PINJ +#define PJ2_WPORT PORTJ +#define PJ2_DDR DDRJ +#define PJ2_PWM NULL +#undef PJ3 +#define PJ3_PIN PINJ3 +#define PJ3_RPORT PINJ +#define PJ3_WPORT PORTJ +#define PJ3_DDR DDRJ +#define PJ3_PWM NULL +#undef PJ4 +#define PJ4_PIN PINJ4 +#define PJ4_RPORT PINJ +#define PJ4_WPORT PORTJ +#define PJ4_DDR DDRJ +#define PJ4_PWM NULL +#undef PJ5 +#define PJ5_PIN PINJ5 +#define PJ5_RPORT PINJ +#define PJ5_WPORT PORTJ +#define PJ5_DDR DDRJ +#define PJ5_PWM NULL +#undef PJ6 +#define PJ6_PIN PINJ6 +#define PJ6_RPORT PINJ +#define PJ6_WPORT PORTJ +#define PJ6_DDR DDRJ +#define PJ6_PWM NULL +#undef PJ7 +#define PJ7_PIN PINJ7 +#define PJ7_RPORT PINJ +#define PJ7_WPORT PORTJ +#define PJ7_DDR DDRJ +#define PJ7_PWM NULL + +#undef PK0 +#define PK0_PIN PINK0 +#define PK0_RPORT PINK +#define PK0_WPORT PORTK +#define PK0_DDR DDRK +#define PK0_PWM NULL +#undef PK1 +#define PK1_PIN PINK1 +#define PK1_RPORT PINK +#define PK1_WPORT PORTK +#define PK1_DDR DDRK +#define PK1_PWM NULL +#undef PK2 +#define PK2_PIN PINK2 +#define PK2_RPORT PINK +#define PK2_WPORT PORTK +#define PK2_DDR DDRK +#define PK2_PWM NULL +#undef PK3 +#define PK3_PIN PINK3 +#define PK3_RPORT PINK +#define PK3_WPORT PORTK +#define PK3_DDR DDRK +#define PK3_PWM NULL +#undef PK4 +#define PK4_PIN PINK4 +#define PK4_RPORT PINK +#define PK4_WPORT PORTK +#define PK4_DDR DDRK +#define PK4_PWM NULL +#undef PK5 +#define PK5_PIN PINK5 +#define PK5_RPORT PINK +#define PK5_WPORT PORTK +#define PK5_DDR DDRK +#define PK5_PWM NULL +#undef PK6 +#define PK6_PIN PINK6 +#define PK6_RPORT PINK +#define PK6_WPORT PORTK +#define PK6_DDR DDRK +#define PK6_PWM NULL +#undef PK7 +#define PK7_PIN PINK7 +#define PK7_RPORT PINK +#define PK7_WPORT PORTK +#define PK7_DDR DDRK +#define PK7_PWM NULL + +#undef PL0 +#define PL0_PIN PINL0 +#define PL0_RPORT PINL +#define PL0_WPORT PORTL +#define PL0_DDR DDRL +#define PL0_PWM NULL +#undef PL1 +#define PL1_PIN PINL1 +#define PL1_RPORT PINL +#define PL1_WPORT PORTL +#define PL1_DDR DDRL +#define PL1_PWM NULL +#undef PL2 +#define PL2_PIN PINL2 +#define PL2_RPORT PINL +#define PL2_WPORT PORTL +#define PL2_DDR DDRL +#define PL2_PWM NULL +#undef PL3 +#define PL3_PIN PINL3 +#define PL3_RPORT PINL +#define PL3_WPORT PORTL +#define PL3_DDR DDRL +#define PL3_PWM &OCR5AL +#undef PL4 +#define PL4_PIN PINL4 +#define PL4_RPORT PINL +#define PL4_WPORT PORTL +#define PL4_DDR DDRL +#define PL4_PWM &OCR5BL +#undef PL5 +#define PL5_PIN PINL5 +#define PL5_RPORT PINL +#define PL5_WPORT PORTL +#define PL5_DDR DDRL +#define PL5_PWM &OCR5CL +#undef PL6 +#define PL6_PIN PINL6 +#define PL6_RPORT PINL +#define PL6_WPORT PORTL +#define PL6_DDR DDRL +#define PL6_PWM NULL +#undef PL7 +#define PL7_PIN PINL7 +#define PL7_RPORT PINL +#define PL7_WPORT PORTL +#define PL7_DDR DDRL +#define PL7_PWM NULL + +#endif + +#if defined (__AVR_AT90USB1287__) +// SPI +#define SCK DIO9 +#define MISO DIO11 +#define MOSI DIO10 +#define SS DIO8 + +// change for your board +#define DEBUG_LED DIO31 /* led D5 red */ + +/* +pins +*/ +#define DIO0_PIN PINA0 +#define DIO0_RPORT PINA +#define DIO0_WPORT PORTA +#define DIO0_PWM NULL +#define DIO0_DDR DDRA + +#define DIO1_PIN PINA1 +#define DIO1_RPORT PINA +#define DIO1_WPORT PORTA +#define DIO1_PWM NULL +#define DIO1_DDR DDRA + +#define DIO2_PIN PINA2 +#define DIO2_RPORT PINA +#define DIO2_WPORT PORTA +#define DIO2_PWM NULL +#define DIO2_DDR DDRA + +#define DIO3_PIN PINA3 +#define DIO3_RPORT PINA +#define DIO3_WPORT PORTA +#define DIO3_PWM NULL +#define DIO3_DDR DDRA + +#define DIO4_PIN PINA4 +#define DIO4_RPORT PINA +#define DIO4_WPORT PORTA +#define DIO4_PWM NULL +#define DIO4_DDR DDRA + +#define DIO5_PIN PINA5 +#define DIO5_RPORT PINA +#define DIO5_WPORT PORTA +#define DIO5_PWM NULL +#define DIO5_DDR DDRA + +#define DIO6_PIN PINA6 +#define DIO6_RPORT PINA +#define DIO6_WPORT PORTA +#define DIO6_PWM NULL +#define DIO6_DDR DDRA + +#define DIO7_PIN PINA7 +#define DIO7_RPORT PINA +#define DIO7_WPORT PORTA +#define DIO7_PWM NULL +#define DIO7_DDR DDRA + +#define DIO8_PIN PINB0 +#define DIO8_RPORT PINB +#define DIO8_WPORT PORTB +#define DIO8_PWM NULL +#define DIO8_DDR DDRB + +#define DIO9_PIN PINB1 +#define DIO9_RPORT PINB +#define DIO9_WPORT PORTB +#define DIO9_PWM NULL +#define DIO9_DDR DDRB + +#define DIO10_PIN PINB2 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_PWM NULL +#define DIO10_DDR DDRB + +#define DIO11_PIN PINB3 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_PWM NULL +#define DIO11_DDR DDRB + +#define DIO12_PIN PINB4 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_PWM NULL +#define DIO12_DDR DDRB + +#define DIO13_PIN PINB5 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_PWM NULL +#define DIO13_DDR DDRB + +#define DIO14_PIN PINB6 +#define DIO14_RPORT PINB +#define DIO14_WPORT PORTB +#define DIO14_PWM NULL +#define DIO14_DDR DDRB + +#define DIO15_PIN PINB7 +#define DIO15_RPORT PINB +#define DIO15_WPORT PORTB +#define DIO15_PWM NULL +#define DIO15_DDR DDRB + +#define DIO16_PIN PINC0 +#define DIO16_RPORT PINC +#define DIO16_WPORT PORTC +#define DIO16_PWM NULL +#define DIO16_DDR DDRC + +#define DIO17_PIN PINC1 +#define DIO17_RPORT PINC +#define DIO17_WPORT PORTC +#define DIO17_PWM NULL +#define DIO17_DDR DDRC + +#define DIO18_PIN PINC2 +#define DIO18_RPORT PINC +#define DIO18_WPORT PORTC +#define DIO18_PWM NULL +#define DIO18_DDR DDRC + +#define DIO19_PIN PINC3 +#define DIO19_RPORT PINC +#define DIO19_WPORT PORTC +#define DIO19_PWM NULL +#define DIO19_DDR DDRC + +#define DIO20_PIN PINC4 +#define DIO20_RPORT PINC +#define DIO20_WPORT PORTC +#define DIO20_PWM NULL +#define DIO20_DDR DDRC + +#define DIO21_PIN PINC5 +#define DIO21_RPORT PINC +#define DIO21_WPORT PORTC +#define DIO21_PWM NULL +#define DIO21_DDR DDRC + +#define DIO22_PIN PINC6 +#define DIO22_RPORT PINC +#define DIO22_WPORT PORTC +#define DIO22_PWM NULL +#define DIO22_DDR DDRC + +#define DIO23_PIN PINC7 +#define DIO23_RPORT PINC +#define DIO23_WPORT PORTC +#define DIO23_PWM NULL +#define DIO23_DDR DDRC + +#define DIO24_PIN PIND0 +#define DIO24_RPORT PIND +#define DIO24_WPORT PORTD +#define DIO24_PWM NULL +#define DIO24_DDR DDRD + +#define DIO25_PIN PIND1 +#define DIO25_RPORT PIND +#define DIO25_WPORT PORTD +#define DIO25_PWM NULL +#define DIO25_DDR DDRD + +#define DIO26_PIN PIND2 +#define DIO26_RPORT PIND +#define DIO26_WPORT PORTD +#define DIO26_PWM NULL +#define DIO26_DDR DDRD + +#define DIO27_PIN PIND3 +#define DIO27_RPORT PIND +#define DIO27_WPORT PORTD +#define DIO27_PWM NULL +#define DIO27_DDR DDRD + +#define DIO28_PIN PIND4 +#define DIO28_RPORT PIND +#define DIO28_WPORT PORTD +#define DIO28_PWM NULL +#define DIO28_DDR DDRD + +#define DIO29_PIN PIND5 +#define DIO29_RPORT PIND +#define DIO29_WPORT PORTD +#define DIO29_PWM NULL +#define DIO29_DDR DDRD + +#define DIO30_PIN PIND6 +#define DIO30_RPORT PIND +#define DIO30_WPORT PORTD +#define DIO30_PWM NULL +#define DIO30_DDR DDRD + +#define DIO31_PIN PIND7 +#define DIO31_RPORT PIND +#define DIO31_WPORT PORTD +#define DIO31_PWM NULL +#define DIO31_DDR DDRD + + +#define DIO32_PIN PINE0 +#define DIO32_RPORT PINE +#define DIO32_WPORT PORTE +#define DIO32_PWM NULL +#define DIO32_DDR DDRE + +#define DIO33_PIN PINE1 +#define DIO33_RPORT PINE +#define DIO33_WPORT PORTE +#define DIO33_PWM NULL +#define DIO33_DDR DDRE + +#define DIO34_PIN PINE2 +#define DIO34_RPORT PINE +#define DIO34_WPORT PORTE +#define DIO34_PWM NULL +#define DIO34_DDR DDRE + +#define DIO35_PIN PINE3 +#define DIO35_RPORT PINE +#define DIO35_WPORT PORTE +#define DIO35_PWM NULL +#define DIO35_DDR DDRE + +#define DIO36_PIN PINE4 +#define DIO36_RPORT PINE +#define DIO36_WPORT PORTE +#define DIO36_PWM NULL +#define DIO36_DDR DDRE + +#define DIO37_PIN PINE5 +#define DIO37_RPORT PINE +#define DIO37_WPORT PORTE +#define DIO37_PWM NULL +#define DIO37_DDR DDRE + +#define DIO38_PIN PINE6 +#define DIO38_RPORT PINE +#define DIO38_WPORT PORTE +#define DIO38_PWM NULL +#define DIO38_DDR DDRE + +#define DIO39_PIN PINE7 +#define DIO39_RPORT PINE +#define DIO39_WPORT PORTE +#define DIO39_PWM NULL +#define DIO39_DDR DDRE + +#define AIO0_PIN PINF0 +#define AIO0_RPORT PINF +#define AIO0_WPORT PORTF +#define AIO0_PWM NULL +#define AIO0_DDR DDRF + +#define AIO1_PIN PINF1 +#define AIO1_RPORT PINF +#define AIO1_WPORT PORTF +#define AIO1_PWM NULL +#define AIO1_DDR DDRF + +#define AIO2_PIN PINF2 +#define AIO2_RPORT PINF +#define AIO2_WPORT PORTF +#define AIO2_PWM NULL +#define AIO2_DDR DDRF + +#define AIO3_PIN PINF3 +#define AIO3_RPORT PINF +#define AIO3_WPORT PORTF +#define AIO3_PWM NULL +#define AIO3_DDR DDRF + +#define AIO4_PIN PINF4 +#define AIO4_RPORT PINF +#define AIO4_WPORT PORTF +#define AIO4_PWM NULL +#define AIO4_DDR DDRF + +#define AIO5_PIN PINF5 +#define AIO5_RPORT PINF +#define AIO5_WPORT PORTF +#define AIO5_PWM NULL +#define AIO5_DDR DDRF + +#define AIO6_PIN PINF6 +#define AIO6_RPORT PINF +#define AIO6_WPORT PORTF +#define AIO6_PWM NULL +#define AIO6_DDR DDRF + +#define AIO7_PIN PINF7 +#define AIO7_RPORT PINF +#define AIO7_WPORT PORTF +#define AIO7_PWM NULL +#define AIO7_DDR DDRF + +#define DIO40_PIN PINF0 +#define DIO40_RPORT PINF +#define DIO40_WPORT PORTF +#define DIO40_PWM NULL +#define DIO40_DDR DDRF + +#define DIO41_PIN PINF1 +#define DIO41_RPORT PINF +#define DIO41_WPORT PORTF +#define DIO41_PWM NULL +#define DIO41_DDR DDRF + +#define DIO42_PIN PINF2 +#define DIO42_RPORT PINF +#define DIO42_WPORT PORTF +#define DIO42_PWM NULL +#define DIO42_DDR DDRF + +#define DIO43_PIN PINF3 +#define DIO43_RPORT PINF +#define DIO43_WPORT PORTF +#define DIO43_PWM NULL +#define DIO43_DDR DDRF + +#define DIO44_PIN PINF4 +#define DIO44_RPORT PINF +#define DIO44_WPORT PORTF +#define DIO44_PWM NULL +#define DIO44_DDR DDRF + +#define DIO45_PIN PINF5 +#define DIO45_RPORT PINF +#define DIO45_WPORT PORTF +#define DIO45_PWM NULL +#define DIO45_DDR DDRF + +#define DIO46_PIN PINF6 +#define DIO46_RPORT PINF +#define DIO46_WPORT PORTF +#define DIO46_PWM NULL +#define DIO46_DDR DDRF + +#define DIO47_PIN PINF7 +#define DIO47_RPORT PINF +#define DIO47_WPORT PORTF +#define DIO47_PWM NULL +#define DIO47_DDR DDRF + + + +#undef PA0 +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_PWM NULL +#define PA0_DDR DDRA +#undef PA1 +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_PWM NULL +#define PA1_DDR DDRA +#undef PA2 +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_PWM NULL +#define PA2_DDR DDRA +#undef PA3 +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_PWM NULL +#define PA3_DDR DDRA +#undef PA4 +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_PWM NULL +#define PA4_DDR DDRA +#undef PA5 +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_PWM NULL +#define PA5_DDR DDRA +#undef PA6 +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_PWM NULL +#define PA6_DDR DDRA +#undef PA7 +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_PWM NULL +#define PA7_DDR DDRA + +#undef PB0 +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_PWM NULL +#define PB0_DDR DDRB +#undef PB1 +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_PWM NULL +#define PB1_DDR DDRB +#undef PB2 +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_PWM NULL +#define PB2_DDR DDRB +#undef PB3 +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_PWM NULL +#define PB3_DDR DDRB +#undef PB4 +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_PWM NULL +#define PB4_DDR DDRB +#undef PB5 +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_PWM NULL +#define PB5_DDR DDRB +#undef PB6 +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_PWM NULL +#define PB6_DDR DDRB +#undef PB7 +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_PWM NULL +#define PB7_DDR DDRB + +#undef PC0 +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_PWM NULL +#define PC0_DDR DDRC +#undef PC1 +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_PWM NULL +#define PC1_DDR DDRC +#undef PC2 +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_PWM NULL +#define PC2_DDR DDRC +#undef PC3 +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_PWM NULL +#define PC3_DDR DDRC +#undef PC4 +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_PWM NULL +#define PC4_DDR DDRC +#undef PC5 +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_PWM NULL +#define PC5_DDR DDRC +#undef PC6 +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_PWM NULL +#define PC6_DDR DDRC +#undef PC7 +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_PWM NULL +#define PC7_DDR DDRC + +#undef PD0 +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_PWM NULL +#define PD0_DDR DDRD +#undef PD1 +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_PWM NULL +#define PD1_DDR DDRD +#undef PD2 +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_PWM NULL +#define PD2_DDR DDRD +#undef PD3 +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_PWM NULL +#define PD3_DDR DDRD +#undef PD4 +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_PWM NULL +#define PD4_DDR DDRD +#undef PD5 +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_PWM NULL +#define PD5_DDR DDRD +#undef PD6 +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_PWM NULL +#define PD6_DDR DDRD +#undef PD7 +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_PWM NULL +#define PD7_DDR DDRD + +#undef PE0 +#define PE0_PIN PINE0 +#define PE0_RPORT PINE +#define PE0_WPORT PORTE +#define PE0_PWM NULL +#define PE0_DDR DDRE +#undef PE1 +#define PE1_PIN PINE1 +#define PE1_RPORT PINE +#define PE1_WPORT PORTE +#define PE1_PWM NULL +#define PE1_DDR DDRE +#undef PE2 +#define PE2_PIN PINE2 +#define PE2_RPORT PINE +#define PE2_WPORT PORTE +#define PE2_PWM NULL +#define PE2_DDR DDRE +#undef PE3 +#define PE3_PIN PINE3 +#define PE3_RPORT PINE +#define PE3_WPORT PORTE +#define PE3_PWM NULL +#define PE3_DDR DDRE +#undef PE4 +#define PE4_PIN PINE4 +#define PE4_RPORT PINE +#define PE4_WPORT PORTE +#define PE4_PWM NULL +#define PE4_DDR DDRE +#undef PE5 +#define PE5_PIN PINE5 +#define PE5_RPORT PINE +#define PE5_WPORT PORTE +#define PE5_PWM NULL +#define PE5_DDR DDRE +#undef PE6 +#define PE6_PIN PINE6 +#define PE6_RPORT PINE +#define PE6_WPORT PORTE +#define PE6_PWM NULL +#define PE6_DDR DDRE +#undef PE7 +#define PE7_PIN PINE7 +#define PE7_RPORT PINE +#define PE7_WPORT PORTE +#define PE7_PWM NULL +#define PE7_DDR DDRE + +#undef PF0 +#define PF0_PIN PINF0 +#define PF0_RPORT PINF +#define PF0_WPORT PORTF +#define PF0_PWM NULL +#define PF0_DDR DDRF +#undef PF1 +#define PF1_PIN PINF1 +#define PF1_RPORT PINF +#define PF1_WPORT PORTF +#define PF1_PWM NULL +#define PF1_DDR DDRF +#undef PF2 +#define PF2_PIN PINF2 +#define PF2_RPORT PINF +#define PF2_WPORT PORTF +#define PF2_PWM NULL +#define PF2_DDR DDRF +#undef PF3 +#define PF3_PIN PINF3 +#define PF3_RPORT PINF +#define PF3_WPORT PORTF +#define PF3_PWM NULL +#define PF3_DDR DDRF +#undef PF4 +#define PF4_PIN PINF4 +#define PF4_RPORT PINF +#define PF4_WPORT PORTF +#define PF4_PWM NULL +#define PF4_DDR DDRF +#undef PF5 +#define PF5_PIN PINF5 +#define PF5_RPORT PINF +#define PF5_WPORT PORTF +#define PF5_PWM NULL +#define PF5_DDR DDRF +#undef PF6 +#define PF6_PIN PINF6 +#define PF6_RPORT PINF +#define PF6_WPORT PORTF +#define PF6_PWM NULL +#define PF6_DDR DDRF +#undef PF7 +#define PF7_PIN PINF7 +#define PF7_RPORT PINF +#define PF7_WPORT PORTF +#define PF7_PWM NULL +#define PF7_DDR DDRF +#endif + +#ifndef DIO0_PIN +#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request +#endif + #endif /* _ARDUINO_H */ diff --git a/Marlin/pins.h b/Marlin/pins.h index 2c2bc91445..4ec22793ec 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -1,738 +1,737 @@ -#ifndef PINS_H -#define PINS_H - -/**************************************************************************************** -* Arduino pin assignment -* -* ATMega168 -* +-\/-+ -* PC6 1| |28 PC5 (AI 5 / D19) -* (D 0) PD0 2| |27 PC4 (AI 4 / D18) -* (D 1) PD1 3| |26 PC3 (AI 3 / D17) -* (D 2) PD2 4| |25 PC2 (AI 2 / D16) -* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) -* (D 4) PD4 6| |23 PC0 (AI 0 / D14) -* VCC 7| |22 GND -* GND 8| |21 AREF -* PB6 9| |20 AVCC -* PB7 10| |19 PB5 (D 13) -* PWM+ (D 5) PD5 11| |18 PB4 (D 12) -* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -* (D 7) PD7 13| |16 PB2 (D 10) PWM -* (D 8) PB0 14| |15 PB1 (D 9) PWM -* +----+ -****************************************************************************************/ -#if MOTHERBOARD == 0 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega168__ -#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. -#endif - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 4 -#define X_MAX_PIN 9 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN 13 - -#define Z_STEP_PIN 19 -#define Z_DIR_PIN 18 -#define Z_ENABLE_PIN 5 -#define Z_MIN_PIN 17 -#define Z_MAX_PIN 16 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 15 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -#endif - - - -/**************************************************************************************** -* Sanguino/RepRap Motherboard with direct-drive extruders -* -* ATMega644P -* -* +---\/---+ -* (D 0) PB0 1| |40 PA0 (AI 0 / D31) -* (D 1) PB1 2| |39 PA1 (AI 1 / D30) -* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) -* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) -* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) -* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) -* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) -* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) -* RST 9| |32 AREF -* VCC 10| |31 GND -* GND 11| |30 AVCC -* XTAL2 12| |29 PC7 (D 23) -* XTAL1 13| |28 PC6 (D 22) -* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI -* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO -* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS -* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK -* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA -* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL -* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM -* +--------+ -* -****************************************************************************************/ -#if MOTHERBOARD == 1 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 19 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PIN 29 -#define Z_DIR_PIN 30 -#define Z_ENABLE_PIN 31 -#define Z_MIN_PIN 2 -#define Z_MAX_PIN 1 - -#define E0_STEP_PIN 12 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN 3 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN 0 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 14 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ - - - -#endif - - -/**************************************************************************************** -* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* -* -****************************************************************************************/ -#if MOTHERBOARD == 2 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PINN 27 -#define Z_DIR_PINN 28 -#define Z_ENABLE_PIN 29 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 31 - -#define E0_STEP_PIN 17 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 4 -#define LED_PIN 0 - -#define SD_CARD_WRITE 2 -#define SD_CARD_DETECT 3 -#define SD_CARD_SELECT 4 - -//our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 - -//pin for controlling the PSU. -#define PS_ON_PIN 14 - -#define FAN_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN -1 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#endif - -/**************************************************************************************** -* Arduino Mega pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 33 -#define MOTHERBOARD 3 -#define RAMPS_V_1_3 -#endif -#if MOTHERBOARD == 3 -#define KNOWN_BOARD 1 - -//////////////////FIX THIS////////////// -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 -// #define RAMPS_V_1_3 -// #define RAMPS_V_1_0 - -#ifdef RAMPS_V_1_3 - -#define X_STEP_PIN 54 -#define X_DIR_PIN 55 -#define X_ENABLE_PIN 38 -#define X_MIN_PIN 3 -#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. - -#define Y_STEP_PIN 60 -#define Y_DIR_PIN 61 -#define Y_ENABLE_PIN 56 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN 15 //15 - -#define Z_STEP_PIN 46 -#define Z_DIR_PIN 48 -#define Z_ENABLE_PIN 62 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN 19 //19 - -#define E0_STEP_PIN 26 -#define E0_DIR_PIN 28 -#define E0_ENABLE_PIN 24 - -#define E1_STEP_PIN 36 -#define E1_DIR_PIN 34 -#define E1_ENABLE_PIN 30 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 4 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#define HEATER_0_PIN 10 // EXTRUDER 1 -#define HEATER_1_PIN 9 // EXTRUDER 2 -#define HEATER_2_PIN -1 // EXTRUDER 2 -#define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 15 // ANALOG NUMBERING -#define TEMP_2_PIN -1 // ANALOG NUMBERING -#define HEATER_BED_PIN 8 // BED -#define TEMP_BED_PIN 14 // ANALOG NUMBERING - - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default - -#define X_STEP_PIN 26 -#define X_DIR_PIN 28 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 - -#define Y_STEP_PIN 38 -#define Y_DIR_PIN 40 -#define Y_ENABLE_PIN 36 -#define Y_MIN_PIN 16 -#define Y_MAX_PIN -1 //17 - -#define Z_STEP_PIN 44 -#define Z_DIR_PIN 46 -#define Z_ENABLE_PIN 42 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E0_STEP_PIN 32 -#define E0_DIR_PIN 34 -#define E0_ENABLE_PIN 30 - -#define SDPOWER 48 -#define SDSS 53 -#define LED_PIN 13 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - - - -#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 - #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_BED_PIN -1 // RAMPS 1.0 - #define FAN_PIN 11 // RAMPS 1.0 -#else // RAMPS_V_1_1 or RAMPS_V_1_2 - #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_BED_PIN 8 // RAMPS 1.1 - #define FAN_PIN 9 // RAMPS 1.1 -#endif -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#endif - -// SPI for Max6675 Thermocouple - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 - #define MISO_PIN 50 - #define MOSI_PIN 51 - #define MAX6675_SS 53 -#else - #define MAX6675_SS 49 -#endif - - -#endif -/**************************************************************************************** -* Duemilanove w/ ATMega328P pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 4 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega328P__ -#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 17 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 13 -#define Z_DIR_PIN 3 -#define Z_ENABLE_PIN 2 -#define Z_MIN_PIN 4 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN 5 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#endif - -/**************************************************************************************** -* Gen6 pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 5 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ - #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -//x axis pins - #define X_STEP_PIN 15 - #define X_DIR_PIN 18 - #define X_ENABLE_PIN 19 - #define X_MIN_PIN 20 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 25 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 27 - #define Z_DIR_PIN 28 - #define Z_ENABLE_PIN 29 - #define Z_MIN_PIN 30 - #define Z_MAX_PIN -1 - - //extruder pins - #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 - #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 - #define HEATER_2_PIN -1 - #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 - - #define SDPOWER -1 - #define SDSS 17 - #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define FAN_PIN -1 //changed @ rkoeppl 20110410 - #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 - //our pin for debugging. - - #define DEBUG_PIN 0 - - //our RS485 pins - #define TX_ENABLE_PIN 12 - #define RX_ENABLE_PIN 13 - - -#endif - -/**************************************************************************************** -* Sanguinololu pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 62 -#define MOTHERBOARD 6 -#define SANGUINOLOLU_V_1_2 -#endif -#if MOTHERBOARD == 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 21 -#define X_MIN_PIN 18 -#define X_MAX_PIN -2 - -#define Y_STEP_PIN 22 -#define Y_DIR_PIN 23 -#define Y_MIN_PIN 19 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 3 -#define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 1 -#define E0_DIR_PIN 0 - -#define LED_PIN -1 - -#define FAN_PIN -1 - -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 // (extruder) -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - -#ifdef SANGUINOLOLU_V_1_2 - -#define HEATER_BED_PIN 12 // (bed) -#define X_ENABLE_PIN 14 -#define Y_ENABLE_PIN 14 -#define Z_ENABLE_PIN 26 -#define E0_ENABLE_PIN 14 - -#else - -#define HEATER_BED_PIN 14 // (bed) -#define X_ENABLE_PIN -1 -#define Y_ENABLE_PIN -1 -#define Z_ENABLE_PIN -1 -#define E0_ENABLE_PIN -1 - -#endif - -#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define SDPOWER -1 -#define SDSS 31 - -#endif - - -#if MOTHERBOARD == 7 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 22 -#define X_MAX_PIN 24 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 26 -#define Y_MAX_PIN 28 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 32 -#define Z_ENABLE_PIN 35 - -#define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 11 - -#define EXTRUDER_0_STEP_PIN 43 -#define EXTRUDER_0_DIR_PIN 45 -#define EXTRUDER_0_ENABLE_PIN 41 -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define EXTRUDER_1_STEP_PIN 49 -#define EXTRUDER_1_DIR_PIN 47 -#define EXTRUDER_1_ENABLE_PIN 51 -#define EXTRUDER_1_HEATER_PIN 3 -#define EXTRUDER_1_TEMPERATURE_PIN 10 -#define HEATER_1_PIN 51 -#define TEMP_1_PIN 3 - - - -#define E0_STEP_PIN EXTRUDER_0_STEP_PIN -#define E0_DIR_PIN EXTRUDER_0_DIR_PIN -#define E0_ENABLE_PIN EXTRUDER_0_ENABLE_PIN - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 7 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#ifdef ULTRA_LCD - - #ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - #else //old style panel with shift register - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - //buttons are attached to a shift register - #define SHIFT_CLK 38 - #define SHIFT_LD 42 - #define SHIFT_OUT 40 - #define SHIFT_EN 17 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 5 - #define LCD_PINS_D4 6 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 20 - #define LCD_PINS_D7 19 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - - //bits in the shift register that carry the buttons for: - // left up center down right red - #define BL_LE 7 - #define BL_UP 6 - #define BL_MI 5 - #define BL_DW 4 - #define BL_RI 3 - #define BL_ST 2 - - #define BLEN_B 1 - #define BLEN_A 0 - #endif -#endif //ULTRA_LCD - -#endif - -/**************************************************************************************** -* Teensylu 0.7 pin assingments (ATMEGA90USB) -* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! -****************************************************************************************/ -#if MOTHERBOARD == 8 -#define MOTHERBOARD 8 -#define KNOWN_BOARD 1 - - -#define X_STEP_PIN 0 -#define X_DIR_PIN 1 -#define X_ENABLE_PIN 39 -#define X_MIN_PIN 13 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 2 -#define Y_DIR_PIN 3 -#define Y_ENABLE_PIN 38 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 4 -#define Z_DIR_PIN 5 -#define Z_ENABLE_PIN 23 -#define Z_MIN_PIN 15 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 6 -#define E0_DIR_PIN 7 -#define E0_ENABLE_PIN 19 - - - -#define HEATER_0_PIN 21 // Extruder -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define HEATER_BED_PIN 20 // Bed -#define FAN_PIN 22 // Fan - -#define TEMP_0_PIN 7 // Extruder -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // Bed - -#define SDPOWER -1 -#define SDSS 8 -#define LED_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define ALARM_PIN -1 - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define SCK_PIN 9 - #define MISO_PIN 11 - #define MOSI_PIN 10 -#endif -#endif - -#ifndef KNOWN_BOARD -#error Unknown MOTHERBOARD value in configuration.h -#endif - -//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN -#if EXTRUDERS == 3 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN -#elif EXTRUDERS == 2 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS -1 -#elif EXTRUDERS == 1 - #define _E1_PINS -1 - #define _E2_PINS -1 -#else - #error Unsupported number of extruders -#endif -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ - HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ - HEATER_BED_PIN, FAN_PIN, \ - _E0_PINS, _E1_PINS, _E2_PINS, \ - TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } +#ifndef PINS_H +#define PINS_H + +/**************************************************************************************** +* Arduino pin assignment +* +* ATMega168 +* +-\/-+ +* PC6 1| |28 PC5 (AI 5 / D19) +* (D 0) PD0 2| |27 PC4 (AI 4 / D18) +* (D 1) PD1 3| |26 PC3 (AI 3 / D17) +* (D 2) PD2 4| |25 PC2 (AI 2 / D16) +* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) +* (D 4) PD4 6| |23 PC0 (AI 0 / D14) +* VCC 7| |22 GND +* GND 8| |21 AREF +* PB6 9| |20 AVCC +* PB7 10| |19 PB5 (D 13) +* PWM+ (D 5) PD5 11| |18 PB4 (D 12) +* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +* (D 7) PD7 13| |16 PB2 (D 10) PWM +* (D 8) PB0 14| |15 PB1 (D 9) PWM +* +----+ +****************************************************************************************/ +#if MOTHERBOARD == 0 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega168__ +#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. +#endif + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 4 +#define X_MAX_PIN 9 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN 13 + +#define Z_STEP_PIN 19 +#define Z_DIR_PIN 18 +#define Z_ENABLE_PIN 5 +#define Z_MIN_PIN 17 +#define Z_MAX_PIN 16 + +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 15 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 +#endif + + + +/**************************************************************************************** +* Sanguino/RepRap Motherboard with direct-drive extruders +* +* ATMega644P +* +* +---\/---+ +* (D 0) PB0 1| |40 PA0 (AI 0 / D31) +* (D 1) PB1 2| |39 PA1 (AI 1 / D30) +* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +* RST 9| |32 AREF +* VCC 10| |31 GND +* GND 11| |30 AVCC +* XTAL2 12| |29 PC7 (D 23) +* XTAL1 13| |28 PC6 (D 22) +* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +* +--------+ +* +****************************************************************************************/ +#if MOTHERBOARD == 1 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 19 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PIN 29 +#define Z_DIR_PIN 30 +#define Z_ENABLE_PIN 31 +#define Z_MIN_PIN 2 +#define Z_MAX_PIN 1 + +#define E0_STEP_PIN 12 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN 3 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN 0 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 14 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 +/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ + + + +#endif + + +/**************************************************************************************** +* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* +* +****************************************************************************************/ +#if MOTHERBOARD == 2 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PINN 27 +#define Z_DIR_PINN 28 +#define Z_ENABLE_PIN 29 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 31 + +#define E0_STEP_PIN 17 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 4 +#define LED_PIN 0 + +#define SD_CARD_WRITE 2 +#define SD_CARD_DETECT 3 +#define SD_CARD_SELECT 4 + +//our RS485 pins +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 + +//pin for controlling the PSU. +#define PS_ON_PIN 14 + +#define FAN_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN -1 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#endif + +/**************************************************************************************** +* Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 33 +#define MOTHERBOARD 3 +#define RAMPS_V_1_3 +#endif +#if MOTHERBOARD == 3 +#define KNOWN_BOARD 1 + +//////////////////FIX THIS////////////// +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 +// #define RAMPS_V_1_3 +// #define RAMPS_V_1_0 + +#ifdef RAMPS_V_1_3 + +#define X_STEP_PIN 54 +#define X_DIR_PIN 55 +#define X_ENABLE_PIN 38 +#define X_MIN_PIN 3 +#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. + +#define Y_STEP_PIN 60 +#define Y_DIR_PIN 61 +#define Y_ENABLE_PIN 56 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN 15 //15 + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 62 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN 19 //19 + +#define E0_STEP_PIN 26 +#define E0_DIR_PIN 28 +#define E0_ENABLE_PIN 24 + +#define E1_STEP_PIN 36 +#define E1_DIR_PIN 34 +#define E1_ENABLE_PIN 30 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 4 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#define HEATER_0_PIN 10 // EXTRUDER 1 +#define HEATER_1_PIN 9 // EXTRUDER 2 +#define HEATER_2_PIN -1 // EXTRUDER 2 +#define TEMP_0_PIN 13 // ANALOG NUMBERING +#define TEMP_1_PIN 15 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING +#define HEATER_BED_PIN 8 // BED +#define TEMP_BED_PIN 14 // ANALOG NUMBERING + + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default + +#define X_STEP_PIN 26 +#define X_DIR_PIN 28 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 + +#define Y_STEP_PIN 38 +#define Y_DIR_PIN 40 +#define Y_ENABLE_PIN 36 +#define Y_MIN_PIN 16 +#define Y_MAX_PIN -1 //17 + +#define Z_STEP_PIN 44 +#define Z_DIR_PIN 46 +#define Z_ENABLE_PIN 42 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E0_STEP_PIN 32 +#define E0_DIR_PIN 34 +#define E0_ENABLE_PIN 30 + +#define SDPOWER 48 +#define SDSS 53 +#define LED_PIN 13 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + + + +#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 + #define HEATER_0_PIN 12 // RAMPS 1.0 + #define HEATER_BED_PIN -1 // RAMPS 1.0 + #define FAN_PIN 11 // RAMPS 1.0 +#else // RAMPS_V_1_1 or RAMPS_V_1_2 + #define HEATER_0_PIN 10 // RAMPS 1.1 + #define HEATER_BED_PIN 8 // RAMPS 1.1 + #define FAN_PIN 9 // RAMPS 1.1 +#endif +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#endif + +// SPI for Max6675 Thermocouple + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 + #define MISO_PIN 50 + #define MOSI_PIN 51 + #define MAX6675_SS 53 +#else + #define MAX6675_SS 49 +#endif + + +#endif +/**************************************************************************************** +* Duemilanove w/ ATMega328P pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 4 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega328P__ +#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 17 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 13 +#define Z_DIR_PIN 3 +#define Z_ENABLE_PIN 2 +#define Z_MIN_PIN 4 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN 5 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#endif + +/**************************************************************************************** +* Gen6 pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 5 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ + #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +//x axis pins + #define X_STEP_PIN 15 + #define X_DIR_PIN 18 + #define X_ENABLE_PIN 19 + #define X_MIN_PIN 20 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 25 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 27 + #define Z_DIR_PIN 28 + #define Z_ENABLE_PIN 29 + #define Z_MIN_PIN 30 + #define Z_MAX_PIN -1 + + //extruder pins + #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 + #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 + #define HEATER_1_PIN -1 + #define HEATER_2_PIN -1 + #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 + + #define SDPOWER -1 + #define SDSS 17 + #define LED_PIN -1 //changed @ rkoeppl 20110410 + #define FAN_PIN -1 //changed @ rkoeppl 20110410 + #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 + //our pin for debugging. + + #define DEBUG_PIN 0 + + //our RS485 pins + #define TX_ENABLE_PIN 12 + #define RX_ENABLE_PIN 13 + + +#endif + +/**************************************************************************************** +* Sanguinololu pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 62 +#define MOTHERBOARD 6 +#define SANGUINOLOLU_V_1_2 +#endif +#if MOTHERBOARD == 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -2 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 1 +#define E0_DIR_PIN 0 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#ifdef SANGUINOLOLU_V_1_2 + +#define HEATER_BED_PIN 12 // (bed) +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E0_ENABLE_PIN 14 + +#else + +#define HEATER_BED_PIN 14 // (bed) +#define X_ENABLE_PIN -1 +#define Y_ENABLE_PIN -1 +#define Z_ENABLE_PIN -1 +#define E0_ENABLE_PIN -1 + +#endif + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define SDPOWER -1 +#define SDSS 31 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 11 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define EXTRUDER_1_HEATER_PIN 3 +#define EXTRUDER_1_TEMPERATURE_PIN 10 +#define HEATER_1_PIN 51 +#define TEMP_1_PIN 3 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN 49 +#define E1_DIR_PIN 47 +#define E1_ENABLE_PIN 51 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + //buttons are attached to a shift register + #define SHIFT_CLK 38 + #define SHIFT_LD 42 + #define SHIFT_OUT 40 + #define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 5 + #define LCD_PINS_D4 6 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 20 + #define LCD_PINS_D7 19 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + +#endif + +/**************************************************************************************** +* Teensylu 0.7 pin assingments (ATMEGA90USB) +* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! +****************************************************************************************/ +#if MOTHERBOARD == 8 +#define MOTHERBOARD 8 +#define KNOWN_BOARD 1 + + +#define X_STEP_PIN 0 +#define X_DIR_PIN 1 +#define X_ENABLE_PIN 39 +#define X_MIN_PIN 13 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 2 +#define Y_DIR_PIN 3 +#define Y_ENABLE_PIN 38 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 4 +#define Z_DIR_PIN 5 +#define Z_ENABLE_PIN 23 +#define Z_MIN_PIN 15 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 6 +#define E0_DIR_PIN 7 +#define E0_ENABLE_PIN 19 + + + +#define HEATER_0_PIN 21 // Extruder +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define HEATER_BED_PIN 20 // Bed +#define FAN_PIN 22 // Fan + +#define TEMP_0_PIN 7 // Extruder +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // Bed + +#define SDPOWER -1 +#define SDSS 8 +#define LED_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define ALARM_PIN -1 + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define SCK_PIN 9 + #define MISO_PIN 11 + #define MOSI_PIN 10 +#endif +#endif + +#ifndef KNOWN_BOARD +#error Unknown MOTHERBOARD value in configuration.h +#endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN +#if EXTRUDERS == 3 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN +#elif EXTRUDERS == 2 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS -1 +#elif EXTRUDERS == 1 + #define _E1_PINS -1 + #define _E2_PINS -1 +#else + #error Unsupported number of extruders +#endif +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ + HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ + HEATER_BED_PIN, FAN_PIN, \ + _E0_PINS, _E1_PINS, _E2_PINS, \ + TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index d2179301f2..afe2f3e83e 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -191,8 +191,8 @@ void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exi } #ifdef ADVANCE - long initial_advance = block->advance*entry_factor*entry_factor; - long final_advance = block->advance*exit_factor*exit_factor; + volatile long initial_advance = block->advance*entry_factor*entry_factor; + volatile long final_advance = block->advance*exit_factor*exit_factor; #endif // ADVANCE // block->accelerate_until = accelerate_steps; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 465ab89ddf..586ea7c95a 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -57,7 +57,7 @@ volatile static unsigned long step_events_completed; // The number of step event static long advance_rate, advance, final_advance = 0; static long old_advance = 0; #endif -static long e_steps; +static long e_steps[3]; static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. static long acceleration_time, deceleration_time; //static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; @@ -266,7 +266,7 @@ FORCE_INLINE void trapezoid_generator_reset() { advance = current_block->initial_advance; final_advance = current_block->final_advance; // Do E steps + advance steps - e_steps += ((advance >>8) - old_advance); + e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); old_advance = advance >>8; #endif deceleration_time = 0; @@ -303,8 +303,8 @@ ISR(TIMER1_COMPA_vect) counter_z = counter_x; counter_e = counter_x; step_events_completed = 0; - // #ifdef ADVANCE - e_steps = 0; +// #ifdef ADVANCE +// e_steps[current_block->active_extruder] = 0; // #endif } else { @@ -418,11 +418,11 @@ ISR(TIMER1_COMPA_vect) #ifndef ADVANCE if ((out_bits & (1< 0) { counter_e -= current_block->step_event_count; if ((out_bits & (1<active_extruder]--; } else { - e_steps++; + e_steps[current_block->active_extruder]++; } } #endif //ADVANCE @@ -503,7 +503,7 @@ ISR(TIMER1_COMPA_vect) } //if(advance > current_block->advance) advance = current_block->advance; // Do E steps + advance steps - e_steps += ((advance >>8) - old_advance); + e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); old_advance = advance >>8; #endif @@ -532,7 +532,7 @@ ISR(TIMER1_COMPA_vect) } if(advance < final_advance) advance = final_advance; // Do E steps + advance steps - e_steps += ((advance >>8) - old_advance); + e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); old_advance = advance >>8; #endif //ADVANCE } @@ -557,20 +557,50 @@ ISR(TIMER1_COMPA_vect) old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz) OCR0A = old_OCR0A; // Set E direction (Depends on E direction + advance) - for(unsigned char i=0; i<4;) { - WRITE_E_STEP(LOW); - if (e_steps == 0) break; - i++; - if (e_steps < 0) { - WRITE_E_DIR(INVERT_E_DIR); - e_steps++; - WRITE_E_STEP(HIGH); - } - else if (e_steps > 0) { - WRITE_E_DIR(!INVERT_E_DIR); - e_steps--; - WRITE_E_STEP(HIGH); + for(unsigned char i=0; i<4;i++) { + if (e_steps[0] != 0) { + WRITE(E0_STEP_PIN, LOW); + if (e_steps[0] < 0) { + WRITE(E0_DIR_PIN, INVERT_E0_DIR); + e_steps[0]++; + WRITE(E0_STEP_PIN, HIGH); + } + else if (e_steps[0] > 0) { + WRITE(E0_DIR_PIN, !INVERT_E0_DIR); + e_steps[0]--; + WRITE(E0_STEP_PIN, HIGH); + } } + #if EXTRUDERS > 1 + if (e_steps[1] != 0) { + WRITE(E1_STEP_PIN, LOW); + if (e_steps[1] < 0) { + WRITE(E1_DIR_PIN, INVERT_E1_DIR); + e_steps[1]++; + WRITE(E1_STEP_PIN, HIGH); + } + else if (e_steps[1] > 0) { + WRITE(E1_DIR_PIN, !INVERT_E1_DIR); + e_steps[1]--; + WRITE(E1_STEP_PIN, HIGH); + } + } + #endif + #if EXTRUDERS > 2 + if (e_steps[2] != 0) { + WRITE(E2_STEP_PIN, LOW); + if (e_steps[2] < 0) { + WRITE(E2_DIR_PIN, INVERT_E2_DIR); + e_steps[2]++; + WRITE(E2_STEP_PIN, HIGH); + } + else if (e_steps[2] > 0) { + WRITE(E2_DIR_PIN, !INVERT_E2_DIR); + e_steps[2]--; + WRITE(E2_STEP_PIN, HIGH); + } + } + #endif } } #endif // ADVANCE @@ -712,7 +742,9 @@ void st_init() TCCR0A &= ~(1< 2 + #define WRITE_E_STEP(v) { if(current_block->active_extruder == 2) { WRITE(E2_STEP_PIN, v); } else { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }}} + #define NORM_E_DIR() { if(current_block->active_extruder == 2) { WRITE(!E2_DIR_PIN, INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(!E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }}} + #define REV_E_DIR() { if(current_block->active_extruder == 2) { WRITE(E2_DIR_PIN, INVERT_E2_DIR); } else { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }}} +#elif EXTRUDERS > 1 + #define WRITE_E_STEP(v) { if(current_block->active_extruder == 1) { WRITE(E1_STEP_PIN, v); } else { WRITE(E0_STEP_PIN, v); }} + #define NORM_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); }} + #define REV_E_DIR() { if(current_block->active_extruder == 1) { WRITE(E1_DIR_PIN, INVERT_E1_DIR); } else { WRITE(E0_DIR_PIN, INVERT_E0_DIR); }} +#else + #define WRITE_E_STEP(v) WRITE(E0_STEP_PIN, v) + #define NORM_E_DIR() WRITE(E0_DIR_PIN, !INVERT_E0_DIR) + #define REV_E_DIR() WRITE(E0_DIR_PIN, INVERT_E0_DIR) +#endif + + // Initialize and start the stepper motor subsystem void st_init(); diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 72b8959791..761e136a32 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -26,7 +26,6 @@ It has preliminary support for Matthew Roberts advance algorithm http://reprap.org/pipermail/reprap-dev/2011-May/003323.html - This firmware is optimized for gen6 electronics. */ #include @@ -82,6 +81,7 @@ static unsigned long previous_millis_bed_heater; // static float pid_output[EXTRUDERS]; static bool pid_reset[EXTRUDERS]; #endif //PIDTEMP + static unsigned char soft_pwm[EXTRUDERS]; #ifdef WATCHPERIOD static int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all @@ -140,6 +140,10 @@ void updatePID() #endif } +int getHeaterPower(int heater) { + return soft_pwm[heater]; +} + void manage_heater() { #ifdef USE_WATCHDOG @@ -198,15 +202,16 @@ void manage_heater() } #endif - // Check if temperature is within the correct range - if((current_raw[e] > minttemp[e]) && (current_raw[e] < maxttemp[e])) - { - analogWrite(heater_pin_map[e], pid_output); - } - else { - analogWrite(heater_pin_map[e], 0); - } - + // Check if temperature is within the correct range + if((current_raw[e] > minttemp[e]) && (current_raw[e] < maxttemp[e])) + { + //analogWrite(heater_pin_map[e], pid_output); + soft_pwm[e] = (int)pid_output >> 1; + } + else { + //analogWrite(heater_pin_map[e], 0); + soft_pwm[e] = 0; + } } // End extruder for loop if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) @@ -418,7 +423,6 @@ void tp_init() DIDR0 |= 1 << TEMP_0_PIN; #else DIDR2 |= 1<<(TEMP_0_PIN - 8); - ADCSRB = 1< -1) @@ -426,7 +430,6 @@ void tp_init() DIDR0 |= 1< -1) @@ -434,7 +437,6 @@ void tp_init() DIDR0 |= 1 << TEMP_2_PIN; #else DIDR2 = 1<<(TEMP_2_PIN - 8); - ADCSRB = 1< -1) @@ -442,7 +444,6 @@ void tp_init() DIDR0 |= 1< -1 target_raw[0]=0; + soft_pwm[0]=0; #if HEATER_0_PIN > -1 digitalWrite(HEATER_0_PIN,LOW); #endif @@ -513,6 +515,7 @@ void disable_heater() #if TEMP_1_PIN > -1 target_raw[1]=0; + soft_pwm[1]=0; #if HEATER_1_PIN > -1 digitalWrite(HEATER_1_PIN,LOW); #endif @@ -520,6 +523,7 @@ void disable_heater() #if TEMP_2_PIN > -1 target_raw[2]=0; + soft_pwm[2]=0; #if HEATER_2_PIN > -1 digitalWrite(HEATER_2_PIN,LOW); #endif @@ -533,6 +537,26 @@ void disable_heater() #endif } +void max_temp_error(uint8_t e) { + digitalWrite(heater_pin_map[e], 0); + SERIAL_ERROR_START; + SERIAL_ERRORLN(e); + SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !"); +} + +void min_temp_error(uint8_t e) { + digitalWrite(heater_pin_map[e], 0); + SERIAL_ERROR_START; + SERIAL_ERRORLN(e); + SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); +} + +void bed_max_temp_error(void) { + digitalWrite(HEATER_BED_PIN, 0); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); +} + // Timer 0 is shared with millies ISR(TIMER0_COMPB_vect) { @@ -543,6 +567,33 @@ ISR(TIMER0_COMPB_vect) static unsigned long raw_temp_2_value = 0; static unsigned long raw_temp_bed_value = 0; static unsigned char temp_state = 0; + static unsigned char pwm_count = 1; + static unsigned char soft_pwm_0; + static unsigned char soft_pwm_1; + static unsigned char soft_pwm_2; + + if(pwm_count == 0){ + soft_pwm_0 = soft_pwm[0]; + if(soft_pwm_0 > 0) WRITE(HEATER_0_PIN,1); + #if EXTRUDERS > 1 + soft_pwm_1 = soft_pwm[1]; + if(soft_pwm_1 > 0) WRITE(HEATER_1_PIN,1); + #endif + #if EXTRUDERS > 2 + soft_pwm_2 = soft_pwm[2]; + if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1); + #endif + } + if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0); + #if EXTRUDERS > 1 + if(soft_pwm_1 <= pwm_count) WRITE(HEATER_1_PIN,0); + #endif + #if EXTRUDERS > 2 + if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0); + #endif + + pwm_count++; + pwm_count &= 0x7f; switch(temp_state) { case 0: // Prepare TEMP_0 @@ -628,10 +679,10 @@ ISR(TIMER0_COMPB_vect) temp_state = 0; temp_count++; break; - default: - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temp measurement error!"); - break; +// default: +// SERIAL_ERROR_START; +// SERIAL_ERRORLNPGM("Temp measurement error!"); +// break; } if(temp_count >= 16) // 8 ms * 16 = 128ms. @@ -671,21 +722,15 @@ ISR(TIMER0_COMPB_vect) raw_temp_2_value = 0; raw_temp_bed_value = 0; - for(int e = 0; e < EXTRUDERS; e++) { + for(unsigned char e = 0; e < EXTRUDERS; e++) { if(current_raw[e] >= maxttemp[e]) { target_raw[e] = 0; - digitalWrite(heater_pin_map[e], 0); - SERIAL_ERROR_START; - SERIAL_ERRORLN((int)e); - SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !"); - kill(); + max_temp_error(e); + kill();; } if(current_raw[e] <= minttemp[e]) { target_raw[e] = 0; - digitalWrite(heater_pin_map[e], 0); - SERIAL_ERROR_START; - SERIAL_ERRORLN(e); - SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); + min_temp_error(e); kill(); } } @@ -693,9 +738,7 @@ ISR(TIMER0_COMPB_vect) #if defined(BED_MAXTEMP) && (HEATER_BED_PIN > -1) if(current_raw_bed >= bed_maxttemp) { target_raw_bed = 0; - digitalWrite(HEATER_BED_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); + bed_max_temp_error(); kill(); } #endif diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 15bc8a8352..aa0d6c4f59 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -1,143 +1,144 @@ -/* - temperature.h - temperature controller - Part of Marlin - - Copyright (c) 2011 Erik van der Zalm - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -#ifndef temperature_h -#define temperature_h - -#include "Marlin.h" -#include "fastio.h" -#ifdef PID_ADD_EXTRUSION_RATE - #include "stepper.h" -#endif - -// public functions -void tp_init(); //initialise the heating -void manage_heater(); //it is critical that this is called periodically. - -//low leven conversion routines -// do not use this routines and variables outsie of temperature.cpp -int temp2analog(int celsius, uint8_t e); -int temp2analogBed(int celsius); -float analog2temp(int raw, uint8_t e); -float analog2tempBed(int raw); -extern int target_raw[EXTRUDERS]; -extern int heatingtarget_raw[EXTRUDERS]; -extern int current_raw[EXTRUDERS]; -extern int target_raw_bed; -extern int current_raw_bed; -extern float Kp,Ki,Kd,Kc; - -#ifdef PIDTEMP - extern float pid_setpoint[EXTRUDERS]; -#endif - -#ifdef WATCHPERIOD - extern int watch_raw[EXTRUDERS] ; - extern unsigned long watchmillis; -#endif - - -//high level conversion routines, for use outside of temperature.cpp -//inline so that there is no performance decrease. -//deg=degreeCelsius - -FORCE_INLINE float degHotend(uint8_t extruder) { - return analog2temp(current_raw[extruder], extruder); -}; - -FORCE_INLINE float degBed() { - return analog2tempBed(current_raw_bed); -}; - -FORCE_INLINE float degTargetHotend(uint8_t extruder) { - return analog2temp(target_raw[extruder], extruder); -}; - -FORCE_INLINE float degTargetBed() { - return analog2tempBed(target_raw_bed); -}; - -FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) { - target_raw[extruder] = temp2analog(celsius, extruder); -#ifdef PIDTEMP - pid_setpoint[extruder] = celsius; -#endif //PIDTEMP -}; - -FORCE_INLINE void setTargetBed(const float &celsius) { - target_raw_bed = temp2analogBed(celsius); -}; - -FORCE_INLINE bool isHeatingHotend(uint8_t extruder){ - return target_raw[extruder] > current_raw[extruder]; -}; - -FORCE_INLINE bool isHeatingBed() { - return target_raw_bed > current_raw_bed; -}; - -FORCE_INLINE bool isCoolingHotend(uint8_t extruder) { - return target_raw[extruder] < current_raw[extruder]; -}; - -FORCE_INLINE bool isCoolingBed() { - return target_raw_bed < current_raw_bed; -}; - -#define degHotend0() degHotend(0) -#define degTargetHotend0() degTargetHotend(0) -#define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0) -#define isHeatingHotend0() isHeatingHotend(0) -#define isCoolingHotend0() isCoolingHotend(0) -#if EXTRUDERS > 1 -#define degHotend1() degHotend(1) -#define degTargetHotend1() degTargetHotend(1) -#define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1) -#define isHeatingHotend1() isHeatingHotend(1) -#define isCoolingHotend1() isCoolingHotend(1) -#endif -#if EXTRUDERS > 2 -#define degHotend2() degHotend(2) -#define degTargetHotend2() degTargetHotend(2) -#define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2) -#define isHeatingHotend2() isHeatingHotend(2) -#define isCoolingHotend2() isCoolingHotend(2) -#endif -#if EXTRUDERS > 3 -#error Invalid number of extruders -#endif - -FORCE_INLINE void autotempShutdown(){ - #ifdef AUTOTEMP - if(autotemp_enabled) - { - autotemp_enabled=false; - if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min) - setTargetHotend(0,ACTIVE_EXTRUDER); - } - #endif -} - -void disable_heater(); -void setWatch(); -void updatePID(); - -#endif +/* + temperature.h - temperature controller + Part of Marlin + + Copyright (c) 2011 Erik van der Zalm + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +#ifndef temperature_h +#define temperature_h + +#include "Marlin.h" +#include "fastio.h" +#ifdef PID_ADD_EXTRUSION_RATE + #include "stepper.h" +#endif + +// public functions +void tp_init(); //initialise the heating +void manage_heater(); //it is critical that this is called periodically. + +//low leven conversion routines +// do not use this routines and variables outsie of temperature.cpp +int temp2analog(int celsius, uint8_t e); +int temp2analogBed(int celsius); +float analog2temp(int raw, uint8_t e); +float analog2tempBed(int raw); +extern int target_raw[EXTRUDERS]; +extern int heatingtarget_raw[EXTRUDERS]; +extern int current_raw[EXTRUDERS]; +extern int target_raw_bed; +extern int current_raw_bed; +extern float Kp,Ki,Kd,Kc; + +#ifdef PIDTEMP + extern float pid_setpoint[EXTRUDERS]; +#endif + +#ifdef WATCHPERIOD + extern int watch_raw[EXTRUDERS] ; + extern unsigned long watchmillis; +#endif + + +//high level conversion routines, for use outside of temperature.cpp +//inline so that there is no performance decrease. +//deg=degreeCelsius + +FORCE_INLINE float degHotend(uint8_t extruder) { + return analog2temp(current_raw[extruder], extruder); +}; + +FORCE_INLINE float degBed() { + return analog2tempBed(current_raw_bed); +}; + +FORCE_INLINE float degTargetHotend(uint8_t extruder) { + return analog2temp(target_raw[extruder], extruder); +}; + +FORCE_INLINE float degTargetBed() { + return analog2tempBed(target_raw_bed); +}; + +FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) { + target_raw[extruder] = temp2analog(celsius, extruder); +#ifdef PIDTEMP + pid_setpoint[extruder] = celsius; +#endif //PIDTEMP +}; + +FORCE_INLINE void setTargetBed(const float &celsius) { + target_raw_bed = temp2analogBed(celsius); +}; + +FORCE_INLINE bool isHeatingHotend(uint8_t extruder){ + return target_raw[extruder] > current_raw[extruder]; +}; + +FORCE_INLINE bool isHeatingBed() { + return target_raw_bed > current_raw_bed; +}; + +FORCE_INLINE bool isCoolingHotend(uint8_t extruder) { + return target_raw[extruder] < current_raw[extruder]; +}; + +FORCE_INLINE bool isCoolingBed() { + return target_raw_bed < current_raw_bed; +}; + +#define degHotend0() degHotend(0) +#define degTargetHotend0() degTargetHotend(0) +#define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0) +#define isHeatingHotend0() isHeatingHotend(0) +#define isCoolingHotend0() isCoolingHotend(0) +#if EXTRUDERS > 1 +#define degHotend1() degHotend(1) +#define degTargetHotend1() degTargetHotend(1) +#define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1) +#define isHeatingHotend1() isHeatingHotend(1) +#define isCoolingHotend1() isCoolingHotend(1) +#endif +#if EXTRUDERS > 2 +#define degHotend2() degHotend(2) +#define degTargetHotend2() degTargetHotend(2) +#define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2) +#define isHeatingHotend2() isHeatingHotend(2) +#define isCoolingHotend2() isCoolingHotend(2) +#endif +#if EXTRUDERS > 3 +#error Invalid number of extruders +#endif + +FORCE_INLINE void autotempShutdown(){ + #ifdef AUTOTEMP + if(autotemp_enabled) + { + autotemp_enabled=false; + if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min) + setTargetHotend(0,ACTIVE_EXTRUDER); + } + #endif +} + +int getHeaterPower(int heater); +void disable_heater(); +void setWatch(); +void updatePID(); + +#endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 88f8f32fb3..d5772750d2 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1,1839 +1,1843 @@ -#include "ultralcd.h" -#ifdef ULTRA_LCD - -//=========================================================================== -//=============================imported variables============================ -//=========================================================================== - -extern volatile int feedmultiply; -extern volatile bool feedmultiplychanged; - -extern long position[4]; -extern CardReader card; - -//=========================================================================== -//=============================public variables============================ -//=========================================================================== -volatile char buttons=0; //the last checked buttons in a bit array. -int encoderpos=0; -short lastenc=0; - - -//=========================================================================== -//=============================private variables============================ -//=========================================================================== -static char messagetext[LCD_WIDTH]=""; - -//return for string conversion routines -static char conv[8]; - -#include -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 - -static unsigned long previous_millis_lcd=0; -static long previous_millis_buttons=0; - - -#ifdef NEWPANEL - static long blocking=0; -#else - static long blocking[8]={0,0,0,0,0,0,0,0}; -#endif - -static MainMenu menu; - -#include - -void lcdProgMemprint(const char *str) -{ - char ch=pgm_read_byte(str); - while(ch) - { - lcd.print(ch); - ch=pgm_read_byte(++str); - } -} -#define lcdprintPGM(x) lcdProgMemprint(MYPGM(x)) - - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== - -FORCE_INLINE int intround(const float &x){return int(0.5+x);} - -void lcd_status(const char* message) -{ - strncpy(messagetext,message,LCD_WIDTH); - messagetext[strlen(message)]=0; -} - -void lcd_statuspgm(const char* message) -{ - char ch=pgm_read_byte(message); - char *target=messagetext; - uint8_t cnt=0; - while(ch &&cnt>1; - if(READ(SHIFT_OUT)) - newbutton|=(1<<7); - WRITE(SHIFT_CLK,HIGH); - WRITE(SHIFT_CLK,LOW); - } - buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 - #endif - - //manage encoder rotation - char enc=0; - if(buttons&EN_A) - enc|=(1<<0); - if(buttons&EN_B) - enc|=(1<<1); - if(enc!=lastenc) - { - switch(enc) - { - case encrot0: - if(lastenc==encrot3) - encoderpos++; - else if(lastenc==encrot1) - encoderpos--; - break; - case encrot1: - if(lastenc==encrot0) - encoderpos++; - else if(lastenc==encrot2) - encoderpos--; - break; - case encrot2: - if(lastenc==encrot1) - encoderpos++; - else if(lastenc==encrot3) - encoderpos--; - break; - case encrot3: - if(lastenc==encrot2) - encoderpos++; - else if(lastenc==encrot0) - encoderpos--; - break; - default: - ; - } - } - lastenc=enc; -} - -#endif - -MainMenu::MainMenu() -{ - status=Main_Status; - displayStartingRow=0; - activeline=0; - force_lcd_update=true; - #ifdef ULTIPANEL - buttons_init(); - #endif - lcd_init(); - linechanging=false; - tune=false; -} - -void MainMenu::showStatus() -{ -#if LCD_HEIGHT==4 - static int olddegHotEnd0=-1; - static int oldtargetHotEnd0=-1; - //force_lcd_update=true; - if(force_lcd_update||feedmultiplychanged) //initial display of content - { - feedmultiplychanged=false; - encoderpos=feedmultiply; - clear(); - lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 "); - #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcdprintPGM("B123/567\001 "); - #endif - } - - int tHotEnd0=intround(degHotend0()); - if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often. - { - lcd.setCursor(1,0); - lcd.print(ftostr3(tHotEnd0)); - olddegHotEnd0=tHotEnd0; - } - int ttHotEnd0=intround(degTargetHotend0()); - if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(ttHotEnd0)); - oldtargetHotEnd0=ttHotEnd0; - } - #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - static int oldtBed=-1; - static int oldtargetBed=-1; - int tBed=intround(degBed()); - if((tBed!=oldtBed)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(tBed)); - oldtBed=tBed; - } - int targetBed=intround(degTargetBed()); - if((targetBed!=oldtargetBed)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(targetBed)); - oldtargetBed=targetBed; - } - #endif - //starttime=2; - static uint16_t oldtime=0; - if(starttime!=0) - { - lcd.setCursor(0,1); - uint16_t time=millis()/60000-starttime/60000; - - if(starttime!=oldtime) - { - lcd.print(itostr2(time/60));lcdprintPGM("h ");lcd.print(itostr2(time%60));lcdprintPGM("m"); - oldtime=time; - } - } - static int oldzpos=0; - int currentz=current_position[2]*10; - if((currentz!=oldzpos)||force_lcd_update) - { - lcd.setCursor(10,1); - lcdprintPGM("Z:");lcd.print(itostr31(currentz)); - oldzpos=currentz; - } - static int oldfeedmultiply=0; - int curfeedmultiply=feedmultiply; - if(encoderpos!=curfeedmultiply||force_lcd_update) - { - curfeedmultiply=encoderpos; - if(curfeedmultiply<10) - curfeedmultiply=10; - if(curfeedmultiply>999) - curfeedmultiply=999; - feedmultiply=curfeedmultiply; - encoderpos=curfeedmultiply; - } - if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) - { - oldfeedmultiply=curfeedmultiply; - lcd.setCursor(0,2); - lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% "); - } - if(messagetext[0]!='\0') - { - lcd.setCursor(0,LCD_HEIGHT-1); - lcd.print(messagetext); - uint8_t n=strlen(messagetext); - for(int8_t i=0;i1)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(tHotEnd0)); - olddegHotEnd0=tHotEnd0; - } - if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(ttHotEnd0)); - oldtargetHotEnd0=ttHotEnd0; - } - - if(messagetext[0]!='\0') - { - lcd.setCursor(0,LCD_HEIGHT-1); - lcd.print(messagetext); - uint8_t n=strlen(messagetext); - for(int8_t i=0;i400) encoderpos=400; - feedmultiply = encoderpos; - feedmultiplychanged=true; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - case ItemT_nozzle: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:"); - lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(degTargetHotend0()); - } - else - { - setTargetHotend0(encoderpos); - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - }break; - - case ItemT_fan: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); - lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=fanpwm; - } - else - { - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - case ItemT_flow://axis_steps_per_unit[i] = code_value(); - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Flow:"); - lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)axis_steps_per_unit[3]; - } - else - { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); - position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); - } - - }break; - default: - break; - } - line++; - } - 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};}\ -// } -// - -enum { - ItemCT_exit,ItemCT_nozzle, -#ifdef AUTOTEMP - ItemCT_autotempactive, - ItemCT_autotempmin,ItemCT_autotempmax,ItemCT_autotempfact, -#endif - ItemCT_fan, - ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C -}; - -void MainMenu::showControlTemp() -{ - uint8_t line=0; - clearIfNecessary(); - for(int8_t i=lineoffset;i260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - #ifdef AUTOTEMP - case ItemCT_autotempmin: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" \002 Min:"); - lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_min)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(autotemp_min); - } - else - { - autotemp_min=encoderpos; - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - case ItemCT_autotempmax: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" \002 Max:"); - lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(autotemp_max); - } - else - { - autotemp_max=encoderpos; - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - case ItemCT_autotempfact: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" \002 Fact:"); - lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=intround(autotemp_factor*100); - } - else - { - autotemp_max=encoderpos; - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>99) encoderpos=99; - lcd.setCursor(13,line);lcd.print(ftostr32(encoderpos/100.)); - } - - }break; - case ItemCT_autotempactive: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Autotemp:"); - lcd.setCursor(13,line); - if(autotemp_enabled) - lcdprintPGM("On"); - else - lcdprintPGM("Off"); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - autotemp_enabled=!autotemp_enabled; - lcd.setCursor(13,line); - if(autotemp_enabled) - lcdprintPGM("On "); - else - lcdprintPGM("Off"); - BLOCK; - } - - }break; - #endif //autotemp - case ItemCT_fan: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); - lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=fanpwm; - } - else - { - encoderpos=activeline*lcdslow; - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - case ItemCT_PID_P: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" PID-P: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kp)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kp; - } - else - { - Kp= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); - } - - }break; - case ItemCT_PID_I: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" PID-I: "); - lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(Ki*10/PID_dT); - } - else - { - Ki= encoderpos/10.*PID_dT; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); - } - - }break; - case ItemCT_PID_D: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" PID-D: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT)); - } - - if((activeline!=line) ) - break; - - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(Kd/5./PID_dT); - } - else - { - Kd= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); - } - - }break; - case ItemCT_PID_C: - #ifdef PID_ADD_EXTRUSION_RATE - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" PID-C: "); - lcd.setCursor(13,line);lcd.print(itostr3(Kc)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kc; - } - else - { - Kc= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - } - #endif - break; - default: - break; - } - line++; - } - #ifdef PID_ADD_EXTRUSION_RATE - updateActiveLines(ItemCT_PID_C,encoderpos); - #else - updateActiveLines(ItemCT_PID_D,encoderpos); - #endif -} - - -enum { - ItemCM_exit, - ItemCM_acc, ItemCM_xyjerk, - ItemCM_vmaxx, ItemCM_vmaxy, ItemCM_vmaxz, ItemCM_vmaxe, - ItemCM_vtravmin,ItemCM_vmin, - ItemCM_amaxx, ItemCM_amaxy, ItemCM_amaxz, ItemCM_amaxe, - ItemCM_aret,ItemCM_esteps -}; - - - -void MainMenu::showControlMotion() -{ - uint8_t line=0; - clearIfNecessary(); - for(int8_t i=lineoffset;i990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); - } - - }break; - case ItemCM_xyjerk: //max_xy_jerk - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: "); - lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_xy_jerk; - } - else - { - max_xy_jerk= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - - case ItemCM_vmaxx: - case ItemCM_vmaxy: - case ItemCM_vmaxz: - case ItemCM_vmaxe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Vmax "); - if(i==ItemCM_vmaxx)lcdprintPGM("x:"); - if(i==ItemCM_vmaxy)lcdprintPGM("y:"); - if(i==ItemCM_vmaxz)lcdprintPGM("z:"); - if(i==ItemCM_vmaxe)lcdprintPGM("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx])); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_feedrate[i-ItemCM_vmaxx]; - } - else - { - max_feedrate[i-ItemCM_vmaxx]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - - case ItemCM_vmin: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Vmin:"); - lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(minimumfeedrate); - } - else - { - minimumfeedrate= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - case ItemCM_vtravmin: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" VTrav min:"); - lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate)); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)mintravelfeedrate; - } - else - { - mintravelfeedrate= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - - }break; - - case ItemCM_amaxx: - case ItemCM_amaxy: - case ItemCM_amaxz: - case ItemCM_amaxe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Amax "); - if(i==ItemCM_amaxx)lcdprintPGM("x:"); - if(i==ItemCM_amaxy)lcdprintPGM("y:"); - if(i==ItemCM_amaxz)lcdprintPGM("z:"); - if(i==ItemCM_amaxe)lcdprintPGM("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));lcdprintPGM("00"); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100; - } - else - { - max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100; - encoderpos=activeline*lcdslow; - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); - } - - }break; - case ItemCM_aret://float retract_acceleration = 7000; - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" A-retract:"); - lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00"); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)retract_acceleration/100; - } - else - { - retract_acceleration= encoderpos*100; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<10) encoderpos=10; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); - } - - }break; - case ItemCM_esteps://axis_steps_per_unit[i] = code_value(); - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcdprintPGM(" Esteps/mm:"); - lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); - } - - if((activeline!=line) ) - break; - - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)axis_steps_per_unit[3]; - } - else - { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); - position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); - } - - }break; - default: - break; - } - line++; - } - updateActiveLines(ItemCM_esteps,encoderpos); -} - - -enum { - ItemC_exit,ItemC_temp,ItemC_move, - ItemC_store, ItemC_load,ItemC_failsafe -}; - -void MainMenu::showControl() -{ - uint8_t line=0; - clearIfNecessary(); - for(int8_t i=lineoffset;i=0)?'+':'-'; - xx=abs(xx); - conv[1]=(xx/1000)%10+'0'; - conv[2]=(xx/100)%10+'0'; - conv[3]=(xx/10)%10+'0'; - conv[4]='.'; - conv[5]=(xx)%10+'0'; - conv[6]=0; - return conv; -} - -char *ftostr32(const float &x) -{ - int xx=x*100; - conv[0]=(xx>=0)?'+':'-'; - xx=abs(xx); - conv[1]=(xx/100)%10+'0'; - conv[2]='.'; - conv[3]=(xx/10)%10+'0'; - conv[4]=(xx)%10+'0'; - conv[6]=0; - return conv; -} - -char *itostr31(const int &xx) -{ - conv[0]=(xx>=0)?'+':'-'; - conv[1]=(xx/1000)%10+'0'; - conv[2]=(xx/100)%10+'0'; - conv[3]=(xx/10)%10+'0'; - conv[4]='.'; - conv[5]=(xx)%10+'0'; - conv[6]=0; - return conv; -} - -char *itostr3(const int &xx) -{ - conv[0]=(xx/100)%10+'0'; - conv[1]=(xx/10)%10+'0'; - conv[2]=(xx)%10+'0'; - conv[3]=0; - return conv; -} - -char *itostr4(const int &xx) -{ - conv[0]=(xx/1000)%10+'0'; - conv[1]=(xx/100)%10+'0'; - conv[2]=(xx/10)%10+'0'; - conv[3]=(xx)%10+'0'; - conv[4]=0; - return conv; -} - -// convert float to string with +1234.5 format -char *ftostr51(const float &x) -{ - int xx=x*10; - conv[0]=(xx>=0)?'+':'-'; - xx=abs(xx); - conv[1]=(xx/10000)%10+'0'; - conv[2]=(xx/1000)%10+'0'; - conv[3]=(xx/100)%10+'0'; - conv[4]=(xx/10)%10+'0'; - conv[5]='.'; - conv[6]=(xx)%10+'0'; - conv[7]=0; - return conv; -} - - -#endif //ULTRA_LCD - +#include "ultralcd.h" +#ifdef ULTRA_LCD + +//=========================================================================== +//=============================imported variables============================ +//=========================================================================== + +extern volatile int feedmultiply; +extern volatile bool feedmultiplychanged; + +extern long position[4]; +extern CardReader card; + +//=========================================================================== +//=============================public variables============================ +//=========================================================================== +volatile char buttons=0; //the last checked buttons in a bit array. +int encoderpos=0; +short lastenc=0; + + +//=========================================================================== +//=============================private variables============================ +//=========================================================================== +static char messagetext[LCD_WIDTH]=""; + +//return for string conversion routines +static char conv[8]; + +#include +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 + +static unsigned long previous_millis_lcd=0; +static long previous_millis_buttons=0; + + +#ifdef NEWPANEL + static long blocking=0; +#else + static long blocking[8]={0,0,0,0,0,0,0,0}; +#endif + +static MainMenu menu; + +#include + +void lcdProgMemprint(const char *str) +{ + char ch=pgm_read_byte(str); + while(ch) + { + lcd.print(ch); + ch=pgm_read_byte(++str); + } +} +#define lcdprintPGM(x) lcdProgMemprint(MYPGM(x)) + + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + +FORCE_INLINE int intround(const float &x){return int(0.5+x);} + +void lcd_status(const char* message) +{ + strncpy(messagetext,message,LCD_WIDTH); + messagetext[strlen(message)]=0; +} + +void lcd_statuspgm(const char* message) +{ + char ch=pgm_read_byte(message); + char *target=messagetext; + uint8_t cnt=0; + while(ch &&cntms)) + buttons &= ~(1<>1; + if(READ(SHIFT_OUT)) + newbutton|=(1<<7); + WRITE(SHIFT_CLK,HIGH); + WRITE(SHIFT_CLK,LOW); + } + buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 + #endif + + //manage encoder rotation + char enc=0; + if(buttons&EN_A) + enc|=(1<<0); + if(buttons&EN_B) + enc|=(1<<1); + if(enc!=lastenc) + { + switch(enc) + { + case encrot0: + if(lastenc==encrot3) + encoderpos++; + else if(lastenc==encrot1) + encoderpos--; + break; + case encrot1: + if(lastenc==encrot0) + encoderpos++; + else if(lastenc==encrot2) + encoderpos--; + break; + case encrot2: + if(lastenc==encrot1) + encoderpos++; + else if(lastenc==encrot3) + encoderpos--; + break; + case encrot3: + if(lastenc==encrot2) + encoderpos++; + else if(lastenc==encrot0) + encoderpos--; + break; + default: + ; + } + } + lastenc=enc; +} + +#endif + +MainMenu::MainMenu() +{ + status=Main_Status; + displayStartingRow=0; + activeline=0; + force_lcd_update=true; + #ifdef ULTIPANEL + buttons_init(); + #endif + lcd_init(); + linechanging=false; + tune=false; +} + +void MainMenu::showStatus() +{ +#if LCD_HEIGHT==4 + static int olddegHotEnd0=-1; + static int oldtargetHotEnd0=-1; + //force_lcd_update=true; + if(force_lcd_update||feedmultiplychanged) //initial display of content + { + feedmultiplychanged=false; + encoderpos=feedmultiply; + clear(); + lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 "); + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + lcd.setCursor(10,0);lcdprintPGM("B123/567\001 "); + #endif + } + + int tHotEnd0=intround(degHotend0()); + if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often. + { + lcd.setCursor(1,0); + lcd.print(ftostr3(tHotEnd0)); + olddegHotEnd0=tHotEnd0; + } + int ttHotEnd0=intround(degTargetHotend0()); + if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(ttHotEnd0)); + oldtargetHotEnd0=ttHotEnd0; + } + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + static int oldtBed=-1; + static int oldtargetBed=-1; + int tBed=intround(degBed()); + if((tBed!=oldtBed)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(tBed)); + oldtBed=tBed; + } + int targetBed=intround(degTargetBed()); + if((targetBed!=oldtargetBed)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(targetBed)); + oldtargetBed=targetBed; + } + #endif + //starttime=2; + static uint16_t oldtime=0; + if(starttime!=0) + { + lcd.setCursor(0,1); + uint16_t time=millis()/60000-starttime/60000; + + if(starttime!=oldtime) + { + lcd.print(itostr2(time/60));lcdprintPGM("h ");lcd.print(itostr2(time%60));lcdprintPGM("m"); + oldtime=time; + } + } + static int oldzpos=0; + int currentz=current_position[2]*10; + if((currentz!=oldzpos)||force_lcd_update) + { + lcd.setCursor(10,1); + lcdprintPGM("Z:");lcd.print(itostr31(currentz)); + oldzpos=currentz; + } + static int oldfeedmultiply=0; + int curfeedmultiply=feedmultiply; + if(encoderpos!=curfeedmultiply||force_lcd_update) + { + curfeedmultiply=encoderpos; + if(curfeedmultiply<10) + curfeedmultiply=10; + if(curfeedmultiply>999) + curfeedmultiply=999; + feedmultiply=curfeedmultiply; + encoderpos=curfeedmultiply; + } + if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) + { + oldfeedmultiply=curfeedmultiply; + lcd.setCursor(0,2); + lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% "); + } + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(messagetext); + uint8_t n=strlen(messagetext); + for(int8_t i=0;i1)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(tHotEnd0)); + olddegHotEnd0=tHotEnd0; + } + if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(ttHotEnd0)); + oldtargetHotEnd0=ttHotEnd0; + } + + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(messagetext); + uint8_t n=strlen(messagetext); + for(int8_t i=0;i400) encoderpos=400; + feedmultiply = encoderpos; + feedmultiplychanged=true; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + case ItemT_nozzle: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:"); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(degTargetHotend0()); + } + else + { + setTargetHotend0(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; + + case ItemT_fan: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=fanpwm; + } + else + { + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + case ItemT_flow://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Flow:"); + lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)axis_steps_per_unit[3]; + } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + + }break; + default: + break; + } + line++; + } + 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};}\ +// } +// + +enum { + ItemCT_exit,ItemCT_nozzle, +#ifdef AUTOTEMP + ItemCT_autotempactive, + ItemCT_autotempmin,ItemCT_autotempmax,ItemCT_autotempfact, +#endif + ItemCT_fan, + ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C +}; + +void MainMenu::showControlTemp() +{ + uint8_t line=0; + clearIfNecessary(); + for(int8_t i=lineoffset;i260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + #ifdef AUTOTEMP + case ItemCT_autotempmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002 Min:"); + lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_min)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(autotemp_min); + } + else + { + autotemp_min=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + case ItemCT_autotempmax: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002 Max:"); + lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(autotemp_max); + } + else + { + autotemp_max=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + case ItemCT_autotempfact: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002 Fact:"); + lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(autotemp_factor*100); + } + else + { + autotemp_max=encoderpos; + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>99) encoderpos=99; + lcd.setCursor(13,line);lcd.print(ftostr32(encoderpos/100.)); + } + + }break; + case ItemCT_autotempactive: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Autotemp:"); + lcd.setCursor(13,line); + if(autotemp_enabled) + lcdprintPGM("On"); + else + lcdprintPGM("Off"); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + autotemp_enabled=!autotemp_enabled; + lcd.setCursor(13,line); + if(autotemp_enabled) + lcdprintPGM("On "); + else + lcdprintPGM("Off"); + BLOCK; + } + + }break; + #endif //autotemp + case ItemCT_fan: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=fanpwm; + } + else + { + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + case ItemCT_PID_P: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" PID-P: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kp)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kp; + } + else + { + Kp= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + + }break; + case ItemCT_PID_I: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" PID-I: "); + lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(Ki*10/PID_dT); + } + else + { + Ki= encoderpos/10.*PID_dT; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); + } + + }break; + case ItemCT_PID_D: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" PID-D: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT)); + } + + if((activeline!=line) ) + break; + + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(Kd/5./PID_dT); + } + else + { + Kd= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + + }break; + case ItemCT_PID_C: + #ifdef PID_ADD_EXTRUSION_RATE + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" PID-C: "); + lcd.setCursor(13,line);lcd.print(itostr3(Kc)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kc; + } + else + { + Kc= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + } + #endif + break; + default: + break; + } + line++; + } + #ifdef PID_ADD_EXTRUSION_RATE + updateActiveLines(ItemCT_PID_C,encoderpos); + #else + updateActiveLines(ItemCT_PID_D,encoderpos); + #endif +} + + +enum { + ItemCM_exit, + ItemCM_acc, ItemCM_xyjerk, + ItemCM_vmaxx, ItemCM_vmaxy, ItemCM_vmaxz, ItemCM_vmaxe, + ItemCM_vtravmin,ItemCM_vmin, + ItemCM_amaxx, ItemCM_amaxy, ItemCM_amaxz, ItemCM_amaxe, + ItemCM_aret,ItemCM_esteps +}; + + + +void MainMenu::showControlMotion() +{ + uint8_t line=0; + clearIfNecessary(); + for(int8_t i=lineoffset;i990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + } + + }break; + case ItemCM_xyjerk: //max_xy_jerk + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: "); + lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_xy_jerk; + } + else + { + max_xy_jerk= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + + case ItemCM_vmaxx: + case ItemCM_vmaxy: + case ItemCM_vmaxz: + case ItemCM_vmaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Vmax "); + if(i==ItemCM_vmaxx)lcdprintPGM("x:"); + if(i==ItemCM_vmaxy)lcdprintPGM("y:"); + if(i==ItemCM_vmaxz)lcdprintPGM("z:"); + if(i==ItemCM_vmaxe)lcdprintPGM("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_feedrate[i-ItemCM_vmaxx]; + } + else + { + max_feedrate[i-ItemCM_vmaxx]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + + case ItemCM_vmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Vmin:"); + lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(minimumfeedrate); + } + else + { + minimumfeedrate= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + case ItemCM_vtravmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" VTrav min:"); + lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)mintravelfeedrate; + } + else + { + mintravelfeedrate= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + + case ItemCM_amaxx: + case ItemCM_amaxy: + case ItemCM_amaxz: + case ItemCM_amaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Amax "); + if(i==ItemCM_amaxx)lcdprintPGM("x:"); + if(i==ItemCM_amaxy)lcdprintPGM("y:"); + if(i==ItemCM_amaxz)lcdprintPGM("z:"); + if(i==ItemCM_amaxe)lcdprintPGM("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));lcdprintPGM("00"); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100; + } + else + { + max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + } + + }break; + case ItemCM_aret://float retract_acceleration = 7000; + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" A-retract:"); + lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00"); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)retract_acceleration/100; + } + else + { + retract_acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<10) encoderpos=10; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00"); + } + + }break; + case ItemCM_esteps://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Esteps/mm:"); + lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)axis_steps_per_unit[3]; + } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + + }break; + default: + break; + } + line++; + } + updateActiveLines(ItemCM_esteps,encoderpos); +} + + +enum { + ItemC_exit,ItemC_temp,ItemC_move, + ItemC_store, ItemC_load,ItemC_failsafe +}; + +void MainMenu::showControl() +{ + uint8_t line=0; + clearIfNecessary(); + for(int8_t i=lineoffset;i=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} + +char *ftostr32(const float &x) +{ + int xx=x*100; + conv[0]=(xx>=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/100)%10+'0'; + conv[2]='.'; + conv[3]=(xx/10)%10+'0'; + conv[4]=(xx)%10+'0'; + conv[6]=0; + return conv; +} + +char *itostr31(const int &xx) +{ + conv[0]=(xx>=0)?'+':'-'; + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} + +char *itostr3(const int &xx) +{ + conv[0]=(xx/100)%10+'0'; + conv[1]=(xx/10)%10+'0'; + conv[2]=(xx)%10+'0'; + conv[3]=0; + return conv; +} + +char *itostr4(const int &xx) +{ + conv[0]=(xx/1000)%10+'0'; + conv[1]=(xx/100)%10+'0'; + conv[2]=(xx/10)%10+'0'; + conv[3]=(xx)%10+'0'; + conv[4]=0; + return conv; +} + +// convert float to string with +1234.5 format +char *ftostr51(const float &x) +{ + int xx=x*10; + conv[0]=(xx>=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/10000)%10+'0'; + conv[2]=(xx/1000)%10+'0'; + conv[3]=(xx/100)%10+'0'; + conv[4]=(xx/10)%10+'0'; + conv[5]='.'; + conv[6]=(xx)%10+'0'; + conv[7]=0; + return conv; +} + + +#endif //ULTRA_LCD + From 617968ab7634c0568532007a2baf07c0f4247bff Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 12 Dec 2011 20:43:47 +0100 Subject: [PATCH 155/228] G92 fix --- Marlin/Marlin.pde | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 79707e8c34..bc5d92c3b9 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -584,7 +584,7 @@ FORCE_INLINE void process_commands() } if(code_seen(axis_codes[Y_AXIS])) { - current_position[1]=code_value()+add_homeing[1]; + current_position[1]=code_value()+add_homeing[1]; } if(code_seen(axis_codes[Z_AXIS])) { @@ -612,9 +612,11 @@ FORCE_INLINE void process_commands() if(code_seen(axis_codes[i])) { current_position[i] = code_value()+add_homeing[i]; if(i == E_AXIS) { + current_position[i] = code_value(); plan_set_e_position(current_position[E_AXIS]); } else { + current_position[i] = code_value()+add_homeing[i]; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); } } @@ -822,7 +824,7 @@ FORCE_INLINE void process_commands() SERIAL_PROTOCOLPGM("T:"); SERIAL_PROTOCOL( degHotend(tmp_extruder) ); SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOLLN( (int)tmp_extruder ); + SERIAL_PROTOCOL( (int)tmp_extruder ); #ifdef TEMP_RESIDENCY_TIME SERIAL_PROTOCOLPGM(" W:"); if(residencyStart > -1) @@ -869,7 +871,7 @@ FORCE_INLINE void process_commands() SERIAL_PROTOCOLPGM("T:"); SERIAL_PROTOCOL(tt); SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOLLN( (int)active_extruder ); + SERIAL_PROTOCOL( (int)active_extruder ); SERIAL_PROTOCOLPGM(" B:"); SERIAL_PROTOCOLLN(degBed()); codenum = millis(); @@ -936,7 +938,11 @@ FORCE_INLINE void process_commands() if(code_seen('Y')) disable_y(); if(code_seen('Z')) disable_z(); #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS - if(code_seen('E')) disable_e(); + if(code_seen('E')) { + disable_e0(); + disable_e1(); + disable_e2(); + } #endif LCD_MESSAGEPGM("Partial Release"); } From 554cc1718d58d20f73b266a6bf6a4f7bca204d63 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Thu, 15 Dec 2011 11:59:07 +0100 Subject: [PATCH 156/228] Fiexed E_ENABLE_PIN errors --- Marlin/Marlin.pde | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index bc5d92c3b9..1dbfb8694c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -937,7 +937,7 @@ FORCE_INLINE void process_commands() if(code_seen('X')) disable_x(); if(code_seen('Y')) disable_y(); if(code_seen('Z')) disable_z(); - #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS + #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(); @@ -1248,8 +1248,8 @@ void manage_inactivity(byte debug) if( (millis()-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) { - bool oldstatus=READ(E_ENABLE_PIN); - enable_e(); + 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], @@ -1261,7 +1261,7 @@ void manage_inactivity(byte debug) previous_millis_cmd=millis(); //enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); st_synchronize(); - WRITE(E_ENABLE_PIN,oldstatus); + WRITE(E0_ENABLE_PIN,oldstatus); } #endif check_axes_activity(); From 651cde8b98b9499796e96cad9e267dcd6bbb86d4 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 09:20:34 +0100 Subject: [PATCH 157/228] untestest commit, so I don't loose code.. features runout prevention addons --- Marlin/Configuration.h | 2 +- Marlin/Marlin.pde | 86 +++++++++++++++++++++++++++++++----------- Marlin/stepper.cpp | 12 ++++-- Marlin/temperature.cpp | 5 +++ 4 files changed, 80 insertions(+), 25 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index dc8c799f5b..16672d01be 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -248,7 +248,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define SLOWDOWN //default stepper release if idle -#define DEFAULT_STEPPER_DEACTIVE_TIME 60 +#define DEFAULT_STEPPER_DEACTIVE_TIME 1200 #define DEFAULT_STEPPER_DEACTIVE_COMMAND "M84 X Y E" //z stays powered diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 4d031ea788..0e62eea254 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -176,8 +176,10 @@ const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 //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*1000; +static unsigned long previous_millis_runoutprevent = 0; +//static unsigned long previous_millis_beep = 0; +static unsigned long max_inactive_time=0; +static unsigned long stepper_inactive_time = 0; static unsigned long last_stepperdisabled_time=30*1000; //first release check after 30 seconds static unsigned long starttime=0; @@ -243,6 +245,10 @@ void setup() fromsd[i] = false; } + max_inactive_time = DEFAULT_MAX_INACTIVE_TIME*1000; + stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000; + + EEPROM_RetrieveSettings(); // loads data from EEPROM if available for(int8_t i=0; i < NUM_AXIS; i++) @@ -415,6 +421,7 @@ FORCE_INLINE void get_command() SERIAL_ECHO_START; SERIAL_ECHOLN(time); LCD_MESSAGE(time); + st_synchronize(); card.printingHasFinished(); card.checkautostart(true); @@ -1200,11 +1207,34 @@ void prepare_arc_move(char isclockwise) { void manage_inactivity(byte debug) { - if( (millis()-previous_millis_cmd) > max_inactive_time ) + unsigned long curtime=millis(); + SERIAL_ECHO_START; + SERIAL_ECHO("MS"); + SERIAL_ECHO(millis()); + SERIAL_ECHO(" PREV_CMD"); + SERIAL_ECHO(previous_millis_cmd); + SERIAL_ECHO(" maxinactive"); + SERIAL_ECHOLN(max_inactive_time ); + + if( (curtime-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) + { + LCD_MESSAGEPGM("Bored Shutdown."); + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Bored Shutdown."); kill(); + } + + if( (curtime-previous_millis_cmd) > DEFAULT_MAX_HOT_TIME*1000 ) + if(DEFAULT_MAX_HOT_TIME && (degHotend0()>HOTTEMP) ) + { + LCD_MESSAGEPGM("Hot too long."); + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("Hot too long"); + disable_heater(); + } if(stepper_inactive_time) - if( (millis()-last_stepperdisabled_time) > stepper_inactive_time ) + if( (curtime-last_stepperdisabled_time) > stepper_inactive_time ) { if(previous_millis_cmd>last_stepperdisabled_time) last_stepperdisabled_time=previous_millis_cmd; @@ -1216,23 +1246,37 @@ void manage_inactivity(byte debug) } } #ifdef EXTRUDER_RUNOUT_PREVENT - if( (millis()-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) - if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) + if(!blocks_queued()) + if( (curtime-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) { - bool oldstatus=READ(E_ENABLE_PIN); - enable_e(); - 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(); - //enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); - st_synchronize(); - WRITE(E_ENABLE_PIN,oldstatus); + if(previous_millis_cmd>previous_millis_runoutprevent) + { + previous_millis_runoutprevent=previous_millis_cmd; + } + + if(degHotend0()>EXTRUDER_RUNOUT_MINTEMP) + if((curtime-previous_millis_runoutprevent) > EXTRUDER_RUNOUT_SECONDS*1000) + { + bool oldstatus=READ(E_ENABLE_PIN); + enable_e(); + 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); + + while(current_block!=NULL || blocks_queued()) + { + manage_heater(); + LCD_STATUS; + } + + previous_millis_runoutprevent=millis(); + WRITE(E_ENABLE_PIN,oldstatus); + } } #endif check_axes_activity(); @@ -1247,7 +1291,7 @@ void kill() disable_z(); disable_e(); - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); //Turn powersupply off SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Printer halted. kill() called !!"); LCD_MESSAGEPGM("KILLED. "); diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 51a9fe0719..e9c505d3f8 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -706,15 +706,21 @@ void st_init() sei(); } - +#include "util/delay.h" // Block until all buffered steps are executed void st_synchronize() { - while( blocks_queued()) { + while(current_block!=NULL || blocks_queued()) { manage_heater(); manage_inactivity(1); - LCD_STATUS; + LCD_STATUS; + //_delay_ms(100); + ; } +// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); +// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); +// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); +// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); } void st_set_position(const long &x, const long &y, const long &z, const long &e) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 785da6c926..4290313c5b 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -451,6 +451,11 @@ void setWatch() void disable_heater() { + for(int i=0;i -1 target_raw[0]=0; #if HEATER_0_PIN > -1 From f312216e972533e99b5ee34b01a319ad4de6e6d8 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 09:22:22 +0100 Subject: [PATCH 158/228] Revert "untestest commit, so I don't loose code.. features runout prevention addons" This reverts commit 651cde8b98b9499796e96cad9e267dcd6bbb86d4. --- Marlin/Configuration.h | 2 +- Marlin/Marlin.pde | 86 +++++++++++------------------------------- Marlin/stepper.cpp | 12 ++---- Marlin/temperature.cpp | 5 --- 4 files changed, 25 insertions(+), 80 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 16672d01be..dc8c799f5b 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -248,7 +248,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define SLOWDOWN //default stepper release if idle -#define DEFAULT_STEPPER_DEACTIVE_TIME 1200 +#define DEFAULT_STEPPER_DEACTIVE_TIME 60 #define DEFAULT_STEPPER_DEACTIVE_COMMAND "M84 X Y E" //z stays powered diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 0e62eea254..4d031ea788 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -176,10 +176,8 @@ const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 //Inactivity shutdown variables static unsigned long previous_millis_cmd = 0; -static unsigned long previous_millis_runoutprevent = 0; -//static unsigned long previous_millis_beep = 0; -static unsigned long max_inactive_time=0; -static unsigned long stepper_inactive_time = 0; +static unsigned long max_inactive_time = 0; +static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000; static unsigned long last_stepperdisabled_time=30*1000; //first release check after 30 seconds static unsigned long starttime=0; @@ -245,10 +243,6 @@ void setup() fromsd[i] = false; } - max_inactive_time = DEFAULT_MAX_INACTIVE_TIME*1000; - stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000; - - EEPROM_RetrieveSettings(); // loads data from EEPROM if available for(int8_t i=0; i < NUM_AXIS; i++) @@ -421,7 +415,6 @@ FORCE_INLINE void get_command() SERIAL_ECHO_START; SERIAL_ECHOLN(time); LCD_MESSAGE(time); - st_synchronize(); card.printingHasFinished(); card.checkautostart(true); @@ -1207,34 +1200,11 @@ void prepare_arc_move(char isclockwise) { void manage_inactivity(byte debug) { - unsigned long curtime=millis(); - SERIAL_ECHO_START; - SERIAL_ECHO("MS"); - SERIAL_ECHO(millis()); - SERIAL_ECHO(" PREV_CMD"); - SERIAL_ECHO(previous_millis_cmd); - SERIAL_ECHO(" maxinactive"); - SERIAL_ECHOLN(max_inactive_time ); - - if( (curtime-previous_millis_cmd) > max_inactive_time ) + if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) - { - LCD_MESSAGEPGM("Bored Shutdown."); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Bored Shutdown."); kill(); - } - - if( (curtime-previous_millis_cmd) > DEFAULT_MAX_HOT_TIME*1000 ) - if(DEFAULT_MAX_HOT_TIME && (degHotend0()>HOTTEMP) ) - { - LCD_MESSAGEPGM("Hot too long."); - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("Hot too long"); - disable_heater(); - } if(stepper_inactive_time) - if( (curtime-last_stepperdisabled_time) > stepper_inactive_time ) + if( (millis()-last_stepperdisabled_time) > stepper_inactive_time ) { if(previous_millis_cmd>last_stepperdisabled_time) last_stepperdisabled_time=previous_millis_cmd; @@ -1246,37 +1216,23 @@ void manage_inactivity(byte debug) } } #ifdef EXTRUDER_RUNOUT_PREVENT - if(!blocks_queued()) - if( (curtime-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) + if( (millis()-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) + if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) { - if(previous_millis_cmd>previous_millis_runoutprevent) - { - previous_millis_runoutprevent=previous_millis_cmd; - } - - if(degHotend0()>EXTRUDER_RUNOUT_MINTEMP) - if((curtime-previous_millis_runoutprevent) > EXTRUDER_RUNOUT_SECONDS*1000) - { - bool oldstatus=READ(E_ENABLE_PIN); - enable_e(); - 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); - - while(current_block!=NULL || blocks_queued()) - { - manage_heater(); - LCD_STATUS; - } - - previous_millis_runoutprevent=millis(); - WRITE(E_ENABLE_PIN,oldstatus); - } + bool oldstatus=READ(E_ENABLE_PIN); + enable_e(); + 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(); + //enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); + st_synchronize(); + WRITE(E_ENABLE_PIN,oldstatus); } #endif check_axes_activity(); @@ -1291,7 +1247,7 @@ void kill() disable_z(); disable_e(); - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); //Turn powersupply off + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Printer halted. kill() called !!"); LCD_MESSAGEPGM("KILLED. "); diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index e9c505d3f8..51a9fe0719 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -706,21 +706,15 @@ void st_init() sei(); } -#include "util/delay.h" + // Block until all buffered steps are executed void st_synchronize() { - while(current_block!=NULL || blocks_queued()) { + while( blocks_queued()) { manage_heater(); manage_inactivity(1); - LCD_STATUS; - //_delay_ms(100); - ; + LCD_STATUS; } -// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); -// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); -// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); -// _delay_ms(250);_delay_ms(250);_delay_ms(250);_delay_ms(250); } void st_set_position(const long &x, const long &y, const long &z, const long &e) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 4290313c5b..785da6c926 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -451,11 +451,6 @@ void setWatch() void disable_heater() { - for(int i=0;i -1 target_raw[0]=0; #if HEATER_0_PIN > -1 From 415aadf704ff545de2db90ffaf2fc351af78331a Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 11:45:52 +0100 Subject: [PATCH 159/228] lcd panel bed support advance and ultipanel not any more in default config --- Marlin/Configuration.h | 9 +++- Marlin/cardreader.pde | 1 + Marlin/pins.h | 4 +- Marlin/temperature.cpp | 48 +++++++++++++++++----- Marlin/temperature.h | 30 +++++++++++--- Marlin/ultralcd.pde | 93 +++++++++++++++++++++++++++++++++++++++--- 6 files changed, 159 insertions(+), 26 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 58f5bcaeaf..3215a09c97 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -58,6 +58,10 @@ // Select one of these only to define how the bed temp is read. //#define THERMISTORBED 1 //#define BED_USES_THERMISTOR +//#define BED_LIMIT_SWITCHING +#ifdef BED_LIMIT_SWITCHING + #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS +#endif //#define BED_USES_AD595 #define BED_CHECK_INTERVAL 5000 //ms @@ -167,6 +171,7 @@ #define EXTRUDER_RUNOUT_SECONDS 30. #define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament #define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed +#define EXTRUDER_RUNOUT_EXTRUDE 100 //=========================================================================== @@ -296,7 +301,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // hooke's law says: force = k * distance // bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant // so: v ^ 2 is proportional to number of steps we advance the extruder -#define ADVANCE +//#define ADVANCE #ifdef ADVANCE #define EXTRUDER_ADVANCE_K .0 @@ -315,7 +320,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? #define SD_FINISHED_RELEASECOMMAND "M84 X Y E" // no z because of layer shift. -#define ULTIPANEL +//#define ULTIPANEL #ifdef ULTIPANEL //#define NEWPANEL //enable this if you have a click-encoder panel #define SDSUPPORT diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 0c346e1ead..a5044f8d33 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -432,6 +432,7 @@ void CardReader::updir() void CardReader::printingHasFinished() { + st_synchronize(); quickStop(); sdprinting = false; stop_heating_wait=true; diff --git a/Marlin/pins.h b/Marlin/pins.h index 4ec22793ec..6451d74250 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -555,7 +555,7 @@ #define Z_ENABLE_PIN 35 #define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 11 +#define TEMP_BED_PIN 10 #define HEATER_0_PIN 2 #define TEMP_0_PIN 8 @@ -734,4 +734,4 @@ HEATER_BED_PIN, FAN_PIN, \ _E0_PINS, _E1_PINS, _E2_PINS, \ TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } -#endif +#endif diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index ba116c7aa3..e6c352fdff 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -42,6 +42,10 @@ //=========================================================================== int target_raw[EXTRUDERS] = { 0 }; int target_raw_bed = 0; +#ifdef BED_LIMIT_SWITCHING +int target_bed_low_temp =0; +int target_bed_high_temp =0; +#endif int current_raw[EXTRUDERS] = { 0 }; int current_raw_bed = 0; @@ -233,20 +237,39 @@ void manage_heater() previous_millis_bed_heater = millis(); #if TEMP_BED_PIN > -1 - // Check if temperature is within the correct range - if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) { - if(current_raw_bed >= target_raw_bed) - { + + #ifndef BED_LIMIT_SWITCHING + // Check if temperature is within the correct range + if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) { + if(current_raw_bed >= target_raw_bed) + { + WRITE(HEATER_BED_PIN,LOW); + } + else + { + WRITE(HEATER_BED_PIN,HIGH); + } + } + else { WRITE(HEATER_BED_PIN,LOW); } - else - { - WRITE(HEATER_BED_PIN,HIGH); + #else //#ifdef BED_LIMIT_SWITCHING + // Check if temperature is within the correct band + if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) { + if(current_raw_bed > target_bed_high_temp) + { + WRITE(HEATER_BED_PIN,LOW); + } + else + if(current_raw_bed <= target_bed_low_temp) + { + WRITE(HEATER_BED_PIN,HIGH); + } } - } - else { - WRITE(HEATER_BED_PIN,LOW); - } + else { + WRITE(HEATER_BED_PIN,LOW); + } + #endif #endif } @@ -520,6 +543,9 @@ void setWatch() void disable_heater() { + for(int i=0;i -1 target_raw[0]=0; soft_pwm[0]=0; diff --git a/Marlin/temperature.h b/Marlin/temperature.h index f8b09649f5..8e1deac8fe 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -43,6 +43,10 @@ extern int heatingtarget_raw[EXTRUDERS]; extern int current_raw[EXTRUDERS]; extern int target_raw_bed; extern int current_raw_bed; +#ifdef BED_LIMIT_SWITCHING + extern int target_bed_low_temp ; + extern int target_bed_high_temp ; +#endif extern float Kp,Ki,Kd,Kc; #ifdef PIDTEMP @@ -83,7 +87,20 @@ FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) { }; FORCE_INLINE void setTargetBed(const float &celsius) { + target_raw_bed = temp2analogBed(celsius); + #ifdef BED_LIMIT_SWITCHING + if(celsius>BED_HYSTERESIS) + { + target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS); + target_bed_high_temp= temp2analogBed(celsius+BED_HYSTERESIS); + } + else + { + target_bed_low_temp=0; + target_bed_high_temp=0; + } + #endif }; FORCE_INLINE bool isHeatingHotend(uint8_t extruder){ @@ -125,6 +142,13 @@ FORCE_INLINE bool isCoolingBed() { #error Invalid number of extruders #endif + + +int getHeaterPower(int heater); +void disable_heater(); +void setWatch(); +void updatePID(); + FORCE_INLINE void autotempShutdown(){ #ifdef AUTOTEMP if(autotemp_enabled) @@ -135,11 +159,5 @@ FORCE_INLINE void autotempShutdown(){ } #endif } - -int getHeaterPower(int heater); -void disable_heater(); -void setWatch(); -void updatePID(); - #endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 3b7663beb9..947ec3dac9 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -165,8 +165,13 @@ void lcd_status() //previous_millis_buttons=millis(); long ms=millis(); for(int8_t i=0; i<8; i++) { + #ifndef NEWPANEL if((blocking[i]>ms)) buttons &= ~(1<ms)) + buttons &= ~(1< -1) +ItemT_bed, +#endif +ItemT_fan}; void MainMenu::showTune() { @@ -572,6 +581,42 @@ void MainMenu::showTune() lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); } }break; + #if (HEATER_BED_PIN > -1) + case ItemT_bed: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002Bed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetBed()))); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(degTargetBed()); + } + else + { + setTargetBed(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; + #endif + case ItemT_fan: { @@ -677,6 +722,9 @@ enum { ItemCT_autotempactive, ItemCT_autotempmin,ItemCT_autotempmax,ItemCT_autotempfact, #endif +#if (HEATER_BED_PIN > -1) +ItemCT_bed, +#endif ItemCT_fan, ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C }; @@ -857,6 +905,41 @@ void MainMenu::showControlTemp() }break; #endif //autotemp + #if (HEATER_BED_PIN > -1) + case ItemCT_bed: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" \002Bed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetBed()))); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(degTargetBed()); + } + else + { + setTargetBed(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + }break; + #endif case ItemCT_fan: { if(force_lcd_update) From 67350254285e98df1c07c5c4855444e6c7b2928c Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 12:02:33 +0100 Subject: [PATCH 160/228] cooldown --- Marlin/ultralcd.pde | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 947ec3dac9..35c0c4091a 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -446,7 +446,7 @@ void MainMenu::showStatus() force_lcd_update=false; } -enum {ItemP_exit, ItemP_autostart,ItemP_disstep,ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude}; +enum {ItemP_exit, ItemP_autostart,ItemP_disstep,ItemP_home, ItemP_origin, ItemP_preheat, ItemP_cooldown,ItemP_extrude}; //any action must not contain a ',' character anywhere, or this breaks: #define MENUITEM(repaint_action, click_action) \ @@ -480,7 +480,10 @@ void MainMenu::showPrepare() MENUITEM( lcdprintPGM(" Set Origin") , BLOCK;enquecommand("G92 X0 Y0 Z0");beepshort(); ) ; break; case ItemP_preheat: - MENUITEM( lcdprintPGM(" Preheat") , BLOCK;setTargetHotend0(170);beepshort(); ) ; + MENUITEM( lcdprintPGM(" Preheat") , BLOCK;setTargetHotend0(170);setTargetBed(70);beepshort(); ) ; + break; + case ItemP_cooldown: + MENUITEM( lcdprintPGM(" Cooldown") , BLOCK;setTargetHotend0(0);setTargetBed(0);beepshort(); ) ; break; case ItemP_extrude: MENUITEM( lcdprintPGM(" Extrude") , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ; From 212515148e70f151e24990312fd1fe6c1de6b104 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 12:11:39 +0100 Subject: [PATCH 161/228] added m240 photography support. default off --- Marlin/Configuration.h | 5 +++++ Marlin/Marlin.pde | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 3215a09c97..85fd389688 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -363,6 +363,11 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th const int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement + +// M240 Triggers a camera by emulating a Canon RC-1 Remote +// Data from: http://www.doc-diy.net/photo/rc-1_hacked/ +// #define PHOTOGRAPH_PIN 23 + //=========================================================================== //=============================Buffers ============================ //=========================================================================== diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 1dbfb8694c..c20ac49b62 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -41,6 +41,7 @@ #include "motion_control.h" #include "cardreader.h" #include "watchdog.h" +#include @@ -109,6 +110,7 @@ // M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk // M206 - set additional homeing offset // M220 - set speed factor override percentage S:factor in percent +// M240 - Trigger a camera to take a photograph // M301 - Set PID parameters P I and D // M302 - Allow cold extrudes // M400 - Finish all moves @@ -227,7 +229,15 @@ void enquecommand(const char *cmd) buflen += 1; } } - +void setup_photpin() +{ + #ifdef PHOTOGRAPH_PIN + #if (PHOTOGRAPH_PIN > -1) + SET_OUTPUT(PHOTOGRAPH_PIN); + WRITE(PHOTOGRAPH_PIN, LOW); + #endif + #endif +} void setup() { MSerial.begin(BAUDRATE); @@ -255,6 +265,7 @@ void setup() plan_init(); // Initialize planner; st_init(); // Initialize stepper; wd_init(); + setup_photpin(); } @@ -1064,6 +1075,8 @@ FORCE_INLINE void process_commands() } } break; + + #ifdef PIDTEMP case 301: // M301 @@ -1089,6 +1102,29 @@ FORCE_INLINE void process_commands() } 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: // finish all moves { From 3c1a4aac2bbe6f77b2e779520f848685c1c57cc1 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 12:38:50 +0100 Subject: [PATCH 162/228] header file simplification --- Marlin/EEPROMwrite.h | 1 - Marlin/Marlin.h | 8 +++++++- Marlin/Marlin.pde | 7 ++++--- Marlin/cardreader.pde | 3 +-- Marlin/motion_control.cpp | 1 - Marlin/planner.cpp | 7 +------ Marlin/planner.h | 3 +-- Marlin/stepper.cpp | 4 +--- Marlin/temperature.cpp | 5 +---- Marlin/temperature.h | 1 - Marlin/ultralcd.h | 5 ++--- Marlin/ultralcd.pde | 4 +--- Marlin/watchdog.h | 2 +- 13 files changed, 20 insertions(+), 31 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 8680a5fdc8..5714dacfe3 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -5,7 +5,6 @@ #include "planner.h" #include "temperature.h" -#include template int EEPROM_writeAnything(int &ee, const T& value) { diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index f8ded924e1..0773f11c1b 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -6,15 +6,21 @@ #define HardwareSerial_h // trick to disable the standard HWserial #include #include +#include +#include + + #if ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif +#include + #include "fastio.h" -#include #include "Configuration.h" +#include "pins.h" #include "MarlinSerial.h" #define FORCE_INLINE __attribute__((always_inline)) inline diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index c20ac49b62..bf9a1bc489 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -25,7 +25,8 @@ http://reprap.org/pipermail/reprap-dev/2011-May/003323.html */ -#include + +#include "Marlin.h" #include #include @@ -33,7 +34,7 @@ #include "fastio.h" #include "Configuration.h" #include "pins.h" -#include "Marlin.h" + #include "ultralcd.h" #include "planner.h" #include "stepper.h" @@ -41,7 +42,7 @@ #include "motion_control.h" #include "cardreader.h" #include "watchdog.h" -#include + diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index a5044f8d33..89f4b2f93f 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -1,8 +1,7 @@ #include "cardreader.h" -//#include #ifdef SDSUPPORT -#include "Configuration.h" +#include "Marlin.h" CardReader::CardReader() { diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index 8ecc1a0445..ab403e9812 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -19,7 +19,6 @@ along with Grbl. If not, see . */ -#include "Configuration.h" #include "Marlin.h" #include "stepper.h" #include "planner.h" diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 1d66dad03f..f3007af531 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -52,14 +52,9 @@ */ -//#include -//#include -//#include -#include "Configuration.h" -#include "pins.h" + #include "Marlin.h" -#include "fastio.h" #include "planner.h" #include "stepper.h" #include "temperature.h" diff --git a/Marlin/planner.h b/Marlin/planner.h index 82f53413ef..02e299fa8c 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -23,8 +23,7 @@ #ifndef planner_h #define planner_h -#include -#include "Configuration.h" + #include "Marlin.h" // This struct is used when buffering the setup for each linear movement "nominal" values are as specified in diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index cffa25f2ac..6985da00b4 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -23,11 +23,9 @@ #include "stepper.h" -#include "Configuration.h" -#include "pins.h" + #include "Marlin.h" #include "planner.h" -#include "fastio.h" #include "temperature.h" #include "ultralcd.h" diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index e6c352fdff..371c6e589b 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -27,11 +27,8 @@ http://reprap.org/pipermail/reprap-dev/2011-May/003323.html */ -#include -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" + #include "Marlin.h" #include "ultralcd.h" #include "temperature.h" diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 8e1deac8fe..80e68f78b4 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -22,7 +22,6 @@ #define temperature_h #include "Marlin.h" -#include "fastio.h" #include "planner.h" #ifdef PID_ADD_EXTRUSION_RATE #include "stepper.h" diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 93fa4895d7..716ddb90c5 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -1,9 +1,8 @@ #ifndef __ULTRALCDH #define __ULTRALCDH -#include "Configuration.h" #include "Marlin.h" #ifdef ULTRA_LCD - + #include void lcd_status(); void lcd_init(); void lcd_status(const char* message); @@ -15,7 +14,7 @@ #define STATUSTIMEOUT 15000 - #include + extern LiquidCrystal lcd; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 35c0c4091a..5be09ac4a6 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1,6 +1,6 @@ #include "ultralcd.h" #ifdef ULTRA_LCD - +#include //=========================================================================== //=============================imported variables============================ //=========================================================================== @@ -27,7 +27,6 @@ static char messagetext[LCD_WIDTH]=""; //return for string conversion routines static char conv[8]; -#include 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 static unsigned long previous_millis_lcd=0; @@ -42,7 +41,6 @@ static long previous_millis_buttons=0; static MainMenu menu; -#include void lcdProgMemprint(const char *str) { diff --git a/Marlin/watchdog.h b/Marlin/watchdog.h index 1d41488271..ff6af60afd 100644 --- a/Marlin/watchdog.h +++ b/Marlin/watchdog.h @@ -1,6 +1,6 @@ #ifndef __WATCHDOGH #define __WATCHDOGH -#include "Configuration.h" +#include "Marlin.h" #ifdef USE_WATCHDOG // intialise watch dog with a 1 sec interrupt time From 57f9359a4147157189cedf6e934dcd5571a79a88 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 14:55:45 +0100 Subject: [PATCH 163/228] simplified the includes, makefile now works with arduino23 --- Marlin/EEPROMwrite.h | 6 ++-- Marlin/Makefile | 21 +++++++++++--- Marlin/Marlin.h | 56 ++++++++++++++++++++++++++------------ Marlin/Marlin.pde | 10 ++----- Marlin/MarlinSerial.cpp | 17 ++---------- Marlin/MarlinSerial.h | 7 +---- Marlin/Sd2Card.cpp | 7 +---- Marlin/SdBaseFile.h | 9 +----- Marlin/SdFatUtil.cpp | 2 ++ Marlin/SdFatUtil.h | 9 +----- Marlin/SdFile.cpp | 1 + Marlin/SdFile.h | 1 + Marlin/cardreader.pde | 3 +- Marlin/planner.h | 7 +---- Marlin/speed_lookuptable.h | 2 +- Marlin/stepper.cpp | 3 +- Marlin/thermistortables.h | 2 +- Marlin/ultralcd.pde | 1 + Marlin/watchdog.pde | 3 +- 19 files changed, 81 insertions(+), 86 deletions(-) diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 5714dacfe3..bb25ae8960 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -4,6 +4,8 @@ #include "Marlin.h" #include "planner.h" #include "temperature.h" +//#include + template int EEPROM_writeAnything(int &ee, const T& value) @@ -11,7 +13,7 @@ template int EEPROM_writeAnything(int &ee, const T& value) const byte* p = (const byte*)(const void*)&value; int i; for (i = 0; i < (int)sizeof(value); i++) - EEPROM.write(ee++, *p++); + eeprom_write_byte((unsigned char *)ee++, *p++); return i; } @@ -20,7 +22,7 @@ template int EEPROM_readAnything(int &ee, T& value) byte* p = (byte*)(void*)&value; int i; for (i = 0; i < (int)sizeof(value); i++) - *p++ = EEPROM.read(ee++); + *p++ = eeprom_read_byte((unsigned char *)ee++); return i; } //====================================================================================== diff --git a/Marlin/Makefile b/Marlin/Makefile index 0504319f72..585530bca0 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -1,7 +1,7 @@ TARGET = $(notdir $(CURDIR)) # CHANGE BELOW: #~ INSTALL_DIR = /Applications/Arduino.app/Contents/Resources/Java -INSTALL_DIR = /home/bkubicek/software/arduino-0022 +INSTALL_DIR = /home/bkubicek/software/arduino-0023 #~ PORT = /dev/cu.usbserial* PORT = /dev/ttyACM0 @@ -60,13 +60,25 @@ OPT = 2 #~ CDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) #~ CXXDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) # now called DF_CPU -CDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=22 -CXXDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=22 +CDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=23 +CXXDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=23 # Place -I options here CINCS = -I$(ARDUINO) -I$(INSTALL_DIR)/libraries/LiquidCrystal/ -I$(INSTALL_DIR)/libraries/EEPROM/ CXXINCS = -I$(ARDUINO) +OBJECTS= applet/Marlin.cpp.o \ + applet/EEPROM.o \ + applet/pins_arduino.o \ + applet/wiring_analog.o \ + applet/wiring_pulse.o \ + applet/main.o \ + applet/Print.o \ + applet/wiring_digital.o \ + applet/wiring_shift.o \ + applet/stepper.o \ + applet/wiring.o \ + applet/WMath.o # Compiler flag to set the C Standard level. # c89 - "ANSI" C # gnu89 - c89 plus GCC extensions @@ -253,7 +265,8 @@ applet/$(TARGET).elf: $(TARGET).pde applet/$(TARGET).cpp.o applet/core.a # $(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) # changed as in IDE v0022: link cpp obj files @echo $$(tput bold)$$(tput setaf 2) $(CC) $$(tput sgr0) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) - @$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) + $(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ $OBJECTS -L. applet/core.a $(LDFLAGS) + #@$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/*.o applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) # added: cpp.o depends on cpp (and .pde which generates it) # $< "first item in the dependencies list"; $@ "left side of the :"; $^ "right side of the :" diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 0773f11c1b..2a237e0939 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -1,35 +1,55 @@ +// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. +// Licence: GPL + #ifndef __MARLINH #define __MARLINH -// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. -// Licence: GPL #define HardwareSerial_h // trick to disable the standard HWserial -#include -#include -#include -#include +#define FORCE_INLINE __attribute__((always_inline)) inline + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + + + + + + + +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" #if ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif -#include - -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" #include "MarlinSerial.h" -#define FORCE_INLINE __attribute__((always_inline)) inline -//#define SERIAL_ECHO(x) Serial << "echo: " << x; -//#define SERIAL_ECHOLN(x) Serial << "echo: "< -#include -#include "EEPROMwrite.h" -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" + #include "ultralcd.h" #include "planner.h" @@ -42,7 +36,7 @@ #include "motion_control.h" #include "cardreader.h" #include "watchdog.h" - +#include "EEPROMwrite.h" diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index 63268e8cfa..7175561e23 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -20,25 +20,14 @@ Modified 28 September 2010 by Mark Sproul */ - -#include -#include -#include -#include -#include -#if ARDUINO >= 100 - #include "Arduino.h" -#else - #include "wiring.h" -#endif -#include "wiring_private.h" +#include "Marlin.h" +#include "MarlinSerial.h" // this next line disables the entire HardwareSerial.cpp, // this is so I can support Attiny series and any other chip without a uart #if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) -#include "MarlinSerial.h" -#include "Marlin.h" + diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 0fe0c52274..71823de8f1 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -21,13 +21,8 @@ #ifndef MarlinSerial_h #define MarlinSerial_h -#include -#include -//#include -#include -#define FORCE_INLINE __attribute__((always_inline)) inline +#include "Marlin.h" -#include "WString.h" #define DEC 10 #define HEX 16 diff --git a/Marlin/Sd2Card.cpp b/Marlin/Sd2Card.cpp index d7f018e4b9..f421154ea0 100644 --- a/Marlin/Sd2Card.cpp +++ b/Marlin/Sd2Card.cpp @@ -17,12 +17,7 @@ * along with the Arduino Sd2Card Library. If not, see * . */ -#define HardwareSerial_h // trick to disable the standard HWserial -#if ARDUINO < 100 -#include -#else // ARDUINO -#include -#endif // ARDUINO +#include "Marlin.h" #include "Sd2Card.h" //------------------------------------------------------------------------------ #ifndef SOFTWARE_SPI diff --git a/Marlin/SdBaseFile.h b/Marlin/SdBaseFile.h index f5c5e4de3f..80402e56c3 100644 --- a/Marlin/SdBaseFile.h +++ b/Marlin/SdBaseFile.h @@ -23,14 +23,7 @@ * \file * \brief SdBaseFile class */ -#include -#define HardwareSerial_h // trick to disable the standard HWserial -#if ARDUINO < 100 -#include -#else // ARDUINO -#include -#endif // ARDUINO -#include "MarlinSerial.h" +#include "Marlin.h" #include "SdFatConfig.h" #include "SdVolume.h" //------------------------------------------------------------------------------ diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp index 0bf86f2956..559305f11e 100644 --- a/Marlin/SdFatUtil.cpp +++ b/Marlin/SdFatUtil.cpp @@ -17,7 +17,9 @@ * along with the Arduino SdFat Library. If not, see * . */ +#include "Marlin.h" #include "SdFatUtil.h" + //------------------------------------------------------------------------------ /** Amount of free RAM * \return The number of free bytes. diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index fc7a17e5bc..d843da04c5 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -23,14 +23,7 @@ * \file * \brief Useful utility functions. */ -#include - -#define HardwareSerial_h // trick to disable the standard HWserial -#if ARDUINO < 100 -#include -#else // ARDUINO -#include -#endif // ARDUINO +#include "Marlin.h" #include "MarlinSerial.h" /** Store and print a string in flash memory.*/ #define PgmPrint(x) SerialPrint_P(PSTR(x)) diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index 68f14b1933..5781d10b46 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -17,6 +17,7 @@ * along with the Arduino SdFat Library. If not, see * . */ +#include "Marlin.h" #include "SdFile.h" /** Create a file object and open it in the current working directory. * diff --git a/Marlin/SdFile.h b/Marlin/SdFile.h index 931486285b..2fd5755921 100644 --- a/Marlin/SdFile.h +++ b/Marlin/SdFile.h @@ -22,6 +22,7 @@ * \brief SdFile class */ #include "SdBaseFile.h" +#include "Marlin.h" #include #ifndef SdFile_h #define SdFile_h diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 89f4b2f93f..3d91224977 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -1,7 +1,8 @@ +#include "Marlin.h" #include "cardreader.h" #ifdef SDSUPPORT -#include "Marlin.h" + CardReader::CardReader() { diff --git a/Marlin/planner.h b/Marlin/planner.h index 02e299fa8c..ac9719fbcf 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -98,12 +98,7 @@ extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; #endif -/////semi-private stuff -#if ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif + extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed diff --git a/Marlin/speed_lookuptable.h b/Marlin/speed_lookuptable.h index 002f852f62..ab3a076f14 100644 --- a/Marlin/speed_lookuptable.h +++ b/Marlin/speed_lookuptable.h @@ -1,7 +1,7 @@ #ifndef SPEED_LOOKUPTABLE_H #define SPEED_LOOKUPTABLE_H -#include +#include "Marlin.h" uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ { 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 6985da00b4..076fbeea1c 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -22,9 +22,10 @@ and Philipp Tiefenbacher. */ -#include "stepper.h" + #include "Marlin.h" +#include "stepper.h" #include "planner.h" #include "temperature.h" #include "ultralcd.h" diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 30f5b62ac7..3071a6b5bb 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -1,7 +1,7 @@ #ifndef THERMISTORTABLES_H_ #define THERMISTORTABLES_H_ -#include +#include "Marlin.h" #define OVERSAMPLENR 16 diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 5be09ac4a6..bc1c9cc6c2 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1,5 +1,6 @@ #include "ultralcd.h" #ifdef ULTRA_LCD +#include "Marlin.h" #include //=========================================================================== //=============================imported variables============================ diff --git a/Marlin/watchdog.pde b/Marlin/watchdog.pde index 7af540c792..356e374738 100644 --- a/Marlin/watchdog.pde +++ b/Marlin/watchdog.pde @@ -1,7 +1,6 @@ #ifdef USE_WATCHDOG +#include "Marlin.h" #include "watchdog.h" -#include -#include //=========================================================================== //=============================private variables ============================ From 2bc160a97879d3b398a6b39bfb0c57c57346685c Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 14:57:28 +0100 Subject: [PATCH 164/228] add wiring.h, that can be used to overwrite: arduino-0023/hardware/arduino/cores/arduino/wiring.h this is necessary if the avr libraries are recent, but arduino is old. Alternative: newer arduino --- Marlin/wiring.h | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 Marlin/wiring.h diff --git a/Marlin/wiring.h b/Marlin/wiring.h new file mode 100644 index 0000000000..904d2ebd4b --- /dev/null +++ b/Marlin/wiring.h @@ -0,0 +1,141 @@ +/* + * fixed by this patch: + * http://code.google.com/p/arduino/issues/detail?id=604 + * */ +/* + wiring.h - Partial implementation of the Wiring API for the ATmega8. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id$ +*/ + +#ifndef Wiring_h +#define Wiring_h + +#include +#include +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 + +#define true 0x1 +#define false 0x0 + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define INTERNAL1V1 2 +#define INTERNAL2V56 3 +#else +#define INTERNAL 3 +#endif +#define DEFAULT 1 +#define EXTERNAL 0 + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#if __AVR_LIBC_VERSION__ < 10701UL +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#endif +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() sei() +#define noInterrupts() cli() + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) ) +#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L ) + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); +int analogRead(uint8_t); +void analogReference(uint8_t mode); +void analogWrite(uint8_t, int); + +unsigned long millis(void); +unsigned long micros(void); +void delay(unsigned long); +void delayMicroseconds(unsigned int us); +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +void loop(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif From 8463e39a4a13985ff135a68fd2a8724e801e8545 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 16:11:15 +0100 Subject: [PATCH 165/228] starting with sanguino arduino 1.0 compatibility --- Marlin/Marlin.h | 15 ++++++--------- Marlin/SdFile.cpp | 3 ++- Marlin/SdFile.h | 8 ++++---- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 2a237e0939..78739af246 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -21,19 +21,16 @@ #include - - - - - - - #include "fastio.h" #include "Configuration.h" #include "pins.h" -#if ARDUINO >= 100 - #include "Arduino.h" +#if ARDUINO >= 100 + #if defined(__AVR_ATmega644P__) + #include "WProgram.h" + #else + #include "Arduino.h" + #endif #else #include "WProgram.h" #endif diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index 5781d10b46..9c42c0074c 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -47,13 +47,14 @@ SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) { int16_t SdFile::write(const void* buf, uint16_t nbyte) { return SdBaseFile::write(buf, nbyte); } +#warning F_CPU //------------------------------------------------------------------------------ /** Write a byte to a file. Required by the Arduino Print class. * \param[in] b the byte to be written. * Use writeError to check for errors. */ #if ARDUINO >= 100 - size_t SdFile::write(uint8_t b) + size_t SdFile::write(uint8_t b) #else void SdFile::write(uint8_t b) #endif diff --git a/Marlin/SdFile.h b/Marlin/SdFile.h index 2fd5755921..a9efebc684 100644 --- a/Marlin/SdFile.h +++ b/Marlin/SdFile.h @@ -21,8 +21,8 @@ * \file * \brief SdFile class */ -#include "SdBaseFile.h" #include "Marlin.h" +#include "SdBaseFile.h" #include #ifndef SdFile_h #define SdFile_h @@ -36,10 +36,10 @@ class SdFile : public SdBaseFile, public Print { SdFile() {} SdFile(const char* name, uint8_t oflag); #if ARDUINO >= 100 - size_t write(uint8_t b); -#else + size_t write(uint8_t b); + #else void write(uint8_t b); -#endif + #endif int16_t write(const void* buf, uint16_t nbyte); void write(const char* str); From 11f2dafc4e65d5bfe169eabb3e4bb0927a23ba61 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Thu, 22 Dec 2011 16:43:28 +0100 Subject: [PATCH 166/228] one step closer to a functional makefile.. --- Marlin/Makefile | 46 +++++++++++++++++++++++++++++++-------------- Marlin/SdFile.cpp | 1 - Marlin/ultralcd.h | 8 ++++++++ Marlin/ultralcd.pde | 2 +- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/Marlin/Makefile b/Marlin/Makefile index 585530bca0..84e540568a 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -26,6 +26,31 @@ TERM=bash ############################################################################ # Below here nothing should be changed... +LINKORDER=\ +applet/Marlin.cpp.o \ +applet/EEPROM.o \ +applet/main.o \ +applet/MarlinSerial.o \ +applet/motion_control.o\ +applet/pins_arduino.o\ +applet/planner.o\ +applet/Print.o\ +applet/Sd2Card.o\ +applet/SdBaseFile.o\ +applet/SdFatUtil.o\ +applet/SdFile.o\ +applet/SdVolume.o\ +applet/stepper.o\ +applet/temperature.o\ +applet/WInterrupts.o\ +applet/wiring_analog.o\ +applet/wiring_digital.o\ +applet/wiring.o\ +applet/wiring_pulse.o\ +applet/wiring_shift.o\ +applet/WMath.o + +PDES=Marlin.pde ultralcd.pde watchdog.pde cardreader.pde ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino # #~ AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin @@ -67,18 +92,6 @@ CXXDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=23 CINCS = -I$(ARDUINO) -I$(INSTALL_DIR)/libraries/LiquidCrystal/ -I$(INSTALL_DIR)/libraries/EEPROM/ CXXINCS = -I$(ARDUINO) -OBJECTS= applet/Marlin.cpp.o \ - applet/EEPROM.o \ - applet/pins_arduino.o \ - applet/wiring_analog.o \ - applet/wiring_pulse.o \ - applet/main.o \ - applet/Print.o \ - applet/wiring_digital.o \ - applet/wiring_shift.o \ - applet/stepper.o \ - applet/wiring.o \ - applet/WMath.o # Compiler flag to set the C Standard level. # c89 - "ANSI" C # gnu89 - c89 plus GCC extensions @@ -141,6 +154,7 @@ MV = mv -f # and then, match to corresponding rule somehow? # or leave this - and parse in rule (auth automatic variable $(@F))? # "Suffix Replacement" +CXXSRC+=MarlinSerial.cpp SdBaseFile.cpp stepper.cpp motion_control.cpp SdFatUtil.cpp temperature.cpp planner.cpp SdFile.cpp Sd2Card.cpp SdVolume.cpp OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) # added - OBJ list, transformed into applet/ @@ -204,7 +218,9 @@ applet_files: $(TARGET).pde @echo ALL CXXLIBOBJ: $(CXXLIBOBJ) # echo '#include "WProgram.h"' > applet/$(TARGET).cpp @echo "#include \"WProgram.h\"\nvoid setup();\nvoid loop();\n" > applet/$(TARGET).cpp - cat $(TARGET).pde >> applet/$(TARGET).cpp + ##cat $(TARGET).pde >> applet/$(TARGET).cpp + cat ${PDES}>> applet/$(TARGET).cpp + cp *.cpp applet/ # no more need to cat main.cpp (v0022) - now it is compiled in # cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp @@ -265,7 +281,9 @@ applet/$(TARGET).elf: $(TARGET).pde applet/$(TARGET).cpp.o applet/core.a # $(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) # changed as in IDE v0022: link cpp obj files @echo $$(tput bold)$$(tput setaf 2) $(CC) $$(tput sgr0) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) - $(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ $OBJECTS -L. applet/core.a $(LDFLAGS) + echo ${OBJT} + #$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o -L. applet/core.a $(LDFLAGS) + $(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ ${LINKORDER} $(LDFLAGS) #@$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/*.o applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) # added: cpp.o depends on cpp (and .pde which generates it) diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index 9c42c0074c..eda85b3ea2 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -47,7 +47,6 @@ SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) { int16_t SdFile::write(const void* buf, uint16_t nbyte) { return SdBaseFile::write(buf, nbyte); } -#warning F_CPU //------------------------------------------------------------------------------ /** Write a byte to a file. Required by the Arduino Print class. * \param[in] b the byte to be written. diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 716ddb90c5..08ac950d38 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -151,5 +151,13 @@ void lcd_statuspgm(const char* message); +char *ftostr3(const float &x); +char *itostr2(const uint8_t &x); +char *ftostr31(const float &x); +char *ftostr32(const float &x); +char *itostr31(const int &xx); +char *itostr3(const int &xx); +char *itostr4(const int &xx); +char *ftostr51(const float &x); #endif //ULTRALCD diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index bc1c9cc6c2..ef86d8f32c 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -31,7 +31,7 @@ static char conv[8]; 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 static unsigned long previous_millis_lcd=0; -static long previous_millis_buttons=0; +//static long previous_millis_buttons=0; #ifdef NEWPANEL From 396270a0de36f1ab6b0a61a7c4a63b933a0ead83 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 26 Dec 2011 09:20:21 +0100 Subject: [PATCH 167/228] fix duplicated definition of MOSI MISO pins in case motherboard==33 --- Marlin/Sd2PinMap.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Marlin/Sd2PinMap.h b/Marlin/Sd2PinMap.h index 847f9f33bb..77a74987c0 100644 --- a/Marlin/Sd2PinMap.h +++ b/Marlin/Sd2PinMap.h @@ -38,6 +38,8 @@ struct pin_map_t { uint8_t const SDA_PIN = 20; // D1 uint8_t const SCL_PIN = 21; // D0 +#undef MOSI_PIN +#undef MISO_PIN // SPI port uint8_t const SS_PIN = 53; // B0 uint8_t const MOSI_PIN = 51; // B2 From 729cde44755732067917988296b59dab1fe3e364 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 26 Dec 2011 09:20:33 +0100 Subject: [PATCH 168/228] fix autostart failure if in wrong directory --- Marlin/cardreader.h | 2 ++ Marlin/cardreader.pde | 9 +++++++++ Marlin/ultralcd.pde | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 70f0d2c1d9..67fe58a90a 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -31,6 +31,8 @@ public: void ls(); void chdir(const char * relpath); void updir(); + void setroot(); + FORCE_INLINE bool eof() { return sdpos>=filesize ;}; FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index 3d91224977..a1f23ce068 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -164,6 +164,15 @@ void CardReader::initsd() SERIAL_ECHOLNPGM("workDir open failed"); } } + +void CardReader::setroot() +{ + curDir=&root; + if(!workDir.openRoot(&volume)) + { + SERIAL_ECHOLNPGM("workDir open failed"); + } +} void CardReader::release() { sdprinting = false; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index ef86d8f32c..69be85959a 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -467,7 +467,7 @@ void MainMenu::showPrepare() MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemP_autostart: - MENUITEM( lcdprintPGM(" Autostart") , BLOCK;card.lastnr=0;card.checkautostart(true);beepshort(); ) ; + MENUITEM( lcdprintPGM(" Autostart") , BLOCK;card.lastnr=0;card.setroot();card.checkautostart(true);beepshort(); ) ; break; case ItemP_disstep: MENUITEM( lcdprintPGM(" Disable Steppers") , BLOCK;enquecommand("M84");beepshort(); ) ; From 3814bbb529e47d0f7388618c1e5bcb114135e09d Mon Sep 17 00:00:00 2001 From: Bernhard Date: Mon, 26 Dec 2011 09:28:51 +0100 Subject: [PATCH 169/228] made sd code only compile with SDSUPPORT defined. safes 10k of codespace --- Marlin/Sd2Card.cpp | 5 +++++ Marlin/Sd2Card.h | 7 +++++++ Marlin/Sd2PinMap.h | 6 ++++++ Marlin/SdBaseFile.cpp | 7 +++++++ Marlin/SdBaseFile.h | 4 ++++ Marlin/SdFatConfig.h | 6 ++++++ Marlin/SdFatStructs.h | 6 ++++++ Marlin/SdFatUtil.cpp | 3 +++ Marlin/SdFatUtil.h | 6 ++++++ Marlin/SdFile.cpp | 5 +++++ Marlin/SdFile.h | 5 +++++ Marlin/SdInfo.h | 5 +++++ Marlin/SdVolume.cpp | 4 ++++ Marlin/SdVolume.h | 3 +++ 14 files changed, 72 insertions(+) diff --git a/Marlin/Sd2Card.cpp b/Marlin/Sd2Card.cpp index f421154ea0..884fa45533 100644 --- a/Marlin/Sd2Card.cpp +++ b/Marlin/Sd2Card.cpp @@ -18,6 +18,8 @@ * . */ #include "Marlin.h" + +#ifdef SDSUPPORT #include "Sd2Card.h" //------------------------------------------------------------------------------ #ifndef SOFTWARE_SPI @@ -636,3 +638,6 @@ bool Sd2Card::writeStop() { chipSelectHigh(); return false; } + + +#endif \ No newline at end of file diff --git a/Marlin/Sd2Card.h b/Marlin/Sd2Card.h index 0e8b6665e9..7de5f11bcc 100644 --- a/Marlin/Sd2Card.h +++ b/Marlin/Sd2Card.h @@ -17,6 +17,10 @@ * along with the Arduino Sd2Card Library. If not, see * . */ + +#include "Marlin.h" +#ifdef SDSUPPORT + #ifndef Sd2Card_h #define Sd2Card_h /** @@ -232,3 +236,6 @@ class Sd2Card { bool writeData(uint8_t token, const uint8_t* src); }; #endif // Sd2Card_h + + +#endif \ No newline at end of file diff --git a/Marlin/Sd2PinMap.h b/Marlin/Sd2PinMap.h index 77a74987c0..a40729df2d 100644 --- a/Marlin/Sd2PinMap.h +++ b/Marlin/Sd2PinMap.h @@ -18,6 +18,9 @@ * . */ // Warning this file was generated by a program. +#include "Marlin.h" +#ifdef SDSUPPORT + #ifndef Sd2PinMap_h #define Sd2PinMap_h #include @@ -360,3 +363,6 @@ static inline __attribute__((always_inline)) } } #endif // Sd2PinMap_h + + +#endif \ No newline at end of file diff --git a/Marlin/SdBaseFile.cpp b/Marlin/SdBaseFile.cpp index d33b1e038b..f8dc83adeb 100644 --- a/Marlin/SdBaseFile.cpp +++ b/Marlin/SdBaseFile.cpp @@ -19,6 +19,10 @@ */ #define SERIAL MSerial + +#include "Marlin.h" +#ifdef SDSUPPORT + #include "SdBaseFile.h" //------------------------------------------------------------------------------ // pointer to cwd directory @@ -1784,3 +1788,6 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) { #if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN) void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT #endif // ALLOW_DEPRECATED_FUNCTIONS + + +#endif \ No newline at end of file diff --git a/Marlin/SdBaseFile.h b/Marlin/SdBaseFile.h index 80402e56c3..1bf75f6f24 100644 --- a/Marlin/SdBaseFile.h +++ b/Marlin/SdBaseFile.h @@ -17,6 +17,9 @@ * along with the Arduino SdFat Library. If not, see * . */ +#include "Marlin.h" +#ifdef SDSUPPORT + #ifndef SdBaseFile_h #define SdBaseFile_h /** @@ -477,3 +480,4 @@ class SdBaseFile { }; #endif // SdBaseFile_h +#endif \ No newline at end of file diff --git a/Marlin/SdFatConfig.h b/Marlin/SdFatConfig.h index 036bdb9c62..2a78c2a857 100644 --- a/Marlin/SdFatConfig.h +++ b/Marlin/SdFatConfig.h @@ -21,6 +21,9 @@ * \file * \brief configuration definitions */ +#include "Marlin.h" +#ifdef SDSUPPORT + #ifndef SdFatConfig_h #define SdFatConfig_h #include @@ -106,3 +109,6 @@ uint8_t const SOFT_SPI_SCK_PIN = 13; */ #define USE_CXA_PURE_VIRTUAL 1 #endif // SdFatConfig_h + + +#endif \ No newline at end of file diff --git a/Marlin/SdFatStructs.h b/Marlin/SdFatStructs.h index 4ea82b766c..7ad88d67fc 100644 --- a/Marlin/SdFatStructs.h +++ b/Marlin/SdFatStructs.h @@ -17,6 +17,9 @@ * along with the Arduino SdFat Library. If not, see * . */ +#include "Marlin.h" +#ifdef SDSUPPORT + #ifndef SdFatStructs_h #define SdFatStructs_h /** @@ -602,3 +605,6 @@ static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; } #endif // SdFatStructs_h + + +#endif \ No newline at end of file diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp index 559305f11e..ffbcba0c69 100644 --- a/Marlin/SdFatUtil.cpp +++ b/Marlin/SdFatUtil.cpp @@ -18,6 +18,8 @@ * . */ #include "Marlin.h" + +#ifdef SDSUPPORT #include "SdFatUtil.h" //------------------------------------------------------------------------------ @@ -74,3 +76,4 @@ void SdFatUtil::SerialPrint_P(PGM_P str) { void SdFatUtil::SerialPrintln_P(PGM_P str) { println_P( str); } +#endif diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index d843da04c5..7f1809422b 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -17,6 +17,9 @@ * along with the Arduino SdFat Library. If not, see * . */ +#include "Marlin.h" +#ifdef SDSUPPORT + #ifndef SdFatUtil_h #define SdFatUtil_h /** @@ -40,3 +43,6 @@ namespace SdFatUtil { using namespace SdFatUtil; // NOLINT #endif // #define SdFatUtil_h + + +#endif \ No newline at end of file diff --git a/Marlin/SdFile.cpp b/Marlin/SdFile.cpp index eda85b3ea2..e9439e3b50 100644 --- a/Marlin/SdFile.cpp +++ b/Marlin/SdFile.cpp @@ -18,6 +18,8 @@ * . */ #include "Marlin.h" + +#ifdef SDSUPPORT #include "SdFile.h" /** Create a file object and open it in the current working directory. * @@ -85,3 +87,6 @@ void SdFile::writeln_P(PGM_P str) { write_P(str); write_P(PSTR("\r\n")); } + + +#endif \ No newline at end of file diff --git a/Marlin/SdFile.h b/Marlin/SdFile.h index a9efebc684..cbf1bbdbd9 100644 --- a/Marlin/SdFile.h +++ b/Marlin/SdFile.h @@ -22,6 +22,8 @@ * \brief SdFile class */ #include "Marlin.h" + +#ifdef SDSUPPORT #include "SdBaseFile.h" #include #ifndef SdFile_h @@ -47,3 +49,6 @@ class SdFile : public SdBaseFile, public Print { void writeln_P(PGM_P str); }; #endif // SdFile_h + + +#endif \ No newline at end of file diff --git a/Marlin/SdInfo.h b/Marlin/SdInfo.h index 2a58eb7db4..03ece10224 100644 --- a/Marlin/SdInfo.h +++ b/Marlin/SdInfo.h @@ -17,6 +17,9 @@ * along with the Arduino Sd2Card Library. If not, see * . */ +#include "Marlin.h" +#ifdef SDSUPPORT + #ifndef SdInfo_h #define SdInfo_h #include @@ -273,3 +276,5 @@ union csd_t { csd2_t v2; }; #endif // SdInfo_h + +#endif \ No newline at end of file diff --git a/Marlin/SdVolume.cpp b/Marlin/SdVolume.cpp index a14bb627ed..f14d7bc70b 100644 --- a/Marlin/SdVolume.cpp +++ b/Marlin/SdVolume.cpp @@ -17,6 +17,9 @@ * along with the Arduino SdFat Library. If not, see * . */ +#include "Marlin.h" +#ifdef SDSUPPORT + #include "SdVolume.h" //------------------------------------------------------------------------------ #if !USE_MULTIPLE_CARDS @@ -399,3 +402,4 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) { fail: return false; } +#endif \ No newline at end of file diff --git a/Marlin/SdVolume.h b/Marlin/SdVolume.h index 0f2e55ab2a..2ff2b6eb96 100644 --- a/Marlin/SdVolume.h +++ b/Marlin/SdVolume.h @@ -17,6 +17,8 @@ * along with the Arduino SdFat Library. If not, see * . */ +#include "Marlin.h" +#ifdef SDSUPPORT #ifndef SdVolume_h #define SdVolume_h /** @@ -209,3 +211,4 @@ class SdVolume { #endif // ALLOW_DEPRECATED_FUNCTIONS }; #endif // SdVolume +#endif \ No newline at end of file From cee5f9020ace7da75895c088a2f9bab3eb2f3a1e Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 15 Jan 2012 17:06:10 +0100 Subject: [PATCH 170/228] added suicide pin for a power supply to the arduino that is only active if the arduino is holding high for an output. --- Marlin/Marlin.pde | 38 ++++++++++++++++++++++++++++++++++---- Marlin/pins.h | 1 + 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index b650909ad1..cabaee13df 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -161,7 +161,7 @@ static bool fromsd[BUFSIZE]; static int bufindr = 0; static int bufindw = 0; static int buflen = 0; -static int i = 0; +//static int i = 0; static char serial_char; static int serial_count = 0; static boolean comment_mode = false; @@ -233,8 +233,30 @@ void setup_photpin() #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_powerhold(); MSerial.begin(BAUDRATE); SERIAL_ECHO_START; SERIAL_ECHOLNPGM(VERSION_STRING); @@ -912,10 +934,17 @@ FORCE_INLINE void process_commands() case 80: // M80 - ATX Power On SET_OUTPUT(PS_ON_PIN); //GND break; + #endif + case 81: // M81 - ATX Power Off - SET_INPUT(PS_ON_PIN); //Floating - break; - #endif + #if (SUICIDE_PIN >-1) + suicide(); + #else + #if (PS_ON_PIN > -1) + SET_INPUT(PS_ON_PIN); //Floating + #endif + #endif + case 82: axis_relative_modes[3] = false; break; @@ -1314,6 +1343,7 @@ void kill() SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Printer halted. kill() called !!"); LCD_MESSAGEPGM("KILLED. "); + suicide(); while(1); // Wait for reset } diff --git a/Marlin/pins.h b/Marlin/pins.h index 6451d74250..28e349161a 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -582,6 +582,7 @@ #define FAN_PIN 7 #define PS_ON_PIN 12 #define KILL_PIN -1 +#define SUICIDE_PIN 54 //PIN that has to be turned on right after start, to keep power flowing. #ifdef ULTRA_LCD From 7aeb45303df1373119a78836621d04f1b1d475e0 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 15 Jan 2012 18:31:21 +0100 Subject: [PATCH 171/228] small mistake --- Marlin/Marlin.pde | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index cabaee13df..23b3acef7e 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -937,7 +937,9 @@ FORCE_INLINE void process_commands() #endif case 81: // M81 - ATX Power Off + #if (SUICIDE_PIN >-1) + st_synchronize(); suicide(); #else #if (PS_ON_PIN > -1) From 157aa7f2fd47d03497a0ca5ec46e6f07ce4cb343 Mon Sep 17 00:00:00 2001 From: Bernhard Date: Sun, 15 Jan 2012 20:51:49 +0100 Subject: [PATCH 172/228] m115 eol fix --- Marlin/Marlin.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 23b3acef7e..824a57d780 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -997,7 +997,7 @@ FORCE_INLINE void process_commands() } break; case 115: // M115 - SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); + SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n"); break; case 117: // M117 display message LCD_MESSAGE(cmdbuffer[bufindr]+5); From 6cc6029d7af47a2a6103742d8af1264af8631226 Mon Sep 17 00:00:00 2001 From: haxar Date: Sun, 22 Jan 2012 03:25:56 -0800 Subject: [PATCH 173/228] M109 EOL fix when TEMP_RESIDENCY_TIME is undefined; printer interface (pronterface) could not see target extruder heater temperature to continue print --- Marlin/Marlin.pde | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 824a57d780..bbef8170d7 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -864,6 +864,8 @@ FORCE_INLINE void process_commands() { SERIAL_PROTOCOLLN( "?" ); } + #else + SERIAL_PROTOCOLLN(""); #endif codenum = millis(); } From 8d0916af1360115d0a86090d1b24a28a1ffef5bd Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 13:18:54 +1100 Subject: [PATCH 174/228] allow Marlin to actually compile with Makefile pulled from Sprinter and a few other modifications --- Marlin/Makefile | 384 ++++++++-------------- Marlin/Marlin.h | 4 +- Marlin/Marlin.pde | 6 +- Marlin/{cardreader.pde => cardreader.cpp} | 0 Marlin/temperature.cpp | 10 +- 5 files changed, 151 insertions(+), 253 deletions(-) rename Marlin/{cardreader.pde => cardreader.cpp} (100%) diff --git a/Marlin/Makefile b/Marlin/Makefile index 84e540568a..1e847a37b8 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -1,76 +1,65 @@ +# Sprinter Arduino Project Makefile +# +# Makefile Based on: +# Arduino 0011 Makefile +# Arduino adaptation by mellis, eighthave, oli.keller +# +# This has been tested with Arduino 0022. +# +# This makefile allows you to build sketches from the command line +# without the Arduino environment (or Java). +# +# Detailed instructions for using the makefile: +# +# 1. Modify the line containg "INSTALL_DIR" to point to the directory that +# contains the Arduino installation (for example, under Mac OS X, this +# might be /Applications/arduino-0012). +# +# 2. Modify the line containing "PORT" to refer to the filename +# representing the USB or serial connection to your Arduino board +# (e.g. PORT = /dev/tty.USB0). If the exact name of this file +# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.usb*). +# +# 3. Set the line containing "MCU" to match your board's processor. +# Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth +# or Diecimila have the atmega168. If you're using a LilyPad Arduino, +# change F_CPU to 8000000. +# +# 4. Type "make" and press enter to compile/verify your program. +# +# 5. Type "make upload", reset your Arduino board, and press enter to +# upload your program to the Arduino board. +# +# $Id$ + TARGET = $(notdir $(CURDIR)) -# CHANGE BELOW: -#~ INSTALL_DIR = /Applications/Arduino.app/Contents/Resources/Java -INSTALL_DIR = /home/bkubicek/software/arduino-0023 -#~ PORT = /dev/cu.usbserial* -PORT = /dev/ttyACM0 +INSTALL_DIR = ../../arduino-0022/ +UPLOAD_RATE = 115200 +AVRDUDE_PROGRAMMER = arduino +# PORT = /dev/arduino_A900G2I3 +PORT = /dev/arduino +MCU = atmega1280 +#For "old" Arduino Mega +#MCU = atmega1280 +#For Sanguinololu +#MCU = atmega644p +F_CPU = 16000000 -# Get these values from: -# $(INSTALL_DIR)/hardware/boards.txt -# (arduino-0022/hardware/arduino/boards.txt) -# The values below are for the "Arduino Duemilanove or Nano w/ ATmega328" -# now for "Arduino Mega 2560" -UPLOAD_SPEED = 115200 -UPLOAD_PROTOCOL = stk500v2 -BUILD_MCU = atmega2560 -BUILD_F_CPU = 16000000L -TERM=bash - -# getting undefined reference to `__cxa_pure_virtual' -#~ [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254180518 Arduino Forum - Makefile] -#~ http://www.arduino.cc/playground/OpenBSD/CLI -#~ [http://arduino.cc/forum/index.php?topic=52041.0 A "simple" makefile for Arduino] -#~ [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1275488191 Arduino Forum - Configuring avr-gcc options in arduino IDE] -# found in /usr/lib/gcc/avr/4.3.5/cc1plus; fixed with -Wl,--gc-section ############################################################################ # Below here nothing should be changed... -LINKORDER=\ -applet/Marlin.cpp.o \ -applet/EEPROM.o \ -applet/main.o \ -applet/MarlinSerial.o \ -applet/motion_control.o\ -applet/pins_arduino.o\ -applet/planner.o\ -applet/Print.o\ -applet/Sd2Card.o\ -applet/SdBaseFile.o\ -applet/SdFatUtil.o\ -applet/SdFile.o\ -applet/SdVolume.o\ -applet/stepper.o\ -applet/temperature.o\ -applet/WInterrupts.o\ -applet/wiring_analog.o\ -applet/wiring_digital.o\ -applet/wiring.o\ -applet/wiring_pulse.o\ -applet/wiring_shift.o\ -applet/WMath.o - -PDES=Marlin.pde ultralcd.pde watchdog.pde cardreader.pde ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino -# -#~ AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin -# in Ubuntu, avr-gcc is installed separate; -# only avrdude comes with the IDE -AVR_TOOLS_PATH = /usr/bin -AVR_DUDE_PATH = $(INSTALL_DIR)/hardware/tools -# -SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ - $(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ - $(ARDUINO)/wiring_pulse.c \ - $(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c -# added applet/$(TARGET).cpp as in IDE 0022 -CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp \ - $(ARDUINO)/Print.cpp \ - $(ARDUINO)/main.cpp -# applet/$(TARGET).cpp # no need, having a rule now for applet/$(TARGET).cpp.o -# added main.cpp, as in 0022 +AVR_TOOLS_PATH = +SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ +$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ +$(ARDUINO)/wiring_pulse.c \ +$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c +CXXSRC = $(ARDUINO)/WMath.cpp $(ARDUINO)/WString.cpp\ +$(ARDUINO)/Print.cpp Marlin.cpp MarlinSerial.cpp Sd2Card.cpp SdBaseFile.cpp SdFatUtil.cpp SdFile.cpp SdVolume.cpp motion_control.cpp planner.cpp stepper.cpp temperature.cpp cardreader.cpp FORMAT = ihex + # Name of this Makefile (used for "make depend"). MAKEFILE = Makefile @@ -79,192 +68,128 @@ MAKEFILE = Makefile # AVR (extended) COFF requires stabs, plus an avr-objcopy run. DEBUG = stabs -OPT = 2 +OPT = s # Place -D or -U options here -#~ CDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) -#~ CXXDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) -# now called DF_CPU -CDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=23 -CXXDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=23 +CDEFS = -DF_CPU=$(F_CPU) +CXXDEFS = -DF_CPU=$(F_CPU) # Place -I options here -CINCS = -I$(ARDUINO) -I$(INSTALL_DIR)/libraries/LiquidCrystal/ -I$(INSTALL_DIR)/libraries/EEPROM/ +CINCS = -I$(ARDUINO) CXXINCS = -I$(ARDUINO) # Compiler flag to set the C Standard level. -# c89 - "ANSI" C +# c89 - "ANSI" C # gnu89 - c89 plus GCC extensions -# c99 - ISO C99 standard (not yet fully implemented) +# c99 - ISO C99 standard (not yet fully implemented) # gnu99 - c99 plus GCC extensions -CSTANDARD = -std=gnu99 +#CSTANDARD = -std=gnu99 CDEBUG = -g$(DEBUG) -# note that typically, IDE 0022 uses -w to suppress warnings (both in cpp and c)! -CWARN = -Wall -#~ CWARN = -w -# "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++: -CCWARN = -Wstrict-prototypes -CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CWARN = -Wall -Wstrict-prototypes +CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -w -ffunction-sections -fdata-sections -DARDUINO=22 #CEXTRA = -Wa,-adhlns=$(<:.c=.lst) -# to eliminate pins_ardiuno warnings: -# http://arduino.cc/pipermail/developers_arduino.cc/2010-December/004005.html - -# [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254180518 Arduino Forum - Makefile] -#~ For building the objects files "-ffunction-sections -fdata-sections" was missing -#~ and the final avr-gcc call needs "-Wl,--gc-section". -CXSECTF = -fno-exceptions -ffunction-sections -fdata-sections -CFINALF = -Wl,--gc-section - -CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CCWARN) $(CSTANDARD) $(CEXTRA) -# added CWARN also to .cpp -CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CXSECTF) -#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs +CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) +CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) +#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs LDFLAGS = -lm + # Programming support using avrdude. Settings and variables. AVRDUDE_PORT = $(PORT) -AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex -AVRDUDE_FLAGS = -V -F \ - -p $(BUILD_MCU) -P $(AVRDUDE_PORT) -c $(UPLOAD_PROTOCOL) \ - -b $(UPLOAD_SPEED) -C $(INSTALL_DIR)/hardware/tools/avrdude.conf -# -b $(UPLOAD_SPEED) -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf +AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex:i +AVRDUDE_FLAGS = -D -C $(INSTALL_DIR)/hardware/tools/avrdude.conf \ +-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \ +-b $(UPLOAD_RATE) # Program settings -CC = $(AVR_TOOLS_PATH)/avr-gcc -CXX = $(AVR_TOOLS_PATH)/avr-g++ -OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy -OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump -AR = $(AVR_TOOLS_PATH)/avr-ar -SIZE = $(AVR_TOOLS_PATH)/avr-size -NM = $(AVR_TOOLS_PATH)/avr-nm -#~ AVRDUDE = $(AVR_TOOLS_PATH)/avrdude -AVRDUDE = $(AVR_DUDE_PATH)/avrdude +CC = $(AVR_TOOLS_PATH)avr-gcc +CXX = $(AVR_TOOLS_PATH)avr-g++ +OBJCOPY = $(AVR_TOOLS_PATH)avr-objcopy +OBJDUMP = $(AVR_TOOLS_PATH)avr-objdump +AR = $(AVR_TOOLS_PATH)avr-ar +SIZE = $(AVR_TOOLS_PATH)avr-size +NM = $(AVR_TOOLS_PATH)avr-nm +AVRDUDE = avrdude REMOVE = rm -f MV = mv -f # Define all object files. -# NOTE: obj files will be created in respective src directories (libraries or $(INSTALL_DIR)); -# make clean deletes them fine -# note that srcs are in libraries or other directories; -# $(CXXSRC:.cpp=.o) will cause obj files to be in same loc as src files -#~ OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) -# to change the output directory for object files; -# must change the obj list here! -# and then, match to corresponding rule somehow? -# or leave this - and parse in rule (auth automatic variable $(@F))? -# "Suffix Replacement" -CXXSRC+=MarlinSerial.cpp SdBaseFile.cpp stepper.cpp motion_control.cpp SdFatUtil.cpp temperature.cpp planner.cpp SdFile.cpp Sd2Card.cpp SdVolume.cpp -OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) - -# added - OBJ list, transformed into applet/ -OBJT = $(addprefix applet/,$(notdir $(OBJ))) -ALLSRC = $(SRC) $(CXXSRC) $(ASRC) +OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) # Define all listing files. LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst) # Combine all necessary flags and optional flags. # Add target processor to flags. -ALL_CFLAGS = -mmcu=$(BUILD_MCU) -I. $(CFLAGS) -ALL_CXXFLAGS = -mmcu=$(BUILD_MCU) -I. $(CXXFLAGS) -ALL_ASFLAGS = -mmcu=$(BUILD_MCU) -I. -x assembler-with-cpp $(ASFLAGS) +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) +ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) -# depended libraries of .pde need to be added from -# $(INSTALL_DIR)/libraries (TODO: and/or ~/sketchbook/libraries) -# grep for 'include', test if exists, add... -# note: prefix "a real tab character" http://www.delorie.com/djgpp/doc/ug/larger/makefiles.html -# $$ to escape $ for shell; -# note: must NOT put comments # inside bash execution; -# those would get removed by make; making shell see "EOF in backquote substitution" -# echo $$ix ; \ -# 'shell' twice - for each subprocess! Backtick doesn't get expanded? -GREPRES:=$(shell for ix in $(shell grep include $(TARGET).pde | sed 's/.*[<"]\(.*\).h[>"].*/\1/'); do \ - if [ -d $(INSTALL_DIR)/libraries/$$ix ] ; then \ - LINCS="$$LINCS -I$(INSTALL_DIR)/libraries/$$ix" ;\ - fi; \ - done; \ - echo $$LINCS) -# append includes: -CINCS += $(GREPRES) -CXXINCS += $(GREPRES) -# append library source .cpp files too (CXXSRC) -GREPRESB:=$(shell for ix in $(shell grep include $(TARGET).pde | sed 's/.*[<"]\(.*\).h[>"].*/\1/'); do \ - if [ -d $(INSTALL_DIR)/libraries/$$ix ] ; then \ - CPPSRCS="$$CPPSRCS $(INSTALL_DIR)/libraries/$$ix/*.cpp" ;\ - fi; \ - done; \ - echo $$CPPSRCS) -CXXSRC += $(GREPRESB) -# added - only CXX obj from libraries: -CXXLIBOBJ = $(GREPRESB:.cpp=.o) # Default target. all: applet_files build sizeafter -build: elf hex +build: elf hex applet_files: $(TARGET).pde - # Here is the "preprocessing". - # It creates a .cpp file based with the same name as the .pde file. - # On top of the new .cpp file comes the WProgram.h header. - # At the end there is a generic main() function attached. - # Then the .cpp file will be compiled. Errors during compile will - # refer to this new, automatically generated, file. - # Not the original .pde file you actually edit... + # Here is the "preprocessing". + # It creates a .cpp file based with the same name as the .pde file. + # On top of the new .cpp file comes the WProgram.h header. + # At the end there is a generic main() function attached. + # Then the .cpp file will be compiled. Errors during compile will + # refer to this new, automatically generated, file. + # Not the original .pde file you actually edit... test -d applet || mkdir applet - # @ supresses printout of the cmdline itself; so only the out of echo is printed - @echo ALL OBJT: $(OBJT) - @echo ALL CXXLIBOBJ: $(CXXLIBOBJ) -# echo '#include "WProgram.h"' > applet/$(TARGET).cpp - @echo "#include \"WProgram.h\"\nvoid setup();\nvoid loop();\n" > applet/$(TARGET).cpp - ##cat $(TARGET).pde >> applet/$(TARGET).cpp - cat ${PDES}>> applet/$(TARGET).cpp - cp *.cpp applet/ - # no more need to cat main.cpp (v0022) - now it is compiled in -# cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp - + echo '#include "WProgram.h"' > applet/$(TARGET).cpp + cat $(TARGET).pde >> applet/$(TARGET).cpp + cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp elf: applet/$(TARGET).elf hex: applet/$(TARGET).hex eep: applet/$(TARGET).eep -lss: applet/$(TARGET).lss +lss: applet/$(TARGET).lss sym: applet/$(TARGET).sym -# Program the device. +# Program the device. upload: applet/$(TARGET).hex $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) -# Display size of file. + + # Display size of file. HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex -ELFSIZE = $(SIZE) applet/$(TARGET).elf +ELFSIZE = $(SIZE) applet/$(TARGET).elf sizebefore: @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi sizeafter: @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi + # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. COFFCONVERT=$(OBJCOPY) --debugging \ - --change-section-address .data-0x800000 \ - --change-section-address .bss-0x800000 \ - --change-section-address .noinit-0x800000 \ - --change-section-address .eeprom-0x810000 +--change-section-address .data-0x800000 \ +--change-section-address .bss-0x800000 \ +--change-section-address .noinit-0x800000 \ +--change-section-address .eeprom-0x810000 + coff: applet/$(TARGET).elf $(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof + extcoff: $(TARGET).elf $(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof + .SUFFIXES: .elf .hex .eep .lss .sym .elf.hex: $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ .elf.eep: - -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ # Create extended listing file from ELF output file. .elf.lss: @@ -274,79 +199,50 @@ extcoff: $(TARGET).elf .elf.sym: $(NM) -n $< > $@ -# Link: create ELF output file from library. -# NOTE: applet/$(TARGET).cpp.o MUST BE BEFORE applet/core.a -# in the dependency list, so its rule runs first! -applet/$(TARGET).elf: $(TARGET).pde applet/$(TARGET).cpp.o applet/core.a -# $(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) -# changed as in IDE v0022: link cpp obj files - @echo $$(tput bold)$$(tput setaf 2) $(CC) $$(tput sgr0) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) - echo ${OBJT} - #$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o -L. applet/core.a $(LDFLAGS) - $(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ ${LINKORDER} $(LDFLAGS) - #@$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/*.o applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) + # Link: create ELF output file from library. +applet/$(TARGET).elf: $(TARGET).pde applet/core.a + $(CC) $(ALL_CFLAGS) -Wl,--gc-sections -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) -# added: cpp.o depends on cpp (and .pde which generates it) -# $< "first item in the dependencies list"; $@ "left side of the :"; $^ "right side of the :" -# http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ -applet/$(TARGET).cpp.o: applet/$(TARGET).cpp - @echo $$(tput bold) $(CXX) $$(tput sgr0) -c $(ALL_CXXFLAGS) $< -o $@ - @$(CXX) -c $(ALL_CXXFLAGS) $< -o $@ +applet/core.a: $(OBJ) + @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done -#~ applet/core.a: $(OBJ) -#~ @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done -applet/core.a: $(OBJT) - @for i in $(OBJT); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done -# iterate through OBJ to find the original location; then build depending on source extension -# TODO: add handling of assembler files -applet/%.o: - @for iob in $(OBJ); do \ - if [ "`basename $$iob`" = "`basename $@`" ]; then \ - for ios in $(ALLSRC); do \ - if [ "$${iob%%.*}" = "$${ios%%.*}" ]; then \ - case $${ios##*.} in \ - "cpp") \ - echo "$$(tput bold)$$(tput setaf 1) $(CXX) $$(tput sgr0) -c $(ALL_CXXFLAGS) $$ios -o $@"; \ - $(CXX) -c $(ALL_CXXFLAGS) $$ios -o $@;; \ - "c") \ - echo "$$(tput bold)$$(tput setaf 1) $(CC) $$(tput sgr0) -c $(ALL_CFLAGS) $$ios -o $@"; \ - $(CC) -c $(ALL_CFLAGS) $$ios -o $@;; \ - esac; \ - fi; \ - done; \ - fi; \ - done; +# Compile: create object files from C++ source files. +.cpp.o: + $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ -#~ # Compile: create object files from C++ source files. -#~ .cpp.o: -#~ $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ +# Compile: create object files from C source files. +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ -#~ # Compile: create object files from C source files. -#~ .c.o: -#~ $(CC) -c $(ALL_CFLAGS) $< -o $@ -#~ # Compile: create assembler files from C source files. -#~ .c.s: -#~ $(CC) -S $(ALL_CFLAGS) $< -o $@ +# Compile: create assembler files from C source files. +.c.s: + $(CC) -S $(ALL_CFLAGS) $< -o $@ -#~ # Assemble: create object files from assembler source files. -#~ .S.o: -#~ $(CC) -c $(ALL_ASFLAGS) $< -o $@ -#~ # Automatic dependencies -#~ %.d: %.c -#~ $(CC) -M $(ALL_CFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ +# Assemble: create object files from assembler source files. +.S.o: + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + -#~ %.d: %.cpp -#~ $(CXX) -M $(ALL_CXXFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ # Target: clean project. clean: $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ - applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ - $(OBJT) applet/$(TARGET).cpp.o \ - $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) + applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ + $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) -.PHONY: all build elf hex eep lss sym program coff extcoff clean applet_files sizebefore sizeafter +depend: + if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \ + then \ + sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \ + $(MAKEFILE).$$$$ && \ + $(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \ + fi + echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \ + >> $(MAKEFILE); \ + $(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE) + +.PHONY: all build elf hex eep lss sym program coff extcoff clean depend applet_files sizebefore sizeafter diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 78739af246..560046a2b0 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ // //# 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 const 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 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 824a57d780..54c0ad3f3e 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1301,8 +1301,10 @@ void manage_inactivity(byte debug) last_stepperdisabled_time=previous_millis_cmd; else { - if( (X_ENABLE_ON && (READ(X_ENABLE_PIN)!=0)) || (!X_ENABLE_ON && READ(X_ENABLE_PIN)==0) ) - enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); + #if X_ENABLE_PIN >= 0 + if( (X_ENABLE_ON && (READ(X_ENABLE_PIN)!=0)) || (!X_ENABLE_ON && READ(X_ENABLE_PIN)==0) ) + enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); + #endif last_stepperdisabled_time=millis(); } } diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.cpp similarity index 100% rename from Marlin/cardreader.pde rename to Marlin/cardreader.cpp diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 371c6e589b..e8ec15e951 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -85,9 +85,9 @@ static unsigned long previous_millis_bed_heater; static unsigned char soft_pwm[EXTRUDERS]; #ifdef WATCHPERIOD - static int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all - static int watch_oldtemp[3] = {0,0,0}; - static unsigned long watchmillis = 0; + int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all + int watch_oldtemp[3] = {0,0,0}; + unsigned long watchmillis = 0; #endif //WATCHPERIOD // Init min and max temp with extreme values to prevent false errors during startup @@ -218,7 +218,7 @@ void manage_heater() #ifdef WATCHPERIOD if(watchmillis && millis() - watchmillis > WATCHPERIOD){ - if(watch_oldtemp[TEMPSENSOR_HOTEND_0] >= degHotend(active_extruder)){ + if(watch_oldtemp[0] >= degHotend(active_extruder)){ setTargetHotend(0,active_extruder); LCD_MESSAGEPGM("Heating failed"); SERIAL_ECHO_START; @@ -527,7 +527,7 @@ void setWatch() for (int e = 0; e < EXTRUDERS; e++) { if(isHeatingHotend(e)) - watch_oldtemp[TEMPSENSOR_HOTEND_0] = degHotend(0); + watch_oldtemp[0] = degHotend(0); { t = max(t,millis()); watch_raw[e] = current_raw[e]; From 5aadc2f5ca43970f6905ea11e9e17868f2e1d0da Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 13:19:24 +1100 Subject: [PATCH 175/228] cardreader needs to include some other files --- Marlin/cardreader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp index a1f23ce068..2a7bd4a57b 100644 --- a/Marlin/cardreader.cpp +++ b/Marlin/cardreader.cpp @@ -1,5 +1,8 @@ #include "Marlin.h" #include "cardreader.h" +#include "ultralcd.h" +#include "stepper.h" +#include "temperature.h" #ifdef SDSUPPORT From 71dc82e0b47a8362f8e03dd361cbc1624b253c6e Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 13:19:37 +1100 Subject: [PATCH 176/228] my local configuration --- Marlin/Configuration.h | 66 +++++++++++++++++++++--------------------- Marlin/pins.h | 43 +++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 33 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 85fd389688..3dd8f61990 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -4,8 +4,8 @@ // This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 +//#define BAUDRATE 250000 +#define BAUDRATE 115200 //#define BAUDRATE 230400 #define EXTRUDERS 1 @@ -29,7 +29,7 @@ // Sanguinololu 1.2 and above = 62 // Ultimaker = 7, // Teensylu = 8 -#define MOTHERBOARD 7 +#define MOTHERBOARD 99 //=========================================================================== //=============================Thermal Settings ============================ @@ -44,36 +44,36 @@ // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 -//#define THERMISTORHEATER_0 3 +#define THERMISTORHEATER_0 1 //#define THERMISTORHEATER_1 1 //#define THERMISTORHEATER_2 1 -//#define HEATER_0_USES_THERMISTOR +#define HEATER_0_USES_THERMISTOR //#define HEATER_1_USES_THERMISTOR //#define HEATER_2_USES_THERMISTOR -#define HEATER_0_USES_AD595 +//#define HEATER_0_USES_AD595 //#define HEATER_1_USES_AD595 //#define HEATER_2_USES_AD595 // Select one of these only to define how the bed temp is read. -//#define THERMISTORBED 1 -//#define BED_USES_THERMISTOR +#define THERMISTORBED 1 +#define BED_USES_THERMISTOR //#define BED_LIMIT_SWITCHING #ifdef BED_LIMIT_SWITCHING #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS #endif //#define BED_USES_AD595 -#define BED_CHECK_INTERVAL 5000 //ms +#define BED_CHECK_INTERVAL 1000 //ms //// Heating sanity check: // This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // If the temperature has not increased at the end of that period, the target temperature is set to zero. // It can be reset with another M104/M109 -//#define WATCHPERIOD 20000 //20 seconds +#define WATCHPERIOD 20000 //20 seconds // Actual temperature must be close to target for this long before M109 returns success -#define TEMP_RESIDENCY_TIME 30 // (seconds) +#define TEMP_RESIDENCY_TIME 50 // (seconds) #define TEMP_HYSTERESIS 3 // (C°) range of +/- temperatures considered "close" to the target one //// The minimal temperature defines the temperature below which the heater will not be enabled @@ -86,10 +86,10 @@ // When temperature exceeds max temp, your heater will be switched off. // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 275 +#define HEATER_0_MAXTEMP 325 //#define HEATER_1_MAXTEMP 275 //#define HEATER_2_MAXTEMP 275 -//#define BED_MAXTEMP 150 +#define BED_MAXTEMP 140 // Wait for Cooldown @@ -103,7 +103,7 @@ // PID settings: // Uncomment the following line to enable PID support. -#define PIDTEMP +//#define PIDTEMP #define PID_MAX 255 // limits current to nozzle; 255=full current #ifdef PIDTEMP //#define PID_DEBUG // Sends debug data to the serial port. @@ -167,7 +167,7 @@ // extruder run-out prevention. //if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded //#define EXTRUDER_RUNOUT_PREVENT -#define EXTRUDER_RUNOUT_MINTEMP 190 +#define EXTRUDER_RUNOUT_MINTEMP 160 #define EXTRUDER_RUNOUT_SECONDS 30. #define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament #define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed @@ -209,8 +209,8 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //#define INVERT_E*_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false, used for all extruders #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_Y_DIR true // for Mendel set to true, for Orca set to false +#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true #define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false #define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false #define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false @@ -223,18 +223,18 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define min_software_endstops true //If true, axis won't move to coordinates less than zero. #define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 205 -#define Y_MAX_LENGTH 205 -#define Z_MAX_LENGTH 200 +#define X_MAX_LENGTH 187 +#define Y_MAX_LENGTH 188 +#define Z_MAX_LENGTH 80 //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) +#define HOMING_FEEDRATE {2400, 2400, 150, 0} // set the homing speeds (mm/min) //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again: -#define X_HOME_RETRACT_MM 5 -#define Y_HOME_RETRACT_MM 5 -#define Z_HOME_RETRACT_MM 1 +#define X_HOME_RETRACT_MM 2 +#define Y_HOME_RETRACT_MM 2 +#define Z_HOME_RETRACT_MM 2 #define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially. #define AXIS_RELATIVE_MODES {false, false, false, false} @@ -243,11 +243,11 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker +#define DEFAULT_AXIS_STEPS_PER_UNIT {64,64,3200,110} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 360} //sells mendel with v9 extruder //#define DEFAULT_AXIS_STEPS_PER_UNIT {80.3232, 80.8900, 2284.7651, 757.2218} // SAE Prusa w/ Wade extruder -#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 1000} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {1200,1200,100,9000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. #define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts @@ -257,7 +257,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. #define DEFAULT_MINSEGMENTTIME 20000 // Obsolete delete this -#define DEFAULT_XYJERK 20.0 // (mm/sec) +#define DEFAULT_XYJERK 12.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) // If defined the movements slow down when the look ahead buffer is only half full @@ -278,7 +278,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // 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. //define this to enable eeprom support -#define EEPROM_SETTINGS +//#define EEPROM_SETTINGS //to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: // please keep turned on if you can. #define EEPROM_CHITCHAT @@ -316,9 +316,9 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 -//#define SDSUPPORT // Enable SD Card Support in Hardware Console -#define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? -#define SD_FINISHED_RELEASECOMMAND "M84 X Y E" // no z because of layer shift. +#define SDSUPPORT // Enable SD Card Support in Hardware Console +#define SD_FINISHED_STEPPERRELEASE false //if sd support and the file is finished: disable steppers? +#define SD_FINISHED_RELEASECOMMAND "M81" // no z because of layer shift. //#define ULTIPANEL #ifdef ULTIPANEL @@ -358,7 +358,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //this prevents dangerous Extruder moves, i.e. if the temperature is under the limit //can be software-disabled for whatever purposes by #define PREVENT_DANGEROUS_EXTRUDE -#define EXTRUDE_MINTEMP 190 +#define EXTRUDE_MINTEMP 150 #define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. const int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement diff --git a/Marlin/pins.h b/Marlin/pins.h index 28e349161a..da573a4237 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -1,6 +1,49 @@ #ifndef PINS_H #define PINS_H +#if MOTHERBOARD == 99 +#define KNOWN_BOARD 1 + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 16 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 5 +#define Y_DIR_PIN 6 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 67 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 62 +#define Z_DIR_PIN 63 +#define Z_ENABLE_PIN -1 +#define Z_MIN_PIN 59 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 65 +#define E0_DIR_PIN 66 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 9 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 10 + +#endif /* 99 */ + /**************************************************************************************** * Arduino pin assignment * From 2ae2ead97b7b24b3e9a03f53da82c00ad7f73b71 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 14:24:24 +1100 Subject: [PATCH 177/228] help residency not overflow --- Marlin/Marlin.pde | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 54c0ad3f3e..0ffbdba80c 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -843,11 +843,11 @@ FORCE_INLINE void process_commands() /* 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 > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + (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) > 1000 ) + if( (millis() - codenum) > 1000UL ) { //Print Temp Reading and remaining time every 1 second while heating up/cooling down SERIAL_PROTOCOLPGM("T:"); SERIAL_PROTOCOL( degHotend(tmp_extruder) ); @@ -857,7 +857,7 @@ FORCE_INLINE void process_commands() SERIAL_PROTOCOLPGM(" W:"); if(residencyStart > -1) { - codenum = TEMP_RESIDENCY_TIME - ((millis() - residencyStart) / 1000); + codenum = ((TEMP_RESIDENCY_TIME * 1000UL) - (millis() - residencyStart)) / 1000UL; SERIAL_PROTOCOLLN( codenum ); } else From 3e575533c5f59f1a0452a7c0061faa4c88cbd0ec Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 14:24:41 +1100 Subject: [PATCH 178/228] get M81 working --- Marlin/Marlin.pde | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 0ffbdba80c..6f13cd3ecd 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -909,7 +909,7 @@ FORCE_INLINE void process_commands() LCD_MESSAGEPGM("Bed done."); previous_millis_cmd = millis(); #endif - break; + break; #if FAN_PIN > -1 case 106: //M106 Fan On @@ -938,14 +938,13 @@ FORCE_INLINE void process_commands() case 81: // M81 - ATX Power Off - #if (SUICIDE_PIN >-1) + #if defined SUICIDE_PIN && SUICIDE_PIN > -1 st_synchronize(); suicide(); - #else - #if (PS_ON_PIN > -1) - SET_INPUT(PS_ON_PIN); //Floating - #endif + #elif (PS_ON_PIN > -1) + SET_INPUT(PS_ON_PIN); //Floating #endif + break; case 82: axis_relative_modes[3] = false; From a991bde523fdd2952d156b457ea7bb6cecdd4bcb Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 14:25:28 +1100 Subject: [PATCH 179/228] enable auto-reset before programming, disable afterwards --- Marlin/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Marlin/Makefile b/Marlin/Makefile index 1e847a37b8..fdff2194f9 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -153,7 +153,9 @@ sym: applet/$(TARGET).sym # Program the device. upload: applet/$(TARGET).hex + stty hup < $(PORT); true $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) + stty -hup < $(PORT); true # Display size of file. From 42bedb3f604ea685dc8b26c2a690ac1891361862 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 15:57:42 +1100 Subject: [PATCH 180/228] PROGMEM elements must be const --- Marlin/speed_lookuptable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/speed_lookuptable.h b/Marlin/speed_lookuptable.h index ab3a076f14..45607bcb0c 100644 --- a/Marlin/speed_lookuptable.h +++ b/Marlin/speed_lookuptable.h @@ -3,7 +3,7 @@ #include "Marlin.h" -uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ +const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ { 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, { 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, { 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, @@ -38,7 +38,7 @@ uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ { 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0} }; -uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ +const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ { 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, { 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, { 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, From ab01658fd2e93dd4ceff47df9fb6b03c95ea9ebf Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 24 Jan 2012 17:02:45 +1100 Subject: [PATCH 181/228] local configuration stuff- WATCHPERIOD causes breakage, disable. few other misc changes --- Marlin/Configuration.h | 32 ++++++++++++++++---------------- Marlin/pins.h | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 3dd8f61990..d410a98355 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -70,10 +70,10 @@ // This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // If the temperature has not increased at the end of that period, the target temperature is set to zero. // It can be reset with another M104/M109 -#define WATCHPERIOD 20000 //20 seconds +// #define WATCHPERIOD 20000 //20 seconds // Actual temperature must be close to target for this long before M109 returns success -#define TEMP_RESIDENCY_TIME 50 // (seconds) +#define TEMP_RESIDENCY_TIME 5 // (seconds) #define TEMP_HYSTERESIS 3 // (C°) range of +/- temperatures considered "close" to the target one //// The minimal temperature defines the temperature below which the heater will not be enabled @@ -181,14 +181,14 @@ // Endstop Settings #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors - // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. + +const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false -#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing +//#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 @@ -217,7 +217,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //// ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN -#define X_HOME_DIR -1 +#define X_HOME_DIR 1 #define Y_HOME_DIR -1 #define Z_HOME_DIR -1 @@ -246,19 +246,19 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define DEFAULT_AXIS_STEPS_PER_UNIT {64,64,3200,110} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 360} //sells mendel with v9 extruder //#define DEFAULT_AXIS_STEPS_PER_UNIT {80.3232, 80.8900, 2284.7651, 757.2218} // SAE Prusa w/ Wade extruder -#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 1000} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {1200,1200,100,9000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +#define DEFAULT_MAX_FEEDRATE {500, 500, 2.5, 1000} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {7000,7000,50,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts +#define DEFAULT_ACCELERATION 4000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts -#define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 0.0 +#define DEFAULT_MINIMUMFEEDRATE 10.0 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 10.0 // minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. #define DEFAULT_MINSEGMENTTIME 20000 // Obsolete delete this -#define DEFAULT_XYJERK 12.0 // (mm/sec) -#define DEFAULT_ZJERK 0.4 // (mm/sec) +#define DEFAULT_XYJERK 8.0 // (mm/sec) +#define DEFAULT_ZJERK 0.1 // (mm/sec) // If defined the movements slow down when the look ahead buffer is only half full #define SLOWDOWN diff --git a/Marlin/pins.h b/Marlin/pins.h index da573a4237..208a040d9a 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -7,8 +7,8 @@ #define X_STEP_PIN 2 #define X_DIR_PIN 3 #define X_ENABLE_PIN -1 -#define X_MIN_PIN 16 -#define X_MAX_PIN -1 +#define X_MIN_PIN -1 +#define X_MAX_PIN 16 #define Y_STEP_PIN 5 #define Y_DIR_PIN 6 From 9c918a497b4cdb1b5cdf1b1237757212652fb08f Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 25 Jan 2012 20:46:27 +1100 Subject: [PATCH 182/228] more work on Makefile - actually rebuilds if Makefile or Configuration.h are altered, also much cleaner output --- Marlin/Makefile | 122 ++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 62 deletions(-) diff --git a/Marlin/Makefile b/Marlin/Makefile index fdff2194f9..71ee747485 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -32,19 +32,24 @@ # # $Id$ -TARGET = $(notdir $(CURDIR)) -INSTALL_DIR = ../../arduino-0022/ -UPLOAD_RATE = 115200 -AVRDUDE_PROGRAMMER = arduino -# PORT = /dev/arduino_A900G2I3 -PORT = /dev/arduino -MCU = atmega1280 #For "old" Arduino Mega -#MCU = atmega1280 +MCU = atmega1280 +#For Arduino Mega2560 +#MCU = atmega2560 #For Sanguinololu #MCU = atmega644p + +#Arduino install directory +INSTALL_DIR = ../../arduino-0022/ + F_CPU = 16000000 +UPLOAD_RATE = 115200 +AVRDUDE_PROGRAMMER = arduino +PORT = /dev/arduino + +TARGET = $(notdir $(CURDIR)) + ############################################################################ # Below here nothing should be changed... @@ -52,11 +57,11 @@ F_CPU = 16000000 ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino AVR_TOOLS_PATH = SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ -$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ -$(ARDUINO)/wiring_pulse.c \ -$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c + $(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ + $(ARDUINO)/wiring_pulse.c \ + $(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c CXXSRC = $(ARDUINO)/WMath.cpp $(ARDUINO)/WString.cpp\ -$(ARDUINO)/Print.cpp Marlin.cpp MarlinSerial.cpp Sd2Card.cpp SdBaseFile.cpp SdFatUtil.cpp SdFile.cpp SdVolume.cpp motion_control.cpp planner.cpp stepper.cpp temperature.cpp cardreader.cpp + $(ARDUINO)/Print.cpp Marlin.cpp MarlinSerial.cpp Sd2Card.cpp SdBaseFile.cpp SdFatUtil.cpp SdFile.cpp SdVolume.cpp motion_control.cpp planner.cpp stepper.cpp temperature.cpp cardreader.cpp FORMAT = ihex @@ -90,7 +95,7 @@ CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -w -f #CEXTRA = -Wa,-adhlns=$(<:.c=.lst) CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) -CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) +CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) #ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs LDFLAGS = -lm @@ -99,8 +104,8 @@ LDFLAGS = -lm AVRDUDE_PORT = $(PORT) AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex:i AVRDUDE_FLAGS = -D -C $(INSTALL_DIR)/hardware/tools/avrdude.conf \ --p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \ --b $(UPLOAD_RATE) + -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \ + -b $(UPLOAD_RATE) # Program settings CC = $(AVR_TOOLS_PATH)avr-gcc @@ -128,22 +133,23 @@ ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) # Default target. -all: applet_files build sizeafter +all: build sizeafter build: elf hex -applet_files: $(TARGET).pde - # Here is the "preprocessing". - # It creates a .cpp file based with the same name as the .pde file. - # On top of the new .cpp file comes the WProgram.h header. - # At the end there is a generic main() function attached. - # Then the .cpp file will be compiled. Errors during compile will - # refer to this new, automatically generated, file. - # Not the original .pde file you actually edit... - test -d applet || mkdir applet - echo '#include "WProgram.h"' > applet/$(TARGET).cpp - cat $(TARGET).pde >> applet/$(TARGET).cpp - cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp +applet/$(TARGET).cpp: $(TARGET).pde $(MAKEFILE) +# Here is the "preprocessing". +# It creates a .cpp file based with the same name as the .pde file. +# On top of the new .cpp file comes the WProgram.h header. +# At the end there is a generic main() function attached. +# Then the .cpp file will be compiled. Errors during compile will +# refer to this new, automatically generated, file. +# Not the original .pde file you actually edit... + @echo " WR applet/$(TARGET).cpp" + @test -d applet || mkdir applet + @echo '#include "WProgram.h"' > applet/$(TARGET).cpp + @cat $(TARGET).pde >> applet/$(TARGET).cpp + @cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp elf: applet/$(TARGET).elf hex: applet/$(TARGET).hex @@ -165,15 +171,15 @@ sizebefore: @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi sizeafter: - @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. COFFCONVERT=$(OBJCOPY) --debugging \ ---change-section-address .data-0x800000 \ ---change-section-address .bss-0x800000 \ ---change-section-address .noinit-0x800000 \ ---change-section-address .eeprom-0x810000 + --change-section-address .data-0x800000 \ + --change-section-address .bss-0x800000 \ + --change-section-address .noinit-0x800000 \ + --change-section-address .eeprom-0x810000 coff: applet/$(TARGET).elf @@ -185,13 +191,15 @@ extcoff: $(TARGET).elf .SUFFIXES: .elf .hex .eep .lss .sym +.PRECIOUS: .o .elf.hex: - $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + @echo " COPY $@" + @$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ .elf.eep: -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ # Create extended listing file from ELF output file. .elf.lss: @@ -202,39 +210,29 @@ extcoff: $(TARGET).elf $(NM) -n $< > $@ # Link: create ELF output file from library. -applet/$(TARGET).elf: $(TARGET).pde applet/core.a - $(CC) $(ALL_CFLAGS) -Wl,--gc-sections -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) +applet/$(TARGET).elf: applet/$(TARGET).cpp applet/core.a Configuration.h + @echo " CXX $@" + @$(CC) $(ALL_CXXFLAGS) -Wl,--gc-sections -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) -applet/core.a: $(OBJ) - @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done - - - -# Compile: create object files from C++ source files. -.cpp.o: - $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ - -# Compile: create object files from C source files. -.c.o: - $(CC) -c $(ALL_CFLAGS) $< -o $@ - - -# Compile: create assembler files from C source files. -.c.s: - $(CC) -S $(ALL_CFLAGS) $< -o $@ - - -# Assemble: create object files from assembler source files. -.S.o: - $(CC) -c $(ALL_ASFLAGS) $< -o $@ +applet/core.a: $(OBJ) Configuration.h + @for i in $(OBJ); do echo " AR $$i"; $(AR) rcs applet/core.a $$i; done +%.o: %.c Configuration.h $(MAKEFILE) + @echo " CC $@" + @$(CC) -c $(ALL_CFLAGS) $< -o $@ +%.o: %.cpp Configuration.h $(MAKEFILE) + @echo " CXX $@" + @$(CXX) -c $(ALL_CXXFLAGS) $< -o $@ # Target: clean project. clean: - $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ - applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ - $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) + @echo " RM applet/*" + @$(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ + applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/$(TARGET).cpp applet/core.a \ + $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) + @echo " RMDIR applet/" + @rmdir applet depend: if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \ From e45e5c68bb67ddec39b9bda25cf96396c12fe10b Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 5 Feb 2012 12:42:15 +0100 Subject: [PATCH 183/228] Added support for Gen3+ (Pins file only) Added late z enable. (blddk request) Only calculate look ahead if >2 moves in buffer. Removed some FORCE_INLINE to save memory. Signed-off-by: Erik van der Zalm --- Marlin/Configuration.h | 4 +- Marlin/Marlin.pde | 16 +++--- Marlin/pins.h | 125 ++++++++++++++++++++++++++++++++++++++++- Marlin/planner.cpp | 12 ++-- Marlin/stepper.cpp | 3 + Marlin/ultralcd.pde | 2 +- 6 files changed, 146 insertions(+), 16 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 85fd389688..6b5e19a3d3 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -28,7 +28,8 @@ // Gen6 = 5, // Sanguinololu 1.2 and above = 62 // Ultimaker = 7, -// Teensylu = 8 +// Teensylu = 8, +// Gen3+ =9 #define MOTHERBOARD 7 //=========================================================================== @@ -201,6 +202,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define DISABLE_Y false #define DISABLE_Z false #define DISABLE_E false // For all extruders +//#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats. // Inverting axis direction //#define INVERT_X_DIR false // for Mendel set to false, for Orca set to true diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index bbef8170d7..57eb61b8e4 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -327,7 +327,7 @@ void loop() } -FORCE_INLINE void get_command() +void get_command() { while( MSerial.available() > 0 && buflen < BUFSIZE) { serial_char = MSerial.read(); @@ -474,20 +474,20 @@ FORCE_INLINE void get_command() } -FORCE_INLINE float code_value() +float code_value() { return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); } -FORCE_INLINE long code_value_long() +long code_value_long() { return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); } -FORCE_INLINE bool code_seen(char code_string[]) //Return True if the string was found +bool code_seen(char code_string[]) //Return True if the string was found { return (strstr(cmdbuffer[bufindr], code_string) != NULL); } -FORCE_INLINE bool code_seen(char code) +bool code_seen(char code) { strchr_pointer = strchr(cmdbuffer[bufindr], code); return (strchr_pointer != NULL); //Return True if a character was found @@ -519,7 +519,7 @@ FORCE_INLINE bool code_seen(char code) endstops_hit_on_purpose();\ } -FORCE_INLINE void process_commands() +void process_commands() { unsigned long codenum; //throw away variable char *starpos = NULL; @@ -1235,7 +1235,7 @@ void ClearToSend() SERIAL_PROTOCOLLNPGM("ok"); } -FORCE_INLINE void get_coordinates() +void get_coordinates() { 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]; @@ -1247,7 +1247,7 @@ FORCE_INLINE void get_coordinates() } } -FORCE_INLINE void get_arc_coordinates() +void get_arc_coordinates() { get_coordinates(); if(code_seen('I')) offset[0] = code_value(); diff --git a/Marlin/pins.h b/Marlin/pins.h index 28e349161a..02f26150a1 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -470,7 +470,7 @@ #define X_STEP_PIN 15 #define X_DIR_PIN 21 #define X_MIN_PIN 18 -#define X_MAX_PIN -2 +#define X_MAX_PIN -1 #define Y_STEP_PIN 22 #define Y_DIR_PIN 23 @@ -653,6 +653,73 @@ #endif +#if MOTHERBOARD == 71 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment (Old electronics) +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 15 +#define X_MAX_PIN 14 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 17 +#define Y_MAX_PIN 16 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 19 +#define Z_MAX_PIN 18 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define HEATER_1_PIN 1 +#define TEMP_1_PIN 1 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN -1 +#define E1_DIR_PIN -1 +#define E1_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define SUICIDE_PIN -1 //PIN that has to be turned on right after start, to keep power flowing. + +#define LCD_PINS_RS 24 +#define LCD_PINS_ENABLE 22 +#define LCD_PINS_D4 36 +#define LCD_PINS_D5 34 +#define LCD_PINS_D6 32 +#define LCD_PINS_D7 30 + +#endif + /**************************************************************************************** * Teensylu 0.7 pin assingments (ATMEGA90USB) * Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! @@ -712,6 +779,62 @@ #endif #endif +/**************************************************************************************** +* Gen3+ pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 9 +#define MOTHERBOARD 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_MIN_PIN 20 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 27 +#define Z_DIR_PIN 28 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 17 +#define E_DIR_PIN 21 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN 14 +#define KILL_PIN -1 + +#define HEATER_0_PIN 12 // (extruder) + +#define HEATER_1_PIN 16 // (bed) +#define X_ENABLE_PIN 19 +#define Y_ENABLE_PIN 24 +#define Z_ENABLE_PIN 29 +#define E_ENABLE_PIN 13 + +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN 5 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 4 +#define HEATER_2_PIN -1 + +#endif + + + + #ifndef KNOWN_BOARD #error Unknown MOTHERBOARD value in configuration.h #endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index f3007af531..cfa478cdd4 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -430,7 +430,9 @@ void check_axes_activity() { } if((DISABLE_X) && (x_active == 0)) disable_x(); if((DISABLE_Y) && (y_active == 0)) disable_y(); - if((DISABLE_Z) && (z_active == 0)) disable_z(); + #ifndef Z_LATE_ENABLE + if((DISABLE_Z) && (z_active == 0)) disable_z(); + #endif if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } } @@ -505,7 +507,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa //enable active axes if(block->steps_x != 0) enable_x(); if(block->steps_y != 0) enable_y(); - if(block->steps_z != 0) enable_z(); +// if(block->steps_z != 0) enable_z(); // Enable all if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } @@ -535,10 +537,10 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa if(feed_rate 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); #endif @@ -686,7 +688,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa vmax_junction = max_z_jerk/2; vmax_junction = min(vmax_junction, block->nominal_speed); - if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { + if ((moves_queued > 1) && (previous_nominal_speed > 0.0)) { float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { vmax_junction = block->nominal_speed; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 076fbeea1c..69d433545a 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -274,6 +274,9 @@ FORCE_INLINE void trapezoid_generator_reset() { acceleration_time = calc_timer(acc_step_rate); OCR1A = acceleration_time; OCR1A_nominal = calc_timer(current_block->nominal_rate); + #ifdef Z_LATE_ENABLE + if(current_block->steps_z > 0) enable_z(); + #endif // SERIAL_ECHO_START; // SERIAL_ECHOPGM("advance :"); diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 69be85959a..68a5954752 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -59,7 +59,7 @@ void lcdProgMemprint(const char *str) //=============================functions ============================ //=========================================================================== -FORCE_INLINE int intround(const float &x){return int(0.5+x);} +int intround(const float &x){return int(0.5+x);} void lcd_status(const char* message) { From 9f139d6e0e3592c71851535f25fb83245361a5f3 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 5 Feb 2012 13:05:07 +0100 Subject: [PATCH 184/228] Added MAX6675 support. (Thanks to gregfrost) Needs some work to remove the blocking in read max6675. --- Marlin/Configuration.h | 2 + Marlin/pins.h | 9 +++-- Marlin/temperature.cpp | 92 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 6 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 6b5e19a3d3..49721cc193 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -55,6 +55,8 @@ #define HEATER_0_USES_AD595 //#define HEATER_1_USES_AD595 //#define HEATER_2_USES_AD595 +//#define HEATER_0_USES_MAX6675 + // Select one of these only to define how the bed temp is read. //#define THERMISTORBED 1 diff --git a/Marlin/pins.h b/Marlin/pins.h index 02f26150a1..9ff7dd94a7 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -331,16 +331,17 @@ // SPI for Max6675 Thermocouple #ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support #define SCK_PIN 52 - #define MISO_PIN 50 - #define MOSI_PIN 51 +// these pins are defined in the SD library if building with SD support + #define MAX_SCK_PIN 52 + #define MAX_MISO_PIN 50 + #define MAX_MOSI_PIN 51 #define MAX6675_SS 53 #else #define MAX6675_SS 49 #endif - #endif + /**************************************************************************************** * Duemilanove w/ ATMega328P pin assignment * diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 371c6e589b..0be5f2607d 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -283,6 +283,12 @@ int temp2analog(int celsius, uint8_t e) { SERIAL_ERRORLNPGM(" - Invalid extruder number!"); kill(); } + #ifdef HEATER_0_USES_MAX6675 + if (e == 0) + { + return celsius * 4; + } + #endif if(heater_ttbl_map[e] != 0) { int raw = 0; @@ -352,7 +358,14 @@ float analog2temp(int raw, uint8_t e) { SERIAL_ERROR((int)e); SERIAL_ERRORLNPGM(" - Invalid extruder number !"); kill(); - } + } + #ifdef HEATER_0_USES_MAX6675 + if (e == 0) + { + return 0.25 * raw; + } + #endif + if(heater_ttbl_map[e] != 0) { float celsius = 0; @@ -446,6 +459,22 @@ void tp_init() SET_OUTPUT(FAN_PIN); #endif + #ifdef HEATER_0_USES_MAX6675 + #ifndef SDSUPPORT + SET_OUTPUT(MAX_SCK_PIN); + WRITE(MAX_SCK_PIN,0); + + SET_OUTPUT(MAX_MOSI_PIN); + WRITE(MAX_MOSI_PIN,1); + + SET_INPUT(MAX_MISO_PIN); + WRITE(MAX_MISO_PIN,1); + #endif + + SET_OUTPUT(MAX6675_SS); + WRITE(MAX6675_SS,1); + #endif + // Set analog inputs ADCSRA = 1<> 3; + } + + return max6675_temp; +} +#endif + + // Timer 0 is shared with millies ISR(TIMER0_COMPB_vect) { @@ -653,6 +738,9 @@ ISR(TIMER0_COMPB_vect) #if (TEMP_0_PIN > -1) raw_temp_0_value += ADC; #endif + #ifdef HEATER_0_USES_MAX6675 // TODO remove the blocking + raw_temp_0_value = read_max6675(); + #endif temp_state = 2; break; case 2: // Prepare TEMP_BED @@ -732,7 +820,7 @@ ISR(TIMER0_COMPB_vect) #endif #if EXTRUDERS > 1 - #ifdef HEATER_1_USES_AD595 + #ifdef HEATER_1_USES_AD595 || defined HEATER_0_USES_MAX6675 current_raw[1] = raw_temp_1_value; #else current_raw[1] = 16383 - raw_temp_1_value; From abb7e639067677257d9409728f1370dcf24e5923 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 5 Feb 2012 21:14:55 +0100 Subject: [PATCH 185/228] fixed z-disable bug. --- Marlin/planner.cpp | 8 ++++---- Marlin/stepper.cpp | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index cfa478cdd4..85c82aecc0 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -430,9 +430,7 @@ void check_axes_activity() { } if((DISABLE_X) && (x_active == 0)) disable_x(); if((DISABLE_Y) && (y_active == 0)) disable_y(); - #ifndef Z_LATE_ENABLE - if((DISABLE_Z) && (z_active == 0)) disable_z(); - #endif + if((DISABLE_Z) && (z_active == 0)) disable_z(); if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } } @@ -507,7 +505,9 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa //enable active axes if(block->steps_x != 0) enable_x(); if(block->steps_y != 0) enable_y(); -// if(block->steps_z != 0) enable_z(); + #ifndef Z_LATE_ENABLE + if(block->steps_z != 0) enable_z(); + #endif // Enable all if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 69d433545a..a32dd8dff9 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -274,7 +274,8 @@ FORCE_INLINE void trapezoid_generator_reset() { acceleration_time = calc_timer(acc_step_rate); OCR1A = acceleration_time; OCR1A_nominal = calc_timer(current_block->nominal_rate); - #ifdef Z_LATE_ENABLE + + #ifdef Z_LATE_ENABLE if(current_block->steps_z > 0) enable_z(); #endif From 292ddd2edbf4663ad2b5f69f7e46e2eb3600d465 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 6 Feb 2012 17:38:16 +0100 Subject: [PATCH 186/228] Fix Z_LATE_ENABLE --- Marlin/stepper.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index a32dd8dff9..26c265e532 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -275,9 +275,7 @@ FORCE_INLINE void trapezoid_generator_reset() { OCR1A = acceleration_time; OCR1A_nominal = calc_timer(current_block->nominal_rate); - #ifdef Z_LATE_ENABLE - if(current_block->steps_z > 0) enable_z(); - #endif + // SERIAL_ECHO_START; // SERIAL_ECHOPGM("advance :"); @@ -306,6 +304,14 @@ ISR(TIMER1_COMPA_vect) counter_z = counter_x; counter_e = counter_x; step_events_completed = 0; + #ifdef Z_LATE_ENABLE + if(current_block->steps_z > 0) { + enable_z(); + OCR1A = 2000; //1ms wait + return; + } + #endif + // #ifdef ADVANCE // e_steps[current_block->active_extruder] = 0; // #endif From f9c5333f97c2533066d4ccbe2479a5ee09b05058 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Mon, 6 Feb 2012 20:13:44 +0100 Subject: [PATCH 187/228] Made "stop heating wait" optional. Default off. --- Marlin/Configuration.h | 3 +++ Marlin/cardreader.pde | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 49721cc193..2a0614787e 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -104,6 +104,9 @@ // Heating is finished if a temperature close to this degree shift is reached #define HEATING_EARLY_FINISH_DEG_OFFSET 1 //Degree +//Do not wait for M109 to finish when printing from SD card +//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING + // PID settings: // Uncomment the following line to enable PID support. #define PIDTEMP diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde index a1f23ce068..2fefbcf535 100644 --- a/Marlin/cardreader.pde +++ b/Marlin/cardreader.pde @@ -444,7 +444,9 @@ void CardReader::printingHasFinished() st_synchronize(); quickStop(); sdprinting = false; + #ifdef STOP_HEATING_WAIT_FOR_SD_PRINTING stop_heating_wait=true; + #endif if(SD_FINISHED_STEPPERRELEASE) { //finishAndDisableSteppers(); From d8a0c6450f01afb22622eb78a23794f72773fbf5 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Tue, 7 Feb 2012 20:23:43 +0100 Subject: [PATCH 188/228] Split the configuration file in two parts. One for common settings. One for advanced settings. --- Marlin/Configuration.h | 271 +++++-------------------------------- Marlin/Configuration_adv.h | 208 ++++++++++++++++++++++++++++ Marlin/Marlin.pde | 24 ++-- 3 files changed, 257 insertions(+), 246 deletions(-) create mode 100644 Marlin/Configuration_adv.h diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 2a0614787e..c1bcc0fae6 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,26 +1,13 @@ #ifndef __CONFIGURATION_H #define __CONFIGURATION_H - +// This configurtion file contains the basic settings. +// Advanced settings can be found in Configuration_adv.h +// BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration // This determines the communication speed of the printer #define BAUDRATE 250000 //#define BAUDRATE 115200 -//#define BAUDRATE 230400 - -#define EXTRUDERS 1 - -// Frequency limit -// See nophead's blog for more info -// Not working O -//#define XY_FREQUENCY_LIMIT 15 - -// Minimum planner junction speed. Sets the default minimum speed the planner plans for at the end -// of the buffer and all stops. This should not be much greater than zero and should only be changed -// if unwanted behavior is observed on a user's machine when running at very slow speeds. -#define MINIMUM_PLANNER_SPEED 2.0 // (mm/sec) - -// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration //// The following define selects which electronics board you have. Please choose the one that matches your setup // MEGA/RAMPS up to 1.2 = 3, @@ -36,7 +23,10 @@ //=============================Thermal Settings ============================ //=========================================================================== -//// Thermistor settings: +//// Temperature sensor settings: +// -2 is thermocouple with MAX6675 (only for sensor 0) +// -1 is thermocouple with AD595 +// 0 is not used // 1 is 100k thermistor // 2 is 200k thermistor // 3 is mendel-parts thermistor @@ -45,70 +35,33 @@ // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 -//#define THERMISTORHEATER_0 3 -//#define THERMISTORHEATER_1 1 -//#define THERMISTORHEATER_2 1 - -//#define HEATER_0_USES_THERMISTOR -//#define HEATER_1_USES_THERMISTOR -//#define HEATER_2_USES_THERMISTOR -#define HEATER_0_USES_AD595 -//#define HEATER_1_USES_AD595 -//#define HEATER_2_USES_AD595 -//#define HEATER_0_USES_MAX6675 - - -// Select one of these only to define how the bed temp is read. -//#define THERMISTORBED 1 -//#define BED_USES_THERMISTOR -//#define BED_LIMIT_SWITCHING -#ifdef BED_LIMIT_SWITCHING - #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS -#endif -//#define BED_USES_AD595 - -#define BED_CHECK_INTERVAL 5000 //ms - -//// Heating sanity check: -// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. -// It can be reset with another M104/M109 -//#define WATCHPERIOD 20000 //20 seconds +#define TEMP_SENSOR_0 -1 +#define TEMP_SENSOR_1 0 +#define TEMP_SENSOR_2 0 +#define TEMP_SENSOR_BED 0 // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 30 // (seconds) #define TEMP_HYSTERESIS 3 // (C°) range of +/- temperatures considered "close" to the target one -//// The minimal temperature defines the temperature below which the heater will not be enabled +// The minimal temperature defines the temperature below which the heater will not be enabled It is used +// to check that the wiring to the thermistor is not broken. +// Otherwise this would lead to the heater being powered on all the time. #define HEATER_0_MINTEMP 5 -//#define HEATER_1_MINTEMP 5 -//#define HEATER_2_MINTEMP 5 -//#define BED_MINTEMP 5 - +#define HEATER_1_MINTEMP 5 +#define HEATER_2_MINTEMP 5 +#define BED_MINTEMP 5 // When temperature exceeds max temp, your heater will be switched off. // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. #define HEATER_0_MAXTEMP 275 -//#define HEATER_1_MAXTEMP 275 -//#define HEATER_2_MAXTEMP 275 -//#define BED_MAXTEMP 150 - - -// Wait for Cooldown -// This defines if the M109 call should not block if it is cooling down. -// example: From a current temp of 220, you set M109 S200. -// if CooldownNoWait is defined M109 will not wait for the cooldown to finish -#define CooldownNoWait true - -// Heating is finished if a temperature close to this degree shift is reached -#define HEATING_EARLY_FINISH_DEG_OFFSET 1 //Degree - -//Do not wait for M109 to finish when printing from SD card -//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING +#define HEATER_1_MAXTEMP 275 +#define HEATER_2_MAXTEMP 275 +#define BED_MAXTEMP 150 // PID settings: -// Uncomment the following line to enable PID support. +// Comment the following line to disable PID and enable bang-bang. #define PIDTEMP #define PID_MAX 255 // limits current to nozzle; 255=full current #ifdef PIDTEMP @@ -118,28 +71,8 @@ #define K1 0.95 //smoothing factor withing the PID #define PID_dT 0.128 //sampling period of the PID - //To develop some PID settings for your machine, you can initiall follow - // the Ziegler-Nichols method. - // set Ki and Kd to zero. - // heat with a defined Kp and see if the temperature stabilizes - // ideally you do this graphically with repg. - // the PID_CRITIAL_GAIN should be the Kp at which temperature oscillatins are not dampned out/decreas in amplitutde - // PID_SWING_AT_CRITIAL is the time for a full period of the oscillations at the critical Gain - // usually further manual tunine is necessary. - - #define PID_CRITIAL_GAIN 50 - #define PID_SWING_AT_CRITIAL 47 //seconds - - //#define PID_PI //no differentail term - #define PID_PID //normal PID - - #ifdef PID_PID - //PID according to Ziegler-Nichols method -// #define DEFAULT_Kp (0.6*PID_CRITIAL_GAIN) -// #define DEFAULT_Ki (2*Kp/PID_SWING_AT_CRITIAL*PID_dT) -// #define DEFAULT_Kd (PID_SWING_AT_CRITIAL/8./PID_dT) - -// Ultitmaker +// If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it +// Ultimaker #define DEFAULT_Kp 22.2 #define DEFAULT_Ki (1.25*PID_dT) #define DEFAULT_Kd (99/PID_dT) @@ -152,39 +85,19 @@ // Mendel Parts V9 on 12V // #define DEFAULT_Kp 63.0 // #define DEFAULT_Ki (2.25*PID_dT) -// #define DEFAULT_Kd (440/PID_dT) - #endif - - #ifdef PID_PI - //PI according to Ziegler-Nichols method - #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) - #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) - #define DEFAULT_Kd (0) - #endif - - // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. - // if Kc is choosen well, the additional required power due to increased melting should be compensated. - #define PID_ADD_EXTRUSION_RATE - #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) - #endif +// #define DEFAULT_Kd (440/PID_dT) #endif // PIDTEMP -// extruder run-out prevention. -//if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded -//#define EXTRUDER_RUNOUT_PREVENT -#define EXTRUDER_RUNOUT_MINTEMP 190 -#define EXTRUDER_RUNOUT_SECONDS 30. -#define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament -#define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed -#define EXTRUDER_RUNOUT_EXTRUDE 100 - +//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit +//can be software-disabled for whatever purposes by +#define PREVENT_DANGEROUS_EXTRUDE +#define EXTRUDE_MINTEMP 190 +#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. //=========================================================================== //=============================Mechanical Settings=========================== //=========================================================================== - // Endstop Settings #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors @@ -192,9 +105,6 @@ const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false - -#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 @@ -207,13 +117,6 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define DISABLE_Y false #define DISABLE_Z false #define DISABLE_E false // For all extruders -//#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats. - -// Inverting axis direction -//#define INVERT_X_DIR false // for Mendel set to false, for Orca set to true -//#define INVERT_Y_DIR true // for Mendel set to true, for Orca set to false -//#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true -//#define INVERT_E*_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false, used for all extruders #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false @@ -222,7 +125,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false #define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -//// ENDSTOP SETTINGS: +// ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN #define X_HOME_DIR -1 #define Y_HOME_DIR -1 @@ -238,43 +141,19 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E #define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) -//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again: -#define X_HOME_RETRACT_MM 5 -#define Y_HOME_RETRACT_MM 5 -#define Z_HOME_RETRACT_MM 1 -#define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially. - -#define AXIS_RELATIVE_MODES {false, false, false, false} - -#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) - // default settings #define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker -//#define DEFAULT_AXIS_STEPS_PER_UNIT {40, 40, 3333.92, 360} //sells mendel with v9 extruder -//#define DEFAULT_AXIS_STEPS_PER_UNIT {80.3232, 80.8900, 2284.7651, 757.2218} // SAE Prusa w/ Wade extruder #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. #define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts -#define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 0.0 - -// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. -#define DEFAULT_MINSEGMENTTIME 20000 // Obsolete delete this +// #define DEFAULT_XYJERK 20.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) -// If defined the movements slow down when the look ahead buffer is only half full -#define SLOWDOWN - -//default stepper release if idle -#define DEFAULT_STEPPER_DEACTIVE_TIME 60 -#define DEFAULT_STEPPER_DEACTIVE_COMMAND "M84 X Y E" //z stays powered - - //=========================================================================== //=============================Additional Features=========================== //=========================================================================== @@ -285,47 +164,14 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // 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. //define this to enable eeprom support -#define EEPROM_SETTINGS +//#define EEPROM_SETTINGS //to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: // please keep turned on if you can. -#define EEPROM_CHITCHAT - - -// 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: -//#define RESET_MANUAL -//#define WATCHDOG_TIMEOUT 4 //seconds -//#endif - -// extruder advance constant (s2/mm3) -// -// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 -// -// hooke's law says: force = k * distance -// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant -// so: v ^ 2 is proportional to number of steps we advance the extruder -//#define ADVANCE - -#ifdef ADVANCE - #define EXTRUDER_ADVANCE_K .0 - - #define D_FILAMENT 2.85 - #define STEPS_MM_E 836 - #define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) - #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) - -#endif // ADVANCE - +//#define EEPROM_CHITCHAT //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 //#define SDSUPPORT // Enable SD Card Support in Hardware Console -#define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? -#define SD_FINISHED_RELEASECOMMAND "M84 X Y E" // no z because of layer shift. //#define ULTIPANEL #ifdef ULTIPANEL @@ -341,60 +187,11 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #endif #endif -// A debugging feature to compare calculated vs performed steps, to see if steps are lost by the software. -//#define DEBUG_STEPS - - -// Arc interpretation settings: -#define MM_PER_ARC_SEGMENT 1 -#define N_ARC_CORRECTION 25 - - -//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode. -//The maximum buffered steps/sec of the extruder motor are called "se". -//You enter the autotemp mode by a M109 S T F -// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp -// you exit the value by any M109 without F* -// Also, if the temperature is set to a value target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS +#endif +#define BED_CHECK_INTERVAL 5000 //ms + +//// Heating sanity check: +// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. +// It can be reset with another M104/M109 +//#define WATCHPERIOD 20000 //20 seconds + +// Wait for Cooldown +// This defines if the M109 call should not block if it is cooling down. +// example: From a current temp of 220, you set M109 S200. +// if CooldownNoWait is defined M109 will not wait for the cooldown to finish +#define CooldownNoWait true + +// Heating is finished if a temperature close to this degree shift is reached +#define HEATING_EARLY_FINISH_DEG_OFFSET 1 //Degree + +//Do not wait for M109 to finish when printing from SD card +//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING + +#ifdef PIDTEMP + // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. + // if Kc is choosen well, the additional required power due to increased melting should be compensated. + #define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) + #endif +#endif + + +//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode. +//The maximum buffered steps/sec of the extruder motor are called "se". +//You enter the autotemp mode by a M109 S T F +// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp +// you exit the value by any M109 without F* +// Also, if the temperature is set to a value 0 + #define THERMISTORHEATER_0 TEMP_SENSOR_0 + #define HEATER_0_USES_THERMISTOR +#endif +#if TEMP_SENSOR_1 > 0 + #define THERMISTORHEATER_1 TEMP_SENSOR_1 + #define HEATER_1_USES_THERMISTOR +#endif +#if TEMP_SENSOR_2 > 0 + #define THERMISTORHEATER_2 TEMP_SENSOR_2 + #define HEATER_2_USES_THERMISTOR +#endif +#if TEMP_SENSOR_BED > 0 + #define THERMISTORBED TEMP_SENSOR_BED + #define BED_USES_THERMISTOR +#endif +#if TEMP_SENSOR_0 == -1 + #define HEATER_0_USES_AD595 +#endif +#if TEMP_SENSOR_1 == -1 + #define HEATER_1_USES_AD595 +#endif +#if TEMP_SENSOR_2 == -1 + #define HEATER_2_USES_AD595 +#endif +#if TEMP_SENSOR_BED == -1 + #define BED_USES_AD595 +#endif +#if TEMP_SENSOR_0 == -2 + #define HEATER_0_USES_MAX6675 +#endif + +#endif //__CONFIGURATION_ADV_H diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 57eb61b8e4..e1decfd3f0 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -254,6 +254,12 @@ void suicide() #endif } +long millis_diff(unsigned long starttime) { + unsigned long difftime = millis() - starttime; + if (difftime > 0x8000) difftime += 0x8000; + return difftime; +} + void setup() { setup_powerhold(); @@ -550,9 +556,9 @@ void process_commands() if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait st_synchronize(); - codenum += millis(); // keep track of when we started waiting +// codenum += millis(); // keep track of when we started waiting previous_millis_cmd = millis(); - while(millis() < codenum ){ + while(millis_diff(previous_millis_cmd) < codenum ){ manage_heater(); } break; @@ -843,11 +849,11 @@ void process_commands() /* 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 > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + (residencyStart > -1 && (millis_diff(residencyStart) < TEMP_RESIDENCY_TIME*1000) )) { #else while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000 ) + if(millis_diff(codenum) > 1000 ) { //Print Temp Reading and remaining time every 1 second while heating up/cooling down SERIAL_PROTOCOLPGM("T:"); SERIAL_PROTOCOL( degHotend(tmp_extruder) ); @@ -857,7 +863,7 @@ void process_commands() SERIAL_PROTOCOLPGM(" W:"); if(residencyStart > -1) { - codenum = TEMP_RESIDENCY_TIME - ((millis() - residencyStart) / 1000); + codenum = TEMP_RESIDENCY_TIME - (millis_diff(residencyStart) / 1000); SERIAL_PROTOCOLLN( codenum ); } else @@ -895,7 +901,7 @@ void process_commands() codenum = millis(); while(isHeatingBed()) { - if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + if( millis_diff(codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { float tt=degHotend(active_extruder); SERIAL_PROTOCOLPGM("T:"); @@ -1293,11 +1299,11 @@ void prepare_arc_move(char isclockwise) { void manage_inactivity(byte debug) { - if( (millis()-previous_millis_cmd) > max_inactive_time ) + if( millis_diff(previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); if(stepper_inactive_time) - if( (millis()-last_stepperdisabled_time) > stepper_inactive_time ) + if( millis_diff(last_stepperdisabled_time) > stepper_inactive_time ) { if(previous_millis_cmd>last_stepperdisabled_time) last_stepperdisabled_time=previous_millis_cmd; @@ -1309,7 +1315,7 @@ void manage_inactivity(byte debug) } } #ifdef EXTRUDER_RUNOUT_PREVENT - if( (millis()-previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) + if( millis_diff(previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) { bool oldstatus=READ(E0_ENABLE_PIN); From 5113513cb2efd62c01a4fab4cb28e0a8d9905005 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Wed, 8 Feb 2012 18:28:54 +0100 Subject: [PATCH 189/228] RC 1 --- Marlin/Configuration_adv.h | 17 +++++++++++++++ Marlin/Marlin.pde | 42 ++++++++++++-------------------------- README.md | 6 +++++- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index a94dba79d6..1bdbd1ac2c 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -204,5 +204,22 @@ const int dropsegments=5; //everything with less than this number of steps will #if TEMP_SENSOR_0 == -2 #define HEATER_0_USES_MAX6675 #endif +#if TEMP_SENSOR_0 == 0 + #undef HEATER_0_MINTEMP + #undef HEATER_0_MAXTEMP +#endif +#if TEMP_SENSOR_1 == 0 + #undef HEATER_1_MINTEMP + #undef HEATER_1_MAXTEMP +#endif +#if TEMP_SENSOR_2 == 0 + #undef HEATER_2_MINTEMP + #undef HEATER_2_MAXTEMP +#endif +#if TEMP_SENSOR_BED == 0 + #undef BED_MINTEMP + #undef BED_MAXTEMP +#endif + #endif //__CONFIGURATION_ADV_H diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index e1decfd3f0..57ededa2ef 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -27,8 +27,6 @@ #include "Marlin.h" - - #include "ultralcd.h" #include "planner.h" #include "stepper.h" @@ -38,12 +36,7 @@ #include "watchdog.h" #include "EEPROMwrite.h" - - -#define VERSION_STRING "1.0.0 Beta 1" - - - +#define VERSION_STRING "1.0.0 RC1" // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html // http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes @@ -147,15 +140,11 @@ static bool home_all_axis = true; static float feedrate = 1500.0, next_feedrate, saved_feedrate; static long gcode_N, gcode_LastN; - - 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 uint8_t fanpwm=0; - - static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; static bool fromsd[BUFSIZE]; static int bufindr = 0; @@ -224,6 +213,7 @@ void enquecommand(const char *cmd) buflen += 1; } } + void setup_photpin() { #ifdef PHOTOGRAPH_PIN @@ -254,12 +244,6 @@ void suicide() #endif } -long millis_diff(unsigned long starttime) { - unsigned long difftime = millis() - starttime; - if (difftime > 0x8000) difftime += 0x8000; - return difftime; -} - void setup() { setup_powerhold(); @@ -332,7 +316,6 @@ void loop() LCD_STATUS; } - void get_command() { while( MSerial.available() > 0 && buflen < BUFSIZE) { @@ -556,9 +539,9 @@ void process_commands() if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait st_synchronize(); -// codenum += millis(); // keep track of when we started waiting + codenum += millis(); // keep track of when we started waiting previous_millis_cmd = millis(); - while(millis_diff(previous_millis_cmd) < codenum ){ + while(millis() < codenum ){ manage_heater(); } break; @@ -795,7 +778,7 @@ void process_commands() #if (TEMP_0_PIN > -1) SERIAL_PROTOCOLPGM("ok T:"); SERIAL_PROTOCOL(degHotend(tmp_extruder)); - #if TEMP_BED_PIN > -1 + #if TEMP_BED_PIN > -1 SERIAL_PROTOCOLPGM(" B:"); SERIAL_PROTOCOL(degBed()); #endif //TEMP_BED_PIN @@ -849,11 +832,11 @@ void process_commands() /* 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 > -1 && (millis_diff(residencyStart) < TEMP_RESIDENCY_TIME*1000) )) { + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { #else while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { #endif //TEMP_RESIDENCY_TIME - if(millis_diff(codenum) > 1000 ) + if((millis() - codenum) > 1000 ) { //Print Temp Reading and remaining time every 1 second while heating up/cooling down SERIAL_PROTOCOLPGM("T:"); SERIAL_PROTOCOL( degHotend(tmp_extruder) ); @@ -863,7 +846,7 @@ void process_commands() SERIAL_PROTOCOLPGM(" W:"); if(residencyStart > -1) { - codenum = TEMP_RESIDENCY_TIME - (millis_diff(residencyStart) / 1000); + codenum = TEMP_RESIDENCY_TIME - ((millis() - residencyStart) / 1000); SERIAL_PROTOCOLLN( codenum ); } else @@ -901,7 +884,7 @@ void process_commands() codenum = millis(); while(isHeatingBed()) { - if( millis_diff(codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + if(( millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. { float tt=degHotend(active_extruder); SERIAL_PROTOCOLPGM("T:"); @@ -971,6 +954,7 @@ void process_commands() 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(); @@ -1299,11 +1283,11 @@ void prepare_arc_move(char isclockwise) { void manage_inactivity(byte debug) { - if( millis_diff(previous_millis_cmd) > max_inactive_time ) + if( (millis() - previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); if(stepper_inactive_time) - if( millis_diff(last_stepperdisabled_time) > stepper_inactive_time ) + if( (millis() - last_stepperdisabled_time) > stepper_inactive_time ) { if(previous_millis_cmd>last_stepperdisabled_time) last_stepperdisabled_time=previous_millis_cmd; @@ -1315,7 +1299,7 @@ void manage_inactivity(byte debug) } } #ifdef EXTRUDER_RUNOUT_PREVENT - if( millis_diff(previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) + if( (millis() - previous_millis_cmd) > EXTRUDER_RUNOUT_SECONDS*1000 ) if(degHotend(active_extruder)>EXTRUDER_RUNOUT_MINTEMP) { bool oldstatus=READ(E0_ENABLE_PIN); diff --git a/README.md b/README.md index 0beb13fe58..6f04764c94 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ WARNING: -------- -THIS IS THE BETA 1 FOR MARLIN 1.0.0 +THIS IS RELEASE CANDIDATE 1 FOR MARLIN 1.0.0 + +The configuration is now split in two files +Configuration.h for the normal settings +Configuration_adv.h for the advanced settings Quick Information =================== From bdb70c050948392004f104402349c08a85cae0eb Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Wed, 8 Feb 2012 18:38:45 +0100 Subject: [PATCH 190/228] Warning for 10k thermistor --- Marlin/Configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index c1bcc0fae6..fe79a9c396 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -30,7 +30,7 @@ // 1 is 100k thermistor // 2 is 200k thermistor // 3 is mendel-parts thermistor -// 4 is 10k thermistor +// 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !! // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 From da040fd3936e59f9d808a126111708ff500343fa Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Thu, 9 Feb 2012 17:19:45 +0100 Subject: [PATCH 191/228] Fixed ultimaker heater 1 pins. (Thanks daid) --- Marlin/pins.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Marlin/pins.h b/Marlin/pins.h index 9ff7dd94a7..2a713c9899 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -561,10 +561,8 @@ #define HEATER_0_PIN 2 #define TEMP_0_PIN 8 -#define EXTRUDER_1_HEATER_PIN 3 -#define EXTRUDER_1_TEMPERATURE_PIN 10 -#define HEATER_1_PIN 51 -#define TEMP_1_PIN 3 +#define HEATER_1_PIN 3 +#define TEMP_1_PIN 9 #define HEATER_2_PIN -1 #define TEMP_2_PIN -1 From 9173a5713baae97f7bfa1cbb168b2ae8d1307245 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Thu, 9 Feb 2012 19:27:45 +0100 Subject: [PATCH 192/228] Teensylu support. --- Marlin/Configuration.h | 2 +- Marlin/Marlin.h | 14 +++++++----- Marlin/Marlin.pde | 8 +++---- Marlin/MarlinSerial.cpp | 11 +++------- Marlin/MarlinSerial.h | 7 +++--- Marlin/SdBaseFile.cpp | 48 ++++++++++++++++++++--------------------- Marlin/SdFatUtil.cpp | 4 ++-- Marlin/fastio.h | 2 +- Marlin/stepper.cpp | 6 ++++-- 9 files changed, 50 insertions(+), 52 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index fe79a9c396..9e14a47fc3 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -171,7 +171,7 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 -//#define SDSUPPORT // Enable SD Card Support in Hardware Console +#define SDSUPPORT // Enable SD Card Support in Hardware Console //#define ULTIPANEL #ifdef ULTIPANEL diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 78739af246..818c6ffe6c 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -46,7 +46,11 @@ #include "WString.h" - +#if MOTHERBOARD == 8 // Teensylu + #define SERIAL Serial +#else + #define SERIAL 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 @@ -59,10 +63,10 @@ //#define MYPGM(s) (__extension__({static prog_char __c[] = (s); &__c[0];})) //this does not work but hides the warnings -#define SERIAL_PROTOCOL(x) MSerial.print(x); +#define SERIAL_PROTOCOL(x) SERIAL.print(x); #define SERIAL_PROTOCOLPGM(x) serialprintPGM(MYPGM(x)); -#define SERIAL_PROTOCOLLN(x) {MSerial.print(x);MSerial.write('\n');} -#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(MYPGM(x));MSerial.write('\n');} +#define SERIAL_PROTOCOLLN(x) {SERIAL.print(x);SERIAL.write('\n');} +#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(MYPGM(x));SERIAL.write('\n');} const prog_char errormagic[] PROGMEM ="Error:"; @@ -89,7 +93,7 @@ FORCE_INLINE void serialprintPGM(const char *str) char ch=pgm_read_byte(str); while(ch) { - MSerial.write(ch); + SERIAL.write(ch); ch=pgm_read_byte(++str); } } diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 57ededa2ef..5c20bd657d 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -247,7 +247,7 @@ void suicide() void setup() { setup_powerhold(); - MSerial.begin(BAUDRATE); + SERIAL.begin(BAUDRATE); SERIAL_ECHO_START; SERIAL_ECHOLNPGM(VERSION_STRING); SERIAL_PROTOCOLLNPGM("start"); @@ -318,8 +318,8 @@ void loop() void get_command() { - while( MSerial.available() > 0 && buflen < BUFSIZE) { - serial_char = MSerial.read(); + while( SERIAL.available() > 0 && buflen < BUFSIZE) { + serial_char = SERIAL.read(); if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) { if(!serial_count) return; //if empty line @@ -1209,7 +1209,7 @@ void process_commands() void FlushSerialRequestResend() { //char cmdbuffer[bufindr][100]="Resend:"; - MSerial.flush(); + SERIAL.flush(); SERIAL_PROTOCOLPGM("Resend:"); SERIAL_PROTOCOLLN(gcode_LastN + 1); ClearToSend(); diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index 7175561e23..e369800b89 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -23,20 +23,15 @@ #include "Marlin.h" #include "MarlinSerial.h" +#if MOTHERBOARD != 8 // !teensylu // this next line disables the entire HardwareSerial.cpp, // this is so I can support Attiny series and any other chip without a uart #if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) - - - - - #if defined(UBRRH) || defined(UBRR0H) ring_buffer rx_buffer = { { 0 }, 0, 0 }; #endif - FORCE_INLINE void store_char(unsigned char c) { int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE; @@ -324,11 +319,11 @@ void MarlinSerial::printFloat(double number, uint8_t digits) remainder -= toPrint; } } - // Preinstantiate Objects ////////////////////////////////////////////////////// + MarlinSerial MSerial; - #endif // whole file +#endif //teensylu diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 71823de8f1..8525cba288 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -31,7 +31,7 @@ #define BYTE 0 - +#if MOTHERBOARD != 8 // ! teensylu // Define constants and variables for buffering incoming serial data. We're // using a ring buffer (I think), in which rx_buffer_head is the index of the // location to which to write the next incoming character and rx_buffer_tail @@ -144,8 +144,7 @@ class MarlinSerial //: public Stream void println(void); }; -#if defined(UBRRH) || defined(UBRR0H) - extern MarlinSerial MSerial; -#endif +extern MarlinSerial MSerial; +#endif // ! teensylu #endif diff --git a/Marlin/SdBaseFile.cpp b/Marlin/SdBaseFile.cpp index f8dc83adeb..450c9f327f 100644 --- a/Marlin/SdBaseFile.cpp +++ b/Marlin/SdBaseFile.cpp @@ -18,8 +18,6 @@ * . */ -#define SERIAL MSerial - #include "Marlin.h" #ifdef SDSUPPORT @@ -345,38 +343,38 @@ int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) { && DIR_IS_FILE_OR_SUBDIR(&dir)) break; } // indent for dir level - for (uint8_t i = 0; i < indent; i++) MSerial.write(' '); + for (uint8_t i = 0; i < indent; i++) SERIAL.write(' '); // print name for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - MSerial.write('.'); + SERIAL.write('.'); w++; } - MSerial.write(dir.name[i]); + SERIAL.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir)) { - MSerial.write('/'); + SERIAL.write('/'); w++; } if (flags & (LS_DATE | LS_SIZE)) { - while (w++ < 14) MSerial.write(' '); + while (w++ < 14) SERIAL.write(' '); } // print modify date/time if requested if (flags & LS_DATE) { - MSerial.write(' '); + SERIAL.write(' '); printFatDate( dir.lastWriteDate); - MSerial.write(' '); + SERIAL.write(' '); printFatTime( dir.lastWriteTime); } // print size if requested if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) { - MSerial.write(' '); - MSerial.print(dir.fileSize); + SERIAL.write(' '); + SERIAL.print(dir.fileSize); } - MSerial.println(); + SERIAL.println(); return DIR_IS_FILE(&dir) ? 1 : 2; } //------------------------------------------------------------------------------ @@ -947,26 +945,26 @@ void SdBaseFile::printDirName(const dir_t& dir, for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - MSerial.write('.'); + SERIAL.write('.'); w++; } - MSerial.write(dir.name[i]); + SERIAL.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir) && printSlash) { - MSerial.write('/'); + SERIAL.write('/'); w++; } while (w < width) { - MSerial.write(' '); + SERIAL.write(' '); w++; } } //------------------------------------------------------------------------------ // print uint8_t with width 2 static void print2u( uint8_t v) { - if (v < 10) MSerial.write('0'); - MSerial.print(v, DEC); + if (v < 10) SERIAL.write('0'); + SERIAL.print(v, DEC); } //------------------------------------------------------------------------------ /** %Print a directory date field to Serial. @@ -985,10 +983,10 @@ static void print2u( uint8_t v) { * \param[in] fatDate The date field from a directory entry. */ void SdBaseFile::printFatDate(uint16_t fatDate) { - MSerial.print(FAT_YEAR(fatDate)); - MSerial.write('-'); + SERIAL.print(FAT_YEAR(fatDate)); + SERIAL.write('-'); print2u( FAT_MONTH(fatDate)); - MSerial.write('-'); + SERIAL.write('-'); print2u( FAT_DAY(fatDate)); } @@ -1002,9 +1000,9 @@ void SdBaseFile::printFatDate(uint16_t fatDate) { */ void SdBaseFile::printFatTime( uint16_t fatTime) { print2u( FAT_HOUR(fatTime)); - MSerial.write(':'); + SERIAL.write(':'); print2u( FAT_MINUTE(fatTime)); - MSerial.write(':'); + SERIAL.write(':'); print2u( FAT_SECOND(fatTime)); } //------------------------------------------------------------------------------ @@ -1016,7 +1014,7 @@ void SdBaseFile::printFatTime( uint16_t fatTime) { bool SdBaseFile::printName() { char name[13]; if (!getFilename(name)) return false; - MSerial.print(name); + SERIAL.print(name); return true; } //------------------------------------------------------------------------------ @@ -1790,4 +1788,4 @@ void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT #endif // ALLOW_DEPRECATED_FUNCTIONS -#endif \ No newline at end of file +#endif diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp index ffbcba0c69..965f6ec218 100644 --- a/Marlin/SdFatUtil.cpp +++ b/Marlin/SdFatUtil.cpp @@ -48,7 +48,7 @@ int SdFatUtil::FreeRam() { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::print_P( PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) MSerial.write(c); + for (uint8_t c; (c = pgm_read_byte(str)); str++) SERIAL.write(c); } //------------------------------------------------------------------------------ /** %Print a string in flash memory followed by a CR/LF. @@ -58,7 +58,7 @@ void SdFatUtil::print_P( PGM_P str) { */ void SdFatUtil::println_P( PGM_P str) { print_P( str); - MSerial.println(); + SERIAL.println(); } //------------------------------------------------------------------------------ /** %Print a string in flash memory to Serial. diff --git a/Marlin/fastio.h b/Marlin/fastio.h index 5188a0681a..42f4ebb4f7 100644 --- a/Marlin/fastio.h +++ b/Marlin/fastio.h @@ -1928,7 +1928,7 @@ pins #endif -#if defined (__AVR_AT90USB1287__) +#if defined (__AVR_AT90USB1287__) || defined (__AVR_AT90USB1286__) // SPI #define SCK DIO9 #define MISO DIO11 diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 26c265e532..994683f5d1 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -254,7 +254,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { timer = (unsigned short)pgm_read_word_near(table_address); timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); } - if(timer < 100) { timer = 100; MSerial.print("Steprate to high : "); MSerial.println(step_rate); }//(20kHz this should never happen) + if(timer < 100) { timer = 100; SERIAL.print("Steprate to high : "); SERIAL.println(step_rate); }//(20kHz this should never happen) return timer; } @@ -439,7 +439,9 @@ ISR(TIMER1_COMPA_vect) for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) - MSerial.checkRx(); // Check for serial chars. + #if MOTHERBOARD != 8 // !teensylu + MSerial.checkRx(); // Check for serial chars. + #endif #ifdef ADVANCE counter_e += current_block->steps_e; From 598eb1d4f16beda0f0cfc796aca1b03a25708047 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Thu, 9 Feb 2012 19:38:53 +0100 Subject: [PATCH 193/228] Fixed compilation for gcc-4.6.2 with avr-lib-1.8.0 (thanks daid) --- Marlin/Marlin.h | 10 +-- Marlin/Marlin.pde | 2 +- Marlin/speed_lookuptable.h | 150 ++++++++++++++++++------------------- 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 818c6ffe6c..821324c13f 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -58,8 +58,8 @@ // //#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) 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 @@ -69,8 +69,8 @@ #define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(MYPGM(x));SERIAL.write('\n');} -const prog_char errormagic[] PROGMEM ="Error:"; -const prog_char echomagic[] PROGMEM ="echo:"; +const char errormagic[] PROGMEM ="Error:"; +const char echomagic[] PROGMEM ="echo:"; #define SERIAL_ERROR_START serialprintPGM(errormagic); #define SERIAL_ERROR(x) SERIAL_PROTOCOL(x) #define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 5c20bd657d..dcd600468d 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -164,7 +164,7 @@ const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 //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*1000; +static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l; static unsigned long last_stepperdisabled_time=30*1000; //first release check after 30 seconds static unsigned long starttime=0; diff --git a/Marlin/speed_lookuptable.h b/Marlin/speed_lookuptable.h index ab3a076f14..0c326d6409 100644 --- a/Marlin/speed_lookuptable.h +++ b/Marlin/speed_lookuptable.h @@ -1,76 +1,76 @@ -#ifndef SPEED_LOOKUPTABLE_H -#define SPEED_LOOKUPTABLE_H - -#include "Marlin.h" - -uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ -{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, -{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, -{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, -{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8}, -{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5}, -{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3}, -{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2}, -{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2}, -{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1}, -{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1}, -{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1}, -{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1}, -{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0}, -{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1}, -{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0}, -{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1}, -{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0}, -{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0}, -{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0}, -{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1}, -{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0}, -{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0}, -{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0}, -{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0}, -{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0}, -{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0}, -{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0}, -{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1}, -{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0}, -{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0}, -{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, -{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0} -}; - -uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ -{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, -{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, -{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, -{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198}, -{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132}, -{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94}, -{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71}, -{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55}, -{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44}, -{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36}, -{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30}, -{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25}, -{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22}, -{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18}, -{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16}, -{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15}, -{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13}, -{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11}, -{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10}, -{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9}, -{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8}, -{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8}, -{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7}, -{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7}, -{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6}, -{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5}, -{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5}, -{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5}, -{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4}, -{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4}, -{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4}, -{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3} -}; - +#ifndef SPEED_LOOKUPTABLE_H +#define SPEED_LOOKUPTABLE_H + +#include "Marlin.h" + +const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ +{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, +{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, +{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14}, +{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8}, +{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5}, +{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3}, +{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2}, +{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2}, +{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1}, +{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1}, +{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1}, +{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1}, +{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0}, +{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1}, +{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0}, +{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1}, +{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0}, +{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0}, +{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0}, +{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1}, +{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0}, +{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0}, +{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0}, +{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0}, +{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0}, +{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0}, +{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0}, +{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1}, +{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0}, +{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0}, +{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0}, +{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0} +}; + +const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ +{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894}, +{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657}, +{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331}, +{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198}, +{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132}, +{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94}, +{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71}, +{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55}, +{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44}, +{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36}, +{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30}, +{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25}, +{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22}, +{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18}, +{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16}, +{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15}, +{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13}, +{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11}, +{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10}, +{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9}, +{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8}, +{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8}, +{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7}, +{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7}, +{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6}, +{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5}, +{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5}, +{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5}, +{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4}, +{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4}, +{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4}, +{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3} +}; + #endif From 6ef8459494cd5ffdc1b2098f81a8346e006c8657 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Thu, 9 Feb 2012 19:53:06 +0100 Subject: [PATCH 194/228] Corrected distance calculation. (thanks jv4779) --- Marlin/planner.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 85c82aecc0..2eb0733330 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -517,8 +517,11 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; - block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + - square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); + if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { + block->millimeters = delta_mm[E_AXIS]; + } else { + block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); + } float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. @@ -527,9 +530,6 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 - - - if (block->steps_e == 0) { if(feed_rate Date: Thu, 9 Feb 2012 20:26:17 +0100 Subject: [PATCH 195/228] Print configuration.h version during startup (thanks hairykiwi) --- Marlin/Configuration.h | 6 ++++++ Marlin/Marlin.pde | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 9e14a47fc3..7288e8fb56 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -5,6 +5,12 @@ // Advanced settings can be found in Configuration_adv.h // BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration +//User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. +//Implementation of an idea by Prof Braino to inform user that any changes made +//to THIS file by the user have been successfully uploaded into firmware. +#define STRING_VERSION_CONFIG_H "2012-02-08j" //Personal revision number for changes to THIS file. +#define STRING_CONFIG_H_AUTHOR "username" //Who made the changes. + // This determines the communication speed of the printer #define BAUDRATE 250000 //#define BAUDRATE 115200 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index dcd600468d..5b4bce9b41 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -248,10 +248,20 @@ void setup() { setup_powerhold(); SERIAL.begin(BAUDRATE); - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM(VERSION_STRING); SERIAL_PROTOCOLLNPGM("start"); SERIAL_ECHO_START; + SERIAL_ECHOPGM("Marlin: "); + SERIAL_ECHOLNPGM(VERSION_STRING); + #ifdef STRING_VERSION_CONFIG_H + #ifdef STRING_CONFIG_H_AUTHOR + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Configuration.h: "); + SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); + SERIAL_ECHOPGM(" | Author: "); + SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); + #endif + #endif + SERIAL_ECHO_START; SERIAL_ECHOPGM("Free Memory:"); SERIAL_ECHO(freeMemory()); SERIAL_ECHOPGM(" PlannerBufferBytes:"); From f87c80889fe967ea883f96d2eed0f82398d8a3dd Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Thu, 9 Feb 2012 20:54:49 +0100 Subject: [PATCH 196/228] Fixed M109 timer overflow (reported by triffid) --- Marlin/Marlin.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 5b4bce9b41..b2a9065f98 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -842,7 +842,7 @@ void process_commands() /* 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 > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000l) ) { #else while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) { #endif //TEMP_RESIDENCY_TIME From d47a3e5950ec8dc129c8939ae8a9acdf32580134 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Thu, 9 Feb 2012 21:02:01 +0100 Subject: [PATCH 197/228] Changed check i mtion_conrol if (millimeters_of_travel == 0.0) => if (millimeters_of_travel < 0.001) (thanks mooselake) --- Marlin/motion_control.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index ab403e9812..a24b2b782c 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -45,7 +45,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 if (isclockwise) { angular_travel -= 2*M_PI; } float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel)); - if (millimeters_of_travel == 0.0) { return; } + if (millimeters_of_travel < 0.001) { return; } uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT); /* // Multiply inverse feed_rate to compensate for the fact that this movement is approximated From 2a77c84c8f673862d93c7734588e6009376169d8 Mon Sep 17 00:00:00 2001 From: daid Date: Sat, 11 Feb 2012 16:02:47 +0100 Subject: [PATCH 198/228] Updated SERIAL define to MYSERIAL, because Arduino 1.0 defines SERIAL as 0. --- Marlin/Marlin.h | 12 ++++++------ Marlin/Marlin.pde | 8 ++++---- Marlin/SdBaseFile.cpp | 44 +++++++++++++++++++++---------------------- Marlin/SdFatUtil.cpp | 4 ++-- Marlin/stepper.cpp | 2 +- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 821324c13f..ffa3839a72 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -47,9 +47,9 @@ #include "WString.h" #if MOTHERBOARD == 8 // Teensylu - #define SERIAL Serial + #define MYSERIAL Serial #else - #define SERIAL MSerial + #define MYSERIAL MSerial #endif //this is a unfinsihed attemp to removes a lot of warning messages, see: @@ -63,10 +63,10 @@ //#define MYPGM(s) (__extension__({static prog_char __c[] = (s); &__c[0];})) //this does not work but hides the warnings -#define SERIAL_PROTOCOL(x) SERIAL.print(x); +#define SERIAL_PROTOCOL(x) MYSERIAL.print(x); #define SERIAL_PROTOCOLPGM(x) serialprintPGM(MYPGM(x)); -#define SERIAL_PROTOCOLLN(x) {SERIAL.print(x);SERIAL.write('\n');} -#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(MYPGM(x));SERIAL.write('\n');} +#define SERIAL_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');} +#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(MYPGM(x));MYSERIAL.write('\n');} const char errormagic[] PROGMEM ="Error:"; @@ -93,7 +93,7 @@ FORCE_INLINE void serialprintPGM(const char *str) char ch=pgm_read_byte(str); while(ch) { - SERIAL.write(ch); + MYSERIAL.write(ch); ch=pgm_read_byte(++str); } } diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index b2a9065f98..b16174c2dd 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -247,7 +247,7 @@ void suicide() void setup() { setup_powerhold(); - SERIAL.begin(BAUDRATE); + MYSERIAL.begin(BAUDRATE); SERIAL_PROTOCOLLNPGM("start"); SERIAL_ECHO_START; SERIAL_ECHOPGM("Marlin: "); @@ -328,8 +328,8 @@ void loop() void get_command() { - while( SERIAL.available() > 0 && buflen < BUFSIZE) { - serial_char = SERIAL.read(); + while( MYSERIAL.available() > 0 && buflen < BUFSIZE) { + serial_char = MYSERIAL.read(); if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) { if(!serial_count) return; //if empty line @@ -1219,7 +1219,7 @@ void process_commands() void FlushSerialRequestResend() { //char cmdbuffer[bufindr][100]="Resend:"; - SERIAL.flush(); + MYSERIAL.flush(); SERIAL_PROTOCOLPGM("Resend:"); SERIAL_PROTOCOLLN(gcode_LastN + 1); ClearToSend(); diff --git a/Marlin/SdBaseFile.cpp b/Marlin/SdBaseFile.cpp index 450c9f327f..b84efc8eaa 100644 --- a/Marlin/SdBaseFile.cpp +++ b/Marlin/SdBaseFile.cpp @@ -343,38 +343,38 @@ int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) { && DIR_IS_FILE_OR_SUBDIR(&dir)) break; } // indent for dir level - for (uint8_t i = 0; i < indent; i++) SERIAL.write(' '); + for (uint8_t i = 0; i < indent; i++) MYSERIAL.write(' '); // print name for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - SERIAL.write('.'); + MYSERIAL.write('.'); w++; } - SERIAL.write(dir.name[i]); + MYSERIAL.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir)) { - SERIAL.write('/'); + MYSERIAL.write('/'); w++; } if (flags & (LS_DATE | LS_SIZE)) { - while (w++ < 14) SERIAL.write(' '); + while (w++ < 14) MYSERIAL.write(' '); } // print modify date/time if requested if (flags & LS_DATE) { - SERIAL.write(' '); + MYSERIAL.write(' '); printFatDate( dir.lastWriteDate); - SERIAL.write(' '); + MYSERIAL.write(' '); printFatTime( dir.lastWriteTime); } // print size if requested if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) { - SERIAL.write(' '); - SERIAL.print(dir.fileSize); + MYSERIAL.write(' '); + MYSERIAL.print(dir.fileSize); } - SERIAL.println(); + MYSERIAL.println(); return DIR_IS_FILE(&dir) ? 1 : 2; } //------------------------------------------------------------------------------ @@ -945,26 +945,26 @@ void SdBaseFile::printDirName(const dir_t& dir, for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - SERIAL.write('.'); + MYSERIAL.write('.'); w++; } - SERIAL.write(dir.name[i]); + MYSERIAL.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir) && printSlash) { - SERIAL.write('/'); + MYSERIAL.write('/'); w++; } while (w < width) { - SERIAL.write(' '); + MYSERIAL.write(' '); w++; } } //------------------------------------------------------------------------------ // print uint8_t with width 2 static void print2u( uint8_t v) { - if (v < 10) SERIAL.write('0'); - SERIAL.print(v, DEC); + if (v < 10) MYSERIAL.write('0'); + MYSERIAL.print(v, DEC); } //------------------------------------------------------------------------------ /** %Print a directory date field to Serial. @@ -983,10 +983,10 @@ static void print2u( uint8_t v) { * \param[in] fatDate The date field from a directory entry. */ void SdBaseFile::printFatDate(uint16_t fatDate) { - SERIAL.print(FAT_YEAR(fatDate)); - SERIAL.write('-'); + MYSERIAL.print(FAT_YEAR(fatDate)); + MYSERIAL.write('-'); print2u( FAT_MONTH(fatDate)); - SERIAL.write('-'); + MYSERIAL.write('-'); print2u( FAT_DAY(fatDate)); } @@ -1000,9 +1000,9 @@ void SdBaseFile::printFatDate(uint16_t fatDate) { */ void SdBaseFile::printFatTime( uint16_t fatTime) { print2u( FAT_HOUR(fatTime)); - SERIAL.write(':'); + MYSERIAL.write(':'); print2u( FAT_MINUTE(fatTime)); - SERIAL.write(':'); + MYSERIAL.write(':'); print2u( FAT_SECOND(fatTime)); } //------------------------------------------------------------------------------ @@ -1014,7 +1014,7 @@ void SdBaseFile::printFatTime( uint16_t fatTime) { bool SdBaseFile::printName() { char name[13]; if (!getFilename(name)) return false; - SERIAL.print(name); + MYSERIAL.print(name); return true; } //------------------------------------------------------------------------------ diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp index 965f6ec218..1187ec5393 100644 --- a/Marlin/SdFatUtil.cpp +++ b/Marlin/SdFatUtil.cpp @@ -48,7 +48,7 @@ int SdFatUtil::FreeRam() { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::print_P( PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) SERIAL.write(c); + for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c); } //------------------------------------------------------------------------------ /** %Print a string in flash memory followed by a CR/LF. @@ -58,7 +58,7 @@ void SdFatUtil::print_P( PGM_P str) { */ void SdFatUtil::println_P( PGM_P str) { print_P( str); - SERIAL.println(); + MYSERIAL.println(); } //------------------------------------------------------------------------------ /** %Print a string in flash memory to Serial. diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 994683f5d1..6bd84b13f0 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -254,7 +254,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { timer = (unsigned short)pgm_read_word_near(table_address); timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); } - if(timer < 100) { timer = 100; SERIAL.print("Steprate to high : "); SERIAL.println(step_rate); }//(20kHz this should never happen) + if(timer < 100) { timer = 100; MYSERIAL.print("Steprate to high : "); MYSERIAL.println(step_rate); }//(20kHz this should never happen) return timer; } From b58eae7657990e59bd6154c9b2a826baa22d7f61 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 11 Feb 2012 18:36:42 +0100 Subject: [PATCH 199/228] Corrected e-length calculation in planner --- Marlin/planner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 2eb0733330..b895b95e52 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -518,7 +518,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { - block->millimeters = delta_mm[E_AXIS]; + block->millimeters = abs(delta_mm[E_AXIS]); } else { block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); } From 13e185d3302649b70bb5c23ecbb27bfe6b1163ba Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sat, 11 Feb 2012 23:22:16 +0100 Subject: [PATCH 200/228] removed unused HEATING_EARLY_FINISH_DEG_OFFSET Simplified stepper inactive time --- Marlin/Configuration_adv.h | 6 +----- Marlin/Marlin.pde | 19 ++++++++----------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 1bdbd1ac2c..a19747d145 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -25,9 +25,6 @@ // if CooldownNoWait is defined M109 will not wait for the cooldown to finish #define CooldownNoWait true -// Heating is finished if a temperature close to this degree shift is reached -#define HEATING_EARLY_FINISH_DEG_OFFSET 1 //Degree - //Do not wait for M109 to finish when printing from SD card //#define STOP_HEATING_WAIT_WHEN_SD_PRINTING @@ -85,7 +82,6 @@ //default stepper release if idle #define DEFAULT_STEPPER_DEACTIVE_TIME 60 -#define DEFAULT_STEPPER_DEACTIVE_COMMAND "M84 X Y E" //z stays powered #define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate #define DEFAULT_MINTRAVELFEEDRATE 0.0 @@ -112,7 +108,7 @@ #define SD_FINISHED_STEPPERRELEASE true //if sd support and the file is finished: disable steppers? -#define SD_FINISHED_RELEASECOMMAND "M84 X Y E" // no z because of layer shift. +#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 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index b16174c2dd..a4997f31cd 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -165,7 +165,6 @@ const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 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 last_stepperdisabled_time=30*1000; //first release check after 30 seconds static unsigned long starttime=0; static unsigned long stoptime=0; @@ -1296,16 +1295,15 @@ void manage_inactivity(byte debug) if( (millis() - previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); - if(stepper_inactive_time) - if( (millis() - last_stepperdisabled_time) > stepper_inactive_time ) - { - if(previous_millis_cmd>last_stepperdisabled_time) - last_stepperdisabled_time=previous_millis_cmd; - else + if(stepper_inactive_time) { + if( (millis() - previous_millis_cmd) > stepper_inactive_time ) { - if( (X_ENABLE_ON && (READ(X_ENABLE_PIN)!=0)) || (!X_ENABLE_ON && READ(X_ENABLE_PIN)==0) ) - enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); - last_stepperdisabled_time=millis(); + disable_x(); + disable_y(); + disable_z(); + disable_e0(); + disable_e1(); + disable_e2(); } } #ifdef EXTRUDER_RUNOUT_PREVENT @@ -1323,7 +1321,6 @@ void manage_inactivity(byte debug) destination[E_AXIS]=oldedes; plan_set_e_position(oldepos); previous_millis_cmd=millis(); - //enquecommand(DEFAULT_STEPPER_DEACTIVE_COMMAND); st_synchronize(); WRITE(E0_ENABLE_PIN,oldstatus); } From 7699f250e31e61fa09636914c8ee7f4a1f340927 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 12 Feb 2012 14:06:08 +0100 Subject: [PATCH 201/228] Fixed small merge bug --- Marlin/Marlin.pde | 1 - 1 file changed, 1 deletion(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 23ff730f39..07716fd35b 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1303,7 +1303,6 @@ void manage_inactivity(byte debug) disable_e0(); disable_e1(); disable_e2(); - #endif } } #ifdef EXTRUDER_RUNOUT_PREVENT From fa2e1be0ca890cd4112dbb951b9297bb38a42f2d Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 12 Feb 2012 17:38:54 +0100 Subject: [PATCH 202/228] changed default EXTRUDE_MINTEMP to 170. --- Marlin/Configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 7288e8fb56..f0d8913631 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -97,7 +97,7 @@ //this prevents dangerous Extruder moves, i.e. if the temperature is under the limit //can be software-disabled for whatever purposes by #define PREVENT_DANGEROUS_EXTRUDE -#define EXTRUDE_MINTEMP 190 +#define EXTRUDE_MINTEMP 170 #define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. //=========================================================================== From 018e04f3f87e049c48f25c3d29b63d01a0d1120c Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Thu, 23 Feb 2012 10:41:52 +0000 Subject: [PATCH 203/228] added fast home, windup setting --- Marlin/Configuration.h | 82 ++-- Marlin/Configuration.h~ | 203 ++++++++ Marlin/Configuration_adv.h | 10 +- Marlin/Configuration_adv.h~ | 221 +++++++++ Marlin/EEPROMwrite.h | 4 + Marlin/Marlin.pde | 10 +- Marlin/fastio.h | 2 +- Marlin/pins.h | 6 +- Marlin/pins.h~ | 905 ++++++++++++++++++++++++++++++++++++ Marlin/temperature.cpp | 5 +- Marlin/temperature.h | 1 + Marlin/thermistortables.h | 60 +++ 12 files changed, 1459 insertions(+), 50 deletions(-) create mode 100644 Marlin/Configuration.h~ create mode 100644 Marlin/Configuration_adv.h~ create mode 100644 Marlin/pins.h~ diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f0d8913631..25e7cf20cf 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -12,8 +12,8 @@ #define STRING_CONFIG_H_AUTHOR "username" //Who made the changes. // This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 +//#define BAUDRATE 250000 +#define BAUDRATE 115200 //// The following define selects which electronics board you have. Please choose the one that matches your setup // MEGA/RAMPS up to 1.2 = 3, @@ -23,7 +23,7 @@ // Ultimaker = 7, // Teensylu = 8, // Gen3+ =9 -#define MOTHERBOARD 7 +#define MOTHERBOARD 62 //=========================================================================== //=============================Thermal Settings ============================ @@ -40,30 +40,32 @@ // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 +// 100 is 100k GE Sensing AL03006-58.2K-97-G1 +// 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT -#define TEMP_SENSOR_0 -1 +#define TEMP_SENSOR_0 100 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 0 +#define TEMP_SENSOR_BED 101 // Actual temperature must be close to target for this long before M109 returns success -#define TEMP_RESIDENCY_TIME 30 // (seconds) -#define TEMP_HYSTERESIS 3 // (C°) range of +/- temperatures considered "close" to the target one +#define TEMP_RESIDENCY_TIME 10 // (seconds) +#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one // The minimal temperature defines the temperature below which the heater will not be enabled It is used // to check that the wiring to the thermistor is not broken. // Otherwise this would lead to the heater being powered on all the time. -#define HEATER_0_MINTEMP 5 -#define HEATER_1_MINTEMP 5 -#define HEATER_2_MINTEMP 5 -#define BED_MINTEMP 5 +#define HEATER_0_MINTEMP 1 +//#define HEATER_1_MINTEMP 5 +//#define HEATER_2_MINTEMP 5 +#define BED_MINTEMP 1 // When temperature exceeds max temp, your heater will be switched off. // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 275 -#define HEATER_1_MAXTEMP 275 -#define HEATER_2_MAXTEMP 275 +#define HEATER_0_MAXTEMP 399 +//#define HEATER_1_MAXTEMP 275 +//#define HEATER_2_MAXTEMP 275 #define BED_MAXTEMP 150 // PID settings: @@ -73,21 +75,26 @@ #ifdef PIDTEMP //#define PID_DEBUG // Sends debug data to the serial port. //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term + #define PID_INTEGRAL_DRIVE_MAX 130 //limit for the integral term #define K1 0.95 //smoothing factor withing the PID - #define PID_dT 0.128 //sampling period of the PID + #define PID_dT 0.122 //sampling period of the PID // If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it // Ultimaker - #define DEFAULT_Kp 22.2 - #define DEFAULT_Ki (1.25*PID_dT) - #define DEFAULT_Kd (99/PID_dT) +// #define DEFAULT_Kp 22.2 +// #define DEFAULT_Ki (1.25*PID_dT) +// #define DEFAULT_Kd (99/PID_dT) // Makergear // #define DEFAULT_Kp 7.0 // #define DEFAULT_Ki 0.1 // #define DEFAULT_Kd 12 +// RepRapPro Huxley + #define DEFAULT_Kp 3.0 + #define DEFAULT_Ki (2*PID_dT) + #define DEFAULT_Kd (80/PID_dT) + // Mendel Parts V9 on 12V // #define DEFAULT_Kp 63.0 // #define DEFAULT_Ki (2.25*PID_dT) @@ -108,9 +115,9 @@ #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 @@ -121,15 +128,15 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // Disables axis when it's not being used. #define DISABLE_X false #define DISABLE_Y false -#define DISABLE_Z false +#define DISABLE_Z true #define DISABLE_E false // For all extruders #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true +#define INVERT_E0_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E2_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false // ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -139,22 +146,23 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define min_software_endstops true //If true, axis won't move to coordinates less than zero. #define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 205 -#define Y_MAX_LENGTH 205 -#define Z_MAX_LENGTH 200 +#define X_MAX_LENGTH 150 +#define Y_MAX_LENGTH 148 +#define Z_MAX_LENGTH 100 //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) +#define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) +#define FAST_HOME_FEEDRATE {80*60, 80*60, 4*60, 0} // set the homing speeds (mm/min) // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker +#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +#define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts +#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for r retracts // #define DEFAULT_XYJERK 20.0 // (mm/sec) @@ -170,10 +178,10 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // 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. //define this to enable eeprom support -//#define EEPROM_SETTINGS +#define EEPROM_SETTINGS //to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: // please keep turned on if you can. -//#define EEPROM_CHITCHAT +#define EEPROM_CHITCHAT //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 diff --git a/Marlin/Configuration.h~ b/Marlin/Configuration.h~ new file mode 100644 index 0000000000..f0d8913631 --- /dev/null +++ b/Marlin/Configuration.h~ @@ -0,0 +1,203 @@ +#ifndef __CONFIGURATION_H +#define __CONFIGURATION_H + +// This configurtion file contains the basic settings. +// Advanced settings can be found in Configuration_adv.h +// BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration + +//User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. +//Implementation of an idea by Prof Braino to inform user that any changes made +//to THIS file by the user have been successfully uploaded into firmware. +#define STRING_VERSION_CONFIG_H "2012-02-08j" //Personal revision number for changes to THIS file. +#define STRING_CONFIG_H_AUTHOR "username" //Who made the changes. + +// This determines the communication speed of the printer +#define BAUDRATE 250000 +//#define BAUDRATE 115200 + +//// The following define selects which electronics board you have. Please choose the one that matches your setup +// MEGA/RAMPS up to 1.2 = 3, +// RAMPS 1.3 = 33 +// Gen6 = 5, +// Sanguinololu 1.2 and above = 62 +// Ultimaker = 7, +// Teensylu = 8, +// Gen3+ =9 +#define MOTHERBOARD 7 + +//=========================================================================== +//=============================Thermal Settings ============================ +//=========================================================================== + +//// Temperature sensor settings: +// -2 is thermocouple with MAX6675 (only for sensor 0) +// -1 is thermocouple with AD595 +// 0 is not used +// 1 is 100k thermistor +// 2 is 200k thermistor +// 3 is mendel-parts thermistor +// 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !! +// 5 is ParCan supplied 104GT-2 100K +// 6 is EPCOS 100k +// 7 is 100k Honeywell thermistor 135-104LAG-J01 + +#define TEMP_SENSOR_0 -1 +#define TEMP_SENSOR_1 0 +#define TEMP_SENSOR_2 0 +#define TEMP_SENSOR_BED 0 + +// Actual temperature must be close to target for this long before M109 returns success +#define TEMP_RESIDENCY_TIME 30 // (seconds) +#define TEMP_HYSTERESIS 3 // (C°) range of +/- temperatures considered "close" to the target one + +// The minimal temperature defines the temperature below which the heater will not be enabled It is used +// to check that the wiring to the thermistor is not broken. +// Otherwise this would lead to the heater being powered on all the time. +#define HEATER_0_MINTEMP 5 +#define HEATER_1_MINTEMP 5 +#define HEATER_2_MINTEMP 5 +#define BED_MINTEMP 5 + +// When temperature exceeds max temp, your heater will be switched off. +// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! +// You should use MINTEMP for thermistor short/failure protection. +#define HEATER_0_MAXTEMP 275 +#define HEATER_1_MAXTEMP 275 +#define HEATER_2_MAXTEMP 275 +#define BED_MAXTEMP 150 + +// PID settings: +// Comment the following line to disable PID and enable bang-bang. +#define PIDTEMP +#define PID_MAX 255 // limits current to nozzle; 255=full current +#ifdef PIDTEMP + //#define PID_DEBUG // Sends debug data to the serial port. + //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % + #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term + #define K1 0.95 //smoothing factor withing the PID + #define PID_dT 0.128 //sampling period of the PID + +// If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it +// Ultimaker + #define DEFAULT_Kp 22.2 + #define DEFAULT_Ki (1.25*PID_dT) + #define DEFAULT_Kd (99/PID_dT) + +// Makergear +// #define DEFAULT_Kp 7.0 +// #define DEFAULT_Ki 0.1 +// #define DEFAULT_Kd 12 + +// Mendel Parts V9 on 12V +// #define DEFAULT_Kp 63.0 +// #define DEFAULT_Ki (2.25*PID_dT) +// #define DEFAULT_Kd (440/PID_dT) +#endif // PIDTEMP + +//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit +//can be software-disabled for whatever purposes by +#define PREVENT_DANGEROUS_EXTRUDE +#define EXTRUDE_MINTEMP 170 +#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. + +//=========================================================================== +//=============================Mechanical Settings=========================== +//=========================================================================== + +// Endstop Settings +#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors + +// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. +const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. + +// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 +#define X_ENABLE_ON 0 +#define Y_ENABLE_ON 0 +#define Z_ENABLE_ON 0 +#define E_ENABLE_ON 0 // For all extruders + +// Disables axis when it's not being used. +#define DISABLE_X false +#define DISABLE_Y false +#define DISABLE_Z false +#define DISABLE_E false // For all extruders + +#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false +#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false + +// ENDSTOP SETTINGS: +// Sets direction of endstops when homing; 1=MAX, -1=MIN +#define X_HOME_DIR -1 +#define Y_HOME_DIR -1 +#define Z_HOME_DIR -1 + +#define min_software_endstops true //If true, axis won't move to coordinates less than zero. +#define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. +#define X_MAX_LENGTH 205 +#define Y_MAX_LENGTH 205 +#define Z_MAX_LENGTH 200 + +//// MOVEMENT SETTINGS +#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E +#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts + +// +#define DEFAULT_XYJERK 20.0 // (mm/sec) +#define DEFAULT_ZJERK 0.4 // (mm/sec) + +//=========================================================================== +//=============================Additional Features=========================== +//=========================================================================== + +// EEPROM +// the microcontroller can store settings in the EEPROM, e.g. max velocity... +// 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. +//define this to enable eeprom support +//#define EEPROM_SETTINGS +//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: +// please keep turned on if you can. +//#define EEPROM_CHITCHAT + +//LCD and SD support +//#define ULTRA_LCD //general lcd support, also 16x2 +#define SDSUPPORT // Enable SD Card Support in Hardware Console + +//#define ULTIPANEL +#ifdef ULTIPANEL + //#define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 + #define LCD_HEIGHT 4 +#else //no panel but just lcd + #ifdef ULTRA_LCD + #define LCD_WIDTH 16 + #define LCD_HEIGHT 2 + #endif +#endif + +// M240 Triggers a camera by emulating a Canon RC-1 Remote +// Data from: http://www.doc-diy.net/photo/rc-1_hacked/ +// #define PHOTOGRAPH_PIN 23 + +#include "Configuration_adv.h" +#include "thermistortables.h" + +#endif //__CONFIGURATION_H diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index a19747d145..6e891cc4e8 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -31,7 +31,7 @@ #ifdef PIDTEMP // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. // if Kc is choosen well, the additional required power due to increased melting should be compensated. - #define PID_ADD_EXTRUSION_RATE + //#define PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) #endif @@ -53,7 +53,7 @@ // extruder run-out prevention. //if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded //#define EXTRUDER_RUNOUT_PREVENT -#define EXTRUDER_RUNOUT_MINTEMP 190 +#define EXTRUDER_RUNOUT_MINTEMP 175 #define EXTRUDER_RUNOUT_SECONDS 30. #define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament #define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed @@ -71,14 +71,14 @@ //#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats. //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again: -#define X_HOME_RETRACT_MM 5 -#define Y_HOME_RETRACT_MM 5 +#define X_HOME_RETRACT_MM 4 +#define Y_HOME_RETRACT_MM 4 #define Z_HOME_RETRACT_MM 1 #define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially. #define AXIS_RELATIVE_MODES {false, false, false, false} -#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) +#define MAX_STEP_FREQUENCY 50000 // Max step frequency for Ultimaker (5000 pps / half step) //default stepper release if idle #define DEFAULT_STEPPER_DEACTIVE_TIME 60 diff --git a/Marlin/Configuration_adv.h~ b/Marlin/Configuration_adv.h~ new file mode 100644 index 0000000000..a19747d145 --- /dev/null +++ b/Marlin/Configuration_adv.h~ @@ -0,0 +1,221 @@ +#ifndef __CONFIGURATION_ADV_H +#define __CONFIGURATION_ADV_H + +//=========================================================================== +//=============================Thermal Settings ============================ +//=========================================================================== + +// Select one of these only to define how the bed temp is read. +// +//#define BED_LIMIT_SWITCHING +#ifdef BED_LIMIT_SWITCHING + #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS +#endif +#define BED_CHECK_INTERVAL 5000 //ms + +//// Heating sanity check: +// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. +// It can be reset with another M104/M109 +//#define WATCHPERIOD 20000 //20 seconds + +// Wait for Cooldown +// This defines if the M109 call should not block if it is cooling down. +// example: From a current temp of 220, you set M109 S200. +// if CooldownNoWait is defined M109 will not wait for the cooldown to finish +#define CooldownNoWait true + +//Do not wait for M109 to finish when printing from SD card +//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING + +#ifdef PIDTEMP + // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. + // if Kc is choosen well, the additional required power due to increased melting should be compensated. + #define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) + #endif +#endif + + +//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode. +//The maximum buffered steps/sec of the extruder motor are called "se". +//You enter the autotemp mode by a M109 S T F +// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp +// you exit the value by any M109 without F* +// Also, if the temperature is set to a value 0 + #define THERMISTORHEATER_0 TEMP_SENSOR_0 + #define HEATER_0_USES_THERMISTOR +#endif +#if TEMP_SENSOR_1 > 0 + #define THERMISTORHEATER_1 TEMP_SENSOR_1 + #define HEATER_1_USES_THERMISTOR +#endif +#if TEMP_SENSOR_2 > 0 + #define THERMISTORHEATER_2 TEMP_SENSOR_2 + #define HEATER_2_USES_THERMISTOR +#endif +#if TEMP_SENSOR_BED > 0 + #define THERMISTORBED TEMP_SENSOR_BED + #define BED_USES_THERMISTOR +#endif +#if TEMP_SENSOR_0 == -1 + #define HEATER_0_USES_AD595 +#endif +#if TEMP_SENSOR_1 == -1 + #define HEATER_1_USES_AD595 +#endif +#if TEMP_SENSOR_2 == -1 + #define HEATER_2_USES_AD595 +#endif +#if TEMP_SENSOR_BED == -1 + #define BED_USES_AD595 +#endif +#if TEMP_SENSOR_0 == -2 + #define HEATER_0_USES_MAX6675 +#endif +#if TEMP_SENSOR_0 == 0 + #undef HEATER_0_MINTEMP + #undef HEATER_0_MAXTEMP +#endif +#if TEMP_SENSOR_1 == 0 + #undef HEATER_1_MINTEMP + #undef HEATER_1_MAXTEMP +#endif +#if TEMP_SENSOR_2 == 0 + #undef HEATER_2_MINTEMP + #undef HEATER_2_MAXTEMP +#endif +#if TEMP_SENSOR_BED == 0 + #undef BED_MINTEMP + #undef BED_MAXTEMP +#endif + + +#endif //__CONFIGURATION_ADV_H diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index bb25ae8960..776b1cfa70 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -60,6 +60,7 @@ inline void EEPROM_StoreSettings() EEPROM_writeAnything(i,Kp); EEPROM_writeAnything(i,Ki); EEPROM_writeAnything(i,Kd); + EEPROM_writeAnything(i,Ki_Max); #else EEPROM_writeAnything(i,3000); EEPROM_writeAnything(i,0); @@ -124,6 +125,7 @@ inline void EEPROM_printSettings() SERIAL_ECHOPAIR(" M301 P",Kp); SERIAL_ECHOPAIR(" I" ,Ki/PID_dT); SERIAL_ECHOPAIR(" D" ,Kd*PID_dT); + SERIAL_ECHOPAIR(" W" ,Ki_Max); SERIAL_ECHOLN(""); #endif #endif @@ -152,10 +154,12 @@ inline void EEPROM_RetrieveSettings(bool def=false) EEPROM_readAnything(i,max_z_jerk); #ifndef PIDTEMP float Kp,Ki,Kd; + int Ki_Max; #endif EEPROM_readAnything(i,Kp); EEPROM_readAnything(i,Ki); EEPROM_readAnything(i,Kd); + EEPROM_readAnything(i,Ki_Max); SERIAL_ECHO_START; SERIAL_ECHOLNPGM("Stored settings retreived:"); diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 07716fd35b..cb7aa1eaa2 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -121,6 +121,7 @@ CardReader card; #endif float homing_feedrate[] = HOMING_FEEDRATE; +float fast_home_feedrate[] = FAST_HOME_FEEDRATE; bool axis_relative_modes[] = AXIS_RELATIVE_MODES; volatile int feedmultiply=100; //100->1 200->2 int saved_feedmultiply; @@ -495,8 +496,8 @@ bool code_seen(char code) { \ current_position[LETTER##_AXIS] = 0; \ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \ - destination[LETTER##_AXIS] = 1.5 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ - feedrate = homing_feedrate[LETTER##_AXIS]; \ + destination[LETTER##_AXIS] = 1.1 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ + feedrate = fast_home_feedrate[LETTER##_AXIS]; \ plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ current_position[LETTER##_AXIS] = 0;\ @@ -572,7 +573,7 @@ void process_commands() 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; + destination[X_AXIS] = 1.1 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.1 * Y_MAX_LENGTH * Y_HOME_DIR; feedrate = homing_feedrate[X_AXIS]; if(homing_feedrate[Y_AXIS] Boards' menu. #endif +#endif #define X_STEP_PIN 15 #define X_DIR_PIN 21 @@ -531,7 +533,7 @@ #define LED_PIN -1 -#define FAN_PIN -1 +#define FAN_PIN -1 //12 #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -542,7 +544,7 @@ #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_BED_PIN 12 // (bed) +#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 diff --git a/Marlin/pins.h~ b/Marlin/pins.h~ new file mode 100644 index 0000000000..59f8fd5f3e --- /dev/null +++ b/Marlin/pins.h~ @@ -0,0 +1,905 @@ +#ifndef PINS_H +#define PINS_H + +#if MOTHERBOARD == 99 +#define KNOWN_BOARD 1 + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN -1 +#define X_MAX_PIN 16 + +#define Y_STEP_PIN 5 +#define Y_DIR_PIN 6 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 67 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 62 +#define Z_DIR_PIN 63 +#define Z_ENABLE_PIN -1 +#define Z_MIN_PIN 59 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 65 +#define E0_DIR_PIN 66 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 9 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 10 + +#endif /* 99 */ + +/**************************************************************************************** +* Arduino pin assignment +* +* ATMega168 +* +-\/-+ +* PC6 1| |28 PC5 (AI 5 / D19) +* (D 0) PD0 2| |27 PC4 (AI 4 / D18) +* (D 1) PD1 3| |26 PC3 (AI 3 / D17) +* (D 2) PD2 4| |25 PC2 (AI 2 / D16) +* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) +* (D 4) PD4 6| |23 PC0 (AI 0 / D14) +* VCC 7| |22 GND +* GND 8| |21 AREF +* PB6 9| |20 AVCC +* PB7 10| |19 PB5 (D 13) +* PWM+ (D 5) PD5 11| |18 PB4 (D 12) +* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +* (D 7) PD7 13| |16 PB2 (D 10) PWM +* (D 8) PB0 14| |15 PB1 (D 9) PWM +* +----+ +****************************************************************************************/ +#if MOTHERBOARD == 0 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega168__ +#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. +#endif + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 4 +#define X_MAX_PIN 9 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN 13 + +#define Z_STEP_PIN 19 +#define Z_DIR_PIN 18 +#define Z_ENABLE_PIN 5 +#define Z_MIN_PIN 17 +#define Z_MAX_PIN 16 + +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 15 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 +#endif + + + +/**************************************************************************************** +* Sanguino/RepRap Motherboard with direct-drive extruders +* +* ATMega644P +* +* +---\/---+ +* (D 0) PB0 1| |40 PA0 (AI 0 / D31) +* (D 1) PB1 2| |39 PA1 (AI 1 / D30) +* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +* RST 9| |32 AREF +* VCC 10| |31 GND +* GND 11| |30 AVCC +* XTAL2 12| |29 PC7 (D 23) +* XTAL1 13| |28 PC6 (D 22) +* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +* +--------+ +* +****************************************************************************************/ +#if MOTHERBOARD == 1 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 19 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PIN 29 +#define Z_DIR_PIN 30 +#define Z_ENABLE_PIN 31 +#define Z_MIN_PIN 2 +#define Z_MAX_PIN 1 + +#define E0_STEP_PIN 12 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN 3 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN 0 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 14 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 +/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ + + + +#endif + + +/**************************************************************************************** +* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* +* +****************************************************************************************/ +#if MOTHERBOARD == 2 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PINN 27 +#define Z_DIR_PINN 28 +#define Z_ENABLE_PIN 29 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 31 + +#define E0_STEP_PIN 17 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 4 +#define LED_PIN 0 + +#define SD_CARD_WRITE 2 +#define SD_CARD_DETECT 3 +#define SD_CARD_SELECT 4 + +//our RS485 pins +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 + +//pin for controlling the PSU. +#define PS_ON_PIN 14 + +#define FAN_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN -1 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#endif + +/**************************************************************************************** +* Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 33 +#define MOTHERBOARD 3 +#define RAMPS_V_1_3 +#endif +#if MOTHERBOARD == 3 +#define KNOWN_BOARD 1 + +//////////////////FIX THIS////////////// +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 +// #define RAMPS_V_1_3 +// #define RAMPS_V_1_0 + +#ifdef RAMPS_V_1_3 + +#define X_STEP_PIN 54 +#define X_DIR_PIN 55 +#define X_ENABLE_PIN 38 +#define X_MIN_PIN 3 +#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. + +#define Y_STEP_PIN 60 +#define Y_DIR_PIN 61 +#define Y_ENABLE_PIN 56 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN 15 //15 + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 62 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN 19 //19 + +#define E0_STEP_PIN 26 +#define E0_DIR_PIN 28 +#define E0_ENABLE_PIN 24 + +#define E1_STEP_PIN 36 +#define E1_DIR_PIN 34 +#define E1_ENABLE_PIN 30 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 4 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#define HEATER_0_PIN 10 // EXTRUDER 1 +#define HEATER_1_PIN 9 // EXTRUDER 2 +#define HEATER_2_PIN -1 // EXTRUDER 2 +#define TEMP_0_PIN 13 // ANALOG NUMBERING +#define TEMP_1_PIN 15 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING +#define HEATER_BED_PIN 8 // BED +#define TEMP_BED_PIN 14 // ANALOG NUMBERING + + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default + +#define X_STEP_PIN 26 +#define X_DIR_PIN 28 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 + +#define Y_STEP_PIN 38 +#define Y_DIR_PIN 40 +#define Y_ENABLE_PIN 36 +#define Y_MIN_PIN 16 +#define Y_MAX_PIN -1 //17 + +#define Z_STEP_PIN 44 +#define Z_DIR_PIN 46 +#define Z_ENABLE_PIN 42 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E0_STEP_PIN 32 +#define E0_DIR_PIN 34 +#define E0_ENABLE_PIN 30 + +#define SDPOWER 48 +#define SDSS 53 +#define LED_PIN 13 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + + + +#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 + #define HEATER_0_PIN 12 // RAMPS 1.0 + #define HEATER_BED_PIN -1 // RAMPS 1.0 + #define FAN_PIN 11 // RAMPS 1.0 +#else // RAMPS_V_1_1 or RAMPS_V_1_2 + #define HEATER_0_PIN 10 // RAMPS 1.1 + #define HEATER_BED_PIN 8 // RAMPS 1.1 + #define FAN_PIN 9 // RAMPS 1.1 +#endif +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#endif + +// SPI for Max6675 Thermocouple + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define MAX_SCK_PIN 52 + #define MAX_MISO_PIN 50 + #define MAX_MOSI_PIN 51 + #define MAX6675_SS 53 +#else + #define MAX6675_SS 49 +#endif + +#endif + +/**************************************************************************************** +* Duemilanove w/ ATMega328P pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 4 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega328P__ +#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 17 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 13 +#define Z_DIR_PIN 3 +#define Z_ENABLE_PIN 2 +#define Z_MIN_PIN 4 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN 5 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#endif + +/**************************************************************************************** +* Gen6 pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 5 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ + #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +//x axis pins + #define X_STEP_PIN 15 + #define X_DIR_PIN 18 + #define X_ENABLE_PIN 19 + #define X_MIN_PIN 20 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 25 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 27 + #define Z_DIR_PIN 28 + #define Z_ENABLE_PIN 29 + #define Z_MIN_PIN 30 + #define Z_MAX_PIN -1 + + //extruder pins + #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 + #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 + #define HEATER_1_PIN -1 + #define HEATER_2_PIN -1 + #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 + + #define SDPOWER -1 + #define SDSS 17 + #define LED_PIN -1 //changed @ rkoeppl 20110410 + #define FAN_PIN -1 //changed @ rkoeppl 20110410 + #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 + //our pin for debugging. + + #define DEBUG_PIN 0 + + //our RS485 pins + #define TX_ENABLE_PIN 12 + #define RX_ENABLE_PIN 13 + + +#endif + +/**************************************************************************************** +* Sanguinololu pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 62 +#define MOTHERBOARD 6 +#define SANGUINOLOLU_V_1_2 +#endif +#if MOTHERBOARD == 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#ifndef __AVR_ATmega1284P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 1 +#define E0_DIR_PIN 0 + +#define LED_PIN -1 + +#define FAN_PIN 12 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#ifdef SANGUINOLOLU_V_1_2 + +#define HEATER_BED_PIN 10 //12 // (bed) +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E0_ENABLE_PIN 14 + +#else + +#define HEATER_BED_PIN 14 // (bed) +#define X_ENABLE_PIN -1 +#define Y_ENABLE_PIN -1 +#define Z_ENABLE_PIN -1 +#define E0_ENABLE_PIN -1 + +#endif + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define SDPOWER -1 +#define SDSS 31 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 10 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define HEATER_1_PIN 3 +#define TEMP_1_PIN 9 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN 49 +#define E1_DIR_PIN 47 +#define E1_ENABLE_PIN 51 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 +#define SUICIDE_PIN 54 //PIN that has to be turned on right after start, to keep power flowing. + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + //buttons are attached to a shift register + #define SHIFT_CLK 38 + #define SHIFT_LD 42 + #define SHIFT_OUT 40 + #define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 5 + #define LCD_PINS_D4 6 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 20 + #define LCD_PINS_D7 19 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + +#endif + +#if MOTHERBOARD == 71 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment (Old electronics) +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 15 +#define X_MAX_PIN 14 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 17 +#define Y_MAX_PIN 16 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 19 +#define Z_MAX_PIN 18 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define HEATER_1_PIN 1 +#define TEMP_1_PIN 1 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN -1 +#define E1_DIR_PIN -1 +#define E1_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define SUICIDE_PIN -1 //PIN that has to be turned on right after start, to keep power flowing. + +#define LCD_PINS_RS 24 +#define LCD_PINS_ENABLE 22 +#define LCD_PINS_D4 36 +#define LCD_PINS_D5 34 +#define LCD_PINS_D6 32 +#define LCD_PINS_D7 30 + +#endif + +/**************************************************************************************** +* Teensylu 0.7 pin assingments (ATMEGA90USB) +* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! +****************************************************************************************/ +#if MOTHERBOARD == 8 +#define MOTHERBOARD 8 +#define KNOWN_BOARD 1 + + +#define X_STEP_PIN 0 +#define X_DIR_PIN 1 +#define X_ENABLE_PIN 39 +#define X_MIN_PIN 13 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 2 +#define Y_DIR_PIN 3 +#define Y_ENABLE_PIN 38 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 4 +#define Z_DIR_PIN 5 +#define Z_ENABLE_PIN 23 +#define Z_MIN_PIN 15 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 6 +#define E0_DIR_PIN 7 +#define E0_ENABLE_PIN 19 + + + +#define HEATER_0_PIN 21 // Extruder +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define HEATER_BED_PIN 20 // Bed +#define FAN_PIN 22 // Fan + +#define TEMP_0_PIN 7 // Extruder +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // Bed + +#define SDPOWER -1 +#define SDSS 8 +#define LED_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define ALARM_PIN -1 + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define SCK_PIN 9 + #define MISO_PIN 11 + #define MOSI_PIN 10 +#endif +#endif + +/**************************************************************************************** +* Gen3+ pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 9 +#define MOTHERBOARD 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_MIN_PIN 20 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 27 +#define Z_DIR_PIN 28 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 17 +#define E_DIR_PIN 21 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN 14 +#define KILL_PIN -1 + +#define HEATER_0_PIN 12 // (extruder) + +#define HEATER_1_PIN 16 // (bed) +#define X_ENABLE_PIN 19 +#define Y_ENABLE_PIN 24 +#define Z_ENABLE_PIN 29 +#define E_ENABLE_PIN 13 + +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN 5 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 4 +#define HEATER_2_PIN -1 + +#endif + + + + +#ifndef KNOWN_BOARD +#error Unknown MOTHERBOARD value in configuration.h +#endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN +#if EXTRUDERS == 3 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN +#elif EXTRUDERS == 2 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS -1 +#elif EXTRUDERS == 1 + #define _E1_PINS -1 + #define _E2_PINS -1 +#else + #error Unsupported number of extruders +#endif +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ + HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ + HEATER_BED_PIN, FAN_PIN, \ + _E0_PINS, _E1_PINS, _E2_PINS, \ + TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } +#endif diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 2f3888c018..40ba855f34 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -52,6 +52,7 @@ int current_raw_bed = 0; float Kp=DEFAULT_Kp; float Ki=DEFAULT_Ki; + int Ki_Max=PID_INTEGRAL_DRIVE_MAX; float Kd=DEFAULT_Kd; #ifdef PID_ADD_EXTRUSION_RATE float Kc=DEFAULT_Kc; @@ -137,7 +138,7 @@ void updatePID() { #ifdef PIDTEMP for(int e = 0; e < EXTRUDERS; e++) { - temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; + temp_iState_max[e] = Ki_Max / Ki; } #endif } @@ -439,7 +440,7 @@ void tp_init() maxttemp[e] = maxttemp[0]; #ifdef PIDTEMP temp_iState_min[e] = 0.0; - temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; + temp_iState_max[e] = Ki_Max / Ki; #endif //PIDTEMP } diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 80e68f78b4..1ff821cdd9 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -47,6 +47,7 @@ extern int current_raw_bed; extern int target_bed_high_temp ; #endif extern float Kp,Ki,Kd,Kc; +extern int Ki_Max; #ifdef PIDTEMP extern float pid_setpoint[EXTRUDERS]; diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 3071a6b5bb..b43c529731 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -320,6 +320,66 @@ const short temptable_7[][2] PROGMEM = { {1005*OVERSAMPLENR, 5} }; #endif +// +#if (THERMISTORHEATER_0 == 100) || (THERMISTORHEATER_1 == 100) || (THERMISTORHEATER_2 == 100) || (THERMISTORBED == 100) // 100k DO-35 NTC +const short temptable_100[][2] PROGMEM = { + {1*OVERSAMPLENR, 929}, + {36*OVERSAMPLENR, 299}, + {71*OVERSAMPLENR, 246}, + {106*OVERSAMPLENR, 217}, + {141*OVERSAMPLENR, 198}, + {176*OVERSAMPLENR, 184}, + {211*OVERSAMPLENR, 173}, + {246*OVERSAMPLENR, 163}, + {281*OVERSAMPLENR, 154}, + {316*OVERSAMPLENR, 147}, + {351*OVERSAMPLENR, 140}, + {386*OVERSAMPLENR, 134}, + {421*OVERSAMPLENR, 128}, + {456*OVERSAMPLENR, 122}, + {491*OVERSAMPLENR, 117}, + {526*OVERSAMPLENR, 112}, + {561*OVERSAMPLENR, 107}, + {596*OVERSAMPLENR, 102}, + {631*OVERSAMPLENR, 97}, + {666*OVERSAMPLENR, 91}, + {701*OVERSAMPLENR, 86}, + {736*OVERSAMPLENR, 81}, + {771*OVERSAMPLENR, 76}, + {806*OVERSAMPLENR, 70}, + {841*OVERSAMPLENR, 63}, + {876*OVERSAMPLENR, 56}, + {911*OVERSAMPLENR, 48}, + {946*OVERSAMPLENR, 38}, + {981*OVERSAMPLENR, 23}, + {1005*OVERSAMPLENR, 5}, + {1016*OVERSAMPLENR, 0} +}; +#endif +#if (THERMISTORHEATER_0 == 101) || (THERMISTORHEATER_1 == 101) || (THERMISTORHEATER_2 == 101) || (THERMISTORBED == 101) // 100k Honeywell 135-104LAG-J01 +const short temptable_101[][2] PROGMEM = { + {1*OVERSAMPLENR, 704}, + {54*OVERSAMPLENR, 216}, + {107*OVERSAMPLENR, 175}, + {160*OVERSAMPLENR, 152}, + {213*OVERSAMPLENR, 137}, + {266*OVERSAMPLENR, 125}, + {319*OVERSAMPLENR, 115}, + {372*OVERSAMPLENR, 106}, + {425*OVERSAMPLENR, 99}, + {478*OVERSAMPLENR, 91}, + {531*OVERSAMPLENR, 85}, + {584*OVERSAMPLENR, 78}, + {637*OVERSAMPLENR, 71}, + {690*OVERSAMPLENR, 65}, + {743*OVERSAMPLENR, 58}, + {796*OVERSAMPLENR, 50}, + {849*OVERSAMPLENR, 42}, + {902*OVERSAMPLENR, 31}, + {955*OVERSAMPLENR, 17}, + {1008*OVERSAMPLENR, 0} +}; +#endif #define _TT_NAME(_N) temptable_ ## _N #define TT_NAME(_N) _TT_NAME(_N) From 8f5cec3e954dd15c240af6c1c6c2166f979b2146 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Thu, 23 Feb 2012 11:14:43 +0000 Subject: [PATCH 204/228] thermistor tables updated --- Marlin/Configuration.h | 7 +- Marlin/Configuration.h~ | 82 +++---- Marlin/thermistortables.h | 95 ++++++++ Marlin/thermistortables.h~ | 433 +++++++++++++++++++++++++++++++++++++ 4 files changed, 577 insertions(+), 40 deletions(-) create mode 100644 Marlin/thermistortables.h~ diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 25e7cf20cf..c8868f3b39 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -43,10 +43,10 @@ // 100 is 100k GE Sensing AL03006-58.2K-97-G1 // 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT -#define TEMP_SENSOR_0 100 +#define TEMP_SENSOR_0 102 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 101 +#define TEMP_SENSOR_BED 103 // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 10 // (seconds) @@ -157,7 +157,8 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker +//#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker +#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,875} #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. diff --git a/Marlin/Configuration.h~ b/Marlin/Configuration.h~ index f0d8913631..25e7cf20cf 100644 --- a/Marlin/Configuration.h~ +++ b/Marlin/Configuration.h~ @@ -12,8 +12,8 @@ #define STRING_CONFIG_H_AUTHOR "username" //Who made the changes. // This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 +//#define BAUDRATE 250000 +#define BAUDRATE 115200 //// The following define selects which electronics board you have. Please choose the one that matches your setup // MEGA/RAMPS up to 1.2 = 3, @@ -23,7 +23,7 @@ // Ultimaker = 7, // Teensylu = 8, // Gen3+ =9 -#define MOTHERBOARD 7 +#define MOTHERBOARD 62 //=========================================================================== //=============================Thermal Settings ============================ @@ -40,30 +40,32 @@ // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 +// 100 is 100k GE Sensing AL03006-58.2K-97-G1 +// 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT -#define TEMP_SENSOR_0 -1 +#define TEMP_SENSOR_0 100 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 0 +#define TEMP_SENSOR_BED 101 // Actual temperature must be close to target for this long before M109 returns success -#define TEMP_RESIDENCY_TIME 30 // (seconds) -#define TEMP_HYSTERESIS 3 // (C°) range of +/- temperatures considered "close" to the target one +#define TEMP_RESIDENCY_TIME 10 // (seconds) +#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one // The minimal temperature defines the temperature below which the heater will not be enabled It is used // to check that the wiring to the thermistor is not broken. // Otherwise this would lead to the heater being powered on all the time. -#define HEATER_0_MINTEMP 5 -#define HEATER_1_MINTEMP 5 -#define HEATER_2_MINTEMP 5 -#define BED_MINTEMP 5 +#define HEATER_0_MINTEMP 1 +//#define HEATER_1_MINTEMP 5 +//#define HEATER_2_MINTEMP 5 +#define BED_MINTEMP 1 // When temperature exceeds max temp, your heater will be switched off. // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 275 -#define HEATER_1_MAXTEMP 275 -#define HEATER_2_MAXTEMP 275 +#define HEATER_0_MAXTEMP 399 +//#define HEATER_1_MAXTEMP 275 +//#define HEATER_2_MAXTEMP 275 #define BED_MAXTEMP 150 // PID settings: @@ -73,21 +75,26 @@ #ifdef PIDTEMP //#define PID_DEBUG // Sends debug data to the serial port. //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term + #define PID_INTEGRAL_DRIVE_MAX 130 //limit for the integral term #define K1 0.95 //smoothing factor withing the PID - #define PID_dT 0.128 //sampling period of the PID + #define PID_dT 0.122 //sampling period of the PID // If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it // Ultimaker - #define DEFAULT_Kp 22.2 - #define DEFAULT_Ki (1.25*PID_dT) - #define DEFAULT_Kd (99/PID_dT) +// #define DEFAULT_Kp 22.2 +// #define DEFAULT_Ki (1.25*PID_dT) +// #define DEFAULT_Kd (99/PID_dT) // Makergear // #define DEFAULT_Kp 7.0 // #define DEFAULT_Ki 0.1 // #define DEFAULT_Kd 12 +// RepRapPro Huxley + #define DEFAULT_Kp 3.0 + #define DEFAULT_Ki (2*PID_dT) + #define DEFAULT_Kd (80/PID_dT) + // Mendel Parts V9 on 12V // #define DEFAULT_Kp 63.0 // #define DEFAULT_Ki (2.25*PID_dT) @@ -108,9 +115,9 @@ #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors // The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool X_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Y_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. +const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 #define X_ENABLE_ON 0 @@ -121,15 +128,15 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // Disables axis when it's not being used. #define DISABLE_X false #define DISABLE_Y false -#define DISABLE_Z false +#define DISABLE_Z true #define DISABLE_E false // For all extruders #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true +#define INVERT_E0_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E2_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false // ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -139,22 +146,23 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th #define min_software_endstops true //If true, axis won't move to coordinates less than zero. #define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 205 -#define Y_MAX_LENGTH 205 -#define Z_MAX_LENGTH 200 +#define X_MAX_LENGTH 150 +#define Y_MAX_LENGTH 148 +#define Z_MAX_LENGTH 100 //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0} // set the homing speeds (mm/min) +#define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) +#define FAST_HOME_FEEDRATE {80*60, 80*60, 4*60, 0} // set the homing speeds (mm/min) // default settings -#define DEFAULT_AXIS_STEPS_PER_UNIT {78.7402,78.7402,200*8/3,760*1.1} // default steps per unit for ultimaker +#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {9000,9000,100,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +#define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts +#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for r retracts // #define DEFAULT_XYJERK 20.0 // (mm/sec) @@ -170,10 +178,10 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // 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. //define this to enable eeprom support -//#define EEPROM_SETTINGS +#define EEPROM_SETTINGS //to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: // please keep turned on if you can. -//#define EEPROM_CHITCHAT +#define EEPROM_CHITCHAT //LCD and SD support //#define ULTRA_LCD //general lcd support, also 16x2 diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index b43c529731..f4c25d357e 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -380,6 +380,101 @@ const short temptable_101[][2] PROGMEM = { {1008*OVERSAMPLENR, 0} }; #endif +#if (THERMISTORHEATER_0 == 102) || (THERMISTORHEATER_1 == 102) || (THERMISTORHEATER_2 == 102) || (THERMISTORBED == 102) // EPCOS G57540 +const short temptable_100[][2] PROGMEM = { +{15*OVERSAMPLENR,286}, +{16*OVERSAMPLENR,282}, +{17*OVERSAMPLENR,278}, +{18*OVERSAMPLENR,274}, +{19*OVERSAMPLENR,270}, +{20*OVERSAMPLENR,266}, +{21*OVERSAMPLENR,262}, +{22*OVERSAMPLENR,258}, +{23*OVERSAMPLENR,254}, +{25*OVERSAMPLENR,250}, +{27*OVERSAMPLENR,246}, +{28*OVERSAMPLENR,242}, +{31*OVERSAMPLENR,238}, +{33*OVERSAMPLENR,234}, +{35*OVERSAMPLENR,230}, +{38*OVERSAMPLENR,226}, +{41*OVERSAMPLENR,222}, +{44*OVERSAMPLENR,218}, +{48*OVERSAMPLENR,214}, +{52*OVERSAMPLENR,210}, +{56*OVERSAMPLENR,206}, +{61*OVERSAMPLENR,202}, +{66*OVERSAMPLENR,198}, +{71*OVERSAMPLENR,194}, +{78*OVERSAMPLENR,190}, +{84*OVERSAMPLENR,186}, +{92*OVERSAMPLENR,182}, +{100*OVERSAMPLENR,178}, +{109*OVERSAMPLENR,174}, +{120*OVERSAMPLENR,170}, +{131*OVERSAMPLENR,166}, +{143*OVERSAMPLENR,162}, +{156*OVERSAMPLENR,158}, +{171*OVERSAMPLENR,154}, +{187*OVERSAMPLENR,150}, +{205*OVERSAMPLENR,146}, +{224*OVERSAMPLENR,142}, +{224*OVERSAMPLENR,160}, +{245*OVERSAMPLENR,155}, +{268*OVERSAMPLENR,150}, +{293*OVERSAMPLENR,145}, +{320*OVERSAMPLENR,140}, +{348*OVERSAMPLENR,135}, +{379*OVERSAMPLENR,130}, +{411*OVERSAMPLENR,125}, +{480*OVERSAMPLENR,115}, +{553*OVERSAMPLENR,105}, +{628*OVERSAMPLENR,95}, +{702*OVERSAMPLENR,85}, +{770*OVERSAMPLENR,75}, +{830*OVERSAMPLENR,65}, +{881*OVERSAMPLENR,55}, +{922*OVERSAMPLENR,45}, +{954*OVERSAMPLENR,35}, +{977*OVERSAMPLENR,25}, +{993*OVERSAMPLENR,15}, +{999*OVERSAMPLENR,10}, +{1008*OVERSAMPLENR,0}, +}; +#endif +#if (THERMISTORHEATER_0 == 103) || (THERMISTORHEATER_1 == 103) || (THERMISTORHEATER_2 == 103) || (THERMISTORBED == 103) // 100k Honeywell 135-104LAG-J01 +const short temptable_103[][2] PROGMEM = { + {1*OVERSAMPLENR, 628}, + {187*OVERSAMPLENR, 156}, + {218*OVERSAMPLENR, 148}, + {249*OVERSAMPLENR, 141}, + {280*OVERSAMPLENR, 135}, + {311*OVERSAMPLENR, 129}, + {342*OVERSAMPLENR, 124}, + {373*OVERSAMPLENR, 120}, + {404*OVERSAMPLENR, 115}, + {435*OVERSAMPLENR, 111}, + {466*OVERSAMPLENR, 107}, + {497*OVERSAMPLENR, 103}, + {528*OVERSAMPLENR, 99}, + {559*OVERSAMPLENR, 96}, + {590*OVERSAMPLENR, 92}, + {621*OVERSAMPLENR, 88}, + {652*OVERSAMPLENR, 84}, + {683*OVERSAMPLENR, 81}, + {714*OVERSAMPLENR, 77}, + {745*OVERSAMPLENR, 73}, + {776*OVERSAMPLENR, 68}, + {807*OVERSAMPLENR, 64}, + {838*OVERSAMPLENR, 59}, + {869*OVERSAMPLENR, 54}, + {900*OVERSAMPLENR, 48}, + {931*OVERSAMPLENR, 40}, + {962*OVERSAMPLENR, 31}, + {993*OVERSAMPLENR, 17}, + {1008*OVERSAMPLENR,0} +}; +#endif #define _TT_NAME(_N) temptable_ ## _N #define TT_NAME(_N) _TT_NAME(_N) diff --git a/Marlin/thermistortables.h~ b/Marlin/thermistortables.h~ new file mode 100644 index 0000000000..b43c529731 --- /dev/null +++ b/Marlin/thermistortables.h~ @@ -0,0 +1,433 @@ +#ifndef THERMISTORTABLES_H_ +#define THERMISTORTABLES_H_ + +#include "Marlin.h" + +#define OVERSAMPLENR 16 + +#if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor + +const short temptable_1[][2] PROGMEM = { +{ 23*OVERSAMPLENR , 300 }, +{ 25*OVERSAMPLENR , 295 }, +{ 27*OVERSAMPLENR , 290 }, +{ 28*OVERSAMPLENR , 285 }, +{ 31*OVERSAMPLENR , 280 }, +{ 33*OVERSAMPLENR , 275 }, +{ 35*OVERSAMPLENR , 270 }, +{ 38*OVERSAMPLENR , 265 }, +{ 41*OVERSAMPLENR , 260 }, +{ 44*OVERSAMPLENR , 255 }, +{ 48*OVERSAMPLENR , 250 }, +{ 52*OVERSAMPLENR , 245 }, +{ 56*OVERSAMPLENR , 240 }, +{ 61*OVERSAMPLENR , 235 }, +{ 66*OVERSAMPLENR , 230 }, +{ 71*OVERSAMPLENR , 225 }, +{ 78*OVERSAMPLENR , 220 }, +{ 84*OVERSAMPLENR , 215 }, +{ 92*OVERSAMPLENR , 210 }, +{ 100*OVERSAMPLENR , 205 }, +{ 109*OVERSAMPLENR , 200 }, +{ 120*OVERSAMPLENR , 195 }, +{ 131*OVERSAMPLENR , 190 }, +{ 143*OVERSAMPLENR , 185 }, +{ 156*OVERSAMPLENR , 180 }, +{ 171*OVERSAMPLENR , 175 }, +{ 187*OVERSAMPLENR , 170 }, +{ 205*OVERSAMPLENR , 165 }, +{ 224*OVERSAMPLENR , 160 }, +{ 245*OVERSAMPLENR , 155 }, +{ 268*OVERSAMPLENR , 150 }, +{ 293*OVERSAMPLENR , 145 }, +{ 320*OVERSAMPLENR , 140 }, +{ 348*OVERSAMPLENR , 135 }, +{ 379*OVERSAMPLENR , 130 }, +{ 411*OVERSAMPLENR , 125 }, +{ 445*OVERSAMPLENR , 120 }, +{ 480*OVERSAMPLENR , 115 }, +{ 516*OVERSAMPLENR , 110 }, +{ 553*OVERSAMPLENR , 105 }, +{ 591*OVERSAMPLENR , 100 }, +{ 628*OVERSAMPLENR , 95 }, +{ 665*OVERSAMPLENR , 90 }, +{ 702*OVERSAMPLENR , 85 }, +{ 737*OVERSAMPLENR , 80 }, +{ 770*OVERSAMPLENR , 75 }, +{ 801*OVERSAMPLENR , 70 }, +{ 830*OVERSAMPLENR , 65 }, +{ 857*OVERSAMPLENR , 60 }, +{ 881*OVERSAMPLENR , 55 }, +{ 903*OVERSAMPLENR , 50 }, +{ 922*OVERSAMPLENR , 45 }, +{ 939*OVERSAMPLENR , 40 }, +{ 954*OVERSAMPLENR , 35 }, +{ 966*OVERSAMPLENR , 30 }, +{ 977*OVERSAMPLENR , 25 }, +{ 985*OVERSAMPLENR , 20 }, +{ 993*OVERSAMPLENR , 15 }, +{ 999*OVERSAMPLENR , 10 }, +{ 1004*OVERSAMPLENR , 5 }, +{ 1008*OVERSAMPLENR , 0 } //safety +}; +#endif +#if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor +const short temptable_2[][2] PROGMEM = { + {1*OVERSAMPLENR, 848}, + {54*OVERSAMPLENR, 275}, + {107*OVERSAMPLENR, 228}, + {160*OVERSAMPLENR, 202}, + {213*OVERSAMPLENR, 185}, + {266*OVERSAMPLENR, 171}, + {319*OVERSAMPLENR, 160}, + {372*OVERSAMPLENR, 150}, + {425*OVERSAMPLENR, 141}, + {478*OVERSAMPLENR, 133}, + {531*OVERSAMPLENR, 125}, + {584*OVERSAMPLENR, 118}, + {637*OVERSAMPLENR, 110}, + {690*OVERSAMPLENR, 103}, + {743*OVERSAMPLENR, 95}, + {796*OVERSAMPLENR, 86}, + {849*OVERSAMPLENR, 77}, + {902*OVERSAMPLENR, 65}, + {955*OVERSAMPLENR, 49}, + {1008*OVERSAMPLENR, 17}, + {1020*OVERSAMPLENR, 0} //safety +}; + +#endif +#if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts +const short temptable_3[][2] PROGMEM = { + {1*OVERSAMPLENR,864}, + {21*OVERSAMPLENR,300}, + {25*OVERSAMPLENR,290}, + {29*OVERSAMPLENR,280}, + {33*OVERSAMPLENR,270}, + {39*OVERSAMPLENR,260}, + {46*OVERSAMPLENR,250}, + {54*OVERSAMPLENR,240}, + {64*OVERSAMPLENR,230}, + {75*OVERSAMPLENR,220}, + {90*OVERSAMPLENR,210}, + {107*OVERSAMPLENR,200}, + {128*OVERSAMPLENR,190}, + {154*OVERSAMPLENR,180}, + {184*OVERSAMPLENR,170}, + {221*OVERSAMPLENR,160}, + {265*OVERSAMPLENR,150}, + {316*OVERSAMPLENR,140}, + {375*OVERSAMPLENR,130}, + {441*OVERSAMPLENR,120}, + {513*OVERSAMPLENR,110}, + {588*OVERSAMPLENR,100}, + {734*OVERSAMPLENR,80}, + {856*OVERSAMPLENR,60}, + {938*OVERSAMPLENR,40}, + {986*OVERSAMPLENR,20}, + {1008*OVERSAMPLENR,0}, + {1018*OVERSAMPLENR,-20} + }; + +#endif +#if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor +const short temptable_4[][2] PROGMEM = { + {1*OVERSAMPLENR, 430}, + {54*OVERSAMPLENR, 137}, + {107*OVERSAMPLENR, 107}, + {160*OVERSAMPLENR, 91}, + {213*OVERSAMPLENR, 80}, + {266*OVERSAMPLENR, 71}, + {319*OVERSAMPLENR, 64}, + {372*OVERSAMPLENR, 57}, + {425*OVERSAMPLENR, 51}, + {478*OVERSAMPLENR, 46}, + {531*OVERSAMPLENR, 41}, + {584*OVERSAMPLENR, 35}, + {637*OVERSAMPLENR, 30}, + {690*OVERSAMPLENR, 25}, + {743*OVERSAMPLENR, 20}, + {796*OVERSAMPLENR, 14}, + {849*OVERSAMPLENR, 7}, + {902*OVERSAMPLENR, 0}, + {955*OVERSAMPLENR, -11}, + {1008*OVERSAMPLENR, -35} +}; +#endif + +#if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) +const short temptable_5[][2] PROGMEM = { +{1*OVERSAMPLENR, 713}, +{18*OVERSAMPLENR, 316}, +{35*OVERSAMPLENR, 266}, +{52*OVERSAMPLENR, 239}, +{69*OVERSAMPLENR, 221}, +{86*OVERSAMPLENR, 208}, +{103*OVERSAMPLENR, 197}, +{120*OVERSAMPLENR, 188}, +{137*OVERSAMPLENR, 181}, +{154*OVERSAMPLENR, 174}, +{171*OVERSAMPLENR, 169}, +{188*OVERSAMPLENR, 163}, +{205*OVERSAMPLENR, 159}, +{222*OVERSAMPLENR, 154}, +{239*OVERSAMPLENR, 150}, +{256*OVERSAMPLENR, 147}, +{273*OVERSAMPLENR, 143}, +{290*OVERSAMPLENR, 140}, +{307*OVERSAMPLENR, 136}, +{324*OVERSAMPLENR, 133}, +{341*OVERSAMPLENR, 130}, +{358*OVERSAMPLENR, 128}, +{375*OVERSAMPLENR, 125}, +{392*OVERSAMPLENR, 122}, +{409*OVERSAMPLENR, 120}, +{426*OVERSAMPLENR, 117}, +{443*OVERSAMPLENR, 115}, +{460*OVERSAMPLENR, 112}, +{477*OVERSAMPLENR, 110}, +{494*OVERSAMPLENR, 108}, +{511*OVERSAMPLENR, 106}, +{528*OVERSAMPLENR, 103}, +{545*OVERSAMPLENR, 101}, +{562*OVERSAMPLENR, 99}, +{579*OVERSAMPLENR, 97}, +{596*OVERSAMPLENR, 95}, +{613*OVERSAMPLENR, 92}, +{630*OVERSAMPLENR, 90}, +{647*OVERSAMPLENR, 88}, +{664*OVERSAMPLENR, 86}, +{681*OVERSAMPLENR, 84}, +{698*OVERSAMPLENR, 81}, +{715*OVERSAMPLENR, 79}, +{732*OVERSAMPLENR, 77}, +{749*OVERSAMPLENR, 75}, +{766*OVERSAMPLENR, 72}, +{783*OVERSAMPLENR, 70}, +{800*OVERSAMPLENR, 67}, +{817*OVERSAMPLENR, 64}, +{834*OVERSAMPLENR, 61}, +{851*OVERSAMPLENR, 58}, +{868*OVERSAMPLENR, 55}, +{885*OVERSAMPLENR, 52}, +{902*OVERSAMPLENR, 48}, +{919*OVERSAMPLENR, 44}, +{936*OVERSAMPLENR, 40}, +{953*OVERSAMPLENR, 34}, +{970*OVERSAMPLENR, 28}, +{987*OVERSAMPLENR, 20}, +{1004*OVERSAMPLENR, 8}, +{1021*OVERSAMPLENR, 0} +}; +#endif + +#if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor +const short temptable_6[][2] PROGMEM = { + {28*OVERSAMPLENR, 250}, + {31*OVERSAMPLENR, 245}, + {35*OVERSAMPLENR, 240}, + {39*OVERSAMPLENR, 235}, + {42*OVERSAMPLENR, 230}, + {44*OVERSAMPLENR, 225}, + {49*OVERSAMPLENR, 220}, + {53*OVERSAMPLENR, 215}, + {62*OVERSAMPLENR, 210}, + {73*OVERSAMPLENR, 205}, + {72*OVERSAMPLENR, 200}, + {94*OVERSAMPLENR, 190}, + {102*OVERSAMPLENR, 185}, + {116*OVERSAMPLENR, 170}, + {143*OVERSAMPLENR, 160}, + {183*OVERSAMPLENR, 150}, + {223*OVERSAMPLENR, 140}, + {270*OVERSAMPLENR, 130}, + {318*OVERSAMPLENR, 120}, + {383*OVERSAMPLENR, 110}, + {413*OVERSAMPLENR, 105}, + {439*OVERSAMPLENR, 100}, + {484*OVERSAMPLENR, 95}, + {513*OVERSAMPLENR, 90}, + {607*OVERSAMPLENR, 80}, + {664*OVERSAMPLENR, 70}, + {781*OVERSAMPLENR, 60}, + {810*OVERSAMPLENR, 55}, + {849*OVERSAMPLENR, 50}, + {914*OVERSAMPLENR, 45}, + {914*OVERSAMPLENR, 40}, + {935*OVERSAMPLENR, 35}, + {954*OVERSAMPLENR, 30}, + {970*OVERSAMPLENR, 25}, + {978*OVERSAMPLENR, 22}, + {1008*OVERSAMPLENR, 3} +}; +#endif + +#if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 +const short temptable_7[][2] PROGMEM = { + {46*OVERSAMPLENR, 270}, + {50*OVERSAMPLENR, 265}, + {54*OVERSAMPLENR, 260}, + {58*OVERSAMPLENR, 255}, + {62*OVERSAMPLENR, 250}, + {67*OVERSAMPLENR, 245}, + {72*OVERSAMPLENR, 240}, + {79*OVERSAMPLENR, 235}, + {85*OVERSAMPLENR, 230}, + {91*OVERSAMPLENR, 225}, + {99*OVERSAMPLENR, 220}, + {107*OVERSAMPLENR, 215}, + {116*OVERSAMPLENR, 210}, + {126*OVERSAMPLENR, 205}, + {136*OVERSAMPLENR, 200}, + {149*OVERSAMPLENR, 195}, + {160*OVERSAMPLENR, 190}, + {175*OVERSAMPLENR, 185}, + {191*OVERSAMPLENR, 180}, + {209*OVERSAMPLENR, 175}, + {224*OVERSAMPLENR, 170}, + {246*OVERSAMPLENR, 165}, + {267*OVERSAMPLENR, 160}, + {293*OVERSAMPLENR, 155}, + {316*OVERSAMPLENR, 150}, + {340*OVERSAMPLENR, 145}, + {364*OVERSAMPLENR, 140}, + {396*OVERSAMPLENR, 135}, + {425*OVERSAMPLENR, 130}, + {460*OVERSAMPLENR, 125}, + {489*OVERSAMPLENR, 120}, + {526*OVERSAMPLENR, 115}, + {558*OVERSAMPLENR, 110}, + {591*OVERSAMPLENR, 105}, + {628*OVERSAMPLENR, 100}, + {660*OVERSAMPLENR, 95}, + {696*OVERSAMPLENR, 90}, + {733*OVERSAMPLENR, 85}, + {761*OVERSAMPLENR, 80}, + {794*OVERSAMPLENR, 75}, + {819*OVERSAMPLENR, 70}, + {847*OVERSAMPLENR, 65}, + {870*OVERSAMPLENR, 60}, + {892*OVERSAMPLENR, 55}, + {911*OVERSAMPLENR, 50}, + {929*OVERSAMPLENR, 45}, + {944*OVERSAMPLENR, 40}, + {959*OVERSAMPLENR, 35}, + {971*OVERSAMPLENR, 30}, + {981*OVERSAMPLENR, 25}, + {989*OVERSAMPLENR, 20}, + {994*OVERSAMPLENR, 15}, + {1001*OVERSAMPLENR, 10}, + {1005*OVERSAMPLENR, 5} +}; +#endif +// +#if (THERMISTORHEATER_0 == 100) || (THERMISTORHEATER_1 == 100) || (THERMISTORHEATER_2 == 100) || (THERMISTORBED == 100) // 100k DO-35 NTC +const short temptable_100[][2] PROGMEM = { + {1*OVERSAMPLENR, 929}, + {36*OVERSAMPLENR, 299}, + {71*OVERSAMPLENR, 246}, + {106*OVERSAMPLENR, 217}, + {141*OVERSAMPLENR, 198}, + {176*OVERSAMPLENR, 184}, + {211*OVERSAMPLENR, 173}, + {246*OVERSAMPLENR, 163}, + {281*OVERSAMPLENR, 154}, + {316*OVERSAMPLENR, 147}, + {351*OVERSAMPLENR, 140}, + {386*OVERSAMPLENR, 134}, + {421*OVERSAMPLENR, 128}, + {456*OVERSAMPLENR, 122}, + {491*OVERSAMPLENR, 117}, + {526*OVERSAMPLENR, 112}, + {561*OVERSAMPLENR, 107}, + {596*OVERSAMPLENR, 102}, + {631*OVERSAMPLENR, 97}, + {666*OVERSAMPLENR, 91}, + {701*OVERSAMPLENR, 86}, + {736*OVERSAMPLENR, 81}, + {771*OVERSAMPLENR, 76}, + {806*OVERSAMPLENR, 70}, + {841*OVERSAMPLENR, 63}, + {876*OVERSAMPLENR, 56}, + {911*OVERSAMPLENR, 48}, + {946*OVERSAMPLENR, 38}, + {981*OVERSAMPLENR, 23}, + {1005*OVERSAMPLENR, 5}, + {1016*OVERSAMPLENR, 0} +}; +#endif +#if (THERMISTORHEATER_0 == 101) || (THERMISTORHEATER_1 == 101) || (THERMISTORHEATER_2 == 101) || (THERMISTORBED == 101) // 100k Honeywell 135-104LAG-J01 +const short temptable_101[][2] PROGMEM = { + {1*OVERSAMPLENR, 704}, + {54*OVERSAMPLENR, 216}, + {107*OVERSAMPLENR, 175}, + {160*OVERSAMPLENR, 152}, + {213*OVERSAMPLENR, 137}, + {266*OVERSAMPLENR, 125}, + {319*OVERSAMPLENR, 115}, + {372*OVERSAMPLENR, 106}, + {425*OVERSAMPLENR, 99}, + {478*OVERSAMPLENR, 91}, + {531*OVERSAMPLENR, 85}, + {584*OVERSAMPLENR, 78}, + {637*OVERSAMPLENR, 71}, + {690*OVERSAMPLENR, 65}, + {743*OVERSAMPLENR, 58}, + {796*OVERSAMPLENR, 50}, + {849*OVERSAMPLENR, 42}, + {902*OVERSAMPLENR, 31}, + {955*OVERSAMPLENR, 17}, + {1008*OVERSAMPLENR, 0} +}; +#endif + +#define _TT_NAME(_N) temptable_ ## _N +#define TT_NAME(_N) _TT_NAME(_N) + +#ifdef THERMISTORHEATER_0 + #define heater_0_temptable TT_NAME(THERMISTORHEATER_0) + #define heater_0_temptable_len (sizeof(heater_0_temptable)/sizeof(*heater_0_temptable)) +#else +#ifdef HEATER_0_USES_THERMISTOR + #error No heater 0 thermistor table specified +#else // HEATER_0_USES_THERMISTOR + #define heater_0_temptable 0 + #define heater_0_temptable_len 0 +#endif // HEATER_0_USES_THERMISTOR +#endif + +#ifdef THERMISTORHEATER_1 + #define heater_1_temptable TT_NAME(THERMISTORHEATER_1) + #define heater_1_temptable_len (sizeof(heater_1_temptable)/sizeof(*heater_1_temptable)) +#else +#ifdef HEATER_1_USES_THERMISTOR + #error No heater 1 thermistor table specified +#else // HEATER_1_USES_THERMISTOR + #define heater_1_temptable 0 + #define heater_1_temptable_len 0 +#endif // HEATER_1_USES_THERMISTOR +#endif + +#ifdef THERMISTORHEATER_2 + #define heater_2_temptable TT_NAME(THERMISTORHEATER_2) + #define heater_2_temptable_len (sizeof(heater_2_temptable)/sizeof(*heater_2_temptable)) +#else +#ifdef HEATER_2_USES_THERMISTOR + #error No heater 2 thermistor table specified +#else // HEATER_2_USES_THERMISTOR + #define heater_2_temptable 0 + #define heater_2_temptable_len 0 +#endif // HEATER_2_USES_THERMISTOR +#endif + +#ifdef THERMISTORBED + #define bedtemptable TT_NAME(THERMISTORBED) + #define bedtemptable_len (sizeof(bedtemptable)/sizeof(*bedtemptable)) +#else +#ifdef BED_USES_THERMISTOR + #error No bed thermistor table specified +#endif // BED_USES_THERMISTOR +#endif + +#endif //THERMISTORTABLES_H_ + From ebc1b54c751f1b0394077f90ce97a064769399a2 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Thu, 23 Feb 2012 11:17:17 +0000 Subject: [PATCH 205/228] typo --- Marlin/thermistortables.h | 2 +- Marlin/thermistortables.h~ | 95 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index f4c25d357e..88e7ddaf3d 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -381,7 +381,7 @@ const short temptable_101[][2] PROGMEM = { }; #endif #if (THERMISTORHEATER_0 == 102) || (THERMISTORHEATER_1 == 102) || (THERMISTORHEATER_2 == 102) || (THERMISTORBED == 102) // EPCOS G57540 -const short temptable_100[][2] PROGMEM = { +const short temptable_102[][2] PROGMEM = { {15*OVERSAMPLENR,286}, {16*OVERSAMPLENR,282}, {17*OVERSAMPLENR,278}, diff --git a/Marlin/thermistortables.h~ b/Marlin/thermistortables.h~ index b43c529731..f4c25d357e 100644 --- a/Marlin/thermistortables.h~ +++ b/Marlin/thermistortables.h~ @@ -380,6 +380,101 @@ const short temptable_101[][2] PROGMEM = { {1008*OVERSAMPLENR, 0} }; #endif +#if (THERMISTORHEATER_0 == 102) || (THERMISTORHEATER_1 == 102) || (THERMISTORHEATER_2 == 102) || (THERMISTORBED == 102) // EPCOS G57540 +const short temptable_100[][2] PROGMEM = { +{15*OVERSAMPLENR,286}, +{16*OVERSAMPLENR,282}, +{17*OVERSAMPLENR,278}, +{18*OVERSAMPLENR,274}, +{19*OVERSAMPLENR,270}, +{20*OVERSAMPLENR,266}, +{21*OVERSAMPLENR,262}, +{22*OVERSAMPLENR,258}, +{23*OVERSAMPLENR,254}, +{25*OVERSAMPLENR,250}, +{27*OVERSAMPLENR,246}, +{28*OVERSAMPLENR,242}, +{31*OVERSAMPLENR,238}, +{33*OVERSAMPLENR,234}, +{35*OVERSAMPLENR,230}, +{38*OVERSAMPLENR,226}, +{41*OVERSAMPLENR,222}, +{44*OVERSAMPLENR,218}, +{48*OVERSAMPLENR,214}, +{52*OVERSAMPLENR,210}, +{56*OVERSAMPLENR,206}, +{61*OVERSAMPLENR,202}, +{66*OVERSAMPLENR,198}, +{71*OVERSAMPLENR,194}, +{78*OVERSAMPLENR,190}, +{84*OVERSAMPLENR,186}, +{92*OVERSAMPLENR,182}, +{100*OVERSAMPLENR,178}, +{109*OVERSAMPLENR,174}, +{120*OVERSAMPLENR,170}, +{131*OVERSAMPLENR,166}, +{143*OVERSAMPLENR,162}, +{156*OVERSAMPLENR,158}, +{171*OVERSAMPLENR,154}, +{187*OVERSAMPLENR,150}, +{205*OVERSAMPLENR,146}, +{224*OVERSAMPLENR,142}, +{224*OVERSAMPLENR,160}, +{245*OVERSAMPLENR,155}, +{268*OVERSAMPLENR,150}, +{293*OVERSAMPLENR,145}, +{320*OVERSAMPLENR,140}, +{348*OVERSAMPLENR,135}, +{379*OVERSAMPLENR,130}, +{411*OVERSAMPLENR,125}, +{480*OVERSAMPLENR,115}, +{553*OVERSAMPLENR,105}, +{628*OVERSAMPLENR,95}, +{702*OVERSAMPLENR,85}, +{770*OVERSAMPLENR,75}, +{830*OVERSAMPLENR,65}, +{881*OVERSAMPLENR,55}, +{922*OVERSAMPLENR,45}, +{954*OVERSAMPLENR,35}, +{977*OVERSAMPLENR,25}, +{993*OVERSAMPLENR,15}, +{999*OVERSAMPLENR,10}, +{1008*OVERSAMPLENR,0}, +}; +#endif +#if (THERMISTORHEATER_0 == 103) || (THERMISTORHEATER_1 == 103) || (THERMISTORHEATER_2 == 103) || (THERMISTORBED == 103) // 100k Honeywell 135-104LAG-J01 +const short temptable_103[][2] PROGMEM = { + {1*OVERSAMPLENR, 628}, + {187*OVERSAMPLENR, 156}, + {218*OVERSAMPLENR, 148}, + {249*OVERSAMPLENR, 141}, + {280*OVERSAMPLENR, 135}, + {311*OVERSAMPLENR, 129}, + {342*OVERSAMPLENR, 124}, + {373*OVERSAMPLENR, 120}, + {404*OVERSAMPLENR, 115}, + {435*OVERSAMPLENR, 111}, + {466*OVERSAMPLENR, 107}, + {497*OVERSAMPLENR, 103}, + {528*OVERSAMPLENR, 99}, + {559*OVERSAMPLENR, 96}, + {590*OVERSAMPLENR, 92}, + {621*OVERSAMPLENR, 88}, + {652*OVERSAMPLENR, 84}, + {683*OVERSAMPLENR, 81}, + {714*OVERSAMPLENR, 77}, + {745*OVERSAMPLENR, 73}, + {776*OVERSAMPLENR, 68}, + {807*OVERSAMPLENR, 64}, + {838*OVERSAMPLENR, 59}, + {869*OVERSAMPLENR, 54}, + {900*OVERSAMPLENR, 48}, + {931*OVERSAMPLENR, 40}, + {962*OVERSAMPLENR, 31}, + {993*OVERSAMPLENR, 17}, + {1008*OVERSAMPLENR,0} +}; +#endif #define _TT_NAME(_N) temptable_ ## _N #define TT_NAME(_N) _TT_NAME(_N) From 340876889be250fe5ec76da9e984039e6e9e8233 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Wed, 29 Feb 2012 16:31:12 +0000 Subject: [PATCH 206/228] hux2 running --- Marlin/Configuration.h | 45 +- Marlin/Configuration_adv.h | 11 + Marlin/Makefile | 2 +- Marlin/Marlin.pde | 56 +- Marlin/Marlin.pde~ | 1350 ++++++++++++++++++++++++++++++++++++ Marlin/language.h | 339 +++++++++ Marlin/planner.cpp | 44 +- Marlin/planner.cpp~ | 808 +++++++++++++++++++++ Marlin/planner.h | 2 +- Marlin/temperature.cpp | 24 +- Marlin/ultralcd.h | 22 +- Marlin/ultralcd.pde | 506 +++++++++++--- 12 files changed, 3039 insertions(+), 170 deletions(-) create mode 100644 Marlin/Marlin.pde~ create mode 100644 Marlin/language.h create mode 100644 Marlin/planner.cpp~ diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index c8868f3b39..ad706fdaf4 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -8,20 +8,25 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-02-08j" //Personal revision number for changes to THIS file. -#define STRING_CONFIG_H_AUTHOR "username" //Who made the changes. +#define STRING_VERSION_CONFIG_H "2012-02-24-2" //Personal revision number for changes to THIS file. +#define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. // This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 +#define BAUDRATE 250000 +//#define BAUDRATE 115200 //// The following define selects which electronics board you have. Please choose the one that matches your setup -// MEGA/RAMPS up to 1.2 = 3, -// RAMPS 1.3 = 33 -// Gen6 = 5, +// Gen7 custom (Alfons3 Version) = 10 "https://github.com/Alfons3/Generation_7_Electronics" +// Gen7 v1.1, v1.2 = 11 +// Gen7 v1.3 = 12 +// MEGA/RAMPS up to 1.2 = 3 +// RAMPS 1.3 = 33 (Power outputs: Extruder, Bed, Fan) +// RAMPS 1.3 = 34 (Power outputs: Extruder0, Extruder1, Bed) +// Gen6 = 5 +// Gen6 deluxe = 51 // Sanguinololu 1.2 and above = 62 -// Ultimaker = 7, -// Teensylu = 8, +// Ultimaker = 7 +// Teensylu = 8 // Gen3+ =9 #define MOTHERBOARD 62 @@ -68,6 +73,7 @@ //#define HEATER_2_MAXTEMP 275 #define BED_MAXTEMP 150 + // PID settings: // Comment the following line to disable PID and enable bang-bang. #define PIDTEMP @@ -150,15 +156,20 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define Y_MAX_LENGTH 148 #define Z_MAX_LENGTH 100 +// The position of the homing switches. Use MAX_LENGTH * -0.5 if the center should be 0, 0, 0 +#define X_HOME_POS 0 +#define Y_HOME_POS 0 +#define Z_HOME_POS 0 + //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E #define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) -#define FAST_HOME_FEEDRATE {80*60, 80*60, 4*60, 0} // set the homing speeds (mm/min) +#define FAST_HOME_FEEDRATE {80*60, 80*60, 3*60, 0} // set the homing speeds (mm/min) // default settings -//#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker -#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,875} +#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker +//#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,850} #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. @@ -195,6 +206,16 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define ULTRA_LCD #define LCD_WIDTH 20 #define LCD_HEIGHT 4 + +// Preheat Constants + #define PLA_PREHEAT_HOTEND_TEMP 180 + #define PLA_PREHEAT_HPB_TEMP 70 + #define PLA_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 + + #define ABS_PREHEAT_HOTEND_TEMP 240 + #define ABS_PREHEAT_HPB_TEMP 100 + #define ABS_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 + #else //no panel but just lcd #ifdef ULTRA_LCD #define LCD_WIDTH 16 diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 6e891cc4e8..c2cb14951e 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -59,6 +59,11 @@ #define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed #define EXTRUDER_RUNOUT_EXTRUDE 100 +//These defines help to calibrate the AD595 sensor in case you get wrong temperature measurements. +//The measured temperature is defined as "actualTemp = (measuredTemp * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET" +#define TEMP_SENSOR_AD595_OFFSET 0.0 +#define TEMP_SENSOR_AD595_GAIN 1.0 + //=========================================================================== //=============================Mechanical Settings=========================== //=========================================================================== @@ -148,6 +153,12 @@ const 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 +// in the pins.h file. When using a push button pulling the pin to ground this will need inverted. This setting should +// be commented out otherwise +//#define SDCARDDETECTINVERTED + //=========================================================================== //=============================Buffers ============================ //=========================================================================== diff --git a/Marlin/Makefile b/Marlin/Makefile index 71ee747485..7c039be571 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -61,7 +61,7 @@ SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ $(ARDUINO)/wiring_pulse.c \ $(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c CXXSRC = $(ARDUINO)/WMath.cpp $(ARDUINO)/WString.cpp\ - $(ARDUINO)/Print.cpp Marlin.cpp MarlinSerial.cpp Sd2Card.cpp SdBaseFile.cpp SdFatUtil.cpp SdFile.cpp SdVolume.cpp motion_control.cpp planner.cpp stepper.cpp temperature.cpp cardreader.cpp + $(ARDUINO)/Print.cpp applet/Marlin.cpp MarlinSerial.cpp Sd2Card.cpp SdBaseFile.cpp SdFatUtil.cpp SdFile.cpp SdVolume.cpp motion_control.cpp planner.cpp stepper.cpp temperature.cpp cardreader.cpp FORMAT = ihex diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index cb7aa1eaa2..e0fa719d86 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -35,8 +35,9 @@ #include "cardreader.h" #include "watchdog.h" #include "EEPROMwrite.h" +#include "language.h" -#define VERSION_STRING "1.0.0 RC1" +#define VERSION_STRING "1.0.0 RC2" // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html // http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes @@ -97,7 +98,8 @@ // 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 // M206 - set additional homeing offset -// M220 - set speed factor override percentage S:factor in percent +// 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 @@ -126,6 +128,7 @@ 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}; uint8_t active_extruder = 0; @@ -227,11 +230,11 @@ void setup_photpin() void setup_powerhold() { #ifdef SUICIDE_PIN - #if (SUICIDE_PIN> -1) + #if (SUICIDE_PIN> -1) SET_OUTPUT(SUICIDE_PIN); WRITE(SUICIDE_PIN, HIGH); - #endif - #endif + #endif + #endif } void suicide() @@ -332,9 +335,13 @@ void get_command() serial_char = MYSERIAL.read(); if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) { - if(!serial_count) return; //if empty line + 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) { @@ -411,9 +418,7 @@ void get_command() } bufindw = (bufindw + 1)%BUFSIZE; buflen += 1; - } - comment_mode = false; //for new command serial_count = 0; //clear buffer } else @@ -447,10 +452,9 @@ void get_command() card.checkautostart(true); } - if(serial_char=='\n') - comment_mode = false; //for new command if(!serial_count) { + comment_mode = false; //for new command return; //if empty line } cmdbuffer[bufindw][serial_count] = 0; //terminate string @@ -459,6 +463,7 @@ void get_command() buflen += 1; bufindw = (bufindw + 1)%BUFSIZE; } + comment_mode = false; //for new command serial_count = 0; //clear buffer } else @@ -506,15 +511,13 @@ bool code_seen(char code) plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ - feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ + feedrate = homing_feedrate[LETTER##_AXIS] ; \ plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ - current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? 0 : LETTER##_MAX_LENGTH;\ - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ + current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? LETTER##_HOME_POS : LETTER##_MAX_LENGTH;\ destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ feedrate = 0.0;\ st_synchronize();\ - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ endstops_hit_on_purpose();\ } @@ -568,7 +571,7 @@ void process_commands() feedrate = 0.0; home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); #ifdef QUICK_HOME - if( code_seen(axis_codes[0]) && code_seen(axis_codes[1]) ) //first diagonal move + if( 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; @@ -579,15 +582,13 @@ void process_commands() feedrate =homing_feedrate[Y_AXIS]; prepare_move(); - current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; - current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; + current_position[X_AXIS] = (X_HOME_DIR == -1) ? X_HOME_POS : X_MAX_LENGTH; + current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? Y_HOME_POS : Y_MAX_LENGTH; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[X_AXIS] = current_position[X_AXIS]; destination[Y_AXIS] = current_position[Y_AXIS]; feedrate = 0.0; st_synchronize(); - plan_set_position(0, 0, current_position[Z_AXIS], current_position[E_AXIS]); - current_position[X_AXIS] = 0;current_position[Y_AXIS] = 0; endstops_hit_on_purpose(); } #endif @@ -600,7 +601,7 @@ void process_commands() if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { HOMEAXIS(Y); } - + if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { HOMEAXIS(Z); } @@ -617,6 +618,8 @@ void process_commands() if(code_seen(axis_codes[Z_AXIS])) { current_position[2]=code_value()+add_homeing[2]; } + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + #ifdef ENDSTOPS_ONLY_FOR_HOMING enable_endstops(false); #endif @@ -1102,8 +1105,14 @@ void process_commands() } } break; - - + case 221: // M221 S- set extrude factor override percentage + { + if(code_seen('S')) + { + extrudemultiply = code_value() ; + } + } + break; #ifdef PIDTEMP case 301: // M301 @@ -1258,7 +1267,6 @@ void get_arc_coordinates() void prepare_move() { - if (min_software_endstops) { if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0; if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0; @@ -1270,7 +1278,7 @@ void prepare_move() if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH; if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; } - + 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]; diff --git a/Marlin/Marlin.pde~ b/Marlin/Marlin.pde~ new file mode 100644 index 0000000000..da29fb37aa --- /dev/null +++ b/Marlin/Marlin.pde~ @@ -0,0 +1,1350 @@ +/* + 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" + +#define VERSION_STRING "1.0.0 RC2" + +// 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 +// G28 - Home all Axis +// G90 - Use Absolute Coordinates +// G91 - Use Relative Coordinates +// G92 - Set current position to cordinates given + +//RepRap M Codes +// 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 - 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 +// M206 - set additional homeing offset +// 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 +// 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) + +//Stepper Movement Variables + +//=========================================================================== +//=============================imported variables============================ +//=========================================================================== + + +//=========================================================================== +//=============================public variables============================= +//=========================================================================== +#ifdef SDSUPPORT +CardReader card; +#endif +float homing_feedrate[] = HOMING_FEEDRATE; +float fast_home_feedrate[] = FAST_HOME_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}; +uint8_t active_extruder = 0; +bool stop_heating_wait=false; + +//=========================================================================== +//=============================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; + +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 uint8_t fanpwm=0; + +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; + + +//=========================================================================== +//=============================ROUTINES============================= +//=========================================================================== + +void get_arc_coordinates(); + +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_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_powerhold(); + MYSERIAL.begin(BAUDRATE); + SERIAL_PROTOCOLLNPGM("start"); + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Marlin: "); + SERIAL_ECHOLNPGM(VERSION_STRING); + #ifdef STRING_VERSION_CONFIG_H + #ifdef STRING_CONFIG_H_AUTHOR + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Configuration.h: "); + SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); + SERIAL_ECHOPGM(" | Author: "); + SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); + #endif + #endif + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Free Memory:"); + SERIAL_ECHO(freeMemory()); + SERIAL_ECHOPGM(" PlannerBufferBytes:"); + 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(); +} + + +void loop() +{ + if(buflen<3) + 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("ok"); + } + else + { + card.closefile(); + SERIAL_PROTOCOLLNPGM("Done saving file."); + } + } + else + { + process_commands(); + } + #else + process_commands(); + #endif //SDSUPPORT + buflen = (buflen-1); + bufindr = (bufindr + 1)%BUFSIZE; + } + //check heater every n milliseconds + manage_heater(); + manage_inactivity(1); + 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 == ':' || 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("Line Number is not Last Line Number+1, Last Line:"); + 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("checksum mismatch, Last Line:"); + SERIAL_ERRORLN(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + //if no errors, continue parsing + } + else + { + SERIAL_ERROR_START; + SERIAL_ERRORPGM("No Checksum with line number, Last Line:"); + 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("No Line Number with checksum, Last Line:"); + 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: + #ifdef SDSUPPORT + if(card.saving) + break; + #endif //SDSUPPORT + SERIAL_PROTOCOLLNPGM("ok"); + 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 == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) + { + if(card.eof()){ + SERIAL_PROTOCOLLNPGM("Done printing file"); + 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 HOMEAXIS(LETTER) \ + if ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))\ + { \ + current_position[LETTER##_AXIS] = 0; \ + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \ + destination[LETTER##_AXIS] = 1.1 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ + feedrate = fast_home_feedrate[LETTER##_AXIS]; \ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ + \ + current_position[LETTER##_AXIS] = 0;\ + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ + destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ + \ + destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ + feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ + \ + current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? LETTER##_HOME_POS : LETTER##_MAX_LENGTH;\ + destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ + feedrate = 0.0;\ + st_synchronize();\ + endstops_hit_on_purpose();\ + } + +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 + get_coordinates(); // For X Y Z E F + prepare_move(); + //ClearToSend(); + return; + //break; + case 2: // G2 - CW ARC + get_arc_coordinates(); + prepare_arc_move(true); + return; + case 3: // G3 - CCW ARC + get_arc_coordinates(); + prepare_arc_move(false); + return; + case 4: // G4 dwell + LCD_MESSAGEPGM("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(); + } + break; + case 28: //G28 Home all Axis one at a time + saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + + 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]))); + #ifdef QUICK_HOME + if( 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.1 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.1 * Y_MAX_LENGTH * Y_HOME_DIR; + feedrate = homing_feedrate[X_AXIS]; + if(homing_feedrate[Y_AXIS]= 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 + tmp_extruder = active_extruder; + if(code_seen('T')) { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHO("M104 Invalid extruder "); + SERIAL_ECHOLN(tmp_extruder); + 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 + tmp_extruder = active_extruder; + if(code_seen('T')) { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHO("M105 Invalid extruder "); + SERIAL_ECHOLN(tmp_extruder); + break; + } + } + #if (TEMP_0_PIN > -1) + SERIAL_PROTOCOLPGM("ok T:"); + SERIAL_PROTOCOL(degHotend(tmp_extruder)); + #if TEMP_BED_PIN > -1 + SERIAL_PROTOCOLPGM(" B:"); + SERIAL_PROTOCOL(degBed()); + #endif //TEMP_BED_PIN + #else + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("No thermistors - no temp"); + #endif + #ifdef PIDTEMP + SERIAL_PROTOCOLPGM(" @:"); + SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); + #endif + SERIAL_PROTOCOLLN(""); + return; + break; + case 109: + {// M109 - Wait for extruder heater to reach target. + tmp_extruder = active_extruder; + if(code_seen('T')) { + tmp_extruder = code_value(); + if(tmp_extruder >= EXTRUDERS) { + SERIAL_ECHO_START; + SERIAL_ECHO("M109 Invalid extruder "); + SERIAL_ECHOLN(tmp_extruder); + break; + } + } + LCD_MESSAGEPGM("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('G')) 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( degHotend(tmp_extruder) ); + 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(); + LCD_STATUS; + if(stop_heating_wait) break; + #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 && !isHeatingHotend(tmp_extruder)) || + (residencyStart == -1 && !target_direction && !isCoolingHotend(tmp_extruder)) || + (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) ) + { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGEPGM("Heating done."); + starttime=millis(); + previous_millis_cmd = millis(); + } + break; + case 190: // M190 - Wait for bed heater to reach target. + #if TEMP_BED_PIN > -1 + LCD_MESSAGEPGM("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_PROTOCOLLN(degBed()); + codenum = millis(); + } + manage_heater(); + } + LCD_MESSAGEPGM("Bed done."); + previous_millis_cmd = millis(); + #endif + break; + + #if FAN_PIN > -1 + case 106: //M106 Fan On + if (code_seen('S')){ + WRITE(FAN_PIN,HIGH); + fanpwm=constrain(code_value(),0,255); + analogWrite(FAN_PIN, fanpwm); + } + else { + WRITE(FAN_PIN,HIGH); + fanpwm=255; + analogWrite(FAN_PIN, fanpwm); + } + break; + case 107: //M107 Fan Off + WRITE(FAN_PIN,LOW); + analogWrite(FAN_PIN, 0); + break; + #endif //FAN_PIN + + #if (PS_ON_PIN > -1) + case 80: // M80 - ATX Power On + SET_OUTPUT(PS_ON_PIN); //GND + break; + #endif + + case 81: // M81 - ATX Power Off + + #if defined SUICIDE_PIN && SUICIDE_PIN > -1 + st_synchronize(); + suicide(); + #elif (PS_ON_PIN > -1) + SET_INPUT(PS_ON_PIN); //Floating + #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("Partial 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])) + axis_steps_per_unit[i] = code_value(); + } + break; + case 115: // M115 + SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n"); + 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(" 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 119: // M119 + #if (X_MIN_PIN > -1) + SERIAL_PROTOCOLPGM("x_min:"); + SERIAL_PROTOCOL(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); + #endif + #if (X_MAX_PIN > -1) + SERIAL_PROTOCOLPGM("x_max:"); + SERIAL_PROTOCOL(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); + #endif + #if (Y_MIN_PIN > -1) + SERIAL_PROTOCOLPGM("y_min:"); + SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); + #endif + #if (Y_MAX_PIN > -1) + SERIAL_PROTOCOLPGM("y_max:"); + SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); + #endif + #if (Z_MIN_PIN > -1) + SERIAL_PROTOCOLPGM("z_min:"); + SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); + #endif + #if (Z_MAX_PIN > -1) + SERIAL_PROTOCOLPGM("z_max:"); + SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); + #endif + SERIAL_PROTOCOLLN(""); + 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() ; + } + 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; + 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; + if(code_seen('W')) Ki_Max = constrain(code_value(),0,255); + #ifdef PID_ADD_EXTRUSION_RATE + if(code_seen('C')) Kc = code_value(); + #endif + updatePID(); + SERIAL_PROTOCOL("ok p:"); + SERIAL_PROTOCOL(Kp); + SERIAL_PROTOCOL(" i:"); + SERIAL_PROTOCOL(Ki/PID_dT); + SERIAL_PROTOCOL(" d:"); + SERIAL_PROTOCOL(Kd*PID_dT); + SERIAL_PROTOCOL(" w:"); + SERIAL_PROTOCOL(Ki_Max); + #ifdef PID_ADD_EXTRUSION_RATE + SERIAL_PROTOCOL(" c:"); + SERIAL_PROTOCOL(Kc*PID_dT); + #endif + 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: // finish all moves + { + allow_cold_extrudes(true); + } + break; + case 400: // 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; + + } + } + + 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("Invalid extruder"); + } + else { + active_extruder = tmp_extruder; + SERIAL_ECHO_START; + SERIAL_ECHO("Active Extruder: "); + SERIAL_PROTOCOLLN((int)active_extruder); + } + } + + else + { + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Unknown command:\""); + SERIAL_ECHO(cmdbuffer[bufindr]); + SERIAL_ECHOLNPGM("\""); + } + + ClearToSend(); +} + +void FlushSerialRequestResend() +{ + //char cmdbuffer[bufindr][100]="Resend:"; + MYSERIAL.flush(); + SERIAL_PROTOCOLPGM("Resend:"); + SERIAL_PROTOCOLLN(gcode_LastN + 1); + ClearToSend(); +} + +void ClearToSend() +{ + previous_millis_cmd = millis(); + #ifdef SDSUPPORT + if(fromsd[bufindr]) + return; + #endif //SDSUPPORT + SERIAL_PROTOCOLLNPGM("ok"); +} + +void get_coordinates() +{ + 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]; + 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; + } +} + +void get_arc_coordinates() +{ + get_coordinates(); + if(code_seen('I')) offset[0] = code_value(); + if(code_seen('J')) offset[1] = code_value(); +} + +void prepare_move() +{ + 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]; + } + previous_millis_cmd = millis(); +} + +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(); +} + +void manage_inactivity(byte debug) +{ + 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 ) + { + disable_x(); + disable_y(); + disable_z(); + disable_e0(); + disable_e1(); + disable_e2(); + } + } + #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("Printer halted. kill() called !!"); + LCD_MESSAGEPGM("KILLED. "); + suicide(); + while(1); // Wait for reset +} + + diff --git a/Marlin/language.h b/Marlin/language.h new file mode 100644 index 0000000000..6dfd7e0be1 --- /dev/null +++ b/Marlin/language.h @@ -0,0 +1,339 @@ +#ifndef LANGUAGE_H +#define LANGUAGE_H + +// Languages +// 1 Custom (For you to add your own messages) +// 2 English +// 3 French (Waiting translation) +// 4 German (Waiting translation) +// 5 Etc + +#define LANGUAGE_CHOICE 1 // Pick your language from the list above + +#if LANGUAGE_CHOICE == 1 + +// LCD Menu Messages + + #define WELCOME_MSG "RepRap Ready." + #define MSG_SD_INSERTED "Card Ready" + #define MSG_SD_REMOVED "Card Initiate" + #define MSG_MAIN " Main \003" + #define MSG_AUTOSTART " Autostart" + #define MSG_DISABLE_STEPPERS " Disable Steppers" + #define MSG_AUTO_HOME " Auto Home" + #define MSG_SET_ORIGIN " Set Origin" + #define MSG_PREHEAT_PLA " Preheat PLA" + #define MSG_PREHEAT_ABS " Preheat ABS" + #define MSG_COOLDOWN " Cooldown" + #define MSG_EXTRUDE " Extrude" + #define MSG_MOVE_AXIS " Move Axis \x7E" + #define MSG_SPEED " Speed:" + #define MSG_NOZZLE " \002Nozzle:" + #define MSG_BED " \002Bed:" + #define MSG_FAN_SPEED " Fan speed:" + #define MSG_FLOW " Flow:" + #define MSG_CONTROL " Control \003" + #define MSG_MIN " \002 Min:" + #define MSG_MAX " \002 Max:" + #define MSG_FACTOR " \002 Fact:" + #define MSG_AUTOTEMP " Autotemp:" + #define MSG_ON "On " + #define MSG_OFF "Off" + #define MSG_PID_P " PID-P: " + #define MSG_PID_I " PID-I: " + #define MSG_PID_D " PID-D: " + #define MSG_PID_C " PID-C: " + #define MSG_ACC " Acc:" + #define MSG_VXY_JERK " Vxy-jerk: " + #define MSG_VMAX " Vmax " + #define MSG_X "x:" + #define MSG_Y "y:" + #define MSG_Z "z:" + #define MSG_E "e:" + #define MSG_VMIN " Vmin:" + #define MSG_VTRAV_MIN " VTrav min:" + #define MSG_AMAX " Amax " + #define MSG_A_RETRACT " A-retract:" + #define MSG_XSTEPS " Xsteps/mm:" + #define MSG_YSTEPS " Ysteps/mm:" + #define MSG_ZSTEPS " Zsteps/mm:" + #define MSG_ESTEPS " Esteps/mm:" + #define MSG_MAIN_WIDE " Main \003" + #define MSG_TEMPERATURE_WIDE " Temperature \x7E" + #define MSG_MOTION_WIDE " Motion \x7E" + #define MSG_STORE_EPROM " Store EPROM" + #define MSG_LOAD_EPROM " Load EPROM" + #define MSG_RESTORE_FAILSAFE " Restore Failsafe" + #define MSG_REFRESH "\004Refresh" + #define MSG_WATCH " Watch \003" + #define MSG_PREPARE " Prepare \x7E" + #define MSG_CONTROL_ARROW " Control \x7E" + #define MSG_TUNE " Tune \x7E" + #define MSG_STOP_PRINT " Stop Print \x7E" + #define MSG_CARD_MENU " Card Menu \x7E" + #define MSG_NO_CARD " No Card" + #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." + +#endif + +#if LANGUAGE_CHOICE == 2 + +// LCD Menu Messages + + #define WELCOME_MSG "UltiMARLIN Ready." + #define MSG_SD_INSERTED "Card inserted" + #define MSG_SD_REMOVED "Card removed" + #define MSG_MAIN " Main \003" + #define MSG_AUTOSTART " Autostart" + #define MSG_DISABLE_STEPPERS " Disable Steppers" + #define MSG_AUTO_HOME " Auto Home" + #define MSG_SET_ORIGIN " Set Origin" + #define MSG_PREHEAT " Preheat" + #define MSG_COOLDOWN " Cooldown" + #define MSG_EXTRUDE " Extrude" + #define MSG_MOVE_AXIS " Move Axis \x7E" + #define MSG_SPEED " Speed:" + #define MSG_NOZZLE " \002Nozzle:" + #define MSG_BED " \002Bed:" + #define MSG_FAN_SPEED " Fan speed:" + #define MSG_FLOW " Flow:" + #define MSG_CONTROL " Control \003" + #define MSG_MIN " \002 Min:" + #define MSG_MAX " \002 Max:" + #define MSG_FACTOR " \002 Fact:" + #define MSG_AUTOTEMP " Autotemp:" + #define MSG_ON "On " + #define MSG_OFF "Off" + #define MSG_PID_P " PID-P: " + #define MSG_PID_I " PID-I: " + #define MSG_PID_D " PID-D: " + #define MSG_PID_C " PID-C: " + #define MSG_ACC " Acc:" + #define MSG_VXY_JERK " Vxy-jerk: " + #define MSG_VMAX " Vmax " + #define MSG_X "x:" + #define MSG_Y "y:" + #define MSG_Z "z:" + #define MSG_E "e:" + #define MSG_VMIN " Vmin:" + #define MSG_VTRAV_MIN " VTrav min:" + #define MSG_AMAX " Amax " + #define MSG_A_RETRACT " A-retract:" + #define MSG_XSTEPS " Xsteps/mm:" + #define MSG_YSTEPS " Ysteps/mm:" + #define MSG_ZSTEPS " Zsteps/mm:" + #define MSG_ESTEPS " Esteps/mm:" + #define MSG_MAIN_WIDE " Main \003" + #define MSG_TEMPERATURE_WIDE " Temperature \x7E" + #define MSG_MOTION_WIDE " Motion \x7E" + #define MSG_STORE_EPROM " Store EPROM" + #define MSG_LOAD_EPROM " Load EPROM" + #define MSG_RESTORE_FAILSAFE " Restore Failsafe" + #define MSG_REFRESH "\004Refresh" + #define MSG_WATCH " Watch \003" + #define MSG_PREPARE " Prepare \x7E" + #define MSG_CONTROL_ARROW " Control \x7E" + #define MSG_TUNE " Tune \x7E" + #define MSG_STOP_PRINT " Stop Print \x7E" + #define MSG_CARD_MENU " Card Menu \x7E" + #define MSG_NO_CARD " No Card" + #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." + +#endif + +#if LANGUAGE_CHOICE == 3 + +// LCD Menu Messages + + #define WELCOME_MSG "RepRap Ready." + #define MSG_SD_INSERTED "Card Ready" + #define MSG_SD_REMOVED "Card Initiate" + #define MSG_MAIN " Main \003" + #define MSG_AUTOSTART " Autostart" + #define MSG_DISABLE_STEPPERS " Disable Steppers" + #define MSG_AUTO_HOME " Auto Home" + #define MSG_SET_ORIGIN " Set Origin" + #define MSG_PREHEAT " Preheat" + #define MSG_COOLDOWN " Cooldown" + #define MSG_EXTRUDE " Extrude" + #define MSG_MOVE_AXIS " Move Axis \x7E" + #define MSG_SPEED " Speed:" + #define MSG_NOZZLE " \002Nozzle:" + #define MSG_BED " \002Bed:" + #define MSG_FAN_SPEED " Fan speed:" + #define MSG_FLOW " Flow:" + #define MSG_CONTROL " Control \003" + #define MSG_MIN " \002 Min:" + #define MSG_MAX " \002 Max:" + #define MSG_FACTOR " \002 Fact:" + #define MSG_AUTOTEMP " Autotemp:" + #define MSG_ON "On " + #define MSG_OFF "Off" + #define MSG_PID_P " PID-P: " + #define MSG_PID_I " PID-I: " + #define MSG_PID_D " PID-D: " + #define MSG_PID_C " PID-C: " + #define MSG_ACC " Acc:" + #define MSG_VXY_JERK " Vxy-jerk: " + #define MSG_VMAX " Vmax " + #define MSG_X "x:" + #define MSG_Y "y:" + #define MSG_Z "z:" + #define MSG_E "e:" + #define MSG_VMIN " Vmin:" + #define MSG_VTRAV_MIN " VTrav min:" + #define MSG_AMAX " Amax " + #define MSG_A_RETRACT " A-retract:" + #define MSG_XSTEPS " Xsteps/mm:" + #define MSG_YSTEPS " Ysteps/mm:" + #define MSG_ZSTEPS " Zsteps/mm:" + #define MSG_ESTEPS " Esteps/mm:" + #define MSG_MAIN_WIDE " Main \003" + #define MSG_TEMPERATURE_WIDE " Temperature \x7E" + #define MSG_MOTION_WIDE " Motion \x7E" + #define MSG_STORE_EPROM " Store EPROM" + #define MSG_LOAD_EPROM " Load EPROM" + #define MSG_RESTORE_FAILSAFE " Restore Failsafe" + #define MSG_REFRESH "\004Refresh" + #define MSG_WATCH " Watch \003" + #define MSG_PREPARE " Prepare \x7E" + #define MSG_CONTROL_ARROW " Control \x7E" + #define MSG_TUNE " Tune \x7E" + #define MSG_STOP_PRINT " Stop Print \x7E" + #define MSG_CARD_MENU " Card Menu \x7E" + #define MSG_NO_CARD " No Card" + #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." + +#endif + +#if LANGUAGE_CHOICE == 4 + +// LCD Menu Messages + + #define WELCOME_MSG "RepRap Ready." + #define MSG_SD_INSERTED "Card Ready" + #define MSG_SD_REMOVED "Card Initiate" + #define MSG_MAIN " Main \003" + #define MSG_AUTOSTART " Autostart" + #define MSG_DISABLE_STEPPERS " Disable Steppers" + #define MSG_AUTO_HOME " Auto Home" + #define MSG_SET_ORIGIN " Set Origin" + #define MSG_PREHEAT " Preheat" + #define MSG_COOLDOWN " Cooldown" + #define MSG_EXTRUDE " Extrude" + #define MSG_MOVE_AXIS " Move Axis \x7E" + #define MSG_SPEED " Speed:" + #define MSG_NOZZLE " \002Nozzle:" + #define MSG_BED " \002Bed:" + #define MSG_FAN_SPEED " Fan speed:" + #define MSG_FLOW " Flow:" + #define MSG_CONTROL " Control \003" + #define MSG_MIN " \002 Min:" + #define MSG_MAX " \002 Max:" + #define MSG_FACTOR " \002 Fact:" + #define MSG_AUTOTEMP " Autotemp:" + #define MSG_ON "On " + #define MSG_OFF "Off" + #define MSG_PID_P " PID-P: " + #define MSG_PID_I " PID-I: " + #define MSG_PID_D " PID-D: " + #define MSG_PID_C " PID-C: " + #define MSG_ACC " Acc:" + #define MSG_VXY_JERK " Vxy-jerk: " + #define MSG_VMAX " Vmax " + #define MSG_X "x:" + #define MSG_Y "y:" + #define MSG_Z "z:" + #define MSG_E "e:" + #define MSG_VMIN " Vmin:" + #define MSG_VTRAV_MIN " VTrav min:" + #define MSG_AMAX " Amax " + #define MSG_A_RETRACT " A-retract:" + #define MSG_XSTEPS " Xsteps/mm:" + #define MSG_YSTEPS " Ysteps/mm:" + #define MSG_ZSTEPS " Zsteps/mm:" + #define MSG_ESTEPS " Esteps/mm:" + #define MSG_MAIN_WIDE " Main \003" + #define MSG_TEMPERATURE_WIDE " Temperature \x7E" + #define MSG_MOTION_WIDE " Motion \x7E" + #define MSG_STORE_EPROM " Store EPROM" + #define MSG_LOAD_EPROM " Load EPROM" + #define MSG_RESTORE_FAILSAFE " Restore Failsafe" + #define MSG_REFRESH "\004Refresh" + #define MSG_WATCH " Watch \003" + #define MSG_PREPARE " Prepare \x7E" + #define MSG_CONTROL_ARROW " Control \x7E" + #define MSG_TUNE " Tune \x7E" + #define MSG_STOP_PRINT " Stop Print \x7E" + #define MSG_CARD_MENU " Card Menu \x7E" + #define MSG_NO_CARD " No Card" + #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." + +#endif + +#if LANGUAGE_CHOICE == 5 + +// LCD Menu Messages + + #define WELCOME_MSG "RepRap Ready." + #define MSG_SD_INSERTED "Card Ready" + #define MSG_SD_REMOVED "Card Initiate" + #define MSG_MAIN " Main \003" + #define MSG_AUTOSTART " Autostart" + #define MSG_DISABLE_STEPPERS " Disable Steppers" + #define MSG_AUTO_HOME " Auto Home" + #define MSG_SET_ORIGIN " Set Origin" + #define MSG_PREHEAT " Preheat" + #define MSG_COOLDOWN " Cooldown" + #define MSG_EXTRUDE " Extrude" + #define MSG_MOVE_AXIS " Move Axis \x7E" + #define MSG_SPEED " Speed:" + #define MSG_NOZZLE " \002Nozzle:" + #define MSG_BED " \002Bed:" + #define MSG_FAN_SPEED " Fan speed:" + #define MSG_FLOW " Flow:" + #define MSG_CONTROL " Control \003" + #define MSG_MIN " \002 Min:" + #define MSG_MAX " \002 Max:" + #define MSG_FACTOR " \002 Fact:" + #define MSG_AUTOTEMP " Autotemp:" + #define MSG_ON "On " + #define MSG_OFF "Off" + #define MSG_PID_P " PID-P: " + #define MSG_PID_I " PID-I: " + #define MSG_PID_D " PID-D: " + #define MSG_PID_C " PID-C: " + #define MSG_ACC " Acc:" + #define MSG_VXY_JERK " Vxy-jerk: " + #define MSG_VMAX " Vmax " + #define MSG_X "x:" + #define MSG_Y "y:" + #define MSG_Z "z:" + #define MSG_E "e:" + #define MSG_VMIN " Vmin:" + #define MSG_VTRAV_MIN " VTrav min:" + #define MSG_AMAX " Amax " + #define MSG_A_RETRACT " A-retract:" + #define MSG_XSTEPS " Xsteps/mm:" + #define MSG_YSTEPS " Ysteps/mm:" + #define MSG_ZSTEPS " Zsteps/mm:" + #define MSG_ESTEPS " Esteps/mm:" + #define MSG_MAIN_WIDE " Main \003" + #define MSG_TEMPERATURE_WIDE " Temperature \x7E" + #define MSG_MOTION_WIDE " Motion \x7E" + #define MSG_STORE_EPROM " Store EPROM" + #define MSG_LOAD_EPROM " Load EPROM" + #define MSG_RESTORE_FAILSAFE " Restore Failsafe" + #define MSG_REFRESH "\004Refresh" + #define MSG_WATCH " Watch \003" + #define MSG_PREPARE " Prepare \x7E" + #define MSG_CONTROL_ARROW " Control \x7E" + #define MSG_TUNE " Tune \x7E" + #define MSG_STOP_PRINT " Stop Print \x7E" + #define MSG_CARD_MENU " Card Menu \x7E" + #define MSG_NO_CARD " No Card" + #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." + +#endif + +#endif // ifndef LANGUAGE_H diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index b895b95e52..e877d43124 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -81,6 +81,8 @@ long position[4]; //rescaled from extern when axis_steps_per_unit are changed static float previous_speed[4]; // Speed of previous path line segment static float previous_nominal_speed; // Nominal speed of previous path line segment +extern volatile int extrudemultiply; // Sets extrude multiply factor (in percent) + #ifdef AUTOTEMP float autotemp_max=250; float autotemp_min=210; @@ -439,11 +441,12 @@ float junction_deviation = 0.1; // Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in // mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration // calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder) +void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, uint8_t &extruder) { // Calculate the buffer head after we push this byte int next_buffer_head = next_block_index(block_buffer_head); + // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. while(block_buffer_tail == next_buffer_head) { @@ -451,7 +454,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa manage_inactivity(1); LCD_STATUS; } - + // The target position of the tool in absolute steps // Calculate target position in absolute steps //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow @@ -488,6 +491,8 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); + block->steps_e *= extrudemultiply; + block->steps_e /= 100; block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); // Bail if this is a zero-length block @@ -512,16 +517,27 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // Enable all if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } + + // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill + int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + #ifdef SLOWDOWN + if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); + #endif + float delta_mm[4]; - delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; - delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; - delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; - delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS]; - if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { - block->millimeters = abs(delta_mm[E_AXIS]); - } else { - block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); - } + delta_mm[X_AXIS] = block->steps_x/axis_steps_per_unit[X_AXIS]; + delta_mm[Y_AXIS] = block->steps_y/axis_steps_per_unit[Y_AXIS]; + delta_mm[Z_AXIS] = block->steps_z/axis_steps_per_unit[Z_AXIS]; + delta_mm[E_AXIS] = block->steps_e/axis_steps_per_unit[E_AXIS]; +// if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { +// block->millimeters = abs(delta_mm[E_AXIS]); +// } else { +// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); +// } + + // TODO - JMG - SORT OUT RETRACTS WHEN e IS NOT ALONE + block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + + square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. @@ -537,12 +553,6 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa if(feed_rate 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); -#endif - /* // segment time im micro seconds long segment_time = lround(1000000.0/inverse_second); diff --git a/Marlin/planner.cpp~ b/Marlin/planner.cpp~ new file mode 100644 index 0000000000..0215c0cfd9 --- /dev/null +++ b/Marlin/planner.cpp~ @@ -0,0 +1,808 @@ +/* + planner.c - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ + +/* + Reasoning behind the mathematics in this module (in the key of 'Mathematica'): + + s == speed, a == acceleration, t == time, d == distance + + Basic definitions: + + Speed[s_, a_, t_] := s + (a*t) + Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] + + Distance to reach a specific speed with a constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] + d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() + + Speed after a given distance of travel with constant acceleration: + + Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] + m -> Sqrt[2 a d + s^2] + + DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] + + When to start braking (di) to reach a specified destionation speed (s2) after accelerating + from initial speed s1 without ever stopping at a plateau: + + Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] + di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() + + IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) +*/ + + + + +#include "Marlin.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" +#include "ultralcd.h" + +//=========================================================================== +//=============================public variables ============================ +//=========================================================================== + +unsigned long minsegmenttime; +float max_feedrate[4]; // set the max speeds +float axis_steps_per_unit[4]; +unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +float minimumfeedrate; +float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +float max_z_jerk; +float mintravelfeedrate; +unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + +// The current position of the tool in absolute steps +long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode +static float previous_speed[4]; // Speed of previous path line segment +static float previous_nominal_speed; // Nominal speed of previous path line segment + +extern volatile int extrudemultiply; // Sets extrude multiply factor (in percent) + +#ifdef AUTOTEMP + float autotemp_max=250; + float autotemp_min=210; + float autotemp_factor=0.1; + bool autotemp_enabled=false; +#endif + +//=========================================================================== +//=================semi-private variables, used in inline functions ===== +//=========================================================================== +block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions +volatile unsigned char block_buffer_head; // Index of the next block to be pushed +volatile unsigned char block_buffer_tail; // Index of the block to process now + +//=========================================================================== +//=============================private variables ============================ +//=========================================================================== +#ifdef PREVENT_DANGEROUS_EXTRUDE + bool allow_cold_extrude=false; +#endif +#ifdef XY_FREQUENCY_LIMIT + // Used for the frequency limit + static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations + static long x_segment_time[3]={0,0,0}; // Segment times (in us). Used for speed calculations + static long y_segment_time[3]={0,0,0}; +#endif + +// Returns the index of the next block in the ring buffer +// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. +static int8_t next_block_index(int8_t block_index) { + block_index++; + if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; } + return(block_index); +} + + +// Returns the index of the previous block in the ring buffer +static int8_t prev_block_index(int8_t block_index) { + if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; } + block_index--; + return(block_index); +} + +//=========================================================================== +//=============================functions ============================ +//=========================================================================== + +// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the +// given acceleration: +FORCE_INLINE float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) +{ + if (acceleration!=0) { + return((target_rate*target_rate-initial_rate*initial_rate)/ + (2.0*acceleration)); + } + else { + return 0.0; // acceleration was 0, set acceleration distance to 0 + } +} + +// This function gives you the point at which you must start braking (at the rate of -acceleration) if +// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after +// a total travel of distance. This can be used to compute the intersection point between acceleration and +// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) + +FORCE_INLINE float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) +{ + if (acceleration!=0) { + return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ + (4.0*acceleration) ); + } + else { + return 0.0; // acceleration was 0, set intersection distance to 0 + } +} + +// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. + +void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) { + unsigned long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) + unsigned long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) + + // Limit minimal step rate (Otherwise the timer will overflow.) + if(initial_rate <120) {initial_rate=120; } + if(final_rate < 120) {final_rate=120; } + + long acceleration = block->acceleration_st; + int32_t accelerate_steps = + ceil(estimate_acceleration_distance(block->initial_rate, block->nominal_rate, acceleration)); + int32_t decelerate_steps = + floor(estimate_acceleration_distance(block->nominal_rate, block->final_rate, -acceleration)); + + // Calculate the size of Plateau of Nominal Rate. + int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; + + // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will + // 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 = max(accelerate_steps,0); // Check limits due to numerical round-off + accelerate_steps = min(accelerate_steps,block->step_event_count); + plateau_steps = 0; + } + + #ifdef ADVANCE + volatile long initial_advance = block->advance*entry_factor*entry_factor; + volatile long final_advance = block->advance*exit_factor*exit_factor; + #endif // ADVANCE + + // block->accelerate_until = accelerate_steps; + // block->decelerate_after = accelerate_steps+plateau_steps; + CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section + if(block->busy == false) { // Don't update variables if block is busy. + block->accelerate_until = accelerate_steps; + block->decelerate_after = accelerate_steps+plateau_steps; + block->initial_rate = initial_rate; + block->final_rate = final_rate; + #ifdef ADVANCE + block->initial_advance = initial_advance; + block->final_advance = final_advance; + #endif //ADVANCE + } + CRITICAL_SECTION_END; +} + +// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the +// acceleration within the allotted distance. +FORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) { + return sqrt(target_velocity*target_velocity-2*acceleration*distance); +} + +// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. +// This method will calculate the junction jerk as the euclidean distance between the nominal +// velocities of the respective blocks. +//inline float junction_jerk(block_t *before, block_t *after) { +// return sqrt( +// pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); +//} + + +// The kernel called by planner_recalculate() when scanning the plan from last to first entry. +void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!current) { return; } + + if (next) { + // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising. + // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and + // check for maximum allowable speed reductions to ensure maximum possible planned speed. + if (current->entry_speed != current->max_entry_speed) { + + // If nominal length true, max junction speed is guaranteed to be reached. Only compute + // for max allowable speed if block is decelerating and nominal length is false. + if ((!current->nominal_length_flag) && (current->max_entry_speed > next->entry_speed)) { + current->entry_speed = min( current->max_entry_speed, + max_allowable_speed(-current->acceleration,next->entry_speed,current->millimeters)); + } else { + current->entry_speed = current->max_entry_speed; + } + current->recalculate_flag = true; + + } + } // Skip last block. Already initialized and set for recalculation. +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the reverse pass. +void planner_reverse_pass() { + uint8_t block_index = block_buffer_head; + if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { + block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); + block_t *block[3] = { NULL, NULL, NULL }; + while(block_index != block_buffer_tail) { + block_index = prev_block_index(block_index); + block[2]= block[1]; + block[1]= block[0]; + block[0] = &block_buffer[block_index]; + planner_reverse_pass_kernel(block[0], block[1], block[2]); + } + } +} + +// The kernel called by planner_recalculate() when scanning the plan from first to last entry. +void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { + if(!previous) { return; } + + // If the previous block is an acceleration block, but it is not long enough to complete the + // full speed change within the block, we need to adjust the entry speed accordingly. Entry + // speeds have already been reset, maximized, and reverse planned by reverse planner. + // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck. + if (!previous->nominal_length_flag) { + if (previous->entry_speed < current->entry_speed) { + double entry_speed = min( current->entry_speed, + max_allowable_speed(-previous->acceleration,previous->entry_speed,previous->millimeters) ); + + // Check for junction speed change + if (current->entry_speed != entry_speed) { + current->entry_speed = entry_speed; + current->recalculate_flag = true; + } + } + } +} + +// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This +// implements the forward pass. +void planner_forward_pass() { + uint8_t block_index = block_buffer_tail; + block_t *block[3] = { NULL, NULL, NULL }; + + while(block_index != block_buffer_head) { + block[0] = block[1]; + block[1] = block[2]; + block[2] = &block_buffer[block_index]; + planner_forward_pass_kernel(block[0],block[1],block[2]); + block_index = next_block_index(block_index); + } + planner_forward_pass_kernel(block[1], block[2], NULL); +} + +// Recalculates the trapezoid speed profiles for all blocks in the plan according to the +// entry_factor for each junction. Must be called by planner_recalculate() after +// updating the blocks. +void planner_recalculate_trapezoids() { + int8_t block_index = block_buffer_tail; + block_t *current; + block_t *next = NULL; + + while(block_index != block_buffer_head) { + current = next; + next = &block_buffer[block_index]; + if (current) { + // Recalculate if current block entry or exit junction speed has changed. + if (current->recalculate_flag || next->recalculate_flag) { + // NOTE: Entry and exit factors always > 0 by all previous logic operations. + calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed, + next->entry_speed/current->nominal_speed); + current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed + } + } + block_index = next_block_index( block_index ); + } + // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated. + if(next != NULL) { + calculate_trapezoid_for_block(next, next->entry_speed/next->nominal_speed, + MINIMUM_PLANNER_SPEED/next->nominal_speed); + next->recalculate_flag = false; + } +} + +// Recalculates the motion plan according to the following algorithm: +// +// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) +// so that: +// a. The junction jerk is within the set limit +// b. No speed reduction within one block requires faster deceleration than the one, true constant +// acceleration. +// 2. Go over every block in chronological order and dial down junction speed reduction values if +// a. The speed increase within one block would require faster accelleration than the one, true +// constant acceleration. +// +// When these stages are complete all blocks have an entry_factor that will allow all speed changes to +// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than +// the set limit. Finally it will: +// +// 3. Recalculate trapezoids for all blocks. + +void planner_recalculate() { + planner_reverse_pass(); + planner_forward_pass(); + planner_recalculate_trapezoids(); +} + +void plan_init() { + block_buffer_head = 0; + block_buffer_tail = 0; + memset(position, 0, sizeof(position)); // clear position + previous_speed[0] = 0.0; + previous_speed[1] = 0.0; + previous_speed[2] = 0.0; + previous_speed[3] = 0.0; + previous_nominal_speed = 0.0; +} + + + + +#ifdef AUTOTEMP +void getHighESpeed() +{ + static float oldt=0; + if(!autotemp_enabled) + return; + if(degTargetHotend0()+2high) + { + high=se; + } + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + + float g=autotemp_min+high*autotemp_factor; + float t=g; + if(tautotemp_max) + t=autotemp_max; + if(oldt>t) + { + t=AUTOTEMP_OLDWEIGHT*oldt+(1-AUTOTEMP_OLDWEIGHT)*t; + } + oldt=t; + setTargetHotend0(t); +// SERIAL_ECHO_START; +// SERIAL_ECHOPAIR("highe",high); +// SERIAL_ECHOPAIR(" t",t); +// SERIAL_ECHOLN(""); +} +#endif + +void check_axes_activity() { + unsigned char x_active = 0; + unsigned char y_active = 0; + unsigned char z_active = 0; + unsigned char e_active = 0; + block_t *block; + + if(block_buffer_tail != block_buffer_head) { + uint8_t block_index = block_buffer_tail; + while(block_index != block_buffer_head) { + block = &block_buffer[block_index]; + if(block->steps_x != 0) x_active++; + if(block->steps_y != 0) y_active++; + if(block->steps_z != 0) z_active++; + if(block->steps_e != 0) e_active++; + block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); + } + } + if((DISABLE_X) && (x_active == 0)) disable_x(); + if((DISABLE_Y) && (y_active == 0)) disable_y(); + if((DISABLE_Z) && (z_active == 0)) disable_z(); + if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } +} + + +float junction_deviation = 0.1; +// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in +// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration +// calculation the caller must also provide the physical length of the line in millimeters. +void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, uint8_t &extruder) +{ + // Calculate the buffer head after we push this byte + int next_buffer_head = next_block_index(block_buffer_head); + + + // If the buffer is full: good! That means we are well ahead of the robot. + // Rest here until there is room in the buffer. + while(block_buffer_tail == next_buffer_head) { + manage_heater(); + manage_inactivity(1); + LCD_STATUS; + } + + // The target position of the tool in absolute steps + // Calculate target position in absolute steps + //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow + long target[4]; + target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + + #ifdef PREVENT_DANGEROUS_EXTRUDE + if(target[E_AXIS]!=position[E_AXIS]) + if(degHotend(active_extruder)axis_steps_per_unit[E_AXIS]*EXTRUDE_MAXLENGTH) + { + position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM(" too long extrusion prevented"); + } + #endif + + // Prepare to set up new block + block_t *block = &block_buffer[block_buffer_head]; + + // Mark block as not busy (Not executed by the stepper interrupt) + block->busy = false; + + // Number of steps for each axis + block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); + block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); + block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); + block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); + block->steps_e *= extrudemultiply; + block->steps_e /= 100; + block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); + + // Bail if this is a zero-length block + if (block->step_event_count <=dropsegments) { return; }; + + // Compute direction bits for this block + block->direction_bits = 0; + if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<active_extruder = extruder; + + //enable active axes + if(block->steps_x != 0) enable_x(); + if(block->steps_y != 0) enable_y(); + #ifndef Z_LATE_ENABLE + if(block->steps_z != 0) enable_z(); + #endif + + // Enable all + if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } + + + // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill + int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + #ifdef SLOWDOWN + if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); + #endif + + float delta_mm[4]; + delta_mm[X_AXIS] = block->steps_x/axis_steps_per_unit[X_AXIS]; + delta_mm[Y_AXIS] = block->steps_y/axis_steps_per_unit[Y_AXIS]; + delta_mm[Z_AXIS] = block->steps_z/axis_steps_per_unit[Z_AXIS]; + delta_mm[E_AXIS] = block->steps_e/axis_steps_per_unit[E_AXIS]; +// if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { +// block->millimeters = abs(delta_mm[E_AXIS]); +// } else { +// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); +// } + block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + + square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); + float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides + + // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. + float inverse_second = feed_rate * inverse_millimeters; + + block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 + block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 + + if (block->steps_e == 0) { + if(feed_rate0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { + if (segment_time max_feedrate[i]) + speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); + } + +// Max segement time in us. +#ifdef XY_FREQUENCY_LIMIT +#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT) + + // Check and limit the xy direction change frequency + unsigned char direction_change = block->direction_bits ^ old_direction_bits; + old_direction_bits = block->direction_bits; + + if((direction_change & (1< max_feedrate[i]) + speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); + /* + if(speed_factor < 0.1) { + Serial.print("speed factor : "); Serial.println(speed_factor); + Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); + } + */ + } + for(unsigned char i=0; i < 4; i++) { + current_speed[i] *= speed_factor; + } + block->nominal_speed *= speed_factor; + block->nominal_rate *= speed_factor; + } + + // Compute and limit the acceleration rate for the trapezoid generator. + float steps_per_mm = block->step_event_count/block->millimeters; + if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { + block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 + } + else { + block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 + // Limit acceleration per axis + if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_y / (float)block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_e / (float)block->step_event_count) > axis_steps_per_sqr_second[E_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; + if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS]) + block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; + } + block->acceleration = block->acceleration_st / steps_per_mm; + block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); + +#if 0 // Use old jerk for now + // Compute path unit vector + double unit_vec[3]; + + unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; + unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; + unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; + + // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. + // Let a circle be tangent to both previous and current path line segments, where the junction + // deviation is defined as the distance from the junction to the closest edge of the circle, + // colinear with the circle center. The circular segment joining the two paths represents the + // path of centripetal acceleration. Solve for max velocity based on max acceleration about the + // radius of the circle, defined indirectly by junction deviation. This may be also viewed as + // path width or max_jerk in the previous grbl version. This approach does not actually deviate + // from path, but used as a robust way to compute cornering speeds, as it takes into account the + // nonlinearities of both the junction angle and junction velocity. + double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed + + // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles. + if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { + // Compute cosine of angle between previous and current path. (prev_unit_vec is negative) + // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity. + double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] + - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] + - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; + + // Skip and use default max junction speed for 0 degree acute junction. + if (cos_theta < 0.95) { + vmax_junction = min(previous_nominal_speed,block->nominal_speed); + // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds. + if (cos_theta > -0.95) { + // Compute maximum junction velocity based on maximum acceleration and junction deviation + double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. + vmax_junction = min(vmax_junction, + sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); + } + } + } +#endif + // Start with a safe speed + float vmax_junction = max_xy_jerk/2; + if(abs(current_speed[Z_AXIS]) > max_z_jerk/2) + vmax_junction = max_z_jerk/2; + vmax_junction = min(vmax_junction, block->nominal_speed); + + if ((moves_queued > 1) && (previous_nominal_speed > 0.0)) { + float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); + if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { + vmax_junction = block->nominal_speed; + } + if (jerk > max_xy_jerk) { + vmax_junction *= (max_xy_jerk/jerk); + } + if(abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { + vmax_junction *= (max_z_jerk/abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); + } + } + block->max_entry_speed = vmax_junction; + + // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. + double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); + block->entry_speed = min(vmax_junction, v_allowable); + + // Initialize planner efficiency flags + // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. + // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then + // the current block and next block junction speeds are guaranteed to always be at their maximum + // junction speeds in deceleration and acceleration, respectively. This is due to how the current + // block nominal speed limits both the current and next maximum junction speeds. Hence, in both + // the reverse and forward planners, the corresponding block junction speed will always be at the + // the maximum junction speed and may always be ignored for any speed reduction checks. + if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } + else { block->nominal_length_flag = false; } + block->recalculate_flag = true; // Always calculate trapezoid for new block + + // Update previous path unit_vector and nominal speed + memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[] + previous_nominal_speed = block->nominal_speed; + + #ifdef ADVANCE + // Calculate advance rate + if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { + block->advance_rate = 0; + block->advance = 0; + } + else { + long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); + float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * + (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUTION_AREA * EXTRUTION_AREA)*256; + block->advance = advance; + if(acc_dist == 0) { + block->advance_rate = 0; + } + else { + block->advance_rate = advance / (float)acc_dist; + } + } + /* + SERIAL_ECHO_START; + SERIAL_ECHOPGM("advance :"); + SERIAL_ECHO(block->advance/256.0); + SERIAL_ECHOPGM("advance rate :"); + SERIAL_ECHOLN(block->advance_rate/256.0); + */ + #endif // ADVANCE + + + + + calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, + MINIMUM_PLANNER_SPEED/block->nominal_speed); + + // Move buffer head + block_buffer_head = next_buffer_head; + + // Update position + memcpy(position, target, sizeof(target)); // position[] = target[] + + planner_recalculate(); + #ifdef AUTOTEMP + getHighESpeed(); + #endif + st_wake_up(); +} + +void plan_set_position(const float &x, const float &y, const float &z, const float &e) +{ + position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]); + previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. + previous_speed[0] = 0.0; + previous_speed[1] = 0.0; + previous_speed[2] = 0.0; + previous_speed[3] = 0.0; +} + +void plan_set_e_position(const float &e) +{ + position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + st_set_e_position(position[E_AXIS]); +} + +uint8_t movesplanned() +{ + return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); +} + +void allow_cold_extrudes(bool allow) +{ + #ifdef PREVENT_DANGEROUS_EXTRUDE + allow_cold_extrude=allow; + #endif +} diff --git a/Marlin/planner.h b/Marlin/planner.h index ac9719fbcf..c90581bfd8 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -67,7 +67,7 @@ void plan_init(); // Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in // millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder); +void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, uint8_t &extruder); // Set position. Used for G92 instructions. void plan_set_position(const float &x, const float &y, const float &z, const float &e); diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 40ba855f34..237425b1db 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -313,7 +313,7 @@ int temp2analog(int celsius, uint8_t e) { return (1023 * OVERSAMPLENR) - raw; } - return celsius * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR; + return ((celsius-TEMP_SENSOR_AD595_OFFSET)/TEMP_SENSOR_AD595_GAIN) * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR; } // Takes bed temperature value as input and returns corresponding raw value. @@ -343,7 +343,7 @@ int temp2analogBed(int celsius) { return (1023 * OVERSAMPLENR) - raw; #elif defined BED_USES_AD595 - return lround(celsius * (1024.0 * OVERSAMPLENR/ (5.0 * 100.0) ) ); + 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; @@ -391,7 +391,7 @@ float analog2temp(int raw, uint8_t e) { return celsius; } - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET; } // Derived from RepRap FiveD extruder::getTemperature() @@ -422,7 +422,7 @@ float analog2tempBed(int raw) { return celsius; #elif defined BED_USES_AD595 - return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; + 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. #endif @@ -852,13 +852,21 @@ ISR(TIMER0_COMPB_vect) for(unsigned char e = 0; e < EXTRUDERS; e++) { if(current_raw[e] >= maxttemp[e]) { target_raw[e] = 0; - max_temp_error(e); - kill();; + #if (PS_ON != -1) + { + max_temp_error(e); + kill();; + } + #endif } if(current_raw[e] <= minttemp[e]) { target_raw[e] = 0; - min_temp_error(e); - kill(); + #if (PS_ON != -1) + { + min_temp_error(e); + kill(); + } + #endif } } diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 08ac950d38..c4392d26fc 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -9,26 +9,25 @@ void beep(); void buttons_check(); - #define LCD_UPDATE_INTERVAL 100 #define STATUSTIMEOUT 15000 - - - extern LiquidCrystal lcd; - - + #ifdef NEWPANEL - - #define EN_C (1< -1) + #ifdef SDCARDDETECTINVERTED + #define CARDINSERTED (READ(SDCARDDETECT)!=0) + #else + #define CARDINSERTED (READ(SDCARDDETECT)==0) + #endif + #endif //SDCARDTETECTINVERTED + #else //atomatic, do not change @@ -50,7 +49,7 @@ #define blocktime 500 #define lcdslow 5 - enum MainStatus{Main_Status, Main_Menu, Main_Prepare, Main_Control, Main_SD,Sub_TempControl,Sub_MotionControl}; + enum MainStatus{Main_Status, Main_Menu, Main_Prepare,Sub_PrepareMove, Main_Control, Main_SD,Sub_TempControl,Sub_MotionControl}; class MainMenu{ public: @@ -67,6 +66,7 @@ void showControl(); void showControlMotion(); void showControlTemp(); + void showAxisMove(); void showSD(); bool force_lcd_update; int lastencoderpos; diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 68a5954752..54b7012848 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -9,6 +9,8 @@ extern volatile int feedmultiply; extern volatile bool feedmultiplychanged; +extern volatile int extrudemultiply; + extern long position[4]; extern CardReader card; @@ -122,7 +124,7 @@ void lcd_init() lcd.createChar(3,uplevel); lcd.createChar(4,refresh); lcd.createChar(5,folder); - LCD_MESSAGEPGM("UltiMarlin ready."); + LCD_MESSAGEPGM(WELCOME_MSG); } @@ -130,13 +132,17 @@ void beep() { //return; #ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int8_t i=0;i<20;i++){ - WRITE(BEEPER,HIGH); - delay(5); - WRITE(BEEPER,LOW); - delay(5); - } + #if (BEEPER > -1) + { + pinMode(BEEPER,OUTPUT); + for(int8_t i=0;i<20;i++){ + WRITE(BEEPER,HIGH); + delay(5); + WRITE(BEEPER,LOW); + delay(5); + } + } + #endif #endif } @@ -144,13 +150,17 @@ void beepshort() { //return; #ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int8_t i=0;i<10;i++){ - WRITE(BEEPER,HIGH); - delay(3); - WRITE(BEEPER,LOW); - delay(3); - } + #if (BEEPER > -1) + { + pinMode(BEEPER,OUTPUT); + for(int8_t i=0;i<10;i++){ + WRITE(BEEPER,HIGH); + delay(3); + WRITE(BEEPER,LOW); + delay(3); + } + } + #endif #endif } @@ -197,7 +207,11 @@ void buttons_init() WRITE(BTN_EN1,HIGH); WRITE(BTN_EN2,HIGH); WRITE(BTN_ENC,HIGH); - WRITE(SDCARDDETECT,HIGH); + #if (SDCARDDETECT > -1) + { + WRITE(SDCARDDETECT,HIGH); + } + #endif #else pinMode(SHIFT_CLK,OUTPUT); pinMode(SHIFT_LD,OUTPUT); @@ -360,7 +374,7 @@ void MainMenu::showStatus() if((currentz!=oldzpos)||force_lcd_update) { lcd.setCursor(10,1); - lcdprintPGM("Z:");lcd.print(ftostr32(current_position[2])); + lcdprintPGM("Z:");lcd.print(ftostr52(current_position[2])); oldzpos=currentz; } static int oldfeedmultiply=0; @@ -399,7 +413,6 @@ void MainMenu::showStatus() lcd.setCursor(7,2); lcd.print(itostr3((int)percent)); lcdprintPGM("%SD"); - } #else //smaller LCDS---------------------------------- @@ -445,7 +458,7 @@ void MainMenu::showStatus() force_lcd_update=false; } -enum {ItemP_exit, ItemP_autostart,ItemP_disstep,ItemP_home, ItemP_origin, ItemP_preheat, ItemP_cooldown,ItemP_extrude}; +enum {ItemP_exit, ItemP_autostart,ItemP_disstep,ItemP_home, ItemP_origin, ItemP_preheat_pla, ItemP_preheat_abs, ItemP_cooldown,/*ItemP_extrude,*/ItemP_move}; //any action must not contain a ',' character anywhere, or this breaks: #define MENUITEM(repaint_action, click_action) \ @@ -464,37 +477,205 @@ void MainMenu::showPrepare() switch(i) { case ItemP_exit: - MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemP_autostart: - MENUITEM( lcdprintPGM(" Autostart") , BLOCK;card.lastnr=0;card.setroot();card.checkautostart(true);beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_AUTOSTART) , BLOCK;card.lastnr=0;card.setroot();card.checkautostart(true);beepshort(); ) ; break; case ItemP_disstep: - MENUITEM( lcdprintPGM(" Disable Steppers") , BLOCK;enquecommand("M84");beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_DISABLE_STEPPERS) , BLOCK;enquecommand("M84");beepshort(); ) ; break; case ItemP_home: - MENUITEM( lcdprintPGM(" Auto Home") , BLOCK;enquecommand("G28 X-105 Y-105 Z0");beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_AUTO_HOME) , BLOCK;enquecommand("G28");beepshort(); ) ; break; case ItemP_origin: - MENUITEM( lcdprintPGM(" Set Origin") , BLOCK;enquecommand("G92 X0 Y0 Z0");beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_SET_ORIGIN) , BLOCK;enquecommand("G92 X0 Y0 Z0");beepshort(); ) ; break; - case ItemP_preheat: - MENUITEM( lcdprintPGM(" Preheat") , BLOCK;setTargetHotend0(170);setTargetBed(70);beepshort(); ) ; + case ItemP_preheat_pla: + MENUITEM( lcdprintPGM(MSG_PREHEAT_PLA) , BLOCK;setTargetHotend0(PLA_PREHEAT_HOTEND_TEMP);setTargetBed(PLA_PREHEAT_HPB_TEMP);analogWrite(FAN_PIN, PLA_PREHEAT_FAN_SPEED); beepshort(); ) ; + break; + case ItemP_preheat_abs: + MENUITEM( lcdprintPGM(MSG_PREHEAT_ABS) , BLOCK;setTargetHotend0(ABS_PREHEAT_HOTEND_TEMP);setTargetBed(ABS_PREHEAT_HPB_TEMP); analogWrite(FAN_PIN, ABS_PREHEAT_FAN_SPEED); beepshort(); ) ; break; case ItemP_cooldown: - MENUITEM( lcdprintPGM(" Cooldown") , BLOCK;setTargetHotend0(0);setTargetBed(0);beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_COOLDOWN) , BLOCK;setTargetHotend0(0);setTargetBed(0);beepshort(); ) ; break; - case ItemP_extrude: - MENUITEM( lcdprintPGM(" Extrude") , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ; +// case ItemP_extrude: + // MENUITEM( lcdprintPGM(" Extrude") , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ; + // break; + case ItemP_move: + MENUITEM( lcdprintPGM(MSG_MOVE_AXIS) , BLOCK;status=Sub_PrepareMove;beepshort(); ); break; - - - default: + default: break; } line++; } - updateActiveLines(ItemP_extrude,encoderpos); + updateActiveLines(ItemP_move,encoderpos); +} + +enum { + ItemAM_exit, + ItemAM_X, ItemAM_Y, ItemAM_Z, ItemAM_E +}; + +void MainMenu::showAxisMove() +{ + uint8_t line=0; + int oldencoderpos=0; + clearIfNecessary(); + for(int8_t i=lineoffset;i0) + { + enquecommand("G1 F700 X0.1"); + oldencoderpos=encoderpos; + encoderpos=0; + } + + else if (encoderpos < 0) + { + enquecommand("G1 F700 X-0.1"); + oldencoderpos=encoderpos; + encoderpos=0; + } + lcd.setCursor(11,line);lcd.print(ftostr52(current_position[X_AXIS])); + } + } + break; + case ItemAM_Y: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Y:"); + lcd.setCursor(11,line);lcd.print(ftostr52(current_position[Y_AXIS])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + enquecommand("G91"); + } + else + { + enquecommand("G90"); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if (encoderpos >0) + { + enquecommand("G1 F700 Y0.1"); + oldencoderpos=encoderpos; + encoderpos=0; + } + + else if (encoderpos < 0) + { + enquecommand("G1 F700 Y-0.1"); + oldencoderpos=encoderpos; + encoderpos=0; + } + lcd.setCursor(11,line);lcd.print(ftostr52(current_position[Y_AXIS])); + } + } + break; + case ItemAM_Z: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(" Z:"); + lcd.setCursor(11,line);lcd.print(ftostr52(current_position[Z_AXIS])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + enquecommand("G91"); + } + else + { + enquecommand("G90"); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if (encoderpos >0) + { + enquecommand("G1 F170 Z0.1"); + oldencoderpos=encoderpos; + encoderpos=0; + } + + else if (encoderpos < 0) + { + enquecommand("G1 F1700 Z-0.1"); + oldencoderpos=encoderpos; + encoderpos=0; + } + lcd.setCursor(11,line);lcd.print(ftostr52(current_position[Z_AXIS])); + } + } + break; + case ItemAM_E: + MENUITEM( lcdprintPGM(MSG_EXTRUDE) , BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E5");beepshort(); ) ; + break; + default: + break; + } + line++; + } + updateActiveLines(ItemAM_E,encoderpos); } enum {ItemT_exit,ItemT_speed,ItemT_flow,ItemT_nozzle, @@ -513,20 +694,20 @@ void MainMenu::showTune() switch(i) { case ItemT_exit: - MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemT_speed: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Speed:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_SPEED); lcd.setCursor(13,line);lcd.print(ftostr3(feedmultiply)); } if((activeline!=line) ) break; - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); + if(CLICKED) //AnalogWrite(FAN_PIN, fanpwm); { linechanging=!linechanging; if(linechanging) @@ -554,7 +735,7 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); } @@ -588,7 +769,7 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" \002Bed:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_BED); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetBed()))); } @@ -659,7 +840,7 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Flow:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_FLOW); lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); } @@ -740,13 +921,13 @@ void MainMenu::showControlTemp() switch(i) { case ItemCT_exit: - MENUITEM( lcdprintPGM(" Control \003") , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; break; case ItemCT_nozzle: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0()))); } @@ -781,7 +962,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" \002 Min:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_MIN); lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_min)); } @@ -815,7 +996,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" \002 Max:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_MAX); lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max)); } @@ -849,7 +1030,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" \002 Fact:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_FACTOR); lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor)); } @@ -883,12 +1064,12 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Autotemp:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_AUTOTEMP); lcd.setCursor(13,line); if(autotemp_enabled) - lcdprintPGM("On"); + lcdprintPGM(MSG_ON); else - lcdprintPGM("Off"); + lcdprintPGM(MSG_OFF); } if((activeline!=line) ) @@ -899,9 +1080,9 @@ void MainMenu::showControlTemp() autotemp_enabled=!autotemp_enabled; lcd.setCursor(13,line); if(autotemp_enabled) - lcdprintPGM("On "); + lcdprintPGM(MSG_ON); else - lcdprintPGM("Off"); + lcdprintPGM(MSG_OFF); BLOCK; } @@ -912,7 +1093,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" \002Bed:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_BED); lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetBed()))); } @@ -946,7 +1127,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_FAN_SPEED); lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); } @@ -1016,7 +1197,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" PID-I: "); + lcd.setCursor(0,line);lcdprintPGM(MSG_PID_I); lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT)); } @@ -1051,7 +1232,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" PID-D: "); + lcd.setCursor(0,line);lcdprintPGM(MSG_PID_D); lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT)); } @@ -1088,7 +1269,7 @@ void MainMenu::showControlTemp() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" PID-C: "); + lcd.setCursor(0,line);lcdprintPGM(MSG_PID_C); lcd.setCursor(13,line);lcd.print(itostr3(Kc)); } @@ -1140,7 +1321,7 @@ enum { ItemCM_vmaxx, ItemCM_vmaxy, ItemCM_vmaxz, ItemCM_vmaxe, ItemCM_vtravmin,ItemCM_vmin, ItemCM_amaxx, ItemCM_amaxy, ItemCM_amaxz, ItemCM_amaxe, - ItemCM_aret,ItemCM_esteps + ItemCM_aret, ItemCM_xsteps,ItemCM_ysteps, ItemCM_zsteps, ItemCM_esteps }; @@ -1154,13 +1335,13 @@ void MainMenu::showControlMotion() switch(i) { case ItemCM_exit: - MENUITEM( lcdprintPGM(" Control \003") , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; break; case ItemCM_acc: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Acc:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_ACC); lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcdprintPGM("00"); } @@ -1194,7 +1375,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: "); + lcd.setCursor(0,line);lcdprintPGM(MSG_VXY_JERK); lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk)); } @@ -1233,11 +1414,11 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Vmax "); - if(i==ItemCM_vmaxx)lcdprintPGM("x:"); - if(i==ItemCM_vmaxy)lcdprintPGM("y:"); - if(i==ItemCM_vmaxz)lcdprintPGM("z:"); - if(i==ItemCM_vmaxe)lcdprintPGM("e:"); + 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(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx])); } @@ -1273,7 +1454,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Vmin:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_VMIN); lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate)); } @@ -1308,7 +1489,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" VTrav min:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_VTRAV_MIN); lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate)); } @@ -1348,10 +1529,10 @@ void MainMenu::showControlMotion() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(" Amax "); - if(i==ItemCM_amaxx)lcdprintPGM("x:"); - if(i==ItemCM_amaxy)lcdprintPGM("y:"); - if(i==ItemCM_amaxz)lcdprintPGM("z:"); - if(i==ItemCM_amaxe)lcdprintPGM("e:"); + 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"); } @@ -1385,7 +1566,7 @@ void MainMenu::showControlMotion() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" A-retract:"); + lcd.setCursor(0,line);lcdprintPGM(MSG_A_RETRACT); lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00"); } @@ -1416,12 +1597,12 @@ void MainMenu::showControlMotion() } }break; - case ItemCM_esteps://axis_steps_per_unit[i] = code_value(); + case ItemCM_xsteps://axis_steps_per_unit[i] = code_value(); { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Esteps/mm:"); - lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + lcd.setCursor(0,line);lcdprintPGM(MSG_XSTEPS); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[0])); } if((activeline!=line) ) @@ -1432,14 +1613,51 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)axis_steps_per_unit[3]; + encoderpos=(int)(axis_steps_per_unit[0]*100.0); } else { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); - position[E_AXIS]=lround(position[E_AXIS]*factor); + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[0]); + position[X_AXIS]=lround(position[X_AXIS]*factor); //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; + axis_steps_per_unit[X_AXIS]= encoderpos/100.0; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>99999) encoderpos=99999; + lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); + } + + }break; + case ItemCM_ysteps://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_YSTEPS); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[1])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(axis_steps_per_unit[1]*100.0); + } + else + { + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[1]); + position[Y_AXIS]=lround(position[Y_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[Y_AXIS]= encoderpos/100.0; encoderpos=activeline*lcdslow; } @@ -1450,7 +1668,84 @@ void MainMenu::showControlMotion() { if(encoderpos<5) encoderpos=5; if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); + } + + }break; + case ItemCM_zsteps://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_ZSTEPS); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[2])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(axis_steps_per_unit[2]*100.0); + } + else + { + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[2]); + position[Z_AXIS]=lround(position[Z_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[Z_AXIS]= encoderpos/100.0; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); + } + + }break; + + case ItemCM_esteps://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_ESTEPS); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[3])); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(axis_steps_per_unit[3]*100.0); + } + else + { + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos/100.0; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); } }break; @@ -1477,19 +1772,19 @@ void MainMenu::showControl() switch(i) { case ItemC_exit: - MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_MAIN_WIDE) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemC_temp: - MENUITEM( lcdprintPGM(" Temperature \x7E") , BLOCK;status=Sub_TempControl;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_TEMPERATURE_WIDE) , BLOCK;status=Sub_TempControl;beepshort(); ) ; break; case ItemC_move: - MENUITEM( lcdprintPGM(" Motion \x7E") , BLOCK;status=Sub_MotionControl;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_MOTION_WIDE) , BLOCK;status=Sub_MotionControl;beepshort(); ) ; break; case ItemC_store: { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Store EPROM"); + lcd.setCursor(0,line);lcdprintPGM(MSG_STORE_EPROM); } if((activeline==line) && CLICKED) { @@ -1503,7 +1798,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Load EPROM"); + lcd.setCursor(0,line);lcdprintPGM(MSG_LOAD_EPROM); } if((activeline==line) && CLICKED) { @@ -1517,7 +1812,7 @@ void MainMenu::showControl() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Restore Failsafe"); + lcd.setCursor(0,line);lcdprintPGM(MSG_RESTORE_FAILSAFE); } if((activeline==line) && CLICKED) { @@ -1564,7 +1859,7 @@ void MainMenu::showSD() switch(i) { case 0: - MENUITEM( lcdprintPGM(" Main \003") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; break; // case 1: // { @@ -1595,7 +1890,7 @@ void MainMenu::showSD() // } // }break; case 1: - MENUITEM( lcd.print(" ");card.getWorkDirName();if(card.filename[0]=='/') lcdprintPGM("\004Refresh");else {lcd.print("\005");lcd.print(card.filename);lcd.print("/..");} , BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ; + MENUITEM( lcd.print(" ");card.getWorkDirName();if(card.filename[0]=='/') lcdprintPGM(MSG_REFRESH);else {lcd.print("\005");lcd.print(card.filename);lcd.print("/..");} , BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ; break; default: @@ -1636,7 +1931,7 @@ void MainMenu::showSD() status=Main_Status; lcd_status(card.filename); } - } + } } } @@ -1682,14 +1977,14 @@ void MainMenu::showMainMenu() switch(line) { case ItemM_watch: - MENUITEM( lcdprintPGM(" Watch \003") , BLOCK;status=Main_Status;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_WATCH) , BLOCK;status=Main_Status;beepshort(); ) ; break; case ItemM_prepare: - MENUITEM( if(!tune) lcdprintPGM(" Prepare \x7E");else lcdprintPGM(" Tune \x7E"); , BLOCK;status=Main_Prepare;beepshort(); ) ; + MENUITEM( if(!tune) lcdprintPGM(MSG_PREPARE);else lcdprintPGM(MSG_TUNE); , BLOCK;status=Main_Prepare;beepshort(); ) ; break; case ItemM_control: - MENUITEM( lcdprintPGM(" Control \x7E") , BLOCK;status=Main_Control;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_CONTROL_ARROW) , BLOCK;status=Main_Control;beepshort(); ) ; break; #ifdef SDSUPPORT case ItemM_file: @@ -1704,13 +1999,13 @@ void MainMenu::showMainMenu() #endif { if(card.sdprinting) - lcdprintPGM(" Stop Print \x7E"); + lcdprintPGM(MSG_STOP_PRINT); else - lcdprintPGM(" Card Menu \x7E"); + lcdprintPGM(MSG_CARD_MENU); } else { - lcdprintPGM(" No Card"); + lcdprintPGM(MSG_NO_CARD); } } #ifdef CARDINSERTED @@ -1730,7 +2025,7 @@ void MainMenu::showMainMenu() #endif default: SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Something is wrong in the MenuStructure."); + SERIAL_ERRORLNPGM(MSG_SERIAL_ERROR_MENU_STRUCTURE); break; } } @@ -1751,12 +2046,12 @@ void MainMenu::update() if(CARDINSERTED) { card.initsd(); - LCD_MESSAGEPGM("Card inserted"); + LCD_MESSAGEPGM(MSG_SD_INSERTED); } else { card.release(); - LCD_MESSAGEPGM("Card removed"); + LCD_MESSAGEPGM(MSG_SD_REMOVED); } } #endif @@ -1801,6 +2096,10 @@ void MainMenu::update() showPrepare(); } }break; + case Sub_PrepareMove: + { + showAxisMove(); + }break; case Main_Control: { showControl(); @@ -1927,6 +2226,21 @@ char *ftostr51(const float &x) return conv; } +// convert float to string with +123.45 format +char *ftostr52(const float &x) +{ + int xx=x*100; + conv[0]=(xx>=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/10000)%10+'0'; + conv[2]=(xx/1000)%10+'0'; + conv[3]=(xx/100)%10+'0'; + conv[4]='.'; + conv[5]=(xx/10)%10+'0'; + conv[6]=(xx)%10+'0'; + conv[7]=0; + return conv; +} #endif //ULTRA_LCD From 5ca66537dc4d8051079169ad49ed30ec9a9471df Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Wed, 29 Feb 2012 16:32:31 +0000 Subject: [PATCH 207/228] temp files removed --- Marlin/Configuration_adv.h~ | 221 --------- Marlin/pins.h~ | 905 ------------------------------------ 2 files changed, 1126 deletions(-) delete mode 100644 Marlin/Configuration_adv.h~ delete mode 100644 Marlin/pins.h~ diff --git a/Marlin/Configuration_adv.h~ b/Marlin/Configuration_adv.h~ deleted file mode 100644 index a19747d145..0000000000 --- a/Marlin/Configuration_adv.h~ +++ /dev/null @@ -1,221 +0,0 @@ -#ifndef __CONFIGURATION_ADV_H -#define __CONFIGURATION_ADV_H - -//=========================================================================== -//=============================Thermal Settings ============================ -//=========================================================================== - -// Select one of these only to define how the bed temp is read. -// -//#define BED_LIMIT_SWITCHING -#ifdef BED_LIMIT_SWITCHING - #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS -#endif -#define BED_CHECK_INTERVAL 5000 //ms - -//// Heating sanity check: -// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. -// It can be reset with another M104/M109 -//#define WATCHPERIOD 20000 //20 seconds - -// Wait for Cooldown -// This defines if the M109 call should not block if it is cooling down. -// example: From a current temp of 220, you set M109 S200. -// if CooldownNoWait is defined M109 will not wait for the cooldown to finish -#define CooldownNoWait true - -//Do not wait for M109 to finish when printing from SD card -//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING - -#ifdef PIDTEMP - // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. - // if Kc is choosen well, the additional required power due to increased melting should be compensated. - #define PID_ADD_EXTRUSION_RATE - #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) - #endif -#endif - - -//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode. -//The maximum buffered steps/sec of the extruder motor are called "se". -//You enter the autotemp mode by a M109 S T F -// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp -// you exit the value by any M109 without F* -// Also, if the temperature is set to a value 0 - #define THERMISTORHEATER_0 TEMP_SENSOR_0 - #define HEATER_0_USES_THERMISTOR -#endif -#if TEMP_SENSOR_1 > 0 - #define THERMISTORHEATER_1 TEMP_SENSOR_1 - #define HEATER_1_USES_THERMISTOR -#endif -#if TEMP_SENSOR_2 > 0 - #define THERMISTORHEATER_2 TEMP_SENSOR_2 - #define HEATER_2_USES_THERMISTOR -#endif -#if TEMP_SENSOR_BED > 0 - #define THERMISTORBED TEMP_SENSOR_BED - #define BED_USES_THERMISTOR -#endif -#if TEMP_SENSOR_0 == -1 - #define HEATER_0_USES_AD595 -#endif -#if TEMP_SENSOR_1 == -1 - #define HEATER_1_USES_AD595 -#endif -#if TEMP_SENSOR_2 == -1 - #define HEATER_2_USES_AD595 -#endif -#if TEMP_SENSOR_BED == -1 - #define BED_USES_AD595 -#endif -#if TEMP_SENSOR_0 == -2 - #define HEATER_0_USES_MAX6675 -#endif -#if TEMP_SENSOR_0 == 0 - #undef HEATER_0_MINTEMP - #undef HEATER_0_MAXTEMP -#endif -#if TEMP_SENSOR_1 == 0 - #undef HEATER_1_MINTEMP - #undef HEATER_1_MAXTEMP -#endif -#if TEMP_SENSOR_2 == 0 - #undef HEATER_2_MINTEMP - #undef HEATER_2_MAXTEMP -#endif -#if TEMP_SENSOR_BED == 0 - #undef BED_MINTEMP - #undef BED_MAXTEMP -#endif - - -#endif //__CONFIGURATION_ADV_H diff --git a/Marlin/pins.h~ b/Marlin/pins.h~ deleted file mode 100644 index 59f8fd5f3e..0000000000 --- a/Marlin/pins.h~ +++ /dev/null @@ -1,905 +0,0 @@ -#ifndef PINS_H -#define PINS_H - -#if MOTHERBOARD == 99 -#define KNOWN_BOARD 1 - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN -1 -#define X_MAX_PIN 16 - -#define Y_STEP_PIN 5 -#define Y_DIR_PIN 6 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 67 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 62 -#define Z_DIR_PIN 63 -#define Z_ENABLE_PIN -1 -#define Z_MIN_PIN 59 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 65 -#define E0_DIR_PIN 66 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 9 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 10 - -#endif /* 99 */ - -/**************************************************************************************** -* Arduino pin assignment -* -* ATMega168 -* +-\/-+ -* PC6 1| |28 PC5 (AI 5 / D19) -* (D 0) PD0 2| |27 PC4 (AI 4 / D18) -* (D 1) PD1 3| |26 PC3 (AI 3 / D17) -* (D 2) PD2 4| |25 PC2 (AI 2 / D16) -* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) -* (D 4) PD4 6| |23 PC0 (AI 0 / D14) -* VCC 7| |22 GND -* GND 8| |21 AREF -* PB6 9| |20 AVCC -* PB7 10| |19 PB5 (D 13) -* PWM+ (D 5) PD5 11| |18 PB4 (D 12) -* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -* (D 7) PD7 13| |16 PB2 (D 10) PWM -* (D 8) PB0 14| |15 PB1 (D 9) PWM -* +----+ -****************************************************************************************/ -#if MOTHERBOARD == 0 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega168__ -#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. -#endif - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 4 -#define X_MAX_PIN 9 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN 13 - -#define Z_STEP_PIN 19 -#define Z_DIR_PIN 18 -#define Z_ENABLE_PIN 5 -#define Z_MIN_PIN 17 -#define Z_MAX_PIN 16 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 15 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -#endif - - - -/**************************************************************************************** -* Sanguino/RepRap Motherboard with direct-drive extruders -* -* ATMega644P -* -* +---\/---+ -* (D 0) PB0 1| |40 PA0 (AI 0 / D31) -* (D 1) PB1 2| |39 PA1 (AI 1 / D30) -* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) -* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) -* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) -* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) -* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) -* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) -* RST 9| |32 AREF -* VCC 10| |31 GND -* GND 11| |30 AVCC -* XTAL2 12| |29 PC7 (D 23) -* XTAL1 13| |28 PC6 (D 22) -* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI -* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO -* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS -* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK -* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA -* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL -* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM -* +--------+ -* -****************************************************************************************/ -#if MOTHERBOARD == 1 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 19 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PIN 29 -#define Z_DIR_PIN 30 -#define Z_ENABLE_PIN 31 -#define Z_MIN_PIN 2 -#define Z_MAX_PIN 1 - -#define E0_STEP_PIN 12 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN 3 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN 0 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 14 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ - - - -#endif - - -/**************************************************************************************** -* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* -* -****************************************************************************************/ -#if MOTHERBOARD == 2 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PINN 27 -#define Z_DIR_PINN 28 -#define Z_ENABLE_PIN 29 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 31 - -#define E0_STEP_PIN 17 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 4 -#define LED_PIN 0 - -#define SD_CARD_WRITE 2 -#define SD_CARD_DETECT 3 -#define SD_CARD_SELECT 4 - -//our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 - -//pin for controlling the PSU. -#define PS_ON_PIN 14 - -#define FAN_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN -1 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#endif - -/**************************************************************************************** -* Arduino Mega pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 33 -#define MOTHERBOARD 3 -#define RAMPS_V_1_3 -#endif -#if MOTHERBOARD == 3 -#define KNOWN_BOARD 1 - -//////////////////FIX THIS////////////// -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 -// #define RAMPS_V_1_3 -// #define RAMPS_V_1_0 - -#ifdef RAMPS_V_1_3 - -#define X_STEP_PIN 54 -#define X_DIR_PIN 55 -#define X_ENABLE_PIN 38 -#define X_MIN_PIN 3 -#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. - -#define Y_STEP_PIN 60 -#define Y_DIR_PIN 61 -#define Y_ENABLE_PIN 56 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN 15 //15 - -#define Z_STEP_PIN 46 -#define Z_DIR_PIN 48 -#define Z_ENABLE_PIN 62 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN 19 //19 - -#define E0_STEP_PIN 26 -#define E0_DIR_PIN 28 -#define E0_ENABLE_PIN 24 - -#define E1_STEP_PIN 36 -#define E1_DIR_PIN 34 -#define E1_ENABLE_PIN 30 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 4 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#define HEATER_0_PIN 10 // EXTRUDER 1 -#define HEATER_1_PIN 9 // EXTRUDER 2 -#define HEATER_2_PIN -1 // EXTRUDER 2 -#define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 15 // ANALOG NUMBERING -#define TEMP_2_PIN -1 // ANALOG NUMBERING -#define HEATER_BED_PIN 8 // BED -#define TEMP_BED_PIN 14 // ANALOG NUMBERING - - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default - -#define X_STEP_PIN 26 -#define X_DIR_PIN 28 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 - -#define Y_STEP_PIN 38 -#define Y_DIR_PIN 40 -#define Y_ENABLE_PIN 36 -#define Y_MIN_PIN 16 -#define Y_MAX_PIN -1 //17 - -#define Z_STEP_PIN 44 -#define Z_DIR_PIN 46 -#define Z_ENABLE_PIN 42 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E0_STEP_PIN 32 -#define E0_DIR_PIN 34 -#define E0_ENABLE_PIN 30 - -#define SDPOWER 48 -#define SDSS 53 -#define LED_PIN 13 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - - - -#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 - #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_BED_PIN -1 // RAMPS 1.0 - #define FAN_PIN 11 // RAMPS 1.0 -#else // RAMPS_V_1_1 or RAMPS_V_1_2 - #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_BED_PIN 8 // RAMPS 1.1 - #define FAN_PIN 9 // RAMPS 1.1 -#endif -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#endif - -// SPI for Max6675 Thermocouple - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define MAX_SCK_PIN 52 - #define MAX_MISO_PIN 50 - #define MAX_MOSI_PIN 51 - #define MAX6675_SS 53 -#else - #define MAX6675_SS 49 -#endif - -#endif - -/**************************************************************************************** -* Duemilanove w/ ATMega328P pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 4 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega328P__ -#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 17 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 13 -#define Z_DIR_PIN 3 -#define Z_ENABLE_PIN 2 -#define Z_MIN_PIN 4 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN 5 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#endif - -/**************************************************************************************** -* Gen6 pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 5 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ - #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -//x axis pins - #define X_STEP_PIN 15 - #define X_DIR_PIN 18 - #define X_ENABLE_PIN 19 - #define X_MIN_PIN 20 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 25 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 27 - #define Z_DIR_PIN 28 - #define Z_ENABLE_PIN 29 - #define Z_MIN_PIN 30 - #define Z_MAX_PIN -1 - - //extruder pins - #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 - #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 - #define HEATER_2_PIN -1 - #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 - - #define SDPOWER -1 - #define SDSS 17 - #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define FAN_PIN -1 //changed @ rkoeppl 20110410 - #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 - //our pin for debugging. - - #define DEBUG_PIN 0 - - //our RS485 pins - #define TX_ENABLE_PIN 12 - #define RX_ENABLE_PIN 13 - - -#endif - -/**************************************************************************************** -* Sanguinololu pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 62 -#define MOTHERBOARD 6 -#define SANGUINOLOLU_V_1_2 -#endif -#if MOTHERBOARD == 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#ifndef __AVR_ATmega1284P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 21 -#define X_MIN_PIN 18 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 22 -#define Y_DIR_PIN 23 -#define Y_MIN_PIN 19 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 3 -#define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 1 -#define E0_DIR_PIN 0 - -#define LED_PIN -1 - -#define FAN_PIN 12 - -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 // (extruder) -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - -#ifdef SANGUINOLOLU_V_1_2 - -#define HEATER_BED_PIN 10 //12 // (bed) -#define X_ENABLE_PIN 14 -#define Y_ENABLE_PIN 14 -#define Z_ENABLE_PIN 26 -#define E0_ENABLE_PIN 14 - -#else - -#define HEATER_BED_PIN 14 // (bed) -#define X_ENABLE_PIN -1 -#define Y_ENABLE_PIN -1 -#define Z_ENABLE_PIN -1 -#define E0_ENABLE_PIN -1 - -#endif - -#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define SDPOWER -1 -#define SDSS 31 - -#endif - - -#if MOTHERBOARD == 7 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 22 -#define X_MAX_PIN 24 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 26 -#define Y_MAX_PIN 28 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 32 -#define Z_ENABLE_PIN 35 - -#define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 10 - -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define HEATER_1_PIN 3 -#define TEMP_1_PIN 9 - -#define HEATER_2_PIN -1 -#define TEMP_2_PIN -1 - -#define E0_STEP_PIN 43 -#define E0_DIR_PIN 45 -#define E0_ENABLE_PIN 41 - -#define E1_STEP_PIN 49 -#define E1_DIR_PIN 47 -#define E1_ENABLE_PIN 51 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 7 -#define PS_ON_PIN 12 -#define KILL_PIN -1 -#define SUICIDE_PIN 54 //PIN that has to be turned on right after start, to keep power flowing. - -#ifdef ULTRA_LCD - - #ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - #else //old style panel with shift register - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - //buttons are attached to a shift register - #define SHIFT_CLK 38 - #define SHIFT_LD 42 - #define SHIFT_OUT 40 - #define SHIFT_EN 17 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 5 - #define LCD_PINS_D4 6 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 20 - #define LCD_PINS_D7 19 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - - //bits in the shift register that carry the buttons for: - // left up center down right red - #define BL_LE 7 - #define BL_UP 6 - #define BL_MI 5 - #define BL_DW 4 - #define BL_RI 3 - #define BL_ST 2 - - #define BLEN_B 1 - #define BLEN_A 0 - #endif -#endif //ULTRA_LCD - -#endif - -#if MOTHERBOARD == 71 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment (Old electronics) -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 15 -#define X_MAX_PIN 14 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 17 -#define Y_MAX_PIN 16 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 19 -#define Z_MAX_PIN 18 -#define Z_ENABLE_PIN 35 - -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define HEATER_1_PIN 1 -#define TEMP_1_PIN 1 - -#define HEATER_2_PIN -1 -#define TEMP_2_PIN -1 - -#define E0_STEP_PIN 43 -#define E0_DIR_PIN 45 -#define E0_ENABLE_PIN 41 - -#define E1_STEP_PIN -1 -#define E1_DIR_PIN -1 -#define E1_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define SUICIDE_PIN -1 //PIN that has to be turned on right after start, to keep power flowing. - -#define LCD_PINS_RS 24 -#define LCD_PINS_ENABLE 22 -#define LCD_PINS_D4 36 -#define LCD_PINS_D5 34 -#define LCD_PINS_D6 32 -#define LCD_PINS_D7 30 - -#endif - -/**************************************************************************************** -* Teensylu 0.7 pin assingments (ATMEGA90USB) -* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! -****************************************************************************************/ -#if MOTHERBOARD == 8 -#define MOTHERBOARD 8 -#define KNOWN_BOARD 1 - - -#define X_STEP_PIN 0 -#define X_DIR_PIN 1 -#define X_ENABLE_PIN 39 -#define X_MIN_PIN 13 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 2 -#define Y_DIR_PIN 3 -#define Y_ENABLE_PIN 38 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 4 -#define Z_DIR_PIN 5 -#define Z_ENABLE_PIN 23 -#define Z_MIN_PIN 15 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 6 -#define E0_DIR_PIN 7 -#define E0_ENABLE_PIN 19 - - - -#define HEATER_0_PIN 21 // Extruder -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define HEATER_BED_PIN 20 // Bed -#define FAN_PIN 22 // Fan - -#define TEMP_0_PIN 7 // Extruder -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // Bed - -#define SDPOWER -1 -#define SDSS 8 -#define LED_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define ALARM_PIN -1 - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define SCK_PIN 9 - #define MISO_PIN 11 - #define MOSI_PIN 10 -#endif -#endif - -/**************************************************************************************** -* Gen3+ pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 9 -#define MOTHERBOARD 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_MIN_PIN 20 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 27 -#define Z_DIR_PIN 28 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 17 -#define E_DIR_PIN 21 - -#define LED_PIN -1 - -#define FAN_PIN -1 - -#define PS_ON_PIN 14 -#define KILL_PIN -1 - -#define HEATER_0_PIN 12 // (extruder) - -#define HEATER_1_PIN 16 // (bed) -#define X_ENABLE_PIN 19 -#define Y_ENABLE_PIN 24 -#define Z_ENABLE_PIN 29 -#define E_ENABLE_PIN 13 - -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN 5 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define TEMP_2_PIN -1 -#define SDPOWER -1 -#define SDSS 4 -#define HEATER_2_PIN -1 - -#endif - - - - -#ifndef KNOWN_BOARD -#error Unknown MOTHERBOARD value in configuration.h -#endif - -//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN -#if EXTRUDERS == 3 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN -#elif EXTRUDERS == 2 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS -1 -#elif EXTRUDERS == 1 - #define _E1_PINS -1 - #define _E2_PINS -1 -#else - #error Unsupported number of extruders -#endif -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ - HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ - HEATER_BED_PIN, FAN_PIN, \ - _E0_PINS, _E1_PINS, _E2_PINS, \ - TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } -#endif From 4eb543e4cabbed4296ed67be6b13271b9cdc5daa Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Wed, 29 Feb 2012 16:45:47 +0000 Subject: [PATCH 208/228] temp files no longer tracked --- Marlin/Configuration.h~ | 211 ------ Marlin/Marlin.pde~ | 1350 ------------------------------------ Marlin/planner.cpp~ | 808 --------------------- Marlin/thermistortables.h~ | 528 -------------- 4 files changed, 2897 deletions(-) delete mode 100644 Marlin/Configuration.h~ delete mode 100644 Marlin/Marlin.pde~ delete mode 100644 Marlin/planner.cpp~ delete mode 100644 Marlin/thermistortables.h~ diff --git a/Marlin/Configuration.h~ b/Marlin/Configuration.h~ deleted file mode 100644 index 25e7cf20cf..0000000000 --- a/Marlin/Configuration.h~ +++ /dev/null @@ -1,211 +0,0 @@ -#ifndef __CONFIGURATION_H -#define __CONFIGURATION_H - -// This configurtion file contains the basic settings. -// Advanced settings can be found in Configuration_adv.h -// BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration - -//User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. -//Implementation of an idea by Prof Braino to inform user that any changes made -//to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-02-08j" //Personal revision number for changes to THIS file. -#define STRING_CONFIG_H_AUTHOR "username" //Who made the changes. - -// This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 - -//// The following define selects which electronics board you have. Please choose the one that matches your setup -// MEGA/RAMPS up to 1.2 = 3, -// RAMPS 1.3 = 33 -// Gen6 = 5, -// Sanguinololu 1.2 and above = 62 -// Ultimaker = 7, -// Teensylu = 8, -// Gen3+ =9 -#define MOTHERBOARD 62 - -//=========================================================================== -//=============================Thermal Settings ============================ -//=========================================================================== - -//// Temperature sensor settings: -// -2 is thermocouple with MAX6675 (only for sensor 0) -// -1 is thermocouple with AD595 -// 0 is not used -// 1 is 100k thermistor -// 2 is 200k thermistor -// 3 is mendel-parts thermistor -// 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !! -// 5 is ParCan supplied 104GT-2 100K -// 6 is EPCOS 100k -// 7 is 100k Honeywell thermistor 135-104LAG-J01 -// 100 is 100k GE Sensing AL03006-58.2K-97-G1 -// 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT - -#define TEMP_SENSOR_0 100 -#define TEMP_SENSOR_1 0 -#define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 101 - -// Actual temperature must be close to target for this long before M109 returns success -#define TEMP_RESIDENCY_TIME 10 // (seconds) -#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one - -// The minimal temperature defines the temperature below which the heater will not be enabled It is used -// to check that the wiring to the thermistor is not broken. -// Otherwise this would lead to the heater being powered on all the time. -#define HEATER_0_MINTEMP 1 -//#define HEATER_1_MINTEMP 5 -//#define HEATER_2_MINTEMP 5 -#define BED_MINTEMP 1 - -// When temperature exceeds max temp, your heater will be switched off. -// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! -// You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 399 -//#define HEATER_1_MAXTEMP 275 -//#define HEATER_2_MAXTEMP 275 -#define BED_MAXTEMP 150 - -// PID settings: -// Comment the following line to disable PID and enable bang-bang. -#define PIDTEMP -#define PID_MAX 255 // limits current to nozzle; 255=full current -#ifdef PIDTEMP - //#define PID_DEBUG // Sends debug data to the serial port. - //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_INTEGRAL_DRIVE_MAX 130 //limit for the integral term - #define K1 0.95 //smoothing factor withing the PID - #define PID_dT 0.122 //sampling period of the PID - -// If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it -// Ultimaker -// #define DEFAULT_Kp 22.2 -// #define DEFAULT_Ki (1.25*PID_dT) -// #define DEFAULT_Kd (99/PID_dT) - -// Makergear -// #define DEFAULT_Kp 7.0 -// #define DEFAULT_Ki 0.1 -// #define DEFAULT_Kd 12 - -// RepRapPro Huxley - #define DEFAULT_Kp 3.0 - #define DEFAULT_Ki (2*PID_dT) - #define DEFAULT_Kd (80/PID_dT) - -// Mendel Parts V9 on 12V -// #define DEFAULT_Kp 63.0 -// #define DEFAULT_Ki (2.25*PID_dT) -// #define DEFAULT_Kd (440/PID_dT) -#endif // PIDTEMP - -//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit -//can be software-disabled for whatever purposes by -#define PREVENT_DANGEROUS_EXTRUDE -#define EXTRUDE_MINTEMP 170 -#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. - -//=========================================================================== -//=============================Mechanical Settings=========================== -//=========================================================================== - -// Endstop Settings -#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors - -// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. -const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. -const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. - -// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 -#define X_ENABLE_ON 0 -#define Y_ENABLE_ON 0 -#define Z_ENABLE_ON 0 -#define E_ENABLE_ON 0 // For all extruders - -// Disables axis when it's not being used. -#define DISABLE_X false -#define DISABLE_Y false -#define DISABLE_Z true -#define DISABLE_E false // For all extruders - -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true -#define INVERT_E0_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E2_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false - -// ENDSTOP SETTINGS: -// Sets direction of endstops when homing; 1=MAX, -1=MIN -#define X_HOME_DIR -1 -#define Y_HOME_DIR -1 -#define Z_HOME_DIR -1 - -#define min_software_endstops true //If true, axis won't move to coordinates less than zero. -#define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 150 -#define Y_MAX_LENGTH 148 -#define Z_MAX_LENGTH 100 - -//// MOVEMENT SETTINGS -#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) -#define FAST_HOME_FEEDRATE {80*60, 80*60, 4*60, 0} // set the homing speeds (mm/min) - -// default settings - -#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker -#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. - -#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for r retracts - -// -#define DEFAULT_XYJERK 20.0 // (mm/sec) -#define DEFAULT_ZJERK 0.4 // (mm/sec) - -//=========================================================================== -//=============================Additional Features=========================== -//=========================================================================== - -// EEPROM -// the microcontroller can store settings in the EEPROM, e.g. max velocity... -// 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. -//define this to enable eeprom support -#define EEPROM_SETTINGS -//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: -// please keep turned on if you can. -#define EEPROM_CHITCHAT - -//LCD and SD support -//#define ULTRA_LCD //general lcd support, also 16x2 -#define SDSUPPORT // Enable SD Card Support in Hardware Console - -//#define ULTIPANEL -#ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 - #define LCD_HEIGHT 4 -#else //no panel but just lcd - #ifdef ULTRA_LCD - #define LCD_WIDTH 16 - #define LCD_HEIGHT 2 - #endif -#endif - -// M240 Triggers a camera by emulating a Canon RC-1 Remote -// Data from: http://www.doc-diy.net/photo/rc-1_hacked/ -// #define PHOTOGRAPH_PIN 23 - -#include "Configuration_adv.h" -#include "thermistortables.h" - -#endif //__CONFIGURATION_H diff --git a/Marlin/Marlin.pde~ b/Marlin/Marlin.pde~ deleted file mode 100644 index da29fb37aa..0000000000 --- a/Marlin/Marlin.pde~ +++ /dev/null @@ -1,1350 +0,0 @@ -/* - 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" - -#define VERSION_STRING "1.0.0 RC2" - -// 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 -// G28 - Home all Axis -// G90 - Use Absolute Coordinates -// G91 - Use Relative Coordinates -// G92 - Set current position to cordinates given - -//RepRap M Codes -// 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 - 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 -// M206 - set additional homeing offset -// 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 -// 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) - -//Stepper Movement Variables - -//=========================================================================== -//=============================imported variables============================ -//=========================================================================== - - -//=========================================================================== -//=============================public variables============================= -//=========================================================================== -#ifdef SDSUPPORT -CardReader card; -#endif -float homing_feedrate[] = HOMING_FEEDRATE; -float fast_home_feedrate[] = FAST_HOME_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}; -uint8_t active_extruder = 0; -bool stop_heating_wait=false; - -//=========================================================================== -//=============================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; - -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 uint8_t fanpwm=0; - -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; - - -//=========================================================================== -//=============================ROUTINES============================= -//=========================================================================== - -void get_arc_coordinates(); - -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_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_powerhold(); - MYSERIAL.begin(BAUDRATE); - SERIAL_PROTOCOLLNPGM("start"); - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Marlin: "); - SERIAL_ECHOLNPGM(VERSION_STRING); - #ifdef STRING_VERSION_CONFIG_H - #ifdef STRING_CONFIG_H_AUTHOR - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Configuration.h: "); - SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); - SERIAL_ECHOPGM(" | Author: "); - SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); - #endif - #endif - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Free Memory:"); - SERIAL_ECHO(freeMemory()); - SERIAL_ECHOPGM(" PlannerBufferBytes:"); - 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(); -} - - -void loop() -{ - if(buflen<3) - 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("ok"); - } - else - { - card.closefile(); - SERIAL_PROTOCOLLNPGM("Done saving file."); - } - } - else - { - process_commands(); - } - #else - process_commands(); - #endif //SDSUPPORT - buflen = (buflen-1); - bufindr = (bufindr + 1)%BUFSIZE; - } - //check heater every n milliseconds - manage_heater(); - manage_inactivity(1); - 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 == ':' || 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("Line Number is not Last Line Number+1, Last Line:"); - 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("checksum mismatch, Last Line:"); - SERIAL_ERRORLN(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { - SERIAL_ERROR_START; - SERIAL_ERRORPGM("No Checksum with line number, Last Line:"); - 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("No Line Number with checksum, Last Line:"); - 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: - #ifdef SDSUPPORT - if(card.saving) - break; - #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM("ok"); - 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 == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) - { - if(card.eof()){ - SERIAL_PROTOCOLLNPGM("Done printing file"); - 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 HOMEAXIS(LETTER) \ - if ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))\ - { \ - current_position[LETTER##_AXIS] = 0; \ - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \ - destination[LETTER##_AXIS] = 1.1 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ - feedrate = fast_home_feedrate[LETTER##_AXIS]; \ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ - \ - current_position[LETTER##_AXIS] = 0;\ - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ - destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ - \ - destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ - feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ - \ - current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? LETTER##_HOME_POS : LETTER##_MAX_LENGTH;\ - destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ - feedrate = 0.0;\ - st_synchronize();\ - endstops_hit_on_purpose();\ - } - -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 - get_coordinates(); // For X Y Z E F - prepare_move(); - //ClearToSend(); - return; - //break; - case 2: // G2 - CW ARC - get_arc_coordinates(); - prepare_arc_move(true); - return; - case 3: // G3 - CCW ARC - get_arc_coordinates(); - prepare_arc_move(false); - return; - case 4: // G4 dwell - LCD_MESSAGEPGM("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(); - } - break; - case 28: //G28 Home all Axis one at a time - saved_feedrate = feedrate; - saved_feedmultiply = feedmultiply; - feedmultiply = 100; - - 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]))); - #ifdef QUICK_HOME - if( 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.1 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.1 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]; - if(homing_feedrate[Y_AXIS]= 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 - tmp_extruder = active_extruder; - if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHO("M104 Invalid extruder "); - SERIAL_ECHOLN(tmp_extruder); - 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 - tmp_extruder = active_extruder; - if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHO("M105 Invalid extruder "); - SERIAL_ECHOLN(tmp_extruder); - break; - } - } - #if (TEMP_0_PIN > -1) - SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL(degHotend(tmp_extruder)); - #if TEMP_BED_PIN > -1 - SERIAL_PROTOCOLPGM(" B:"); - SERIAL_PROTOCOL(degBed()); - #endif //TEMP_BED_PIN - #else - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("No thermistors - no temp"); - #endif - #ifdef PIDTEMP - SERIAL_PROTOCOLPGM(" @:"); - SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); - #endif - SERIAL_PROTOCOLLN(""); - return; - break; - case 109: - {// M109 - Wait for extruder heater to reach target. - tmp_extruder = active_extruder; - if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHO("M109 Invalid extruder "); - SERIAL_ECHOLN(tmp_extruder); - break; - } - } - LCD_MESSAGEPGM("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('G')) 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( degHotend(tmp_extruder) ); - 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(); - LCD_STATUS; - if(stop_heating_wait) break; - #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 && !isHeatingHotend(tmp_extruder)) || - (residencyStart == -1 && !target_direction && !isCoolingHotend(tmp_extruder)) || - (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) ) - { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGEPGM("Heating done."); - starttime=millis(); - previous_millis_cmd = millis(); - } - break; - case 190: // M190 - Wait for bed heater to reach target. - #if TEMP_BED_PIN > -1 - LCD_MESSAGEPGM("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_PROTOCOLLN(degBed()); - codenum = millis(); - } - manage_heater(); - } - LCD_MESSAGEPGM("Bed done."); - previous_millis_cmd = millis(); - #endif - break; - - #if FAN_PIN > -1 - case 106: //M106 Fan On - if (code_seen('S')){ - WRITE(FAN_PIN,HIGH); - fanpwm=constrain(code_value(),0,255); - analogWrite(FAN_PIN, fanpwm); - } - else { - WRITE(FAN_PIN,HIGH); - fanpwm=255; - analogWrite(FAN_PIN, fanpwm); - } - break; - case 107: //M107 Fan Off - WRITE(FAN_PIN,LOW); - analogWrite(FAN_PIN, 0); - break; - #endif //FAN_PIN - - #if (PS_ON_PIN > -1) - case 80: // M80 - ATX Power On - SET_OUTPUT(PS_ON_PIN); //GND - break; - #endif - - case 81: // M81 - ATX Power Off - - #if defined SUICIDE_PIN && SUICIDE_PIN > -1 - st_synchronize(); - suicide(); - #elif (PS_ON_PIN > -1) - SET_INPUT(PS_ON_PIN); //Floating - #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("Partial 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])) - axis_steps_per_unit[i] = code_value(); - } - break; - case 115: // M115 - SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n"); - 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(" 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 119: // M119 - #if (X_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("x_min:"); - SERIAL_PROTOCOL(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (X_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("x_max:"); - SERIAL_PROTOCOL(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Y_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("y_min:"); - SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Y_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("y_max:"); - SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Z_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("z_min:"); - SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Z_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("z_max:"); - SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - SERIAL_PROTOCOLLN(""); - 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() ; - } - 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; - 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; - if(code_seen('W')) Ki_Max = constrain(code_value(),0,255); - #ifdef PID_ADD_EXTRUSION_RATE - if(code_seen('C')) Kc = code_value(); - #endif - updatePID(); - SERIAL_PROTOCOL("ok p:"); - SERIAL_PROTOCOL(Kp); - SERIAL_PROTOCOL(" i:"); - SERIAL_PROTOCOL(Ki/PID_dT); - SERIAL_PROTOCOL(" d:"); - SERIAL_PROTOCOL(Kd*PID_dT); - SERIAL_PROTOCOL(" w:"); - SERIAL_PROTOCOL(Ki_Max); - #ifdef PID_ADD_EXTRUSION_RATE - SERIAL_PROTOCOL(" c:"); - SERIAL_PROTOCOL(Kc*PID_dT); - #endif - 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: // finish all moves - { - allow_cold_extrudes(true); - } - break; - case 400: // 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; - - } - } - - 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("Invalid extruder"); - } - else { - active_extruder = tmp_extruder; - SERIAL_ECHO_START; - SERIAL_ECHO("Active Extruder: "); - SERIAL_PROTOCOLLN((int)active_extruder); - } - } - - else - { - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Unknown command:\""); - SERIAL_ECHO(cmdbuffer[bufindr]); - SERIAL_ECHOLNPGM("\""); - } - - ClearToSend(); -} - -void FlushSerialRequestResend() -{ - //char cmdbuffer[bufindr][100]="Resend:"; - MYSERIAL.flush(); - SERIAL_PROTOCOLPGM("Resend:"); - SERIAL_PROTOCOLLN(gcode_LastN + 1); - ClearToSend(); -} - -void ClearToSend() -{ - previous_millis_cmd = millis(); - #ifdef SDSUPPORT - if(fromsd[bufindr]) - return; - #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM("ok"); -} - -void get_coordinates() -{ - 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]; - 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; - } -} - -void get_arc_coordinates() -{ - get_coordinates(); - if(code_seen('I')) offset[0] = code_value(); - if(code_seen('J')) offset[1] = code_value(); -} - -void prepare_move() -{ - 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]; - } - previous_millis_cmd = millis(); -} - -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(); -} - -void manage_inactivity(byte debug) -{ - 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 ) - { - disable_x(); - disable_y(); - disable_z(); - disable_e0(); - disable_e1(); - disable_e2(); - } - } - #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("Printer halted. kill() called !!"); - LCD_MESSAGEPGM("KILLED. "); - suicide(); - while(1); // Wait for reset -} - - diff --git a/Marlin/planner.cpp~ b/Marlin/planner.cpp~ deleted file mode 100644 index 0215c0cfd9..0000000000 --- a/Marlin/planner.cpp~ +++ /dev/null @@ -1,808 +0,0 @@ -/* - planner.c - buffers movement commands and manages the acceleration profile plan - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ - -/* - Reasoning behind the mathematics in this module (in the key of 'Mathematica'): - - s == speed, a == acceleration, t == time, d == distance - - Basic definitions: - - Speed[s_, a_, t_] := s + (a*t) - Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] - - Distance to reach a specific speed with a constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] - d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() - - Speed after a given distance of travel with constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] - m -> Sqrt[2 a d + s^2] - - DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] - - When to start braking (di) to reach a specified destionation speed (s2) after accelerating - from initial speed s1 without ever stopping at a plateau: - - Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] - di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() - - IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) -*/ - - - - -#include "Marlin.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" -#include "ultralcd.h" - -//=========================================================================== -//=============================public variables ============================ -//=========================================================================== - -unsigned long minsegmenttime; -float max_feedrate[4]; // set the max speeds -float axis_steps_per_unit[4]; -unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -float minimumfeedrate; -float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -float max_z_jerk; -float mintravelfeedrate; -unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - -// The current position of the tool in absolute steps -long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode -static float previous_speed[4]; // Speed of previous path line segment -static float previous_nominal_speed; // Nominal speed of previous path line segment - -extern volatile int extrudemultiply; // Sets extrude multiply factor (in percent) - -#ifdef AUTOTEMP - float autotemp_max=250; - float autotemp_min=210; - float autotemp_factor=0.1; - bool autotemp_enabled=false; -#endif - -//=========================================================================== -//=================semi-private variables, used in inline functions ===== -//=========================================================================== -block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions -volatile unsigned char block_buffer_head; // Index of the next block to be pushed -volatile unsigned char block_buffer_tail; // Index of the block to process now - -//=========================================================================== -//=============================private variables ============================ -//=========================================================================== -#ifdef PREVENT_DANGEROUS_EXTRUDE - bool allow_cold_extrude=false; -#endif -#ifdef XY_FREQUENCY_LIMIT - // Used for the frequency limit - static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations - static long x_segment_time[3]={0,0,0}; // Segment times (in us). Used for speed calculations - static long y_segment_time[3]={0,0,0}; -#endif - -// Returns the index of the next block in the ring buffer -// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. -static int8_t next_block_index(int8_t block_index) { - block_index++; - if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; } - return(block_index); -} - - -// Returns the index of the previous block in the ring buffer -static int8_t prev_block_index(int8_t block_index) { - if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; } - block_index--; - return(block_index); -} - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== - -// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the -// given acceleration: -FORCE_INLINE float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) -{ - if (acceleration!=0) { - return((target_rate*target_rate-initial_rate*initial_rate)/ - (2.0*acceleration)); - } - else { - return 0.0; // acceleration was 0, set acceleration distance to 0 - } -} - -// This function gives you the point at which you must start braking (at the rate of -acceleration) if -// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after -// a total travel of distance. This can be used to compute the intersection point between acceleration and -// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) - -FORCE_INLINE float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) -{ - if (acceleration!=0) { - return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ - (4.0*acceleration) ); - } - else { - return 0.0; // acceleration was 0, set intersection distance to 0 - } -} - -// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. - -void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) { - unsigned long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) - unsigned long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) - - // Limit minimal step rate (Otherwise the timer will overflow.) - if(initial_rate <120) {initial_rate=120; } - if(final_rate < 120) {final_rate=120; } - - long acceleration = block->acceleration_st; - int32_t accelerate_steps = - ceil(estimate_acceleration_distance(block->initial_rate, block->nominal_rate, acceleration)); - int32_t decelerate_steps = - floor(estimate_acceleration_distance(block->nominal_rate, block->final_rate, -acceleration)); - - // Calculate the size of Plateau of Nominal Rate. - int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; - - // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will - // 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 = max(accelerate_steps,0); // Check limits due to numerical round-off - accelerate_steps = min(accelerate_steps,block->step_event_count); - plateau_steps = 0; - } - - #ifdef ADVANCE - volatile long initial_advance = block->advance*entry_factor*entry_factor; - volatile long final_advance = block->advance*exit_factor*exit_factor; - #endif // ADVANCE - - // block->accelerate_until = accelerate_steps; - // block->decelerate_after = accelerate_steps+plateau_steps; - CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section - if(block->busy == false) { // Don't update variables if block is busy. - block->accelerate_until = accelerate_steps; - block->decelerate_after = accelerate_steps+plateau_steps; - block->initial_rate = initial_rate; - block->final_rate = final_rate; - #ifdef ADVANCE - block->initial_advance = initial_advance; - block->final_advance = final_advance; - #endif //ADVANCE - } - CRITICAL_SECTION_END; -} - -// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the -// acceleration within the allotted distance. -FORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) { - return sqrt(target_velocity*target_velocity-2*acceleration*distance); -} - -// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. -// This method will calculate the junction jerk as the euclidean distance between the nominal -// velocities of the respective blocks. -//inline float junction_jerk(block_t *before, block_t *after) { -// return sqrt( -// pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); -//} - - -// The kernel called by planner_recalculate() when scanning the plan from last to first entry. -void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { return; } - - if (next) { - // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising. - // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and - // check for maximum allowable speed reductions to ensure maximum possible planned speed. - if (current->entry_speed != current->max_entry_speed) { - - // If nominal length true, max junction speed is guaranteed to be reached. Only compute - // for max allowable speed if block is decelerating and nominal length is false. - if ((!current->nominal_length_flag) && (current->max_entry_speed > next->entry_speed)) { - current->entry_speed = min( current->max_entry_speed, - max_allowable_speed(-current->acceleration,next->entry_speed,current->millimeters)); - } else { - current->entry_speed = current->max_entry_speed; - } - current->recalculate_flag = true; - - } - } // Skip last block. Already initialized and set for recalculation. -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the reverse pass. -void planner_reverse_pass() { - uint8_t block_index = block_buffer_head; - if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { - block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); - block_t *block[3] = { NULL, NULL, NULL }; - while(block_index != block_buffer_tail) { - block_index = prev_block_index(block_index); - block[2]= block[1]; - block[1]= block[0]; - block[0] = &block_buffer[block_index]; - planner_reverse_pass_kernel(block[0], block[1], block[2]); - } - } -} - -// The kernel called by planner_recalculate() when scanning the plan from first to last entry. -void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!previous) { return; } - - // If the previous block is an acceleration block, but it is not long enough to complete the - // full speed change within the block, we need to adjust the entry speed accordingly. Entry - // speeds have already been reset, maximized, and reverse planned by reverse planner. - // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck. - if (!previous->nominal_length_flag) { - if (previous->entry_speed < current->entry_speed) { - double entry_speed = min( current->entry_speed, - max_allowable_speed(-previous->acceleration,previous->entry_speed,previous->millimeters) ); - - // Check for junction speed change - if (current->entry_speed != entry_speed) { - current->entry_speed = entry_speed; - current->recalculate_flag = true; - } - } - } -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the forward pass. -void planner_forward_pass() { - uint8_t block_index = block_buffer_tail; - block_t *block[3] = { NULL, NULL, NULL }; - - while(block_index != block_buffer_head) { - block[0] = block[1]; - block[1] = block[2]; - block[2] = &block_buffer[block_index]; - planner_forward_pass_kernel(block[0],block[1],block[2]); - block_index = next_block_index(block_index); - } - planner_forward_pass_kernel(block[1], block[2], NULL); -} - -// Recalculates the trapezoid speed profiles for all blocks in the plan according to the -// entry_factor for each junction. Must be called by planner_recalculate() after -// updating the blocks. -void planner_recalculate_trapezoids() { - int8_t block_index = block_buffer_tail; - block_t *current; - block_t *next = NULL; - - while(block_index != block_buffer_head) { - current = next; - next = &block_buffer[block_index]; - if (current) { - // Recalculate if current block entry or exit junction speed has changed. - if (current->recalculate_flag || next->recalculate_flag) { - // NOTE: Entry and exit factors always > 0 by all previous logic operations. - calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed, - next->entry_speed/current->nominal_speed); - current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed - } - } - block_index = next_block_index( block_index ); - } - // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated. - if(next != NULL) { - calculate_trapezoid_for_block(next, next->entry_speed/next->nominal_speed, - MINIMUM_PLANNER_SPEED/next->nominal_speed); - next->recalculate_flag = false; - } -} - -// Recalculates the motion plan according to the following algorithm: -// -// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) -// so that: -// a. The junction jerk is within the set limit -// b. No speed reduction within one block requires faster deceleration than the one, true constant -// acceleration. -// 2. Go over every block in chronological order and dial down junction speed reduction values if -// a. The speed increase within one block would require faster accelleration than the one, true -// constant acceleration. -// -// When these stages are complete all blocks have an entry_factor that will allow all speed changes to -// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than -// the set limit. Finally it will: -// -// 3. Recalculate trapezoids for all blocks. - -void planner_recalculate() { - planner_reverse_pass(); - planner_forward_pass(); - planner_recalculate_trapezoids(); -} - -void plan_init() { - block_buffer_head = 0; - block_buffer_tail = 0; - memset(position, 0, sizeof(position)); // clear position - previous_speed[0] = 0.0; - previous_speed[1] = 0.0; - previous_speed[2] = 0.0; - previous_speed[3] = 0.0; - previous_nominal_speed = 0.0; -} - - - - -#ifdef AUTOTEMP -void getHighESpeed() -{ - static float oldt=0; - if(!autotemp_enabled) - return; - if(degTargetHotend0()+2high) - { - high=se; - } - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - - float g=autotemp_min+high*autotemp_factor; - float t=g; - if(tautotemp_max) - t=autotemp_max; - if(oldt>t) - { - t=AUTOTEMP_OLDWEIGHT*oldt+(1-AUTOTEMP_OLDWEIGHT)*t; - } - oldt=t; - setTargetHotend0(t); -// SERIAL_ECHO_START; -// SERIAL_ECHOPAIR("highe",high); -// SERIAL_ECHOPAIR(" t",t); -// SERIAL_ECHOLN(""); -} -#endif - -void check_axes_activity() { - unsigned char x_active = 0; - unsigned char y_active = 0; - unsigned char z_active = 0; - unsigned char e_active = 0; - block_t *block; - - if(block_buffer_tail != block_buffer_head) { - uint8_t block_index = block_buffer_tail; - while(block_index != block_buffer_head) { - block = &block_buffer[block_index]; - if(block->steps_x != 0) x_active++; - if(block->steps_y != 0) y_active++; - if(block->steps_z != 0) z_active++; - if(block->steps_e != 0) e_active++; - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - } - if((DISABLE_X) && (x_active == 0)) disable_x(); - if((DISABLE_Y) && (y_active == 0)) disable_y(); - if((DISABLE_Z) && (z_active == 0)) disable_z(); - if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } -} - - -float junction_deviation = 0.1; -// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in -// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration -// calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, uint8_t &extruder) -{ - // Calculate the buffer head after we push this byte - int next_buffer_head = next_block_index(block_buffer_head); - - - // If the buffer is full: good! That means we are well ahead of the robot. - // Rest here until there is room in the buffer. - while(block_buffer_tail == next_buffer_head) { - manage_heater(); - manage_inactivity(1); - LCD_STATUS; - } - - // The target position of the tool in absolute steps - // Calculate target position in absolute steps - //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow - long target[4]; - target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - - #ifdef PREVENT_DANGEROUS_EXTRUDE - if(target[E_AXIS]!=position[E_AXIS]) - if(degHotend(active_extruder)axis_steps_per_unit[E_AXIS]*EXTRUDE_MAXLENGTH) - { - position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM(" too long extrusion prevented"); - } - #endif - - // Prepare to set up new block - block_t *block = &block_buffer[block_buffer_head]; - - // Mark block as not busy (Not executed by the stepper interrupt) - block->busy = false; - - // Number of steps for each axis - block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); - block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); - block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); - block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); - block->steps_e *= extrudemultiply; - block->steps_e /= 100; - block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); - - // Bail if this is a zero-length block - if (block->step_event_count <=dropsegments) { return; }; - - // Compute direction bits for this block - block->direction_bits = 0; - if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<active_extruder = extruder; - - //enable active axes - if(block->steps_x != 0) enable_x(); - if(block->steps_y != 0) enable_y(); - #ifndef Z_LATE_ENABLE - if(block->steps_z != 0) enable_z(); - #endif - - // Enable all - if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } - - - // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill - int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); - #ifdef SLOWDOWN - if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); - #endif - - float delta_mm[4]; - delta_mm[X_AXIS] = block->steps_x/axis_steps_per_unit[X_AXIS]; - delta_mm[Y_AXIS] = block->steps_y/axis_steps_per_unit[Y_AXIS]; - delta_mm[Z_AXIS] = block->steps_z/axis_steps_per_unit[Z_AXIS]; - delta_mm[E_AXIS] = block->steps_e/axis_steps_per_unit[E_AXIS]; -// if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { -// block->millimeters = abs(delta_mm[E_AXIS]); -// } else { -// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); -// } - block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + - square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); - float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides - - // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. - float inverse_second = feed_rate * inverse_millimeters; - - block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 - block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 - - if (block->steps_e == 0) { - if(feed_rate0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { - if (segment_time max_feedrate[i]) - speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); - } - -// Max segement time in us. -#ifdef XY_FREQUENCY_LIMIT -#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT) - - // Check and limit the xy direction change frequency - unsigned char direction_change = block->direction_bits ^ old_direction_bits; - old_direction_bits = block->direction_bits; - - if((direction_change & (1< max_feedrate[i]) - speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); - /* - if(speed_factor < 0.1) { - Serial.print("speed factor : "); Serial.println(speed_factor); - Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); - } - */ - } - for(unsigned char i=0; i < 4; i++) { - current_speed[i] *= speed_factor; - } - block->nominal_speed *= speed_factor; - block->nominal_rate *= speed_factor; - } - - // Compute and limit the acceleration rate for the trapezoid generator. - float steps_per_mm = block->step_event_count/block->millimeters; - if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { - block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 - } - else { - block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 - // Limit acceleration per axis - if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; - if(((float)block->acceleration_st * (float)block->steps_y / (float)block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; - if(((float)block->acceleration_st * (float)block->steps_e / (float)block->step_event_count) > axis_steps_per_sqr_second[E_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; - if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; - } - block->acceleration = block->acceleration_st / steps_per_mm; - block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); - -#if 0 // Use old jerk for now - // Compute path unit vector - double unit_vec[3]; - - unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; - unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; - unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; - - // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. - // Let a circle be tangent to both previous and current path line segments, where the junction - // deviation is defined as the distance from the junction to the closest edge of the circle, - // colinear with the circle center. The circular segment joining the two paths represents the - // path of centripetal acceleration. Solve for max velocity based on max acceleration about the - // radius of the circle, defined indirectly by junction deviation. This may be also viewed as - // path width or max_jerk in the previous grbl version. This approach does not actually deviate - // from path, but used as a robust way to compute cornering speeds, as it takes into account the - // nonlinearities of both the junction angle and junction velocity. - double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed - - // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles. - if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { - // Compute cosine of angle between previous and current path. (prev_unit_vec is negative) - // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity. - double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] - - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] - - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; - - // Skip and use default max junction speed for 0 degree acute junction. - if (cos_theta < 0.95) { - vmax_junction = min(previous_nominal_speed,block->nominal_speed); - // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds. - if (cos_theta > -0.95) { - // Compute maximum junction velocity based on maximum acceleration and junction deviation - double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. - vmax_junction = min(vmax_junction, - sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); - } - } - } -#endif - // Start with a safe speed - float vmax_junction = max_xy_jerk/2; - if(abs(current_speed[Z_AXIS]) > max_z_jerk/2) - vmax_junction = max_z_jerk/2; - vmax_junction = min(vmax_junction, block->nominal_speed); - - if ((moves_queued > 1) && (previous_nominal_speed > 0.0)) { - float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); - if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { - vmax_junction = block->nominal_speed; - } - if (jerk > max_xy_jerk) { - vmax_junction *= (max_xy_jerk/jerk); - } - if(abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { - vmax_junction *= (max_z_jerk/abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); - } - } - block->max_entry_speed = vmax_junction; - - // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. - double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); - block->entry_speed = min(vmax_junction, v_allowable); - - // Initialize planner efficiency flags - // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. - // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then - // the current block and next block junction speeds are guaranteed to always be at their maximum - // junction speeds in deceleration and acceleration, respectively. This is due to how the current - // block nominal speed limits both the current and next maximum junction speeds. Hence, in both - // the reverse and forward planners, the corresponding block junction speed will always be at the - // the maximum junction speed and may always be ignored for any speed reduction checks. - if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } - else { block->nominal_length_flag = false; } - block->recalculate_flag = true; // Always calculate trapezoid for new block - - // Update previous path unit_vector and nominal speed - memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[] - previous_nominal_speed = block->nominal_speed; - - #ifdef ADVANCE - // Calculate advance rate - if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { - block->advance_rate = 0; - block->advance = 0; - } - else { - long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); - float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUTION_AREA * EXTRUTION_AREA)*256; - block->advance = advance; - if(acc_dist == 0) { - block->advance_rate = 0; - } - else { - block->advance_rate = advance / (float)acc_dist; - } - } - /* - SERIAL_ECHO_START; - SERIAL_ECHOPGM("advance :"); - SERIAL_ECHO(block->advance/256.0); - SERIAL_ECHOPGM("advance rate :"); - SERIAL_ECHOLN(block->advance_rate/256.0); - */ - #endif // ADVANCE - - - - - calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, - MINIMUM_PLANNER_SPEED/block->nominal_speed); - - // Move buffer head - block_buffer_head = next_buffer_head; - - // Update position - memcpy(position, target, sizeof(target)); // position[] = target[] - - planner_recalculate(); - #ifdef AUTOTEMP - getHighESpeed(); - #endif - st_wake_up(); -} - -void plan_set_position(const float &x, const float &y, const float &z, const float &e) -{ - position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]); - previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. - previous_speed[0] = 0.0; - previous_speed[1] = 0.0; - previous_speed[2] = 0.0; - previous_speed[3] = 0.0; -} - -void plan_set_e_position(const float &e) -{ - position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - st_set_e_position(position[E_AXIS]); -} - -uint8_t movesplanned() -{ - return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); -} - -void allow_cold_extrudes(bool allow) -{ - #ifdef PREVENT_DANGEROUS_EXTRUDE - allow_cold_extrude=allow; - #endif -} diff --git a/Marlin/thermistortables.h~ b/Marlin/thermistortables.h~ deleted file mode 100644 index f4c25d357e..0000000000 --- a/Marlin/thermistortables.h~ +++ /dev/null @@ -1,528 +0,0 @@ -#ifndef THERMISTORTABLES_H_ -#define THERMISTORTABLES_H_ - -#include "Marlin.h" - -#define OVERSAMPLENR 16 - -#if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor - -const short temptable_1[][2] PROGMEM = { -{ 23*OVERSAMPLENR , 300 }, -{ 25*OVERSAMPLENR , 295 }, -{ 27*OVERSAMPLENR , 290 }, -{ 28*OVERSAMPLENR , 285 }, -{ 31*OVERSAMPLENR , 280 }, -{ 33*OVERSAMPLENR , 275 }, -{ 35*OVERSAMPLENR , 270 }, -{ 38*OVERSAMPLENR , 265 }, -{ 41*OVERSAMPLENR , 260 }, -{ 44*OVERSAMPLENR , 255 }, -{ 48*OVERSAMPLENR , 250 }, -{ 52*OVERSAMPLENR , 245 }, -{ 56*OVERSAMPLENR , 240 }, -{ 61*OVERSAMPLENR , 235 }, -{ 66*OVERSAMPLENR , 230 }, -{ 71*OVERSAMPLENR , 225 }, -{ 78*OVERSAMPLENR , 220 }, -{ 84*OVERSAMPLENR , 215 }, -{ 92*OVERSAMPLENR , 210 }, -{ 100*OVERSAMPLENR , 205 }, -{ 109*OVERSAMPLENR , 200 }, -{ 120*OVERSAMPLENR , 195 }, -{ 131*OVERSAMPLENR , 190 }, -{ 143*OVERSAMPLENR , 185 }, -{ 156*OVERSAMPLENR , 180 }, -{ 171*OVERSAMPLENR , 175 }, -{ 187*OVERSAMPLENR , 170 }, -{ 205*OVERSAMPLENR , 165 }, -{ 224*OVERSAMPLENR , 160 }, -{ 245*OVERSAMPLENR , 155 }, -{ 268*OVERSAMPLENR , 150 }, -{ 293*OVERSAMPLENR , 145 }, -{ 320*OVERSAMPLENR , 140 }, -{ 348*OVERSAMPLENR , 135 }, -{ 379*OVERSAMPLENR , 130 }, -{ 411*OVERSAMPLENR , 125 }, -{ 445*OVERSAMPLENR , 120 }, -{ 480*OVERSAMPLENR , 115 }, -{ 516*OVERSAMPLENR , 110 }, -{ 553*OVERSAMPLENR , 105 }, -{ 591*OVERSAMPLENR , 100 }, -{ 628*OVERSAMPLENR , 95 }, -{ 665*OVERSAMPLENR , 90 }, -{ 702*OVERSAMPLENR , 85 }, -{ 737*OVERSAMPLENR , 80 }, -{ 770*OVERSAMPLENR , 75 }, -{ 801*OVERSAMPLENR , 70 }, -{ 830*OVERSAMPLENR , 65 }, -{ 857*OVERSAMPLENR , 60 }, -{ 881*OVERSAMPLENR , 55 }, -{ 903*OVERSAMPLENR , 50 }, -{ 922*OVERSAMPLENR , 45 }, -{ 939*OVERSAMPLENR , 40 }, -{ 954*OVERSAMPLENR , 35 }, -{ 966*OVERSAMPLENR , 30 }, -{ 977*OVERSAMPLENR , 25 }, -{ 985*OVERSAMPLENR , 20 }, -{ 993*OVERSAMPLENR , 15 }, -{ 999*OVERSAMPLENR , 10 }, -{ 1004*OVERSAMPLENR , 5 }, -{ 1008*OVERSAMPLENR , 0 } //safety -}; -#endif -#if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor -const short temptable_2[][2] PROGMEM = { - {1*OVERSAMPLENR, 848}, - {54*OVERSAMPLENR, 275}, - {107*OVERSAMPLENR, 228}, - {160*OVERSAMPLENR, 202}, - {213*OVERSAMPLENR, 185}, - {266*OVERSAMPLENR, 171}, - {319*OVERSAMPLENR, 160}, - {372*OVERSAMPLENR, 150}, - {425*OVERSAMPLENR, 141}, - {478*OVERSAMPLENR, 133}, - {531*OVERSAMPLENR, 125}, - {584*OVERSAMPLENR, 118}, - {637*OVERSAMPLENR, 110}, - {690*OVERSAMPLENR, 103}, - {743*OVERSAMPLENR, 95}, - {796*OVERSAMPLENR, 86}, - {849*OVERSAMPLENR, 77}, - {902*OVERSAMPLENR, 65}, - {955*OVERSAMPLENR, 49}, - {1008*OVERSAMPLENR, 17}, - {1020*OVERSAMPLENR, 0} //safety -}; - -#endif -#if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts -const short temptable_3[][2] PROGMEM = { - {1*OVERSAMPLENR,864}, - {21*OVERSAMPLENR,300}, - {25*OVERSAMPLENR,290}, - {29*OVERSAMPLENR,280}, - {33*OVERSAMPLENR,270}, - {39*OVERSAMPLENR,260}, - {46*OVERSAMPLENR,250}, - {54*OVERSAMPLENR,240}, - {64*OVERSAMPLENR,230}, - {75*OVERSAMPLENR,220}, - {90*OVERSAMPLENR,210}, - {107*OVERSAMPLENR,200}, - {128*OVERSAMPLENR,190}, - {154*OVERSAMPLENR,180}, - {184*OVERSAMPLENR,170}, - {221*OVERSAMPLENR,160}, - {265*OVERSAMPLENR,150}, - {316*OVERSAMPLENR,140}, - {375*OVERSAMPLENR,130}, - {441*OVERSAMPLENR,120}, - {513*OVERSAMPLENR,110}, - {588*OVERSAMPLENR,100}, - {734*OVERSAMPLENR,80}, - {856*OVERSAMPLENR,60}, - {938*OVERSAMPLENR,40}, - {986*OVERSAMPLENR,20}, - {1008*OVERSAMPLENR,0}, - {1018*OVERSAMPLENR,-20} - }; - -#endif -#if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor -const short temptable_4[][2] PROGMEM = { - {1*OVERSAMPLENR, 430}, - {54*OVERSAMPLENR, 137}, - {107*OVERSAMPLENR, 107}, - {160*OVERSAMPLENR, 91}, - {213*OVERSAMPLENR, 80}, - {266*OVERSAMPLENR, 71}, - {319*OVERSAMPLENR, 64}, - {372*OVERSAMPLENR, 57}, - {425*OVERSAMPLENR, 51}, - {478*OVERSAMPLENR, 46}, - {531*OVERSAMPLENR, 41}, - {584*OVERSAMPLENR, 35}, - {637*OVERSAMPLENR, 30}, - {690*OVERSAMPLENR, 25}, - {743*OVERSAMPLENR, 20}, - {796*OVERSAMPLENR, 14}, - {849*OVERSAMPLENR, 7}, - {902*OVERSAMPLENR, 0}, - {955*OVERSAMPLENR, -11}, - {1008*OVERSAMPLENR, -35} -}; -#endif - -#if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) -const short temptable_5[][2] PROGMEM = { -{1*OVERSAMPLENR, 713}, -{18*OVERSAMPLENR, 316}, -{35*OVERSAMPLENR, 266}, -{52*OVERSAMPLENR, 239}, -{69*OVERSAMPLENR, 221}, -{86*OVERSAMPLENR, 208}, -{103*OVERSAMPLENR, 197}, -{120*OVERSAMPLENR, 188}, -{137*OVERSAMPLENR, 181}, -{154*OVERSAMPLENR, 174}, -{171*OVERSAMPLENR, 169}, -{188*OVERSAMPLENR, 163}, -{205*OVERSAMPLENR, 159}, -{222*OVERSAMPLENR, 154}, -{239*OVERSAMPLENR, 150}, -{256*OVERSAMPLENR, 147}, -{273*OVERSAMPLENR, 143}, -{290*OVERSAMPLENR, 140}, -{307*OVERSAMPLENR, 136}, -{324*OVERSAMPLENR, 133}, -{341*OVERSAMPLENR, 130}, -{358*OVERSAMPLENR, 128}, -{375*OVERSAMPLENR, 125}, -{392*OVERSAMPLENR, 122}, -{409*OVERSAMPLENR, 120}, -{426*OVERSAMPLENR, 117}, -{443*OVERSAMPLENR, 115}, -{460*OVERSAMPLENR, 112}, -{477*OVERSAMPLENR, 110}, -{494*OVERSAMPLENR, 108}, -{511*OVERSAMPLENR, 106}, -{528*OVERSAMPLENR, 103}, -{545*OVERSAMPLENR, 101}, -{562*OVERSAMPLENR, 99}, -{579*OVERSAMPLENR, 97}, -{596*OVERSAMPLENR, 95}, -{613*OVERSAMPLENR, 92}, -{630*OVERSAMPLENR, 90}, -{647*OVERSAMPLENR, 88}, -{664*OVERSAMPLENR, 86}, -{681*OVERSAMPLENR, 84}, -{698*OVERSAMPLENR, 81}, -{715*OVERSAMPLENR, 79}, -{732*OVERSAMPLENR, 77}, -{749*OVERSAMPLENR, 75}, -{766*OVERSAMPLENR, 72}, -{783*OVERSAMPLENR, 70}, -{800*OVERSAMPLENR, 67}, -{817*OVERSAMPLENR, 64}, -{834*OVERSAMPLENR, 61}, -{851*OVERSAMPLENR, 58}, -{868*OVERSAMPLENR, 55}, -{885*OVERSAMPLENR, 52}, -{902*OVERSAMPLENR, 48}, -{919*OVERSAMPLENR, 44}, -{936*OVERSAMPLENR, 40}, -{953*OVERSAMPLENR, 34}, -{970*OVERSAMPLENR, 28}, -{987*OVERSAMPLENR, 20}, -{1004*OVERSAMPLENR, 8}, -{1021*OVERSAMPLENR, 0} -}; -#endif - -#if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor -const short temptable_6[][2] PROGMEM = { - {28*OVERSAMPLENR, 250}, - {31*OVERSAMPLENR, 245}, - {35*OVERSAMPLENR, 240}, - {39*OVERSAMPLENR, 235}, - {42*OVERSAMPLENR, 230}, - {44*OVERSAMPLENR, 225}, - {49*OVERSAMPLENR, 220}, - {53*OVERSAMPLENR, 215}, - {62*OVERSAMPLENR, 210}, - {73*OVERSAMPLENR, 205}, - {72*OVERSAMPLENR, 200}, - {94*OVERSAMPLENR, 190}, - {102*OVERSAMPLENR, 185}, - {116*OVERSAMPLENR, 170}, - {143*OVERSAMPLENR, 160}, - {183*OVERSAMPLENR, 150}, - {223*OVERSAMPLENR, 140}, - {270*OVERSAMPLENR, 130}, - {318*OVERSAMPLENR, 120}, - {383*OVERSAMPLENR, 110}, - {413*OVERSAMPLENR, 105}, - {439*OVERSAMPLENR, 100}, - {484*OVERSAMPLENR, 95}, - {513*OVERSAMPLENR, 90}, - {607*OVERSAMPLENR, 80}, - {664*OVERSAMPLENR, 70}, - {781*OVERSAMPLENR, 60}, - {810*OVERSAMPLENR, 55}, - {849*OVERSAMPLENR, 50}, - {914*OVERSAMPLENR, 45}, - {914*OVERSAMPLENR, 40}, - {935*OVERSAMPLENR, 35}, - {954*OVERSAMPLENR, 30}, - {970*OVERSAMPLENR, 25}, - {978*OVERSAMPLENR, 22}, - {1008*OVERSAMPLENR, 3} -}; -#endif - -#if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 -const short temptable_7[][2] PROGMEM = { - {46*OVERSAMPLENR, 270}, - {50*OVERSAMPLENR, 265}, - {54*OVERSAMPLENR, 260}, - {58*OVERSAMPLENR, 255}, - {62*OVERSAMPLENR, 250}, - {67*OVERSAMPLENR, 245}, - {72*OVERSAMPLENR, 240}, - {79*OVERSAMPLENR, 235}, - {85*OVERSAMPLENR, 230}, - {91*OVERSAMPLENR, 225}, - {99*OVERSAMPLENR, 220}, - {107*OVERSAMPLENR, 215}, - {116*OVERSAMPLENR, 210}, - {126*OVERSAMPLENR, 205}, - {136*OVERSAMPLENR, 200}, - {149*OVERSAMPLENR, 195}, - {160*OVERSAMPLENR, 190}, - {175*OVERSAMPLENR, 185}, - {191*OVERSAMPLENR, 180}, - {209*OVERSAMPLENR, 175}, - {224*OVERSAMPLENR, 170}, - {246*OVERSAMPLENR, 165}, - {267*OVERSAMPLENR, 160}, - {293*OVERSAMPLENR, 155}, - {316*OVERSAMPLENR, 150}, - {340*OVERSAMPLENR, 145}, - {364*OVERSAMPLENR, 140}, - {396*OVERSAMPLENR, 135}, - {425*OVERSAMPLENR, 130}, - {460*OVERSAMPLENR, 125}, - {489*OVERSAMPLENR, 120}, - {526*OVERSAMPLENR, 115}, - {558*OVERSAMPLENR, 110}, - {591*OVERSAMPLENR, 105}, - {628*OVERSAMPLENR, 100}, - {660*OVERSAMPLENR, 95}, - {696*OVERSAMPLENR, 90}, - {733*OVERSAMPLENR, 85}, - {761*OVERSAMPLENR, 80}, - {794*OVERSAMPLENR, 75}, - {819*OVERSAMPLENR, 70}, - {847*OVERSAMPLENR, 65}, - {870*OVERSAMPLENR, 60}, - {892*OVERSAMPLENR, 55}, - {911*OVERSAMPLENR, 50}, - {929*OVERSAMPLENR, 45}, - {944*OVERSAMPLENR, 40}, - {959*OVERSAMPLENR, 35}, - {971*OVERSAMPLENR, 30}, - {981*OVERSAMPLENR, 25}, - {989*OVERSAMPLENR, 20}, - {994*OVERSAMPLENR, 15}, - {1001*OVERSAMPLENR, 10}, - {1005*OVERSAMPLENR, 5} -}; -#endif -// -#if (THERMISTORHEATER_0 == 100) || (THERMISTORHEATER_1 == 100) || (THERMISTORHEATER_2 == 100) || (THERMISTORBED == 100) // 100k DO-35 NTC -const short temptable_100[][2] PROGMEM = { - {1*OVERSAMPLENR, 929}, - {36*OVERSAMPLENR, 299}, - {71*OVERSAMPLENR, 246}, - {106*OVERSAMPLENR, 217}, - {141*OVERSAMPLENR, 198}, - {176*OVERSAMPLENR, 184}, - {211*OVERSAMPLENR, 173}, - {246*OVERSAMPLENR, 163}, - {281*OVERSAMPLENR, 154}, - {316*OVERSAMPLENR, 147}, - {351*OVERSAMPLENR, 140}, - {386*OVERSAMPLENR, 134}, - {421*OVERSAMPLENR, 128}, - {456*OVERSAMPLENR, 122}, - {491*OVERSAMPLENR, 117}, - {526*OVERSAMPLENR, 112}, - {561*OVERSAMPLENR, 107}, - {596*OVERSAMPLENR, 102}, - {631*OVERSAMPLENR, 97}, - {666*OVERSAMPLENR, 91}, - {701*OVERSAMPLENR, 86}, - {736*OVERSAMPLENR, 81}, - {771*OVERSAMPLENR, 76}, - {806*OVERSAMPLENR, 70}, - {841*OVERSAMPLENR, 63}, - {876*OVERSAMPLENR, 56}, - {911*OVERSAMPLENR, 48}, - {946*OVERSAMPLENR, 38}, - {981*OVERSAMPLENR, 23}, - {1005*OVERSAMPLENR, 5}, - {1016*OVERSAMPLENR, 0} -}; -#endif -#if (THERMISTORHEATER_0 == 101) || (THERMISTORHEATER_1 == 101) || (THERMISTORHEATER_2 == 101) || (THERMISTORBED == 101) // 100k Honeywell 135-104LAG-J01 -const short temptable_101[][2] PROGMEM = { - {1*OVERSAMPLENR, 704}, - {54*OVERSAMPLENR, 216}, - {107*OVERSAMPLENR, 175}, - {160*OVERSAMPLENR, 152}, - {213*OVERSAMPLENR, 137}, - {266*OVERSAMPLENR, 125}, - {319*OVERSAMPLENR, 115}, - {372*OVERSAMPLENR, 106}, - {425*OVERSAMPLENR, 99}, - {478*OVERSAMPLENR, 91}, - {531*OVERSAMPLENR, 85}, - {584*OVERSAMPLENR, 78}, - {637*OVERSAMPLENR, 71}, - {690*OVERSAMPLENR, 65}, - {743*OVERSAMPLENR, 58}, - {796*OVERSAMPLENR, 50}, - {849*OVERSAMPLENR, 42}, - {902*OVERSAMPLENR, 31}, - {955*OVERSAMPLENR, 17}, - {1008*OVERSAMPLENR, 0} -}; -#endif -#if (THERMISTORHEATER_0 == 102) || (THERMISTORHEATER_1 == 102) || (THERMISTORHEATER_2 == 102) || (THERMISTORBED == 102) // EPCOS G57540 -const short temptable_100[][2] PROGMEM = { -{15*OVERSAMPLENR,286}, -{16*OVERSAMPLENR,282}, -{17*OVERSAMPLENR,278}, -{18*OVERSAMPLENR,274}, -{19*OVERSAMPLENR,270}, -{20*OVERSAMPLENR,266}, -{21*OVERSAMPLENR,262}, -{22*OVERSAMPLENR,258}, -{23*OVERSAMPLENR,254}, -{25*OVERSAMPLENR,250}, -{27*OVERSAMPLENR,246}, -{28*OVERSAMPLENR,242}, -{31*OVERSAMPLENR,238}, -{33*OVERSAMPLENR,234}, -{35*OVERSAMPLENR,230}, -{38*OVERSAMPLENR,226}, -{41*OVERSAMPLENR,222}, -{44*OVERSAMPLENR,218}, -{48*OVERSAMPLENR,214}, -{52*OVERSAMPLENR,210}, -{56*OVERSAMPLENR,206}, -{61*OVERSAMPLENR,202}, -{66*OVERSAMPLENR,198}, -{71*OVERSAMPLENR,194}, -{78*OVERSAMPLENR,190}, -{84*OVERSAMPLENR,186}, -{92*OVERSAMPLENR,182}, -{100*OVERSAMPLENR,178}, -{109*OVERSAMPLENR,174}, -{120*OVERSAMPLENR,170}, -{131*OVERSAMPLENR,166}, -{143*OVERSAMPLENR,162}, -{156*OVERSAMPLENR,158}, -{171*OVERSAMPLENR,154}, -{187*OVERSAMPLENR,150}, -{205*OVERSAMPLENR,146}, -{224*OVERSAMPLENR,142}, -{224*OVERSAMPLENR,160}, -{245*OVERSAMPLENR,155}, -{268*OVERSAMPLENR,150}, -{293*OVERSAMPLENR,145}, -{320*OVERSAMPLENR,140}, -{348*OVERSAMPLENR,135}, -{379*OVERSAMPLENR,130}, -{411*OVERSAMPLENR,125}, -{480*OVERSAMPLENR,115}, -{553*OVERSAMPLENR,105}, -{628*OVERSAMPLENR,95}, -{702*OVERSAMPLENR,85}, -{770*OVERSAMPLENR,75}, -{830*OVERSAMPLENR,65}, -{881*OVERSAMPLENR,55}, -{922*OVERSAMPLENR,45}, -{954*OVERSAMPLENR,35}, -{977*OVERSAMPLENR,25}, -{993*OVERSAMPLENR,15}, -{999*OVERSAMPLENR,10}, -{1008*OVERSAMPLENR,0}, -}; -#endif -#if (THERMISTORHEATER_0 == 103) || (THERMISTORHEATER_1 == 103) || (THERMISTORHEATER_2 == 103) || (THERMISTORBED == 103) // 100k Honeywell 135-104LAG-J01 -const short temptable_103[][2] PROGMEM = { - {1*OVERSAMPLENR, 628}, - {187*OVERSAMPLENR, 156}, - {218*OVERSAMPLENR, 148}, - {249*OVERSAMPLENR, 141}, - {280*OVERSAMPLENR, 135}, - {311*OVERSAMPLENR, 129}, - {342*OVERSAMPLENR, 124}, - {373*OVERSAMPLENR, 120}, - {404*OVERSAMPLENR, 115}, - {435*OVERSAMPLENR, 111}, - {466*OVERSAMPLENR, 107}, - {497*OVERSAMPLENR, 103}, - {528*OVERSAMPLENR, 99}, - {559*OVERSAMPLENR, 96}, - {590*OVERSAMPLENR, 92}, - {621*OVERSAMPLENR, 88}, - {652*OVERSAMPLENR, 84}, - {683*OVERSAMPLENR, 81}, - {714*OVERSAMPLENR, 77}, - {745*OVERSAMPLENR, 73}, - {776*OVERSAMPLENR, 68}, - {807*OVERSAMPLENR, 64}, - {838*OVERSAMPLENR, 59}, - {869*OVERSAMPLENR, 54}, - {900*OVERSAMPLENR, 48}, - {931*OVERSAMPLENR, 40}, - {962*OVERSAMPLENR, 31}, - {993*OVERSAMPLENR, 17}, - {1008*OVERSAMPLENR,0} -}; -#endif - -#define _TT_NAME(_N) temptable_ ## _N -#define TT_NAME(_N) _TT_NAME(_N) - -#ifdef THERMISTORHEATER_0 - #define heater_0_temptable TT_NAME(THERMISTORHEATER_0) - #define heater_0_temptable_len (sizeof(heater_0_temptable)/sizeof(*heater_0_temptable)) -#else -#ifdef HEATER_0_USES_THERMISTOR - #error No heater 0 thermistor table specified -#else // HEATER_0_USES_THERMISTOR - #define heater_0_temptable 0 - #define heater_0_temptable_len 0 -#endif // HEATER_0_USES_THERMISTOR -#endif - -#ifdef THERMISTORHEATER_1 - #define heater_1_temptable TT_NAME(THERMISTORHEATER_1) - #define heater_1_temptable_len (sizeof(heater_1_temptable)/sizeof(*heater_1_temptable)) -#else -#ifdef HEATER_1_USES_THERMISTOR - #error No heater 1 thermistor table specified -#else // HEATER_1_USES_THERMISTOR - #define heater_1_temptable 0 - #define heater_1_temptable_len 0 -#endif // HEATER_1_USES_THERMISTOR -#endif - -#ifdef THERMISTORHEATER_2 - #define heater_2_temptable TT_NAME(THERMISTORHEATER_2) - #define heater_2_temptable_len (sizeof(heater_2_temptable)/sizeof(*heater_2_temptable)) -#else -#ifdef HEATER_2_USES_THERMISTOR - #error No heater 2 thermistor table specified -#else // HEATER_2_USES_THERMISTOR - #define heater_2_temptable 0 - #define heater_2_temptable_len 0 -#endif // HEATER_2_USES_THERMISTOR -#endif - -#ifdef THERMISTORBED - #define bedtemptable TT_NAME(THERMISTORBED) - #define bedtemptable_len (sizeof(bedtemptable)/sizeof(*bedtemptable)) -#else -#ifdef BED_USES_THERMISTOR - #error No bed thermistor table specified -#endif // BED_USES_THERMISTOR -#endif - -#endif //THERMISTORTABLES_H_ - From 9ea7de270bc604d89492ede7f0c68e747e1c2949 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Sat, 17 Mar 2012 22:47:44 +0000 Subject: [PATCH 209/228] added E jerk. Initial test with fast SD xfer. --- .gitignore | 1 + Marlin/.gitignore | 2 + Marlin/Configuration.h | 6 +- Marlin/Configuration.h~ | 48 +- Marlin/Configuration_adv.h | 7 +- Marlin/Configuration_adv.h~ | 232 +++++++++ Marlin/EEPROMwrite.h | 6 +- Marlin/Makefile | 12 +- Marlin/Marlin.h | 2 +- Marlin/Marlin.pde | 175 ++++--- Marlin/Marlin.pde~ | 38 +- Marlin/cardreader.cpp | 208 ++++++++- Marlin/cardreader.cpp~ | 565 ++++++++++++++++++++++ Marlin/cardreader.h | 40 +- Marlin/cardreader.h~ | 109 +++++ Marlin/language.h | 414 ++++++++--------- Marlin/motion_control.cpp | 12 + Marlin/pins.h | 4 +- Marlin/pins.h~ | 905 ++++++++++++++++++++++++++++++++++++ Marlin/planner.cpp | 42 +- Marlin/planner.h | 4 +- Marlin/stepper.cpp | 17 +- Marlin/temperature.cpp | 18 +- Marlin/ultralcd.h | 8 +- Marlin/ultralcd.pde | 54 ++- 25 files changed, 2482 insertions(+), 447 deletions(-) create mode 100644 .gitignore create mode 100644 Marlin/.gitignore create mode 100644 Marlin/Configuration_adv.h~ create mode 100644 Marlin/cardreader.cpp~ create mode 100644 Marlin/cardreader.h~ create mode 100644 Marlin/pins.h~ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..54bcf30465 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +~ diff --git a/Marlin/.gitignore b/Marlin/.gitignore new file mode 100644 index 0000000000..37a3c9b84d --- /dev/null +++ b/Marlin/.gitignore @@ -0,0 +1,2 @@ +*.o +applet/ diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index ad706fdaf4..b2b361f0c5 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -8,7 +8,7 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-02-24-2" //Personal revision number for changes to THIS file. +#define STRING_VERSION_CONFIG_H "2012-03-01-1" //Personal revision number for changes to THIS file. #define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. // This determines the communication speed of the printer @@ -19,6 +19,7 @@ // Gen7 custom (Alfons3 Version) = 10 "https://github.com/Alfons3/Generation_7_Electronics" // Gen7 v1.1, v1.2 = 11 // Gen7 v1.3 = 12 +// Gen7 v1.4 = 13 // MEGA/RAMPS up to 1.2 = 3 // RAMPS 1.3 = 33 (Power outputs: Extruder, Bed, Fan) // RAMPS 1.3 = 34 (Power outputs: Extruder0, Extruder1, Bed) @@ -177,8 +178,9 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for r retracts // -#define DEFAULT_XYJERK 20.0 // (mm/sec) +#define DEFAULT_XYJERK 15.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) +#define DEFAULT_EJERK 5.0 // (mm/sec) //=========================================================================== //=============================Additional Features=========================== diff --git a/Marlin/Configuration.h~ b/Marlin/Configuration.h~ index 25e7cf20cf..8e380ee358 100644 --- a/Marlin/Configuration.h~ +++ b/Marlin/Configuration.h~ @@ -8,20 +8,26 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-02-08j" //Personal revision number for changes to THIS file. -#define STRING_CONFIG_H_AUTHOR "username" //Who made the changes. +#define STRING_VERSION_CONFIG_H "2012-03-01-1" //Personal revision number for changes to THIS file. +#define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. // This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 +#define BAUDRATE 250000 +//#define BAUDRATE 115200 //// The following define selects which electronics board you have. Please choose the one that matches your setup -// MEGA/RAMPS up to 1.2 = 3, -// RAMPS 1.3 = 33 -// Gen6 = 5, +// Gen7 custom (Alfons3 Version) = 10 "https://github.com/Alfons3/Generation_7_Electronics" +// Gen7 v1.1, v1.2 = 11 +// Gen7 v1.3 = 12 +// Gen7 v1.4 = 13 +// MEGA/RAMPS up to 1.2 = 3 +// RAMPS 1.3 = 33 (Power outputs: Extruder, Bed, Fan) +// RAMPS 1.3 = 34 (Power outputs: Extruder0, Extruder1, Bed) +// Gen6 = 5 +// Gen6 deluxe = 51 // Sanguinololu 1.2 and above = 62 -// Ultimaker = 7, -// Teensylu = 8, +// Ultimaker = 7 +// Teensylu = 8 // Gen3+ =9 #define MOTHERBOARD 62 @@ -43,10 +49,10 @@ // 100 is 100k GE Sensing AL03006-58.2K-97-G1 // 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT -#define TEMP_SENSOR_0 100 +#define TEMP_SENSOR_0 102 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 101 +#define TEMP_SENSOR_BED 103 // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 10 // (seconds) @@ -68,6 +74,7 @@ //#define HEATER_2_MAXTEMP 275 #define BED_MAXTEMP 150 + // PID settings: // Comment the following line to disable PID and enable bang-bang. #define PIDTEMP @@ -150,14 +157,20 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define Y_MAX_LENGTH 148 #define Z_MAX_LENGTH 100 +// The position of the homing switches. Use MAX_LENGTH * -0.5 if the center should be 0, 0, 0 +#define X_HOME_POS 0 +#define Y_HOME_POS 0 +#define Z_HOME_POS 0 + //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E #define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) -#define FAST_HOME_FEEDRATE {80*60, 80*60, 4*60, 0} // set the homing speeds (mm/min) +#define FAST_HOME_FEEDRATE {80*60, 80*60, 3*60, 0} // set the homing speeds (mm/min) // default settings #define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker +//#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,850} #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) #define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. @@ -167,6 +180,7 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t // #define DEFAULT_XYJERK 20.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) +#define DEFAULT_EJERK 5.0 // (mm/sec) //=========================================================================== //=============================Additional Features=========================== @@ -194,6 +208,16 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define ULTRA_LCD #define LCD_WIDTH 20 #define LCD_HEIGHT 4 + +// Preheat Constants + #define PLA_PREHEAT_HOTEND_TEMP 180 + #define PLA_PREHEAT_HPB_TEMP 70 + #define PLA_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 + + #define ABS_PREHEAT_HOTEND_TEMP 240 + #define ABS_PREHEAT_HPB_TEMP 100 + #define ABS_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 + #else //no panel but just lcd #ifdef ULTRA_LCD #define LCD_WIDTH 16 diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index c2cb14951e..4af432e82b 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -25,9 +25,6 @@ // if CooldownNoWait is defined M109 will not wait for the cooldown to finish #define CooldownNoWait true -//Do not wait for M109 to finish when printing from SD card -//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING - #ifdef PIDTEMP // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. // if Kc is choosen well, the additional required power due to increased melting should be compensated. @@ -79,7 +76,7 @@ #define X_HOME_RETRACT_MM 4 #define Y_HOME_RETRACT_MM 4 #define Z_HOME_RETRACT_MM 1 -#define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially. +//#define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially. #define AXIS_RELATIVE_MODES {false, false, false, false} @@ -167,6 +164,8 @@ const int dropsegments=5; //everything with less than this number of steps will // THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ringbuffering. #if defined SDSUPPORT #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller +// Chuck size for fast sd transfer + #define SD_FAST_XFER_CHUNK_SIZE 1024 #else #define BLOCK_BUFFER_SIZE 16 // maximize block buffer #endif diff --git a/Marlin/Configuration_adv.h~ b/Marlin/Configuration_adv.h~ new file mode 100644 index 0000000000..c2cb14951e --- /dev/null +++ b/Marlin/Configuration_adv.h~ @@ -0,0 +1,232 @@ +#ifndef __CONFIGURATION_ADV_H +#define __CONFIGURATION_ADV_H + +//=========================================================================== +//=============================Thermal Settings ============================ +//=========================================================================== + +// Select one of these only to define how the bed temp is read. +// +//#define BED_LIMIT_SWITCHING +#ifdef BED_LIMIT_SWITCHING + #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS +#endif +#define BED_CHECK_INTERVAL 5000 //ms + +//// Heating sanity check: +// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. +// It can be reset with another M104/M109 +//#define WATCHPERIOD 20000 //20 seconds + +// Wait for Cooldown +// This defines if the M109 call should not block if it is cooling down. +// example: From a current temp of 220, you set M109 S200. +// if CooldownNoWait is defined M109 will not wait for the cooldown to finish +#define CooldownNoWait true + +//Do not wait for M109 to finish when printing from SD card +//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING + +#ifdef PIDTEMP + // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. + // if Kc is choosen well, the additional required power due to increased melting should be compensated. + //#define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) + #endif +#endif + + +//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode. +//The maximum buffered steps/sec of the extruder motor are called "se". +//You enter the autotemp mode by a M109 S T F +// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp +// you exit the value by any M109 without F* +// Also, if the temperature is set to a value 0 + #define THERMISTORHEATER_0 TEMP_SENSOR_0 + #define HEATER_0_USES_THERMISTOR +#endif +#if TEMP_SENSOR_1 > 0 + #define THERMISTORHEATER_1 TEMP_SENSOR_1 + #define HEATER_1_USES_THERMISTOR +#endif +#if TEMP_SENSOR_2 > 0 + #define THERMISTORHEATER_2 TEMP_SENSOR_2 + #define HEATER_2_USES_THERMISTOR +#endif +#if TEMP_SENSOR_BED > 0 + #define THERMISTORBED TEMP_SENSOR_BED + #define BED_USES_THERMISTOR +#endif +#if TEMP_SENSOR_0 == -1 + #define HEATER_0_USES_AD595 +#endif +#if TEMP_SENSOR_1 == -1 + #define HEATER_1_USES_AD595 +#endif +#if TEMP_SENSOR_2 == -1 + #define HEATER_2_USES_AD595 +#endif +#if TEMP_SENSOR_BED == -1 + #define BED_USES_AD595 +#endif +#if TEMP_SENSOR_0 == -2 + #define HEATER_0_USES_MAX6675 +#endif +#if TEMP_SENSOR_0 == 0 + #undef HEATER_0_MINTEMP + #undef HEATER_0_MAXTEMP +#endif +#if TEMP_SENSOR_1 == 0 + #undef HEATER_1_MINTEMP + #undef HEATER_1_MAXTEMP +#endif +#if TEMP_SENSOR_2 == 0 + #undef HEATER_2_MINTEMP + #undef HEATER_2_MAXTEMP +#endif +#if TEMP_SENSOR_BED == 0 + #undef BED_MINTEMP + #undef BED_MAXTEMP +#endif + + +#endif //__CONFIGURATION_ADV_H diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 776b1cfa70..649fa9100a 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -38,7 +38,7 @@ template int EEPROM_readAnything(int &ee, T& value) // the default values are used whenever there is a change to the data, to prevent // wrong data being written to the variables. // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. -#define EEPROM_VERSION "V04" +#define EEPROM_VERSION "V05" inline void EEPROM_StoreSettings() { @@ -56,6 +56,7 @@ inline void EEPROM_StoreSettings() EEPROM_writeAnything(i,minsegmenttime); EEPROM_writeAnything(i,max_xy_jerk); EEPROM_writeAnything(i,max_z_jerk); + EEPROM_writeAnything(i,max_e_jerk); #ifdef PIDTEMP EEPROM_writeAnything(i,Kp); EEPROM_writeAnything(i,Ki); @@ -117,6 +118,7 @@ inline void EEPROM_printSettings() SERIAL_ECHOPAIR(" B" ,minsegmenttime ); SERIAL_ECHOPAIR(" X" ,max_xy_jerk ); SERIAL_ECHOPAIR(" Z" ,max_z_jerk); + SERIAL_ECHOPAIR(" E" ,max_e_jerk); SERIAL_ECHOLN(""); #ifdef PIDTEMP SERIAL_ECHO_START; @@ -152,6 +154,7 @@ inline void EEPROM_RetrieveSettings(bool def=false) EEPROM_readAnything(i,minsegmenttime); EEPROM_readAnything(i,max_xy_jerk); EEPROM_readAnything(i,max_z_jerk); + EEPROM_readAnything(i,max_e_jerk); #ifndef PIDTEMP float Kp,Ki,Kd; int Ki_Max; @@ -183,6 +186,7 @@ inline void EEPROM_RetrieveSettings(bool def=false) mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; max_xy_jerk=DEFAULT_XYJERK; max_z_jerk=DEFAULT_ZJERK; + max_e_jerk=DEFAULT_EJERK; SERIAL_ECHO_START; SERIAL_ECHOLN("Using Default settings:"); } diff --git a/Marlin/Makefile b/Marlin/Makefile index 7c039be571..9e41c28d33 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -138,6 +138,8 @@ all: build sizeafter build: elf hex applet/$(TARGET).cpp: $(TARGET).pde $(MAKEFILE) + +applet/%.cpp: %.pde # Here is the "preprocessing". # It creates a .cpp file based with the same name as the .pde file. # On top of the new .cpp file comes the WProgram.h header. @@ -145,11 +147,11 @@ applet/$(TARGET).cpp: $(TARGET).pde $(MAKEFILE) # Then the .cpp file will be compiled. Errors during compile will # refer to this new, automatically generated, file. # Not the original .pde file you actually edit... - @echo " WR applet/$(TARGET).cpp" - @test -d applet || mkdir applet - @echo '#include "WProgram.h"' > applet/$(TARGET).cpp - @cat $(TARGET).pde >> applet/$(TARGET).cpp - @cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp + @echo " WR $@" + @test -d $(dir $@) || mkdir $(dir $@) + @echo '#include "WProgram.h"' > $@ + @cat $< >> $@ + @cat $(ARDUINO)/main.cpp >> $@ elf: applet/$(TARGET).elf hex: applet/$(TARGET).hex diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index ffa3839a72..919287260b 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -175,7 +175,7 @@ extern float homing_feedrate[]; extern bool axis_relative_modes[]; extern float current_position[NUM_AXIS] ; extern float add_homeing[3]; -extern bool stop_heating_wait; +extern unsigned char FanSpeed; // Handling multiple extruders pins extern uint8_t active_extruder; diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index e0fa719d86..103913a7cd 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -75,7 +75,8 @@ // M27 - Report SD print status // M28 - Start SD write (M28 filename.g) // M29 - Stop SD write -// M30 - Output time since last M109 or SD card start to serial +// 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 @@ -96,7 +97,7 @@ // 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 +// 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 // M220 S- set speed factor override percentage // M221 S- set extrude factor override percentage @@ -132,7 +133,7 @@ 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}; uint8_t active_extruder = 0; -bool stop_heating_wait=false; +unsigned char FanSpeed=0; //=========================================================================== //=============================private variables============================= @@ -147,8 +148,6 @@ static long gcode_N, gcode_LastN; 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 uint8_t fanpwm=0; - static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; static bool fromsd[BUFSIZE]; static int bufindr = 0; @@ -253,21 +252,31 @@ void setup() MYSERIAL.begin(BAUDRATE); SERIAL_PROTOCOLLNPGM("start"); SERIAL_ECHO_START; - SERIAL_ECHOPGM("Marlin: "); + + // 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("Configuration.h: "); + SERIAL_ECHOPGM(MSG_CONFIGURATION_VER); SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); - SERIAL_ECHOPGM(" | Author: "); + SERIAL_ECHOPGM(MSG_AUTHOR); SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); #endif #endif SERIAL_ECHO_START; - SERIAL_ECHOPGM("Free Memory:"); + SERIAL_ECHOPGM(MSG_FREE_MEMORY); SERIAL_ECHO(freeMemory()); - SERIAL_ECHOPGM(" PlannerBufferBytes:"); + SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES); SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE); for(int8_t i = 0; i < BUFSIZE; i++) { @@ -291,7 +300,7 @@ void setup() void loop() { - if(buflen<3) + if(buflen < (BUFSIZE-1)) get_command(); #ifdef SDSUPPORT card.checkautostart(false); @@ -304,12 +313,12 @@ void loop() if(strstr(cmdbuffer[bufindr],"M29") == NULL) { card.write_command(cmdbuffer[bufindr]); - SERIAL_PROTOCOLLNPGM("ok"); + SERIAL_PROTOCOLLNPGM(MSG_OK); } else { card.closefile(); - SERIAL_PROTOCOLLNPGM("Done saving file."); + SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED); } } else @@ -349,7 +358,7 @@ void get_command() 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("Line Number is not Last Line Number+1, Last Line:"); + SERIAL_ERRORPGM(MSG_ERR_LINE_NO); SERIAL_ERRORLN(gcode_LastN); //Serial.println(gcode_N); FlushSerialRequestResend(); @@ -366,7 +375,7 @@ void get_command() if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) { SERIAL_ERROR_START; - SERIAL_ERRORPGM("checksum mismatch, Last Line:"); + SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH); SERIAL_ERRORLN(gcode_LastN); FlushSerialRequestResend(); serial_count = 0; @@ -377,7 +386,7 @@ void get_command() else { SERIAL_ERROR_START; - SERIAL_ERRORPGM("No Checksum with line number, Last Line:"); + SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM); SERIAL_ERRORLN(gcode_LastN); FlushSerialRequestResend(); serial_count = 0; @@ -392,7 +401,7 @@ void get_command() if((strstr(cmdbuffer[bufindw], "*") != NULL)) { SERIAL_ERROR_START; - SERIAL_ERRORPGM("No Line Number with checksum, Last Line:"); + SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM); SERIAL_ERRORLN(gcode_LastN); serial_count = 0; return; @@ -409,7 +418,7 @@ void get_command() if(card.saving) break; #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM("ok"); + SERIAL_PROTOCOLLNPGM(MSG_OK); break; default: break; @@ -437,7 +446,7 @@ void get_command() if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) { if(card.eof()){ - SERIAL_PROTOCOLLNPGM("Done printing file"); + SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED); stoptime=millis(); char time[30]; unsigned long t=(stoptime-starttime)/1000; @@ -458,11 +467,11 @@ void get_command() return; //if empty line } cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ +// if(!comment_mode){ fromsd[bufindw] = true; buflen += 1; bufindw = (bufindw + 1)%BUFSIZE; - } +// } comment_mode = false; //for new command serial_count = 0; //clear buffer } @@ -482,10 +491,12 @@ 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); @@ -496,6 +507,7 @@ bool code_seen(char code) strchr_pointer = strchr(cmdbuffer[bufindr], code); return (strchr_pointer != NULL); //Return True if a character was found } + #define HOMEAXIS(LETTER) \ if ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))\ { \ @@ -504,20 +516,22 @@ bool code_seen(char code) destination[LETTER##_AXIS] = 1.1 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ feedrate = fast_home_feedrate[LETTER##_AXIS]; \ plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ + st_synchronize();\ \ current_position[LETTER##_AXIS] = 0;\ plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ + st_synchronize();\ \ destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ feedrate = homing_feedrate[LETTER##_AXIS] ; \ plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ + st_synchronize();\ \ current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? LETTER##_HOME_POS : LETTER##_MAX_LENGTH;\ destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ feedrate = 0.0;\ - st_synchronize();\ endstops_hit_on_purpose();\ } @@ -546,7 +560,7 @@ void process_commands() prepare_arc_move(false); return; case 4: // G4 dwell - LCD_MESSAGEPGM("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 @@ -580,13 +594,15 @@ void process_commands() feedrate = homing_feedrate[X_AXIS]; if(homing_feedrate[Y_AXIS] 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; + + case 32: //M32 - fast SD transfer + card.fast_xfer(strchr_pointer+4); + break; + case 33: //M31 - high speed xfer capabilities + SERIAL_ECHOPGM("RAW:"); + SERIAL_ECHOLN(SD_FAST_XFER_CHUNK_SIZE); + break; #endif //SDSUPPORT - case 30: //M30 take time since the start of the SD print or an M109 command + case 31: //M31 take time since the start of the SD print or an M109 command { stoptime=millis(); char time[30]; @@ -766,7 +808,7 @@ void process_commands() tmp_extruder = code_value(); if(tmp_extruder >= EXTRUDERS) { SERIAL_ECHO_START; - SERIAL_ECHO("M104 Invalid extruder "); + SERIAL_ECHO(MSG_M104_INVALID_EXTRUDER); SERIAL_ECHOLN(tmp_extruder); break; } @@ -783,7 +825,7 @@ void process_commands() tmp_extruder = code_value(); if(tmp_extruder >= EXTRUDERS) { SERIAL_ECHO_START; - SERIAL_ECHO("M105 Invalid extruder "); + SERIAL_ECHO(MSG_M105_INVALID_EXTRUDER); SERIAL_ECHOLN(tmp_extruder); break; } @@ -797,7 +839,7 @@ void process_commands() #endif //TEMP_BED_PIN #else SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("No thermistors - no temp"); + SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS); #endif #ifdef PIDTEMP SERIAL_PROTOCOLPGM(" @:"); @@ -813,12 +855,12 @@ void process_commands() tmp_extruder = code_value(); if(tmp_extruder >= EXTRUDERS) { SERIAL_ECHO_START; - SERIAL_ECHO("M109 Invalid extruder "); + SERIAL_ECHO(MSG_M109_INVALID_EXTRUDER); SERIAL_ECHOLN(tmp_extruder); break; } } - LCD_MESSAGEPGM("Heating..."); + LCD_MESSAGEPGM(MSG_HEATING); #ifdef AUTOTEMP autotemp_enabled=false; #endif @@ -873,7 +915,6 @@ void process_commands() } manage_heater(); LCD_STATUS; - if(stop_heating_wait) break; #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 */ @@ -885,14 +926,14 @@ void process_commands() } #endif //TEMP_RESIDENCY_TIME } - LCD_MESSAGEPGM("Heating done."); + 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("Bed Heating."); + LCD_MESSAGEPGM(MSG_BED_HEATING); if (code_seen('S')) setTargetBed(code_value()); codenum = millis(); while(isHeatingBed()) @@ -909,8 +950,9 @@ void process_commands() codenum = millis(); } manage_heater(); + LCD_STATUS; } - LCD_MESSAGEPGM("Bed done."); + LCD_MESSAGEPGM(MSG_BED_DONE); previous_millis_cmd = millis(); #endif break; @@ -918,19 +960,14 @@ void process_commands() #if FAN_PIN > -1 case 106: //M106 Fan On if (code_seen('S')){ - WRITE(FAN_PIN,HIGH); - fanpwm=constrain(code_value(),0,255); - analogWrite(FAN_PIN, fanpwm); + FanSpeed=constrain(code_value(),0,255); } else { - WRITE(FAN_PIN,HIGH); - fanpwm=255; - analogWrite(FAN_PIN, fanpwm); + FanSpeed=255; } break; case 107: //M107 Fan Off - WRITE(FAN_PIN,LOW); - analogWrite(FAN_PIN, 0); + FanSpeed = 0; break; #endif //FAN_PIN @@ -985,7 +1022,7 @@ void process_commands() disable_e2(); } #endif - LCD_MESSAGEPGM("Partial Release"); + LCD_MESSAGEPGM(MSG_PART_RELEASE); } } break; @@ -1001,7 +1038,7 @@ void process_commands() } break; case 115: // M115 - SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n"); + SerialprintPGM(MSG_M115_REPORT); break; case 117: // M117 display message LCD_MESSAGE(cmdbuffer[bufindr]+5); @@ -1016,7 +1053,7 @@ void process_commands() SERIAL_PROTOCOLPGM("E:"); SERIAL_PROTOCOL(current_position[E_AXIS]); - SERIAL_PROTOCOLPGM(" Count X:"); + 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]); @@ -1027,27 +1064,27 @@ void process_commands() break; case 119: // M119 #if (X_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("x_min:"); + SERIAL_PROTOCOLPGM(MSG_X_MIN); SERIAL_PROTOCOL(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (X_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("x_max:"); + SERIAL_PROTOCOLPGM(MSG_X_MAX); SERIAL_PROTOCOL(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("y_min:"); + SERIAL_PROTOCOLPGM(MSG_Y_MIN); SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Y_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("y_max:"); + SERIAL_PROTOCOLPGM(MSG_Y_MAX); SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("z_min:"); + SERIAL_PROTOCOLPGM(MSG_Z_MIN); SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); #endif #if (Z_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("z_max:"); + SERIAL_PROTOCOLPGM(MSG_Z_MAX); SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); #endif SERIAL_PROTOCOLLN(""); @@ -1088,6 +1125,7 @@ void process_commands() 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 @@ -1125,7 +1163,8 @@ void process_commands() if(code_seen('C')) Kc = code_value(); #endif updatePID(); - SERIAL_PROTOCOL("ok p:"); + SERIAL_PROTOCOL(MSG_OK); + SERIAL_PROTOCOL(" p:"); SERIAL_PROTOCOL(Kp); SERIAL_PROTOCOL(" i:"); SERIAL_PROTOCOL(Ki/PID_dT); @@ -1206,12 +1245,12 @@ void process_commands() SERIAL_ECHO_START; SERIAL_ECHO("T"); SERIAL_ECHO(tmp_extruder); - SERIAL_ECHOLN("Invalid extruder"); + SERIAL_ECHOLN(MSG_INVALID_EXTRUDER); } else { active_extruder = tmp_extruder; SERIAL_ECHO_START; - SERIAL_ECHO("Active Extruder: "); + SERIAL_ECHO(MSG_ACTIVE_EXTRUDER); SERIAL_PROTOCOLLN((int)active_extruder); } } @@ -1219,7 +1258,7 @@ void process_commands() else { SERIAL_ECHO_START; - SERIAL_ECHOPGM("Unknown command:\""); + SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND); SERIAL_ECHO(cmdbuffer[bufindr]); SERIAL_ECHOLNPGM("\""); } @@ -1231,7 +1270,7 @@ void FlushSerialRequestResend() { //char cmdbuffer[bufindr][100]="Resend:"; MYSERIAL.flush(); - SERIAL_PROTOCOLPGM("Resend:"); + SERIAL_PROTOCOLPGM(MSG_RESEND); SERIAL_PROTOCOLLN(gcode_LastN + 1); ClearToSend(); } @@ -1243,7 +1282,7 @@ void ClearToSend() if(fromsd[bufindr]) return; #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM("ok"); + SERIAL_PROTOCOLLNPGM(MSG_OK); } void get_coordinates() @@ -1268,9 +1307,9 @@ void get_arc_coordinates() void prepare_move() { if (min_software_endstops) { - if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0; - if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0; - if (destination[Z_AXIS] < 0) destination[Z_AXIS] = 0.0; + if (destination[X_AXIS] < X_HOME_POS) destination[X_AXIS] = X_HOME_POS; + if (destination[Y_AXIS] < Y_HOME_POS) destination[Y_AXIS] = Y_HOME_POS; + if (destination[Z_AXIS] < Z_HOME_POS) destination[Z_AXIS] = Z_HOME_POS; } if (max_software_endstops) { @@ -1353,8 +1392,8 @@ void kill() if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Printer halted. kill() called !!"); - LCD_MESSAGEPGM("KILLED. "); + SERIAL_ERRORLNPGM(MSG_ERR_KILLED); + LCD_MESSAGEPGM(MSG_KILLED); suicide(); while(1); // Wait for reset } diff --git a/Marlin/Marlin.pde~ b/Marlin/Marlin.pde~ index da29fb37aa..a3d091f503 100644 --- a/Marlin/Marlin.pde~ +++ b/Marlin/Marlin.pde~ @@ -511,7 +511,7 @@ bool code_seen(char code) plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ - feedrate = homing_feedrate[LETTER##_AXIS]/2 ; \ + feedrate = homing_feedrate[LETTER##_AXIS] ; \ plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ \ current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? LETTER##_HOME_POS : LETTER##_MAX_LENGTH;\ @@ -712,29 +712,21 @@ void process_commands() strchr_pointer = strchr(npos,' ') + 1; *(starpos-1) = '\0'; } - card.openFile(strchr_pointer+4,false); + card.openFile(strchr_pointer,false); break; case 29: //M29 - Stop SD write //processed in write to file routine above //card,saving = false; break; + case 30: //M30 - fast SD transfer + card.fast_xfer(strchr_pointer); + break; + case 31: //M31 - high speed xfer capabilities + SERIAL_ECHOPGM("RAW:"); + SERIAL_ECHOLN(SD_FAST_XFER_CHUNK_SIZE); + break; #endif //SDSUPPORT - case 30: //M30 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')) { @@ -1267,6 +1259,18 @@ void get_arc_coordinates() void prepare_move() { + if (min_software_endstops) { + if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0; + if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0; + if (destination[Z_AXIS] < 0) destination[Z_AXIS] = 0.0; + } + + if (max_software_endstops) { + if (destination[X_AXIS] > X_MAX_LENGTH) destination[X_AXIS] = X_MAX_LENGTH; + if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH; + if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; + } + 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]; diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp index ecf0c47121..d6ba0b97ba 100644 --- a/Marlin/cardreader.cpp +++ b/Marlin/cardreader.cpp @@ -3,6 +3,8 @@ #include "ultralcd.h" #include "stepper.h" #include "temperature.h" +#include "language.h" + #ifdef SDSUPPORT @@ -75,7 +77,7 @@ void CardReader::lsDive(const char *prepend,SdFile parent) if(lsAction==LS_SerialPrint) { SERIAL_ECHO_START; - SERIAL_ECHOLN("Cannot open subdir"); + SERIAL_ECHOLN(MSG_SD_CANT_OPEN_SUBDIR); SERIAL_ECHOLN(lfilename); } } @@ -143,28 +145,28 @@ void CardReader::initsd() { //if (!card.init(SPI_HALF_SPEED,SDSS)) SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("SD init fail"); + SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL); } else if (!volume.init(&card)) { SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("volume.init failed"); + SERIAL_ERRORLNPGM(MSG_SD_VOL_INIT_FAIL); } else if (!root.openRoot(&volume)) { SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("openRoot failed"); + SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL); } else { cardOK = true; SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("SD card ok"); + SERIAL_ECHOLNPGM(MSG_SD_CARD_OK); } curDir=&root; if(!workDir.openRoot(&volume)) { - SERIAL_ECHOLNPGM("workDir open failed"); + SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL); } } @@ -173,7 +175,7 @@ void CardReader::setroot() curDir=&root; if(!workDir.openRoot(&volume)) { - SERIAL_ECHOLNPGM("workDir open failed"); + SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL); } } void CardReader::release() @@ -230,7 +232,7 @@ void CardReader::openFile(char* name,bool read) SERIAL_ECHOLN(subdirname); if(!myDir.open(curDir,subdirname,O_READ)) { - SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL); SERIAL_PROTOCOL(subdirname); SERIAL_PROTOCOLLNPGM("."); return; @@ -260,18 +262,18 @@ void CardReader::openFile(char* name,bool read) if (file.open(curDir, fname, O_READ)) { filesize = file.fileSize(); - SERIAL_PROTOCOLPGM("File opened:"); + SERIAL_PROTOCOLPGM(MSG_SD_FILE_OPENED); SERIAL_PROTOCOL(fname); - SERIAL_PROTOCOLPGM(" Size:"); + SERIAL_PROTOCOLPGM(MSG_SD_SIZE); SERIAL_PROTOCOLLN(filesize); sdpos = 0; - SERIAL_PROTOCOLLNPGM("File selected"); + SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED); LCD_MESSAGE(fname); } else { - SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL); SERIAL_PROTOCOL(fname); SERIAL_PROTOCOLLNPGM("."); } @@ -280,14 +282,14 @@ void CardReader::openFile(char* name,bool read) { //write if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) { - SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL); SERIAL_PROTOCOL(fname); SERIAL_PROTOCOLLNPGM("."); } else { saving = true; - SERIAL_PROTOCOLPGM("Writing to file: "); + SERIAL_PROTOCOLPGM(MSG_SD_WRITE_TO_FILE); SERIAL_PROTOCOLLN(name); LCD_MESSAGE(fname); } @@ -295,16 +297,85 @@ void CardReader::openFile(char* name,bool read) } +void CardReader::removeFile(char* name) +{ + if(!cardOK) + return; + file.close(); + sdprinting = false; + + + SdFile myDir; + curDir=&root; + char *fname=name; + + char *dirname_start,*dirname_end; + if(name[0]=='/') + { + dirname_start=strchr(name,'/')+1; + while(dirname_start>0) + { + dirname_end=strchr(dirname_start,'/'); + //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); + //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); + if(dirname_end>0 && dirname_end>dirname_start) + { + char subdirname[13]; + strncpy(subdirname, dirname_start, dirname_end-dirname_start); + subdirname[dirname_end-dirname_start]=0; + SERIAL_ECHOLN(subdirname); + if(!myDir.open(curDir,subdirname,O_READ)) + { + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(subdirname); + SERIAL_PROTOCOLLNPGM("."); + return; + } + else + ;//SERIAL_ECHOLN("dive ok"); + + curDir=&myDir; + dirname_start=dirname_end+1; + } + else // the reminder after all /fsa/fdsa/ is the filename + { + fname=dirname_start; + //SERIAL_ECHOLN("remaider"); + //SERIAL_ECHOLN(fname); + break; + } + + } + } + else //relative path + { + curDir=&workDir; + } + if (file.remove(curDir, fname)) + { + SERIAL_PROTOCOLPGM("File deleted:"); + SERIAL_PROTOCOL(fname); + sdpos = 0; + } + else + { + SERIAL_PROTOCOLPGM("Deletion failed, File: "); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLLNPGM("."); + } + +} + void CardReader::getStatus() { if(cardOK){ - SERIAL_PROTOCOLPGM("SD printing byte "); + SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE); SERIAL_PROTOCOL(sdpos); SERIAL_PROTOCOLPGM("/"); SERIAL_PROTOCOLLN(filesize); } else{ - SERIAL_PROTOCOLLNPGM("Not SD printing"); + SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING); } } void CardReader::write_command(char *buf) @@ -326,7 +397,7 @@ void CardReader::write_command(char *buf) if (file.writeError) { SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("error writing to file"); + SERIAL_ERRORLNPGM(MSG_SD_ERR_WRITE_TO_FILE); } } @@ -420,7 +491,7 @@ void CardReader::chdir(const char * relpath) if(!newfile.open(*parent,relpath, O_READ)) { SERIAL_ECHO_START; - SERIAL_ECHOPGM("Cannot enter subdir:"); + SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR); SERIAL_ECHOLN(relpath); } else @@ -447,9 +518,6 @@ void CardReader::printingHasFinished() st_synchronize(); quickStop(); sdprinting = false; - #ifdef STOP_HEATING_WAIT_FOR_SD_PRINTING - stop_heating_wait=true; - #endif if(SD_FINISHED_STEPPERRELEASE) { //finishAndDisableSteppers(); @@ -457,4 +525,102 @@ void CardReader::printingHasFinished() } autotempShutdown(); } +void CardReader::fast_xfer(char* strchr_pointer) + { + char *pstr; + boolean done = false; + + //force heater pins low + if(HEATER_0_PIN > -1) WRITE(HEATER_0_PIN,LOW); + if(HEATER_BED_PIN > -1) WRITE(HEATER_BED_PIN,LOW); + + lastxferchar = 1; + xferbytes = 0; + + pstr = strstr(strchr_pointer, " "); + //pstr = strchr_pointer; + + if(pstr == NULL) + { + SERIAL_ECHOLN("invalid command"); + return; + } + + *pstr = '\0'; + + //check mode (currently only RAW is supported + if(strcmp(strchr_pointer, "RAW") != 0) + { + SERIAL_ECHOLN("Invalid transfer codec"); + return; + }else{ + SERIAL_ECHOPGM("Selected codec: "); + SERIAL_ECHOLN(strchr_pointer+4); + } + + if (!file.open(&root, pstr+1, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + SERIAL_ECHOPGM("open failed, File: "); + SERIAL_ECHOLN(pstr+1); + SERIAL_ECHOPGM("."); + }else{ + SERIAL_ECHOPGM("Writing to file: "); + SERIAL_ECHOLN(pstr+1); + } + + SERIAL_ECHOLN("ok"); + + //RAW transfer codec + //Host sends \0 then up to SD_FAST_XFER_CHUNK_SIZE then \0 + //when host is done, it sends \0\0. + //if a non \0 character is recieved at the beginning, host has failed somehow, kill the transfer. + + //read SD_FAST_XFER_CHUNK_SIZE bytes (or until \0 is recieved) + while(!done) + { + while(!MYSERIAL.available()) + { + } + if(MYSERIAL.peek() != 0) + { + //host has failed, this isn't a RAW chunk, it's an actual command + file.sync(); + file.close(); + SERIAL_ECHOLN("Not RAW data"); + return; + } + //clear the initial 0 + MYSERIAL.read(); + for(int i=0;i -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); + #endif //SDPOWER + + autostart_atmillis=millis()+5000; +} + +char *createFilename(char *buffer,const dir_t &p) //buffer>12characters +{ + char *pos=buffer; + for (uint8_t i = 0; i < 11; i++) + { + if (p.name[i] == ' ')continue; + if (i == 8) + { + *pos++='.'; + } + *pos++=p.name[i]; + } + *pos++=0; + return buffer; +} + + +void CardReader::lsDive(const char *prepend,SdFile parent) +{ + dir_t p; + uint8_t cnt=0; + + while (parent.readDir(p) > 0) + { + if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) + { + + char path[13*2]; + char lfilename[13]; + createFilename(lfilename,p); + + path[0]=0; + if(strlen(prepend)==0) //avoid leading / if already in prepend + { + strcat(path,"/"); + } + strcat(path,prepend); + strcat(path,lfilename); + strcat(path,"/"); + + //Serial.print(path); + + SdFile dir; + if(!dir.open(parent,lfilename, O_READ)) + { + if(lsAction==LS_SerialPrint) + { + SERIAL_ECHO_START; + SERIAL_ECHOLN("Cannot open subdir"); + SERIAL_ECHOLN(lfilename); + } + } + lsDive(path,dir); + //close done automatically by destructor of SdFile + + + } + else + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if ( p.name[0] == '.') + { + if ( p.name[1] != '.') + continue; + } + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + filenameIsDir=DIR_IS_SUBDIR(&p); + + if(!filenameIsDir) + { + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + } + //if(cnt++!=nr) continue; + createFilename(filename,p); + if(lsAction==LS_SerialPrint) + { + SERIAL_PROTOCOL(prepend); + SERIAL_PROTOCOLLN(filename); + } + else if(lsAction==LS_Count) + { + nrFiles++; + } + else if(lsAction==LS_GetFilename) + { + if(cnt==nrFiles) + return; + cnt++; + + } + } + } +} + +void CardReader::ls() +{ + lsAction=LS_SerialPrint; + if(lsAction==LS_Count) + nrFiles=0; + + root.rewind(); + lsDive("",root); +} + + +void CardReader::initsd() +{ + cardOK = false; + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)) + { + //if (!card.init(SPI_HALF_SPEED,SDSS)) + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("SD init fail"); + } + else if (!volume.init(&card)) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("volume.init failed"); + } + else if (!root.openRoot(&volume)) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("openRoot failed"); + } + else + { + cardOK = true; + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM("SD card ok"); + } + curDir=&root; + if(!workDir.openRoot(&volume)) + { + SERIAL_ECHOLNPGM("workDir open failed"); + } +} + +void CardReader::setroot() +{ + curDir=&root; + if(!workDir.openRoot(&volume)) + { + SERIAL_ECHOLNPGM("workDir open failed"); + } +} +void CardReader::release() +{ + sdprinting = false; + cardOK = false; +} + +void CardReader::startFileprint() +{ + if(cardOK) + { + sdprinting = true; + + } +} + +void CardReader::pauseSDPrint() +{ + if(sdprinting) + { + sdprinting = false; + } +} + + + +void CardReader::openFile(char* name,bool read) +{ + if(!cardOK) + return; + file.close(); + sdprinting = false; + + + SdFile myDir; + curDir=&root; + char *fname=name; + + char *dirname_start,*dirname_end; + if(name[0]=='/') + { + dirname_start=strchr(name,'/')+1; + while(dirname_start>0) + { + dirname_end=strchr(dirname_start,'/'); + //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); + //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); + if(dirname_end>0 && dirname_end>dirname_start) + { + char subdirname[13]; + strncpy(subdirname, dirname_start, dirname_end-dirname_start); + subdirname[dirname_end-dirname_start]=0; + SERIAL_ECHOLN(subdirname); + if(!myDir.open(curDir,subdirname,O_READ)) + { + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(subdirname); + SERIAL_PROTOCOLLNPGM("."); + return; + } + else + ;//SERIAL_ECHOLN("dive ok"); + + curDir=&myDir; + dirname_start=dirname_end+1; + } + else // the reminder after all /fsa/fdsa/ is the filename + { + fname=dirname_start; + //SERIAL_ECHOLN("remaider"); + //SERIAL_ECHOLN(fname); + break; + } + + } + } + else //relative path + { + curDir=&workDir; + } + if(read) + { + if (file.open(curDir, fname, O_READ)) + { + filesize = file.fileSize(); + SERIAL_PROTOCOLPGM("File opened:"); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLPGM(" Size:"); + SERIAL_PROTOCOLLN(filesize); + sdpos = 0; + + SERIAL_PROTOCOLLNPGM("File selected"); + LCD_MESSAGE(fname); + } + else + { + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLLNPGM("."); + } + } + else + { //write + if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + SERIAL_PROTOCOLPGM("open failed, File: "); + SERIAL_PROTOCOL(fname); + SERIAL_PROTOCOLLNPGM("."); + } + else + { + saving = true; + SERIAL_PROTOCOLPGM("Writing to file: "); + SERIAL_PROTOCOLLN(name); + LCD_MESSAGE(fname); + } + } + +} + +void CardReader::getStatus() +{ + if(cardOK){ + SERIAL_PROTOCOLPGM("SD printing byte "); + SERIAL_PROTOCOL(sdpos); + SERIAL_PROTOCOLPGM("/"); + SERIAL_PROTOCOLLN(filesize); + } + else{ + SERIAL_PROTOCOLLNPGM("Not SD printing"); + } +} +void CardReader::write_command(char *buf) +{ + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL) + { + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + file.write(begin); + if (file.writeError) + { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("error writing to file"); + } +} + + +void CardReader::checkautostart(bool force) +{ + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int8_t i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + enquecommand(cmd); + enquecommand("M24"); + found=true; + } + } + if(!found) + lastnr=-1; + else + lastnr++; +} + +void CardReader::closefile() +{ + file.sync(); + file.close(); + saving = false; +} + +void CardReader::getfilename(const uint8_t nr) +{ + curDir=&workDir; + lsAction=LS_GetFilename; + nrFiles=nr; + curDir->rewind(); + lsDive("",*curDir); + +} + +uint16_t CardReader::getnrfilenames() +{ + curDir=&workDir; + lsAction=LS_Count; + nrFiles=0; + curDir->rewind(); + lsDive("",*curDir); + //SERIAL_ECHOLN(nrFiles); + return nrFiles; +} + +void CardReader::chdir(const char * relpath) +{ + SdFile newfile; + SdFile *parent=&root; + + if(workDir.isOpen()) + parent=&workDir; + + if(!newfile.open(*parent,relpath, O_READ)) + { + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Cannot enter subdir:"); + SERIAL_ECHOLN(relpath); + } + else + { + workDirParentParent=workDirParent; + workDirParent=*parent; + + workDir=newfile; + } +} + +void CardReader::updir() +{ + if(!workDir.isRoot()) + { + workDir=workDirParent; + workDirParent=workDirParentParent; + } +} + + +void CardReader::printingHasFinished() +{ + st_synchronize(); + quickStop(); + sdprinting = false; + #ifdef STOP_HEATING_WAIT_FOR_SD_PRINTING + stop_heating_wait=true; + #endif + if(SD_FINISHED_STEPPERRELEASE) + { + //finishAndDisableSteppers(); + enquecommand(SD_FINISHED_RELEASECOMMAND); + } + autotempShutdown(); +} +void CardReader::fast_xfer(char* strchr_pointer) + { + char *pstr; + boolean done = false; + + //force heater pins low + if(HEATER_0_PIN > -1) WRITE(HEATER_0_PIN,LOW); + if(HEATER_BED_PIN > -1) WRITE(HEATER_BED_PIN,LOW); + + lastxferchar = 1; + xferbytes = 0; + + SERIAL_ECHOPGM("strchr_pointer "); + SERIAL_ECHOLN(strchr_pointer); + + pstr = strstr(strchr_pointer, " "); + //pstr = strchr_pointer; + + SERIAL_ECHOPGM("pstr "); + SERIAL_ECHOLN(pstr); + + if(pstr == NULL) + { + SERIAL_ECHOLN("invalid command"); + return; + } + + *pstr = '\0'; + + //check mode (currently only RAW is supported + if(strcmp(strchr_pointer, "RAW") != 0) + { + SERIAL_ECHOPGM("strchr_pointer "); + SERIAL_ECHOLN(strchr_pointer); + SERIAL_ECHOLN("Invalid transfer codec"); + return; + }else{ + SERIAL_ECHOPGM("Selected codec: "); + SERIAL_ECHOLN(strchr_pointer+4); + } + + if (!file.open(&root, pstr+1, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + SERIAL_ECHOPGM("open failed, File: "); + SERIAL_ECHOLN(pstr+1); + SERIAL_ECHOPGM("."); + }else{ + SERIAL_ECHOPGM("Writing to file: "); + SERIAL_ECHOLN(pstr+1); + } + + SERIAL_ECHOLN("ok"); + + //RAW transfer codec + //Host sends \0 then up to SD_FAST_XFER_CHUNK_SIZE then \0 + //when host is done, it sends \0\0. + //if a non \0 character is recieved at the beginning, host has failed somehow, kill the transfer. + + //read SD_FAST_XFER_CHUNK_SIZE bytes (or until \0 is recieved) + while(!done) + { + while(!MYSERIAL.available()) + { + } + if(MYSERIAL.peek() != 0) + { + //host has failed, this isn't a RAW chunk, it's an actual command + file.sync(); + file.close(); + return; + } + //clear the initial 0 + MYSERIAL.read(); + for(int i=0;i=filesize ;}; @@ -47,6 +50,7 @@ public: char filename[11]; bool filenameIsDir; int lastnr; //last number of the autostart; + char fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE + 1]; private: SdFile root,*curDir,workDir,workDirParent,workDirParentParent; Sd2Card card; @@ -63,40 +67,14 @@ private: int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. char* diveDirName; void lsDive(const char *prepend,SdFile parent); + int lastxferchar; + long xferbytes; }; - +#define IS_SD_PRINTING (card.sdprinting) #else -#define dir_t bool -class CardReader -{ -public: - FORCE_INLINE CardReader(){}; - - FORCE_INLINE static void initsd(){}; - FORCE_INLINE static void write_command(char *buf){}; - - FORCE_INLINE static void checkautostart(bool x) {}; - - FORCE_INLINE static void openFile(char* name,bool read){}; - FORCE_INLINE static void closefile() {}; - FORCE_INLINE static void release(){}; - FORCE_INLINE static void startFileprint(){}; - FORCE_INLINE static void startFilewrite(char *name){}; - FORCE_INLINE static void pauseSDPrint(){}; - FORCE_INLINE static void getStatus(){}; - - FORCE_INLINE static void selectFile(char* name){}; - FORCE_INLINE static void getfilename(const uint8_t nr){}; - FORCE_INLINE static uint8_t getnrfilenames(){return 0;}; - +#define IS_SD_PRINTING (false) - FORCE_INLINE static void ls() {}; - FORCE_INLINE static bool eof() {return true;}; - FORCE_INLINE static char get() {return 0;}; - FORCE_INLINE static void setIndex(){}; - FORCE_INLINE uint8_t percentDone(){return 0;}; -}; #endif //SDSUPPORT -#endif \ No newline at end of file +#endif diff --git a/Marlin/cardreader.h~ b/Marlin/cardreader.h~ new file mode 100644 index 0000000000..f8d604a329 --- /dev/null +++ b/Marlin/cardreader.h~ @@ -0,0 +1,109 @@ +#ifndef __CARDREADERH +#define __CARDREADERH + +#ifdef SDSUPPORT + +#include "SdFile.h" +enum LsAction {LS_SerialPrint,LS_Count,LS_GetFilename}; +class CardReader +{ +public: + CardReader(); + + void initsd(); + void write_command(char *buf); + //files auto[0-9].g on the sd card are performed in a row + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + + void checkautostart(bool x); + void openFile(char* name,bool read); + void closefile(); + void release(); + void startFileprint(); + void pauseSDPrint(); + void getStatus(); + void printingHasFinished(); + + void getfilename(const uint8_t nr); + uint16_t getnrfilenames(); + + + void ls(); + void chdir(const char * relpath); + void updir(); + void setroot(); + + void fast_xfer(char* strchr_pointer); + + + FORCE_INLINE bool eof() { return sdpos>=filesize ;}; + FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; + FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);}; + FORCE_INLINE uint8_t percentDone(){if(!sdprinting) return 0; if(filesize) return sdpos*100/filesize; else return 0;}; + FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;}; + +public: + bool saving; + bool sdprinting ; + bool cardOK ; + char filename[11]; + bool filenameIsDir; + int lastnr; //last number of the autostart; + char fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE + 1]; + int lastxferchar; + long xferbytes; +private: + SdFile root,*curDir,workDir,workDirParent,workDirParentParent; + Sd2Card card; + SdVolume volume; + SdFile file; + uint32_t filesize; + //int16_t n; + unsigned long autostart_atmillis; + uint32_t sdpos ; + + bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. + + LsAction lsAction; //stored for recursion. + int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. + char* diveDirName; + void lsDive(const char *prepend,SdFile parent); +}; + + +#else + +#define dir_t bool +class CardReader +{ +public: + FORCE_INLINE CardReader(){}; + + FORCE_INLINE static void initsd(){}; + FORCE_INLINE static void write_command(char *buf){}; + + FORCE_INLINE static void checkautostart(bool x) {}; + + FORCE_INLINE static void openFile(char* name,bool read){}; + FORCE_INLINE static void closefile() {}; + FORCE_INLINE static void release(){}; + FORCE_INLINE static void startFileprint(){}; + FORCE_INLINE static void startFilewrite(char *name){}; + FORCE_INLINE static void pauseSDPrint(){}; + FORCE_INLINE static void getStatus(){}; + + FORCE_INLINE static void selectFile(char* name){}; + FORCE_INLINE static void getfilename(const uint8_t nr){}; + FORCE_INLINE static uint8_t getnrfilenames(){return 0;}; + + + FORCE_INLINE static void ls() {}; + FORCE_INLINE static bool eof() {return true;}; + FORCE_INLINE static char get() {return 0;}; + FORCE_INLINE static void setIndex(){}; + FORCE_INLINE uint8_t percentDone(){return 0;}; + + FORCE_INLINE static void fast_xfer(char* strchr_pointer) {}; +}; +#endif //SDSUPPORT +#endif diff --git a/Marlin/language.h b/Marlin/language.h index 6dfd7e0be1..2cdbc59426 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -14,73 +14,7 @@ // LCD Menu Messages - #define WELCOME_MSG "RepRap Ready." - #define MSG_SD_INSERTED "Card Ready" - #define MSG_SD_REMOVED "Card Initiate" - #define MSG_MAIN " Main \003" - #define MSG_AUTOSTART " Autostart" - #define MSG_DISABLE_STEPPERS " Disable Steppers" - #define MSG_AUTO_HOME " Auto Home" - #define MSG_SET_ORIGIN " Set Origin" - #define MSG_PREHEAT_PLA " Preheat PLA" - #define MSG_PREHEAT_ABS " Preheat ABS" - #define MSG_COOLDOWN " Cooldown" - #define MSG_EXTRUDE " Extrude" - #define MSG_MOVE_AXIS " Move Axis \x7E" - #define MSG_SPEED " Speed:" - #define MSG_NOZZLE " \002Nozzle:" - #define MSG_BED " \002Bed:" - #define MSG_FAN_SPEED " Fan speed:" - #define MSG_FLOW " Flow:" - #define MSG_CONTROL " Control \003" - #define MSG_MIN " \002 Min:" - #define MSG_MAX " \002 Max:" - #define MSG_FACTOR " \002 Fact:" - #define MSG_AUTOTEMP " Autotemp:" - #define MSG_ON "On " - #define MSG_OFF "Off" - #define MSG_PID_P " PID-P: " - #define MSG_PID_I " PID-I: " - #define MSG_PID_D " PID-D: " - #define MSG_PID_C " PID-C: " - #define MSG_ACC " Acc:" - #define MSG_VXY_JERK " Vxy-jerk: " - #define MSG_VMAX " Vmax " - #define MSG_X "x:" - #define MSG_Y "y:" - #define MSG_Z "z:" - #define MSG_E "e:" - #define MSG_VMIN " Vmin:" - #define MSG_VTRAV_MIN " VTrav min:" - #define MSG_AMAX " Amax " - #define MSG_A_RETRACT " A-retract:" - #define MSG_XSTEPS " Xsteps/mm:" - #define MSG_YSTEPS " Ysteps/mm:" - #define MSG_ZSTEPS " Zsteps/mm:" - #define MSG_ESTEPS " Esteps/mm:" - #define MSG_MAIN_WIDE " Main \003" - #define MSG_TEMPERATURE_WIDE " Temperature \x7E" - #define MSG_MOTION_WIDE " Motion \x7E" - #define MSG_STORE_EPROM " Store EPROM" - #define MSG_LOAD_EPROM " Load EPROM" - #define MSG_RESTORE_FAILSAFE " Restore Failsafe" - #define MSG_REFRESH "\004Refresh" - #define MSG_WATCH " Watch \003" - #define MSG_PREPARE " Prepare \x7E" - #define MSG_CONTROL_ARROW " Control \x7E" - #define MSG_TUNE " Tune \x7E" - #define MSG_STOP_PRINT " Stop Print \x7E" - #define MSG_CARD_MENU " Card Menu \x7E" - #define MSG_NO_CARD " No Card" - #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." - -#endif - -#if LANGUAGE_CHOICE == 2 - -// LCD Menu Messages - - #define WELCOME_MSG "UltiMARLIN Ready." + #define WELCOME_MSG "Printer Ready." #define MSG_SD_INSERTED "Card inserted" #define MSG_SD_REMOVED "Card removed" #define MSG_MAIN " Main \003" @@ -88,10 +22,11 @@ #define MSG_DISABLE_STEPPERS " Disable Steppers" #define MSG_AUTO_HOME " Auto Home" #define MSG_SET_ORIGIN " Set Origin" - #define MSG_PREHEAT " Preheat" #define MSG_COOLDOWN " Cooldown" #define MSG_EXTRUDE " Extrude" - #define MSG_MOVE_AXIS " Move Axis \x7E" + #define MSG_PREHEAT_PLA " Preheat PLA" + #define MSG_PREHEAT_ABS " Preheat ABS" + #define MSG_MOVE_AXIS " Move Axis \x7E" #define MSG_SPEED " Speed:" #define MSG_NOZZLE " \002Nozzle:" #define MSG_BED " \002Bed:" @@ -132,108 +67,121 @@ #define MSG_REFRESH "\004Refresh" #define MSG_WATCH " Watch \003" #define MSG_PREPARE " Prepare \x7E" + #define MSG_PREPARE_ALT " Prepare \003" #define MSG_CONTROL_ARROW " Control \x7E" #define MSG_TUNE " Tune \x7E" #define MSG_STOP_PRINT " Stop Print \x7E" #define MSG_CARD_MENU " Card Menu \x7E" #define MSG_NO_CARD " No Card" #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." + #define MSG_DWELL "DWELL..." + #define MSG_NO_MOVE "No move." + #define MSG_PART_RELEASE "Partial Release" + #define MSG_KILLED "KILLED. " + #define MSG_PREHEAT_PLA " Preheat PLA" + #define MSG_PREHEAT_ABS " Preheat ABS" + #define MSG_STEPPER_RELEASED "Released." + + +// Serial Console Messages + + #define MSG_Enqueing "enqueing \"" + #define MSG_POWERUP "PowerUp" + #define MSG_EXTERNAL_RESET " External Reset" + #define MSG_BROWNOUT_RESET " Brown out Reset" + #define MSG_WATCHDOG_RESET " Watchdog Reset" + #define MSG_SOFTWARE_RESET " Software Reset" + #define MSG_MARLIN "Marlin: " + #define MSG_AUTHOR " | Author: " + #define MSG_CONFIGURATION_VER " Last Updated: " + #define MSG_FREE_MEMORY " Free Memory: " + #define MSG_PLANNER_BUFFER_BYTES " PlannerBufferBytes: " + #define MSG_OK "ok" + #define MSG_FILE_SAVED "Done saving file." + #define MSG_ERR_LINE_NO "Line Number is not Last Line Number+1, Last Line:" + #define MSG_ERR_CHECKSUM_MISMATCH "checksum mismatch, Last Line:" + #define MSG_ERR_NO_CHECKSUM "No Checksum with line number, Last Line:" + #define MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM "No Line Number with checksum, Last Line:" + #define MSG_FILE_PRINTED "Done printing file" + #define MSG_BEGIN_FILE_LIST "Begin file list" + #define MSG_END_FILE_LIST "End file list" + #define MSG_M104_INVALID_EXTRUDER "M104 Invalid extruder " + #define MSG_M105_INVALID_EXTRUDER "M105 Invalid extruder " + #define MSG_ERR_NO_THERMISTORS "No thermistors - no temp" + #define MSG_M109_INVALID_EXTRUDER "M109 Invalid extruder " + #define MSG_HEATING "Heating..." + #define MSG_HEATING_COMPLETE "Heating done." + #define MSG_BED_HEATING "Bed Heating." + #define MSG_BED_DONE "Bed done." + #define MSG_M115_REPORT "FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n" + #define MSG_COUNT_X " Count X:" + #define MSG_ERR_KILLED "Printer halted. kill() called !!" + #define MSG_RESEND "Resend:" + #define MSG_UNKNOWN_COMMAND "Unknown command:\"" + #define MSG_ACTIVE_EXTRUDER "Active Extruder: " + #define MSG_INVALID_EXTRUDER "Invalid extruder" + #define MSG_X_MIN "x_min:" + #define MSG_X_MAX "x_max:" + #define MSG_Y_MIN "y_min:" + #define MSG_Y_MAX "y_max:" + #define MSG_Z_MIN "z_min:" + #define MSG_Z_MAX "z_max:" + + #define MSG_SD_CANT_OPEN_SUBDIR "Cannot open subdir" + #define MSG_SD_INIT_FAIL "SD init fail" + #define MSG_SD_VOL_INIT_FAIL "volume.init failed" + #define MSG_SD_OPENROOT_FAIL "openRoot failed" + #define MSG_SD_CARD_OK "SD card ok" + #define MSG_SD_WORKDIR_FAIL "workDir open failed" + #define MSG_SD_OPEN_FILE_FAIL "open failed, File: " + #define MSG_SD_FILE_OPENED "File opened:" + #define MSG_SD_SIZE " Size:" + #define MSG_SD_FILE_SELECTED "File selected" + #define MSG_SD_WRITE_TO_FILE "Writing to file: " + #define MSG_SD_PRINTING_BYTE "SD printing byte " + #define MSG_SD_NOT_PRINTING "Not SD printing" + #define MSG_SD_ERR_WRITE_TO_FILE "error writing to file" + #define MSG_SD_CANT_ENTER_SUBDIR "Cannot enter subdir:" + + #define MSG_STEPPER_TO_HIGH "Steprate to high : " + #define MSG_ENDSTOPS_HIT "endstops hit: " + #define MSG_ERR_COLD_EXTRUDE_STOP " cold extrusion prevented" + #define MSG_ERR_LONG_EXTRUDE_STOP " too long extrusion prevented" #endif - -#if LANGUAGE_CHOICE == 3 - -// LCD Menu Messages - - #define WELCOME_MSG "RepRap Ready." - #define MSG_SD_INSERTED "Card Ready" - #define MSG_SD_REMOVED "Card Initiate" - #define MSG_MAIN " Main \003" - #define MSG_AUTOSTART " Autostart" - #define MSG_DISABLE_STEPPERS " Disable Steppers" - #define MSG_AUTO_HOME " Auto Home" - #define MSG_SET_ORIGIN " Set Origin" - #define MSG_PREHEAT " Preheat" - #define MSG_COOLDOWN " Cooldown" - #define MSG_EXTRUDE " Extrude" - #define MSG_MOVE_AXIS " Move Axis \x7E" - #define MSG_SPEED " Speed:" - #define MSG_NOZZLE " \002Nozzle:" - #define MSG_BED " \002Bed:" - #define MSG_FAN_SPEED " Fan speed:" - #define MSG_FLOW " Flow:" - #define MSG_CONTROL " Control \003" - #define MSG_MIN " \002 Min:" - #define MSG_MAX " \002 Max:" - #define MSG_FACTOR " \002 Fact:" - #define MSG_AUTOTEMP " Autotemp:" - #define MSG_ON "On " - #define MSG_OFF "Off" - #define MSG_PID_P " PID-P: " - #define MSG_PID_I " PID-I: " - #define MSG_PID_D " PID-D: " - #define MSG_PID_C " PID-C: " - #define MSG_ACC " Acc:" - #define MSG_VXY_JERK " Vxy-jerk: " - #define MSG_VMAX " Vmax " - #define MSG_X "x:" - #define MSG_Y "y:" - #define MSG_Z "z:" - #define MSG_E "e:" - #define MSG_VMIN " Vmin:" - #define MSG_VTRAV_MIN " VTrav min:" - #define MSG_AMAX " Amax " - #define MSG_A_RETRACT " A-retract:" - #define MSG_XSTEPS " Xsteps/mm:" - #define MSG_YSTEPS " Ysteps/mm:" - #define MSG_ZSTEPS " Zsteps/mm:" - #define MSG_ESTEPS " Esteps/mm:" - #define MSG_MAIN_WIDE " Main \003" - #define MSG_TEMPERATURE_WIDE " Temperature \x7E" - #define MSG_MOTION_WIDE " Motion \x7E" - #define MSG_STORE_EPROM " Store EPROM" - #define MSG_LOAD_EPROM " Load EPROM" - #define MSG_RESTORE_FAILSAFE " Restore Failsafe" - #define MSG_REFRESH "\004Refresh" - #define MSG_WATCH " Watch \003" - #define MSG_PREPARE " Prepare \x7E" - #define MSG_CONTROL_ARROW " Control \x7E" - #define MSG_TUNE " Tune \x7E" - #define MSG_STOP_PRINT " Stop Print \x7E" - #define MSG_CARD_MENU " Card Menu \x7E" - #define MSG_NO_CARD " No Card" - #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." - -#endif - #if LANGUAGE_CHOICE == 4 // LCD Menu Messages - #define WELCOME_MSG "RepRap Ready." - #define MSG_SD_INSERTED "Card Ready" - #define MSG_SD_REMOVED "Card Initiate" + #define WELCOME_MSG "UltiMARLIN Ready." + + #define MSG_SD_INSERTED "Card inserted" + #define MSG_SD_REMOVED "Card removed" #define MSG_MAIN " Main \003" #define MSG_AUTOSTART " Autostart" - #define MSG_DISABLE_STEPPERS " Disable Steppers" - #define MSG_AUTO_HOME " Auto Home" - #define MSG_SET_ORIGIN " Set Origin" - #define MSG_PREHEAT " Preheat" - #define MSG_COOLDOWN " Cooldown" + #define MSG_DISABLE_STEPPERS " Stepper abschalten" + #define MSG_AUTO_HOME " Auto Heim" + #define MSG_SET_ORIGIN " Position setzen" + #define MSG_PREHEAT_PLA " Aufheizen PLA" + #define MSG_PREHEAT_ABS " Aufheizen ABS" + #define MSG_COOLDOWN " Abkuehlen" #define MSG_EXTRUDE " Extrude" - #define MSG_MOVE_AXIS " Move Axis \x7E" - #define MSG_SPEED " Speed:" - #define MSG_NOZZLE " \002Nozzle:" - #define MSG_BED " \002Bed:" - #define MSG_FAN_SPEED " Fan speed:" - #define MSG_FLOW " Flow:" - #define MSG_CONTROL " Control \003" + #define MSG_PREHEAT_PLA " Preheat PLA" + #define MSG_PREHEAT_ABS " Preheat ABS" + #define MSG_MOVE_AXIS " Move Axis \x7E" + #define MSG_MOVE_AXIS " Achsen verfahren \x7E" + #define MSG_SPEED " Geschw:" + #define MSG_NOZZLE " \002Duese:" + #define MSG_BED " \002Bett:" + #define MSG_FAN_SPEED " Luefter geschw.:" + #define MSG_FLOW " Fluss:" + #define MSG_CONTROL " Kontrolle \003" #define MSG_MIN " \002 Min:" #define MSG_MAX " \002 Max:" - #define MSG_FACTOR " \002 Fact:" - #define MSG_AUTOTEMP " Autotemp:" - #define MSG_ON "On " - #define MSG_OFF "Off" + #define MSG_FACTOR " \002 Faktor:" + #define MSG_AUTOTEMP " AutoTemp:" + #define MSG_ON "Ein " + #define MSG_OFF "Aus " #define MSG_PID_P " PID-P: " #define MSG_PID_I " PID-I: " #define MSG_PID_D " PID-D: " @@ -254,86 +202,94 @@ #define MSG_ZSTEPS " Zsteps/mm:" #define MSG_ESTEPS " Esteps/mm:" #define MSG_MAIN_WIDE " Main \003" - #define MSG_TEMPERATURE_WIDE " Temperature \x7E" + #define MSG_TEMPERATURE_WIDE " Temperatur \x7E" #define MSG_MOTION_WIDE " Motion \x7E" - #define MSG_STORE_EPROM " Store EPROM" - #define MSG_LOAD_EPROM " Load EPROM" - #define MSG_RESTORE_FAILSAFE " Restore Failsafe" + #define MSG_STORE_EPROM " EPROM speichern" + #define MSG_LOAD_EPROM " EPROM laden" + #define MSG_RESTORE_FAILSAFE " Standard Konfig." #define MSG_REFRESH "\004Refresh" - #define MSG_WATCH " Watch \003" + #define MSG_WATCH " Beobachten \003" #define MSG_PREPARE " Prepare \x7E" + #define MSG_PREPARE_ALT " Prepare \003" #define MSG_CONTROL_ARROW " Control \x7E" #define MSG_TUNE " Tune \x7E" - #define MSG_STOP_PRINT " Stop Print \x7E" - #define MSG_CARD_MENU " Card Menu \x7E" - #define MSG_NO_CARD " No Card" - #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." + #define MSG_STOP_PRINT " Druck stoppen \x7E" + #define MSG_CARD_MENU " SDKarten Menue \x7E" + #define MSG_NO_CARD " Keine SDKarte" + #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Fehler in der Menuestruktur." + #define MSG_DWELL "DWELL..." + #define MSG_NO_MOVE "No move." + #define MSG_PART_RELEASE "Partial Release" + #define MSG_KILLED "KILLED. " + #define MSG_PREHEAT_PLA " Preheat PLA" + #define MSG_PREHEAT_ABS " Preheat ABS" + #define MSG_STEPPER_RELEASED "Released." + + +// Serial Console Messages + + #define MSG_Enqueing "enqueing \"" + #define MSG_POWERUP "PowerUp" + #define MSG_EXTERNAL_RESET " External Reset" + #define MSG_BROWNOUT_RESET " Brown out Reset" + #define MSG_WATCHDOG_RESET " Watchdog Reset" + #define MSG_SOFTWARE_RESET " Software Reset" + #define MSG_MARLIN "Marlin: " + #define MSG_AUTHOR " | Author: " + #define MSG_CONFIGURATION_VER " Last Updated: " + #define MSG_FREE_MEMORY " Free Memory: " + #define MSG_PLANNER_BUFFER_BYTES " PlannerBufferBytes: " + #define MSG_OK "ok" + #define MSG_FILE_SAVED "Done saving file." + #define MSG_ERR_LINE_NO "Line Number is not Last Line Number+1, Last Line:" + #define MSG_ERR_CHECKSUM_MISMATCH "checksum mismatch, Last Line:" + #define MSG_ERR_NO_CHECKSUM "No Checksum with line number, Last Line:" + #define MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM "No Line Number with checksum, Last Line:" + #define MSG_FILE_PRINTED "Done printing file" + #define MSG_BEGIN_FILE_LIST "Begin file list" + #define MSG_END_FILE_LIST "End file list" + #define MSG_M104_INVALID_EXTRUDER "M104 Invalid extruder " + #define MSG_M105_INVALID_EXTRUDER "M105 Invalid extruder " + #define MSG_ERR_NO_THERMISTORS "No thermistors - no temp" + #define MSG_M109_INVALID_EXTRUDER "M109 Invalid extruder " + #define MSG_HEATING "Heating..." + #define MSG_HEATING_COMPLETE "Heating done." + #define MSG_BED_HEATING "Bed Heating." + #define MSG_BED_DONE "Bed done." + #define MSG_M115_REPORT "FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n" + #define MSG_COUNT_X " Count X:" + #define MSG_ERR_KILLED "Printer halted. kill() called !!" + #define MSG_RESEND "Resend:" + #define MSG_UNKNOWN_COMMAND "Unknown command:\"" + #define MSG_ACTIVE_EXTRUDER "Active Extruder: " + #define MSG_INVALID_EXTRUDER "Invalid extruder" + #define MSG_X_MIN "x_min:" + #define MSG_X_MAX "x_max:" + #define MSG_Y_MIN "y_min:" + #define MSG_Y_MAX "y_max:" + #define MSG_Z_MIN "z_min:" + #define MSG_Z_MAX "z_max:" + + #define MSG_SD_CANT_OPEN_SUBDIR "Cannot open subdir" + #define MSG_SD_INIT_FAIL "SD init fail" + #define MSG_SD_VOL_INIT_FAIL "volume.init failed" + #define MSG_SD_OPENROOT_FAIL "openRoot failed" + #define MSG_SD_CARD_OK "SD card ok" + #define MSG_SD_WORKDIR_FAIL "workDir open failed" + #define MSG_SD_OPEN_FILE_FAIL "open failed, File: " + #define MSG_SD_FILE_OPENED "File opened:" + #define MSG_SD_SIZE " Size:" + #define MSG_SD_FILE_SELECTED "File selected" + #define MSG_SD_WRITE_TO_FILE "Writing to file: " + #define MSG_SD_PRINTING_BYTE "SD printing byte " + #define MSG_SD_NOT_PRINTING "Not SD printing" + #define MSG_SD_ERR_WRITE_TO_FILE "error writing to file" + #define MSG_SD_CANT_ENTER_SUBDIR "Cannot enter subdir:" + + #define MSG_STEPPER_TO_HIGH "Steprate to high : " + #define MSG_ENDSTOPS_HIT "endstops hit: " + #define MSG_ERR_COLD_EXTRUDE_STOP " cold extrusion prevented" + #define MSG_ERR_LONG_EXTRUDE_STOP " too long extrusion prevented" #endif - -#if LANGUAGE_CHOICE == 5 - -// LCD Menu Messages - - #define WELCOME_MSG "RepRap Ready." - #define MSG_SD_INSERTED "Card Ready" - #define MSG_SD_REMOVED "Card Initiate" - #define MSG_MAIN " Main \003" - #define MSG_AUTOSTART " Autostart" - #define MSG_DISABLE_STEPPERS " Disable Steppers" - #define MSG_AUTO_HOME " Auto Home" - #define MSG_SET_ORIGIN " Set Origin" - #define MSG_PREHEAT " Preheat" - #define MSG_COOLDOWN " Cooldown" - #define MSG_EXTRUDE " Extrude" - #define MSG_MOVE_AXIS " Move Axis \x7E" - #define MSG_SPEED " Speed:" - #define MSG_NOZZLE " \002Nozzle:" - #define MSG_BED " \002Bed:" - #define MSG_FAN_SPEED " Fan speed:" - #define MSG_FLOW " Flow:" - #define MSG_CONTROL " Control \003" - #define MSG_MIN " \002 Min:" - #define MSG_MAX " \002 Max:" - #define MSG_FACTOR " \002 Fact:" - #define MSG_AUTOTEMP " Autotemp:" - #define MSG_ON "On " - #define MSG_OFF "Off" - #define MSG_PID_P " PID-P: " - #define MSG_PID_I " PID-I: " - #define MSG_PID_D " PID-D: " - #define MSG_PID_C " PID-C: " - #define MSG_ACC " Acc:" - #define MSG_VXY_JERK " Vxy-jerk: " - #define MSG_VMAX " Vmax " - #define MSG_X "x:" - #define MSG_Y "y:" - #define MSG_Z "z:" - #define MSG_E "e:" - #define MSG_VMIN " Vmin:" - #define MSG_VTRAV_MIN " VTrav min:" - #define MSG_AMAX " Amax " - #define MSG_A_RETRACT " A-retract:" - #define MSG_XSTEPS " Xsteps/mm:" - #define MSG_YSTEPS " Ysteps/mm:" - #define MSG_ZSTEPS " Zsteps/mm:" - #define MSG_ESTEPS " Esteps/mm:" - #define MSG_MAIN_WIDE " Main \003" - #define MSG_TEMPERATURE_WIDE " Temperature \x7E" - #define MSG_MOTION_WIDE " Motion \x7E" - #define MSG_STORE_EPROM " Store EPROM" - #define MSG_LOAD_EPROM " Load EPROM" - #define MSG_RESTORE_FAILSAFE " Restore Failsafe" - #define MSG_REFRESH "\004Refresh" - #define MSG_WATCH " Watch \003" - #define MSG_PREPARE " Prepare \x7E" - #define MSG_CONTROL_ARROW " Control \x7E" - #define MSG_TUNE " Tune \x7E" - #define MSG_STOP_PRINT " Stop Print \x7E" - #define MSG_CARD_MENU " Card Menu \x7E" - #define MSG_NO_CARD " No Card" - #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." - -#endif - #endif // ifndef LANGUAGE_H diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index a24b2b782c..67619b86f3 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -122,6 +122,18 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 arc_target[axis_1] = center_axis1 + r_axis1; arc_target[axis_linear] += linear_per_segment; arc_target[E_AXIS] += extruder_per_segment; + + if (min_software_endstops) { + if (arc_target[X_AXIS] < X_HOME_POS) arc_target[X_AXIS] = X_HOME_POS; + if (arc_target[Y_AXIS] < Y_HOME_POS) arc_target[Y_AXIS] = Y_HOME_POS; + if (arc_target[Z_AXIS] < Z_HOME_POS) arc_target[Z_AXIS] = Z_HOME_POS; + } + + if (max_software_endstops) { + if (arc_target[X_AXIS] > X_MAX_LENGTH) arc_target[X_AXIS] = X_MAX_LENGTH; + if (arc_target[Y_AXIS] > Y_MAX_LENGTH) arc_target[Y_AXIS] = Y_MAX_LENGTH; + if (arc_target[Z_AXIS] > Z_MAX_LENGTH) arc_target[Z_AXIS] = Z_MAX_LENGTH; + } plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, extruder); } diff --git a/Marlin/pins.h b/Marlin/pins.h index 0b0cba3371..25c69b6ce6 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -533,7 +533,7 @@ #define LED_PIN -1 -#define FAN_PIN -1 //12 +#define FAN_PIN 12 //12 #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -544,7 +544,7 @@ #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 diff --git a/Marlin/pins.h~ b/Marlin/pins.h~ new file mode 100644 index 0000000000..0b0cba3371 --- /dev/null +++ b/Marlin/pins.h~ @@ -0,0 +1,905 @@ +#ifndef PINS_H +#define PINS_H + +#if MOTHERBOARD == 99 +#define KNOWN_BOARD 1 + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN -1 +#define X_MAX_PIN 16 + +#define Y_STEP_PIN 5 +#define Y_DIR_PIN 6 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 67 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 62 +#define Z_DIR_PIN 63 +#define Z_ENABLE_PIN -1 +#define Z_MIN_PIN 59 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 65 +#define E0_DIR_PIN 66 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 9 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 10 + +#endif /* 99 */ + +/**************************************************************************************** +* Arduino pin assignment +* +* ATMega168 +* +-\/-+ +* PC6 1| |28 PC5 (AI 5 / D19) +* (D 0) PD0 2| |27 PC4 (AI 4 / D18) +* (D 1) PD1 3| |26 PC3 (AI 3 / D17) +* (D 2) PD2 4| |25 PC2 (AI 2 / D16) +* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) +* (D 4) PD4 6| |23 PC0 (AI 0 / D14) +* VCC 7| |22 GND +* GND 8| |21 AREF +* PB6 9| |20 AVCC +* PB7 10| |19 PB5 (D 13) +* PWM+ (D 5) PD5 11| |18 PB4 (D 12) +* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +* (D 7) PD7 13| |16 PB2 (D 10) PWM +* (D 8) PB0 14| |15 PB1 (D 9) PWM +* +----+ +****************************************************************************************/ +#if MOTHERBOARD == 0 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega168__ +#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. +#endif + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 4 +#define X_MAX_PIN 9 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN 13 + +#define Z_STEP_PIN 19 +#define Z_DIR_PIN 18 +#define Z_ENABLE_PIN 5 +#define Z_MIN_PIN 17 +#define Z_MAX_PIN 16 + +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 15 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 +#endif + + + +/**************************************************************************************** +* Sanguino/RepRap Motherboard with direct-drive extruders +* +* ATMega644P +* +* +---\/---+ +* (D 0) PB0 1| |40 PA0 (AI 0 / D31) +* (D 1) PB1 2| |39 PA1 (AI 1 / D30) +* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) +* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) +* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) +* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) +* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) +* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) +* RST 9| |32 AREF +* VCC 10| |31 GND +* GND 11| |30 AVCC +* XTAL2 12| |29 PC7 (D 23) +* XTAL1 13| |28 PC6 (D 22) +* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI +* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO +* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS +* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK +* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA +* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL +* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM +* +--------+ +* +****************************************************************************************/ +#if MOTHERBOARD == 1 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 19 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PIN 29 +#define Z_DIR_PIN 30 +#define Z_ENABLE_PIN 31 +#define Z_MIN_PIN 2 +#define Z_MAX_PIN 1 + +#define E0_STEP_PIN 12 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN 3 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN 0 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 14 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 +/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ + + + +#endif + + +/**************************************************************************************** +* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* +* +****************************************************************************************/ +#if MOTHERBOARD == 2 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 19 +#define X_MIN_PIN 20 +#define X_MAX_PIN 21 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN 26 + +#define Z_STEP_PINN 27 +#define Z_DIR_PINN 28 +#define Z_ENABLE_PIN 29 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 31 + +#define E0_STEP_PIN 17 +#define E0_DIR_PIN 16 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 4 +#define LED_PIN 0 + +#define SD_CARD_WRITE 2 +#define SD_CARD_DETECT 3 +#define SD_CARD_SELECT 4 + +//our RS485 pins +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 + +//pin for controlling the PSU. +#define PS_ON_PIN 14 + +#define FAN_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN -1 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#endif + +/**************************************************************************************** +* Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 33 +#define MOTHERBOARD 3 +#define RAMPS_V_1_3 +#endif +#if MOTHERBOARD == 3 +#define KNOWN_BOARD 1 + +//////////////////FIX THIS////////////// +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 +// #define RAMPS_V_1_3 +// #define RAMPS_V_1_0 + +#ifdef RAMPS_V_1_3 + +#define X_STEP_PIN 54 +#define X_DIR_PIN 55 +#define X_ENABLE_PIN 38 +#define X_MIN_PIN 3 +#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. + +#define Y_STEP_PIN 60 +#define Y_DIR_PIN 61 +#define Y_ENABLE_PIN 56 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN 15 //15 + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 62 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN 19 //19 + +#define E0_STEP_PIN 26 +#define E0_DIR_PIN 28 +#define E0_ENABLE_PIN 24 + +#define E1_STEP_PIN 36 +#define E1_DIR_PIN 34 +#define E1_ENABLE_PIN 30 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 4 +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#define HEATER_0_PIN 10 // EXTRUDER 1 +#define HEATER_1_PIN 9 // EXTRUDER 2 +#define HEATER_2_PIN -1 // EXTRUDER 2 +#define TEMP_0_PIN 13 // ANALOG NUMBERING +#define TEMP_1_PIN 15 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING +#define HEATER_BED_PIN 8 // BED +#define TEMP_BED_PIN 14 // ANALOG NUMBERING + + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default + +#define X_STEP_PIN 26 +#define X_DIR_PIN 28 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 + +#define Y_STEP_PIN 38 +#define Y_DIR_PIN 40 +#define Y_ENABLE_PIN 36 +#define Y_MIN_PIN 16 +#define Y_MAX_PIN -1 //17 + +#define Z_STEP_PIN 44 +#define Z_DIR_PIN 46 +#define Z_ENABLE_PIN 42 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E0_STEP_PIN 32 +#define E0_DIR_PIN 34 +#define E0_ENABLE_PIN 30 + +#define SDPOWER 48 +#define SDSS 53 +#define LED_PIN 13 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + + + +#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 + #define HEATER_0_PIN 12 // RAMPS 1.0 + #define HEATER_BED_PIN -1 // RAMPS 1.0 + #define FAN_PIN 11 // RAMPS 1.0 +#else // RAMPS_V_1_1 or RAMPS_V_1_2 + #define HEATER_0_PIN 10 // RAMPS 1.1 + #define HEATER_BED_PIN 8 // RAMPS 1.1 + #define FAN_PIN 9 // RAMPS 1.1 +#endif +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#endif + +// SPI for Max6675 Thermocouple + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define MAX_SCK_PIN 52 + #define MAX_MISO_PIN 50 + #define MAX_MOSI_PIN 51 + #define MAX6675_SS 53 +#else + #define MAX6675_SS 49 +#endif + +#endif + +/**************************************************************************************** +* Duemilanove w/ ATMega328P pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 4 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega328P__ +#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 17 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 13 +#define Z_DIR_PIN 3 +#define Z_ENABLE_PIN 2 +#define Z_MIN_PIN 4 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN 5 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#endif + +/**************************************************************************************** +* Gen6 pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 5 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ + #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +//x axis pins + #define X_STEP_PIN 15 + #define X_DIR_PIN 18 + #define X_ENABLE_PIN 19 + #define X_MIN_PIN 20 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 25 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 27 + #define Z_DIR_PIN 28 + #define Z_ENABLE_PIN 29 + #define Z_MIN_PIN 30 + #define Z_MAX_PIN -1 + + //extruder pins + #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 + #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 + #define HEATER_1_PIN -1 + #define HEATER_2_PIN -1 + #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 + + #define SDPOWER -1 + #define SDSS 17 + #define LED_PIN -1 //changed @ rkoeppl 20110410 + #define FAN_PIN -1 //changed @ rkoeppl 20110410 + #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 + //our pin for debugging. + + #define DEBUG_PIN 0 + + //our RS485 pins + #define TX_ENABLE_PIN 12 + #define RX_ENABLE_PIN 13 + + +#endif + +/**************************************************************************************** +* Sanguinololu pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 62 +#define MOTHERBOARD 6 +#define SANGUINOLOLU_V_1_2 +#endif +#if MOTHERBOARD == 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#ifndef __AVR_ATmega1284P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 1 +#define E0_DIR_PIN 0 + +#define LED_PIN -1 + +#define FAN_PIN -1 //12 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#ifdef SANGUINOLOLU_V_1_2 + +#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E0_ENABLE_PIN 14 + +#else + +#define HEATER_BED_PIN 14 // (bed) +#define X_ENABLE_PIN -1 +#define Y_ENABLE_PIN -1 +#define Z_ENABLE_PIN -1 +#define E0_ENABLE_PIN -1 + +#endif + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define SDPOWER -1 +#define SDSS 31 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 10 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define HEATER_1_PIN 3 +#define TEMP_1_PIN 9 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN 49 +#define E1_DIR_PIN 47 +#define E1_ENABLE_PIN 51 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 +#define SUICIDE_PIN 54 //PIN that has to be turned on right after start, to keep power flowing. + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + //buttons are attached to a shift register + #define SHIFT_CLK 38 + #define SHIFT_LD 42 + #define SHIFT_OUT 40 + #define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 5 + #define LCD_PINS_D4 6 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 20 + #define LCD_PINS_D7 19 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + +#endif + +#if MOTHERBOARD == 71 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment (Old electronics) +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 15 +#define X_MAX_PIN 14 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 17 +#define Y_MAX_PIN 16 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 19 +#define Z_MAX_PIN 18 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define HEATER_1_PIN 1 +#define TEMP_1_PIN 1 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN -1 +#define E1_DIR_PIN -1 +#define E1_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define SUICIDE_PIN -1 //PIN that has to be turned on right after start, to keep power flowing. + +#define LCD_PINS_RS 24 +#define LCD_PINS_ENABLE 22 +#define LCD_PINS_D4 36 +#define LCD_PINS_D5 34 +#define LCD_PINS_D6 32 +#define LCD_PINS_D7 30 + +#endif + +/**************************************************************************************** +* Teensylu 0.7 pin assingments (ATMEGA90USB) +* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! +****************************************************************************************/ +#if MOTHERBOARD == 8 +#define MOTHERBOARD 8 +#define KNOWN_BOARD 1 + + +#define X_STEP_PIN 0 +#define X_DIR_PIN 1 +#define X_ENABLE_PIN 39 +#define X_MIN_PIN 13 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 2 +#define Y_DIR_PIN 3 +#define Y_ENABLE_PIN 38 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 4 +#define Z_DIR_PIN 5 +#define Z_ENABLE_PIN 23 +#define Z_MIN_PIN 15 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 6 +#define E0_DIR_PIN 7 +#define E0_ENABLE_PIN 19 + + + +#define HEATER_0_PIN 21 // Extruder +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define HEATER_BED_PIN 20 // Bed +#define FAN_PIN 22 // Fan + +#define TEMP_0_PIN 7 // Extruder +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // Bed + +#define SDPOWER -1 +#define SDSS 8 +#define LED_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define ALARM_PIN -1 + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define SCK_PIN 9 + #define MISO_PIN 11 + #define MOSI_PIN 10 +#endif +#endif + +/**************************************************************************************** +* Gen3+ pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 9 +#define MOTHERBOARD 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_MIN_PIN 20 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 27 +#define Z_DIR_PIN 28 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 17 +#define E_DIR_PIN 21 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN 14 +#define KILL_PIN -1 + +#define HEATER_0_PIN 12 // (extruder) + +#define HEATER_1_PIN 16 // (bed) +#define X_ENABLE_PIN 19 +#define Y_ENABLE_PIN 24 +#define Z_ENABLE_PIN 29 +#define E_ENABLE_PIN 13 + +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN 5 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 4 +#define HEATER_2_PIN -1 + +#endif + + + + +#ifndef KNOWN_BOARD +#error Unknown MOTHERBOARD value in configuration.h +#endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN +#if EXTRUDERS == 3 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN +#elif EXTRUDERS == 2 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN + #define _E2_PINS -1 +#elif EXTRUDERS == 1 + #define _E1_PINS -1 + #define _E2_PINS -1 +#else + #error Unsupported number of extruders +#endif +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ + HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ + HEATER_BED_PIN, FAN_PIN, \ + _E0_PINS, _E1_PINS, _E2_PINS, \ + TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } +#endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index e877d43124..7a8c121db9 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -59,6 +59,7 @@ #include "stepper.h" #include "temperature.h" #include "ultralcd.h" +#include "language.h" //=========================================================================== //=============================public variables ============================ @@ -73,6 +74,7 @@ float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT A float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. float max_z_jerk; +float max_e_jerk; float mintravelfeedrate; unsigned long axis_steps_per_sqr_second[NUM_AXIS]; @@ -417,23 +419,34 @@ void check_axes_activity() { unsigned char y_active = 0; unsigned char z_active = 0; unsigned char e_active = 0; + unsigned char fan_speed = 0; + unsigned char tail_fan_speed = 0; block_t *block; if(block_buffer_tail != block_buffer_head) { uint8_t block_index = block_buffer_tail; + tail_fan_speed = block_buffer[block_index].fan_speed; while(block_index != block_buffer_head) { block = &block_buffer[block_index]; if(block->steps_x != 0) x_active++; if(block->steps_y != 0) y_active++; if(block->steps_z != 0) z_active++; if(block->steps_e != 0) e_active++; + if(block->fan_speed != 0) fan_speed++; block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); } } + else { + if (FanSpeed != 0) analogWrite(FAN_PIN,FanSpeed); // If buffer is empty use current fan speed + } if((DISABLE_X) && (x_active == 0)) disable_x(); if((DISABLE_Y) && (y_active == 0)) disable_y(); if((DISABLE_Z) && (z_active == 0)) disable_z(); if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } + if((FanSpeed == 0) && (fan_speed ==0)) analogWrite(FAN_PIN, 0); + if (FanSpeed != 0 && tail_fan_speed !=0) { + analogWrite(FAN_PIN,tail_fan_speed); + } } @@ -441,12 +454,11 @@ float junction_deviation = 0.1; // Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in // mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration // calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, uint8_t &extruder) +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder) { // Calculate the buffer head after we push this byte int next_buffer_head = next_block_index(block_buffer_head); - // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. while(block_buffer_tail == next_buffer_head) { @@ -470,13 +482,13 @@ void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, u { position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part SERIAL_ECHO_START; - SERIAL_ECHOLNPGM(" cold extrusion prevented"); + SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP); } if(labs(target[E_AXIS]-position[E_AXIS])>axis_steps_per_unit[E_AXIS]*EXTRUDE_MAXLENGTH) { position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part SERIAL_ECHO_START; - SERIAL_ECHOLNPGM(" too long extrusion prevented"); + SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP); } #endif @@ -498,6 +510,8 @@ void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, u // Bail if this is a zero-length block if (block->step_event_count <=dropsegments) { return; }; + block->fan_speed = FanSpeed; + // Compute direction bits for this block block->direction_bits = 0; if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<steps_e != 0) { enable_e0();enable_e1();enable_e2(); } + if (block->steps_e == 0) { + if(feed_ratenominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 - if (block->steps_e == 0) { - if(feed_rate max_z_jerk/2) vmax_junction = max_z_jerk/2; vmax_junction = min(vmax_junction, block->nominal_speed); - + if(abs(current_speed[E_AXIS]) > max_e_jerk/2) + vmax_junction = min(vmax_junction, max_e_jerk/2); + if ((moves_queued > 1) && (previous_nominal_speed > 0.0)) { float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { @@ -708,6 +725,9 @@ void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, u if(abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { vmax_junction *= (max_z_jerk/abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); } + if(abs(current_speed[E_AXIS] - previous_speed[E_AXIS]) > max_e_jerk) { + vmax_junction *= (max_e_jerk/abs(current_speed[E_AXIS] - previous_speed[E_AXIS])); + } } block->max_entry_speed = vmax_junction; diff --git a/Marlin/planner.h b/Marlin/planner.h index c90581bfd8..873441bb05 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -59,6 +59,7 @@ typedef struct { unsigned long initial_rate; // The jerk-adjusted step rate at start of block unsigned long final_rate; // The minimal rate at exit unsigned long acceleration_st; // acceleration steps/sec^2 + unsigned long fan_speed; volatile char busy; } block_t; @@ -67,7 +68,7 @@ void plan_init(); // Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in // millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, uint8_t &extruder); +void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder); // Set position. Used for G92 instructions. void plan_set_position(const float &x, const float &y, const float &z, const float &e); @@ -87,6 +88,7 @@ extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DE extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. extern float max_z_jerk; +extern float max_e_jerk; extern float mintravelfeedrate; extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 6bd84b13f0..55c09902bc 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -21,15 +21,12 @@ /* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith and Philipp Tiefenbacher. */ - - - #include "Marlin.h" #include "stepper.h" #include "planner.h" #include "temperature.h" #include "ultralcd.h" - +#include "language.h" #include "speed_lookuptable.h" @@ -172,7 +169,7 @@ void checkHitEndstops() { if( endstop_x_hit || endstop_y_hit || endstop_z_hit) { SERIAL_ECHO_START; - SERIAL_ECHOPGM("endstops hit: "); + SERIAL_ECHOPGM(MSG_ENDSTOPS_HIT); if(endstop_x_hit) { SERIAL_ECHOPAIR(" X:",(float)endstops_trigsteps[X_AXIS]/axis_steps_per_unit[X_AXIS]); } @@ -254,7 +251,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { timer = (unsigned short)pgm_read_word_near(table_address); timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); } - if(timer < 100) { timer = 100; MYSERIAL.print("Steprate to high : "); MYSERIAL.println(step_rate); }//(20kHz this should never happen) + if(timer < 100) { timer = 100; MYSERIAL.print(MSG_STEPPER_TO_HIGH); MYSERIAL.println(step_rate); }//(20kHz this should never happen) return timer; } @@ -303,7 +300,8 @@ ISR(TIMER1_COMPA_vect) counter_y = counter_x; counter_z = counter_x; counter_e = counter_x; - step_events_completed = 0; + step_events_completed = 0; + #ifdef Z_LATE_ENABLE if(current_block->steps_z > 0) { enable_z(); @@ -432,7 +430,7 @@ ISR(TIMER1_COMPA_vect) } else { // +direction NORM_E_DIR(); - count_direction[E_AXIS]=-1; + count_direction[E_AXIS]=1; } #endif //!ADVANCE @@ -808,7 +806,7 @@ long st_get_position(uint8_t axis) void finishAndDisableSteppers() { st_synchronize(); - LCD_MESSAGEPGM("Released."); + LCD_MESSAGEPGM(MSG_STEPPER_RELEASED); disable_x(); disable_y(); disable_z(); @@ -822,6 +820,7 @@ void quickStop() DISABLE_STEPPER_DRIVER_INTERRUPT(); while(blocks_queued()) plan_discard_current_block(); + current_block = NULL; ENABLE_STEPPER_DRIVER_INTERRUPT(); } diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 237425b1db..49c2eb4d40 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -398,7 +398,7 @@ float analog2temp(int raw, uint8_t e) { // For bed temperature measurement. float analog2tempBed(int raw) { #ifdef BED_USES_THERMISTOR - int celsius = 0; + float celsius = 0; byte i; raw = (1023 * OVERSAMPLENR) - raw; @@ -409,9 +409,8 @@ float analog2tempBed(int raw) { { celsius = PGM_RD_W(bedtemptable[i-1][1]) + (raw - PGM_RD_W(bedtemptable[i-1][0])) * - (PGM_RD_W(bedtemptable[i][1]) - PGM_RD_W(bedtemptable[i-1][1])) / - (PGM_RD_W(bedtemptable[i][0]) - PGM_RD_W(bedtemptable[i-1][0])); - + (float)(PGM_RD_W(bedtemptable[i][1]) - PGM_RD_W(bedtemptable[i-1][1])) / + (float)(PGM_RD_W(bedtemptable[i][0]) - PGM_RD_W(bedtemptable[i-1][0])); break; } } @@ -420,13 +419,12 @@ float analog2tempBed(int raw) { if (i == bedtemptable_len) celsius = PGM_RD_W(bedtemptable[i-1][1]); return celsius; - #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 - return 0; } void tp_init() @@ -852,18 +850,18 @@ ISR(TIMER0_COMPB_vect) for(unsigned char e = 0; e < EXTRUDERS; e++) { if(current_raw[e] >= maxttemp[e]) { target_raw[e] = 0; - #if (PS_ON != -1) + max_temp_error(e); + #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE { - max_temp_error(e); kill();; } #endif } if(current_raw[e] <= minttemp[e]) { target_raw[e] = 0; - #if (PS_ON != -1) + min_temp_error(e); + #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE { - min_temp_error(e); kill(); } #endif diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index c4392d26fc..253149cbba 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -129,6 +129,7 @@ //conversion routines, could need some overworking char *ftostr51(const float &x); + char *ftostr52(const float &x); char *ftostr31(const float &x); char *ftostr3(const float &x); @@ -142,10 +143,8 @@ #define LCD_MESSAGE(x) #define LCD_MESSAGEPGM(x) FORCE_INLINE void lcd_status() {}; -#endif - -#ifndef ULTIPANEL - #define CLICKED false + + #define CLICKED false #define BLOCK ; #endif @@ -160,4 +159,3 @@ char *itostr3(const int &xx); char *itostr4(const int &xx); char *ftostr51(const float &x); #endif //ULTRALCD - diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 54b7012848..47dc2d5cc9 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -12,7 +12,9 @@ extern volatile bool feedmultiplychanged; extern volatile int extrudemultiply; extern long position[4]; +#ifdef SDSUPPORT extern CardReader card; +#endif //=========================================================================== //=============================public variables============================ @@ -410,7 +412,7 @@ void MainMenu::showStatus() uint8_t percent=card.percentDone(); if(oldpercent!=percent ||force_lcd_update) { - lcd.setCursor(7,2); + lcd.setCursor(10,2); lcd.print(itostr3((int)percent)); lcdprintPGM("%SD"); } @@ -480,7 +482,11 @@ void MainMenu::showPrepare() MENUITEM( lcdprintPGM(MSG_MAIN) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemP_autostart: - MENUITEM( lcdprintPGM(MSG_AUTOSTART) , BLOCK;card.lastnr=0;card.setroot();card.checkautostart(true);beepshort(); ) ; + MENUITEM( lcdprintPGM(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(); ) ; @@ -529,7 +535,7 @@ void MainMenu::showAxisMove() switch(i) { case ItemAM_exit: - MENUITEM( lcdprintPGM(" Prepare \003") , BLOCK;status=Main_Menu;beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_PREPARE_ALT) , BLOCK;status=Main_Menu;beepshort(); ) ; break; case ItemAM_X: { @@ -652,14 +658,14 @@ void MainMenu::showAxisMove() { if (encoderpos >0) { - enquecommand("G1 F170 Z0.1"); + enquecommand("G1 F70 Z0.1"); oldencoderpos=encoderpos; encoderpos=0; } else if (encoderpos < 0) { - enquecommand("G1 F1700 Z-0.1"); + enquecommand("G1 F70 Z-0.1"); oldencoderpos=encoderpos; encoderpos=0; } @@ -805,8 +811,8 @@ void MainMenu::showTune() { if(force_lcd_update) { - lcd.setCursor(0,line);lcdprintPGM(" Fan speed:"); - lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + lcd.setCursor(0,line);lcdprintPGM(MSG_FAN_SPEED); + lcd.setCursor(13,line);lcd.print(ftostr3(FanSpeed)); } if((activeline!=line) ) @@ -817,7 +823,7 @@ void MainMenu::showTune() linechanging=!linechanging; if(linechanging) { - encoderpos=fanpwm; + encoderpos=FanSpeed; } else { @@ -830,8 +836,8 @@ void MainMenu::showTune() { if(encoderpos<0) encoderpos=0; if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); + FanSpeed=encoderpos; + analogWrite(FAN_PIN, FanSpeed); lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); } @@ -1128,7 +1134,7 @@ void MainMenu::showControlTemp() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(MSG_FAN_SPEED); - lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + lcd.setCursor(13,line);lcd.print(ftostr3(FanSpeed)); } if((activeline!=line) ) @@ -1139,7 +1145,7 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=fanpwm; + encoderpos=FanSpeed; } else { @@ -1152,8 +1158,8 @@ void MainMenu::showControlTemp() { if(encoderpos<0) encoderpos=0; if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); + FanSpeed=encoderpos; + analogWrite(FAN_PIN, FanSpeed); lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); } @@ -1629,7 +1635,7 @@ void MainMenu::showControlMotion() if(linechanging) { if(encoderpos<5) encoderpos=5; - if(encoderpos>99999) encoderpos=99999; + if(encoderpos>32000) encoderpos=32000;//TODO: This is a problem, encoderpos is 16bit, but steps_per_unit for e can be wel over 800 lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); } @@ -1890,7 +1896,19 @@ void MainMenu::showSD() // } // }break; case 1: - MENUITEM( lcd.print(" ");card.getWorkDirName();if(card.filename[0]=='/') lcdprintPGM(MSG_REFRESH);else {lcd.print("\005");lcd.print(card.filename);lcd.print("/..");} , BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ; + MENUITEM( lcd.print(" ");card.getWorkDirName(); + if(card.filename[0]=='/') lcdprintPGM(MSG_REFRESH); + else { + lcd.print("\005"); + lcd.print(card.filename); + lcd.print("/.."); + } , + BLOCK; + if(SDCARDDETECT == -1) card.initsd(); + card.updir(); + enforceupdate=true; + lineoffset=0; + beepshort(); ) ; break; default: @@ -1957,7 +1975,7 @@ void MainMenu::showMainMenu() #endif if(tune) { - if(!(movesplanned() ||card.sdprinting)) + if(!(movesplanned() || IS_SD_PRINTING)) { force_lcd_update=true; tune=false; @@ -1965,7 +1983,7 @@ void MainMenu::showMainMenu() } else { - if(movesplanned() ||card.sdprinting) + if(movesplanned() || IS_SD_PRINTING) { force_lcd_update=true; tune=true; From e44ab05e0fe850a148f05f7fbfb6ea7f8f3d95e1 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Sat, 17 Mar 2012 22:52:58 +0000 Subject: [PATCH 210/228] removed temp files --- Marlin/Configuration.h~ | 235 ------ Marlin/Configuration_adv.h~ | 232 ------ Marlin/Marlin.pde~ | 1354 ----------------------------------- Marlin/cardreader.cpp~ | 565 --------------- Marlin/cardreader.h~ | 109 --- Marlin/pins.h~ | 905 ----------------------- Marlin/planner.cpp~ | 808 --------------------- Marlin/thermistortables.h~ | 528 -------------- 8 files changed, 4736 deletions(-) delete mode 100644 Marlin/Configuration.h~ delete mode 100644 Marlin/Configuration_adv.h~ delete mode 100644 Marlin/Marlin.pde~ delete mode 100644 Marlin/cardreader.cpp~ delete mode 100644 Marlin/cardreader.h~ delete mode 100644 Marlin/pins.h~ delete mode 100644 Marlin/planner.cpp~ delete mode 100644 Marlin/thermistortables.h~ diff --git a/Marlin/Configuration.h~ b/Marlin/Configuration.h~ deleted file mode 100644 index 8e380ee358..0000000000 --- a/Marlin/Configuration.h~ +++ /dev/null @@ -1,235 +0,0 @@ -#ifndef __CONFIGURATION_H -#define __CONFIGURATION_H - -// This configurtion file contains the basic settings. -// Advanced settings can be found in Configuration_adv.h -// BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration - -//User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. -//Implementation of an idea by Prof Braino to inform user that any changes made -//to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-03-01-1" //Personal revision number for changes to THIS file. -#define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. - -// This determines the communication speed of the printer -#define BAUDRATE 250000 -//#define BAUDRATE 115200 - -//// The following define selects which electronics board you have. Please choose the one that matches your setup -// Gen7 custom (Alfons3 Version) = 10 "https://github.com/Alfons3/Generation_7_Electronics" -// Gen7 v1.1, v1.2 = 11 -// Gen7 v1.3 = 12 -// Gen7 v1.4 = 13 -// MEGA/RAMPS up to 1.2 = 3 -// RAMPS 1.3 = 33 (Power outputs: Extruder, Bed, Fan) -// RAMPS 1.3 = 34 (Power outputs: Extruder0, Extruder1, Bed) -// Gen6 = 5 -// Gen6 deluxe = 51 -// Sanguinololu 1.2 and above = 62 -// Ultimaker = 7 -// Teensylu = 8 -// Gen3+ =9 -#define MOTHERBOARD 62 - -//=========================================================================== -//=============================Thermal Settings ============================ -//=========================================================================== - -//// Temperature sensor settings: -// -2 is thermocouple with MAX6675 (only for sensor 0) -// -1 is thermocouple with AD595 -// 0 is not used -// 1 is 100k thermistor -// 2 is 200k thermistor -// 3 is mendel-parts thermistor -// 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !! -// 5 is ParCan supplied 104GT-2 100K -// 6 is EPCOS 100k -// 7 is 100k Honeywell thermistor 135-104LAG-J01 -// 100 is 100k GE Sensing AL03006-58.2K-97-G1 -// 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT - -#define TEMP_SENSOR_0 102 -#define TEMP_SENSOR_1 0 -#define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 103 - -// Actual temperature must be close to target for this long before M109 returns success -#define TEMP_RESIDENCY_TIME 10 // (seconds) -#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one - -// The minimal temperature defines the temperature below which the heater will not be enabled It is used -// to check that the wiring to the thermistor is not broken. -// Otherwise this would lead to the heater being powered on all the time. -#define HEATER_0_MINTEMP 1 -//#define HEATER_1_MINTEMP 5 -//#define HEATER_2_MINTEMP 5 -#define BED_MINTEMP 1 - -// When temperature exceeds max temp, your heater will be switched off. -// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! -// You should use MINTEMP for thermistor short/failure protection. -#define HEATER_0_MAXTEMP 399 -//#define HEATER_1_MAXTEMP 275 -//#define HEATER_2_MAXTEMP 275 -#define BED_MAXTEMP 150 - - -// PID settings: -// Comment the following line to disable PID and enable bang-bang. -#define PIDTEMP -#define PID_MAX 255 // limits current to nozzle; 255=full current -#ifdef PIDTEMP - //#define PID_DEBUG // Sends debug data to the serial port. - //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_INTEGRAL_DRIVE_MAX 130 //limit for the integral term - #define K1 0.95 //smoothing factor withing the PID - #define PID_dT 0.122 //sampling period of the PID - -// If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it -// Ultimaker -// #define DEFAULT_Kp 22.2 -// #define DEFAULT_Ki (1.25*PID_dT) -// #define DEFAULT_Kd (99/PID_dT) - -// Makergear -// #define DEFAULT_Kp 7.0 -// #define DEFAULT_Ki 0.1 -// #define DEFAULT_Kd 12 - -// RepRapPro Huxley - #define DEFAULT_Kp 3.0 - #define DEFAULT_Ki (2*PID_dT) - #define DEFAULT_Kd (80/PID_dT) - -// Mendel Parts V9 on 12V -// #define DEFAULT_Kp 63.0 -// #define DEFAULT_Ki (2.25*PID_dT) -// #define DEFAULT_Kd (440/PID_dT) -#endif // PIDTEMP - -//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit -//can be software-disabled for whatever purposes by -#define PREVENT_DANGEROUS_EXTRUDE -#define EXTRUDE_MINTEMP 170 -#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. - -//=========================================================================== -//=============================Mechanical Settings=========================== -//=========================================================================== - -// Endstop Settings -#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors - -// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. -const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. -const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. - -// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 -#define X_ENABLE_ON 0 -#define Y_ENABLE_ON 0 -#define Z_ENABLE_ON 0 -#define E_ENABLE_ON 0 // For all extruders - -// Disables axis when it's not being used. -#define DISABLE_X false -#define DISABLE_Y false -#define DISABLE_Z true -#define DISABLE_E false // For all extruders - -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true -#define INVERT_E0_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E2_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false - -// ENDSTOP SETTINGS: -// Sets direction of endstops when homing; 1=MAX, -1=MIN -#define X_HOME_DIR -1 -#define Y_HOME_DIR -1 -#define Z_HOME_DIR -1 - -#define min_software_endstops true //If true, axis won't move to coordinates less than zero. -#define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 150 -#define Y_MAX_LENGTH 148 -#define Z_MAX_LENGTH 100 - -// The position of the homing switches. Use MAX_LENGTH * -0.5 if the center should be 0, 0, 0 -#define X_HOME_POS 0 -#define Y_HOME_POS 0 -#define Z_HOME_POS 0 - -//// MOVEMENT SETTINGS -#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -#define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) -#define FAST_HOME_FEEDRATE {80*60, 80*60, 3*60, 0} // set the homing speeds (mm/min) - -// default settings - -#define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker -//#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,850} -#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. - -#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for r retracts - -// -#define DEFAULT_XYJERK 20.0 // (mm/sec) -#define DEFAULT_ZJERK 0.4 // (mm/sec) -#define DEFAULT_EJERK 5.0 // (mm/sec) - -//=========================================================================== -//=============================Additional Features=========================== -//=========================================================================== - -// EEPROM -// the microcontroller can store settings in the EEPROM, e.g. max velocity... -// 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. -//define this to enable eeprom support -#define EEPROM_SETTINGS -//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out: -// please keep turned on if you can. -#define EEPROM_CHITCHAT - -//LCD and SD support -//#define ULTRA_LCD //general lcd support, also 16x2 -#define SDSUPPORT // Enable SD Card Support in Hardware Console - -//#define ULTIPANEL -#ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 - #define LCD_HEIGHT 4 - -// Preheat Constants - #define PLA_PREHEAT_HOTEND_TEMP 180 - #define PLA_PREHEAT_HPB_TEMP 70 - #define PLA_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 - - #define ABS_PREHEAT_HOTEND_TEMP 240 - #define ABS_PREHEAT_HPB_TEMP 100 - #define ABS_PREHEAT_FAN_SPEED 255 // Insert Value between 0 and 255 - -#else //no panel but just lcd - #ifdef ULTRA_LCD - #define LCD_WIDTH 16 - #define LCD_HEIGHT 2 - #endif -#endif - -// M240 Triggers a camera by emulating a Canon RC-1 Remote -// Data from: http://www.doc-diy.net/photo/rc-1_hacked/ -// #define PHOTOGRAPH_PIN 23 - -#include "Configuration_adv.h" -#include "thermistortables.h" - -#endif //__CONFIGURATION_H diff --git a/Marlin/Configuration_adv.h~ b/Marlin/Configuration_adv.h~ deleted file mode 100644 index c2cb14951e..0000000000 --- a/Marlin/Configuration_adv.h~ +++ /dev/null @@ -1,232 +0,0 @@ -#ifndef __CONFIGURATION_ADV_H -#define __CONFIGURATION_ADV_H - -//=========================================================================== -//=============================Thermal Settings ============================ -//=========================================================================== - -// Select one of these only to define how the bed temp is read. -// -//#define BED_LIMIT_SWITCHING -#ifdef BED_LIMIT_SWITCHING - #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS -#endif -#define BED_CHECK_INTERVAL 5000 //ms - -//// Heating sanity check: -// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. -// It can be reset with another M104/M109 -//#define WATCHPERIOD 20000 //20 seconds - -// Wait for Cooldown -// This defines if the M109 call should not block if it is cooling down. -// example: From a current temp of 220, you set M109 S200. -// if CooldownNoWait is defined M109 will not wait for the cooldown to finish -#define CooldownNoWait true - -//Do not wait for M109 to finish when printing from SD card -//#define STOP_HEATING_WAIT_WHEN_SD_PRINTING - -#ifdef PIDTEMP - // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. - // if Kc is choosen well, the additional required power due to increased melting should be compensated. - //#define PID_ADD_EXTRUSION_RATE - #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (1) //heatingpower=Kc*(e_speed) - #endif -#endif - - -//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode. -//The maximum buffered steps/sec of the extruder motor are called "se". -//You enter the autotemp mode by a M109 S T F -// the target temperature is set to mintemp+factor*se[steps/sec] and limited by mintemp and maxtemp -// you exit the value by any M109 without F* -// Also, if the temperature is set to a value 0 - #define THERMISTORHEATER_0 TEMP_SENSOR_0 - #define HEATER_0_USES_THERMISTOR -#endif -#if TEMP_SENSOR_1 > 0 - #define THERMISTORHEATER_1 TEMP_SENSOR_1 - #define HEATER_1_USES_THERMISTOR -#endif -#if TEMP_SENSOR_2 > 0 - #define THERMISTORHEATER_2 TEMP_SENSOR_2 - #define HEATER_2_USES_THERMISTOR -#endif -#if TEMP_SENSOR_BED > 0 - #define THERMISTORBED TEMP_SENSOR_BED - #define BED_USES_THERMISTOR -#endif -#if TEMP_SENSOR_0 == -1 - #define HEATER_0_USES_AD595 -#endif -#if TEMP_SENSOR_1 == -1 - #define HEATER_1_USES_AD595 -#endif -#if TEMP_SENSOR_2 == -1 - #define HEATER_2_USES_AD595 -#endif -#if TEMP_SENSOR_BED == -1 - #define BED_USES_AD595 -#endif -#if TEMP_SENSOR_0 == -2 - #define HEATER_0_USES_MAX6675 -#endif -#if TEMP_SENSOR_0 == 0 - #undef HEATER_0_MINTEMP - #undef HEATER_0_MAXTEMP -#endif -#if TEMP_SENSOR_1 == 0 - #undef HEATER_1_MINTEMP - #undef HEATER_1_MAXTEMP -#endif -#if TEMP_SENSOR_2 == 0 - #undef HEATER_2_MINTEMP - #undef HEATER_2_MAXTEMP -#endif -#if TEMP_SENSOR_BED == 0 - #undef BED_MINTEMP - #undef BED_MAXTEMP -#endif - - -#endif //__CONFIGURATION_ADV_H diff --git a/Marlin/Marlin.pde~ b/Marlin/Marlin.pde~ deleted file mode 100644 index a3d091f503..0000000000 --- a/Marlin/Marlin.pde~ +++ /dev/null @@ -1,1354 +0,0 @@ -/* - 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" - -#define VERSION_STRING "1.0.0 RC2" - -// 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 -// G28 - Home all Axis -// G90 - Use Absolute Coordinates -// G91 - Use Relative Coordinates -// G92 - Set current position to cordinates given - -//RepRap M Codes -// 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 - 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 -// M206 - set additional homeing offset -// 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 -// 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) - -//Stepper Movement Variables - -//=========================================================================== -//=============================imported variables============================ -//=========================================================================== - - -//=========================================================================== -//=============================public variables============================= -//=========================================================================== -#ifdef SDSUPPORT -CardReader card; -#endif -float homing_feedrate[] = HOMING_FEEDRATE; -float fast_home_feedrate[] = FAST_HOME_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}; -uint8_t active_extruder = 0; -bool stop_heating_wait=false; - -//=========================================================================== -//=============================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; - -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 uint8_t fanpwm=0; - -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; - - -//=========================================================================== -//=============================ROUTINES============================= -//=========================================================================== - -void get_arc_coordinates(); - -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_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_powerhold(); - MYSERIAL.begin(BAUDRATE); - SERIAL_PROTOCOLLNPGM("start"); - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Marlin: "); - SERIAL_ECHOLNPGM(VERSION_STRING); - #ifdef STRING_VERSION_CONFIG_H - #ifdef STRING_CONFIG_H_AUTHOR - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Configuration.h: "); - SERIAL_ECHOPGM(STRING_VERSION_CONFIG_H); - SERIAL_ECHOPGM(" | Author: "); - SERIAL_ECHOLNPGM(STRING_CONFIG_H_AUTHOR); - #endif - #endif - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Free Memory:"); - SERIAL_ECHO(freeMemory()); - SERIAL_ECHOPGM(" PlannerBufferBytes:"); - 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(); -} - - -void loop() -{ - if(buflen<3) - 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("ok"); - } - else - { - card.closefile(); - SERIAL_PROTOCOLLNPGM("Done saving file."); - } - } - else - { - process_commands(); - } - #else - process_commands(); - #endif //SDSUPPORT - buflen = (buflen-1); - bufindr = (bufindr + 1)%BUFSIZE; - } - //check heater every n milliseconds - manage_heater(); - manage_inactivity(1); - 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 == ':' || 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("Line Number is not Last Line Number+1, Last Line:"); - 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("checksum mismatch, Last Line:"); - SERIAL_ERRORLN(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { - SERIAL_ERROR_START; - SERIAL_ERRORPGM("No Checksum with line number, Last Line:"); - 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("No Line Number with checksum, Last Line:"); - 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: - #ifdef SDSUPPORT - if(card.saving) - break; - #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM("ok"); - 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 == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) - { - if(card.eof()){ - SERIAL_PROTOCOLLNPGM("Done printing file"); - 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 HOMEAXIS(LETTER) \ - if ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))\ - { \ - current_position[LETTER##_AXIS] = 0; \ - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); \ - destination[LETTER##_AXIS] = 1.1 * LETTER##_MAX_LENGTH * LETTER##_HOME_DIR; \ - feedrate = fast_home_feedrate[LETTER##_AXIS]; \ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ - \ - current_position[LETTER##_AXIS] = 0;\ - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);\ - destination[LETTER##_AXIS] = -LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ - \ - destination[LETTER##_AXIS] = 2*LETTER##_HOME_RETRACT_MM * LETTER##_HOME_DIR;\ - feedrate = homing_feedrate[LETTER##_AXIS] ; \ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); \ - \ - current_position[LETTER##_AXIS] = (LETTER##_HOME_DIR == -1) ? LETTER##_HOME_POS : LETTER##_MAX_LENGTH;\ - destination[LETTER##_AXIS] = current_position[LETTER##_AXIS];\ - feedrate = 0.0;\ - st_synchronize();\ - endstops_hit_on_purpose();\ - } - -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 - get_coordinates(); // For X Y Z E F - prepare_move(); - //ClearToSend(); - return; - //break; - case 2: // G2 - CW ARC - get_arc_coordinates(); - prepare_arc_move(true); - return; - case 3: // G3 - CCW ARC - get_arc_coordinates(); - prepare_arc_move(false); - return; - case 4: // G4 dwell - LCD_MESSAGEPGM("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(); - } - break; - case 28: //G28 Home all Axis one at a time - saved_feedrate = feedrate; - saved_feedmultiply = feedmultiply; - feedmultiply = 100; - - 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]))); - #ifdef QUICK_HOME - if( 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.1 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.1 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]; - if(homing_feedrate[Y_AXIS]= 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 - tmp_extruder = active_extruder; - if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHO("M104 Invalid extruder "); - SERIAL_ECHOLN(tmp_extruder); - 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 - tmp_extruder = active_extruder; - if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHO("M105 Invalid extruder "); - SERIAL_ECHOLN(tmp_extruder); - break; - } - } - #if (TEMP_0_PIN > -1) - SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL(degHotend(tmp_extruder)); - #if TEMP_BED_PIN > -1 - SERIAL_PROTOCOLPGM(" B:"); - SERIAL_PROTOCOL(degBed()); - #endif //TEMP_BED_PIN - #else - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("No thermistors - no temp"); - #endif - #ifdef PIDTEMP - SERIAL_PROTOCOLPGM(" @:"); - SERIAL_PROTOCOL(getHeaterPower(tmp_extruder)); - #endif - SERIAL_PROTOCOLLN(""); - return; - break; - case 109: - {// M109 - Wait for extruder heater to reach target. - tmp_extruder = active_extruder; - if(code_seen('T')) { - tmp_extruder = code_value(); - if(tmp_extruder >= EXTRUDERS) { - SERIAL_ECHO_START; - SERIAL_ECHO("M109 Invalid extruder "); - SERIAL_ECHOLN(tmp_extruder); - break; - } - } - LCD_MESSAGEPGM("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('G')) 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( degHotend(tmp_extruder) ); - 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(); - LCD_STATUS; - if(stop_heating_wait) break; - #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 && !isHeatingHotend(tmp_extruder)) || - (residencyStart == -1 && !target_direction && !isCoolingHotend(tmp_extruder)) || - (residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS) ) - { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGEPGM("Heating done."); - starttime=millis(); - previous_millis_cmd = millis(); - } - break; - case 190: // M190 - Wait for bed heater to reach target. - #if TEMP_BED_PIN > -1 - LCD_MESSAGEPGM("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_PROTOCOLLN(degBed()); - codenum = millis(); - } - manage_heater(); - } - LCD_MESSAGEPGM("Bed done."); - previous_millis_cmd = millis(); - #endif - break; - - #if FAN_PIN > -1 - case 106: //M106 Fan On - if (code_seen('S')){ - WRITE(FAN_PIN,HIGH); - fanpwm=constrain(code_value(),0,255); - analogWrite(FAN_PIN, fanpwm); - } - else { - WRITE(FAN_PIN,HIGH); - fanpwm=255; - analogWrite(FAN_PIN, fanpwm); - } - break; - case 107: //M107 Fan Off - WRITE(FAN_PIN,LOW); - analogWrite(FAN_PIN, 0); - break; - #endif //FAN_PIN - - #if (PS_ON_PIN > -1) - case 80: // M80 - ATX Power On - SET_OUTPUT(PS_ON_PIN); //GND - break; - #endif - - case 81: // M81 - ATX Power Off - - #if defined SUICIDE_PIN && SUICIDE_PIN > -1 - st_synchronize(); - suicide(); - #elif (PS_ON_PIN > -1) - SET_INPUT(PS_ON_PIN); //Floating - #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("Partial 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])) - axis_steps_per_unit[i] = code_value(); - } - break; - case 115: // M115 - SerialprintPGM("FIRMWARE_NAME:Marlin; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n"); - 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(" 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 119: // M119 - #if (X_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("x_min:"); - SERIAL_PROTOCOL(((READ(X_MIN_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (X_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("x_max:"); - SERIAL_PROTOCOL(((READ(X_MAX_PIN)^X_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Y_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("y_min:"); - SERIAL_PROTOCOL(((READ(Y_MIN_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Y_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("y_max:"); - SERIAL_PROTOCOL(((READ(Y_MAX_PIN)^Y_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Z_MIN_PIN > -1) - SERIAL_PROTOCOLPGM("z_min:"); - SERIAL_PROTOCOL(((READ(Z_MIN_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - #if (Z_MAX_PIN > -1) - SERIAL_PROTOCOLPGM("z_max:"); - SERIAL_PROTOCOL(((READ(Z_MAX_PIN)^Z_ENDSTOPS_INVERTING)?"H ":"L ")); - #endif - SERIAL_PROTOCOLLN(""); - 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() ; - } - 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; - 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; - if(code_seen('W')) Ki_Max = constrain(code_value(),0,255); - #ifdef PID_ADD_EXTRUSION_RATE - if(code_seen('C')) Kc = code_value(); - #endif - updatePID(); - SERIAL_PROTOCOL("ok p:"); - SERIAL_PROTOCOL(Kp); - SERIAL_PROTOCOL(" i:"); - SERIAL_PROTOCOL(Ki/PID_dT); - SERIAL_PROTOCOL(" d:"); - SERIAL_PROTOCOL(Kd*PID_dT); - SERIAL_PROTOCOL(" w:"); - SERIAL_PROTOCOL(Ki_Max); - #ifdef PID_ADD_EXTRUSION_RATE - SERIAL_PROTOCOL(" c:"); - SERIAL_PROTOCOL(Kc*PID_dT); - #endif - 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: // finish all moves - { - allow_cold_extrudes(true); - } - break; - case 400: // 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; - - } - } - - 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("Invalid extruder"); - } - else { - active_extruder = tmp_extruder; - SERIAL_ECHO_START; - SERIAL_ECHO("Active Extruder: "); - SERIAL_PROTOCOLLN((int)active_extruder); - } - } - - else - { - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Unknown command:\""); - SERIAL_ECHO(cmdbuffer[bufindr]); - SERIAL_ECHOLNPGM("\""); - } - - ClearToSend(); -} - -void FlushSerialRequestResend() -{ - //char cmdbuffer[bufindr][100]="Resend:"; - MYSERIAL.flush(); - SERIAL_PROTOCOLPGM("Resend:"); - SERIAL_PROTOCOLLN(gcode_LastN + 1); - ClearToSend(); -} - -void ClearToSend() -{ - previous_millis_cmd = millis(); - #ifdef SDSUPPORT - if(fromsd[bufindr]) - return; - #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM("ok"); -} - -void get_coordinates() -{ - 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]; - 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; - } -} - -void get_arc_coordinates() -{ - get_coordinates(); - if(code_seen('I')) offset[0] = code_value(); - if(code_seen('J')) offset[1] = code_value(); -} - -void prepare_move() -{ - if (min_software_endstops) { - if (destination[X_AXIS] < 0) destination[X_AXIS] = 0.0; - if (destination[Y_AXIS] < 0) destination[Y_AXIS] = 0.0; - if (destination[Z_AXIS] < 0) destination[Z_AXIS] = 0.0; - } - - if (max_software_endstops) { - if (destination[X_AXIS] > X_MAX_LENGTH) destination[X_AXIS] = X_MAX_LENGTH; - if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH; - if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; - } - - 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]; - } - previous_millis_cmd = millis(); -} - -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(); -} - -void manage_inactivity(byte debug) -{ - 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 ) - { - disable_x(); - disable_y(); - disable_z(); - disable_e0(); - disable_e1(); - disable_e2(); - } - } - #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("Printer halted. kill() called !!"); - LCD_MESSAGEPGM("KILLED. "); - suicide(); - while(1); // Wait for reset -} - - diff --git a/Marlin/cardreader.cpp~ b/Marlin/cardreader.cpp~ deleted file mode 100644 index 6ac5e5fa0b..0000000000 --- a/Marlin/cardreader.cpp~ +++ /dev/null @@ -1,565 +0,0 @@ -#include "Marlin.h" -#include "cardreader.h" -#include "ultralcd.h" -#include "stepper.h" -#include "temperature.h" -#ifdef SDSUPPORT - - - -CardReader::CardReader() -{ - filesize = 0; - sdpos = 0; - sdprinting = false; - cardOK = false; - saving = false; - autostart_atmillis=0; - - autostart_stilltocheck=true; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. - lastnr=0; - //power to SD reader - #if SDPOWER > -1 - SET_OUTPUT(SDPOWER); - WRITE(SDPOWER,HIGH); - #endif //SDPOWER - - autostart_atmillis=millis()+5000; -} - -char *createFilename(char *buffer,const dir_t &p) //buffer>12characters -{ - char *pos=buffer; - for (uint8_t i = 0; i < 11; i++) - { - if (p.name[i] == ' ')continue; - if (i == 8) - { - *pos++='.'; - } - *pos++=p.name[i]; - } - *pos++=0; - return buffer; -} - - -void CardReader::lsDive(const char *prepend,SdFile parent) -{ - dir_t p; - uint8_t cnt=0; - - while (parent.readDir(p) > 0) - { - if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) - { - - char path[13*2]; - char lfilename[13]; - createFilename(lfilename,p); - - path[0]=0; - if(strlen(prepend)==0) //avoid leading / if already in prepend - { - strcat(path,"/"); - } - strcat(path,prepend); - strcat(path,lfilename); - strcat(path,"/"); - - //Serial.print(path); - - SdFile dir; - if(!dir.open(parent,lfilename, O_READ)) - { - if(lsAction==LS_SerialPrint) - { - SERIAL_ECHO_START; - SERIAL_ECHOLN("Cannot open subdir"); - SERIAL_ECHOLN(lfilename); - } - } - lsDive(path,dir); - //close done automatically by destructor of SdFile - - - } - else - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if ( p.name[0] == '.') - { - if ( p.name[1] != '.') - continue; - } - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - filenameIsDir=DIR_IS_SUBDIR(&p); - - if(!filenameIsDir) - { - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - } - //if(cnt++!=nr) continue; - createFilename(filename,p); - if(lsAction==LS_SerialPrint) - { - SERIAL_PROTOCOL(prepend); - SERIAL_PROTOCOLLN(filename); - } - else if(lsAction==LS_Count) - { - nrFiles++; - } - else if(lsAction==LS_GetFilename) - { - if(cnt==nrFiles) - return; - cnt++; - - } - } - } -} - -void CardReader::ls() -{ - lsAction=LS_SerialPrint; - if(lsAction==LS_Count) - nrFiles=0; - - root.rewind(); - lsDive("",root); -} - - -void CardReader::initsd() -{ - cardOK = false; - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)) - { - //if (!card.init(SPI_HALF_SPEED,SDSS)) - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("SD init fail"); - } - else if (!volume.init(&card)) - { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("volume.init failed"); - } - else if (!root.openRoot(&volume)) - { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("openRoot failed"); - } - else - { - cardOK = true; - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM("SD card ok"); - } - curDir=&root; - if(!workDir.openRoot(&volume)) - { - SERIAL_ECHOLNPGM("workDir open failed"); - } -} - -void CardReader::setroot() -{ - curDir=&root; - if(!workDir.openRoot(&volume)) - { - SERIAL_ECHOLNPGM("workDir open failed"); - } -} -void CardReader::release() -{ - sdprinting = false; - cardOK = false; -} - -void CardReader::startFileprint() -{ - if(cardOK) - { - sdprinting = true; - - } -} - -void CardReader::pauseSDPrint() -{ - if(sdprinting) - { - sdprinting = false; - } -} - - - -void CardReader::openFile(char* name,bool read) -{ - if(!cardOK) - return; - file.close(); - sdprinting = false; - - - SdFile myDir; - curDir=&root; - char *fname=name; - - char *dirname_start,*dirname_end; - if(name[0]=='/') - { - dirname_start=strchr(name,'/')+1; - while(dirname_start>0) - { - dirname_end=strchr(dirname_start,'/'); - //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name)); - //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name)); - if(dirname_end>0 && dirname_end>dirname_start) - { - char subdirname[13]; - strncpy(subdirname, dirname_start, dirname_end-dirname_start); - subdirname[dirname_end-dirname_start]=0; - SERIAL_ECHOLN(subdirname); - if(!myDir.open(curDir,subdirname,O_READ)) - { - SERIAL_PROTOCOLPGM("open failed, File: "); - SERIAL_PROTOCOL(subdirname); - SERIAL_PROTOCOLLNPGM("."); - return; - } - else - ;//SERIAL_ECHOLN("dive ok"); - - curDir=&myDir; - dirname_start=dirname_end+1; - } - else // the reminder after all /fsa/fdsa/ is the filename - { - fname=dirname_start; - //SERIAL_ECHOLN("remaider"); - //SERIAL_ECHOLN(fname); - break; - } - - } - } - else //relative path - { - curDir=&workDir; - } - if(read) - { - if (file.open(curDir, fname, O_READ)) - { - filesize = file.fileSize(); - SERIAL_PROTOCOLPGM("File opened:"); - SERIAL_PROTOCOL(fname); - SERIAL_PROTOCOLPGM(" Size:"); - SERIAL_PROTOCOLLN(filesize); - sdpos = 0; - - SERIAL_PROTOCOLLNPGM("File selected"); - LCD_MESSAGE(fname); - } - else - { - SERIAL_PROTOCOLPGM("open failed, File: "); - SERIAL_PROTOCOL(fname); - SERIAL_PROTOCOLLNPGM("."); - } - } - else - { //write - if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) - { - SERIAL_PROTOCOLPGM("open failed, File: "); - SERIAL_PROTOCOL(fname); - SERIAL_PROTOCOLLNPGM("."); - } - else - { - saving = true; - SERIAL_PROTOCOLPGM("Writing to file: "); - SERIAL_PROTOCOLLN(name); - LCD_MESSAGE(fname); - } - } - -} - -void CardReader::getStatus() -{ - if(cardOK){ - SERIAL_PROTOCOLPGM("SD printing byte "); - SERIAL_PROTOCOL(sdpos); - SERIAL_PROTOCOLPGM("/"); - SERIAL_PROTOCOLLN(filesize); - } - else{ - SERIAL_PROTOCOLLNPGM("Not SD printing"); - } -} -void CardReader::write_command(char *buf) -{ - char* begin = buf; - char* npos = 0; - char* end = buf + strlen(buf) - 1; - - file.writeError = false; - if((npos = strchr(buf, 'N')) != NULL) - { - begin = strchr(npos, ' ') + 1; - end = strchr(npos, '*') - 1; - } - end[1] = '\r'; - end[2] = '\n'; - end[3] = '\0'; - file.write(begin); - if (file.writeError) - { - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("error writing to file"); - } -} - - -void CardReader::checkautostart(bool force) -{ - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) - { - for(int8_t i=0;i<(int)strlen((char*)p.name);i++) - p.name[i]=tolower(p.name[i]); - //Serial.print((char*)p.name); - //Serial.print(" "); - //Serial.println(autoname); - if(p.name[9]!='~') //skip safety copies - if(strncmp((char*)p.name,autoname,5)==0) - { - char cmd[30]; - - sprintf(cmd,"M23 %s",autoname); - enquecommand(cmd); - enquecommand("M24"); - found=true; - } - } - if(!found) - lastnr=-1; - else - lastnr++; -} - -void CardReader::closefile() -{ - file.sync(); - file.close(); - saving = false; -} - -void CardReader::getfilename(const uint8_t nr) -{ - curDir=&workDir; - lsAction=LS_GetFilename; - nrFiles=nr; - curDir->rewind(); - lsDive("",*curDir); - -} - -uint16_t CardReader::getnrfilenames() -{ - curDir=&workDir; - lsAction=LS_Count; - nrFiles=0; - curDir->rewind(); - lsDive("",*curDir); - //SERIAL_ECHOLN(nrFiles); - return nrFiles; -} - -void CardReader::chdir(const char * relpath) -{ - SdFile newfile; - SdFile *parent=&root; - - if(workDir.isOpen()) - parent=&workDir; - - if(!newfile.open(*parent,relpath, O_READ)) - { - SERIAL_ECHO_START; - SERIAL_ECHOPGM("Cannot enter subdir:"); - SERIAL_ECHOLN(relpath); - } - else - { - workDirParentParent=workDirParent; - workDirParent=*parent; - - workDir=newfile; - } -} - -void CardReader::updir() -{ - if(!workDir.isRoot()) - { - workDir=workDirParent; - workDirParent=workDirParentParent; - } -} - - -void CardReader::printingHasFinished() -{ - st_synchronize(); - quickStop(); - sdprinting = false; - #ifdef STOP_HEATING_WAIT_FOR_SD_PRINTING - stop_heating_wait=true; - #endif - if(SD_FINISHED_STEPPERRELEASE) - { - //finishAndDisableSteppers(); - enquecommand(SD_FINISHED_RELEASECOMMAND); - } - autotempShutdown(); -} -void CardReader::fast_xfer(char* strchr_pointer) - { - char *pstr; - boolean done = false; - - //force heater pins low - if(HEATER_0_PIN > -1) WRITE(HEATER_0_PIN,LOW); - if(HEATER_BED_PIN > -1) WRITE(HEATER_BED_PIN,LOW); - - lastxferchar = 1; - xferbytes = 0; - - SERIAL_ECHOPGM("strchr_pointer "); - SERIAL_ECHOLN(strchr_pointer); - - pstr = strstr(strchr_pointer, " "); - //pstr = strchr_pointer; - - SERIAL_ECHOPGM("pstr "); - SERIAL_ECHOLN(pstr); - - if(pstr == NULL) - { - SERIAL_ECHOLN("invalid command"); - return; - } - - *pstr = '\0'; - - //check mode (currently only RAW is supported - if(strcmp(strchr_pointer, "RAW") != 0) - { - SERIAL_ECHOPGM("strchr_pointer "); - SERIAL_ECHOLN(strchr_pointer); - SERIAL_ECHOLN("Invalid transfer codec"); - return; - }else{ - SERIAL_ECHOPGM("Selected codec: "); - SERIAL_ECHOLN(strchr_pointer+4); - } - - if (!file.open(&root, pstr+1, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) - { - SERIAL_ECHOPGM("open failed, File: "); - SERIAL_ECHOLN(pstr+1); - SERIAL_ECHOPGM("."); - }else{ - SERIAL_ECHOPGM("Writing to file: "); - SERIAL_ECHOLN(pstr+1); - } - - SERIAL_ECHOLN("ok"); - - //RAW transfer codec - //Host sends \0 then up to SD_FAST_XFER_CHUNK_SIZE then \0 - //when host is done, it sends \0\0. - //if a non \0 character is recieved at the beginning, host has failed somehow, kill the transfer. - - //read SD_FAST_XFER_CHUNK_SIZE bytes (or until \0 is recieved) - while(!done) - { - while(!MYSERIAL.available()) - { - } - if(MYSERIAL.peek() != 0) - { - //host has failed, this isn't a RAW chunk, it's an actual command - file.sync(); - file.close(); - return; - } - //clear the initial 0 - MYSERIAL.read(); - for(int i=0;i=filesize ;}; - FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();}; - FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);}; - FORCE_INLINE uint8_t percentDone(){if(!sdprinting) return 0; if(filesize) return sdpos*100/filesize; else return 0;}; - FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;}; - -public: - bool saving; - bool sdprinting ; - bool cardOK ; - char filename[11]; - bool filenameIsDir; - int lastnr; //last number of the autostart; - char fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE + 1]; - int lastxferchar; - long xferbytes; -private: - SdFile root,*curDir,workDir,workDirParent,workDirParentParent; - Sd2Card card; - SdVolume volume; - SdFile file; - uint32_t filesize; - //int16_t n; - unsigned long autostart_atmillis; - uint32_t sdpos ; - - bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. - - LsAction lsAction; //stored for recursion. - int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. - char* diveDirName; - void lsDive(const char *prepend,SdFile parent); -}; - - -#else - -#define dir_t bool -class CardReader -{ -public: - FORCE_INLINE CardReader(){}; - - FORCE_INLINE static void initsd(){}; - FORCE_INLINE static void write_command(char *buf){}; - - FORCE_INLINE static void checkautostart(bool x) {}; - - FORCE_INLINE static void openFile(char* name,bool read){}; - FORCE_INLINE static void closefile() {}; - FORCE_INLINE static void release(){}; - FORCE_INLINE static void startFileprint(){}; - FORCE_INLINE static void startFilewrite(char *name){}; - FORCE_INLINE static void pauseSDPrint(){}; - FORCE_INLINE static void getStatus(){}; - - FORCE_INLINE static void selectFile(char* name){}; - FORCE_INLINE static void getfilename(const uint8_t nr){}; - FORCE_INLINE static uint8_t getnrfilenames(){return 0;}; - - - FORCE_INLINE static void ls() {}; - FORCE_INLINE static bool eof() {return true;}; - FORCE_INLINE static char get() {return 0;}; - FORCE_INLINE static void setIndex(){}; - FORCE_INLINE uint8_t percentDone(){return 0;}; - - FORCE_INLINE static void fast_xfer(char* strchr_pointer) {}; -}; -#endif //SDSUPPORT -#endif diff --git a/Marlin/pins.h~ b/Marlin/pins.h~ deleted file mode 100644 index 0b0cba3371..0000000000 --- a/Marlin/pins.h~ +++ /dev/null @@ -1,905 +0,0 @@ -#ifndef PINS_H -#define PINS_H - -#if MOTHERBOARD == 99 -#define KNOWN_BOARD 1 - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN -1 -#define X_MAX_PIN 16 - -#define Y_STEP_PIN 5 -#define Y_DIR_PIN 6 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 67 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 62 -#define Z_DIR_PIN 63 -#define Z_ENABLE_PIN -1 -#define Z_MIN_PIN 59 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 65 -#define E0_DIR_PIN 66 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 9 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 10 - -#endif /* 99 */ - -/**************************************************************************************** -* Arduino pin assignment -* -* ATMega168 -* +-\/-+ -* PC6 1| |28 PC5 (AI 5 / D19) -* (D 0) PD0 2| |27 PC4 (AI 4 / D18) -* (D 1) PD1 3| |26 PC3 (AI 3 / D17) -* (D 2) PD2 4| |25 PC2 (AI 2 / D16) -* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) -* (D 4) PD4 6| |23 PC0 (AI 0 / D14) -* VCC 7| |22 GND -* GND 8| |21 AREF -* PB6 9| |20 AVCC -* PB7 10| |19 PB5 (D 13) -* PWM+ (D 5) PD5 11| |18 PB4 (D 12) -* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -* (D 7) PD7 13| |16 PB2 (D 10) PWM -* (D 8) PB0 14| |15 PB1 (D 9) PWM -* +----+ -****************************************************************************************/ -#if MOTHERBOARD == 0 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega168__ -#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. -#endif - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 4 -#define X_MAX_PIN 9 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN 13 - -#define Z_STEP_PIN 19 -#define Z_DIR_PIN 18 -#define Z_ENABLE_PIN 5 -#define Z_MIN_PIN 17 -#define Z_MAX_PIN 16 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 15 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -#endif - - - -/**************************************************************************************** -* Sanguino/RepRap Motherboard with direct-drive extruders -* -* ATMega644P -* -* +---\/---+ -* (D 0) PB0 1| |40 PA0 (AI 0 / D31) -* (D 1) PB1 2| |39 PA1 (AI 1 / D30) -* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) -* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) -* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) -* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) -* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) -* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) -* RST 9| |32 AREF -* VCC 10| |31 GND -* GND 11| |30 AVCC -* XTAL2 12| |29 PC7 (D 23) -* XTAL1 13| |28 PC6 (D 22) -* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI -* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO -* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS -* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK -* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA -* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL -* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM -* +--------+ -* -****************************************************************************************/ -#if MOTHERBOARD == 1 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 19 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PIN 29 -#define Z_DIR_PIN 30 -#define Z_ENABLE_PIN 31 -#define Z_MIN_PIN 2 -#define Z_MAX_PIN 1 - -#define E0_STEP_PIN 12 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN 3 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN 0 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 14 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ - - - -#endif - - -/**************************************************************************************** -* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* -* -****************************************************************************************/ -#if MOTHERBOARD == 2 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PINN 27 -#define Z_DIR_PINN 28 -#define Z_ENABLE_PIN 29 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 31 - -#define E0_STEP_PIN 17 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 4 -#define LED_PIN 0 - -#define SD_CARD_WRITE 2 -#define SD_CARD_DETECT 3 -#define SD_CARD_SELECT 4 - -//our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 - -//pin for controlling the PSU. -#define PS_ON_PIN 14 - -#define FAN_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN -1 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#endif - -/**************************************************************************************** -* Arduino Mega pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 33 -#define MOTHERBOARD 3 -#define RAMPS_V_1_3 -#endif -#if MOTHERBOARD == 3 -#define KNOWN_BOARD 1 - -//////////////////FIX THIS////////////// -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 -// #define RAMPS_V_1_3 -// #define RAMPS_V_1_0 - -#ifdef RAMPS_V_1_3 - -#define X_STEP_PIN 54 -#define X_DIR_PIN 55 -#define X_ENABLE_PIN 38 -#define X_MIN_PIN 3 -#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. - -#define Y_STEP_PIN 60 -#define Y_DIR_PIN 61 -#define Y_ENABLE_PIN 56 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN 15 //15 - -#define Z_STEP_PIN 46 -#define Z_DIR_PIN 48 -#define Z_ENABLE_PIN 62 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN 19 //19 - -#define E0_STEP_PIN 26 -#define E0_DIR_PIN 28 -#define E0_ENABLE_PIN 24 - -#define E1_STEP_PIN 36 -#define E1_DIR_PIN 34 -#define E1_ENABLE_PIN 30 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 4 -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#define HEATER_0_PIN 10 // EXTRUDER 1 -#define HEATER_1_PIN 9 // EXTRUDER 2 -#define HEATER_2_PIN -1 // EXTRUDER 2 -#define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 15 // ANALOG NUMBERING -#define TEMP_2_PIN -1 // ANALOG NUMBERING -#define HEATER_BED_PIN 8 // BED -#define TEMP_BED_PIN 14 // ANALOG NUMBERING - - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default - -#define X_STEP_PIN 26 -#define X_DIR_PIN 28 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 - -#define Y_STEP_PIN 38 -#define Y_DIR_PIN 40 -#define Y_ENABLE_PIN 36 -#define Y_MIN_PIN 16 -#define Y_MAX_PIN -1 //17 - -#define Z_STEP_PIN 44 -#define Z_DIR_PIN 46 -#define Z_ENABLE_PIN 42 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E0_STEP_PIN 32 -#define E0_DIR_PIN 34 -#define E0_ENABLE_PIN 30 - -#define SDPOWER 48 -#define SDSS 53 -#define LED_PIN 13 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - - - -#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 - #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_BED_PIN -1 // RAMPS 1.0 - #define FAN_PIN 11 // RAMPS 1.0 -#else // RAMPS_V_1_1 or RAMPS_V_1_2 - #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_BED_PIN 8 // RAMPS 1.1 - #define FAN_PIN 9 // RAMPS 1.1 -#endif -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#endif - -// SPI for Max6675 Thermocouple - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define MAX_SCK_PIN 52 - #define MAX_MISO_PIN 50 - #define MAX_MOSI_PIN 51 - #define MAX6675_SS 53 -#else - #define MAX6675_SS 49 -#endif - -#endif - -/**************************************************************************************** -* Duemilanove w/ ATMega328P pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 4 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega328P__ -#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 17 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 13 -#define Z_DIR_PIN 3 -#define Z_ENABLE_PIN 2 -#define Z_MIN_PIN 4 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN 5 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#endif - -/**************************************************************************************** -* Gen6 pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 5 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ - #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -//x axis pins - #define X_STEP_PIN 15 - #define X_DIR_PIN 18 - #define X_ENABLE_PIN 19 - #define X_MIN_PIN 20 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 25 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 27 - #define Z_DIR_PIN 28 - #define Z_ENABLE_PIN 29 - #define Z_MIN_PIN 30 - #define Z_MAX_PIN -1 - - //extruder pins - #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 - #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 - #define HEATER_2_PIN -1 - #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 - - #define SDPOWER -1 - #define SDSS 17 - #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define FAN_PIN -1 //changed @ rkoeppl 20110410 - #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 - //our pin for debugging. - - #define DEBUG_PIN 0 - - //our RS485 pins - #define TX_ENABLE_PIN 12 - #define RX_ENABLE_PIN 13 - - -#endif - -/**************************************************************************************** -* Sanguinololu pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 62 -#define MOTHERBOARD 6 -#define SANGUINOLOLU_V_1_2 -#endif -#if MOTHERBOARD == 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#ifndef __AVR_ATmega1284P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 21 -#define X_MIN_PIN 18 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 22 -#define Y_DIR_PIN 23 -#define Y_MIN_PIN 19 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 3 -#define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 1 -#define E0_DIR_PIN 0 - -#define LED_PIN -1 - -#define FAN_PIN -1 //12 - -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 // (extruder) -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - -#ifdef SANGUINOLOLU_V_1_2 - -#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET -#define X_ENABLE_PIN 14 -#define Y_ENABLE_PIN 14 -#define Z_ENABLE_PIN 26 -#define E0_ENABLE_PIN 14 - -#else - -#define HEATER_BED_PIN 14 // (bed) -#define X_ENABLE_PIN -1 -#define Y_ENABLE_PIN -1 -#define Z_ENABLE_PIN -1 -#define E0_ENABLE_PIN -1 - -#endif - -#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define SDPOWER -1 -#define SDSS 31 - -#endif - - -#if MOTHERBOARD == 7 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 22 -#define X_MAX_PIN 24 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 26 -#define Y_MAX_PIN 28 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 32 -#define Z_ENABLE_PIN 35 - -#define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 10 - -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define HEATER_1_PIN 3 -#define TEMP_1_PIN 9 - -#define HEATER_2_PIN -1 -#define TEMP_2_PIN -1 - -#define E0_STEP_PIN 43 -#define E0_DIR_PIN 45 -#define E0_ENABLE_PIN 41 - -#define E1_STEP_PIN 49 -#define E1_DIR_PIN 47 -#define E1_ENABLE_PIN 51 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 7 -#define PS_ON_PIN 12 -#define KILL_PIN -1 -#define SUICIDE_PIN 54 //PIN that has to be turned on right after start, to keep power flowing. - -#ifdef ULTRA_LCD - - #ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - #else //old style panel with shift register - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - //buttons are attached to a shift register - #define SHIFT_CLK 38 - #define SHIFT_LD 42 - #define SHIFT_OUT 40 - #define SHIFT_EN 17 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 5 - #define LCD_PINS_D4 6 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 20 - #define LCD_PINS_D7 19 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - - //bits in the shift register that carry the buttons for: - // left up center down right red - #define BL_LE 7 - #define BL_UP 6 - #define BL_MI 5 - #define BL_DW 4 - #define BL_RI 3 - #define BL_ST 2 - - #define BLEN_B 1 - #define BLEN_A 0 - #endif -#endif //ULTRA_LCD - -#endif - -#if MOTHERBOARD == 71 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment (Old electronics) -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 15 -#define X_MAX_PIN 14 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 17 -#define Y_MAX_PIN 16 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 19 -#define Z_MAX_PIN 18 -#define Z_ENABLE_PIN 35 - -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define HEATER_1_PIN 1 -#define TEMP_1_PIN 1 - -#define HEATER_2_PIN -1 -#define TEMP_2_PIN -1 - -#define E0_STEP_PIN 43 -#define E0_DIR_PIN 45 -#define E0_ENABLE_PIN 41 - -#define E1_STEP_PIN -1 -#define E1_DIR_PIN -1 -#define E1_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define SUICIDE_PIN -1 //PIN that has to be turned on right after start, to keep power flowing. - -#define LCD_PINS_RS 24 -#define LCD_PINS_ENABLE 22 -#define LCD_PINS_D4 36 -#define LCD_PINS_D5 34 -#define LCD_PINS_D6 32 -#define LCD_PINS_D7 30 - -#endif - -/**************************************************************************************** -* Teensylu 0.7 pin assingments (ATMEGA90USB) -* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! -****************************************************************************************/ -#if MOTHERBOARD == 8 -#define MOTHERBOARD 8 -#define KNOWN_BOARD 1 - - -#define X_STEP_PIN 0 -#define X_DIR_PIN 1 -#define X_ENABLE_PIN 39 -#define X_MIN_PIN 13 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 2 -#define Y_DIR_PIN 3 -#define Y_ENABLE_PIN 38 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 4 -#define Z_DIR_PIN 5 -#define Z_ENABLE_PIN 23 -#define Z_MIN_PIN 15 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 6 -#define E0_DIR_PIN 7 -#define E0_ENABLE_PIN 19 - - - -#define HEATER_0_PIN 21 // Extruder -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define HEATER_BED_PIN 20 // Bed -#define FAN_PIN 22 // Fan - -#define TEMP_0_PIN 7 // Extruder -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // Bed - -#define SDPOWER -1 -#define SDSS 8 -#define LED_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define ALARM_PIN -1 - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define SCK_PIN 9 - #define MISO_PIN 11 - #define MOSI_PIN 10 -#endif -#endif - -/**************************************************************************************** -* Gen3+ pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 9 -#define MOTHERBOARD 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_MIN_PIN 20 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 27 -#define Z_DIR_PIN 28 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 17 -#define E_DIR_PIN 21 - -#define LED_PIN -1 - -#define FAN_PIN -1 - -#define PS_ON_PIN 14 -#define KILL_PIN -1 - -#define HEATER_0_PIN 12 // (extruder) - -#define HEATER_1_PIN 16 // (bed) -#define X_ENABLE_PIN 19 -#define Y_ENABLE_PIN 24 -#define Z_ENABLE_PIN 29 -#define E_ENABLE_PIN 13 - -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN 5 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define TEMP_2_PIN -1 -#define SDPOWER -1 -#define SDSS 4 -#define HEATER_2_PIN -1 - -#endif - - - - -#ifndef KNOWN_BOARD -#error Unknown MOTHERBOARD value in configuration.h -#endif - -//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN -#if EXTRUDERS == 3 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN -#elif EXTRUDERS == 2 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS -1 -#elif EXTRUDERS == 1 - #define _E1_PINS -1 - #define _E2_PINS -1 -#else - #error Unsupported number of extruders -#endif -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ - HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ - HEATER_BED_PIN, FAN_PIN, \ - _E0_PINS, _E1_PINS, _E2_PINS, \ - TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } -#endif diff --git a/Marlin/planner.cpp~ b/Marlin/planner.cpp~ deleted file mode 100644 index 0215c0cfd9..0000000000 --- a/Marlin/planner.cpp~ +++ /dev/null @@ -1,808 +0,0 @@ -/* - planner.c - buffers movement commands and manages the acceleration profile plan - Part of Grbl - - Copyright (c) 2009-2011 Simen Svale Skogsrud - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */ - -/* - Reasoning behind the mathematics in this module (in the key of 'Mathematica'): - - s == speed, a == acceleration, t == time, d == distance - - Basic definitions: - - Speed[s_, a_, t_] := s + (a*t) - Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t] - - Distance to reach a specific speed with a constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t] - d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance() - - Speed after a given distance of travel with constant acceleration: - - Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t] - m -> Sqrt[2 a d + s^2] - - DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2] - - When to start braking (di) to reach a specified destionation speed (s2) after accelerating - from initial speed s1 without ever stopping at a plateau: - - Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di] - di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance() - - IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) -*/ - - - - -#include "Marlin.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" -#include "ultralcd.h" - -//=========================================================================== -//=============================public variables ============================ -//=========================================================================== - -unsigned long minsegmenttime; -float max_feedrate[4]; // set the max speeds -float axis_steps_per_unit[4]; -unsigned long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -float minimumfeedrate; -float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -float max_z_jerk; -float mintravelfeedrate; -unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - -// The current position of the tool in absolute steps -long position[4]; //rescaled from extern when axis_steps_per_unit are changed by gcode -static float previous_speed[4]; // Speed of previous path line segment -static float previous_nominal_speed; // Nominal speed of previous path line segment - -extern volatile int extrudemultiply; // Sets extrude multiply factor (in percent) - -#ifdef AUTOTEMP - float autotemp_max=250; - float autotemp_min=210; - float autotemp_factor=0.1; - bool autotemp_enabled=false; -#endif - -//=========================================================================== -//=================semi-private variables, used in inline functions ===== -//=========================================================================== -block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions -volatile unsigned char block_buffer_head; // Index of the next block to be pushed -volatile unsigned char block_buffer_tail; // Index of the block to process now - -//=========================================================================== -//=============================private variables ============================ -//=========================================================================== -#ifdef PREVENT_DANGEROUS_EXTRUDE - bool allow_cold_extrude=false; -#endif -#ifdef XY_FREQUENCY_LIMIT - // Used for the frequency limit - static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations - static long x_segment_time[3]={0,0,0}; // Segment times (in us). Used for speed calculations - static long y_segment_time[3]={0,0,0}; -#endif - -// Returns the index of the next block in the ring buffer -// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. -static int8_t next_block_index(int8_t block_index) { - block_index++; - if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; } - return(block_index); -} - - -// Returns the index of the previous block in the ring buffer -static int8_t prev_block_index(int8_t block_index) { - if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; } - block_index--; - return(block_index); -} - -//=========================================================================== -//=============================functions ============================ -//=========================================================================== - -// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the -// given acceleration: -FORCE_INLINE float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) -{ - if (acceleration!=0) { - return((target_rate*target_rate-initial_rate*initial_rate)/ - (2.0*acceleration)); - } - else { - return 0.0; // acceleration was 0, set acceleration distance to 0 - } -} - -// This function gives you the point at which you must start braking (at the rate of -acceleration) if -// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after -// a total travel of distance. This can be used to compute the intersection point between acceleration and -// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) - -FORCE_INLINE float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) -{ - if (acceleration!=0) { - return((2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/ - (4.0*acceleration) ); - } - else { - return 0.0; // acceleration was 0, set intersection distance to 0 - } -} - -// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. - -void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) { - unsigned long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) - unsigned long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) - - // Limit minimal step rate (Otherwise the timer will overflow.) - if(initial_rate <120) {initial_rate=120; } - if(final_rate < 120) {final_rate=120; } - - long acceleration = block->acceleration_st; - int32_t accelerate_steps = - ceil(estimate_acceleration_distance(block->initial_rate, block->nominal_rate, acceleration)); - int32_t decelerate_steps = - floor(estimate_acceleration_distance(block->nominal_rate, block->final_rate, -acceleration)); - - // Calculate the size of Plateau of Nominal Rate. - int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps; - - // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will - // 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 = max(accelerate_steps,0); // Check limits due to numerical round-off - accelerate_steps = min(accelerate_steps,block->step_event_count); - plateau_steps = 0; - } - - #ifdef ADVANCE - volatile long initial_advance = block->advance*entry_factor*entry_factor; - volatile long final_advance = block->advance*exit_factor*exit_factor; - #endif // ADVANCE - - // block->accelerate_until = accelerate_steps; - // block->decelerate_after = accelerate_steps+plateau_steps; - CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section - if(block->busy == false) { // Don't update variables if block is busy. - block->accelerate_until = accelerate_steps; - block->decelerate_after = accelerate_steps+plateau_steps; - block->initial_rate = initial_rate; - block->final_rate = final_rate; - #ifdef ADVANCE - block->initial_advance = initial_advance; - block->final_advance = final_advance; - #endif //ADVANCE - } - CRITICAL_SECTION_END; -} - -// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the -// acceleration within the allotted distance. -FORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) { - return sqrt(target_velocity*target_velocity-2*acceleration*distance); -} - -// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks. -// This method will calculate the junction jerk as the euclidean distance between the nominal -// velocities of the respective blocks. -//inline float junction_jerk(block_t *before, block_t *after) { -// return sqrt( -// pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2)); -//} - - -// The kernel called by planner_recalculate() when scanning the plan from last to first entry. -void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!current) { return; } - - if (next) { - // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising. - // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and - // check for maximum allowable speed reductions to ensure maximum possible planned speed. - if (current->entry_speed != current->max_entry_speed) { - - // If nominal length true, max junction speed is guaranteed to be reached. Only compute - // for max allowable speed if block is decelerating and nominal length is false. - if ((!current->nominal_length_flag) && (current->max_entry_speed > next->entry_speed)) { - current->entry_speed = min( current->max_entry_speed, - max_allowable_speed(-current->acceleration,next->entry_speed,current->millimeters)); - } else { - current->entry_speed = current->max_entry_speed; - } - current->recalculate_flag = true; - - } - } // Skip last block. Already initialized and set for recalculation. -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the reverse pass. -void planner_reverse_pass() { - uint8_t block_index = block_buffer_head; - if(((block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) { - block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1); - block_t *block[3] = { NULL, NULL, NULL }; - while(block_index != block_buffer_tail) { - block_index = prev_block_index(block_index); - block[2]= block[1]; - block[1]= block[0]; - block[0] = &block_buffer[block_index]; - planner_reverse_pass_kernel(block[0], block[1], block[2]); - } - } -} - -// The kernel called by planner_recalculate() when scanning the plan from first to last entry. -void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { - if(!previous) { return; } - - // If the previous block is an acceleration block, but it is not long enough to complete the - // full speed change within the block, we need to adjust the entry speed accordingly. Entry - // speeds have already been reset, maximized, and reverse planned by reverse planner. - // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck. - if (!previous->nominal_length_flag) { - if (previous->entry_speed < current->entry_speed) { - double entry_speed = min( current->entry_speed, - max_allowable_speed(-previous->acceleration,previous->entry_speed,previous->millimeters) ); - - // Check for junction speed change - if (current->entry_speed != entry_speed) { - current->entry_speed = entry_speed; - current->recalculate_flag = true; - } - } - } -} - -// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This -// implements the forward pass. -void planner_forward_pass() { - uint8_t block_index = block_buffer_tail; - block_t *block[3] = { NULL, NULL, NULL }; - - while(block_index != block_buffer_head) { - block[0] = block[1]; - block[1] = block[2]; - block[2] = &block_buffer[block_index]; - planner_forward_pass_kernel(block[0],block[1],block[2]); - block_index = next_block_index(block_index); - } - planner_forward_pass_kernel(block[1], block[2], NULL); -} - -// Recalculates the trapezoid speed profiles for all blocks in the plan according to the -// entry_factor for each junction. Must be called by planner_recalculate() after -// updating the blocks. -void planner_recalculate_trapezoids() { - int8_t block_index = block_buffer_tail; - block_t *current; - block_t *next = NULL; - - while(block_index != block_buffer_head) { - current = next; - next = &block_buffer[block_index]; - if (current) { - // Recalculate if current block entry or exit junction speed has changed. - if (current->recalculate_flag || next->recalculate_flag) { - // NOTE: Entry and exit factors always > 0 by all previous logic operations. - calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed, - next->entry_speed/current->nominal_speed); - current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed - } - } - block_index = next_block_index( block_index ); - } - // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated. - if(next != NULL) { - calculate_trapezoid_for_block(next, next->entry_speed/next->nominal_speed, - MINIMUM_PLANNER_SPEED/next->nominal_speed); - next->recalculate_flag = false; - } -} - -// Recalculates the motion plan according to the following algorithm: -// -// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor) -// so that: -// a. The junction jerk is within the set limit -// b. No speed reduction within one block requires faster deceleration than the one, true constant -// acceleration. -// 2. Go over every block in chronological order and dial down junction speed reduction values if -// a. The speed increase within one block would require faster accelleration than the one, true -// constant acceleration. -// -// When these stages are complete all blocks have an entry_factor that will allow all speed changes to -// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than -// the set limit. Finally it will: -// -// 3. Recalculate trapezoids for all blocks. - -void planner_recalculate() { - planner_reverse_pass(); - planner_forward_pass(); - planner_recalculate_trapezoids(); -} - -void plan_init() { - block_buffer_head = 0; - block_buffer_tail = 0; - memset(position, 0, sizeof(position)); // clear position - previous_speed[0] = 0.0; - previous_speed[1] = 0.0; - previous_speed[2] = 0.0; - previous_speed[3] = 0.0; - previous_nominal_speed = 0.0; -} - - - - -#ifdef AUTOTEMP -void getHighESpeed() -{ - static float oldt=0; - if(!autotemp_enabled) - return; - if(degTargetHotend0()+2high) - { - high=se; - } - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - - float g=autotemp_min+high*autotemp_factor; - float t=g; - if(tautotemp_max) - t=autotemp_max; - if(oldt>t) - { - t=AUTOTEMP_OLDWEIGHT*oldt+(1-AUTOTEMP_OLDWEIGHT)*t; - } - oldt=t; - setTargetHotend0(t); -// SERIAL_ECHO_START; -// SERIAL_ECHOPAIR("highe",high); -// SERIAL_ECHOPAIR(" t",t); -// SERIAL_ECHOLN(""); -} -#endif - -void check_axes_activity() { - unsigned char x_active = 0; - unsigned char y_active = 0; - unsigned char z_active = 0; - unsigned char e_active = 0; - block_t *block; - - if(block_buffer_tail != block_buffer_head) { - uint8_t block_index = block_buffer_tail; - while(block_index != block_buffer_head) { - block = &block_buffer[block_index]; - if(block->steps_x != 0) x_active++; - if(block->steps_y != 0) y_active++; - if(block->steps_z != 0) z_active++; - if(block->steps_e != 0) e_active++; - block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); - } - } - if((DISABLE_X) && (x_active == 0)) disable_x(); - if((DISABLE_Y) && (y_active == 0)) disable_y(); - if((DISABLE_Z) && (z_active == 0)) disable_z(); - if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } -} - - -float junction_deviation = 0.1; -// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in -// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration -// calculation the caller must also provide the physical length of the line in millimeters. -void plan_buffer_line(float &x, float &y, float &z, float &e, float feed_rate, uint8_t &extruder) -{ - // Calculate the buffer head after we push this byte - int next_buffer_head = next_block_index(block_buffer_head); - - - // If the buffer is full: good! That means we are well ahead of the robot. - // Rest here until there is room in the buffer. - while(block_buffer_tail == next_buffer_head) { - manage_heater(); - manage_inactivity(1); - LCD_STATUS; - } - - // The target position of the tool in absolute steps - // Calculate target position in absolute steps - //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow - long target[4]; - target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - - #ifdef PREVENT_DANGEROUS_EXTRUDE - if(target[E_AXIS]!=position[E_AXIS]) - if(degHotend(active_extruder)axis_steps_per_unit[E_AXIS]*EXTRUDE_MAXLENGTH) - { - position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part - SERIAL_ECHO_START; - SERIAL_ECHOLNPGM(" too long extrusion prevented"); - } - #endif - - // Prepare to set up new block - block_t *block = &block_buffer[block_buffer_head]; - - // Mark block as not busy (Not executed by the stepper interrupt) - block->busy = false; - - // Number of steps for each axis - block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); - block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); - block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); - block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); - block->steps_e *= extrudemultiply; - block->steps_e /= 100; - block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); - - // Bail if this is a zero-length block - if (block->step_event_count <=dropsegments) { return; }; - - // Compute direction bits for this block - block->direction_bits = 0; - if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<direction_bits |= (1<active_extruder = extruder; - - //enable active axes - if(block->steps_x != 0) enable_x(); - if(block->steps_y != 0) enable_y(); - #ifndef Z_LATE_ENABLE - if(block->steps_z != 0) enable_z(); - #endif - - // Enable all - if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } - - - // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill - int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); - #ifdef SLOWDOWN - if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); - #endif - - float delta_mm[4]; - delta_mm[X_AXIS] = block->steps_x/axis_steps_per_unit[X_AXIS]; - delta_mm[Y_AXIS] = block->steps_y/axis_steps_per_unit[Y_AXIS]; - delta_mm[Z_AXIS] = block->steps_z/axis_steps_per_unit[Z_AXIS]; - delta_mm[E_AXIS] = block->steps_e/axis_steps_per_unit[E_AXIS]; -// if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { -// block->millimeters = abs(delta_mm[E_AXIS]); -// } else { -// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); -// } - block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + - square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); - float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides - - // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. - float inverse_second = feed_rate * inverse_millimeters; - - block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 - block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 - - if (block->steps_e == 0) { - if(feed_rate0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { - if (segment_time max_feedrate[i]) - speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); - } - -// Max segement time in us. -#ifdef XY_FREQUENCY_LIMIT -#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT) - - // Check and limit the xy direction change frequency - unsigned char direction_change = block->direction_bits ^ old_direction_bits; - old_direction_bits = block->direction_bits; - - if((direction_change & (1< max_feedrate[i]) - speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); - /* - if(speed_factor < 0.1) { - Serial.print("speed factor : "); Serial.println(speed_factor); - Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); - } - */ - } - for(unsigned char i=0; i < 4; i++) { - current_speed[i] *= speed_factor; - } - block->nominal_speed *= speed_factor; - block->nominal_rate *= speed_factor; - } - - // Compute and limit the acceleration rate for the trapezoid generator. - float steps_per_mm = block->step_event_count/block->millimeters; - if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0) { - block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 - } - else { - block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 - // Limit acceleration per axis - if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; - if(((float)block->acceleration_st * (float)block->steps_y / (float)block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; - if(((float)block->acceleration_st * (float)block->steps_e / (float)block->step_event_count) > axis_steps_per_sqr_second[E_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; - if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS]) - block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; - } - block->acceleration = block->acceleration_st / steps_per_mm; - block->acceleration_rate = (long)((float)block->acceleration_st * 8.388608); - -#if 0 // Use old jerk for now - // Compute path unit vector - double unit_vec[3]; - - unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; - unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; - unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; - - // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. - // Let a circle be tangent to both previous and current path line segments, where the junction - // deviation is defined as the distance from the junction to the closest edge of the circle, - // colinear with the circle center. The circular segment joining the two paths represents the - // path of centripetal acceleration. Solve for max velocity based on max acceleration about the - // radius of the circle, defined indirectly by junction deviation. This may be also viewed as - // path width or max_jerk in the previous grbl version. This approach does not actually deviate - // from path, but used as a robust way to compute cornering speeds, as it takes into account the - // nonlinearities of both the junction angle and junction velocity. - double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed - - // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles. - if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { - // Compute cosine of angle between previous and current path. (prev_unit_vec is negative) - // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity. - double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] - - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] - - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; - - // Skip and use default max junction speed for 0 degree acute junction. - if (cos_theta < 0.95) { - vmax_junction = min(previous_nominal_speed,block->nominal_speed); - // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds. - if (cos_theta > -0.95) { - // Compute maximum junction velocity based on maximum acceleration and junction deviation - double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. - vmax_junction = min(vmax_junction, - sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); - } - } - } -#endif - // Start with a safe speed - float vmax_junction = max_xy_jerk/2; - if(abs(current_speed[Z_AXIS]) > max_z_jerk/2) - vmax_junction = max_z_jerk/2; - vmax_junction = min(vmax_junction, block->nominal_speed); - - if ((moves_queued > 1) && (previous_nominal_speed > 0.0)) { - float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); - if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { - vmax_junction = block->nominal_speed; - } - if (jerk > max_xy_jerk) { - vmax_junction *= (max_xy_jerk/jerk); - } - if(abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { - vmax_junction *= (max_z_jerk/abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); - } - } - block->max_entry_speed = vmax_junction; - - // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. - double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); - block->entry_speed = min(vmax_junction, v_allowable); - - // Initialize planner efficiency flags - // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. - // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then - // the current block and next block junction speeds are guaranteed to always be at their maximum - // junction speeds in deceleration and acceleration, respectively. This is due to how the current - // block nominal speed limits both the current and next maximum junction speeds. Hence, in both - // the reverse and forward planners, the corresponding block junction speed will always be at the - // the maximum junction speed and may always be ignored for any speed reduction checks. - if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } - else { block->nominal_length_flag = false; } - block->recalculate_flag = true; // Always calculate trapezoid for new block - - // Update previous path unit_vector and nominal speed - memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[] - previous_nominal_speed = block->nominal_speed; - - #ifdef ADVANCE - // Calculate advance rate - if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) { - block->advance_rate = 0; - block->advance = 0; - } - else { - long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st); - float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * - (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUTION_AREA * EXTRUTION_AREA)*256; - block->advance = advance; - if(acc_dist == 0) { - block->advance_rate = 0; - } - else { - block->advance_rate = advance / (float)acc_dist; - } - } - /* - SERIAL_ECHO_START; - SERIAL_ECHOPGM("advance :"); - SERIAL_ECHO(block->advance/256.0); - SERIAL_ECHOPGM("advance rate :"); - SERIAL_ECHOLN(block->advance_rate/256.0); - */ - #endif // ADVANCE - - - - - calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, - MINIMUM_PLANNER_SPEED/block->nominal_speed); - - // Move buffer head - block_buffer_head = next_buffer_head; - - // Update position - memcpy(position, target, sizeof(target)); // position[] = target[] - - planner_recalculate(); - #ifdef AUTOTEMP - getHighESpeed(); - #endif - st_wake_up(); -} - -void plan_set_position(const float &x, const float &y, const float &z, const float &e) -{ - position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]); - previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest. - previous_speed[0] = 0.0; - previous_speed[1] = 0.0; - previous_speed[2] = 0.0; - previous_speed[3] = 0.0; -} - -void plan_set_e_position(const float &e) -{ - position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); - st_set_e_position(position[E_AXIS]); -} - -uint8_t movesplanned() -{ - return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); -} - -void allow_cold_extrudes(bool allow) -{ - #ifdef PREVENT_DANGEROUS_EXTRUDE - allow_cold_extrude=allow; - #endif -} diff --git a/Marlin/thermistortables.h~ b/Marlin/thermistortables.h~ deleted file mode 100644 index f4c25d357e..0000000000 --- a/Marlin/thermistortables.h~ +++ /dev/null @@ -1,528 +0,0 @@ -#ifndef THERMISTORTABLES_H_ -#define THERMISTORTABLES_H_ - -#include "Marlin.h" - -#define OVERSAMPLENR 16 - -#if (THERMISTORHEATER_0 == 1) || (THERMISTORHEATER_1 == 1) || (THERMISTORHEATER_2 == 1) || (THERMISTORBED == 1) //100k bed thermistor - -const short temptable_1[][2] PROGMEM = { -{ 23*OVERSAMPLENR , 300 }, -{ 25*OVERSAMPLENR , 295 }, -{ 27*OVERSAMPLENR , 290 }, -{ 28*OVERSAMPLENR , 285 }, -{ 31*OVERSAMPLENR , 280 }, -{ 33*OVERSAMPLENR , 275 }, -{ 35*OVERSAMPLENR , 270 }, -{ 38*OVERSAMPLENR , 265 }, -{ 41*OVERSAMPLENR , 260 }, -{ 44*OVERSAMPLENR , 255 }, -{ 48*OVERSAMPLENR , 250 }, -{ 52*OVERSAMPLENR , 245 }, -{ 56*OVERSAMPLENR , 240 }, -{ 61*OVERSAMPLENR , 235 }, -{ 66*OVERSAMPLENR , 230 }, -{ 71*OVERSAMPLENR , 225 }, -{ 78*OVERSAMPLENR , 220 }, -{ 84*OVERSAMPLENR , 215 }, -{ 92*OVERSAMPLENR , 210 }, -{ 100*OVERSAMPLENR , 205 }, -{ 109*OVERSAMPLENR , 200 }, -{ 120*OVERSAMPLENR , 195 }, -{ 131*OVERSAMPLENR , 190 }, -{ 143*OVERSAMPLENR , 185 }, -{ 156*OVERSAMPLENR , 180 }, -{ 171*OVERSAMPLENR , 175 }, -{ 187*OVERSAMPLENR , 170 }, -{ 205*OVERSAMPLENR , 165 }, -{ 224*OVERSAMPLENR , 160 }, -{ 245*OVERSAMPLENR , 155 }, -{ 268*OVERSAMPLENR , 150 }, -{ 293*OVERSAMPLENR , 145 }, -{ 320*OVERSAMPLENR , 140 }, -{ 348*OVERSAMPLENR , 135 }, -{ 379*OVERSAMPLENR , 130 }, -{ 411*OVERSAMPLENR , 125 }, -{ 445*OVERSAMPLENR , 120 }, -{ 480*OVERSAMPLENR , 115 }, -{ 516*OVERSAMPLENR , 110 }, -{ 553*OVERSAMPLENR , 105 }, -{ 591*OVERSAMPLENR , 100 }, -{ 628*OVERSAMPLENR , 95 }, -{ 665*OVERSAMPLENR , 90 }, -{ 702*OVERSAMPLENR , 85 }, -{ 737*OVERSAMPLENR , 80 }, -{ 770*OVERSAMPLENR , 75 }, -{ 801*OVERSAMPLENR , 70 }, -{ 830*OVERSAMPLENR , 65 }, -{ 857*OVERSAMPLENR , 60 }, -{ 881*OVERSAMPLENR , 55 }, -{ 903*OVERSAMPLENR , 50 }, -{ 922*OVERSAMPLENR , 45 }, -{ 939*OVERSAMPLENR , 40 }, -{ 954*OVERSAMPLENR , 35 }, -{ 966*OVERSAMPLENR , 30 }, -{ 977*OVERSAMPLENR , 25 }, -{ 985*OVERSAMPLENR , 20 }, -{ 993*OVERSAMPLENR , 15 }, -{ 999*OVERSAMPLENR , 10 }, -{ 1004*OVERSAMPLENR , 5 }, -{ 1008*OVERSAMPLENR , 0 } //safety -}; -#endif -#if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor -const short temptable_2[][2] PROGMEM = { - {1*OVERSAMPLENR, 848}, - {54*OVERSAMPLENR, 275}, - {107*OVERSAMPLENR, 228}, - {160*OVERSAMPLENR, 202}, - {213*OVERSAMPLENR, 185}, - {266*OVERSAMPLENR, 171}, - {319*OVERSAMPLENR, 160}, - {372*OVERSAMPLENR, 150}, - {425*OVERSAMPLENR, 141}, - {478*OVERSAMPLENR, 133}, - {531*OVERSAMPLENR, 125}, - {584*OVERSAMPLENR, 118}, - {637*OVERSAMPLENR, 110}, - {690*OVERSAMPLENR, 103}, - {743*OVERSAMPLENR, 95}, - {796*OVERSAMPLENR, 86}, - {849*OVERSAMPLENR, 77}, - {902*OVERSAMPLENR, 65}, - {955*OVERSAMPLENR, 49}, - {1008*OVERSAMPLENR, 17}, - {1020*OVERSAMPLENR, 0} //safety -}; - -#endif -#if (THERMISTORHEATER_0 == 3) || (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts -const short temptable_3[][2] PROGMEM = { - {1*OVERSAMPLENR,864}, - {21*OVERSAMPLENR,300}, - {25*OVERSAMPLENR,290}, - {29*OVERSAMPLENR,280}, - {33*OVERSAMPLENR,270}, - {39*OVERSAMPLENR,260}, - {46*OVERSAMPLENR,250}, - {54*OVERSAMPLENR,240}, - {64*OVERSAMPLENR,230}, - {75*OVERSAMPLENR,220}, - {90*OVERSAMPLENR,210}, - {107*OVERSAMPLENR,200}, - {128*OVERSAMPLENR,190}, - {154*OVERSAMPLENR,180}, - {184*OVERSAMPLENR,170}, - {221*OVERSAMPLENR,160}, - {265*OVERSAMPLENR,150}, - {316*OVERSAMPLENR,140}, - {375*OVERSAMPLENR,130}, - {441*OVERSAMPLENR,120}, - {513*OVERSAMPLENR,110}, - {588*OVERSAMPLENR,100}, - {734*OVERSAMPLENR,80}, - {856*OVERSAMPLENR,60}, - {938*OVERSAMPLENR,40}, - {986*OVERSAMPLENR,20}, - {1008*OVERSAMPLENR,0}, - {1018*OVERSAMPLENR,-20} - }; - -#endif -#if (THERMISTORHEATER_0 == 4) || (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor -const short temptable_4[][2] PROGMEM = { - {1*OVERSAMPLENR, 430}, - {54*OVERSAMPLENR, 137}, - {107*OVERSAMPLENR, 107}, - {160*OVERSAMPLENR, 91}, - {213*OVERSAMPLENR, 80}, - {266*OVERSAMPLENR, 71}, - {319*OVERSAMPLENR, 64}, - {372*OVERSAMPLENR, 57}, - {425*OVERSAMPLENR, 51}, - {478*OVERSAMPLENR, 46}, - {531*OVERSAMPLENR, 41}, - {584*OVERSAMPLENR, 35}, - {637*OVERSAMPLENR, 30}, - {690*OVERSAMPLENR, 25}, - {743*OVERSAMPLENR, 20}, - {796*OVERSAMPLENR, 14}, - {849*OVERSAMPLENR, 7}, - {902*OVERSAMPLENR, 0}, - {955*OVERSAMPLENR, -11}, - {1008*OVERSAMPLENR, -35} -}; -#endif - -#if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) -const short temptable_5[][2] PROGMEM = { -{1*OVERSAMPLENR, 713}, -{18*OVERSAMPLENR, 316}, -{35*OVERSAMPLENR, 266}, -{52*OVERSAMPLENR, 239}, -{69*OVERSAMPLENR, 221}, -{86*OVERSAMPLENR, 208}, -{103*OVERSAMPLENR, 197}, -{120*OVERSAMPLENR, 188}, -{137*OVERSAMPLENR, 181}, -{154*OVERSAMPLENR, 174}, -{171*OVERSAMPLENR, 169}, -{188*OVERSAMPLENR, 163}, -{205*OVERSAMPLENR, 159}, -{222*OVERSAMPLENR, 154}, -{239*OVERSAMPLENR, 150}, -{256*OVERSAMPLENR, 147}, -{273*OVERSAMPLENR, 143}, -{290*OVERSAMPLENR, 140}, -{307*OVERSAMPLENR, 136}, -{324*OVERSAMPLENR, 133}, -{341*OVERSAMPLENR, 130}, -{358*OVERSAMPLENR, 128}, -{375*OVERSAMPLENR, 125}, -{392*OVERSAMPLENR, 122}, -{409*OVERSAMPLENR, 120}, -{426*OVERSAMPLENR, 117}, -{443*OVERSAMPLENR, 115}, -{460*OVERSAMPLENR, 112}, -{477*OVERSAMPLENR, 110}, -{494*OVERSAMPLENR, 108}, -{511*OVERSAMPLENR, 106}, -{528*OVERSAMPLENR, 103}, -{545*OVERSAMPLENR, 101}, -{562*OVERSAMPLENR, 99}, -{579*OVERSAMPLENR, 97}, -{596*OVERSAMPLENR, 95}, -{613*OVERSAMPLENR, 92}, -{630*OVERSAMPLENR, 90}, -{647*OVERSAMPLENR, 88}, -{664*OVERSAMPLENR, 86}, -{681*OVERSAMPLENR, 84}, -{698*OVERSAMPLENR, 81}, -{715*OVERSAMPLENR, 79}, -{732*OVERSAMPLENR, 77}, -{749*OVERSAMPLENR, 75}, -{766*OVERSAMPLENR, 72}, -{783*OVERSAMPLENR, 70}, -{800*OVERSAMPLENR, 67}, -{817*OVERSAMPLENR, 64}, -{834*OVERSAMPLENR, 61}, -{851*OVERSAMPLENR, 58}, -{868*OVERSAMPLENR, 55}, -{885*OVERSAMPLENR, 52}, -{902*OVERSAMPLENR, 48}, -{919*OVERSAMPLENR, 44}, -{936*OVERSAMPLENR, 40}, -{953*OVERSAMPLENR, 34}, -{970*OVERSAMPLENR, 28}, -{987*OVERSAMPLENR, 20}, -{1004*OVERSAMPLENR, 8}, -{1021*OVERSAMPLENR, 0} -}; -#endif - -#if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor -const short temptable_6[][2] PROGMEM = { - {28*OVERSAMPLENR, 250}, - {31*OVERSAMPLENR, 245}, - {35*OVERSAMPLENR, 240}, - {39*OVERSAMPLENR, 235}, - {42*OVERSAMPLENR, 230}, - {44*OVERSAMPLENR, 225}, - {49*OVERSAMPLENR, 220}, - {53*OVERSAMPLENR, 215}, - {62*OVERSAMPLENR, 210}, - {73*OVERSAMPLENR, 205}, - {72*OVERSAMPLENR, 200}, - {94*OVERSAMPLENR, 190}, - {102*OVERSAMPLENR, 185}, - {116*OVERSAMPLENR, 170}, - {143*OVERSAMPLENR, 160}, - {183*OVERSAMPLENR, 150}, - {223*OVERSAMPLENR, 140}, - {270*OVERSAMPLENR, 130}, - {318*OVERSAMPLENR, 120}, - {383*OVERSAMPLENR, 110}, - {413*OVERSAMPLENR, 105}, - {439*OVERSAMPLENR, 100}, - {484*OVERSAMPLENR, 95}, - {513*OVERSAMPLENR, 90}, - {607*OVERSAMPLENR, 80}, - {664*OVERSAMPLENR, 70}, - {781*OVERSAMPLENR, 60}, - {810*OVERSAMPLENR, 55}, - {849*OVERSAMPLENR, 50}, - {914*OVERSAMPLENR, 45}, - {914*OVERSAMPLENR, 40}, - {935*OVERSAMPLENR, 35}, - {954*OVERSAMPLENR, 30}, - {970*OVERSAMPLENR, 25}, - {978*OVERSAMPLENR, 22}, - {1008*OVERSAMPLENR, 3} -}; -#endif - -#if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 -const short temptable_7[][2] PROGMEM = { - {46*OVERSAMPLENR, 270}, - {50*OVERSAMPLENR, 265}, - {54*OVERSAMPLENR, 260}, - {58*OVERSAMPLENR, 255}, - {62*OVERSAMPLENR, 250}, - {67*OVERSAMPLENR, 245}, - {72*OVERSAMPLENR, 240}, - {79*OVERSAMPLENR, 235}, - {85*OVERSAMPLENR, 230}, - {91*OVERSAMPLENR, 225}, - {99*OVERSAMPLENR, 220}, - {107*OVERSAMPLENR, 215}, - {116*OVERSAMPLENR, 210}, - {126*OVERSAMPLENR, 205}, - {136*OVERSAMPLENR, 200}, - {149*OVERSAMPLENR, 195}, - {160*OVERSAMPLENR, 190}, - {175*OVERSAMPLENR, 185}, - {191*OVERSAMPLENR, 180}, - {209*OVERSAMPLENR, 175}, - {224*OVERSAMPLENR, 170}, - {246*OVERSAMPLENR, 165}, - {267*OVERSAMPLENR, 160}, - {293*OVERSAMPLENR, 155}, - {316*OVERSAMPLENR, 150}, - {340*OVERSAMPLENR, 145}, - {364*OVERSAMPLENR, 140}, - {396*OVERSAMPLENR, 135}, - {425*OVERSAMPLENR, 130}, - {460*OVERSAMPLENR, 125}, - {489*OVERSAMPLENR, 120}, - {526*OVERSAMPLENR, 115}, - {558*OVERSAMPLENR, 110}, - {591*OVERSAMPLENR, 105}, - {628*OVERSAMPLENR, 100}, - {660*OVERSAMPLENR, 95}, - {696*OVERSAMPLENR, 90}, - {733*OVERSAMPLENR, 85}, - {761*OVERSAMPLENR, 80}, - {794*OVERSAMPLENR, 75}, - {819*OVERSAMPLENR, 70}, - {847*OVERSAMPLENR, 65}, - {870*OVERSAMPLENR, 60}, - {892*OVERSAMPLENR, 55}, - {911*OVERSAMPLENR, 50}, - {929*OVERSAMPLENR, 45}, - {944*OVERSAMPLENR, 40}, - {959*OVERSAMPLENR, 35}, - {971*OVERSAMPLENR, 30}, - {981*OVERSAMPLENR, 25}, - {989*OVERSAMPLENR, 20}, - {994*OVERSAMPLENR, 15}, - {1001*OVERSAMPLENR, 10}, - {1005*OVERSAMPLENR, 5} -}; -#endif -// -#if (THERMISTORHEATER_0 == 100) || (THERMISTORHEATER_1 == 100) || (THERMISTORHEATER_2 == 100) || (THERMISTORBED == 100) // 100k DO-35 NTC -const short temptable_100[][2] PROGMEM = { - {1*OVERSAMPLENR, 929}, - {36*OVERSAMPLENR, 299}, - {71*OVERSAMPLENR, 246}, - {106*OVERSAMPLENR, 217}, - {141*OVERSAMPLENR, 198}, - {176*OVERSAMPLENR, 184}, - {211*OVERSAMPLENR, 173}, - {246*OVERSAMPLENR, 163}, - {281*OVERSAMPLENR, 154}, - {316*OVERSAMPLENR, 147}, - {351*OVERSAMPLENR, 140}, - {386*OVERSAMPLENR, 134}, - {421*OVERSAMPLENR, 128}, - {456*OVERSAMPLENR, 122}, - {491*OVERSAMPLENR, 117}, - {526*OVERSAMPLENR, 112}, - {561*OVERSAMPLENR, 107}, - {596*OVERSAMPLENR, 102}, - {631*OVERSAMPLENR, 97}, - {666*OVERSAMPLENR, 91}, - {701*OVERSAMPLENR, 86}, - {736*OVERSAMPLENR, 81}, - {771*OVERSAMPLENR, 76}, - {806*OVERSAMPLENR, 70}, - {841*OVERSAMPLENR, 63}, - {876*OVERSAMPLENR, 56}, - {911*OVERSAMPLENR, 48}, - {946*OVERSAMPLENR, 38}, - {981*OVERSAMPLENR, 23}, - {1005*OVERSAMPLENR, 5}, - {1016*OVERSAMPLENR, 0} -}; -#endif -#if (THERMISTORHEATER_0 == 101) || (THERMISTORHEATER_1 == 101) || (THERMISTORHEATER_2 == 101) || (THERMISTORBED == 101) // 100k Honeywell 135-104LAG-J01 -const short temptable_101[][2] PROGMEM = { - {1*OVERSAMPLENR, 704}, - {54*OVERSAMPLENR, 216}, - {107*OVERSAMPLENR, 175}, - {160*OVERSAMPLENR, 152}, - {213*OVERSAMPLENR, 137}, - {266*OVERSAMPLENR, 125}, - {319*OVERSAMPLENR, 115}, - {372*OVERSAMPLENR, 106}, - {425*OVERSAMPLENR, 99}, - {478*OVERSAMPLENR, 91}, - {531*OVERSAMPLENR, 85}, - {584*OVERSAMPLENR, 78}, - {637*OVERSAMPLENR, 71}, - {690*OVERSAMPLENR, 65}, - {743*OVERSAMPLENR, 58}, - {796*OVERSAMPLENR, 50}, - {849*OVERSAMPLENR, 42}, - {902*OVERSAMPLENR, 31}, - {955*OVERSAMPLENR, 17}, - {1008*OVERSAMPLENR, 0} -}; -#endif -#if (THERMISTORHEATER_0 == 102) || (THERMISTORHEATER_1 == 102) || (THERMISTORHEATER_2 == 102) || (THERMISTORBED == 102) // EPCOS G57540 -const short temptable_100[][2] PROGMEM = { -{15*OVERSAMPLENR,286}, -{16*OVERSAMPLENR,282}, -{17*OVERSAMPLENR,278}, -{18*OVERSAMPLENR,274}, -{19*OVERSAMPLENR,270}, -{20*OVERSAMPLENR,266}, -{21*OVERSAMPLENR,262}, -{22*OVERSAMPLENR,258}, -{23*OVERSAMPLENR,254}, -{25*OVERSAMPLENR,250}, -{27*OVERSAMPLENR,246}, -{28*OVERSAMPLENR,242}, -{31*OVERSAMPLENR,238}, -{33*OVERSAMPLENR,234}, -{35*OVERSAMPLENR,230}, -{38*OVERSAMPLENR,226}, -{41*OVERSAMPLENR,222}, -{44*OVERSAMPLENR,218}, -{48*OVERSAMPLENR,214}, -{52*OVERSAMPLENR,210}, -{56*OVERSAMPLENR,206}, -{61*OVERSAMPLENR,202}, -{66*OVERSAMPLENR,198}, -{71*OVERSAMPLENR,194}, -{78*OVERSAMPLENR,190}, -{84*OVERSAMPLENR,186}, -{92*OVERSAMPLENR,182}, -{100*OVERSAMPLENR,178}, -{109*OVERSAMPLENR,174}, -{120*OVERSAMPLENR,170}, -{131*OVERSAMPLENR,166}, -{143*OVERSAMPLENR,162}, -{156*OVERSAMPLENR,158}, -{171*OVERSAMPLENR,154}, -{187*OVERSAMPLENR,150}, -{205*OVERSAMPLENR,146}, -{224*OVERSAMPLENR,142}, -{224*OVERSAMPLENR,160}, -{245*OVERSAMPLENR,155}, -{268*OVERSAMPLENR,150}, -{293*OVERSAMPLENR,145}, -{320*OVERSAMPLENR,140}, -{348*OVERSAMPLENR,135}, -{379*OVERSAMPLENR,130}, -{411*OVERSAMPLENR,125}, -{480*OVERSAMPLENR,115}, -{553*OVERSAMPLENR,105}, -{628*OVERSAMPLENR,95}, -{702*OVERSAMPLENR,85}, -{770*OVERSAMPLENR,75}, -{830*OVERSAMPLENR,65}, -{881*OVERSAMPLENR,55}, -{922*OVERSAMPLENR,45}, -{954*OVERSAMPLENR,35}, -{977*OVERSAMPLENR,25}, -{993*OVERSAMPLENR,15}, -{999*OVERSAMPLENR,10}, -{1008*OVERSAMPLENR,0}, -}; -#endif -#if (THERMISTORHEATER_0 == 103) || (THERMISTORHEATER_1 == 103) || (THERMISTORHEATER_2 == 103) || (THERMISTORBED == 103) // 100k Honeywell 135-104LAG-J01 -const short temptable_103[][2] PROGMEM = { - {1*OVERSAMPLENR, 628}, - {187*OVERSAMPLENR, 156}, - {218*OVERSAMPLENR, 148}, - {249*OVERSAMPLENR, 141}, - {280*OVERSAMPLENR, 135}, - {311*OVERSAMPLENR, 129}, - {342*OVERSAMPLENR, 124}, - {373*OVERSAMPLENR, 120}, - {404*OVERSAMPLENR, 115}, - {435*OVERSAMPLENR, 111}, - {466*OVERSAMPLENR, 107}, - {497*OVERSAMPLENR, 103}, - {528*OVERSAMPLENR, 99}, - {559*OVERSAMPLENR, 96}, - {590*OVERSAMPLENR, 92}, - {621*OVERSAMPLENR, 88}, - {652*OVERSAMPLENR, 84}, - {683*OVERSAMPLENR, 81}, - {714*OVERSAMPLENR, 77}, - {745*OVERSAMPLENR, 73}, - {776*OVERSAMPLENR, 68}, - {807*OVERSAMPLENR, 64}, - {838*OVERSAMPLENR, 59}, - {869*OVERSAMPLENR, 54}, - {900*OVERSAMPLENR, 48}, - {931*OVERSAMPLENR, 40}, - {962*OVERSAMPLENR, 31}, - {993*OVERSAMPLENR, 17}, - {1008*OVERSAMPLENR,0} -}; -#endif - -#define _TT_NAME(_N) temptable_ ## _N -#define TT_NAME(_N) _TT_NAME(_N) - -#ifdef THERMISTORHEATER_0 - #define heater_0_temptable TT_NAME(THERMISTORHEATER_0) - #define heater_0_temptable_len (sizeof(heater_0_temptable)/sizeof(*heater_0_temptable)) -#else -#ifdef HEATER_0_USES_THERMISTOR - #error No heater 0 thermistor table specified -#else // HEATER_0_USES_THERMISTOR - #define heater_0_temptable 0 - #define heater_0_temptable_len 0 -#endif // HEATER_0_USES_THERMISTOR -#endif - -#ifdef THERMISTORHEATER_1 - #define heater_1_temptable TT_NAME(THERMISTORHEATER_1) - #define heater_1_temptable_len (sizeof(heater_1_temptable)/sizeof(*heater_1_temptable)) -#else -#ifdef HEATER_1_USES_THERMISTOR - #error No heater 1 thermistor table specified -#else // HEATER_1_USES_THERMISTOR - #define heater_1_temptable 0 - #define heater_1_temptable_len 0 -#endif // HEATER_1_USES_THERMISTOR -#endif - -#ifdef THERMISTORHEATER_2 - #define heater_2_temptable TT_NAME(THERMISTORHEATER_2) - #define heater_2_temptable_len (sizeof(heater_2_temptable)/sizeof(*heater_2_temptable)) -#else -#ifdef HEATER_2_USES_THERMISTOR - #error No heater 2 thermistor table specified -#else // HEATER_2_USES_THERMISTOR - #define heater_2_temptable 0 - #define heater_2_temptable_len 0 -#endif // HEATER_2_USES_THERMISTOR -#endif - -#ifdef THERMISTORBED - #define bedtemptable TT_NAME(THERMISTORBED) - #define bedtemptable_len (sizeof(bedtemptable)/sizeof(*bedtemptable)) -#else -#ifdef BED_USES_THERMISTOR - #error No bed thermistor table specified -#endif // BED_USES_THERMISTOR -#endif - -#endif //THERMISTORTABLES_H_ - From fc4eaabe603767e9309966787e738731bf7568e5 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Sun, 18 Mar 2012 21:47:29 +0000 Subject: [PATCH 211/228] brought up to date with Erik Zalm Marlin. Included Melzi LED pin. --- Marlin/Configuration_adv.h | 6 + Marlin/Makefile | 6 +- Marlin/Marlin.pde | 67 +- Marlin/create_speed_lookuptable.py | 50 ++ Marlin/pins.h | 490 ++++++++------- Marlin/pins.h~ | 965 +++++++++++++++++++++++++++++ Marlin/planner.cpp | 8 +- Marlin/speed_lookuptable.h | 76 +++ Marlin/stepper.cpp | 22 +- Marlin/temperature.cpp | 106 +++- Marlin/temperature.h | 7 +- Marlin/ultralcd.pde | 38 +- 12 files changed, 1599 insertions(+), 242 deletions(-) create mode 100755 Marlin/create_speed_lookuptable.py create mode 100644 Marlin/pins.h~ diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 4af432e82b..4fb63ec62d 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -61,6 +61,12 @@ #define TEMP_SENSOR_AD595_OFFSET 0.0 #define TEMP_SENSOR_AD595_GAIN 1.0 +//This is for controlling a fan to cool down the stepper drivers +//it will turn on when any driver is enabled +//and turn off after the set amount of seconds from last driver being disabled again +//#define CONTROLLERFAN_PIN 23 //Pin used for the fan to cool controller, comment out to disable this function +#define CONTROLLERFAN_SEC 60 //How many seconds, after all motors were disabled, the fan should run + //=========================================================================== //=============================Mechanical Settings=========================== //=========================================================================== diff --git a/Marlin/Makefile b/Marlin/Makefile index 9e41c28d33..955ccd5e33 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -23,7 +23,9 @@ # 3. Set the line containing "MCU" to match your board's processor. # Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth # or Diecimila have the atmega168. If you're using a LilyPad Arduino, -# change F_CPU to 8000000. +# change F_CPU to 8000000. If you are using Gen7 electronics, you +# probably need to use 20000000. Either way, you must regenerate +# the speed lookup table with create_speed_lookuptable.py. # # 4. Type "make" and press enter to compile/verify your program. # @@ -42,6 +44,8 @@ MCU = atmega1280 #Arduino install directory INSTALL_DIR = ../../arduino-0022/ +# Be sure to regenerate speed_lookuptable.h with create_speed_lookuptable.py +# if you are setting this to something other than 16MHz F_CPU = 16000000 UPLOAD_RATE = 115200 diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 103913a7cd..45996427e9 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -109,6 +109,7 @@ // 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) +// M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) //Stepper Movement Variables @@ -290,6 +291,7 @@ void setup() 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; @@ -570,12 +572,14 @@ void process_commands() previous_millis_cmd = millis(); while(millis() < codenum ){ manage_heater(); + manage_inactivity(1); } break; 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); @@ -914,6 +918,7 @@ void process_commands() codenum = millis(); } manage_heater(); + manage_inactivity(1); LCD_STATUS; #ifdef TEMP_RESIDENCY_TIME /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time @@ -950,6 +955,7 @@ void process_commands() codenum = millis(); } manage_heater(); + manage_inactivity(1); LCD_STATUS; } LCD_MESSAGEPGM(MSG_BED_DONE); @@ -1209,6 +1215,13 @@ void process_commands() allow_cold_extrudes(true); } break; + case 303: // M303 PID autotune + { + float temp = 150.0; + if (code_seen('S')) temp=code_value(); + PID_autotune(temp); + } + break; case 400: // finish all moves { st_synchronize(); @@ -1317,12 +1330,11 @@ void prepare_move() if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH; if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; } - + previous_millis_cmd = millis(); 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]; } - previous_millis_cmd = millis(); } void prepare_arc_move(char isclockwise) { @@ -1340,6 +1352,40 @@ void prepare_arc_move(char isclockwise) { 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(byte debug) { if( (millis() - previous_millis_cmd) > max_inactive_time ) @@ -1348,14 +1394,19 @@ void manage_inactivity(byte debug) if(stepper_inactive_time) { if( (millis() - previous_millis_cmd) > stepper_inactive_time ) { - disable_x(); - disable_y(); - disable_z(); - disable_e0(); - disable_e1(); - disable_e2(); + if(blocks_queued() == false) { + disable_x(); + disable_y(); + disable_z(); + disable_e0(); + disable_e1(); + disable_e2(); + } } } + #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) diff --git a/Marlin/create_speed_lookuptable.py b/Marlin/create_speed_lookuptable.py new file mode 100755 index 0000000000..13ed92d520 --- /dev/null +++ b/Marlin/create_speed_lookuptable.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python + +""" Generate the stepper delay lookup table for Marlin firmware. """ + +import argparse + +__author__ = "Ben Gamari " +__copyright__ = "Copyright 2012, Ben Gamari" +__license__ = "GPL" + +parser = argparse.ArgumentParser(description=__doc__) +parser.add_argument('-f', '--cpu-freq', type=int, default=16, help='CPU clockrate in MHz (default=16)') +parser.add_argument('-d', '--divider', type=int, default=8, help='Timer/counter pre-scale divider (default=8)') +args = parser.parse_args() + +cpu_freq = args.cpu_freq * 1000000 +timer_freq = cpu_freq / args.divider + +print "#ifndef SPEED_LOOKUPTABLE_H" +print "#define SPEED_LOOKUPTABLE_H" +print +print '#include "Marlin.h"' +print + +print "const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {" +a = [ timer_freq / ((i*256)+(args.cpu_freq*2)) for i in range(256) ] +b = [ a[i] - a[i+1] for i in range(255) ] +b.append(b[-1]) +for i in range(32): + print " ", + for j in range(8): + print "{%d, %d}," % (a[8*i+j], b[8*i+j]), + print +print "};" +print + +print "const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {" +a = [ timer_freq / ((i*8)+(args.cpu_freq*2)) for i in range(256) ] +b = [ a[i] - a[i+1] for i in range(255) ] +b.append(b[-1]) +for i in range(32): + print " ", + for j in range(8): + print "{%d, %d}," % (a[8*i+j], b[8*i+j]), + print +print "};" +print + +print "#endif" + diff --git a/Marlin/pins.h b/Marlin/pins.h index 25c69b6ce6..056d861d69 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -45,225 +45,195 @@ #endif /* 99 */ /**************************************************************************************** -* Arduino pin assignment -* -* ATMega168 -* +-\/-+ -* PC6 1| |28 PC5 (AI 5 / D19) -* (D 0) PD0 2| |27 PC4 (AI 4 / D18) -* (D 1) PD1 3| |26 PC3 (AI 3 / D17) -* (D 2) PD2 4| |25 PC2 (AI 2 / D16) -* PWM+ (D 3) PD3 5| |24 PC1 (AI 1 / D15) -* (D 4) PD4 6| |23 PC0 (AI 0 / D14) -* VCC 7| |22 GND -* GND 8| |21 AREF -* PB6 9| |20 AVCC -* PB7 10| |19 PB5 (D 13) -* PWM+ (D 5) PD5 11| |18 PB4 (D 12) -* PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM -* (D 7) PD7 13| |16 PB2 (D 10) PWM -* (D 8) PB0 14| |15 PB1 (D 9) PWM -* +----+ -****************************************************************************************/ -#if MOTHERBOARD == 0 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega168__ -#error Oops! Make sure you have 'Arduino Diecimila' selected from the boards menu. -#endif - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 4 -#define X_MAX_PIN 9 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN 13 - -#define Z_STEP_PIN 19 -#define Z_DIR_PIN 18 -#define Z_ENABLE_PIN 5 -#define Z_MIN_PIN 17 -#define Z_MAX_PIN 16 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 15 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -#endif - - - -/**************************************************************************************** -* Sanguino/RepRap Motherboard with direct-drive extruders -* -* ATMega644P -* -* +---\/---+ -* (D 0) PB0 1| |40 PA0 (AI 0 / D31) -* (D 1) PB1 2| |39 PA1 (AI 1 / D30) -* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29) -* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28) -* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27) -* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26) -* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25) -* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24) -* RST 9| |32 AREF -* VCC 10| |31 GND -* GND 11| |30 AVCC -* XTAL2 12| |29 PC7 (D 23) -* XTAL1 13| |28 PC6 (D 22) -* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI -* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO -* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS -* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK -* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA -* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL -* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM -* +--------+ +* Gen7 v1.1, v1.2, v1.3, v1.4 pin assignment * ****************************************************************************************/ -#if MOTHERBOARD == 1 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. + +#if MOTHERBOARD == 13 +#define MOTHERBOARD 11 +#define GEN7_VERSION 14 // v1.4 #endif -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 19 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 - -#define Z_STEP_PIN 29 -#define Z_DIR_PIN 30 -#define Z_ENABLE_PIN 31 -#define Z_MIN_PIN 2 -#define Z_MAX_PIN 1 - -#define E0_STEP_PIN 12 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN 3 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN 0 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 14 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 4 //D27 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 -/* Unused (1) (2) (3) 4 5 6 7 8 9 10 11 12 13 (14) (15) (16) 17 (18) (19) (20) (21) (22) (23) 24 (25) (26) (27) 28 (29) (30) (31) */ +#if MOTHERBOARD == 12 +#define MOTHERBOARD 11 +#define GEN7_VERSION 13 // v1.3 +#endif +#if MOTHERBOARD == 11 +#define KNOWN_BOARD +#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega644__) && !defined(__AVR_ATmega1284P__) +#error Oops! Make sure you have 'Gen7' selected from the 'Tools -> Boards' menu. #endif - -/**************************************************************************************** -* RepRap Motherboard ****---NOOOOOO RS485/EXTRUDER CONTROLLER!!!!!!!!!!!!!!!!!---******* -* -****************************************************************************************/ -#if MOTHERBOARD == 2 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#ifndef GEN7_VERSION +#define GEN7_VERSION 12 // v1.x #endif -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 19 -#define X_MIN_PIN 20 -#define X_MAX_PIN 21 +//x axis pins +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 7 +#define X_MAX_PIN -1 -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN 26 +//y axis pins +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 5 +#define Y_MAX_PIN -1 -#define Z_STEP_PINN 27 -#define Z_DIR_PINN 28 -#define Z_ENABLE_PIN 29 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 31 +//z axis pins +#define Z_STEP_PIN 26 +#define Z_DIR_PIN 25 +#define Z_ENABLE_PIN 24 +#define Z_MIN_PIN 1 +#define Z_MAX_PIN 0 -#define E0_STEP_PIN 17 -#define E0_DIR_PIN 16 -#define E0_ENABLE_PIN -1 +//extruder pins +#define E0_STEP_PIN 28 +#define E0_DIR_PIN 27 +#define E0_ENABLE_PIN 24 -#define SDPOWER -1 -#define SDSS 4 -#define LED_PIN 0 +#define TEMP_0_PIN 1 +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 2 -#define SD_CARD_WRITE 2 -#define SD_CARD_DETECT 3 -#define SD_CARD_SELECT 4 +#define HEATER_0_PIN 4 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define HEATER_BED_PIN 3 + + +#define SDPOWER -1 +#define SDSS -1 // SCL pin of I2C header +#define LED_PIN -1 + +#if (GEN7_VERSION >= 13) +// Gen7 v1.3 removed the fan pin +#define FAN_PIN -1 +#else +#define FAN_PIN 31 +#endif +#define PS_ON_PIN 15 + +#if (GEN7_VERSION < 14) +// Gen 1.3 and earlier supplied thermistor power via PS_ON +// Need to ignore the bad thermistor readings on those units +#define BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE +#endif + +//our pin for debugging. +#define DEBUG_PIN 0 //our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 -//pin for controlling the PSU. -#define PS_ON_PIN 14 +#endif -#define FAN_PIN -1 -#define KILL_PIN -1 +/******************************************************************************* +********* +* Gen7 Alfons3 pin assignment +* +******************************************************************************** +********/ +/* These Pins are assigned for the modified GEN7 Board from Alfons3 Please review the pins and adjust it for your needs*/ -#define HEATER_0_PIN -1 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 +#if MOTHERBOARD == 10 +#define KNOWN_BOARD +#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega644__) && !defined(__AVR_ATmega1284P__) + #error Oops! Make sure you have 'Gen7' selected from the 'Tools -> Boards' menu. + +#endif + +//x axis pins + #define X_STEP_PIN 21 //different from stanard GEN7 + #define X_DIR_PIN 20 //different from stanard GEN7 + #define X_ENABLE_PIN 24 + #define X_MIN_PIN 0 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 1 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 26 + #define Z_DIR_PIN 25 + #define Z_ENABLE_PIN 24 + #define Z_MIN_PIN 2 + #define Z_MAX_PIN -1 + + //extruder pins + #define E0_STEP_PIN 28 + #define E0_DIR_PIN 27 + #define E0_ENABLE_PIN 24 + + #define TEMP_0_PIN 2 + #define TEMP_1_PIN -1 + #define TEMP_2_PIN -1 + #define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) + + #define HEATER_0_PIN 4 + #define HEATER_1_PIN -1 + #define HEATER_2_PIN -1 + #define HEATER_BED_PIN 3 // (bed) + + #define SDPOWER -1 + #define SDSS 31 // SCL pin of I2C header || CS Pin for SD Card support + #define LED_PIN -1 + + #define FAN_PIN -1 + #define PS_ON_PIN 19 + //our pin for debugging. + + #define DEBUG_PIN -1 + + //our RS485 pins + //#define TX_ENABLE_PIN 12 + //#define RX_ENABLE_PIN 13 + + #define BEEPER -1 + #define SDCARDDETECT -1 + #define SUICIDE_PIN -1 //has to be defined; otherwise Power_off doesn't work + + //Pins for 4bit LCD Support + #define LCD_PINS_RS 18 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 15 + #define LCD_PINS_D6 13 + #define LCD_PINS_D7 14 + + //buttons are directly attached + #define BTN_EN1 11 + #define BTN_EN2 10 + #define BTN_ENC 12 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 #endif /**************************************************************************************** * Arduino Mega pin assignment * ****************************************************************************************/ -#if MOTHERBOARD == 33 -#define MOTHERBOARD 3 -#define RAMPS_V_1_3 -#endif -#if MOTHERBOARD == 3 +#if MOTHERBOARD == 3 || MOTHERBOARD == 33 || MOTHERBOARD == 34 #define KNOWN_BOARD 1 //////////////////FIX THIS////////////// @@ -277,7 +247,7 @@ // #define RAMPS_V_1_3 // #define RAMPS_V_1_0 -#ifdef RAMPS_V_1_3 +#if MOTHERBOARD == 33 || MOTHERBOARD == 34 #define X_STEP_PIN 54 #define X_DIR_PIN 55 @@ -295,7 +265,7 @@ #define Z_DIR_PIN 48 #define Z_ENABLE_PIN 62 #define Z_MIN_PIN 18 -#define Z_MAX_PIN 19 //19 +#define Z_MAX_PIN 19 #define E0_STEP_PIN 26 #define E0_DIR_PIN 28 @@ -308,19 +278,96 @@ #define SDPOWER -1 #define SDSS 53 #define LED_PIN 13 -#define FAN_PIN 4 + +#if MOTHERBOARD == 33 +#define FAN_PIN 9 // (Sprinter config) +#else +#define FAN_PIN 4 // IO pin. Buffer needed +#endif #define PS_ON_PIN 12 #define KILL_PIN -1 #define HEATER_0_PIN 10 // EXTRUDER 1 -#define HEATER_1_PIN 9 // EXTRUDER 2 -#define HEATER_2_PIN -1 // EXTRUDER 2 +#if MOTHERBOARD == 33 +#define HEATER_1_PIN -1 +#else +#define HEATER_1_PIN 9 // EXTRUDER 2 (FAN On Sprinter) +#endif +#define HEATER_2_PIN -1 #define TEMP_0_PIN 13 // ANALOG NUMBERING #define TEMP_1_PIN 15 // ANALOG NUMBERING #define TEMP_2_PIN -1 // ANALOG NUMBERING #define HEATER_BED_PIN 8 // BED #define TEMP_BED_PIN 14 // ANALOG NUMBERING +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin which triggers an piezzo beeper + #define BEEPER 33 // Beeper on AUX-4 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 23 + #define LCD_PINS_D5 25 + #define LCD_PINS_D6 27 + #define LCD_PINS_D7 29 + + //buttons are directly attached using AUX-2 + #define BTN_EN1 37 + #define BTN_EN2 35 + #define BTN_ENC 31 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT -1 // Ramps does not use this port + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 33 No Beeper added + + //buttons are attached to a shift register + // Not wired this yet + //#define SHIFT_CLK 38 + //#define SHIFT_LD 42 + //#define SHIFT_OUT 40 + //#define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 23 + #define LCD_PINS_D5 25 + #define LCD_PINS_D6 27 + #define LCD_PINS_D7 29 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD #else // RAMPS_V_1_1 or RAMPS_V_1_2 as default @@ -352,8 +399,6 @@ #define PS_ON_PIN -1 #define KILL_PIN -1 - - #ifdef RAMPS_V_1_0 // RAMPS_V_1_0 #define HEATER_0_PIN 12 // RAMPS 1.0 #define HEATER_BED_PIN -1 // RAMPS 1.0 @@ -440,11 +485,13 @@ * Gen6 pin assignment * ****************************************************************************************/ -#if MOTHERBOARD == 5 +#if MOTHERBOARD == 5 || MOTHERBOARD == 51 #define KNOWN_BOARD 1 #ifndef __AVR_ATmega644P__ - #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#ifndef __AVR_ATmega1284P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif #endif //x axis pins @@ -474,13 +521,19 @@ #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + + #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 #define HEATER_1_PIN -1 #define HEATER_2_PIN -1 + #if MOTHERBOARD == 5 #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 - + #else + #define HEATER_BED_PIN 1 //changed @ rkoeppl 20110410 + #define TEMP_BED_PIN 0 //changed @ rkoeppl 20110410 + #endif #define SDPOWER -1 #define SDSS 17 #define LED_PIN -1 //changed @ rkoeppl 20110410 @@ -502,6 +555,7 @@ * ****************************************************************************************/ #if MOTHERBOARD == 62 +#undef MOTHERBOARD #define MOTHERBOARD 6 #define SANGUINOLOLU_V_1_2 #endif @@ -533,7 +587,7 @@ #define LED_PIN -1 -#define FAN_PIN 12 //12 +#define FAN_PIN 27 #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -680,7 +734,7 @@ #define encrot2 3 #define encrot3 1 - + #define SDCARDDETECT -1 //bits in the shift register that carry the buttons for: // left up center down right red #define BL_LE 7 @@ -831,8 +885,10 @@ #define MOTHERBOARD 6 #define KNOWN_BOARD 1 #ifndef __AVR_ATmega644P__ +#ifndef __AVR_ATmega1284P__ #error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. #endif +#endif #define X_STEP_PIN 15 #define X_DIR_PIN 18 @@ -884,22 +940,26 @@ #endif //List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN -#if EXTRUDERS == 3 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN -#elif EXTRUDERS == 2 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN - #define _E2_PINS -1 -#elif EXTRUDERS == 1 - #define _E1_PINS -1 - #define _E2_PINS -1 +#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN, +#if EXTRUDERS > 1 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, HEATER_1_PIN, #else - #error Unsupported number of extruders + #define _E1_PINS #endif +#if EXTRUDERS > 2 + #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, HEATER_2_PIN, +#else + #define _E2_PINS +#endif + +#ifdef DISABLE_MAX_ENDSTOPS +#define X_MAX_PIN -1 +#define Y_MAX_PIN -1 +#define Z_MAX_PIN -1 +#endif + #define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ - HEATER_0_PIN, HEATER_1_PIN, HEATER_2_PIN, \ HEATER_BED_PIN, FAN_PIN, \ - _E0_PINS, _E1_PINS, _E2_PINS, \ + _E0_PINS _E1_PINS _E2_PINS \ TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } #endif diff --git a/Marlin/pins.h~ b/Marlin/pins.h~ new file mode 100644 index 0000000000..034db11d93 --- /dev/null +++ b/Marlin/pins.h~ @@ -0,0 +1,965 @@ +#ifndef PINS_H +#define PINS_H + +#if MOTHERBOARD == 99 +#define KNOWN_BOARD 1 + +#define X_STEP_PIN 2 +#define X_DIR_PIN 3 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN -1 +#define X_MAX_PIN 16 + +#define Y_STEP_PIN 5 +#define Y_DIR_PIN 6 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 67 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 62 +#define Z_DIR_PIN 63 +#define Z_ENABLE_PIN -1 +#define Z_MIN_PIN 59 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 65 +#define E0_DIR_PIN 66 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN 9 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 10 + +#endif /* 99 */ + +/**************************************************************************************** +* Gen7 v1.1, v1.2, v1.3, v1.4 pin assignment +* +****************************************************************************************/ + + +#if MOTHERBOARD == 13 +#define MOTHERBOARD 11 +#define GEN7_VERSION 14 // v1.4 +#endif + +#if MOTHERBOARD == 12 +#define MOTHERBOARD 11 +#define GEN7_VERSION 13 // v1.3 +#endif + +#if MOTHERBOARD == 11 +#define KNOWN_BOARD + +#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega644__) && !defined(__AVR_ATmega1284P__) +#error Oops! Make sure you have 'Gen7' selected from the 'Tools -> Boards' menu. + +#endif + +#ifndef GEN7_VERSION +#define GEN7_VERSION 12 // v1.x +#endif + +//x axis pins +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 7 +#define X_MAX_PIN -1 + +//y axis pins +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_ENABLE_PIN 24 +#define Y_MIN_PIN 5 +#define Y_MAX_PIN -1 + +//z axis pins +#define Z_STEP_PIN 26 +#define Z_DIR_PIN 25 +#define Z_ENABLE_PIN 24 +#define Z_MIN_PIN 1 +#define Z_MAX_PIN 0 + +//extruder pins +#define E0_STEP_PIN 28 +#define E0_DIR_PIN 27 +#define E0_ENABLE_PIN 24 + +#define TEMP_0_PIN 1 +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 2 + +#define HEATER_0_PIN 4 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define HEATER_BED_PIN 3 + + +#define SDPOWER -1 +#define SDSS -1 // SCL pin of I2C header +#define LED_PIN -1 + +#if (GEN7_VERSION >= 13) +// Gen7 v1.3 removed the fan pin +#define FAN_PIN -1 +#else +#define FAN_PIN 31 +#endif +#define PS_ON_PIN 15 + +#if (GEN7_VERSION < 14) +// Gen 1.3 and earlier supplied thermistor power via PS_ON +// Need to ignore the bad thermistor readings on those units +#define BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE +#endif + +//our pin for debugging. +#define DEBUG_PIN 0 + +//our RS485 pins +#define TX_ENABLE_PIN 12 +#define RX_ENABLE_PIN 13 + +#endif + +/******************************************************************************* +********* +* Gen7 Alfons3 pin assignment +* +******************************************************************************** +********/ +/* These Pins are assigned for the modified GEN7 Board from Alfons3 Please review the pins and adjust it for your needs*/ + +#if MOTHERBOARD == 10 +#define KNOWN_BOARD + +#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega644__) && !defined(__AVR_ATmega1284P__) + #error Oops! Make sure you have 'Gen7' selected from the 'Tools -> Boards' menu. + +#endif + +//x axis pins + #define X_STEP_PIN 21 //different from stanard GEN7 + #define X_DIR_PIN 20 //different from stanard GEN7 + #define X_ENABLE_PIN 24 + #define X_MIN_PIN 0 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 1 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 26 + #define Z_DIR_PIN 25 + #define Z_ENABLE_PIN 24 + #define Z_MIN_PIN 2 + #define Z_MAX_PIN -1 + + //extruder pins + #define E0_STEP_PIN 28 + #define E0_DIR_PIN 27 + #define E0_ENABLE_PIN 24 + + #define TEMP_0_PIN 2 + #define TEMP_1_PIN -1 + #define TEMP_2_PIN -1 + #define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) + + #define HEATER_0_PIN 4 + #define HEATER_1_PIN -1 + #define HEATER_2_PIN -1 + #define HEATER_BED_PIN 3 // (bed) + + #define SDPOWER -1 + #define SDSS 31 // SCL pin of I2C header || CS Pin for SD Card support + #define LED_PIN -1 + + #define FAN_PIN -1 + #define PS_ON_PIN 19 + //our pin for debugging. + + #define DEBUG_PIN -1 + + //our RS485 pins + //#define TX_ENABLE_PIN 12 + //#define RX_ENABLE_PIN 13 + + #define BEEPER -1 + #define SDCARDDETECT -1 + #define SUICIDE_PIN -1 //has to be defined; otherwise Power_off doesn't work + + //Pins for 4bit LCD Support + #define LCD_PINS_RS 18 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 15 + #define LCD_PINS_D6 13 + #define LCD_PINS_D7 14 + + //buttons are directly attached + #define BTN_EN1 11 + #define BTN_EN2 10 + #define BTN_ENC 12 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 +#endif + +/**************************************************************************************** +* Arduino Mega pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 3 || MOTHERBOARD == 33 || MOTHERBOARD == 34 +#define KNOWN_BOARD 1 + +//////////////////FIX THIS////////////// +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 +// #define RAMPS_V_1_3 +// #define RAMPS_V_1_0 + +#if MOTHERBOARD == 33 || MOTHERBOARD == 34 + +#define X_STEP_PIN 54 +#define X_DIR_PIN 55 +#define X_ENABLE_PIN 38 +#define X_MIN_PIN 3 +#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. + +#define Y_STEP_PIN 60 +#define Y_DIR_PIN 61 +#define Y_ENABLE_PIN 56 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN 15 //15 + +#define Z_STEP_PIN 46 +#define Z_DIR_PIN 48 +#define Z_ENABLE_PIN 62 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN 19 + +#define E0_STEP_PIN 26 +#define E0_DIR_PIN 28 +#define E0_ENABLE_PIN 24 + +#define E1_STEP_PIN 36 +#define E1_DIR_PIN 34 +#define E1_ENABLE_PIN 30 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 + +#if MOTHERBOARD == 33 +#define FAN_PIN 9 // (Sprinter config) +#else +#define FAN_PIN 4 // IO pin. Buffer needed +#endif +#define PS_ON_PIN 12 +#define KILL_PIN -1 + +#define HEATER_0_PIN 10 // EXTRUDER 1 +#if MOTHERBOARD == 33 +#define HEATER_1_PIN -1 +#else +#define HEATER_1_PIN 9 // EXTRUDER 2 (FAN On Sprinter) +#endif +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 13 // ANALOG NUMBERING +#define TEMP_1_PIN 15 // ANALOG NUMBERING +#define TEMP_2_PIN -1 // ANALOG NUMBERING +#define HEATER_BED_PIN 8 // BED +#define TEMP_BED_PIN 14 // ANALOG NUMBERING + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin which triggers an piezzo beeper + #define BEEPER 33 // Beeper on AUX-4 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 23 + #define LCD_PINS_D5 25 + #define LCD_PINS_D6 27 + #define LCD_PINS_D7 29 + + //buttons are directly attached using AUX-2 + #define BTN_EN1 37 + #define BTN_EN2 35 + #define BTN_ENC 31 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT -1 // Ramps does not use this port + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 33 No Beeper added + + //buttons are attached to a shift register + // Not wired this yet + //#define SHIFT_CLK 38 + //#define SHIFT_LD 42 + //#define SHIFT_OUT 40 + //#define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 23 + #define LCD_PINS_D5 25 + #define LCD_PINS_D6 27 + #define LCD_PINS_D7 29 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + +#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default + +#define X_STEP_PIN 26 +#define X_DIR_PIN 28 +#define X_ENABLE_PIN 24 +#define X_MIN_PIN 3 +#define X_MAX_PIN -1 //2 + +#define Y_STEP_PIN 38 +#define Y_DIR_PIN 40 +#define Y_ENABLE_PIN 36 +#define Y_MIN_PIN 16 +#define Y_MAX_PIN -1 //17 + +#define Z_STEP_PIN 44 +#define Z_DIR_PIN 46 +#define Z_ENABLE_PIN 42 +#define Z_MIN_PIN 18 +#define Z_MAX_PIN -1 //19 + +#define E0_STEP_PIN 32 +#define E0_DIR_PIN 34 +#define E0_ENABLE_PIN 30 + +#define SDPOWER 48 +#define SDSS 53 +#define LED_PIN 13 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 + #define HEATER_0_PIN 12 // RAMPS 1.0 + #define HEATER_BED_PIN -1 // RAMPS 1.0 + #define FAN_PIN 11 // RAMPS 1.0 +#else // RAMPS_V_1_1 or RAMPS_V_1_2 + #define HEATER_0_PIN 10 // RAMPS 1.1 + #define HEATER_BED_PIN 8 // RAMPS 1.1 + #define FAN_PIN 9 // RAMPS 1.1 +#endif +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#endif + +// SPI for Max6675 Thermocouple + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define MAX_SCK_PIN 52 + #define MAX_MISO_PIN 50 + #define MAX_MOSI_PIN 51 + #define MAX6675_SS 53 +#else + #define MAX6675_SS 49 +#endif + +#endif + +/**************************************************************************************** +* Duemilanove w/ ATMega328P pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 4 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega328P__ +#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. +#endif + +#define X_STEP_PIN 19 +#define X_DIR_PIN 18 +#define X_ENABLE_PIN -1 +#define X_MIN_PIN 17 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 10 +#define Y_DIR_PIN 7 +#define Y_ENABLE_PIN -1 +#define Y_MIN_PIN 8 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 13 +#define Z_DIR_PIN 3 +#define Z_ENABLE_PIN 2 +#define Z_MIN_PIN 4 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 11 +#define E0_DIR_PIN 12 +#define E0_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN 5 +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 6 +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#endif + +/**************************************************************************************** +* Gen6 pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 5 || MOTHERBOARD == 51 +#define KNOWN_BOARD 1 + +#ifndef __AVR_ATmega644P__ +#ifndef __AVR_ATmega1284P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif +#endif + +//x axis pins + #define X_STEP_PIN 15 + #define X_DIR_PIN 18 + #define X_ENABLE_PIN 19 + #define X_MIN_PIN 20 + #define X_MAX_PIN -1 + + //y axis pins + #define Y_STEP_PIN 23 + #define Y_DIR_PIN 22 + #define Y_ENABLE_PIN 24 + #define Y_MIN_PIN 25 + #define Y_MAX_PIN -1 + + //z axis pins + #define Z_STEP_PIN 27 + #define Z_DIR_PIN 28 + #define Z_ENABLE_PIN 29 + #define Z_MIN_PIN 30 + #define Z_MAX_PIN -1 + + //extruder pins + #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 + #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 + #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 + #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 + #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 + + + #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 + #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 + #define HEATER_1_PIN -1 + #define HEATER_2_PIN -1 + #if MOTHERBOARD == 5 + #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 + #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 + #else + #define HEATER_BED_PIN 1 //changed @ rkoeppl 20110410 + #define TEMP_BED_PIN 0 //changed @ rkoeppl 20110410 + #endif + #define SDPOWER -1 + #define SDSS 17 + #define LED_PIN -1 //changed @ rkoeppl 20110410 + #define FAN_PIN -1 //changed @ rkoeppl 20110410 + #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 + //our pin for debugging. + + #define DEBUG_PIN 0 + + //our RS485 pins + #define TX_ENABLE_PIN 12 + #define RX_ENABLE_PIN 13 + + +#endif + +/**************************************************************************************** +* Sanguinololu pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 62 +#undef MOTHERBOARD +#define MOTHERBOARD 6 +#define SANGUINOLOLU_V_1_2 +#endif +#if MOTHERBOARD == 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#ifndef __AVR_ATmega1284P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 1 +#define E0_DIR_PIN 0 + +#define LED_PIN -1 + +#define FAN_PIN 12 //12 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#ifdef SANGUINOLOLU_V_1_2 + +#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E0_ENABLE_PIN 14 + +#else + +#define HEATER_BED_PIN 14 // (bed) +#define X_ENABLE_PIN -1 +#define Y_ENABLE_PIN -1 +#define Z_ENABLE_PIN -1 +#define E0_ENABLE_PIN -1 + +#endif + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define SDPOWER -1 +#define SDSS 31 + +#endif + + +#if MOTHERBOARD == 7 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 22 +#define X_MAX_PIN 24 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 26 +#define Y_MAX_PIN 28 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN 32 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN 4 +#define TEMP_BED_PIN 10 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define HEATER_1_PIN 3 +#define TEMP_1_PIN 9 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN 49 +#define E1_DIR_PIN 47 +#define E1_ENABLE_PIN 51 + +#define SDPOWER -1 +#define SDSS 53 +#define LED_PIN 13 +#define FAN_PIN 7 +#define PS_ON_PIN 12 +#define KILL_PIN -1 +#define SUICIDE_PIN 54 //PIN that has to be turned on right after start, to keep power flowing. + +#ifdef ULTRA_LCD + + #ifdef NEWPANEL + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + #define LCD_PINS_RS 20 + #define LCD_PINS_ENABLE 17 + #define LCD_PINS_D4 16 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 5 + #define LCD_PINS_D7 6 + + //buttons are directly attached + #define BTN_EN1 40 + #define BTN_EN2 42 + #define BTN_ENC 19 //the click + + #define BLEN_C 2 + #define BLEN_B 1 + #define BLEN_A 0 + + #define SDCARDDETECT 38 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + #else //old style panel with shift register + //arduino pin witch triggers an piezzo beeper + #define BEEPER 18 + + //buttons are attached to a shift register + #define SHIFT_CLK 38 + #define SHIFT_LD 42 + #define SHIFT_OUT 40 + #define SHIFT_EN 17 + + #define LCD_PINS_RS 16 + #define LCD_PINS_ENABLE 5 + #define LCD_PINS_D4 6 + #define LCD_PINS_D5 21 + #define LCD_PINS_D6 20 + #define LCD_PINS_D7 19 + + //encoder rotation values + #define encrot0 0 + #define encrot1 2 + #define encrot2 3 + #define encrot3 1 + + #define SDCARDDETECT -1 + //bits in the shift register that carry the buttons for: + // left up center down right red + #define BL_LE 7 + #define BL_UP 6 + #define BL_MI 5 + #define BL_DW 4 + #define BL_RI 3 + #define BL_ST 2 + + #define BLEN_B 1 + #define BLEN_A 0 + #endif +#endif //ULTRA_LCD + +#endif + +#if MOTHERBOARD == 71 +#define KNOWN_BOARD +/***************************************************************** +* Ultimaker pin assignment (Old electronics) +******************************************************************/ + +#ifndef __AVR_ATmega1280__ + #ifndef __AVR_ATmega2560__ + #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. + #endif +#endif + +#define X_STEP_PIN 25 +#define X_DIR_PIN 23 +#define X_MIN_PIN 15 +#define X_MAX_PIN 14 +#define X_ENABLE_PIN 27 + +#define Y_STEP_PIN 31 +#define Y_DIR_PIN 33 +#define Y_MIN_PIN 17 +#define Y_MAX_PIN 16 +#define Y_ENABLE_PIN 29 + +#define Z_STEP_PIN 37 +#define Z_DIR_PIN 39 +#define Z_MIN_PIN 19 +#define Z_MAX_PIN 18 +#define Z_ENABLE_PIN 35 + +#define HEATER_BED_PIN -1 +#define TEMP_BED_PIN -1 + +#define HEATER_0_PIN 2 +#define TEMP_0_PIN 8 + +#define HEATER_1_PIN 1 +#define TEMP_1_PIN 1 + +#define HEATER_2_PIN -1 +#define TEMP_2_PIN -1 + +#define E0_STEP_PIN 43 +#define E0_DIR_PIN 45 +#define E0_ENABLE_PIN 41 + +#define E1_STEP_PIN -1 +#define E1_DIR_PIN -1 +#define E1_ENABLE_PIN -1 + +#define SDPOWER -1 +#define SDSS -1 +#define LED_PIN -1 +#define FAN_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define SUICIDE_PIN -1 //PIN that has to be turned on right after start, to keep power flowing. + +#define LCD_PINS_RS 24 +#define LCD_PINS_ENABLE 22 +#define LCD_PINS_D4 36 +#define LCD_PINS_D5 34 +#define LCD_PINS_D6 32 +#define LCD_PINS_D7 30 + +#endif + +/**************************************************************************************** +* Teensylu 0.7 pin assingments (ATMEGA90USB) +* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! +****************************************************************************************/ +#if MOTHERBOARD == 8 +#define MOTHERBOARD 8 +#define KNOWN_BOARD 1 + + +#define X_STEP_PIN 0 +#define X_DIR_PIN 1 +#define X_ENABLE_PIN 39 +#define X_MIN_PIN 13 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 2 +#define Y_DIR_PIN 3 +#define Y_ENABLE_PIN 38 +#define Y_MIN_PIN 14 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 4 +#define Z_DIR_PIN 5 +#define Z_ENABLE_PIN 23 +#define Z_MIN_PIN 15 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 6 +#define E0_DIR_PIN 7 +#define E0_ENABLE_PIN 19 + + + +#define HEATER_0_PIN 21 // Extruder +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 +#define HEATER_BED_PIN 20 // Bed +#define FAN_PIN 22 // Fan + +#define TEMP_0_PIN 7 // Extruder +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // Bed + +#define SDPOWER -1 +#define SDSS 8 +#define LED_PIN -1 +#define PS_ON_PIN -1 +#define KILL_PIN -1 +#define ALARM_PIN -1 + +#ifndef SDSUPPORT +// these pins are defined in the SD library if building with SD support + #define SCK_PIN 9 + #define MISO_PIN 11 + #define MOSI_PIN 10 +#endif +#endif + +/**************************************************************************************** +* Gen3+ pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 9 +#define MOTHERBOARD 6 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#ifndef __AVR_ATmega1284P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 18 +#define X_MIN_PIN 20 +#define X_MAX_PIN -1 + +#define Y_STEP_PIN 23 +#define Y_DIR_PIN 22 +#define Y_MIN_PIN 25 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 27 +#define Z_DIR_PIN 28 +#define Z_MIN_PIN 30 +#define Z_MAX_PIN -1 + +#define E_STEP_PIN 17 +#define E_DIR_PIN 21 + +#define LED_PIN -1 + +#define FAN_PIN -1 + +#define PS_ON_PIN 14 +#define KILL_PIN -1 + +#define HEATER_0_PIN 12 // (extruder) + +#define HEATER_1_PIN 16 // (bed) +#define X_ENABLE_PIN 19 +#define Y_ENABLE_PIN 24 +#define Z_ENABLE_PIN 29 +#define E_ENABLE_PIN 13 + +#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN 5 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define TEMP_2_PIN -1 +#define SDPOWER -1 +#define SDSS 4 +#define HEATER_2_PIN -1 + +#endif + + + + +#ifndef KNOWN_BOARD +#error Unknown MOTHERBOARD value in configuration.h +#endif + +//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! +#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN, +#if EXTRUDERS > 1 + #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, HEATER_1_PIN, +#else + #define _E1_PINS +#endif +#if EXTRUDERS > 2 + #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, HEATER_2_PIN, +#else + #define _E2_PINS +#endif + +#ifdef DISABLE_MAX_ENDSTOPS +#define X_MAX_PIN -1 +#define Y_MAX_PIN -1 +#define Z_MAX_PIN -1 +#endif + +#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ + HEATER_BED_PIN, FAN_PIN, \ + _E0_PINS _E1_PINS _E2_PINS \ + TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } +#endif diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 7a8c121db9..5da384f02a 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -437,13 +437,17 @@ void check_axes_activity() { } } else { - if (FanSpeed != 0) analogWrite(FAN_PIN,FanSpeed); // If buffer is empty use current fan speed + #if FAN_PIN > -1 + if (FanSpeed != 0) analogWrite(FAN_PIN,FanSpeed); // If buffer is empty use current fan speed + #endif } if((DISABLE_X) && (x_active == 0)) disable_x(); if((DISABLE_Y) && (y_active == 0)) disable_y(); if((DISABLE_Z) && (z_active == 0)) disable_z(); if((DISABLE_E) && (e_active == 0)) { disable_e0();disable_e1();disable_e2(); } - if((FanSpeed == 0) && (fan_speed ==0)) analogWrite(FAN_PIN, 0); + #if FAN_PIN > -1 + if((FanSpeed == 0) && (fan_speed ==0)) analogWrite(FAN_PIN, 0); + #endif if (FanSpeed != 0 && tail_fan_speed !=0) { analogWrite(FAN_PIN,tail_fan_speed); } diff --git a/Marlin/speed_lookuptable.h b/Marlin/speed_lookuptable.h index 77f766188d..670e744c73 100644 --- a/Marlin/speed_lookuptable.h +++ b/Marlin/speed_lookuptable.h @@ -3,6 +3,8 @@ #include "Marlin.h" +#if F_CPU == 16000000 + const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\ { 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, { 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32}, @@ -73,4 +75,78 @@ const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\ { 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3} }; +#else + +const uint16_t speed_lookuptable_fast[256][2] PROGMEM = { + {62500, 54055}, {8445, 3917}, {4528, 1434}, {3094, 745}, {2349, 456}, {1893, 307}, {1586, 222}, {1364, 167}, + {1197, 131}, {1066, 105}, {961, 86}, {875, 72}, {803, 61}, {742, 53}, {689, 45}, {644, 40}, + {604, 35}, {569, 32}, {537, 28}, {509, 25}, {484, 23}, {461, 21}, {440, 19}, {421, 17}, + {404, 16}, {388, 15}, {373, 14}, {359, 13}, {346, 12}, {334, 11}, {323, 10}, {313, 10}, + {303, 9}, {294, 9}, {285, 8}, {277, 7}, {270, 8}, {262, 7}, {255, 6}, {249, 6}, + {243, 6}, {237, 6}, {231, 5}, {226, 5}, {221, 5}, {216, 5}, {211, 4}, {207, 5}, + {202, 4}, {198, 4}, {194, 4}, {190, 3}, {187, 4}, {183, 3}, {180, 3}, {177, 4}, + {173, 3}, {170, 3}, {167, 2}, {165, 3}, {162, 3}, {159, 2}, {157, 3}, {154, 2}, + {152, 3}, {149, 2}, {147, 2}, {145, 2}, {143, 2}, {141, 2}, {139, 2}, {137, 2}, + {135, 2}, {133, 2}, {131, 2}, {129, 1}, {128, 2}, {126, 2}, {124, 1}, {123, 2}, + {121, 1}, {120, 2}, {118, 1}, {117, 1}, {116, 2}, {114, 1}, {113, 1}, {112, 2}, + {110, 1}, {109, 1}, {108, 1}, {107, 2}, {105, 1}, {104, 1}, {103, 1}, {102, 1}, + {101, 1}, {100, 1}, {99, 1}, {98, 1}, {97, 1}, {96, 1}, {95, 1}, {94, 1}, + {93, 1}, {92, 1}, {91, 0}, {91, 1}, {90, 1}, {89, 1}, {88, 1}, {87, 0}, + {87, 1}, {86, 1}, {85, 1}, {84, 0}, {84, 1}, {83, 1}, {82, 1}, {81, 0}, + {81, 1}, {80, 1}, {79, 0}, {79, 1}, {78, 0}, {78, 1}, {77, 1}, {76, 0}, + {76, 1}, {75, 0}, {75, 1}, {74, 1}, {73, 0}, {73, 1}, {72, 0}, {72, 1}, + {71, 0}, {71, 1}, {70, 0}, {70, 1}, {69, 0}, {69, 1}, {68, 0}, {68, 1}, + {67, 0}, {67, 1}, {66, 0}, {66, 1}, {65, 0}, {65, 0}, {65, 1}, {64, 0}, + {64, 1}, {63, 0}, {63, 1}, {62, 0}, {62, 0}, {62, 1}, {61, 0}, {61, 1}, + {60, 0}, {60, 0}, {60, 1}, {59, 0}, {59, 0}, {59, 1}, {58, 0}, {58, 0}, + {58, 1}, {57, 0}, {57, 0}, {57, 1}, {56, 0}, {56, 0}, {56, 1}, {55, 0}, + {55, 0}, {55, 1}, {54, 0}, {54, 0}, {54, 1}, {53, 0}, {53, 0}, {53, 0}, + {53, 1}, {52, 0}, {52, 0}, {52, 1}, {51, 0}, {51, 0}, {51, 0}, {51, 1}, + {50, 0}, {50, 0}, {50, 0}, {50, 1}, {49, 0}, {49, 0}, {49, 0}, {49, 1}, + {48, 0}, {48, 0}, {48, 0}, {48, 1}, {47, 0}, {47, 0}, {47, 0}, {47, 1}, + {46, 0}, {46, 0}, {46, 0}, {46, 0}, {46, 1}, {45, 0}, {45, 0}, {45, 0}, + {45, 1}, {44, 0}, {44, 0}, {44, 0}, {44, 0}, {44, 1}, {43, 0}, {43, 0}, + {43, 0}, {43, 0}, {43, 1}, {42, 0}, {42, 0}, {42, 0}, {42, 0}, {42, 0}, + {42, 1}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 1}, {40, 0}, + {40, 0}, {40, 0}, {40, 0}, {40, 1}, {39, 0}, {39, 0}, {39, 0}, {39, 0}, + {39, 0}, {39, 0}, {39, 1}, {38, 0}, {38, 0}, {38, 0}, {38, 0}, {38, 0}, +}; + +const uint16_t speed_lookuptable_slow[256][2] PROGMEM = { + {62500, 10417}, {52083, 7441}, {44642, 5580}, {39062, 4340}, {34722, 3472}, {31250, 2841}, {28409, 2368}, {26041, 2003}, + {24038, 1717}, {22321, 1488}, {20833, 1302}, {19531, 1149}, {18382, 1021}, {17361, 914}, {16447, 822}, {15625, 745}, + {14880, 676}, {14204, 618}, {13586, 566}, {13020, 520}, {12500, 481}, {12019, 445}, {11574, 414}, {11160, 385}, + {10775, 359}, {10416, 336}, {10080, 315}, {9765, 296}, {9469, 278}, {9191, 263}, {8928, 248}, {8680, 235}, + {8445, 222}, {8223, 211}, {8012, 200}, {7812, 191}, {7621, 181}, {7440, 173}, {7267, 165}, {7102, 158}, + {6944, 151}, {6793, 145}, {6648, 138}, {6510, 133}, {6377, 127}, {6250, 123}, {6127, 118}, {6009, 113}, + {5896, 109}, {5787, 106}, {5681, 101}, {5580, 98}, {5482, 95}, {5387, 91}, {5296, 88}, {5208, 86}, + {5122, 82}, {5040, 80}, {4960, 78}, {4882, 75}, {4807, 73}, {4734, 70}, {4664, 69}, {4595, 67}, + {4528, 64}, {4464, 63}, {4401, 61}, {4340, 60}, {4280, 58}, {4222, 56}, {4166, 55}, {4111, 53}, + {4058, 52}, {4006, 51}, {3955, 49}, {3906, 48}, {3858, 48}, {3810, 45}, {3765, 45}, {3720, 44}, + {3676, 43}, {3633, 42}, {3591, 40}, {3551, 40}, {3511, 39}, {3472, 38}, {3434, 38}, {3396, 36}, + {3360, 36}, {3324, 35}, {3289, 34}, {3255, 34}, {3221, 33}, {3188, 32}, {3156, 31}, {3125, 31}, + {3094, 31}, {3063, 30}, {3033, 29}, {3004, 28}, {2976, 28}, {2948, 28}, {2920, 27}, {2893, 27}, + {2866, 26}, {2840, 25}, {2815, 25}, {2790, 25}, {2765, 24}, {2741, 24}, {2717, 24}, {2693, 23}, + {2670, 22}, {2648, 22}, {2626, 22}, {2604, 22}, {2582, 21}, {2561, 21}, {2540, 20}, {2520, 20}, + {2500, 20}, {2480, 20}, {2460, 19}, {2441, 19}, {2422, 19}, {2403, 18}, {2385, 18}, {2367, 18}, + {2349, 17}, {2332, 18}, {2314, 17}, {2297, 16}, {2281, 17}, {2264, 16}, {2248, 16}, {2232, 16}, + {2216, 16}, {2200, 15}, {2185, 15}, {2170, 15}, {2155, 15}, {2140, 15}, {2125, 14}, {2111, 14}, + {2097, 14}, {2083, 14}, {2069, 14}, {2055, 13}, {2042, 13}, {2029, 13}, {2016, 13}, {2003, 13}, + {1990, 13}, {1977, 12}, {1965, 12}, {1953, 13}, {1940, 11}, {1929, 12}, {1917, 12}, {1905, 12}, + {1893, 11}, {1882, 11}, {1871, 11}, {1860, 11}, {1849, 11}, {1838, 11}, {1827, 11}, {1816, 10}, + {1806, 11}, {1795, 10}, {1785, 10}, {1775, 10}, {1765, 10}, {1755, 10}, {1745, 9}, {1736, 10}, + {1726, 9}, {1717, 10}, {1707, 9}, {1698, 9}, {1689, 9}, {1680, 9}, {1671, 9}, {1662, 9}, + {1653, 9}, {1644, 8}, {1636, 9}, {1627, 8}, {1619, 9}, {1610, 8}, {1602, 8}, {1594, 8}, + {1586, 8}, {1578, 8}, {1570, 8}, {1562, 8}, {1554, 7}, {1547, 8}, {1539, 8}, {1531, 7}, + {1524, 8}, {1516, 7}, {1509, 7}, {1502, 7}, {1495, 7}, {1488, 7}, {1481, 7}, {1474, 7}, + {1467, 7}, {1460, 7}, {1453, 7}, {1446, 6}, {1440, 7}, {1433, 7}, {1426, 6}, {1420, 6}, + {1414, 7}, {1407, 6}, {1401, 6}, {1395, 7}, {1388, 6}, {1382, 6}, {1376, 6}, {1370, 6}, + {1364, 6}, {1358, 6}, {1352, 6}, {1346, 5}, {1341, 6}, {1335, 6}, {1329, 5}, {1324, 6}, + {1318, 5}, {1313, 6}, {1307, 5}, {1302, 6}, {1296, 5}, {1291, 5}, {1286, 6}, {1280, 5}, + {1275, 5}, {1270, 5}, {1265, 5}, {1260, 5}, {1255, 5}, {1250, 5}, {1245, 5}, {1240, 5}, + {1235, 5}, {1230, 5}, {1225, 5}, {1220, 5}, {1215, 4}, {1211, 5}, {1206, 5}, {1201, 5}, +}; + +#endif + #endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 55c09902bc..e9b42f45de 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -236,8 +236,8 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { step_loops = 1; } - if(step_rate < 32) step_rate = 32; - step_rate -= 32; // Correct for minimal speed + if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000); + step_rate -= (F_CPU/500000); // Correct for minimal speed if(step_rate >= (8*256)){ // higher step rate unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; unsigned char tmp_step_rate = (step_rate & 0x00ff); @@ -714,23 +714,33 @@ void st_init() //Initialize Step Pins #if (X_STEP_PIN > -1) SET_OUTPUT(X_STEP_PIN); + if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); #endif #if (Y_STEP_PIN > -1) SET_OUTPUT(Y_STEP_PIN); + if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); #endif #if (Z_STEP_PIN > -1) SET_OUTPUT(Z_STEP_PIN); + if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); #endif #if (E0_STEP_PIN > -1) SET_OUTPUT(E0_STEP_PIN); + if(!E_ENABLE_ON) WRITE(E0_ENABLE_PIN,HIGH); #endif #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) SET_OUTPUT(E1_STEP_PIN); + if(!E_ENABLE_ON) WRITE(E1_ENABLE_PIN,HIGH); #endif #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) SET_OUTPUT(E2_STEP_PIN); + if(!E_ENABLE_ON) WRITE(E2_ENABLE_PIN,HIGH); #endif + #ifdef CONTROLLERFAN_PIN + SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan + #endif + // waveform generation = 0100 = CTC TCCR1B &= ~(1<>1; + + unsigned long temp_millis = millis(); + unsigned long t1=temp_millis; + unsigned long t2=temp_millis; + long t_high; + long t_low; + + long bias=127; + long d = 127; + float Ku, Tu; + float Kp, Ki, Kd; + float max, min; + SERIAL_ECHOLN("PID Autotune start"); + + for(;;) { + + if(temp_meas_ready == true) { // temp sample ready + CRITICAL_SECTION_START; + temp_meas_ready = false; + CRITICAL_SECTION_END; + input = analog2temp(current_raw[0], 0); + + max=max(max,input); + min=min(min,input); + if(heating == true && input > temp) { + if(millis() - t2 > 5000) { + heating=false; + soft_pwm[0] = (bias - d) >> 1; + t1=millis(); + t_high=t1 - t2; + max=temp; + } + } + if(heating == false && input < temp) { + if(millis() - t1 > 5000) { + heating=true; + t2=millis(); + t_low=t2 - t1; + if(cycles > 0) { + bias += (d*(t_high - t_low))/(t_low + t_high); + bias = constrain(bias, 20 ,235); + if(bias > 127) d = 254 - bias; + else d = bias; + + SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias); + SERIAL_PROTOCOLPGM(" d: "); SERIAL_PROTOCOL(d); + SERIAL_PROTOCOLPGM(" min: "); SERIAL_PROTOCOL(min); + SERIAL_PROTOCOLPGM(" max: "); SERIAL_PROTOCOLLN(max); + if(cycles > 2) { + Ku = (4.0*d)/(3.14159*(max-min)/2.0); + Tu = ((float)(t_low + t_high)/1000.0); + SERIAL_PROTOCOLPGM(" Ku: "); SERIAL_PROTOCOL(Ku); + SERIAL_PROTOCOLPGM(" Tu: "); SERIAL_PROTOCOLLN(Tu); + Kp = 0.6*Ku; + Ki = 2*Kp/Tu; + Kd = Kp*Tu/8; + SERIAL_PROTOCOLLNPGM(" Clasic PID ") + SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); + SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); + SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); + Kp = 0.33*Ku; + Ki = Kp/Tu; + Kd = Kp*Tu/3; + SERIAL_PROTOCOLLNPGM(" Some overshoot ") + SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); + SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); + SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); + Kp = 0.2*Ku; + Ki = 2*Kp/Tu; + Kd = Kp*Tu/3; + SERIAL_PROTOCOLLNPGM(" No overshoot ") + SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); + SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); + SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); + } + } + soft_pwm[0] = (bias + d) >> 1; + cycles++; + min=temp; + } + } + } + if(input > (temp + 20)) { + SERIAL_PROTOCOLLNPGM("PID Autotune failed !, Temperature to high"); + return; + } + if(millis() - temp_millis > 2000) { + temp_millis = millis(); + SERIAL_PROTOCOLPGM("ok T:"); + SERIAL_PROTOCOL(degHotend(0)); + SERIAL_PROTOCOLPGM(" @:"); + SERIAL_PROTOCOLLN(getHeaterPower(0)); + } + LCD_STATUS; + } +} + void updatePID() { #ifdef PIDTEMP diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 1ff821cdd9..1cfdae0243 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -154,10 +154,13 @@ FORCE_INLINE void autotempShutdown(){ if(autotemp_enabled) { autotemp_enabled=false; - if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min) - setTargetHotend(0,ACTIVE_EXTRUDER); + if(degTargetHotend(active_extruder)>autotemp_min) + setTargetHotend(0,active_extruder); } #endif } + +void PID_autotune(float temp); + #endif diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 47dc2d5cc9..c1214b59f0 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -315,19 +315,18 @@ void MainMenu::showStatus() static int olddegHotEnd0=-1; static int oldtargetHotEnd0=-1; //force_lcd_update=true; - if(force_lcd_update||feedmultiplychanged) //initial display of content + if(force_lcd_update) //initial display of content { - feedmultiplychanged=false; encoderpos=feedmultiply; clear(); - lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 "); + lcd.setCursor(0,0);lcdprintPGM("\002---/---\001 "); #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcdprintPGM("B123/567\001 "); + lcd.setCursor(10,0);lcdprintPGM("B---/---\001 "); #endif } int tHotEnd0=intround(degHotend0()); - if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often. + if((tHotEnd0!=olddegHotEnd0)||force_lcd_update) { lcd.setCursor(1,0); lcd.print(ftostr3(tHotEnd0)); @@ -379,8 +378,15 @@ void MainMenu::showStatus() lcdprintPGM("Z:");lcd.print(ftostr52(current_position[2])); oldzpos=currentz; } + static int oldfeedmultiply=0; int curfeedmultiply=feedmultiply; + + if(feedmultiplychanged == true) { + feedmultiplychanged = false; + encoderpos = curfeedmultiply; + } + if(encoderpos!=curfeedmultiply||force_lcd_update) { curfeedmultiply=encoderpos; @@ -391,12 +397,14 @@ void MainMenu::showStatus() feedmultiply=curfeedmultiply; encoderpos=curfeedmultiply; } + if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) { oldfeedmultiply=curfeedmultiply; lcd.setCursor(0,2); lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% "); } + if(messagetext[0]!='\0') { lcd.setCursor(0,LCD_HEIGHT-1); @@ -404,10 +412,9 @@ void MainMenu::showStatus() uint8_t n=strlen(messagetext); for(int8_t i=0;i -1 + analogWrite(FAN_PIN, PLA_PREHEAT_FAN_SPEED); + #endif + beepshort(); ); break; case ItemP_preheat_abs: - MENUITEM( lcdprintPGM(MSG_PREHEAT_ABS) , BLOCK;setTargetHotend0(ABS_PREHEAT_HOTEND_TEMP);setTargetBed(ABS_PREHEAT_HPB_TEMP); analogWrite(FAN_PIN, ABS_PREHEAT_FAN_SPEED); beepshort(); ) ; + MENUITEM( lcdprintPGM(MSG_PREHEAT_ABS) , BLOCK;setTargetHotend0(ABS_PREHEAT_HOTEND_TEMP);setTargetBed(ABS_PREHEAT_HPB_TEMP); + #if FAN_PIN > -1 + analogWrite(FAN_PIN, ABS_PREHEAT_FAN_SPEED); + #endif + beepshort(); ); break; case ItemP_cooldown: MENUITEM( lcdprintPGM(MSG_COOLDOWN) , BLOCK;setTargetHotend0(0);setTargetBed(0);beepshort(); ) ; @@ -518,6 +534,7 @@ void MainMenu::showPrepare() line++; } updateActiveLines(ItemP_move,encoderpos); +#endif } enum { @@ -1966,6 +1983,7 @@ void MainMenu::showSD() #endif } + enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file }; void MainMenu::showMainMenu() { From e70f1e58718b968eb60c3c8eba195e1267ca348d Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Sun, 18 Mar 2012 21:48:13 +0000 Subject: [PATCH 212/228] removed temp file --- Marlin/pins.h~ | 965 ------------------------------------------------- 1 file changed, 965 deletions(-) delete mode 100644 Marlin/pins.h~ diff --git a/Marlin/pins.h~ b/Marlin/pins.h~ deleted file mode 100644 index 034db11d93..0000000000 --- a/Marlin/pins.h~ +++ /dev/null @@ -1,965 +0,0 @@ -#ifndef PINS_H -#define PINS_H - -#if MOTHERBOARD == 99 -#define KNOWN_BOARD 1 - -#define X_STEP_PIN 2 -#define X_DIR_PIN 3 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN -1 -#define X_MAX_PIN 16 - -#define Y_STEP_PIN 5 -#define Y_DIR_PIN 6 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 67 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 62 -#define Z_DIR_PIN 63 -#define Z_ENABLE_PIN -1 -#define Z_MIN_PIN 59 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 65 -#define E0_DIR_PIN 66 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN 9 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_2_PIN -1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 10 - -#endif /* 99 */ - -/**************************************************************************************** -* Gen7 v1.1, v1.2, v1.3, v1.4 pin assignment -* -****************************************************************************************/ - - -#if MOTHERBOARD == 13 -#define MOTHERBOARD 11 -#define GEN7_VERSION 14 // v1.4 -#endif - -#if MOTHERBOARD == 12 -#define MOTHERBOARD 11 -#define GEN7_VERSION 13 // v1.3 -#endif - -#if MOTHERBOARD == 11 -#define KNOWN_BOARD - -#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega644__) && !defined(__AVR_ATmega1284P__) -#error Oops! Make sure you have 'Gen7' selected from the 'Tools -> Boards' menu. - -#endif - -#ifndef GEN7_VERSION -#define GEN7_VERSION 12 // v1.x -#endif - -//x axis pins -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 7 -#define X_MAX_PIN -1 - -//y axis pins -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_ENABLE_PIN 24 -#define Y_MIN_PIN 5 -#define Y_MAX_PIN -1 - -//z axis pins -#define Z_STEP_PIN 26 -#define Z_DIR_PIN 25 -#define Z_ENABLE_PIN 24 -#define Z_MIN_PIN 1 -#define Z_MAX_PIN 0 - -//extruder pins -#define E0_STEP_PIN 28 -#define E0_DIR_PIN 27 -#define E0_ENABLE_PIN 24 - -#define TEMP_0_PIN 1 -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 2 - -#define HEATER_0_PIN 4 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define HEATER_BED_PIN 3 - - -#define SDPOWER -1 -#define SDSS -1 // SCL pin of I2C header -#define LED_PIN -1 - -#if (GEN7_VERSION >= 13) -// Gen7 v1.3 removed the fan pin -#define FAN_PIN -1 -#else -#define FAN_PIN 31 -#endif -#define PS_ON_PIN 15 - -#if (GEN7_VERSION < 14) -// Gen 1.3 and earlier supplied thermistor power via PS_ON -// Need to ignore the bad thermistor readings on those units -#define BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE -#endif - -//our pin for debugging. -#define DEBUG_PIN 0 - -//our RS485 pins -#define TX_ENABLE_PIN 12 -#define RX_ENABLE_PIN 13 - -#endif - -/******************************************************************************* -********* -* Gen7 Alfons3 pin assignment -* -******************************************************************************** -********/ -/* These Pins are assigned for the modified GEN7 Board from Alfons3 Please review the pins and adjust it for your needs*/ - -#if MOTHERBOARD == 10 -#define KNOWN_BOARD - -#if !defined(__AVR_ATmega644P__) && !defined(__AVR_ATmega644__) && !defined(__AVR_ATmega1284P__) - #error Oops! Make sure you have 'Gen7' selected from the 'Tools -> Boards' menu. - -#endif - -//x axis pins - #define X_STEP_PIN 21 //different from stanard GEN7 - #define X_DIR_PIN 20 //different from stanard GEN7 - #define X_ENABLE_PIN 24 - #define X_MIN_PIN 0 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 1 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 26 - #define Z_DIR_PIN 25 - #define Z_ENABLE_PIN 24 - #define Z_MIN_PIN 2 - #define Z_MAX_PIN -1 - - //extruder pins - #define E0_STEP_PIN 28 - #define E0_DIR_PIN 27 - #define E0_ENABLE_PIN 24 - - #define TEMP_0_PIN 2 - #define TEMP_1_PIN -1 - #define TEMP_2_PIN -1 - #define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) - - #define HEATER_0_PIN 4 - #define HEATER_1_PIN -1 - #define HEATER_2_PIN -1 - #define HEATER_BED_PIN 3 // (bed) - - #define SDPOWER -1 - #define SDSS 31 // SCL pin of I2C header || CS Pin for SD Card support - #define LED_PIN -1 - - #define FAN_PIN -1 - #define PS_ON_PIN 19 - //our pin for debugging. - - #define DEBUG_PIN -1 - - //our RS485 pins - //#define TX_ENABLE_PIN 12 - //#define RX_ENABLE_PIN 13 - - #define BEEPER -1 - #define SDCARDDETECT -1 - #define SUICIDE_PIN -1 //has to be defined; otherwise Power_off doesn't work - - //Pins for 4bit LCD Support - #define LCD_PINS_RS 18 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 15 - #define LCD_PINS_D6 13 - #define LCD_PINS_D7 14 - - //buttons are directly attached - #define BTN_EN1 11 - #define BTN_EN2 10 - #define BTN_ENC 12 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 -#endif - -/**************************************************************************************** -* Arduino Mega pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 3 || MOTHERBOARD == 33 || MOTHERBOARD == 34 -#define KNOWN_BOARD 1 - -//////////////////FIX THIS////////////// -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -// uncomment one of the following lines for RAMPS v1.3 or v1.0, comment both for v1.2 or 1.1 -// #define RAMPS_V_1_3 -// #define RAMPS_V_1_0 - -#if MOTHERBOARD == 33 || MOTHERBOARD == 34 - -#define X_STEP_PIN 54 -#define X_DIR_PIN 55 -#define X_ENABLE_PIN 38 -#define X_MIN_PIN 3 -#define X_MAX_PIN 2 //2 //Max endstops default to disabled "-1", set to commented value to enable. - -#define Y_STEP_PIN 60 -#define Y_DIR_PIN 61 -#define Y_ENABLE_PIN 56 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN 15 //15 - -#define Z_STEP_PIN 46 -#define Z_DIR_PIN 48 -#define Z_ENABLE_PIN 62 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN 19 - -#define E0_STEP_PIN 26 -#define E0_DIR_PIN 28 -#define E0_ENABLE_PIN 24 - -#define E1_STEP_PIN 36 -#define E1_DIR_PIN 34 -#define E1_ENABLE_PIN 30 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 - -#if MOTHERBOARD == 33 -#define FAN_PIN 9 // (Sprinter config) -#else -#define FAN_PIN 4 // IO pin. Buffer needed -#endif -#define PS_ON_PIN 12 -#define KILL_PIN -1 - -#define HEATER_0_PIN 10 // EXTRUDER 1 -#if MOTHERBOARD == 33 -#define HEATER_1_PIN -1 -#else -#define HEATER_1_PIN 9 // EXTRUDER 2 (FAN On Sprinter) -#endif -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 13 // ANALOG NUMBERING -#define TEMP_1_PIN 15 // ANALOG NUMBERING -#define TEMP_2_PIN -1 // ANALOG NUMBERING -#define HEATER_BED_PIN 8 // BED -#define TEMP_BED_PIN 14 // ANALOG NUMBERING - -#ifdef ULTRA_LCD - - #ifdef NEWPANEL - //arduino pin which triggers an piezzo beeper - #define BEEPER 33 // Beeper on AUX-4 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 23 - #define LCD_PINS_D5 25 - #define LCD_PINS_D6 27 - #define LCD_PINS_D7 29 - - //buttons are directly attached using AUX-2 - #define BTN_EN1 37 - #define BTN_EN2 35 - #define BTN_ENC 31 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT -1 // Ramps does not use this port - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - #else //old style panel with shift register - //arduino pin witch triggers an piezzo beeper - #define BEEPER 33 No Beeper added - - //buttons are attached to a shift register - // Not wired this yet - //#define SHIFT_CLK 38 - //#define SHIFT_LD 42 - //#define SHIFT_OUT 40 - //#define SHIFT_EN 17 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 23 - #define LCD_PINS_D5 25 - #define LCD_PINS_D6 27 - #define LCD_PINS_D7 29 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - - //bits in the shift register that carry the buttons for: - // left up center down right red - #define BL_LE 7 - #define BL_UP 6 - #define BL_MI 5 - #define BL_DW 4 - #define BL_RI 3 - #define BL_ST 2 - - #define BLEN_B 1 - #define BLEN_A 0 - #endif -#endif //ULTRA_LCD - -#else // RAMPS_V_1_1 or RAMPS_V_1_2 as default - -#define X_STEP_PIN 26 -#define X_DIR_PIN 28 -#define X_ENABLE_PIN 24 -#define X_MIN_PIN 3 -#define X_MAX_PIN -1 //2 - -#define Y_STEP_PIN 38 -#define Y_DIR_PIN 40 -#define Y_ENABLE_PIN 36 -#define Y_MIN_PIN 16 -#define Y_MAX_PIN -1 //17 - -#define Z_STEP_PIN 44 -#define Z_DIR_PIN 46 -#define Z_ENABLE_PIN 42 -#define Z_MIN_PIN 18 -#define Z_MAX_PIN -1 //19 - -#define E0_STEP_PIN 32 -#define E0_DIR_PIN 34 -#define E0_ENABLE_PIN 30 - -#define SDPOWER 48 -#define SDSS 53 -#define LED_PIN 13 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#ifdef RAMPS_V_1_0 // RAMPS_V_1_0 - #define HEATER_0_PIN 12 // RAMPS 1.0 - #define HEATER_BED_PIN -1 // RAMPS 1.0 - #define FAN_PIN 11 // RAMPS 1.0 -#else // RAMPS_V_1_1 or RAMPS_V_1_2 - #define HEATER_0_PIN 10 // RAMPS 1.1 - #define HEATER_BED_PIN 8 // RAMPS 1.1 - #define FAN_PIN 9 // RAMPS 1.1 -#endif -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 2 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 1 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#endif - -// SPI for Max6675 Thermocouple - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define MAX_SCK_PIN 52 - #define MAX_MISO_PIN 50 - #define MAX_MOSI_PIN 51 - #define MAX6675_SS 53 -#else - #define MAX6675_SS 49 -#endif - -#endif - -/**************************************************************************************** -* Duemilanove w/ ATMega328P pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 4 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega328P__ -#error Oops! Make sure you have 'Arduino Duemilanove w/ ATMega328' selected from the 'Tools -> Boards' menu. -#endif - -#define X_STEP_PIN 19 -#define X_DIR_PIN 18 -#define X_ENABLE_PIN -1 -#define X_MIN_PIN 17 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 10 -#define Y_DIR_PIN 7 -#define Y_ENABLE_PIN -1 -#define Y_MIN_PIN 8 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 13 -#define Z_DIR_PIN 3 -#define Z_ENABLE_PIN 2 -#define Z_MIN_PIN 4 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 11 -#define E0_DIR_PIN 12 -#define E0_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN 5 -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 6 -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#endif - -/**************************************************************************************** -* Gen6 pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 5 || MOTHERBOARD == 51 -#define KNOWN_BOARD 1 - -#ifndef __AVR_ATmega644P__ -#ifndef __AVR_ATmega1284P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif -#endif - -//x axis pins - #define X_STEP_PIN 15 - #define X_DIR_PIN 18 - #define X_ENABLE_PIN 19 - #define X_MIN_PIN 20 - #define X_MAX_PIN -1 - - //y axis pins - #define Y_STEP_PIN 23 - #define Y_DIR_PIN 22 - #define Y_ENABLE_PIN 24 - #define Y_MIN_PIN 25 - #define Y_MAX_PIN -1 - - //z axis pins - #define Z_STEP_PIN 27 - #define Z_DIR_PIN 28 - #define Z_ENABLE_PIN 29 - #define Z_MIN_PIN 30 - #define Z_MAX_PIN -1 - - //extruder pins - #define E0_STEP_PIN 4 //Edited @ EJE Electronics 20100715 - #define E0_DIR_PIN 2 //Edited @ EJE Electronics 20100715 - #define E0_ENABLE_PIN 3 //Added @ EJE Electronics 20100715 - #define TEMP_0_PIN 5 //changed @ rkoeppl 20110410 - #define TEMP_1_PIN -1 //changed @ rkoeppl 20110410 - - - #define TEMP_2_PIN -1 //changed @ rkoeppl 20110410 - #define HEATER_0_PIN 14 //changed @ rkoeppl 20110410 - #define HEATER_1_PIN -1 - #define HEATER_2_PIN -1 - #if MOTHERBOARD == 5 - #define HEATER_BED_PIN -1 //changed @ rkoeppl 20110410 - #define TEMP_BED_PIN -1 //changed @ rkoeppl 20110410 - #else - #define HEATER_BED_PIN 1 //changed @ rkoeppl 20110410 - #define TEMP_BED_PIN 0 //changed @ rkoeppl 20110410 - #endif - #define SDPOWER -1 - #define SDSS 17 - #define LED_PIN -1 //changed @ rkoeppl 20110410 - #define FAN_PIN -1 //changed @ rkoeppl 20110410 - #define PS_ON_PIN -1 //changed @ rkoeppl 20110410 - //our pin for debugging. - - #define DEBUG_PIN 0 - - //our RS485 pins - #define TX_ENABLE_PIN 12 - #define RX_ENABLE_PIN 13 - - -#endif - -/**************************************************************************************** -* Sanguinololu pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 62 -#undef MOTHERBOARD -#define MOTHERBOARD 6 -#define SANGUINOLOLU_V_1_2 -#endif -#if MOTHERBOARD == 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#ifndef __AVR_ATmega1284P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 21 -#define X_MIN_PIN 18 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 22 -#define Y_DIR_PIN 23 -#define Y_MIN_PIN 19 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 3 -#define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 1 -#define E0_DIR_PIN 0 - -#define LED_PIN -1 - -#define FAN_PIN 12 //12 - -#define PS_ON_PIN -1 -#define KILL_PIN -1 - -#define HEATER_0_PIN 13 // (extruder) -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 - -#ifdef SANGUINOLOLU_V_1_2 - -#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET -#define X_ENABLE_PIN 14 -#define Y_ENABLE_PIN 14 -#define Z_ENABLE_PIN 26 -#define E0_ENABLE_PIN 14 - -#else - -#define HEATER_BED_PIN 14 // (bed) -#define X_ENABLE_PIN -1 -#define Y_ENABLE_PIN -1 -#define Z_ENABLE_PIN -1 -#define E0_ENABLE_PIN -1 - -#endif - -#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define SDPOWER -1 -#define SDSS 31 - -#endif - - -#if MOTHERBOARD == 7 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 22 -#define X_MAX_PIN 24 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 26 -#define Y_MAX_PIN 28 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN 32 -#define Z_ENABLE_PIN 35 - -#define HEATER_BED_PIN 4 -#define TEMP_BED_PIN 10 - -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define HEATER_1_PIN 3 -#define TEMP_1_PIN 9 - -#define HEATER_2_PIN -1 -#define TEMP_2_PIN -1 - -#define E0_STEP_PIN 43 -#define E0_DIR_PIN 45 -#define E0_ENABLE_PIN 41 - -#define E1_STEP_PIN 49 -#define E1_DIR_PIN 47 -#define E1_ENABLE_PIN 51 - -#define SDPOWER -1 -#define SDSS 53 -#define LED_PIN 13 -#define FAN_PIN 7 -#define PS_ON_PIN 12 -#define KILL_PIN -1 -#define SUICIDE_PIN 54 //PIN that has to be turned on right after start, to keep power flowing. - -#ifdef ULTRA_LCD - - #ifdef NEWPANEL - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - #define LCD_PINS_RS 20 - #define LCD_PINS_ENABLE 17 - #define LCD_PINS_D4 16 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 5 - #define LCD_PINS_D7 6 - - //buttons are directly attached - #define BTN_EN1 40 - #define BTN_EN2 42 - #define BTN_ENC 19 //the click - - #define BLEN_C 2 - #define BLEN_B 1 - #define BLEN_A 0 - - #define SDCARDDETECT 38 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - #else //old style panel with shift register - //arduino pin witch triggers an piezzo beeper - #define BEEPER 18 - - //buttons are attached to a shift register - #define SHIFT_CLK 38 - #define SHIFT_LD 42 - #define SHIFT_OUT 40 - #define SHIFT_EN 17 - - #define LCD_PINS_RS 16 - #define LCD_PINS_ENABLE 5 - #define LCD_PINS_D4 6 - #define LCD_PINS_D5 21 - #define LCD_PINS_D6 20 - #define LCD_PINS_D7 19 - - //encoder rotation values - #define encrot0 0 - #define encrot1 2 - #define encrot2 3 - #define encrot3 1 - - #define SDCARDDETECT -1 - //bits in the shift register that carry the buttons for: - // left up center down right red - #define BL_LE 7 - #define BL_UP 6 - #define BL_MI 5 - #define BL_DW 4 - #define BL_RI 3 - #define BL_ST 2 - - #define BLEN_B 1 - #define BLEN_A 0 - #endif -#endif //ULTRA_LCD - -#endif - -#if MOTHERBOARD == 71 -#define KNOWN_BOARD -/***************************************************************** -* Ultimaker pin assignment (Old electronics) -******************************************************************/ - -#ifndef __AVR_ATmega1280__ - #ifndef __AVR_ATmega2560__ - #error Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu. - #endif -#endif - -#define X_STEP_PIN 25 -#define X_DIR_PIN 23 -#define X_MIN_PIN 15 -#define X_MAX_PIN 14 -#define X_ENABLE_PIN 27 - -#define Y_STEP_PIN 31 -#define Y_DIR_PIN 33 -#define Y_MIN_PIN 17 -#define Y_MAX_PIN 16 -#define Y_ENABLE_PIN 29 - -#define Z_STEP_PIN 37 -#define Z_DIR_PIN 39 -#define Z_MIN_PIN 19 -#define Z_MAX_PIN 18 -#define Z_ENABLE_PIN 35 - -#define HEATER_BED_PIN -1 -#define TEMP_BED_PIN -1 - -#define HEATER_0_PIN 2 -#define TEMP_0_PIN 8 - -#define HEATER_1_PIN 1 -#define TEMP_1_PIN 1 - -#define HEATER_2_PIN -1 -#define TEMP_2_PIN -1 - -#define E0_STEP_PIN 43 -#define E0_DIR_PIN 45 -#define E0_ENABLE_PIN 41 - -#define E1_STEP_PIN -1 -#define E1_DIR_PIN -1 -#define E1_ENABLE_PIN -1 - -#define SDPOWER -1 -#define SDSS -1 -#define LED_PIN -1 -#define FAN_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define SUICIDE_PIN -1 //PIN that has to be turned on right after start, to keep power flowing. - -#define LCD_PINS_RS 24 -#define LCD_PINS_ENABLE 22 -#define LCD_PINS_D4 36 -#define LCD_PINS_D5 34 -#define LCD_PINS_D6 32 -#define LCD_PINS_D7 30 - -#endif - -/**************************************************************************************** -* Teensylu 0.7 pin assingments (ATMEGA90USB) -* Requires the Teensyduino software with Teensy2.0++ selected in arduino IDE! -****************************************************************************************/ -#if MOTHERBOARD == 8 -#define MOTHERBOARD 8 -#define KNOWN_BOARD 1 - - -#define X_STEP_PIN 0 -#define X_DIR_PIN 1 -#define X_ENABLE_PIN 39 -#define X_MIN_PIN 13 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 2 -#define Y_DIR_PIN 3 -#define Y_ENABLE_PIN 38 -#define Y_MIN_PIN 14 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 4 -#define Z_DIR_PIN 5 -#define Z_ENABLE_PIN 23 -#define Z_MIN_PIN 15 -#define Z_MAX_PIN -1 - -#define E0_STEP_PIN 6 -#define E0_DIR_PIN 7 -#define E0_ENABLE_PIN 19 - - - -#define HEATER_0_PIN 21 // Extruder -#define HEATER_1_PIN -1 -#define HEATER_2_PIN -1 -#define HEATER_BED_PIN 20 // Bed -#define FAN_PIN 22 // Fan - -#define TEMP_0_PIN 7 // Extruder -#define TEMP_1_PIN -1 -#define TEMP_2_PIN -1 -#define TEMP_BED_PIN 6 // Bed - -#define SDPOWER -1 -#define SDSS 8 -#define LED_PIN -1 -#define PS_ON_PIN -1 -#define KILL_PIN -1 -#define ALARM_PIN -1 - -#ifndef SDSUPPORT -// these pins are defined in the SD library if building with SD support - #define SCK_PIN 9 - #define MISO_PIN 11 - #define MOSI_PIN 10 -#endif -#endif - -/**************************************************************************************** -* Gen3+ pin assignment -* -****************************************************************************************/ -#if MOTHERBOARD == 9 -#define MOTHERBOARD 6 -#define KNOWN_BOARD 1 -#ifndef __AVR_ATmega644P__ -#ifndef __AVR_ATmega1284P__ -#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. -#endif -#endif - -#define X_STEP_PIN 15 -#define X_DIR_PIN 18 -#define X_MIN_PIN 20 -#define X_MAX_PIN -1 - -#define Y_STEP_PIN 23 -#define Y_DIR_PIN 22 -#define Y_MIN_PIN 25 -#define Y_MAX_PIN -1 - -#define Z_STEP_PIN 27 -#define Z_DIR_PIN 28 -#define Z_MIN_PIN 30 -#define Z_MAX_PIN -1 - -#define E_STEP_PIN 17 -#define E_DIR_PIN 21 - -#define LED_PIN -1 - -#define FAN_PIN -1 - -#define PS_ON_PIN 14 -#define KILL_PIN -1 - -#define HEATER_0_PIN 12 // (extruder) - -#define HEATER_1_PIN 16 // (bed) -#define X_ENABLE_PIN 19 -#define Y_ENABLE_PIN 24 -#define Z_ENABLE_PIN 29 -#define E_ENABLE_PIN 13 - -#define TEMP_0_PIN 0 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) -#define TEMP_1_PIN 5 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) -#define TEMP_2_PIN -1 -#define SDPOWER -1 -#define SDSS 4 -#define HEATER_2_PIN -1 - -#endif - - - - -#ifndef KNOWN_BOARD -#error Unknown MOTHERBOARD value in configuration.h -#endif - -//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! -#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN, -#if EXTRUDERS > 1 - #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, HEATER_1_PIN, -#else - #define _E1_PINS -#endif -#if EXTRUDERS > 2 - #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, HEATER_2_PIN, -#else - #define _E2_PINS -#endif - -#ifdef DISABLE_MAX_ENDSTOPS -#define X_MAX_PIN -1 -#define Y_MAX_PIN -1 -#define Z_MAX_PIN -1 -#endif - -#define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, LED_PIN, PS_ON_PIN, \ - HEATER_BED_PIN, FAN_PIN, \ - _E0_PINS _E1_PINS _E2_PINS \ - TEMP_0_PIN, TEMP_1_PIN, TEMP_2_PIN, TEMP_BED_PIN } -#endif From 34dfe7a6b4d566df22546043aa3eac1139b4ffe5 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Sun, 18 Mar 2012 21:53:18 +0000 Subject: [PATCH 213/228] Set correct thermistor tables. --- Marlin/Configuration.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index b2b361f0c5..1abcf20edb 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -49,10 +49,10 @@ // 100 is 100k GE Sensing AL03006-58.2K-97-G1 // 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT -#define TEMP_SENSOR_0 102 +#define TEMP_SENSOR_0 100 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 103 +#define TEMP_SENSOR_BED 101 // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 10 // (seconds) From 21a2cf0a9e6fbac64a857eeb9eb4f72307183ce1 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Mon, 19 Mar 2012 00:09:22 +0000 Subject: [PATCH 214/228] scropp's levelling added for testing. --- .gitignore | 2 +- Marlin/.gitignore | 1 + Marlin/Configuration.h | 3 ++ Marlin/Configuration_adv.h | 2 + Marlin/EEPROMwrite.h | 11 +++++ Marlin/Marlin.h | 15 +++++- Marlin/Marlin.pde | 93 ++++++++++++++++++++++++++++++++------ Marlin/pins.h | 7 +-- Marlin/planner.cpp | 2 + Marlin/stepper.cpp | 1 + 10 files changed, 118 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 54bcf30465..b25c15b81f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -~ +*~ diff --git a/Marlin/.gitignore b/Marlin/.gitignore index 37a3c9b84d..651c36bb9d 100644 --- a/Marlin/.gitignore +++ b/Marlin/.gitignore @@ -1,2 +1,3 @@ *.o +*.~ applet/ diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 1abcf20edb..b4a11af42f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -225,6 +225,9 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #endif #endif +// Enable uM-FPU support: +#define UMFPUSUPPORT 1 + // M240 Triggers a camera by emulating a Canon RC-1 Remote // Data from: http://www.doc-diy.net/photo/rc-1_hacked/ // #define PHOTOGRAPH_PIN 23 diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 4fb63ec62d..ac7492498e 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -74,6 +74,8 @@ // This defines the number of extruders #define EXTRUDERS 1 +#define Z_INCREMENT .0040 //Probe Movement Increment - 1 Full step on Huxley = 1/250 + #define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing //#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats. diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 649fa9100a..fa07592025 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -4,6 +4,7 @@ #include "Marlin.h" #include "planner.h" #include "temperature.h" +#include "FPUTransform.h" //#include @@ -67,6 +68,9 @@ inline void EEPROM_StoreSettings() EEPROM_writeAnything(i,0); EEPROM_writeAnything(i,0); #endif + #if defined(UMFPUSUPPORT) && (UMFPUSUPPORT > -1) + EEPROM_writeAnything(i,FPUEnabled); + #endif char ver2[4]=EEPROM_VERSION; i=EEPROM_OFFSET; EEPROM_writeAnything(i,ver2); // validate data @@ -130,6 +134,10 @@ inline void EEPROM_printSettings() SERIAL_ECHOPAIR(" W" ,Ki_Max); SERIAL_ECHOLN(""); #endif + #if defined(UMFPUSUPPORT) && (UMFPUSUPPORT > -1) + SERIAL_ECHOPAIR(" FPU Enabled" , FPUEnabled?" yes":" no"); + SERIAL_ECHOLN(""); + #endif #endif } @@ -163,6 +171,9 @@ inline void EEPROM_RetrieveSettings(bool def=false) EEPROM_readAnything(i,Ki); EEPROM_readAnything(i,Kd); EEPROM_readAnything(i,Ki_Max); + #if defined(UMFPUSUPPORT) && (UMFPUSUPPORT > -1) + EEPROM_readAnything(i,FPUEnabled); + #endif SERIAL_ECHO_START; SERIAL_ECHOLNPGM("Stored settings retreived:"); diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 919287260b..b6c5c7707c 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -26,7 +26,7 @@ #include "pins.h" #if ARDUINO >= 100 - #if defined(__AVR_ATmega644P__) + #if defined(__AVR_ATmega644P__) || defined (__AVR_ATmega1284P__) #include "WProgram.h" #else #include "Arduino.h" @@ -98,6 +98,13 @@ FORCE_INLINE void serialprintPGM(const char *str) } } +// printing floats to 3DP +FORCE_INLINE void serialPrintFloat( float f){ + SERIAL_ECHO((int)f); + SERIAL_ECHOPGM("."); + int mantissa = (f - (int)f) * 1000; + SERIAL_ECHO( abs(mantissa) ); +} void get_command(); void process_commands(); @@ -177,6 +184,12 @@ extern float current_position[NUM_AXIS] ; extern float add_homeing[3]; extern unsigned char FanSpeed; +extern float destination[NUM_AXIS]; +extern float modified_destination[NUM_AXIS]; +extern float offset[3]; +extern float feedrate, next_feedrate, saved_feedrate; + + // Handling multiple extruders pins extern uint8_t active_extruder; diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index 45996427e9..a5b30bae2b 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -28,6 +28,9 @@ #include "Marlin.h" #include "ultralcd.h" +#include "led.h" +#include "z_probe.h" +#include "FPUTransform.h" #include "planner.h" #include "stepper.h" #include "temperature.h" @@ -50,6 +53,10 @@ // G3 - CCW ARC // G4 - Dwell S or P // G28 - Home all Axis +// G29 - Detailed Z-Probe (3 location test) +// G30 - Single Z Probe (probe current location) +// G31 - Report Curent Probe status +// G32 - Probe Z and calibrate with FPU // G90 - Use Absolute Coordinates // G91 - Use Relative Coordinates // G92 - Set current position to cordinates given @@ -75,8 +82,10 @@ // 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 +// M30 - Fast SD transfer +// M31 - high speed xfer capabilities +// M35 - 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 @@ -110,6 +119,9 @@ // 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) // M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) +// M510 - FPU Enable +// M511 - FPU Reset +// M512 - FPU Disable //Stepper Movement Variables @@ -136,14 +148,18 @@ float add_homeing[3]={0,0,0}; uint8_t active_extruder = 0; unsigned char FanSpeed=0; +float destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; +float offset[3] = {0.0, 0.0, 0.0}; +float feedrate = 1500.0, next_feedrate, saved_feedrate; + +// used by FPU transform code +float modified_destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; + //=========================================================================== //=============================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; static bool relative_mode = false; //Determines Absolute or Relative Coordinates @@ -296,6 +312,11 @@ void setup() plan_init(); // Initialize planner; st_init(); // Initialize stepper; wd_init(); + #if (LED_PIN > -1) + led_init(); + #endif + probe_init(); //Initializes probe if PROBE_PIN is defined + FPUTransform_init(); //Initializes FPU when UMFPUSUPPORT defined setup_photpin(); } @@ -338,6 +359,7 @@ void loop() manage_inactivity(1); checkHitEndstops(); LCD_STATUS; + LED_STATUS; } void get_command() @@ -655,6 +677,18 @@ void process_commands() previous_millis_cmd = millis(); endstops_hit_on_purpose(); break; + case 29: + probe_3points(); + break; + case 30: + probe_1point(); + break; + case 31: + probe_status(); + break; + case 32: + FPUTransform_determineBedOrientation(); + break; case 90: // G90 relative_mode = false; break; @@ -766,7 +800,7 @@ void process_commands() break; #endif //SDSUPPORT - case 31: //M31 take time since the start of the SD print or an M109 command + case 35: //M35 take time since the start of the SD print or an M109 command { stoptime=millis(); char time[30]; @@ -920,6 +954,7 @@ void process_commands() manage_heater(); manage_inactivity(1); LCD_STATUS; + LED_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 */ @@ -1247,6 +1282,28 @@ void process_commands() EEPROM_printSettings(); } break; + case 504: // print free memory + { + SERIAL_ECHO_START; + SERIAL_ECHOPGM("Free Memory:"); + SERIAL_ECHO(freeMemory()); + } + break; + case 510: // FPU Enable + { + FPUEnable(); + } + break; + case 511: // FPU Reset + { + FPUReset(); + } + break; + case 512: // FPU Disable + { + FPUDisable(); + } + break; } } @@ -1319,19 +1376,24 @@ void get_arc_coordinates() void prepare_move() { + +// transform destination ********************************************* + + FPUTransform_transformDestination(); + if (min_software_endstops) { - if (destination[X_AXIS] < X_HOME_POS) destination[X_AXIS] = X_HOME_POS; - if (destination[Y_AXIS] < Y_HOME_POS) destination[Y_AXIS] = Y_HOME_POS; - if (destination[Z_AXIS] < Z_HOME_POS) destination[Z_AXIS] = Z_HOME_POS; + if (modified_destination[X_AXIS] < X_HOME_POS) modified_destination[X_AXIS] = X_HOME_POS; + if (modified_destination[Y_AXIS] < Y_HOME_POS) modified_destination[Y_AXIS] = Y_HOME_POS; + if (modified_destination[Z_AXIS] < Z_HOME_POS) modified_destination[Z_AXIS] = Z_HOME_POS; } if (max_software_endstops) { - if (destination[X_AXIS] > X_MAX_LENGTH) destination[X_AXIS] = X_MAX_LENGTH; - if (destination[Y_AXIS] > Y_MAX_LENGTH) destination[Y_AXIS] = Y_MAX_LENGTH; - if (destination[Z_AXIS] > Z_MAX_LENGTH) destination[Z_AXIS] = Z_MAX_LENGTH; + if (modified_destination[X_AXIS] > X_MAX_LENGTH) modified_destination[X_AXIS] = X_MAX_LENGTH; + if (modified_destination[Y_AXIS] > Y_MAX_LENGTH) modified_destination[Y_AXIS] = Y_MAX_LENGTH; + if (modified_destination[Z_AXIS] > Z_MAX_LENGTH) modified_destination[Z_AXIS] = Z_MAX_LENGTH; } previous_millis_cmd = millis(); - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60/100.0, active_extruder); + plan_buffer_line(modified_destination[X_AXIS], modified_destination[Y_AXIS], modified_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]; } @@ -1340,8 +1402,11 @@ void prepare_move() void prepare_arc_move(char isclockwise) { float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc +// transform destination ********************************************* + FPUTransform_transformDestination(); + // Trace the arc - mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise, active_extruder); + mc_arc(current_position, modified_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 diff --git a/Marlin/pins.h b/Marlin/pins.h index 056d861d69..952d7d537b 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -585,9 +585,10 @@ #define E0_STEP_PIN 1 #define E0_DIR_PIN 0 -#define LED_PIN -1 +#define PROBE_PIN 29 //A2 -#define FAN_PIN 27 +#define LED_PIN 27 +#define FAN_PIN 4 #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -598,7 +599,7 @@ #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 5da384f02a..54be28670c 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -60,6 +60,7 @@ #include "temperature.h" #include "ultralcd.h" #include "language.h" +#include "led.h" //=========================================================================== //=============================public variables ============================ @@ -469,6 +470,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa manage_heater(); manage_inactivity(1); LCD_STATUS; + LED_STATUS; } // The target position of the tool in absolute steps diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index e9b42f45de..ffd4ecddf8 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -27,6 +27,7 @@ #include "temperature.h" #include "ultralcd.h" #include "language.h" +#include "led.h" #include "speed_lookuptable.h" From 62b5f458d4055726c99b68f4423772bd4e8fc401 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Wed, 21 Mar 2012 14:05:12 +0000 Subject: [PATCH 215/228] bed levelled --- Marlin/Configuration.h | 6 +- Marlin/FPUTransform.cpp | 201 +++++++++++++++++++++++++++++++++++++ Marlin/FPUTransform.h | 21 ++++ Marlin/MatrixMath.cpp | 206 ++++++++++++++++++++++++++++++++++++++ Marlin/MatrixMath.h | 29 ++++++ Marlin/led.cpp | 35 +++++++ Marlin/led.h | 20 ++++ Marlin/pins.h | 8 +- Marlin/thermistortables.h | 2 +- Marlin/z_probe.cpp | 140 ++++++++++++++++++++++++++ Marlin/z_probe.h | 21 ++++ 11 files changed, 681 insertions(+), 8 deletions(-) create mode 100755 Marlin/FPUTransform.cpp create mode 100644 Marlin/FPUTransform.h create mode 100644 Marlin/MatrixMath.cpp create mode 100644 Marlin/MatrixMath.h create mode 100644 Marlin/led.cpp create mode 100644 Marlin/led.h create mode 100644 Marlin/z_probe.cpp create mode 100644 Marlin/z_probe.h diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index b4a11af42f..0b27a17b5d 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -172,10 +172,10 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,850} #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {1500,1500,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +#define DEFAULT_MAX_ACCELERATION {1000,1000,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. -#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for r retracts +#define DEFAULT_ACCELERATION 1000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 1000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts // #define DEFAULT_XYJERK 15.0 // (mm/sec) diff --git a/Marlin/FPUTransform.cpp b/Marlin/FPUTransform.cpp new file mode 100755 index 0000000000..5cb69ff2d8 --- /dev/null +++ b/Marlin/FPUTransform.cpp @@ -0,0 +1,201 @@ +#include "FPUTransform.h" + +#if defined(UMFPUSUPPORT) && (UMFPUSUPPORT > -1) + +#include "MatrixMath.h" + +float MasterTransform[4][4]; // this is the transform that describes how to move from + // ideal coordinates to real world coords + +// private functions +void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3); +void transformDestination(float &X, float &Y, float &Z); + +bool FPUEnabled; // this is a bypass switch so that with one command the FPU can be + // turned off + +void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3) +{ +float Xdiff = X3 - X1; + serialPrintFloat(Xdiff); + SERIAL_ECHOLN(""); +float Ydiff = Y2 - Y1; + serialPrintFloat(Ydiff); + SERIAL_ECHOLN(""); +//clockwise +float ZdiffX = Z3 - Z1; + serialPrintFloat(ZdiffX); + SERIAL_ECHOLN(""); +//anti clockwise +float ZdiffY = Z1 - Z2; + serialPrintFloat(ZdiffY); + SERIAL_ECHOLN(""); + + +//modified to take advantage of small angle trig. +float Xtheta = ZdiffX / Xdiff; +// serialPrintFloat(Xtheta); +// SERIAL_ECHOLN(""); +float Ytheta = ZdiffY / Ydiff; +// serialPrintFloat(Ytheta); +// SERIAL_ECHOLN(""); +float cosxtheta = 1-(Xtheta*Xtheta)/2; +// serialPrintFloat(cosxtheta); +// SERIAL_ECHOLN(""); +float sinxtheta = Xtheta; +// serialPrintFloat(sinxtheta); +// SERIAL_ECHOLN(""); +float cosytheta = 1-(Ytheta*Ytheta)/2; +// serialPrintFloat(cosytheta); +// SERIAL_ECHOLN(""); +float sinytheta = Ytheta; +// serialPrintFloat(sinytheta); +// SERIAL_ECHOLN(""); + + +// Start by moving X and Y to 0 (seperating this out as we want to undo this later) +float Translate00Z[4][4] = {{1.0, 0.0, 0.0, -X1}, + {0.0, 1.0, 0.0, -Y1}, + {0.0, 0.0, 1.0, 0.0}, + {0.0, 0.0, 0.0, 1.0}}; + +//now move Z to 0 +float TranslateZ0[4][4] = {{1.0, 0.0, 0.0, 0.0}, + {0.0, 1.0, 0.0, 0.0}, + {0.0, 0.0, 1.0, -Z1}, + {0.0, 0.0, 0.0, 1.0}}; + +float Transform0[4][4]; +matrixMaths.MatrixMult((float*)Translate00Z, (float*)TranslateZ0, 4, 4, 4, (float*)Transform0); + +//first rotate in Y using XZ +//[cos(t), 0, -sin(t), 0] +//[0 , 1, 0 , 0] +//[sin{t}, 0, cos(t), 0] +//[0 , 0, 0 , 1] + +float Transform1[4][4] = {{cosxtheta, 0.0, sinxtheta, 0.0}, + { 0.0, 1.0, 0.0, 0.0}, + {-sinxtheta, 0.0, cosxtheta, 0.0}, + { 0.0, 0.0, 0.0, 1.0}}; +//matrixMaths.MatrixPrint((float*)Transform1, 4, 4, "Transform1"); +float rotMatrix1[4][4]; +matrixMaths.MatrixMult((float*)Transform1, (float*)Transform0, 4, 4, 4, (float*)rotMatrix1); + +//first rotate in X using YZ +//[1, 0, 0 , 0] +//[0, cos(t), sin(t), 0] +//[0, -sin{t}, cos(t), 0] +//[0, 0, 0 , 1] + +float Transform2[4][4] = {{ 1.0, 0.0, 0.0, 0.0}, + { 0.0, cosytheta, sinytheta, 0.0}, + { 0.0,sinytheta, cosytheta, 0.0}, + { 0.0, 0.0, 0.0, 1.0}}; +//matrixMaths.MatrixPrint((float*)Transform2, 4, 4, "Transform2"); +//float rotMatrix[4][4]; +//matrixMaths.MatrixMult((float*)Transform1, (float*)Transform2, 4, 4, 4, (float*)rotMatrix); +float rotMatrix2[4][4]; +matrixMaths.MatrixMult((float*)Transform2, (float*)rotMatrix1, 4, 4, 4, (float*)rotMatrix2); +//translate back to XY +//matrixMaths.MatrixInvert((float*)Translate00Z, 4); +Translate00Z[0][3] = X1; +Translate00Z[1][3] = Y1; +matrixMaths.MatrixMult((float*)rotMatrix2, (float*)Translate00Z, 4, 4, 4, (float*)MasterTransform); +//matrixMaths.MatrixPrint((float*)rotMatrix, 4, 4, "rotMatrix"); + +//now we have the object in a plane that is parallel to the x axes, but we do not have the z height correct. +//transform the x15 y15 position using our rotation matrix and use the result to determine where z0 is and +//add this translate function to the transform matrix. + +//float zError[4][1]={{X1},{Y1},{Z1},{1.0}}; +//float zErrNew[1][4]; +//matrixMaths.MatrixMult((float*)rotMatrix, (float*)zError, 1, 4, 4, (float*)zErrNew); + +//float zTranslate[4][4] = {{ 1.0, 0.0, 0.0, 0.0}, +// { 0.0, 1.0, 0.0, 0.0}, +// { 0.0, 0.0, 1.0, 0.0}, +// { 15-zErrNew[0][0],15-zErrNew[1][0],-zErrNew[2][0], 1.0}}; +//matrixMaths.MatrixMult((float*)rotMatrix, (float*)zTranslate, 4, 4, 4, (float*)MasterTransform); + +// We now have a way to translate from real-world coordinates to idealised coortdinates, // but what we actually want is a way to transform from the idealised g-code coordinates +// to real world coordinates. +// This is simply the inverse. +matrixMaths.MatrixInvert((float*)MasterTransform, 4); +matrixMaths.MatrixPrint((float*)MasterTransform, 4, 4, "MasterTransform"); +} + +void transformDestination(float &X, float &Y, float &Z) +{ +float oldPoint[4][1]={{X}, {Y}, {Z}, {1.0}}; +float newPoint[1][4]={{0.0,0.0,0.0,0.0}}; +matrixMaths.MatrixMult((float*)MasterTransform, (float*)oldPoint, 4, 4, 1, (float*)newPoint); +X=newPoint[0][0]; +Y=newPoint[0][1]; +Z=newPoint[0][2]; +} + +void FPUTransform_init() +{ +if (FPUEnabled == true) + { + // It is important to ensure that if the bed levelling routine has not been called the + // printer behaves as if the real world and idealised world are one and the same + matrixMaths.MatrixIdentity((float*)MasterTransform,4,4); + SERIAL_ECHO("transform configured to identity"); + } +else + { + SERIAL_ECHO("transform correction not enabled"); + } +} + +void FPUEnable() +{ + FPUEnabled = true; + FPUTransform_init(); +} + +void FPUReset() +{ + FPUTransform_init(); +} + +void FPUDisable() +{ + FPUEnabled = false; +} + +void FPUTransform_determineBedOrientation() +{ +float Z1; +float Y2 = Y_MAX_LENGTH - 15; +float Z2; +float X3 = X_MAX_LENGTH - 15; +float Z3; + +//get Z for X15 Y15, X15 Y(Y_MAX_LENGTH - 15) and X(X_MAX_LENGTH - 15) Y15 +Z1 = Probe_Bed(15,15); +Z2 = Probe_Bed(15,Y2); +Z3 = Probe_Bed(X3,15); +if(FPUEnabled) + { + loadMatrix(15, 15, Z1, Y2, Z2, X3, Z3); + } +} + +void FPUTransform_transformDestination() +{ +float XPoint = destination[X_AXIS]; // float variable +float YPoint = destination[Y_AXIS]; // float variable +float ZPoint = destination[Z_AXIS]; // float variable +if(FPUEnabled) + { + transformDestination(XPoint, YPoint, ZPoint); + } +modified_destination[X_AXIS] = XPoint; // float variable +modified_destination[Y_AXIS] = YPoint; // float variable +modified_destination[Z_AXIS] = ZPoint; // float variable +} + +#endif //UMFPUSUPPORT diff --git a/Marlin/FPUTransform.h b/Marlin/FPUTransform.h new file mode 100644 index 0000000000..661ccca94a --- /dev/null +++ b/Marlin/FPUTransform.h @@ -0,0 +1,21 @@ +#ifndef __FPUTRANSFORM + +#define __FPUTRANSFORM +#include "Marlin.h" +#include "z_probe.h" + +#if defined(UMFPUSUPPORT) && (UMFPUSUPPORT > -1) + extern bool FPUEnabled; + void FPUTransform_init(); + void FPUEnable(); + void FPUReset(); + void FPUDisable(); + void FPUTransform_determineBedOrientation(); + void FPUTransform_transformDestination(); + +#else //no UMFPU SUPPORT + FORCE_INLINE void FPUTransform_init() {}; + +#endif //UMFPUSUPPORT + +#endif //__FPUTRANSFORM diff --git a/Marlin/MatrixMath.cpp b/Marlin/MatrixMath.cpp new file mode 100644 index 0000000000..b02b9ed6a8 --- /dev/null +++ b/Marlin/MatrixMath.cpp @@ -0,0 +1,206 @@ +/* + * MatrixMath.cpp Library for MatrixMath + * + * Created by Charlie Matlack on 12/18/10. + * Modified from code by RobH45345 on Arduino Forums, taken from unknown source. + * MatrixMath.cpp + */ + +#include "Marlin.h" +#include "MatrixMath.h" + +#define NR_END 1 + +MatrixMath::MatrixMath() +{ +} + +// Matrix Printing Routine +// Uses tabs to separate numbers under assumption printed float width won't cause problems +void MatrixMath::MatrixPrint(float* A, int m, int n, String label){ + // A = input matrix (m x n) + int i,j; + SERIAL_ECHOLN(' '); + SERIAL_ECHOLN(label); + for (i=0; i= tmp) // 'Avoid using other functions inside abs()?' + { + tmp = abs(A[i*n+k]); + pivrow = i; + } + } + + // check for singular matrix + if (A[pivrow*n+k] == 0.0f) + { + SERIAL_ECHOLNPGM("Inversion failed due to singular matrix"); + return 0; + } + + // Execute pivot (row swap) if needed + if (pivrow != k) + { + // swap row k with pivrow + for (j = 0; j < n; j++) + { + tmp = A[k*n+j]; + A[k*n+j] = A[pivrow*n+j]; + A[pivrow*n+j] = tmp; + } + } + pivrows[k] = pivrow; // record row swap (even if no swap happened) + + tmp = 1.0f/A[k*n+k]; // invert pivot element + A[k*n+k] = 1.0f; // This element of input matrix becomes result matrix + + // Perform row reduction (divide every element by pivot) + for (j = 0; j < n; j++) + { + A[k*n+j] = A[k*n+j]*tmp; + } + + // Now eliminate all other entries in this column + for (i = 0; i < n; i++) + { + if (i != k) + { + tmp = A[i*n+k]; + A[i*n+k] = 0.0f; // The other place where in matrix becomes result mat + for (j = 0; j < n; j++) + { + A[i*n+j] = A[i*n+j] - A[k*n+j]*tmp; + } + } + } + } + + // Done, now need to undo pivot row swaps by doing column swaps in reverse order + for (k = n-1; k >= 0; k--) + { + if (pivrows[k] != k) + { + for (i = 0; i < n; i++) + { + tmp = A[i*n+k]; + A[i*n+k] = A[i*n+pivrows[k]]; + A[i*n+pivrows[k]] = tmp; + } + } + } + return 1; +} + +void MatrixMath::MatrixIdentity(float* A, int m, int n) +{ + int i, j; + for (i=0;i -1) +#include "Marlin.h" +#include "temperature.h" + +static unsigned long previous_millis_led=0; +static unsigned long previous_millis_toggle=0; + +void led_init() +{ + SET_OUTPUT(LED_PIN); +} + +void led_status() +{ + if (((millis() - previous_millis_led) < LED_UPDATE_INTERVAL)) + return; + previous_millis_led=millis(); + if (degTargetHotend(active_extruder) > HEATER_0_MINTEMP) + { + if (((millis() - previous_millis_toggle) < LED_HOTEND_ACTIVE_FLASH)) + return; + previous_millis_toggle=millis(); + TOGGLE(LED_PIN); + } + else + { + WRITE(LED_PIN, HIGH); + } +} + + +#endif //LED_PIN > -1 + + diff --git a/Marlin/led.h b/Marlin/led.h new file mode 100644 index 0000000000..66da0ab3a3 --- /dev/null +++ b/Marlin/led.h @@ -0,0 +1,20 @@ +#ifndef __LEDH + +#define __LEDH +#include "Marlin.h" + +#if (LED_PIN > -1) + void led_status(); + void led_init(); + + #define LED_UPDATE_INTERVAL 100 + #define LED_HOTEND_ACTIVE_FLASH 800 + #define LED_ERROR_FLASH 200 + #define LED_STATUS led_status() + +#else //no led + #define LED_STATUS + FORCE_INLINE void led_status() {}; +#endif //LED_PIN > -1 + +#endif diff --git a/Marlin/pins.h b/Marlin/pins.h index 952d7d537b..d3be5642ed 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -585,10 +585,10 @@ #define E0_STEP_PIN 1 #define E0_DIR_PIN 0 -#define PROBE_PIN 29 //A2 +#define PROBE_PIN 11 //29 on Melzi1284p A2, 11 on SL1.3a -#define LED_PIN 27 -#define FAN_PIN 4 +#define LED_PIN -1 //27 on Melzi1284p +#define FAN_PIN 12 //4 on Melzi1284p #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -599,7 +599,7 @@ #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 88e7ddaf3d..91eec98405 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -442,7 +442,7 @@ const short temptable_102[][2] PROGMEM = { {1008*OVERSAMPLENR,0}, }; #endif -#if (THERMISTORHEATER_0 == 103) || (THERMISTORHEATER_1 == 103) || (THERMISTORHEATER_2 == 103) || (THERMISTORBED == 103) // 100k Honeywell 135-104LAG-J01 +#if (THERMISTORHEATER_0 == 103) || (THERMISTORHEATER_1 == 103) || (THERMISTORHEATER_2 == 103) || (THERMISTORBED == 103) // EPCOS G57540 const short temptable_103[][2] PROGMEM = { {1*OVERSAMPLENR, 628}, {187*OVERSAMPLENR, 156}, diff --git a/Marlin/z_probe.cpp b/Marlin/z_probe.cpp new file mode 100644 index 0000000000..72dbc99f64 --- /dev/null +++ b/Marlin/z_probe.cpp @@ -0,0 +1,140 @@ +#include "z_probe.h" +#if defined(PROBE_PIN) && (PROBE_PIN > -1) +#include "Marlin.h" + + +//Crash1 - Probes bed at least twice until distances are similar then takes average of 2 +float Probe_Bed(float x_pos, float y_pos) +{ + //returns Probed Z average height + float ProbeDepth[6], ProbeDepthAvg; + if (Z_HOME_DIR==-1) + { + saved_feedrate = feedrate; + destination[Z_AXIS] = 3; //* Z_HOME_DIR; //Lift over bed for initial Move + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); + + //Move to Probe Coordinates, Use current Position if none given + if (x_pos < 0) + destination[X_AXIS] = current_position[X_AXIS]; + else + destination[X_AXIS] = x_pos; + if (y_pos < 0) + destination[Y_AXIS] = current_position[Y_AXIS]; + else + destination[Y_AXIS] = y_pos; + feedrate = 7500; // 500 is way too slow- WTF - max_feedrate[X_AXIS]; //homing_feedrate[X_AXIS]; //250; + prepare_move(); + + destination[Z_AXIS] = .75; //* Z_HOME_DIR; //move close to Z Home - bed should be within .75mm of level + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); + + //Plunge down final distance slowly until bed breaks contact and pin true + //*******************************************************************************************Bed Loop************************************* + for(int8_t i=0; i < 2 ; i++) + { //probe 2 or more times to get repeatable reading + //2DO If bed currently true then it is stuck - need to do something smart here. + int probeSteps = 500; //distance to move down and max distance to scan up in one step. + int z = 0; + while(READ(PROBE_PIN) == false && z < probeSteps) + { //if it takes more than 500 steps then something is wrong + destination[Z_AXIS] = current_position[Z_AXIS] - Z_INCREMENT; //* Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); + z++; + } + //move up in small increments until switch makes + z = 0; + while(READ(PROBE_PIN) == true && z < probeSteps) + { //if it takes more than 100 steps then bed is likely stuck - still need to error on this to stop process + destination[Z_AXIS] = current_position[Z_AXIS] + Z_INCREMENT; //* Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); + z++; + } + //************************************************************************************************************************************************** + //if Z is probeSteps here then we have a stuck bed and it will keep on advancing upward. So send hot end toward Zstop to try to unstick. + if (z == probeSteps) + { + SERIAL_ECHOLN("Poking Stuck Bed:"); + destination[Z_AXIS] = 1; feedrate = homing_feedrate[Z_AXIS]; prepare_move(); + destination[Z_AXIS] = .2; feedrate = homing_feedrate[Z_AXIS]; prepare_move(); + destination[Z_AXIS] = 1; feedrate = homing_feedrate[Z_AXIS]; prepare_move(); + i--; //Throw out this meaningless probe + z == 0; + } + //************************************************************************************************************* + ProbeDepth[i]= current_position[Z_AXIS]; + if (i == 1 ) + { + if (abs(ProbeDepth[i] - ProbeDepth[i - 1]) > .02) + { //keep going until readings match to avoid sticky bed + SERIAL_ECHO("Probing again - difference:"); SERIAL_ECHO(abs(ProbeDepth[i] - ProbeDepth[i - 1])); SERIAL_ECHO(", Z="); SERIAL_ECHOLN(ProbeDepth[i]); + i -= 2; //Throw out both that don't match because we don't know which one is accurate + } + } + feedrate = 0; + } //end probe loop + feedrate = saved_feedrate; + } + ProbeDepthAvg = (ProbeDepth[0] + ProbeDepth[1]) / 2; + SERIAL_ECHO("Z="); SERIAL_ECHOLN(ProbeDepthAvg); + return ProbeDepthAvg; + } +//Crash1 END Add Probe Bed Function + +void probe_init() +{ + SET_INPUT(PROBE_PIN); + WRITE(PROBE_PIN,HIGH); +} + +/*Crash1 - G29 to Probe and stop on Bed +G29 will probe bed at least twice at 3 points and take an average. G30 will probe bed at it's current location. +Z stop should be set slightly below bed height. Solder stub wire to each hole in huxley bed and attach a ring terminal under spring. +Wire bed probe to A2 on Melzi and duplicate cap/resistor circuit in schematic. + +Use something like this in the start.gcode file: +G29 ;Probe bed for Z height +G92 Z0 ;Set Z to Probed Depth +G1 Z5 F200 ;Lift Z out of way +*/ +void probe_3points() +{ + float Probe_Avg, Point1, Point2, Point3; + Point1 = Probe_Bed(15, 15); + Point2 = Probe_Bed(15, Y_MAX_LENGTH - 15); + Point3 = Probe_Bed(X_MAX_LENGTH - 15, Y_MAX_LENGTH/2) ; + Probe_Avg = (Point1 + Point2 + Point3) / 3; + destination[2] = Probe_Avg; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); + SERIAL_ECHOLN("**************************************"); + SERIAL_ECHO("Point1 ="); SERIAL_ECHOLN(Point1); + SERIAL_ECHO("Point2 ="); SERIAL_ECHOLN(Point2); + SERIAL_ECHO("Point3 ="); SERIAL_ECHOLN(Point3); + SERIAL_ECHO("Probed Average="); SERIAL_ECHOLN(Probe_Avg); + SERIAL_ECHOLN("**************************************"); +} + +void probe_1point() +{ + float Point; + Point = Probe_Bed(-1,-1); + destination[2] = Point +1; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); + SERIAL_ECHOLN("**************************************"); + SERIAL_ECHO("Probed Z="); SERIAL_ECHOLN(Point); +} + +void probe_status() +{ + SERIAL_ECHO("Probe Status = "); SERIAL_ECHOLN(READ(PROBE_PIN)); +} + +#endif //defined(PROBE_PIN) > -1 + + diff --git a/Marlin/z_probe.h b/Marlin/z_probe.h new file mode 100644 index 0000000000..1135c29181 --- /dev/null +++ b/Marlin/z_probe.h @@ -0,0 +1,21 @@ +#ifndef __Z_PROBEH + +#define __Z_PROBEH +#include "Marlin.h" + +#if defined(PROBE_PIN) && (PROBE_PIN > -1) + void probe_init(); + void probe_3points(); + void probe_1point(); + void probe_status(); + float Probe_Bed(float x_pos, float y_pos); + +#else //no probe pin + FORCE_INLINE void probe_init() {}; + FORCE_INLINE void probe_3points() {}; + FORCE_INLINE void probe_1point() {}; + FORCE_INLINE void probe_status() {}; + FORCE_INLINE float Probe_Bed(float x_pos, float y_pos) {return 0;} +#endif //PROBE_PIN + +#endif From 6db3d3b90d6dfe2c8ce524eda478531f23e71daa Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Wed, 21 Mar 2012 17:09:51 +0000 Subject: [PATCH 216/228] made m206 work --- Marlin/Marlin.pde | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index a5b30bae2b..c6dec40c52 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -648,23 +648,26 @@ void process_commands() HOMEAXIS(Z); } - if(code_seen(axis_codes[X_AXIS])) + if((home_all_axis) || code_seen(axis_codes[X_AXIS])) { if(code_value_long() != 0) { - current_position[X_AXIS]=code_value()+add_homeing[0]; + current_position[X_AXIS]=code_value(); } + current_position[X_AXIS]+=add_homeing[0]; } - if(code_seen(axis_codes[Y_AXIS])) { + if((home_all_axis) || code_seen(axis_codes[Y_AXIS])) { if(code_value_long() != 0) { - current_position[Y_AXIS]=code_value()+add_homeing[1]; + current_position[Y_AXIS]=code_value(); } + current_position[Y_AXIS]+=add_homeing[1]; } - if(code_seen(axis_codes[Z_AXIS])) { + if((home_all_axis) || code_seen(axis_codes[Z_AXIS])) { if(code_value_long() != 0) { - current_position[Z_AXIS]=code_value()+add_homeing[2]; + current_position[Z_AXIS]=code_value(); } + current_position[Z_AXIS]+=add_homeing[2]; } plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); From a89e833b50d241097f17cef03392db96c227e313 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Thu, 22 Mar 2012 16:29:02 +0000 Subject: [PATCH 217/228] minor changes --- Marlin/Configuration.h | 6 +++--- Marlin/pins.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 0b27a17b5d..6e7c223998 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -8,7 +8,7 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-03-01-1" //Personal revision number for changes to THIS file. +#define STRING_VERSION_CONFIG_H "2012-03-22-1" //Personal revision number for changes to THIS file. #define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. // This determines the communication speed of the printer @@ -49,10 +49,10 @@ // 100 is 100k GE Sensing AL03006-58.2K-97-G1 // 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT -#define TEMP_SENSOR_0 100 +#define TEMP_SENSOR_0 102 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 101 +#define TEMP_SENSOR_BED 103 // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 10 // (seconds) diff --git a/Marlin/pins.h b/Marlin/pins.h index d3be5642ed..a051e3cce5 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -585,10 +585,10 @@ #define E0_STEP_PIN 1 #define E0_DIR_PIN 0 -#define PROBE_PIN 11 //29 on Melzi1284p A2, 11 on SL1.3a +#define PROBE_PIN -1 //29 on Melzi1284p A2, 11 on SL1.3a #define LED_PIN -1 //27 on Melzi1284p -#define FAN_PIN 12 //4 on Melzi1284p +#define FAN_PIN -1 //4 on Melzi1284p #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -599,7 +599,7 @@ #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 From 7a3845527d3f8b29f176c44490403d76ff21ccba Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Mon, 26 Mar 2012 09:47:17 +0100 Subject: [PATCH 218/228] fixed bug in accel code --- Marlin/Configuration.h | 12 ++-- Marlin/Configuration_adv.h | 1 + Marlin/FPUTransform.cpp | 23 ++++--- Marlin/Marlin.h | 3 + Marlin/pins.h | 8 +-- Marlin/planner.cpp | 8 +-- Marlin/stepper.cpp | 4 +- Marlin/stepper.h | 3 + Marlin/z_probe.cpp | 126 +++++++++++++++++++++++++++++++++++-- Marlin/z_probe.h | 4 +- 10 files changed, 160 insertions(+), 32 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 6e7c223998..f4ebad47e5 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -8,7 +8,7 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-03-22-1" //Personal revision number for changes to THIS file. +#define STRING_VERSION_CONFIG_H "2012-03-26-1" //Personal revision number for changes to THIS file. #define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. // This determines the communication speed of the printer @@ -141,9 +141,9 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false #define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true -#define INVERT_E0_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E2_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false // ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -153,8 +153,8 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define min_software_endstops true //If true, axis won't move to coordinates less than zero. #define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 150 -#define Y_MAX_LENGTH 148 +#define X_MAX_LENGTH 145 +#define Y_MAX_LENGTH 145 #define Z_MAX_LENGTH 100 // The position of the homing switches. Use MAX_LENGTH * -0.5 if the center should be 0, 0, 0 diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ac7492498e..9a44923927 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -75,6 +75,7 @@ #define EXTRUDERS 1 #define Z_INCREMENT .0040 //Probe Movement Increment - 1 Full step on Huxley = 1/250 +#define PROBE_N 3 #define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing diff --git a/Marlin/FPUTransform.cpp b/Marlin/FPUTransform.cpp index 5cb69ff2d8..cfffabc46b 100755 --- a/Marlin/FPUTransform.cpp +++ b/Marlin/FPUTransform.cpp @@ -8,14 +8,15 @@ float MasterTransform[4][4]; // this is the transform that describes how to move // ideal coordinates to real world coords // private functions -void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3); +void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3, float Z4); void transformDestination(float &X, float &Y, float &Z); bool FPUEnabled; // this is a bypass switch so that with one command the FPU can be // turned off -void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3) +void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3, float Z4) { +//add calculated 4th point float Xdiff = X3 - X1; serialPrintFloat(Xdiff); SERIAL_ECHOLN(""); @@ -23,7 +24,7 @@ float Ydiff = Y2 - Y1; serialPrintFloat(Ydiff); SERIAL_ECHOLN(""); //clockwise -float ZdiffX = Z3 - Z1; +float ZdiffX = Z4 - Z3; serialPrintFloat(ZdiffX); SERIAL_ECHOLN(""); //anti clockwise @@ -168,19 +169,23 @@ void FPUDisable() void FPUTransform_determineBedOrientation() { +int X1 = 10; +int Y1 = 10; float Z1; -float Y2 = Y_MAX_LENGTH - 15; +float Y2 = Y_MAX_LENGTH - 5; float Z2; -float X3 = X_MAX_LENGTH - 15; +float X3 = X_MAX_LENGTH - 20; float Z3; +float Z4; //get Z for X15 Y15, X15 Y(Y_MAX_LENGTH - 15) and X(X_MAX_LENGTH - 15) Y15 -Z1 = Probe_Bed(15,15); -Z2 = Probe_Bed(15,Y2); -Z3 = Probe_Bed(X3,15); +Z3 = Probe_Bed(10,10,PROBE_N); +Z4 = Probe_Bed(X3,10,PROBE_N); +Z1 = (Z3 + Z4) / 2; +Z2 = Probe_Bed(X3/2,Y2,PROBE_N); if(FPUEnabled) { - loadMatrix(15, 15, Z1, Y2, Z2, X3, Z3); + loadMatrix(X1, Y1, Z1, Y2, Z2, X3, Z3, Z4); } } diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index b6c5c7707c..57aa579f45 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -179,7 +179,10 @@ void prepare_arc_move(char isclockwise); #endif //CRITICAL_SECTION_START extern float homing_feedrate[]; +extern float fast_home_feedrate[]; extern bool axis_relative_modes[]; +extern volatile int feedmultiply; +extern int saved_feedmultiply; extern float current_position[NUM_AXIS] ; extern float add_homeing[3]; extern unsigned char FanSpeed; diff --git a/Marlin/pins.h b/Marlin/pins.h index a051e3cce5..44a7d63abb 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -579,16 +579,16 @@ #define Z_STEP_PIN 3 #define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 +#define Z_MIN_PIN 11//20 #define Z_MAX_PIN -1 #define E0_STEP_PIN 1 #define E0_DIR_PIN 0 -#define PROBE_PIN -1 //29 on Melzi1284p A2, 11 on SL1.3a +#define PROBE_PIN 11 //29 on Melzi1284p A2, 11 on SL1.3a -#define LED_PIN -1 //27 on Melzi1284p -#define FAN_PIN -1 //4 on Melzi1284p +#define LED_PIN 27 //27 on Melzi1284p +#define FAN_PIN 4 //4 on Melzi1284p #define PS_ON_PIN -1 #define KILL_PIN -1 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 54be28670c..628620652f 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -552,10 +552,10 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa #endif float delta_mm[4]; - delta_mm[X_AXIS] = block->steps_x/axis_steps_per_unit[X_AXIS]; - delta_mm[Y_AXIS] = block->steps_y/axis_steps_per_unit[Y_AXIS]; - delta_mm[Z_AXIS] = block->steps_z/axis_steps_per_unit[Z_AXIS]; - delta_mm[E_AXIS] = block->steps_e/axis_steps_per_unit[E_AXIS]; + delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; + delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; + delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; + delta_mm[E_AXIS] = ((target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS])*extrudemultiply/100.0; // if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { // block->millimeters = abs(delta_mm[E_AXIS]); // } else { diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index ffd4ecddf8..1b35c9db33 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -36,6 +36,8 @@ //=============================public variables ============================ //=========================================================================== block_t *current_block; // A pointer to the block currently being traced +volatile bool endstop_z_hit=false; +bool old_z_min_endstop=false; //=========================================================================== @@ -66,13 +68,11 @@ volatile long endstops_trigsteps[3]={0,0,0}; volatile long endstops_stepsTotal,endstops_stepsDone; static volatile bool endstop_x_hit=false; static volatile bool endstop_y_hit=false; -static volatile bool endstop_z_hit=false; static bool old_x_min_endstop=false; static bool old_x_max_endstop=false; static bool old_y_min_endstop=false; static bool old_y_max_endstop=false; -static bool old_z_min_endstop=false; static bool old_z_max_endstop=false; static bool check_endstops = true; diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 7671a65ea0..5af498000a 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -66,6 +66,9 @@ void checkStepperErrors(); //Print errors detected by the stepper void finishAndDisableSteppers(); extern block_t *current_block; // A pointer to the block currently being traced +extern volatile long endstops_trigsteps[]; +extern volatile bool endstop_z_hit; +extern bool old_z_min_endstop; void quickStop(); #endif diff --git a/Marlin/z_probe.cpp b/Marlin/z_probe.cpp index 72dbc99f64..a3fdd05be7 100644 --- a/Marlin/z_probe.cpp +++ b/Marlin/z_probe.cpp @@ -1,8 +1,124 @@ #include "z_probe.h" #if defined(PROBE_PIN) && (PROBE_PIN > -1) #include "Marlin.h" +#include "stepper.h" +#define PROBE_DOWN +#ifdef PROBE_DOWN +float Probe_Bed(float x_pos, float y_pos, int n) +{ + //returns Probed Z average height + float ProbeDepth[n], ProbeDepthAvg; + if (Z_HOME_DIR==-1) + { + //int probe_flag =1; + int fails = 0; + saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + //previous_millis_cmd = millis(); + + enable_endstops(true); + + //Move to Probe Coordinates, Use current Position if none given - ie. for G30 + if (x_pos < 0) + destination[X_AXIS] = current_position[X_AXIS]; + else + destination[X_AXIS] = x_pos; + if (y_pos < 0) + destination[Y_AXIS] = current_position[Y_AXIS]; + else + destination[Y_AXIS] = y_pos; + + //Probe bed n times + //*******************************************************************************************Bed Loop************************************* + for(int8_t i=0; i < n ; i++) + { + //int z = 0; + + if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)) + { + //current_position[Z_AXIS] = 0; + //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = 1.1 * Z_MAX_LENGTH * Z_HOME_DIR; + feedrate = fast_home_feedrate[Z_AXIS]; + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + + //current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = current_position[Z_AXIS] - Z_HOME_RETRACT_MM * Z_HOME_DIR; + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + + destination[Z_AXIS] = current_position[Z_AXIS] + 2*Z_HOME_RETRACT_MM * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]; + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + + //current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? Z_HOME_POS : Z_MAX_LENGTH; + //destination[Z_AXIS] = current_position[Z_AXIS]; + feedrate = 0.0; + endstops_hit_on_purpose(); + } + + if(endstop_z_hit == true) + { + ProbeDepth[i]= endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]; + SERIAL_ECHO("ProbeDepth[");SERIAL_ECHO(i);SERIAL_ECHO("]=");SERIAL_ECHOLN(ProbeDepth[i]); + } + //************************************************************************************************************* + if (i > 0 ) //Second probe has happened so compare results + { + if (abs(ProbeDepth[i] - ProbeDepth[i - 1]) > .05) + { //keep going until readings match to avoid sticky bed + SERIAL_ECHO("Probing again: "); + SERIAL_ECHO(ProbeDepth[i]); SERIAL_ECHO(" - "); SERIAL_ECHO(ProbeDepth[i - 1]);SERIAL_ECHO(" = "); SERIAL_ECHOLN(abs(ProbeDepth[i] - ProbeDepth[i - 1])); + i--; i--; //Throw out both that don't match because we don't know which one is accurate + if(fails++ > 9) break; + } + } + //************************************************************************************************************************************************** + //fast move clear + //z = 0; + //current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = -Z_HOME_RETRACT_MM * Z_HOME_DIR; + feedrate = fast_home_feedrate[Z_AXIS]; + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + + //check z stop isn't still triggered + if ( READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING ) + { + SERIAL_ECHOLN("Poking Stuck Bed:"); + destination[Z_AXIS] = -1; prepare_move(); + destination[Z_AXIS] = Z_HOME_RETRACT_MM; prepare_move(); + st_synchronize(); + i--; //Throw out this meaningless probe + } + feedrate = 0; + } //end probe loop + #ifdef ENDSTOPS_ONLY_FOR_HOMING + enable_endstops(false); + #endif + + feedrate = saved_feedrate; + feedmultiply = saved_feedmultiply; + //previous_millis_cmd = millis(); + endstops_hit_on_purpose(); + } + for(int8_t i=0;i -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)) - { + //current_position[Z_AXIS] = 0; - //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[Z_AXIS] = 1.1 * Z_MAX_LENGTH * Z_HOME_DIR; feedrate = fast_home_feedrate[Z_AXIS]; plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); @@ -52,6 +50,7 @@ float Probe_Bed(float x_pos, float y_pos, int n) plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); st_synchronize(); + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[Z_AXIS] = current_position[Z_AXIS] + 2*Z_HOME_RETRACT_MM * Z_HOME_DIR; feedrate = homing_feedrate[Z_AXIS]; plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); @@ -60,34 +59,38 @@ float Probe_Bed(float x_pos, float y_pos, int n) //current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? Z_HOME_POS : Z_MAX_LENGTH; //destination[Z_AXIS] = current_position[Z_AXIS]; feedrate = 0.0; - endstops_hit_on_purpose(); - } + //endstops_hit_on_purpose(); + SERIAL_ECHO("current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); if(endstop_z_hit == true) { ProbeDepth[i]= endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]; SERIAL_ECHO("ProbeDepth[");SERIAL_ECHO(i);SERIAL_ECHO("]=");SERIAL_ECHOLN(ProbeDepth[i]); + //************************************************************************************************************* + if (i > 0 ) //Second probe has happened so compare results + { + if (abs(ProbeDepth[i] - ProbeDepth[i - 1]) > .05) + { //keep going until readings match to avoid sticky bed + SERIAL_ECHO("Probing again: "); + SERIAL_ECHO(ProbeDepth[i]); SERIAL_ECHO(" - "); SERIAL_ECHO(ProbeDepth[i - 1]);SERIAL_ECHO(" = "); SERIAL_ECHOLN(abs(ProbeDepth[i] - ProbeDepth[i - 1])); + i--; i--; //Throw out both that don't match because we don't know which one is accurate + if(fails++ > 4) break; + } + } + }else{ + SERIAL_ECHOLN("Probe not triggered."); + i=n-1; } - //************************************************************************************************************* - if (i > 0 ) //Second probe has happened so compare results - { - if (abs(ProbeDepth[i] - ProbeDepth[i - 1]) > .05) - { //keep going until readings match to avoid sticky bed - SERIAL_ECHO("Probing again: "); - SERIAL_ECHO(ProbeDepth[i]); SERIAL_ECHO(" - "); SERIAL_ECHO(ProbeDepth[i - 1]);SERIAL_ECHO(" = "); SERIAL_ECHOLN(abs(ProbeDepth[i] - ProbeDepth[i - 1])); - i--; i--; //Throw out both that don't match because we don't know which one is accurate - if(fails++ > 9) break; - } - } //************************************************************************************************************************************************** //fast move clear //z = 0; //current_position[Z_AXIS] = 0; plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = -Z_HOME_RETRACT_MM * Z_HOME_DIR; + destination[Z_AXIS] = current_position[Z_AXIS]-Z_HOME_RETRACT_MM * Z_HOME_DIR; feedrate = fast_home_feedrate[Z_AXIS]; plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); st_synchronize(); + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); //check z stop isn't still triggered if ( READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING ) @@ -96,7 +99,7 @@ float Probe_Bed(float x_pos, float y_pos, int n) destination[Z_AXIS] = -1; prepare_move(); destination[Z_AXIS] = Z_HOME_RETRACT_MM; prepare_move(); st_synchronize(); - i--; //Throw out this meaningless probe + i--; //Throw out this meaningless measurement } feedrate = 0; } //end probe loop @@ -114,7 +117,11 @@ float Probe_Bed(float x_pos, float y_pos, int n) ProbeDepthAvg += ProbeDepth[i]; } ProbeDepthAvg /= n; - SERIAL_ECHO("Z="); SERIAL_ECHOLN(ProbeDepthAvg); + SERIAL_ECHO("Probed Z="); SERIAL_ECHOLN(ProbeDepthAvg); + SERIAL_ECHO("RAW current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); +// current_position[Z_AXIS]+=ProbeDepthAvg; +// SERIAL_ECHO("ADJUSTED current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); return ProbeDepthAvg; } @@ -220,13 +227,13 @@ G1 Z5 F200 ;Lift Z out of way void probe_3points() { float Probe_Avg, Point1, Point2, Point3; - Point1 = Probe_Bed(10, 10,PROBE_N); - Point2 = Probe_Bed(X_MAX_LENGTH - 20, 10,PROBE_N) ; - Point3 = Probe_Bed(X_MAX_LENGTH/2, Y_MAX_LENGTH - 5,PROBE_N); + Point1 = Probe_Bed(15,15,PROBE_N); + Point2 = Probe_Bed(X_MAX_LENGTH - 20,15,PROBE_N) ; + Point3 = Probe_Bed(X_MAX_LENGTH/2,Y_MAX_LENGTH - 5,PROBE_N); Probe_Avg = (Point1 + Point2 + Point3) / 3; - destination[2] = Probe_Avg; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); + //destination[2] = Probe_Avg; + //feedrate = homing_feedrate[Z_AXIS]; + //prepare_move(); SERIAL_ECHOLN("**************************************"); SERIAL_ECHO("Point1 ="); SERIAL_ECHOLN(Point1); SERIAL_ECHO("Point2 ="); SERIAL_ECHOLN(Point2); @@ -239,9 +246,9 @@ void probe_1point() { float Point; Point = Probe_Bed(-1,-1,PROBE_N); - destination[2] = Point +1; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); + //destination[2] = Point +1; + //feedrate = homing_feedrate[Z_AXIS]; + //prepare_move(); SERIAL_ECHOLN("**************************************"); SERIAL_ECHO("Probed Z="); SERIAL_ECHOLN(Point); } diff --git a/Marlin/z_probe.h b/Marlin/z_probe.h index f86bf7f8a2..98935e48f3 100644 --- a/Marlin/z_probe.h +++ b/Marlin/z_probe.h @@ -8,14 +8,14 @@ void probe_3points(); void probe_1point(); void probe_status(); - float Probe_Bed(float x_pos, float y_pos, int n); + float Probe_Bed(float x_pos, float y_pos,int n); #else //no probe pin FORCE_INLINE void probe_init() {}; FORCE_INLINE void probe_3points() {}; FORCE_INLINE void probe_1point() {}; FORCE_INLINE void probe_status() {}; - FORCE_INLINE float Probe_Bed(float x_pos, float y_pos, int n) {return 0;} + FORCE_INLINE float Probe_Bed(float x_pos, float y_pos,int n) {return 0;} #endif //PROBE_PIN #endif From eba50c1d0e12a282548c521089654ad7aa1e07c9 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Wed, 28 Mar 2012 15:02:42 +0100 Subject: [PATCH 220/228] probing actually working now --- Marlin/Configuration_adv.h | 2 +- Marlin/FPUTransform.cpp | 112 ++++++++++++++++--------------------- Marlin/z_probe.cpp | 42 ++++++++------ 3 files changed, 73 insertions(+), 83 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 9a44923927..baf757ea05 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -84,7 +84,7 @@ //homing hits the endstop, then retracts by this distance, before it tries to slowly bump again: #define X_HOME_RETRACT_MM 4 #define Y_HOME_RETRACT_MM 4 -#define Z_HOME_RETRACT_MM 1 +#define Z_HOME_RETRACT_MM 2 //#define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially. #define AXIS_RELATIVE_MODES {false, false, false, false} diff --git a/Marlin/FPUTransform.cpp b/Marlin/FPUTransform.cpp index cfffabc46b..17d7660306 100755 --- a/Marlin/FPUTransform.cpp +++ b/Marlin/FPUTransform.cpp @@ -8,16 +8,15 @@ float MasterTransform[4][4]; // this is the transform that describes how to move // ideal coordinates to real world coords // private functions -void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3, float Z4); +void loadMatrix(float X4, float Y3, float Z1, float X2, float Y2, float Z2, float X3, float Z3, float Z4); void transformDestination(float &X, float &Y, float &Z); bool FPUEnabled; // this is a bypass switch so that with one command the FPU can be // turned off -void loadMatrix(float X1, float Y1, float Z1, float Y2, float Z2, float X3, float Z3, float Z4) +void loadMatrix(float X4, float Y1, float Z1, float X2, float Y2, float Z2, float X3, float Z3, float Z4) { -//add calculated 4th point -float Xdiff = X3 - X1; +float Xdiff = X4 - X3; serialPrintFloat(Xdiff); SERIAL_ECHOLN(""); float Ydiff = Y2 - Y1; @@ -53,73 +52,57 @@ float sinytheta = Ytheta; // serialPrintFloat(sinytheta); // SERIAL_ECHOLN(""); - -// Start by moving X and Y to 0 (seperating this out as we want to undo this later) -float Translate00Z[4][4] = {{1.0, 0.0, 0.0, -X1}, +//these transforms are to set the origin for each rotation +float TranslateX0[4][4] = {{1.0, 0.0, 0.0, -X3}, {0.0, 1.0, 0.0, -Y1}, - {0.0, 0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0, -Z3}, {0.0, 0.0, 0.0, 1.0}}; -//now move Z to 0 -float TranslateZ0[4][4] = {{1.0, 0.0, 0.0, 0.0}, - {0.0, 1.0, 0.0, 0.0}, +float TranslateY0[4][4] = {{1.0, 0.0, 0.0, -X2}, + {0.0, 1.0, 0.0, -Y1}, {0.0, 0.0, 1.0, -Z1}, {0.0, 0.0, 0.0, 1.0}}; -float Transform0[4][4]; -matrixMaths.MatrixMult((float*)Translate00Z, (float*)TranslateZ0, 4, 4, 4, (float*)Transform0); - -//first rotate in Y using XZ -//[cos(t), 0, -sin(t), 0] -//[0 , 1, 0 , 0] -//[sin{t}, 0, cos(t), 0] -//[0 , 0, 0 , 1] - -float Transform1[4][4] = {{cosxtheta, 0.0, sinxtheta, 0.0}, +//rotate in Y using XZ +float TransformY[4][4] = {{cosxtheta, 0.0, sinxtheta, 0.0}, { 0.0, 1.0, 0.0, 0.0}, {-sinxtheta, 0.0, cosxtheta, 0.0}, { 0.0, 0.0, 0.0, 1.0}}; -//matrixMaths.MatrixPrint((float*)Transform1, 4, 4, "Transform1"); -float rotMatrix1[4][4]; -matrixMaths.MatrixMult((float*)Transform1, (float*)Transform0, 4, 4, 4, (float*)rotMatrix1); - -//first rotate in X using YZ -//[1, 0, 0 , 0] -//[0, cos(t), sin(t), 0] -//[0, -sin{t}, cos(t), 0] -//[0, 0, 0 , 1] - -float Transform2[4][4] = {{ 1.0, 0.0, 0.0, 0.0}, +//rotate in X using YZ +float TransformX[4][4] = {{ 1.0, 0.0, 0.0, 0.0}, { 0.0, cosytheta, sinytheta, 0.0}, { 0.0,sinytheta, cosytheta, 0.0}, { 0.0, 0.0, 0.0, 1.0}}; -//matrixMaths.MatrixPrint((float*)Transform2, 4, 4, "Transform2"); -//float rotMatrix[4][4]; -//matrixMaths.MatrixMult((float*)Transform1, (float*)Transform2, 4, 4, 4, (float*)rotMatrix); -float rotMatrix2[4][4]; -matrixMaths.MatrixMult((float*)Transform2, (float*)rotMatrix1, 4, 4, 4, (float*)rotMatrix2); -//translate back to XY -//matrixMaths.MatrixInvert((float*)Translate00Z, 4); -Translate00Z[0][3] = X1; -Translate00Z[1][3] = Y1; -matrixMaths.MatrixMult((float*)rotMatrix2, (float*)Translate00Z, 4, 4, 4, (float*)MasterTransform); -//matrixMaths.MatrixPrint((float*)rotMatrix, 4, 4, "rotMatrix"); -//now we have the object in a plane that is parallel to the x axes, but we do not have the z height correct. -//transform the x15 y15 position using our rotation matrix and use the result to determine where z0 is and -//add this translate function to the transform matrix. -//float zError[4][1]={{X1},{Y1},{Z1},{1.0}}; -//float zErrNew[1][4]; -//matrixMaths.MatrixMult((float*)rotMatrix, (float*)zError, 1, 4, 4, (float*)zErrNew); +// first translate point1 to 0 then rotate in Y then translate back +float MatrixStage1[4][4]; +float MatrixStage2[4][4]; +//matrixMaths.MatrixMult((float*)TranslateY0, (float*)TransformX, 4, 4, 4, (float*)MatrixStage1); +//matrixMaths.MatrixPrint((float*)MatrixStage1, 4, 4, "MatrixStage1"); +//TranslateY0[0][3] = -TranslateY0[0][3]; +//TranslateY0[1][3] = -TranslateY0[1][3]; +//TranslateY0[2][3] = -TranslateY0[2][3]; +//matrixMaths.MatrixPrint((float*)TranslateY0, 4, 4, "TranslateY0"); +//matrixMaths.MatrixMult((float*)MatrixStage1, (float*)TranslateY0, 4, 4, 4, (float*)MatrixStage2); +//matrixMaths.MatrixPrint((float*)MatrixStage2, 4, 4, "MatrixStage2"); +//Now translate point3 to 0 and rotate in x before translating back +float MatrixStage3[4][4]; +float MatrixStage4[4][4]; +//matrixMaths.MatrixMult((float*)MatrixStage2, (float*)TranslateX0, 4, 4, 4, (float*)MatrixStage3); +//matrixMaths.MatrixPrint((float*)MatrixStage3, 4, 4, "MatrixStage3"); +//matrixMaths.MatrixMult((float*)MatrixStage3, (float*)TransformY, 4, 4, 4, (float*)MatrixStage4); +matrixMaths.MatrixMult((float*)TransformX, (float*)TransformY, 4, 4, 4, (float*)MasterTransform); +matrixMaths.MatrixPrint((float*)MatrixStage4, 4, 4, "MatrixStage4"); +//TranslateX0[0][3] = -TranslateX0[0][3]; +//TranslateX0[1][3] = -TranslateX0[1][3]; +//TranslateX0[2][3] = -TranslateX0[2][3]; +//matrixMaths.MatrixPrint((float*)TranslateX0, 4, 4, "TranslateX0"); +//matrixMaths.MatrixMult((float*)MatrixStage4, (float*)TranslateX0, 4, 4, 4, (float*)MasterTransform); +//matrixMaths.MatrixPrint((float*)MasterTransform, 4, 4, "MasterTransform (pre-invert)"); -//float zTranslate[4][4] = {{ 1.0, 0.0, 0.0, 0.0}, -// { 0.0, 1.0, 0.0, 0.0}, -// { 0.0, 0.0, 1.0, 0.0}, -// { 15-zErrNew[0][0],15-zErrNew[1][0],-zErrNew[2][0], 1.0}}; -//matrixMaths.MatrixMult((float*)rotMatrix, (float*)zTranslate, 4, 4, 4, (float*)MasterTransform); - -// We now have a way to translate from real-world coordinates to idealised coortdinates, // but what we actually want is a way to transform from the idealised g-code coordinates +// We now have a way to translate from real-world coordinates to idealised coortdinates, +// but what we actually want is a way to transform from the idealised g-code coordinates // to real world coordinates. // This is simply the inverse. matrixMaths.MatrixInvert((float*)MasterTransform, 4); @@ -169,23 +152,24 @@ void FPUDisable() void FPUTransform_determineBedOrientation() { -int X1 = 10; -int Y1 = 10; -float Z1; +int X3 = 15; +float X4 = X_MAX_LENGTH - 20; +float X2 = (X4 + X3) / 2; +int Y1 = 15; float Y2 = Y_MAX_LENGTH - 5; +float Z1; float Z2; -float X3 = X_MAX_LENGTH - 20; float Z3; float Z4; //get Z for X15 Y15, X15 Y(Y_MAX_LENGTH - 15) and X(X_MAX_LENGTH - 15) Y15 -Z3 = Probe_Bed(10,10,PROBE_N); -Z4 = Probe_Bed(X3,10,PROBE_N); +Z3 = Probe_Bed(X3,Y1,PROBE_N); +Z4 = Probe_Bed(X4,Y1,PROBE_N); Z1 = (Z3 + Z4) / 2; -Z2 = Probe_Bed(X3/2,Y2,PROBE_N); +Z2 = Probe_Bed(X2,Y2,PROBE_N); if(FPUEnabled) { - loadMatrix(X1, Y1, Z1, Y2, Z2, X3, Z3, Z4); + loadMatrix(X4, Y1, Z1, X2, Y2, Z2, X3, Z3, Z4); } } diff --git a/Marlin/z_probe.cpp b/Marlin/z_probe.cpp index ef50dda72d..d6ba480169 100644 --- a/Marlin/z_probe.cpp +++ b/Marlin/z_probe.cpp @@ -15,14 +15,18 @@ float Probe_Bed(float x_pos, float y_pos, int n) if (Z_HOME_DIR==-1) { //int probe_flag =1; + float start_z = current_position[Z_AXIS]; int fails = 0; saved_feedrate = feedrate; saved_feedmultiply = feedmultiply; feedmultiply = 100; //previous_millis_cmd = millis(); + + //Move to probe position if (x_pos >= 0) destination[X_AXIS]=x_pos; if (y_pos >= 0) destination[Y_AXIS]=y_pos; - destination[Z_AXIS]=current_position[Z_AXIS]; + //destination[Z_AXIS]=current_position[Z_AXIS]; + destination[Z_AXIS]=Z_HOME_RETRACT_MM; feedrate = 9000; prepare_move(); @@ -37,24 +41,25 @@ float Probe_Bed(float x_pos, float y_pos, int n) { //int z = 0; - //current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + //fast probe + //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); destination[Z_AXIS] = 1.1 * Z_MAX_LENGTH * Z_HOME_DIR; - feedrate = fast_home_feedrate[Z_AXIS]; + feedrate = homing_feedrate[Z_AXIS]; plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); st_synchronize(); - //current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS] - Z_HOME_RETRACT_MM * Z_HOME_DIR; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - st_synchronize(); + //back off + //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + //destination[Z_AXIS] = Z_HOME_RETRACT_MM * Z_HOME_DIR; + //plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + //st_synchronize(); - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS] + 2*Z_HOME_RETRACT_MM * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - st_synchronize(); + //slow probe + //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + //destination[Z_AXIS] = 2*Z_HOME_RETRACT_MM * Z_HOME_DIR; + //feedrate = homing_feedrate[Z_AXIS]; + //plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + //st_synchronize(); //current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? Z_HOME_POS : Z_MAX_LENGTH; //destination[Z_AXIS] = current_position[Z_AXIS]; @@ -64,6 +69,7 @@ float Probe_Bed(float x_pos, float y_pos, int n) SERIAL_ECHO("current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); if(endstop_z_hit == true) { + SERIAL_ECHO("endstops_trigsteps[Z_AXIS]=");SERIAL_ECHOLN(endstops_trigsteps[Z_AXIS]); ProbeDepth[i]= endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]; SERIAL_ECHO("ProbeDepth[");SERIAL_ECHO(i);SERIAL_ECHO("]=");SERIAL_ECHOLN(ProbeDepth[i]); //************************************************************************************************************* @@ -85,12 +91,12 @@ float Probe_Bed(float x_pos, float y_pos, int n) //fast move clear //z = 0; //current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS]-Z_HOME_RETRACT_MM * Z_HOME_DIR; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], ProbeDepth[i], current_position[E_AXIS]); + destination[Z_AXIS] = Z_HOME_RETRACT_MM;//start_z; feedrate = fast_home_feedrate[Z_AXIS]; plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); st_synchronize(); - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); //check z stop isn't still triggered if ( READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING ) @@ -121,7 +127,7 @@ float Probe_Bed(float x_pos, float y_pos, int n) SERIAL_ECHO("RAW current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); // current_position[Z_AXIS]+=ProbeDepthAvg; // SERIAL_ECHO("ADJUSTED current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], Z_HOME_RETRACT_MM, current_position[E_AXIS]); return ProbeDepthAvg; } From a3915a5351252f0265278f6dab6221384db42f1a Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Tue, 3 Apr 2012 16:58:20 +0100 Subject: [PATCH 221/228] some #ifs added to cope with SL 1.1! --- Marlin/Marlin.pde | 5 +- Marlin/stepper.cpp | 24 ++++++--- Marlin/z_probe.cpp | 118 +++------------------------------------------ 3 files changed, 29 insertions(+), 118 deletions(-) diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index c6dec40c52..d3d848c515 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1429,7 +1429,7 @@ void controllerFan() if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms { lastMotorCheck = millis(); - + #if (X_ENABLE_PIN > -1 && Y_ENABLE_PIN > -1 && Z_ENABLE_PIN > -1 && E0_ENABLE_PIN > -1) if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) #if EXTRUDERS > 2 || !READ(E2_ENABLE_PIN) @@ -1441,6 +1441,9 @@ void controllerFan() { lastMotor = millis(); //... set time to NOW so the fan will turn on } + #else + lastMotor = millis(); + #endif if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC... { diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 1b35c9db33..f66d869d4c 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -715,27 +715,39 @@ void st_init() //Initialize Step Pins #if (X_STEP_PIN > -1) SET_OUTPUT(X_STEP_PIN); - if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); + #if X_ENABLE_PIN > -1 + if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); + #endif #endif #if (Y_STEP_PIN > -1) SET_OUTPUT(Y_STEP_PIN); - if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); + #if Y_ENABLE_PIN > -1 + if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); + #endif #endif #if (Z_STEP_PIN > -1) SET_OUTPUT(Z_STEP_PIN); - if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); + #if Z_ENABLE_PIN > -1 + if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); + #endif #endif #if (E0_STEP_PIN > -1) SET_OUTPUT(E0_STEP_PIN); - if(!E_ENABLE_ON) WRITE(E0_ENABLE_PIN,HIGH); + #if E0_ENABLE_PIN > -1 + if(!E_ENABLE_ON) WRITE(E0_ENABLE_PIN,HIGH); + #endif #endif #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) SET_OUTPUT(E1_STEP_PIN); - if(!E_ENABLE_ON) WRITE(E1_ENABLE_PIN,HIGH); + #if E1_ENABLE_PIN > -1 + if(!E_ENABLE_ON) WRITE(E1_ENABLE_PIN,HIGH); + #endif #endif #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) SET_OUTPUT(E2_STEP_PIN); - if(!E_ENABLE_ON) WRITE(E2_ENABLE_PIN,HIGH); + #if E2_ENABLE_PIN > -1 + if(!E_ENABLE_ON) WRITE(E2_ENABLE_PIN,HIGH); + #endif #endif #ifdef CONTROLLERFAN_PIN diff --git a/Marlin/z_probe.cpp b/Marlin/z_probe.cpp index d6ba480169..ce61cd6fef 100644 --- a/Marlin/z_probe.cpp +++ b/Marlin/z_probe.cpp @@ -3,9 +3,6 @@ #include "Marlin.h" #include "stepper.h" -#define PROBE_DOWN - -#ifdef PROBE_DOWN float Probe_Bed(float x_pos, float y_pos, int n) { //returns Probed Z average height @@ -15,7 +12,7 @@ float Probe_Bed(float x_pos, float y_pos, int n) if (Z_HOME_DIR==-1) { //int probe_flag =1; - float start_z = current_position[Z_AXIS]; + float meas = 0; int fails = 0; saved_feedrate = feedrate; saved_feedmultiply = feedmultiply; @@ -48,29 +45,14 @@ float Probe_Bed(float x_pos, float y_pos, int n) plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); st_synchronize(); - //back off - //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - //destination[Z_AXIS] = Z_HOME_RETRACT_MM * Z_HOME_DIR; - //plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - //st_synchronize(); - - //slow probe - //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - //destination[Z_AXIS] = 2*Z_HOME_RETRACT_MM * Z_HOME_DIR; - //feedrate = homing_feedrate[Z_AXIS]; - //plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); - //st_synchronize(); - - //current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? Z_HOME_POS : Z_MAX_LENGTH; - //destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0.0; - //endstops_hit_on_purpose(); + //feedrate = 0.0; SERIAL_ECHO("current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); if(endstop_z_hit == true) { SERIAL_ECHO("endstops_trigsteps[Z_AXIS]=");SERIAL_ECHOLN(endstops_trigsteps[Z_AXIS]); ProbeDepth[i]= endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]; + meas = ProbeDepth[i]; SERIAL_ECHO("ProbeDepth[");SERIAL_ECHO(i);SERIAL_ECHO("]=");SERIAL_ECHOLN(ProbeDepth[i]); //************************************************************************************************************* if (i > 0 ) //Second probe has happened so compare results @@ -79,6 +61,7 @@ float Probe_Bed(float x_pos, float y_pos, int n) { //keep going until readings match to avoid sticky bed SERIAL_ECHO("Probing again: "); SERIAL_ECHO(ProbeDepth[i]); SERIAL_ECHO(" - "); SERIAL_ECHO(ProbeDepth[i - 1]);SERIAL_ECHO(" = "); SERIAL_ECHOLN(abs(ProbeDepth[i] - ProbeDepth[i - 1])); + meas = ProbeDepth[i]; i--; i--; //Throw out both that don't match because we don't know which one is accurate if(fails++ > 4) break; } @@ -89,14 +72,11 @@ float Probe_Bed(float x_pos, float y_pos, int n) } //************************************************************************************************************************************************** //fast move clear - //z = 0; - //current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], ProbeDepth[i], current_position[E_AXIS]); - destination[Z_AXIS] = Z_HOME_RETRACT_MM;//start_z; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], meas, current_position[E_AXIS]); + destination[Z_AXIS] = Z_HOME_RETRACT_MM; feedrate = fast_home_feedrate[Z_AXIS]; plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); st_synchronize(); - //plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); //check z stop isn't still triggered if ( READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING ) @@ -125,95 +105,11 @@ float Probe_Bed(float x_pos, float y_pos, int n) ProbeDepthAvg /= n; SERIAL_ECHO("Probed Z="); SERIAL_ECHOLN(ProbeDepthAvg); SERIAL_ECHO("RAW current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); -// current_position[Z_AXIS]+=ProbeDepthAvg; -// SERIAL_ECHO("ADJUSTED current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], Z_HOME_RETRACT_MM, current_position[E_AXIS]); return ProbeDepthAvg; } -#else -//Crash1 - Probes bed at least twice until distances are similar then takes average of 2 -float Probe_Bed(float x_pos, float y_pos) -{ - //returns Probed Z average height - float ProbeDepth[6], ProbeDepthAvg; - if (Z_HOME_DIR==-1) - { - saved_feedrate = feedrate; - destination[Z_AXIS] = 3; //* Z_HOME_DIR; //Lift over bed for initial Move - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); - - //Move to Probe Coordinates, Use current Position if none given - if (x_pos < 0) - destination[X_AXIS] = current_position[X_AXIS]; - else - destination[X_AXIS] = x_pos; - if (y_pos < 0) - destination[Y_AXIS] = current_position[Y_AXIS]; - else - destination[Y_AXIS] = y_pos; - feedrate = 7500; // 500 is way too slow- WTF - max_feedrate[X_AXIS]; //homing_feedrate[X_AXIS]; //250; - prepare_move(); - - destination[Z_AXIS] = .75; //* Z_HOME_DIR; //move close to Z Home - bed should be within .75mm of level - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); - - //Plunge down final distance slowly until bed breaks contact and pin true - //*******************************************************************************************Bed Loop************************************* - for(int8_t i=0; i < 2 ; i++) - { //probe 2 or more times to get repeatable reading - //2DO If bed currently true then it is stuck - need to do something smart here. - int probeSteps = 500; //distance to move down and max distance to scan up in one step. - int z = 0; - while(READ(PROBE_PIN) == false && z < probeSteps) - { //if it takes more than 500 steps then something is wrong - destination[Z_AXIS] = current_position[Z_AXIS] - Z_INCREMENT; //* Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); - z++; - } - //move up in small increments until switch makes - z = 0; - while(READ(PROBE_PIN) == true && z < probeSteps) - { //if it takes more than 100 steps then bed is likely stuck - still need to error on this to stop process - destination[Z_AXIS] = current_position[Z_AXIS] + Z_INCREMENT; //* Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); - z++; - } - //************************************************************************************************************************************************** - //if Z is probeSteps here then we have a stuck bed and it will keep on advancing upward. So send hot end toward Zstop to try to unstick. - if (z == probeSteps) - { - SERIAL_ECHOLN("Poking Stuck Bed:"); - destination[Z_AXIS] = 1; feedrate = homing_feedrate[Z_AXIS]; prepare_move(); - destination[Z_AXIS] = .2; feedrate = homing_feedrate[Z_AXIS]; prepare_move(); - destination[Z_AXIS] = 1; feedrate = homing_feedrate[Z_AXIS]; prepare_move(); - i--; //Throw out this meaningless probe - z == 0; - } - //************************************************************************************************************* - ProbeDepth[i]= current_position[Z_AXIS]; - if (i == 1 ) - { - if (abs(ProbeDepth[i] - ProbeDepth[i - 1]) > .02) - { //keep going until readings match to avoid sticky bed - SERIAL_ECHO("Probing again - difference:"); SERIAL_ECHO(abs(ProbeDepth[i] - ProbeDepth[i - 1])); SERIAL_ECHO(", Z="); SERIAL_ECHOLN(ProbeDepth[i]); - i -= 2; //Throw out both that don't match because we don't know which one is accurate - } - } - feedrate = 0; - } //end probe loop - feedrate = saved_feedrate; - } - ProbeDepthAvg = (ProbeDepth[0] + ProbeDepth[1]) / 2; - SERIAL_ECHO("Z="); SERIAL_ECHOLN(ProbeDepthAvg); - return ProbeDepthAvg; - } -//Crash1 END Add Probe Bed Function -#endif + void probe_init() { SET_INPUT(PROBE_PIN); From 0580997a9917557ed4ecdba81cd2f360d82d4d59 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Mon, 7 May 2012 19:42:55 +0100 Subject: [PATCH 222/228] M206 persistent. --- Marlin/Configuration.h | 24 +++++++++++++----------- Marlin/EEPROMwrite.h | 7 +++++++ Marlin/FPUTransform.cpp | 0 Marlin/create_speed_lookuptable.py | 0 Marlin/pins.h | 10 +++++----- Marlin/z_probe.cpp | 8 ++++++++ 6 files changed, 33 insertions(+), 16 deletions(-) mode change 100755 => 100644 Marlin/FPUTransform.cpp mode change 100755 => 100644 Marlin/create_speed_lookuptable.py diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 15931b64bc..20589d5620 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -8,7 +8,7 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-03-26-1" //Personal revision number for changes to THIS file. +#define STRING_VERSION_CONFIG_H "2012-04-12-2" //Personal revision number for changes to THIS file. #define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. // This determines the communication speed of the printer @@ -48,11 +48,13 @@ // 7 is 100k Honeywell thermistor 135-104LAG-J01 // 100 is 100k GE Sensing AL03006-58.2K-97-G1 // 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT +// 102 is 100k EPCOS G57540 Nozzle +// 103 is 100k EPCOS G57540 Bed -#define TEMP_SENSOR_0 102 +#define TEMP_SENSOR_0 100 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 103 +#define TEMP_SENSOR_BED 101 // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 10 // (seconds) @@ -139,11 +141,11 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define DISABLE_E false // For all extruders #define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR true // for Mendel set to true, for Orca set to false +#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false #define INVERT_Z_DIR false // for Mendel set to false, for Orca set to true -#define INVERT_E0_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E1_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false -#define INVERT_E2_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E0_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E1_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false +#define INVERT_E2_DIR true // for direct drive extruder v9 set to true, for geared extruder set to false // ENDSTOP SETTINGS: // Sets direction of endstops when homing; 1=MAX, -1=MIN @@ -153,8 +155,8 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define min_software_endstops true //If true, axis won't move to coordinates less than zero. #define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 145 -#define Y_MAX_LENGTH 145 +#define X_MAX_LENGTH 145 //155 for v2 +#define Y_MAX_LENGTH 145 //150 for v2 #define Z_MAX_LENGTH 100 // The position of the homing switches. Use MAX_LENGTH * -0.5 if the center should be 0, 0, 0 @@ -172,7 +174,7 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker //#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,850} #define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {1000,1000,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. +#define DEFAULT_MAX_ACCELERATION {1000,1000,50,1000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. #define DEFAULT_ACCELERATION 1000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 1000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts @@ -180,7 +182,7 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t // #define DEFAULT_XYJERK 15.0 // (mm/sec) #define DEFAULT_ZJERK 0.4 // (mm/sec) -#define DEFAULT_EJERK 5.0 // (mm/sec) +#define DEFAULT_EJERK 15.0 // (mm/sec) //=========================================================================== //=============================Additional Features=========================== diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index fa07592025..2bb5b5cbbc 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -58,6 +58,7 @@ inline void EEPROM_StoreSettings() EEPROM_writeAnything(i,max_xy_jerk); EEPROM_writeAnything(i,max_z_jerk); EEPROM_writeAnything(i,max_e_jerk); + EEPROM_writeAnything(i,add_homeing); #ifdef PIDTEMP EEPROM_writeAnything(i,Kp); EEPROM_writeAnything(i,Ki); @@ -124,6 +125,11 @@ inline void EEPROM_printSettings() SERIAL_ECHOPAIR(" Z" ,max_z_jerk); SERIAL_ECHOPAIR(" E" ,max_e_jerk); SERIAL_ECHOLN(""); + SERIAL_ECHO_START; + SERIAL_ECHOPAIR(" M206 X",add_homeing[0]); + SERIAL_ECHOPAIR(" Y",add_homeing[1] ); + SERIAL_ECHOPAIR(" Z", add_homeing[2] ); + SERIAL_ECHOLN(""); #ifdef PIDTEMP SERIAL_ECHO_START; SERIAL_ECHOLNPGM("PID settings:"); @@ -163,6 +169,7 @@ inline void EEPROM_RetrieveSettings(bool def=false) EEPROM_readAnything(i,max_xy_jerk); EEPROM_readAnything(i,max_z_jerk); EEPROM_readAnything(i,max_e_jerk); + EEPROM_readAnything(i,add_homeing); #ifndef PIDTEMP float Kp,Ki,Kd; int Ki_Max; diff --git a/Marlin/FPUTransform.cpp b/Marlin/FPUTransform.cpp old mode 100755 new mode 100644 diff --git a/Marlin/create_speed_lookuptable.py b/Marlin/create_speed_lookuptable.py old mode 100755 new mode 100644 diff --git a/Marlin/pins.h b/Marlin/pins.h index 44a7d63abb..681f608056 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -579,16 +579,16 @@ #define Z_STEP_PIN 3 #define Z_DIR_PIN 2 -#define Z_MIN_PIN 11//20 +#define Z_MIN_PIN 20 //for Melzi Z bed probe, 20 for standard Z endstop #define Z_MAX_PIN -1 #define E0_STEP_PIN 1 #define E0_DIR_PIN 0 -#define PROBE_PIN 11 //29 on Melzi1284p A2, 11 on SL1.3a +#define PROBE_PIN -1 //29 on Melzi1284p A2, 11 on SL1.3a -#define LED_PIN 27 //27 on Melzi1284p -#define FAN_PIN 4 //4 on Melzi1284p +#define LED_PIN -1//27 //27 on Melzi1284p +#define FAN_PIN 12 //4 on Melzi1284p #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -599,7 +599,7 @@ #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 diff --git a/Marlin/z_probe.cpp b/Marlin/z_probe.cpp index ce61cd6fef..7c696cf0e1 100644 --- a/Marlin/z_probe.cpp +++ b/Marlin/z_probe.cpp @@ -2,6 +2,7 @@ #if defined(PROBE_PIN) && (PROBE_PIN > -1) #include "Marlin.h" #include "stepper.h" +#include "temperature.h" float Probe_Bed(float x_pos, float y_pos, int n) { @@ -9,6 +10,11 @@ float Probe_Bed(float x_pos, float y_pos, int n) float ProbeDepth[n]; float ProbeDepthAvg=0; + //force bed heater off for probing + int save_bed_targ = target_raw_bed; + target_raw_bed = 0; + WRITE(HEATER_BED_PIN,LOW); + if (Z_HOME_DIR==-1) { //int probe_flag =1; @@ -106,7 +112,9 @@ float Probe_Bed(float x_pos, float y_pos, int n) SERIAL_ECHO("Probed Z="); SERIAL_ECHOLN(ProbeDepthAvg); SERIAL_ECHO("RAW current_position[Z_AXIS]=");SERIAL_ECHOLN(current_position[Z_AXIS]); plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], Z_HOME_RETRACT_MM, current_position[E_AXIS]); + current_position[Z_AXIS] = Z_HOME_RETRACT_MM; + target_raw_bed = save_bed_targ; return ProbeDepthAvg; } From 34d72198e68a6d2c9ccd142bc76afacd1d2049cc Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Tue, 22 May 2012 10:05:39 +0100 Subject: [PATCH 223/228] more thermistor tables added --- Marlin/Configuration.h | 21 ++++---- Marlin/pins.h | 4 +- Marlin/thermistortables.h | 108 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 11 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 20589d5620..edd6947ab2 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -46,15 +46,18 @@ // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k // 7 is 100k Honeywell thermistor 135-104LAG-J01 -// 100 is 100k GE Sensing AL03006-58.2K-97-G1 -// 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT -// 102 is 100k EPCOS G57540 Nozzle -// 103 is 100k EPCOS G57540 Bed +// 100 is 100k GE Sensing AL03006-58.2K-97-G1 with r2=4k7 +// 101 is 100k 0603 SMD Vishay NTCS0603E3104FXT with r2=4k7 +// 102 is 100k EPCOS G57540 Nozzle with r2=4k7 +// 103 is 100k EPCOS G57540 Bed with r2=4k7 +// 104 is 10k G57540 Bed with r2=4k7 +// 105 is 10k G57540 Bed with r2=10k +// 110 is reprappro xmas huxley hot end with 10K resistor (RS thermistor 198-961) -#define TEMP_SENSOR_0 100 +#define TEMP_SENSOR_0 110 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 -#define TEMP_SENSOR_BED 101 +#define TEMP_SENSOR_BED 105 // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 10 // (seconds) @@ -155,9 +158,9 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define min_software_endstops true //If true, axis won't move to coordinates less than zero. #define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 145 //155 for v2 -#define Y_MAX_LENGTH 145 //150 for v2 -#define Z_MAX_LENGTH 100 +#define X_MAX_LENGTH 250 //155 for v2 +#define Y_MAX_LENGTH 200 //150 for v2 +#define Z_MAX_LENGTH 140 // The position of the homing switches. Use MAX_LENGTH * -0.5 if the center should be 0, 0, 0 #define X_HOME_POS 0 diff --git a/Marlin/pins.h b/Marlin/pins.h index 681f608056..c98a233781 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -588,7 +588,7 @@ #define PROBE_PIN -1 //29 on Melzi1284p A2, 11 on SL1.3a #define LED_PIN -1//27 //27 on Melzi1284p -#define FAN_PIN 12 //4 on Melzi1284p +#define FAN_PIN -1 //4 on Melzi1284p #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -599,7 +599,7 @@ #ifdef SANGUINOLOLU_V_1_2 -#define HEATER_BED_PIN 10 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET +#define HEATER_BED_PIN 12 // (bed) - 10 for spare DIO pin and bed MOSFET, 12 for SL MOSFET #define X_ENABLE_PIN 14 #define Y_ENABLE_PIN 14 #define Z_ENABLE_PIN 26 diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 91eec98405..5da8a40fe6 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -475,6 +475,114 @@ const short temptable_103[][2] PROGMEM = { {1008*OVERSAMPLENR,0} }; #endif +#if (THERMISTORHEATER_0 == 104) || (THERMISTORHEATER_1 == 104) || (THERMISTORHEATER_2 == 104) || (THERMISTORBED == 104) // EPCOS G57540G103F - r2=4k7 +const short temptable_104[][2] PROGMEM = { + {1*OVERSAMPLENR, 599}, + {54*OVERSAMPLENR, 160}, + {107*OVERSAMPLENR, 123}, + {160*OVERSAMPLENR, 103}, + {213*OVERSAMPLENR, 90}, + {266*OVERSAMPLENR, 79}, + {319*OVERSAMPLENR, 70}, + {372*OVERSAMPLENR, 62}, + {425*OVERSAMPLENR, 55}, + {478*OVERSAMPLENR, 49}, + {531*OVERSAMPLENR, 43}, + {584*OVERSAMPLENR, 37}, + {637*OVERSAMPLENR, 31}, + {690*OVERSAMPLENR, 25}, + {743*OVERSAMPLENR, 19}, + {796*OVERSAMPLENR, 12}, + {849*OVERSAMPLENR, 5}, + {902*OVERSAMPLENR, -3}, + {955*OVERSAMPLENR, -16}, + {1008*OVERSAMPLENR, -42} +}; +#endif +#if (THERMISTORHEATER_0 == 105) || (THERMISTORHEATER_1 == 105) || (THERMISTORHEATER_2 == 105) || (THERMISTORBED == 105) // EPCOS G57540G103F - r2=10k +const short temptable_105[][2] PROGMEM = { + {1*OVERSAMPLENR, 460}, + {54*OVERSAMPLENR, 123}, + {107*OVERSAMPLENR, 92}, + {160*OVERSAMPLENR, 75}, + {213*OVERSAMPLENR, 63}, + {266*OVERSAMPLENR, 54}, + {319*OVERSAMPLENR, 46}, + {372*OVERSAMPLENR, 40}, + {425*OVERSAMPLENR, 34}, + {478*OVERSAMPLENR, 28}, + {531*OVERSAMPLENR, 23}, + {584*OVERSAMPLENR, 17}, + {637*OVERSAMPLENR, 12}, + {690*OVERSAMPLENR, 7}, + {743*OVERSAMPLENR, 2}, + {796*OVERSAMPLENR, -3}, + {849*OVERSAMPLENR, -10}, + {902*OVERSAMPLENR, -18}, + {955*OVERSAMPLENR, -29}, + {1008*OVERSAMPLENR, -53} +}; +#endif + +#if (THERMISTORHEATER_0 == 110) || (THERMISTORHEATER_1 == 110) || (THERMISTORHEATER_2 == 110) || (THERMISTORBED == 110) // RS thermistor 198-961 +const short temptable_110[][2] PROGMEM = { + {1*OVERSAMPLENR, 704}, + {15*OVERSAMPLENR, 280}, + {21*OVERSAMPLENR, 266}, + {41*OVERSAMPLENR, 234}, + {61*OVERSAMPLENR, 208}, + {81*OVERSAMPLENR, 191}, + {101*OVERSAMPLENR, 178}, + {121*OVERSAMPLENR, 168}, + {141*OVERSAMPLENR, 159}, + {161*OVERSAMPLENR, 152}, + {181*OVERSAMPLENR, 146}, + {221*OVERSAMPLENR, 135}, + {261*OVERSAMPLENR, 126}, + {301*OVERSAMPLENR, 118}, + {341*OVERSAMPLENR, 111}, + {381*OVERSAMPLENR, 105}, + {421*OVERSAMPLENR, 99}, + {461*OVERSAMPLENR, 94}, + {501*OVERSAMPLENR, 88}, + {541*OVERSAMPLENR, 83}, + {581*OVERSAMPLENR, 78}, + {621*OVERSAMPLENR, 73}, + {661*OVERSAMPLENR, 68}, + {741*OVERSAMPLENR, 58}, + {781*OVERSAMPLENR, 52}, + {821*OVERSAMPLENR, 46}, + {861*OVERSAMPLENR, 40}, + {901*OVERSAMPLENR, 32}, + {981*OVERSAMPLENR, 7}, + {1008*OVERSAMPLENR, 0} +}; +#endif + +#if (THERMISTORHEATER_0 == 111) || (THERMISTORHEATER_1 == 111) || (THERMISTORHEATER_2 == 111) || (THERMISTORBED == 111) //100k EPCOS +const short temptable_111[][2] PROGMEM = { + {1*OVERSAMPLENR, 704}, + {54*OVERSAMPLENR, 216}, + {107*OVERSAMPLENR, 175}, + {160*OVERSAMPLENR, 152}, + {213*OVERSAMPLENR, 137}, + {266*OVERSAMPLENR, 125}, + {319*OVERSAMPLENR, 115}, + {372*OVERSAMPLENR, 106}, + {425*OVERSAMPLENR, 99}, + {478*OVERSAMPLENR, 91}, + {531*OVERSAMPLENR, 85}, + {584*OVERSAMPLENR, 78}, + {637*OVERSAMPLENR, 71}, + {690*OVERSAMPLENR, 65}, + {743*OVERSAMPLENR, 58}, + {796*OVERSAMPLENR, 50}, + {849*OVERSAMPLENR, 42}, + {902*OVERSAMPLENR, 31}, + {955*OVERSAMPLENR, 17}, + {1008*OVERSAMPLENR, 0} +}; +#endif #define _TT_NAME(_N) temptable_ ## _N #define TT_NAME(_N) _TT_NAME(_N) From 42423d53fa83f3aacaf157045ac8e4390831c799 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Sat, 2 Jun 2012 21:28:49 +0100 Subject: [PATCH 224/228] need to test FULL_PID_BAND --- Marlin/Configuration.h | 5 +++-- Marlin/pins.h | 4 ++-- Marlin/temperature.cpp | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index edd6947ab2..67091c7172 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -8,7 +8,7 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-04-12-2" //Personal revision number for changes to THIS file. +#define STRING_VERSION_CONFIG_H "2012-05-22-1" //Personal revision number for changes to THIS file. #define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. // This determines the communication speed of the printer @@ -84,10 +84,11 @@ // Comment the following line to disable PID and enable bang-bang. #define PIDTEMP #define PID_MAX 255 // limits current to nozzle; 255=full current +#define FULL_PID_BAND 150 // Full power is applied when pid_error[e] > FULL_PID_BAND #ifdef PIDTEMP //#define PID_DEBUG // Sends debug data to the serial port. //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % - #define PID_INTEGRAL_DRIVE_MAX 130 //limit for the integral term + #define PID_INTEGRAL_DRIVE_MAX 100 //limit for the integral term #define K1 0.95 //smoothing factor withing the PID #define PID_dT 0.122 //sampling period of the PID diff --git a/Marlin/pins.h b/Marlin/pins.h index c98a233781..2d7b1fbf70 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -587,8 +587,8 @@ #define PROBE_PIN -1 //29 on Melzi1284p A2, 11 on SL1.3a -#define LED_PIN -1//27 //27 on Melzi1284p -#define FAN_PIN -1 //4 on Melzi1284p +#define LED_PIN 27//27 //27 on Melzi1284p +#define FAN_PIN 4 //4 on Melzi1284p #define PS_ON_PIN -1 #define KILL_PIN -1 diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index fae9272374..84b551e008 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -275,11 +275,11 @@ void manage_heater() #ifndef PID_OPENLOOP pid_error[e] = pid_setpoint[e] - pid_input; - if(pid_error[e] > 10) { + if(pid_error[e] > FULL_PID_BAND) { pid_output = PID_MAX; pid_reset[e] = true; } - else if(pid_error[e] < -10) { + else if(pid_error[e] < -FULL_PID_BAND) { pid_output = 0; pid_reset[e] = true; } From c8e953bdf90faea8dd08f7db1bb4f7233d30cc30 Mon Sep 17 00:00:00 2001 From: reprappro Date: Sun, 3 Jun 2012 22:37:38 +0100 Subject: [PATCH 225/228] Algebraic temperature code added. Melzi pins defined. Huxley/Mendel selection added. --- Marlin/Configuration.h | 103 ++++++++++++++++++++++++++++++++++++----- Marlin/pins.h | 57 +++++++++++++++++++++++ Marlin/temperature.cpp | 26 +++++++++++ 3 files changed, 175 insertions(+), 11 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 67091c7172..6660da6c5a 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,6 +1,23 @@ #ifndef __CONFIGURATION_H #define __CONFIGURATION_H +// Uncomment ONE of the next three lines - the one for your RepRap machine +//#define REPRAPPRO_HUXLEY +#define REPRAPPRO_MENDEL +//#define REPRAPPRO_WALLACE + +#ifndef REPRAPPRO_HUXLEY +#ifndef REPRAPPRO_MENDEL +#ifndef REPRAPPRO_WALLACE +#error Uncomment one of #define REPRAPPRO_HUXLEY, REPRAPPRO_MENDEL or REPRAPPRO_WALLACE at the start of the file Configuration.h +#endif +#endif +#endif + +// Uncomment this if you are experimenting, know what you are doing, and want to switch off some safety +// features, e.g. allow extrude at low temperature etc. +//#define DEVELOPING + // This configurtion file contains the basic settings. // Advanced settings can be found in Configuration_adv.h // BASIC SETTINGS: select your board type, temperature sensor type, axis scaling, and endstop configuration @@ -8,8 +25,8 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-05-22-1" //Personal revision number for changes to THIS file. -#define STRING_CONFIG_H_AUTHOR "eMAKER" //Who made the changes. +#define STRING_VERSION_CONFIG_H "2012-06-03-1" //Personal revision number for changes to THIS file. +#define STRING_CONFIG_H_AUTHOR "RepRapPro" //Who made the changes. // This determines the communication speed of the printer #define BAUDRATE 250000 @@ -26,15 +43,59 @@ // Gen6 = 5 // Gen6 deluxe = 51 // Sanguinololu 1.2 and above = 62 +// Melzi 63 // Ultimaker = 7 // Teensylu = 8 // Gen3+ =9 -#define MOTHERBOARD 62 +#define MOTHERBOARD 63 //=========================================================================== //=============================Thermal Settings ============================ //=========================================================================== +// Set this if you want to define the constants in the thermistor circuit +// and work out temperatures algebraically - added by AB. +#define COMPUTE_THERMISTORS + +#ifdef COMPUTE_THERMISTORS + +// See http://en.wikipedia.org/wiki/Thermistor#B_or_.CE.B2_parameter_equation + +// BETA is the B value +// RS is the value of the series resistor in ohms +// R_INF is R0.exp(-BETA/T0), where R0 is the thermistor resistance at T0 (T0 is in kelvin) +// Normally T0 is 298.15K (25 C). If you write that expression in brackets in the #define the compiler +// should compute it for you (i.e. it won't need to be calculated at run time). + +// If the A->D converter has a range of 0..1023 and the measured voltage is V (between 0 and 1023) +// then the thermistor resistance, R = V.RS/(1023 - V) +// and the temperature, T = BETA/ln(R/R_INF) +// To get degrees celsius (instead of kelvin) add -273.15 to T + +// This DOES assume that all extruders use the same thermistor type. + +#define ABS_ZERO -273.15 +#define AD_RANGE 16383 + +// RS 198-961 +#define E_BETA 3960.0 +#define E_RS 4700.0 +#define E_R_INF ( 100000.0*exp(-E_BETA/298.15) ) + +// RS 484-0149; EPCOS B57550G103J +#define BED_BETA 3480.0 +#define BED_RS 4700.0 +#define BED_R_INF ( 10000.0*exp(-BED_BETA/298.15) ) + +#define BED_USES_THERMISTOR +#define HEATER_0_USES_THERMISTOR +//#define HEATER_1_USES_THERMISTOR +//#define HEATER_2_USES_THERMISTOR + +#endif + + + //// Temperature sensor settings: // -2 is thermocouple with MAX6675 (only for sensor 0) // -1 is thermocouple with AD595 @@ -103,7 +164,7 @@ // #define DEFAULT_Ki 0.1 // #define DEFAULT_Kd 12 -// RepRapPro Huxley +// RepRapPro Huxley + Mendel #define DEFAULT_Kp 3.0 #define DEFAULT_Ki (2*PID_dT) #define DEFAULT_Kd (80/PID_dT) @@ -114,11 +175,13 @@ // #define DEFAULT_Kd (440/PID_dT) #endif // PIDTEMP +#ifndef DEVELOPING //this prevents dangerous Extruder moves, i.e. if the temperature is under the limit //can be software-disabled for whatever purposes by #define PREVENT_DANGEROUS_EXTRUDE #define EXTRUDE_MINTEMP 170 #define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances. +#endif //=========================================================================== //=============================Mechanical Settings=========================== @@ -159,9 +222,6 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define min_software_endstops true //If true, axis won't move to coordinates less than zero. #define max_software_endstops true //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 250 //155 for v2 -#define Y_MAX_LENGTH 200 //150 for v2 -#define Z_MAX_LENGTH 140 // The position of the homing switches. Use MAX_LENGTH * -0.5 if the center should be 0, 0, 0 #define X_HOME_POS 0 @@ -170,15 +230,36 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t //// MOVEMENT SETTINGS #define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E + +#ifdef REPRAPPRO_MENDEL + +#define X_MAX_LENGTH 210 +#define Y_MAX_LENGTH 210 +#define Z_MAX_LENGTH 100 #define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) -#define FAST_HOME_FEEDRATE {80*60, 80*60, 3*60, 0} // set the homing speeds (mm/min) +#define FAST_HOME_FEEDRATE {50*60, 50*60, 1*60, 0} // set the homing speeds (mm/min) +#define DEFAULT_MAX_FEEDRATE {500, 500, 3, 45} +#define DEFAULT_MAX_FEEDRATE {300, 300, 3, 45} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {800,800,30,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values + +#else + +#define X_MAX_LENGTH 150 +#define Y_MAX_LENGTH 148 +#define Z_MAX_LENGTH 100 +#define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) +#define FAST_HOME_FEEDRATE {80*60, 80*60, 4*60, 0} // set the homing speeds (mm/min) +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) +#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) +#define DEFAULT_MAX_ACCELERATION {1000,1000,50,250} // X, Y, Z, E maximum start speed for accelerated moves. E default values + +#endif + // default settings #define DEFAULT_AXIS_STEPS_PER_UNIT {91.4286, 91.4286,4000,875} // default steps per unit for ultimaker -//#define DEFAULT_AXIS_STEPS_PER_UNIT {80,80,4571.429,850} -#define DEFAULT_MAX_FEEDRATE {500, 500, 5, 45} // (mm/sec) -#define DEFAULT_MAX_ACCELERATION {1000,1000,50,1000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. + #define DEFAULT_ACCELERATION 1000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 1000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts diff --git a/Marlin/pins.h b/Marlin/pins.h index 2d7b1fbf70..26c69e39a2 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -624,6 +624,63 @@ #endif +/**************************************************************************************** +* Melzi pin assignment +* +****************************************************************************************/ +#if MOTHERBOARD == 63 +#define KNOWN_BOARD 1 +#ifndef __AVR_ATmega644P__ +#ifndef __AVR_ATmega1284P__ +#error Oops! Make sure you have 'Sanguino' selected from the 'Tools -> Boards' menu. +#endif +#endif + +#define X_STEP_PIN 15 +#define X_DIR_PIN 21 +#define X_MIN_PIN 18 +#define X_MAX_PIN -2 + +#define Y_STEP_PIN 22 +#define Y_DIR_PIN 23 +#define Y_MIN_PIN 19 +#define Y_MAX_PIN -1 + +#define Z_STEP_PIN 3 +#define Z_DIR_PIN 2 +#define Z_MIN_PIN 20 +#define Z_MAX_PIN -1 + +#define E0_STEP_PIN 1 +#define E0_DIR_PIN 0 + +#define LED_PIN 27 + +#define FAN_PIN 4 + +#define PS_ON_PIN -1 +#define KILL_PIN -1 + +#define HEATER_0_PIN 13 // (extruder) +#define HEATER_1_PIN -1 +#define HEATER_2_PIN -1 + +#define HEATER_BED_PIN 12 // bed (change to 10 for gate pin of MOSFET on heated bed) +#define X_ENABLE_PIN 14 +#define Y_ENABLE_PIN 14 +#define Z_ENABLE_PIN 26 +#define E0_ENABLE_PIN 14 + +#define TEMP_0_PIN 7 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 33 extruder) +#define TEMP_1_PIN -1 +#define TEMP_2_PIN -1 +#define TEMP_BED_PIN 6 // MUST USE ANALOG INPUT NUMBERING NOT DIGITAL OUTPUT NUMBERING!!!!!!!!! (pin 34 bed) +#define SDPOWER -1 +#define SDSS 31 + +#endif + + #if MOTHERBOARD == 7 #define KNOWN_BOARD diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 84b551e008..dcc491616f 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -376,6 +376,30 @@ void manage_heater() } #define PGM_RD_W(x) (short)pgm_read_word(&x) + +#ifdef COMPUTE_THERMISTORS +// Use algebra to work out temperatures, not tables +// NB - this assumes all extruders use the same thermistor type. +int temp2analogi(int celsius, const float& beta, const float& rs, const float& r_inf) +{ + float r = r_inf*exp(beta/(celsius - ABS_ZERO)); + return AD_RANGE - (int)(0.5 + AD_RANGE*r/(r + rs)); +} + +float analog2tempi(int raw, const float& beta, const float& rs, const float& r_inf) +{ + float rawf = (float)(AD_RANGE - raw); + return ABS_ZERO + beta/log( (rawf*rs/(AD_RANGE - rawf))/r_inf ); +} + +int temp2analog(int celsius, uint8_t e) { return temp2analogi(celsius, E_BETA, E_RS, E_R_INF); } +int temp2analogBed(int celsius) { return temp2analogi(celsius, BED_BETA, BED_RS, BED_R_INF); } +float analog2temp(int raw, uint8_t e) { return analog2tempi(raw, E_BETA, E_RS, E_R_INF); } +float analog2tempBed(int raw) { return analog2tempi(raw, BED_BETA, BED_RS, BED_R_INF); } + +#else + + // Takes hot end temperature value as input and returns corresponding raw value. // For a thermistor, it uses the RepRap thermistor temp table. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. @@ -531,6 +555,8 @@ float analog2tempBed(int raw) { #endif } +#endif + void tp_init() { // Finish init of mult extruder arrays From d5eb0622eecf26a43638a7953fa6759bbee8dd30 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Mon, 25 Jun 2012 08:30:48 +0100 Subject: [PATCH 226/228] configuration changes --- Marlin/Configuration.h | 15 +- Marlin/Configuration_adv.h | 7 +- Marlin/EEPROMwrite.h | 4 +- Marlin/Marlin.h | 8 +- Marlin/Marlin.pde | 202 ++++++++++++--- Marlin/cardreader.cpp | 16 +- Marlin/cardreader.h | 6 +- Marlin/language.h | 14 +- Marlin/motion_control.cpp | 2 + Marlin/pins.h | 12 +- Marlin/planner.cpp | 134 +++++----- Marlin/planner.h | 8 +- Marlin/stepper.cpp | 9 +- Marlin/temperature.cpp | 88 ++++--- Marlin/temperature.h | 4 + Marlin/thermistortables.h | 160 ++++++------ Marlin/ultralcd.h | 18 +- Marlin/ultralcd.pde | 491 ++++++++++++++++++++++++++++++++----- Marlin/watchdog.h | 4 +- 19 files changed, 844 insertions(+), 358 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 6660da6c5a..2162d22712 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,5 +1,5 @@ -#ifndef __CONFIGURATION_H -#define __CONFIGURATION_H +#ifndef CONFIGURATION_H +#define CONFIGURATION_H // Uncomment ONE of the next three lines - the one for your RepRap machine //#define REPRAPPRO_HUXLEY @@ -55,7 +55,7 @@ // Set this if you want to define the constants in the thermistor circuit // and work out temperatures algebraically - added by AB. -#define COMPUTE_THERMISTORS +//#define COMPUTE_THERMISTORS #ifdef COMPUTE_THERMISTORS @@ -100,9 +100,9 @@ // -2 is thermocouple with MAX6675 (only for sensor 0) // -1 is thermocouple with AD595 // 0 is not used -// 1 is 100k thermistor -// 2 is 200k thermistor -// 3 is mendel-parts thermistor +// 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup) +// 2 is 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup) +// 3 is mendel-parts thermistor (4.7k pullup) // 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !! // 5 is ParCan supplied 104GT-2 100K // 6 is EPCOS 100k @@ -113,7 +113,7 @@ // 103 is 100k EPCOS G57540 Bed with r2=4k7 // 104 is 10k G57540 Bed with r2=4k7 // 105 is 10k G57540 Bed with r2=10k -// 110 is reprappro xmas huxley hot end with 10K resistor (RS thermistor 198-961) +// 110 is 100k RS thermistor 198-961 hot end with 10K resistor #define TEMP_SENSOR_0 110 #define TEMP_SENSOR_1 0 @@ -123,6 +123,7 @@ // Actual temperature must be close to target for this long before M109 returns success #define TEMP_RESIDENCY_TIME 10 // (seconds) #define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one +#define TEMP_WINDOW 2 // (degC) Window around target to start the recidency timer x degC early. // The minimal temperature defines the temperature below which the heater will not be enabled It is used // to check that the wiring to the thermistor is not broken. diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index baf757ea05..10ee4eb3de 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1,5 +1,5 @@ -#ifndef __CONFIGURATION_ADV_H -#define __CONFIGURATION_ADV_H +#ifndef CONFIGURATION_ADV_H +#define CONFIGURATION_ADV_H //=========================================================================== //=============================Thermal Settings ============================ @@ -150,9 +150,6 @@ #endif // ADVANCE -// A debugging feature to compare calculated vs performed steps, to see if steps are lost by the software. -//#define DEBUG_STEPS - // Arc interpretation settings: #define MM_PER_ARC_SEGMENT 1 #define N_ARC_CORRECTION 25 diff --git a/Marlin/EEPROMwrite.h b/Marlin/EEPROMwrite.h index 2bb5b5cbbc..31cf8cd2f7 100644 --- a/Marlin/EEPROMwrite.h +++ b/Marlin/EEPROMwrite.h @@ -1,5 +1,5 @@ -#ifndef __EEPROMH -#define __EEPROMH +#ifndef EEPROM_H +#define EEPROM_H #include "Marlin.h" #include "planner.h" diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 57aa579f45..70f9062428 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -1,8 +1,8 @@ // Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. // Licence: GPL -#ifndef __MARLINH -#define __MARLINH +#ifndef MARLIN_H +#define MARLIN_H #define HardwareSerial_h // trick to disable the standard HWserial @@ -64,6 +64,7 @@ #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_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');} #define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(MYPGM(x));MYSERIAL.write('\n');} @@ -169,6 +170,9 @@ void ClearToSend(); void get_coordinates(); void prepare_move(); void kill(); +void Stop(); + +bool IsStopped(); void enquecommand(const char *cmd); //put an ascii command at the end of the current buffer. void prepare_arc_move(char isclockwise); diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index d3d848c515..e99cba46a1 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -39,6 +39,7 @@ #include "watchdog.h" #include "EEPROMwrite.h" #include "language.h" +#include "pins_arduino.h" #define VERSION_STRING "1.0.0 RC2" @@ -113,15 +114,16 @@ // 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) // 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) -// M303 - PID relay autotune S sets the target temperature. (default target temperature = 150C) // M510 - FPU Enable // M511 - FPU Reset // M512 - FPU Disable +// M999 - Restart after being stopped by error //Stepper Movement Variables @@ -160,7 +162,7 @@ float modified_destination[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0}; //=========================================================================== const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; static bool home_all_axis = true; -static long gcode_N, gcode_LastN; +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. @@ -192,6 +194,8 @@ static unsigned long stoptime=0; static uint8_t tmp_extruder; +bool Stopped=false; + //=========================================================================== //=============================ROUTINES============================= //=========================================================================== @@ -366,7 +370,10 @@ void get_command() { while( MYSERIAL.available() > 0 && buflen < BUFSIZE) { serial_char = MYSERIAL.read(); - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) + 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 @@ -438,11 +445,17 @@ void get_command() case 1: case 2: case 3: - #ifdef SDSUPPORT - if(card.saving) - break; - #endif //SDSUPPORT - SERIAL_PROTOCOLLNPGM(MSG_OK); + 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; @@ -467,7 +480,10 @@ void get_command() while( !card.eof() && buflen < BUFSIZE) { int16_t n=card.get(); serial_char = (char)n; - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1)||n==-1) + 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); @@ -570,19 +586,25 @@ void process_commands() { case 0: // G0 -> G1 case 1: // G1 - get_coordinates(); // For X Y Z E F - prepare_move(); - //ClearToSend(); - return; + if(Stopped == false) { + get_coordinates(); // For X Y Z E F + prepare_move(); + //ClearToSend(); + return; + } //break; case 2: // G2 - CW ARC - get_arc_coordinates(); - prepare_arc_move(true); - return; + if(Stopped == false) { + get_arc_coordinates(); + prepare_arc_move(true); + return; + } case 3: // G3 - CCW ARC - get_arc_coordinates(); - prepare_arc_move(false); - return; + if(Stopped == false) { + get_arc_coordinates(); + prepare_arc_move(false); + return; + } case 4: // G4 dwell LCD_MESSAGEPGM(MSG_DWELL); codenum = 0; @@ -873,10 +895,14 @@ void process_commands() } #if (TEMP_0_PIN > -1) SERIAL_PROTOCOLPGM("ok T:"); - SERIAL_PROTOCOL(degHotend(tmp_extruder)); + 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(degBed()); + SERIAL_PROTOCOL_F(degBed(),1); + SERIAL_PROTOCOLPGM(" /"); + SERIAL_PROTOCOL_F(degTargetBed(),1); #endif //TEMP_BED_PIN #else SERIAL_ERROR_START; @@ -908,7 +934,7 @@ void process_commands() if (code_seen('S')) setTargetHotend(code_value(), tmp_extruder); #ifdef AUTOTEMP if (code_seen('S')) autotemp_min=code_value(); - if (code_seen('G')) autotemp_max=code_value(); + if (code_seen('B')) autotemp_max=code_value(); if (code_seen('F')) { autotemp_factor=code_value(); @@ -935,9 +961,9 @@ void process_commands() if( (millis() - codenum) > 1000UL ) { //Print Temp Reading and remaining time every 1 second while heating up/cooling down SERIAL_PROTOCOLPGM("T:"); - SERIAL_PROTOCOL( degHotend(tmp_extruder) ); + SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1); SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOL( (int)tmp_extruder ); + SERIAL_PROTOCOL((int)tmp_extruder); #ifdef TEMP_RESIDENCY_TIME SERIAL_PROTOCOLPGM(" W:"); if(residencyStart > -1) @@ -961,8 +987,8 @@ void process_commands() #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 && !isHeatingHotend(tmp_extruder)) || - (residencyStart == -1 && !target_direction && !isCoolingHotend(tmp_extruder)) || + 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(); @@ -987,9 +1013,10 @@ void process_commands() SERIAL_PROTOCOLPGM("T:"); SERIAL_PROTOCOL(tt); SERIAL_PROTOCOLPGM(" E:"); - SERIAL_PROTOCOL( (int)active_extruder ); + SERIAL_PROTOCOL((int)active_extruder); SERIAL_PROTOCOLPGM(" B:"); - SERIAL_PROTOCOLLN(degBed()); + SERIAL_PROTOCOL_F(degBed(),1); + SERIAL_PROTOCOLLN(""); codenum = millis(); } manage_heater(); @@ -1018,6 +1045,7 @@ void process_commands() #if (PS_ON_PIN > -1) case 80: // M80 - ATX Power On SET_OUTPUT(PS_ON_PIN); //GND + WRITE(PS_ON_PIN, LOW); break; #endif @@ -1106,6 +1134,12 @@ void process_commands() SERIAL_PROTOCOLLN(""); break; + case 120: // M120 + enable_endstops(false) ; + break; + case 121: // M121 + enable_endstops(true) ; + break; case 119: // M119 #if (X_MIN_PIN > -1) SERIAL_PROTOCOLPGM(MSG_X_MIN); @@ -1248,7 +1282,7 @@ void process_commands() } break; - case 302: // finish all moves + case 302: // allow cold extrudes { allow_cold_extrudes(true); } @@ -1260,7 +1294,7 @@ void process_commands() PID_autotune(temp); } break; - case 400: // finish all moves + case 400: // M400 finish all moves { st_synchronize(); } @@ -1292,6 +1326,11 @@ void process_commands() SERIAL_ECHO(freeMemory()); } break; + case 999: // Restart after being stopped + Stopped = false; + gcode_LastN = Stopped_gcode_LastN; + FlushSerialRequestResend(); + break; case 510: // FPU Enable { FPUEnable(); @@ -1373,8 +1412,18 @@ void get_coordinates() void get_arc_coordinates() { get_coordinates(); - if(code_seen('I')) offset[0] = code_value(); - if(code_seen('J')) offset[1] = code_value(); + 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 prepare_move() @@ -1429,7 +1478,7 @@ void controllerFan() if ((millis() - lastMotorCheck) >= 2500) //Not a time critical function, so we only check every 2500ms { lastMotorCheck = millis(); - #if (X_ENABLE_PIN > -1 && Y_ENABLE_PIN > -1 && Z_ENABLE_PIN > -1 && E0_ENABLE_PIN > -1) + if(!READ(X_ENABLE_PIN) || !READ(Y_ENABLE_PIN) || !READ(Z_ENABLE_PIN) #if EXTRUDERS > 2 || !READ(E2_ENABLE_PIN) @@ -1441,9 +1490,6 @@ void controllerFan() { lastMotor = millis(); //... set time to NOW so the fan will turn on } - #else - lastMotor = millis(); - #endif if ((millis() - lastMotor) >= (CONTROLLERFAN_SEC*1000UL) || lastMotor == 0) //If the last time any driver was enabled, is longer since than CONTROLLERSEC... { @@ -1520,4 +1566,88 @@ void kill() 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 + diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp index d6ba0b97ba..627f14442e 100644 --- a/Marlin/cardreader.cpp +++ b/Marlin/cardreader.cpp @@ -53,7 +53,7 @@ void CardReader::lsDive(const char *prepend,SdFile parent) while (parent.readDir(p) > 0) { - if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) + if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint { char path[13*2]; @@ -95,9 +95,11 @@ void CardReader::lsDive(const char *prepend,SdFile parent) if ( p.name[1] != '.') continue; } + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; filenameIsDir=DIR_IS_SUBDIR(&p); + if(!filenameIsDir) { if(p.name[8]!='G') continue; @@ -163,20 +165,26 @@ void CardReader::initsd() SERIAL_ECHO_START; SERIAL_ECHOLNPGM(MSG_SD_CARD_OK); } + workDir=root; curDir=&root; + /* if(!workDir.openRoot(&volume)) { SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL); } + */ + } void CardReader::setroot() { - curDir=&root; - if(!workDir.openRoot(&volume)) + /*if(!workDir.openRoot(&volume)) { SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL); - } + }*/ + workDir=root; + + curDir=&workDir; } void CardReader::release() { diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 452bc0eed5..1a8aad3d3e 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -1,5 +1,5 @@ -#ifndef __CARDREADERH -#define __CARDREADERH +#ifndef CARDREADER_H +#define CARDREADER_H #ifdef SDSUPPORT @@ -47,7 +47,7 @@ public: bool saving; bool sdprinting ; bool cardOK ; - char filename[11]; + char filename[12]; bool filenameIsDir; int lastnr; //last number of the autostart; char fastxferbuffer[SD_FAST_XFER_CHUNK_SIZE + 1]; diff --git a/Marlin/language.h b/Marlin/language.h index 2cdbc59426..7db579750b 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -61,8 +61,8 @@ #define MSG_MAIN_WIDE " Main \003" #define MSG_TEMPERATURE_WIDE " Temperature \x7E" #define MSG_MOTION_WIDE " Motion \x7E" - #define MSG_STORE_EPROM " Store EPROM" - #define MSG_LOAD_EPROM " Load EPROM" + #define MSG_STORE_EPROM " Store memory" + #define MSG_LOAD_EPROM " Load memory" #define MSG_RESTORE_FAILSAFE " Restore Failsafe" #define MSG_REFRESH "\004Refresh" #define MSG_WATCH " Watch \003" @@ -74,10 +74,12 @@ #define MSG_CARD_MENU " Card Menu \x7E" #define MSG_NO_CARD " No Card" #define MSG_SERIAL_ERROR_MENU_STRUCTURE "Something is wrong in the MenuStructure." - #define MSG_DWELL "DWELL..." + #define MSG_DWELL "Sleep..." + #define MSG_USERWAIT "Wait for user..." #define MSG_NO_MOVE "No move." #define MSG_PART_RELEASE "Partial Release" #define MSG_KILLED "KILLED. " + #define MSG_STOPPED "STOPPED. " #define MSG_PREHEAT_PLA " Preheat PLA" #define MSG_PREHEAT_ABS " Preheat ABS" #define MSG_STEPPER_RELEASED "Released." @@ -91,7 +93,7 @@ #define MSG_BROWNOUT_RESET " Brown out Reset" #define MSG_WATCHDOG_RESET " Watchdog Reset" #define MSG_SOFTWARE_RESET " Software Reset" - #define MSG_MARLIN "Marlin: " + #define MSG_MARLIN "Marlin " #define MSG_AUTHOR " | Author: " #define MSG_CONFIGURATION_VER " Last Updated: " #define MSG_FREE_MEMORY " Free Memory: " @@ -116,6 +118,7 @@ #define MSG_M115_REPORT "FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n" #define MSG_COUNT_X " Count X:" #define MSG_ERR_KILLED "Printer halted. kill() called !!" + #define MSG_ERR_STOPPED "Printer stopped due to errors. Fix the error and use M999 to restart!. (Temperature is reset. Set it before restarting)" #define MSG_RESEND "Resend:" #define MSG_UNKNOWN_COMMAND "Unknown command:\"" #define MSG_ACTIVE_EXTRUDER "Active Extruder: " @@ -153,7 +156,7 @@ // LCD Menu Messages - #define WELCOME_MSG "UltiMARLIN Ready." + #define WELCOME_MSG "MARLIN Ready." #define MSG_SD_INSERTED "Card inserted" #define MSG_SD_REMOVED "Card removed" @@ -259,6 +262,7 @@ #define MSG_M115_REPORT "FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1\n" #define MSG_COUNT_X " Count X:" #define MSG_ERR_KILLED "Printer halted. kill() called !!" + #define MSG_ERR_STOPPED "Printer stopped due to errors. Fix the error and use M999 to restart!" #define MSG_RESEND "Resend:" #define MSG_UNKNOWN_COMMAND "Unknown command:\"" #define MSG_ACTIVE_EXTRUDER "Active Extruder: " diff --git a/Marlin/motion_control.cpp b/Marlin/motion_control.cpp index 67619b86f3..f11d8c8b8e 100644 --- a/Marlin/motion_control.cpp +++ b/Marlin/motion_control.cpp @@ -47,6 +47,8 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel)); if (millimeters_of_travel < 0.001) { return; } uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT); + if(segments == 0) segments = 1; + /* // Multiply inverse feed_rate to compensate for the fact that this movement is approximated // by a number of discrete segments. The inverse feed_rate should be correct for the sum of diff --git a/Marlin/pins.h b/Marlin/pins.h index 26c69e39a2..56b7651108 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -579,16 +579,16 @@ #define Z_STEP_PIN 3 #define Z_DIR_PIN 2 -#define Z_MIN_PIN 20 //for Melzi Z bed probe, 20 for standard Z endstop +#define Z_MIN_PIN 20 #define Z_MAX_PIN -1 #define E0_STEP_PIN 1 #define E0_DIR_PIN 0 -#define PROBE_PIN -1 //29 on Melzi1284p A2, 11 on SL1.3a +#define PROBE_PIN -1 -#define LED_PIN 27//27 //27 on Melzi1284p -#define FAN_PIN 4 //4 on Melzi1284p +#define LED_PIN -1 +#define FAN_PIN -1 #define PS_ON_PIN -1 #define KILL_PIN -1 @@ -654,6 +654,8 @@ #define E0_STEP_PIN 1 #define E0_DIR_PIN 0 +#define PROBE_PIN -1 //29 on Melzi1284p A2 + #define LED_PIN 27 #define FAN_PIN 4 @@ -730,7 +732,7 @@ #define E1_STEP_PIN 49 #define E1_DIR_PIN 47 -#define E1_ENABLE_PIN 51 +#define E1_ENABLE_PIN 48 #define SDPOWER -1 #define SDSS 53 diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 628620652f..58b94527ed 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -51,9 +51,6 @@ IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a) */ - - - #include "Marlin.h" #include "planner.h" #include "stepper.h" @@ -378,20 +375,26 @@ void plan_init() { void getHighESpeed() { static float oldt=0; - if(!autotemp_enabled) + if(!autotemp_enabled){ return; - if(degTargetHotend0()+2high) - { - high=se; + if((block_buffer[block_index].steps_x != 0) || + (block_buffer[block_index].steps_y != 0) || + (block_buffer[block_index].steps_z != 0)) { + float se=(float(block_buffer[block_index].steps_e)/float(block_buffer[block_index].step_event_count))*block_buffer[block_index].nominal_speed; + //se; mm/sec; + if(se>high) + { + high=se; + } } block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1); } @@ -408,10 +411,6 @@ void getHighESpeed() } oldt=t; setTargetHotend0(t); -// SERIAL_ECHO_START; -// SERIAL_ECHOPAIR("highe",high); -// SERIAL_ECHOPAIR(" t",t); -// SERIAL_ECHOLN(""); } #endif @@ -514,7 +513,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e))); // Bail if this is a zero-length block - if (block->step_event_count <=dropsegments) { return; }; + if (block->step_event_count <= dropsegments) { return; }; block->fan_speed = FanSpeed; @@ -537,7 +536,6 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // Enable all if(block->steps_e != 0) { enable_e0();enable_e1();enable_e2(); } - if (block->steps_e == 0) { if(feed_rate 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); - #endif - float delta_mm[4]; delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS]; delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; delta_mm[E_AXIS] = ((target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS])*extrudemultiply/100.0; -// if ( block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0 ) { -// block->millimeters = abs(delta_mm[E_AXIS]); -// } else { -// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); -// } + if ( block->steps_x <=dropsegments && block->steps_y <=dropsegments && block->steps_z <=dropsegments ) { + block->millimeters = abs(delta_mm[E_AXIS]); + } else { + block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); + } // TODO - JMG - SORT OUT RETRACTS WHEN e IS NOT ALONE - block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + - square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); +// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + +// square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. float inverse_second = feed_rate * inverse_millimeters; + int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1); + + // slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill + #ifdef OLD_SLOWDOWN + if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1) feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5); + #endif + + #ifdef SLOWDOWN + // segment time im micro seconds + unsigned long segment_time = lround(1000000.0/inverse_second); + if ((moves_queued > 1) && (moves_queued < (BLOCK_BUFFER_SIZE * 0.5))) { + if (segment_time < minsegmenttime) { // buffer is draining, add extra time. The amount of time added increases if the buffer is still emptied more. + inverse_second=1000000.0/(segment_time+lround(2*(minsegmenttime-segment_time)/moves_queued)); + } + } + #endif + // END OF SLOW DOWN SECTION + + block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0 block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0 - -/* - // segment time im micro seconds - long segment_time = lround(1000000.0/inverse_second); - if ((blockcount>0) && (blockcount < (BLOCK_BUFFER_SIZE - 4))) { - if (segment_time max_feedrate[i]) - speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); + current_speed[i] = delta_mm[i] * inverse_second; + if(fabs(current_speed[i]) > max_feedrate[i]) + speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i])); } // Max segement time in us. @@ -634,17 +625,6 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // Correct the speed if( speed_factor < 1.0) { -// Serial.print("speed factor : "); Serial.println(speed_factor); - for(int i=0; i < 4; i++) { - if(abs(current_speed[i]) > max_feedrate[i]) - speed_factor = min(speed_factor, max_feedrate[i] / abs(current_speed[i])); - /* - if(speed_factor < 0.1) { - Serial.print("speed factor : "); Serial.println(speed_factor); - Serial.print("current_speed"); Serial.print(i); Serial.print(" : "); Serial.println(current_speed[i]); - } - */ - } for(unsigned char i=0; i < 4; i++) { current_speed[i] *= speed_factor; } @@ -714,25 +694,25 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa #endif // Start with a safe speed float vmax_junction = max_xy_jerk/2; - if(abs(current_speed[Z_AXIS]) > max_z_jerk/2) + if(fabs(current_speed[Z_AXIS]) > max_z_jerk/2) vmax_junction = max_z_jerk/2; vmax_junction = min(vmax_junction, block->nominal_speed); - if(abs(current_speed[E_AXIS]) > max_e_jerk/2) + if(fabs(current_speed[E_AXIS]) > max_e_jerk/2) vmax_junction = min(vmax_junction, max_e_jerk/2); - if ((moves_queued > 1) && (previous_nominal_speed > 0.0)) { + if ((moves_queued > 1) && (previous_nominal_speed > 0.0001)) { float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2)); - if((previous_speed[X_AXIS] != 0.0) || (previous_speed[Y_AXIS] != 0.0)) { + if((fabs(previous_speed[X_AXIS]) > 0.0001) || (fabs(previous_speed[Y_AXIS]) > 0.0001)) { vmax_junction = block->nominal_speed; } if (jerk > max_xy_jerk) { vmax_junction *= (max_xy_jerk/jerk); } - if(abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { - vmax_junction *= (max_z_jerk/abs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); + if(fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) { + vmax_junction *= (max_z_jerk/fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])); } - if(abs(current_speed[E_AXIS] - previous_speed[E_AXIS]) > max_e_jerk) { - vmax_junction *= (max_e_jerk/abs(current_speed[E_AXIS] - previous_speed[E_AXIS])); + if(fabs(current_speed[E_AXIS] - previous_speed[E_AXIS]) > max_e_jerk) { + vmax_junction *= (max_e_jerk/fabs(current_speed[E_AXIS] - previous_speed[E_AXIS])); } } block->max_entry_speed = vmax_junction; @@ -756,6 +736,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa // Update previous path unit_vector and nominal speed memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[] previous_nominal_speed = block->nominal_speed; + #ifdef ADVANCE // Calculate advance rate @@ -784,9 +765,6 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa */ #endif // ADVANCE - - - calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, MINIMUM_PLANNER_SPEED/block->nominal_speed); @@ -797,9 +775,7 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa memcpy(position, target, sizeof(target)); // position[] = target[] planner_recalculate(); - #ifdef AUTOTEMP - getHighESpeed(); - #endif + st_wake_up(); } diff --git a/Marlin/planner.h b/Marlin/planner.h index 873441bb05..fc0d83c2b8 100644 --- a/Marlin/planner.h +++ b/Marlin/planner.h @@ -45,10 +45,10 @@ typedef struct { #endif // Fields used by the motion planner to manage acceleration -// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis - float nominal_speed; // The nominal speed for this block in mm/min - float entry_speed; // Entry speed at previous-current junction in mm/min - float max_entry_speed; // Maximum allowable junction entry speed in mm/min +// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis + float nominal_speed; // The nominal speed for this block in mm/sec + float entry_speed; // Entry speed at previous-current junction in mm/sec + float max_entry_speed; // Maximum allowable junction entry speed in mm/sec float millimeters; // The total travel of this block in mm float acceleration; // acceleration mm/sec^2 unsigned char recalculate_flag; // Planner flag to recalculate trapezoids on entry junction diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index f66d869d4c..597d320011 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -57,7 +57,6 @@ volatile static unsigned long step_events_completed; // The number of step event static long old_advance = 0; #endif static long e_steps[3]; -static unsigned char busy = false; // TRUE when SIG_OUTPUT_COMPARE1A is being serviced. Used to avoid retriggering that handler. static long acceleration_time, deceleration_time; //static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate; static unsigned short acc_step_rate; // needed for deccelaration start point @@ -84,11 +83,7 @@ volatile char count_direction[NUM_AXIS] = { 1, 1, 1, 1}; //=============================functions ============================ //=========================================================================== -#ifdef ENDSTOPS_ONLY_FOR_HOMING - #define CHECK_ENDSTOPS if(check_endstops) -#else - #define CHECK_ENDSTOPS -#endif +#define CHECK_ENDSTOPS if(check_endstops) // intRes = intIn1 * intIn2 >> 16 // uses: @@ -217,7 +212,6 @@ void enable_endstops(bool check) void st_wake_up() { // TCNT1 = 0; - if(busy == false) ENABLE_STEPPER_DRIVER_INTERRUPT(); } @@ -296,6 +290,7 @@ ISR(TIMER1_COMPA_vect) // Anything in the buffer? current_block = plan_get_current_block(); if (current_block != NULL) { + current_block->busy = true; trapezoid_generator_reset(); counter_x = -(current_block->step_event_count >> 1); counter_y = counter_x; diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index dcc491616f..17446a7bf6 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -96,17 +96,6 @@ static unsigned long previous_millis_bed_heater; static int maxttemp[EXTRUDERS] = { 16383 }; // the first value used for all static int bed_minttemp = 0; static int bed_maxttemp = 16383; - static int heater_pin_map[EXTRUDERS] = { HEATER_0_PIN -#if EXTRUDERS > 1 - , HEATER_1_PIN -#endif -#if EXTRUDERS > 2 - , HEATER_2_PIN -#endif -#if EXTRUDERS > 3 - #error Unsupported number of extruders -#endif - }; static void *heater_ttbl_map[EXTRUDERS] = { (void *)heater_0_temptable #if EXTRUDERS > 1 , (void *)heater_1_temptable @@ -139,7 +128,6 @@ void PID_autotune(float temp) float input; int cycles=0; bool heating = true; - soft_pwm[0] = 255>>1; unsigned long temp_millis = millis(); unsigned long t1=temp_millis; @@ -147,14 +135,18 @@ void PID_autotune(float temp) long t_high; long t_low; - long bias=127; - long d = 127; + long bias=PID_MAX/2; + long d = PID_MAX/2; float Ku, Tu; float Kp, Ki, Kd; float max, min; SERIAL_ECHOLN("PID Autotune start"); - + + disable_heater(); // switch off all heaters. + + soft_pwm[0] = PID_MAX/2; + for(;;) { if(temp_meas_ready == true) { // temp sample ready @@ -181,8 +173,8 @@ void PID_autotune(float temp) t_low=t2 - t1; if(cycles > 0) { bias += (d*(t_high - t_low))/(t_low + t_high); - bias = constrain(bias, 20 ,235); - if(bias > 127) d = 254 - bias; + bias = constrain(bias, 20 ,PID_MAX-FULL_PID_BAND); + if(bias > PID_MAX/2) d = PID_MAX - 1 - bias; else d = bias; SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias); @@ -201,6 +193,7 @@ void PID_autotune(float temp) SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); + /* Kp = 0.33*Ku; Ki = Kp/Tu; Kd = Kp*Tu/3; @@ -215,6 +208,7 @@ void PID_autotune(float temp) SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp); SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki); SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd); + */ } } soft_pwm[0] = (bias + d) >> 1; @@ -224,7 +218,7 @@ void PID_autotune(float temp) } } if(input > (temp + 20)) { - SERIAL_PROTOCOLLNPGM("PID Autotune failed !, Temperature to high"); + SERIAL_PROTOCOLLNPGM("PID Autotune failed! Temperature to high"); return; } if(millis() - temp_millis > 2000) { @@ -234,6 +228,14 @@ void PID_autotune(float temp) SERIAL_PROTOCOLPGM(" @:"); SERIAL_PROTOCOLLN(getHeaterPower(0)); } + if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) { + SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout"); + return; + } + if(cycles > 5) { + SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h"); + return; + } LCD_STATUS; } } @@ -312,11 +314,9 @@ void manage_heater() // Check if temperature is within the correct range if((current_raw[e] > minttemp[e]) && (current_raw[e] < maxttemp[e])) { - //analogWrite(heater_pin_map[e], pid_output); soft_pwm[e] = (int)pid_output >> 1; } else { - //analogWrite(heater_pin_map[e], 0); soft_pwm[e] = 0; } } // End extruder for loop @@ -705,7 +705,7 @@ void disable_heater() target_raw[0]=0; soft_pwm[0]=0; #if HEATER_0_PIN > -1 - digitalWrite(HEATER_0_PIN,LOW); + WRITE(HEATER_0_PIN,LOW); #endif #endif @@ -713,7 +713,7 @@ void disable_heater() target_raw[1]=0; soft_pwm[1]=0; #if HEATER_1_PIN > -1 - digitalWrite(HEATER_1_PIN,LOW); + WRITE(HEATER_1_PIN,LOW); #endif #endif @@ -721,36 +721,44 @@ void disable_heater() target_raw[2]=0; soft_pwm[2]=0; #if HEATER_2_PIN > -1 - digitalWrite(HEATER_2_PIN,LOW); + WRITE(HEATER_2_PIN,LOW); #endif #endif #if TEMP_BED_PIN > -1 target_raw_bed=0; #if HEATER_BED_PIN > -1 - digitalWrite(HEATER_BED_PIN,LOW); + WRITE(HEATER_BED_PIN,LOW); #endif #endif } void max_temp_error(uint8_t e) { - digitalWrite(heater_pin_map[e], 0); - SERIAL_ERROR_START; - SERIAL_ERRORLN(e); - SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !"); + disable_heater(); + if(IsStopped() == false) { + SERIAL_ERROR_START; + SERIAL_ERRORLN((int)e); + SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !"); + } } void min_temp_error(uint8_t e) { - digitalWrite(heater_pin_map[e], 0); - SERIAL_ERROR_START; - SERIAL_ERRORLN(e); - SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); + disable_heater(); + if(IsStopped() == false) { + SERIAL_ERROR_START; + SERIAL_ERRORLN((int)e); + SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !"); + } } void bed_max_temp_error(void) { - digitalWrite(HEATER_BED_PIN, 0); - SERIAL_ERROR_START; - SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); +#if HEATER_BED_PIN > -1 + WRITE(HEATER_BED_PIN, 0); +#endif + if(IsStopped() == false) { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !!"); + } } #define HEAT_INTERVAL 250 @@ -942,14 +950,14 @@ ISR(TIMER0_COMPB_vect) if(temp_count >= 16) // 8 ms * 16 = 128ms. { - #ifdef HEATER_0_USES_AD595 + #if defined(HEATER_0_USES_AD595) || defined(HEATER_0_USES_MAX6675) current_raw[0] = raw_temp_0_value; #else current_raw[0] = 16383 - raw_temp_0_value; #endif #if EXTRUDERS > 1 - #ifdef HEATER_1_USES_AD595 || defined HEATER_0_USES_MAX6675 + #ifdef HEATER_1_USES_AD595 current_raw[1] = raw_temp_1_value; #else current_raw[1] = 16383 - raw_temp_1_value; @@ -983,7 +991,7 @@ ISR(TIMER0_COMPB_vect) max_temp_error(e); #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE { - kill();; + Stop();; } #endif } @@ -992,7 +1000,7 @@ ISR(TIMER0_COMPB_vect) min_temp_error(e); #ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE { - kill(); + Stop(); } #endif } @@ -1002,7 +1010,7 @@ ISR(TIMER0_COMPB_vect) if(current_raw_bed >= bed_maxttemp) { target_raw_bed = 0; bed_max_temp_error(); - kill(); + Stop(); } #endif } diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 1cfdae0243..1e6c1be3ae 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -130,6 +130,8 @@ FORCE_INLINE bool isCoolingBed() { #define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1) #define isHeatingHotend1() isHeatingHotend(1) #define isCoolingHotend1() isCoolingHotend(1) +#else +#define setTargetHotend1(_celsius) do{}while(0) #endif #if EXTRUDERS > 2 #define degHotend2() degHotend(2) @@ -137,6 +139,8 @@ FORCE_INLINE bool isCoolingBed() { #define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2) #define isHeatingHotend2() isHeatingHotend(2) #define isCoolingHotend2() isCoolingHotend(2) +#else +#define setTargetHotend2(_celsius) do{}while(0) #endif #if EXTRUDERS > 3 #error Invalid number of extruders diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 5da8a40fe6..8d2e710ad6 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -73,27 +73,41 @@ const short temptable_1[][2] PROGMEM = { #endif #if (THERMISTORHEATER_0 == 2) || (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor const short temptable_2[][2] PROGMEM = { +//200k ATC Semitec 204GT-2 +//Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf +// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance {1*OVERSAMPLENR, 848}, - {54*OVERSAMPLENR, 275}, - {107*OVERSAMPLENR, 228}, - {160*OVERSAMPLENR, 202}, - {213*OVERSAMPLENR, 185}, - {266*OVERSAMPLENR, 171}, - {319*OVERSAMPLENR, 160}, - {372*OVERSAMPLENR, 150}, - {425*OVERSAMPLENR, 141}, - {478*OVERSAMPLENR, 133}, - {531*OVERSAMPLENR, 125}, - {584*OVERSAMPLENR, 118}, - {637*OVERSAMPLENR, 110}, - {690*OVERSAMPLENR, 103}, - {743*OVERSAMPLENR, 95}, - {796*OVERSAMPLENR, 86}, - {849*OVERSAMPLENR, 77}, - {902*OVERSAMPLENR, 65}, - {955*OVERSAMPLENR, 49}, - {1008*OVERSAMPLENR, 17}, - {1020*OVERSAMPLENR, 0} //safety + {30*OVERSAMPLENR, 300}, //top rating 300C + {34*OVERSAMPLENR, 290}, + {39*OVERSAMPLENR, 280}, + {46*OVERSAMPLENR, 270}, + {53*OVERSAMPLENR, 260}, + {63*OVERSAMPLENR, 250}, + {74*OVERSAMPLENR, 240}, + {87*OVERSAMPLENR, 230}, + {104*OVERSAMPLENR, 220}, + {124*OVERSAMPLENR, 210}, + {148*OVERSAMPLENR, 200}, + {176*OVERSAMPLENR, 190}, + {211*OVERSAMPLENR, 180}, + {252*OVERSAMPLENR, 170}, + {301*OVERSAMPLENR, 160}, + {357*OVERSAMPLENR, 150}, + {420*OVERSAMPLENR, 140}, + {489*OVERSAMPLENR, 130}, + {562*OVERSAMPLENR, 120}, + {636*OVERSAMPLENR, 110}, + {708*OVERSAMPLENR, 100}, + {775*OVERSAMPLENR, 90}, + {835*OVERSAMPLENR, 80}, + {884*OVERSAMPLENR, 70}, + {924*OVERSAMPLENR, 60}, + {955*OVERSAMPLENR, 50}, + {977*OVERSAMPLENR, 40}, + {993*OVERSAMPLENR, 30}, + {1004*OVERSAMPLENR, 20}, + {1012*OVERSAMPLENR, 10}, + {1016*OVERSAMPLENR, 0}, }; #endif @@ -157,73 +171,48 @@ const short temptable_4[][2] PROGMEM = { #if (THERMISTORHEATER_0 == 5) || (THERMISTORHEATER_1 == 5) || (THERMISTORHEATER_2 == 5) || (THERMISTORBED == 5) //100k ParCan thermistor (104GT-2) const short temptable_5[][2] PROGMEM = { -{1*OVERSAMPLENR, 713}, -{18*OVERSAMPLENR, 316}, -{35*OVERSAMPLENR, 266}, -{52*OVERSAMPLENR, 239}, -{69*OVERSAMPLENR, 221}, -{86*OVERSAMPLENR, 208}, -{103*OVERSAMPLENR, 197}, -{120*OVERSAMPLENR, 188}, -{137*OVERSAMPLENR, 181}, -{154*OVERSAMPLENR, 174}, -{171*OVERSAMPLENR, 169}, -{188*OVERSAMPLENR, 163}, -{205*OVERSAMPLENR, 159}, -{222*OVERSAMPLENR, 154}, -{239*OVERSAMPLENR, 150}, -{256*OVERSAMPLENR, 147}, -{273*OVERSAMPLENR, 143}, -{290*OVERSAMPLENR, 140}, -{307*OVERSAMPLENR, 136}, -{324*OVERSAMPLENR, 133}, -{341*OVERSAMPLENR, 130}, -{358*OVERSAMPLENR, 128}, -{375*OVERSAMPLENR, 125}, -{392*OVERSAMPLENR, 122}, -{409*OVERSAMPLENR, 120}, -{426*OVERSAMPLENR, 117}, -{443*OVERSAMPLENR, 115}, -{460*OVERSAMPLENR, 112}, -{477*OVERSAMPLENR, 110}, -{494*OVERSAMPLENR, 108}, -{511*OVERSAMPLENR, 106}, -{528*OVERSAMPLENR, 103}, -{545*OVERSAMPLENR, 101}, -{562*OVERSAMPLENR, 99}, -{579*OVERSAMPLENR, 97}, -{596*OVERSAMPLENR, 95}, -{613*OVERSAMPLENR, 92}, -{630*OVERSAMPLENR, 90}, -{647*OVERSAMPLENR, 88}, -{664*OVERSAMPLENR, 86}, -{681*OVERSAMPLENR, 84}, -{698*OVERSAMPLENR, 81}, -{715*OVERSAMPLENR, 79}, -{732*OVERSAMPLENR, 77}, -{749*OVERSAMPLENR, 75}, -{766*OVERSAMPLENR, 72}, -{783*OVERSAMPLENR, 70}, -{800*OVERSAMPLENR, 67}, -{817*OVERSAMPLENR, 64}, -{834*OVERSAMPLENR, 61}, -{851*OVERSAMPLENR, 58}, -{868*OVERSAMPLENR, 55}, -{885*OVERSAMPLENR, 52}, -{902*OVERSAMPLENR, 48}, -{919*OVERSAMPLENR, 44}, -{936*OVERSAMPLENR, 40}, -{953*OVERSAMPLENR, 34}, -{970*OVERSAMPLENR, 28}, -{987*OVERSAMPLENR, 20}, -{1004*OVERSAMPLENR, 8}, -{1021*OVERSAMPLENR, 0} +// ATC Semitec 104GT-2 (Used in ParCan) +// Verified by linagee. Source: http://shop.arcol.hu/static/datasheets/thermistors.pdf +// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance + {1*OVERSAMPLENR, 713}, + {17*OVERSAMPLENR, 300}, //top rating 300C + {20*OVERSAMPLENR, 290}, + {23*OVERSAMPLENR, 280}, + {27*OVERSAMPLENR, 270}, + {31*OVERSAMPLENR, 260}, + {37*OVERSAMPLENR, 250}, + {43*OVERSAMPLENR, 240}, + {51*OVERSAMPLENR, 230}, + {61*OVERSAMPLENR, 220}, + {73*OVERSAMPLENR, 210}, + {87*OVERSAMPLENR, 200}, + {106*OVERSAMPLENR, 190}, + {128*OVERSAMPLENR, 180}, + {155*OVERSAMPLENR, 170}, + {189*OVERSAMPLENR, 160}, + {230*OVERSAMPLENR, 150}, + {278*OVERSAMPLENR, 140}, + {336*OVERSAMPLENR, 130}, + {402*OVERSAMPLENR, 120}, + {476*OVERSAMPLENR, 110}, + {554*OVERSAMPLENR, 100}, + {635*OVERSAMPLENR, 90}, + {713*OVERSAMPLENR, 80}, + {784*OVERSAMPLENR, 70}, + {846*OVERSAMPLENR, 60}, + {897*OVERSAMPLENR, 50}, + {937*OVERSAMPLENR, 40}, + {966*OVERSAMPLENR, 30}, + {986*OVERSAMPLENR, 20}, + {1000*OVERSAMPLENR, 10}, + {1010*OVERSAMPLENR, 0} }; #endif #if (THERMISTORHEATER_0 == 6) || (THERMISTORHEATER_1 == 6) || (THERMISTORHEATER_2 == 6) || (THERMISTORBED == 6) // 100k Epcos thermistor const short temptable_6[][2] PROGMEM = { - {28*OVERSAMPLENR, 250}, + {1*OVERSAMPLENR, 350}, + {28*OVERSAMPLENR, 250}, //top rating 250C {31*OVERSAMPLENR, 245}, {35*OVERSAMPLENR, 240}, {39*OVERSAMPLENR, 235}, @@ -232,8 +221,8 @@ const short temptable_6[][2] PROGMEM = { {49*OVERSAMPLENR, 220}, {53*OVERSAMPLENR, 215}, {62*OVERSAMPLENR, 210}, - {73*OVERSAMPLENR, 205}, - {72*OVERSAMPLENR, 200}, + {71*OVERSAMPLENR, 205}, //fitted graphically + {78*OVERSAMPLENR, 200}, //fitted graphically {94*OVERSAMPLENR, 190}, {102*OVERSAMPLENR, 185}, {116*OVERSAMPLENR, 170}, @@ -264,7 +253,8 @@ const short temptable_6[][2] PROGMEM = { #if (THERMISTORHEATER_0 == 7) || (THERMISTORHEATER_1 == 7) || (THERMISTORHEATER_2 == 7) || (THERMISTORBED == 7) // 100k Honeywell 135-104LAG-J01 const short temptable_7[][2] PROGMEM = { - {46*OVERSAMPLENR, 270}, + {1*OVERSAMPLENR, 500}, + {46*OVERSAMPLENR, 270}, //top rating 300C {50*OVERSAMPLENR, 265}, {54*OVERSAMPLENR, 260}, {58*OVERSAMPLENR, 255}, diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 253149cbba..dc44d1cda9 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -1,5 +1,5 @@ -#ifndef __ULTRALCDH -#define __ULTRALCDH +#ifndef ULTRALCD_H +#define ULTRALCD_H #include "Marlin.h" #ifdef ULTRA_LCD #include @@ -7,11 +7,13 @@ 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 LiquidCrystal lcd; + extern volatile char buttons; //the last checked buttons in a bit array. #ifdef NEWPANEL #define EN_C (1< //=========================================================================== //=============================imported variables============================ @@ -13,6 +18,7 @@ extern volatile int extrudemultiply; extern long position[4]; #ifdef SDSUPPORT +#include "cardreader.h" extern CardReader card; #endif @@ -20,7 +26,7 @@ extern CardReader card; //=============================public variables============================ //=========================================================================== volatile char buttons=0; //the last checked buttons in a bit array. -int encoderpos=0; +long encoderpos=0; short lastenc=0; @@ -95,6 +101,10 @@ FORCE_INLINE void clear() void lcd_init() { //beep(); + #ifdef ULTIPANEL + buttons_init(); + #endif + byte Degree[8] = { B01100, @@ -301,10 +311,6 @@ MainMenu::MainMenu() displayStartingRow=0; activeline=0; force_lcd_update=true; - #ifdef ULTIPANEL - buttons_init(); - #endif - lcd_init(); linechanging=false; tune=false; } @@ -322,6 +328,8 @@ void MainMenu::showStatus() lcd.setCursor(0,0);lcdprintPGM("\002---/---\001 "); #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 lcd.setCursor(10,0);lcdprintPGM("B---/---\001 "); + #elif EXTRUDERS > 1 + lcd.setCursor(10,0);lcdprintPGM("\002---/---\001 "); #endif } @@ -356,6 +364,23 @@ void MainMenu::showStatus() lcd.print(ftostr3(targetBed)); oldtargetBed=targetBed; } + #elif EXTRUDERS > 1 + static int olddegHotEnd1=-1; + static int oldtargetHotEnd1=-1; + int tHotEnd1=intround(degHotend1()); + if((tHotEnd1!=olddegHotEnd1)||force_lcd_update) + { + lcd.setCursor(11,0); + lcd.print(ftostr3(tHotEnd1)); + olddegHotEnd1=tHotEnd1; + } + int ttHotEnd1=intround(degTargetHotend1()); + if((ttHotEnd1!=oldtargetHotEnd1)||force_lcd_update) + { + lcd.setCursor(15,0); + lcd.print(ftostr3(ttHotEnd1)); + oldtargetHotEnd1=ttHotEnd1; + } #endif //starttime=2; static uint16_t oldtime=0; @@ -430,10 +455,7 @@ void MainMenu::showStatus() if(force_lcd_update) //initial display of content { encoderpos=feedmultiply; - lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 "); - #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcdprintPGM("B123/567\001 "); - #endif + lcd.setCursor(0,0);lcdprintPGM("\002---/---\001 "); } int tHotEnd0=intround(degHotend0()); @@ -520,7 +542,7 @@ void MainMenu::showPrepare() beepshort(); ); break; case ItemP_cooldown: - MENUITEM( lcdprintPGM(MSG_COOLDOWN) , BLOCK;setTargetHotend0(0);setTargetBed(0);beepshort(); ) ; + MENUITEM( lcdprintPGM(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(); ) ; @@ -691,6 +713,7 @@ 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 F700 E5");beepshort(); ) ; break; default: @@ -864,7 +887,7 @@ void MainMenu::showTune() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(MSG_FLOW); - lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + lcd.setCursor(13,line);lcd.print(ftostr52(axis_steps_per_unit[E_AXIS])); } if((activeline!=line) ) @@ -875,14 +898,14 @@ void MainMenu::showTune() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)axis_steps_per_unit[3]; + encoderpos=(long)(axis_steps_per_unit[E_AXIS]*100.0); } else { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[E_AXIS]); position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; + //current_position[E_AXIS]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos/100.0; encoderpos=activeline*lcdslow; } @@ -892,8 +915,8 @@ void MainMenu::showTune() if(linechanging) { if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + if(encoderpos>999999) encoderpos=999999; + lcd.setCursor(13,line);lcd.print(ftostr52(encoderpos/100.0)); } }break; @@ -923,12 +946,18 @@ void MainMenu::showTune() // enum { - ItemCT_exit,ItemCT_nozzle, + ItemCT_exit,ItemCT_nozzle0, #ifdef AUTOTEMP ItemCT_autotempactive, ItemCT_autotempmin,ItemCT_autotempmax,ItemCT_autotempfact, #endif -#if (HEATER_BED_PIN > -1) +#if EXTRUDERS > 1 + ItemCT_nozzle1, +#endif +#if EXTRUDERS > 2 + ItemCT_nozzle2, +#endif +#if defined BED_USES_THERMISTOR || BED_USES_AD595 ItemCT_bed, #endif ItemCT_fan, @@ -946,7 +975,7 @@ void MainMenu::showControlTemp() case ItemCT_exit: MENUITEM( lcdprintPGM(MSG_CONTROL) , BLOCK;status=Main_Control;beepshort(); ) ; break; - case ItemCT_nozzle: + case ItemCT_nozzle0: { if(force_lcd_update) { @@ -980,8 +1009,80 @@ void MainMenu::showControlTemp() } }break; - #ifdef AUTOTEMP - case ItemCT_autotempmin: + #if EXTRUDERS > 1 + case ItemCT_nozzle1: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE1); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend1()))); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(degTargetHotend1()); + } + else + { + setTargetHotend1(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + #endif + #if EXTRUDERS > 2 + case ItemCT_nozzle2: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_NOZZLE2); + lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend2()))); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=intround(degTargetHotend2()); + } + else + { + setTargetHotend1(encoderpos); + encoderpos=activeline*lcdslow; + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + + }break; + #endif + #ifdef AUTOTEMP + case ItemCT_autotempmin: { if(force_lcd_update) { @@ -1015,7 +1116,7 @@ void MainMenu::showControlTemp() } }break; - case ItemCT_autotempmax: + case ItemCT_autotempmax: { if(force_lcd_update) { @@ -1049,7 +1150,7 @@ void MainMenu::showControlTemp() } }break; - case ItemCT_autotempfact: + case ItemCT_autotempfact: { if(force_lcd_update) { @@ -1083,7 +1184,7 @@ void MainMenu::showControlTemp() } }break; - case ItemCT_autotempactive: + case ItemCT_autotempactive: { if(force_lcd_update) { @@ -1110,9 +1211,9 @@ void MainMenu::showControlTemp() } }break; - #endif //autotemp - #if (HEATER_BED_PIN > -1) - case ItemCT_bed: + #endif //autotemp + #if defined BED_USES_THERMISTOR || BED_USES_AD595 + case ItemCT_bed: { if(force_lcd_update) { @@ -1145,8 +1246,8 @@ void MainMenu::showControlTemp() lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); } }break; - #endif - case ItemCT_fan: + #endif + case ItemCT_fan: { if(force_lcd_update) { @@ -1181,7 +1282,8 @@ void MainMenu::showControlTemp() } }break; - case ItemCT_PID_P: + #ifdef PIDTEMP + case ItemCT_PID_P: { if(force_lcd_update) { @@ -1197,7 +1299,7 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Kp; + encoderpos=(long)Kp; } else { @@ -1232,7 +1334,7 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(Ki*10/PID_dT); + encoderpos=(long)(Ki*10/PID_dT); } else { @@ -1251,7 +1353,7 @@ void MainMenu::showControlTemp() } }break; - case ItemCT_PID_D: + case ItemCT_PID_D: { if(force_lcd_update) { @@ -1268,7 +1370,7 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(Kd/5./PID_dT); + encoderpos=(long)(Kd/5./PID_dT); } else { @@ -1304,7 +1406,7 @@ void MainMenu::showControlTemp() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)Kc; + encoderpos=(long)Kc; } else { @@ -1324,6 +1426,7 @@ void MainMenu::showControlTemp() } #endif + #endif break; default: break; @@ -1376,7 +1479,7 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)acceleration/100; + encoderpos=(long)acceleration/100; } else { @@ -1410,7 +1513,7 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)max_xy_jerk; + encoderpos=(long)max_xy_jerk; } else { @@ -1453,7 +1556,7 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)max_feedrate[i-ItemCM_vmaxx]; + encoderpos=(long)max_feedrate[i-ItemCM_vmaxx]; } else { @@ -1489,7 +1592,7 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(minimumfeedrate); + encoderpos=(long)(minimumfeedrate); } else { @@ -1524,7 +1627,7 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)mintravelfeedrate; + encoderpos=(long)mintravelfeedrate; } else { @@ -1567,7 +1670,7 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100; + encoderpos=(long)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100; } else { @@ -1585,6 +1688,8 @@ void MainMenu::showControlMotion() } }break; + + case ItemCM_aret://float retract_acceleration = 7000; { if(force_lcd_update) @@ -1601,7 +1706,7 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)retract_acceleration/100; + encoderpos=(long)retract_acceleration/100; } else { @@ -1625,7 +1730,7 @@ void MainMenu::showControlMotion() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(MSG_XSTEPS); - lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[0])); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[X_AXIS])); } if((activeline!=line) ) @@ -1636,13 +1741,13 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(axis_steps_per_unit[0]*100.0); + encoderpos=(long)(axis_steps_per_unit[X_AXIS]*100.0); } else { - float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[0]); + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[X_AXIS]); position[X_AXIS]=lround(position[X_AXIS]*factor); - //current_position[3]*=factor; + //current_position[X_AXIS]*=factor; axis_steps_per_unit[X_AXIS]= encoderpos/100.0; encoderpos=activeline*lcdslow; } @@ -1652,7 +1757,7 @@ void MainMenu::showControlMotion() if(linechanging) { if(encoderpos<5) encoderpos=5; - if(encoderpos>32000) encoderpos=32000;//TODO: This is a problem, encoderpos is 16bit, but steps_per_unit for e can be wel over 800 + if(encoderpos>999999) encoderpos=999999; lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); } @@ -1662,7 +1767,7 @@ void MainMenu::showControlMotion() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(MSG_YSTEPS); - lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[1])); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[Y_AXIS])); } if((activeline!=line) ) @@ -1673,13 +1778,13 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(axis_steps_per_unit[1]*100.0); + encoderpos=(long)(axis_steps_per_unit[Y_AXIS]*100.0); } else { - float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[1]); + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[Y_AXIS]); position[Y_AXIS]=lround(position[Y_AXIS]*factor); - //current_position[3]*=factor; + //current_position[Y_AXIS]*=factor; axis_steps_per_unit[Y_AXIS]= encoderpos/100.0; encoderpos=activeline*lcdslow; @@ -1690,7 +1795,7 @@ void MainMenu::showControlMotion() if(linechanging) { if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; + if(encoderpos>999999) encoderpos=999999; lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); } @@ -1700,7 +1805,7 @@ void MainMenu::showControlMotion() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(MSG_ZSTEPS); - lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[2])); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[Z_AXIS])); } if((activeline!=line) ) @@ -1711,13 +1816,13 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(axis_steps_per_unit[2]*100.0); + encoderpos=(long)(axis_steps_per_unit[Z_AXIS]*100.0); } else { - float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[2]); + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[Z_AXIS]); position[Z_AXIS]=lround(position[Z_AXIS]*factor); - //current_position[3]*=factor; + //current_position[Z_AXIS]*=factor; axis_steps_per_unit[Z_AXIS]= encoderpos/100.0; encoderpos=activeline*lcdslow; @@ -1728,7 +1833,7 @@ void MainMenu::showControlMotion() if(linechanging) { if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; + if(encoderpos>999999) encoderpos=999999; lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); } @@ -1739,7 +1844,7 @@ void MainMenu::showControlMotion() if(force_lcd_update) { lcd.setCursor(0,line);lcdprintPGM(MSG_ESTEPS); - lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[3])); + lcd.setCursor(11,line);lcd.print(ftostr52(axis_steps_per_unit[E_AXIS])); } if((activeline!=line) ) @@ -1750,13 +1855,13 @@ void MainMenu::showControlMotion() linechanging=!linechanging; if(linechanging) { - encoderpos=(int)(axis_steps_per_unit[3]*100.0); + encoderpos=(long)(axis_steps_per_unit[E_AXIS]*100.0); } else { - float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[3]); + float factor=float(encoderpos)/100.0/float(axis_steps_per_unit[E_AXIS]); position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; + //current_position[E_AXIS]*=factor; axis_steps_per_unit[E_AXIS]= encoderpos/100.0; encoderpos=activeline*lcdslow; @@ -1767,7 +1872,7 @@ void MainMenu::showControlMotion() if(linechanging) { if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; + if(encoderpos>999999) encoderpos=999999; lcd.setCursor(11,line);lcd.print(ftostr52(encoderpos/100.0)); } @@ -1781,8 +1886,252 @@ void MainMenu::showControlMotion() } +enum { + ItemR_exit, + ItemR_autoretract, + ItemR_retract_length,ItemR_retract_feedrate,ItemR_retract_zlift, + ItemR_unretract_length,ItemR_unretract_feedrate, + +}; + + + +void MainMenu::showControlRetract() +{ +#ifdef FWRETRACT + uint8_t line=0; + clearIfNecessary(); + for(int8_t i=lineoffset;i990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(ftostr52(encoderpos/100.)); + } + + }break; + case ItemR_retract_feedrate: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACTF); + lcd.setCursor(13,line);lcd.print(itostr4(retract_feedrate)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(long)(retract_feedrate/5); + } + else + { + retract_feedrate= encoderpos*5.; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + + }break; + case ItemR_retract_zlift://float retract_acceleration = 7000; + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACT_ZLIFT); + lcd.setCursor(13,line);lcd.print(ftostr52(retract_zlift));; + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(long)(retract_zlift*10); + } + else + { + retract_zlift= encoderpos/10.; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(ftostr52(encoderpos/10.)); + } + + }break; + case ItemR_unretract_length: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACT_RECOVER); + lcd.setCursor(13,line);lcd.print(ftostr52(retract_recover_length));; + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(long)(retract_recover_length*100); + } + else + { + retract_recover_length= encoderpos/100.; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(ftostr52(encoderpos/100.)); + } + + }break; + + case ItemR_unretract_feedrate: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcdprintPGM(MSG_CONTROL_RETRACT_RECOVERF); + lcd.setCursor(13,line);lcd.print(itostr4(retract_recover_feedrate)); + } + + if((activeline!=line) ) + break; + + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(long)retract_recover_feedrate/5; + } + else + { + retract_recover_feedrate= encoderpos*5.; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + + }break; + + default: + break; + } + line++; + } + updateActiveLines(ItemR_unretract_feedrate,encoderpos); +#endif +} + + + enum { ItemC_exit,ItemC_temp,ItemC_move, +#ifdef FWRETRACT + ItemC_rectract, +#endif ItemC_store, ItemC_load,ItemC_failsafe }; @@ -1803,6 +2152,11 @@ void MainMenu::showControl() case ItemC_move: MENUITEM( lcdprintPGM(MSG_MOTION_WIDE) , BLOCK;status=Sub_MotionControl;beepshort(); ) ; break; +#ifdef FWRETRACT + case ItemC_rectract: + MENUITEM( lcdprintPGM(MSG_RECTRACT_WIDE) , BLOCK;status=Sub_RetractControl;beepshort(); ) ; + break; +#endif case ItemC_store: { if(force_lcd_update) @@ -2008,9 +2362,10 @@ void MainMenu::showMainMenu() } } clearIfNecessary(); - for(int8_t line=0;line Date: Mon, 25 Jun 2012 09:58:17 +0100 Subject: [PATCH 227/228] revert planner.cpp change which broke retracts --- Marlin/planner.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 58b94527ed..91b5b46381 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -548,15 +548,15 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]; delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]; delta_mm[E_AXIS] = ((target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS])*extrudemultiply/100.0; - if ( block->steps_x <=dropsegments && block->steps_y <=dropsegments && block->steps_z <=dropsegments ) { - block->millimeters = abs(delta_mm[E_AXIS]); - } else { - block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); - } +// if ( block->steps_x <=dropsegments && block->steps_y <=dropsegments && block->steps_z <=dropsegments ) { +// block->millimeters = abs(delta_mm[E_AXIS]); +// } else { +// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); +// } - // TODO - JMG - SORT OUT RETRACTS WHEN e IS NOT ALONE -// block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + -// square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); +// TODO - JMG - SORT OUT RETRACTS WHEN e IS NOT ALONE + block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + + square(delta_mm[Z_AXIS]) + square(delta_mm[E_AXIS])); float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides // Calculate speed in mm/second for each axis. No divide by zero due to previous checks. From b000747fe5e95ca00a172f5cea0e726842d08b55 Mon Sep 17 00:00:00 2001 From: jeanmarc Date: Fri, 6 Jul 2012 20:33:12 +0100 Subject: [PATCH 228/228] Z max height updated --- Marlin/Configuration.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 2162d22712..75ba7d2054 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -25,7 +25,7 @@ //User specified version info of THIS file to display in [Pronterface, etc] terminal window during startup. //Implementation of an idea by Prof Braino to inform user that any changes made //to THIS file by the user have been successfully uploaded into firmware. -#define STRING_VERSION_CONFIG_H "2012-06-03-1" //Personal revision number for changes to THIS file. +#define STRING_VERSION_CONFIG_H "2012-06-25-1" //Personal revision number for changes to THIS file. #define STRING_CONFIG_H_AUTHOR "RepRapPro" //Who made the changes. // This determines the communication speed of the printer @@ -236,7 +236,7 @@ const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of t #define X_MAX_LENGTH 210 #define Y_MAX_LENGTH 210 -#define Z_MAX_LENGTH 100 +#define Z_MAX_LENGTH 140 #define HOMING_FEEDRATE {10*60, 10*60, 1*60, 0} // set the homing speeds (mm/min) #define FAST_HOME_FEEDRATE {50*60, 50*60, 1*60, 0} // set the homing speeds (mm/min) #define DEFAULT_MAX_FEEDRATE {500, 500, 3, 45}