Commit 2e813978 authored by MagoKimbra's avatar MagoKimbra

Update 4.2.5

BIG UPDATE
Add HAL for 8 bit version
Rewrite communication and use HAL for it.
Rewrite servo
and more
parent cbdc92ce
......@@ -24,13 +24,15 @@
// Serial port 0 is still used by the Arduino bootloader regardless of this setting.
#define SERIAL_PORT 0
// Enable the Bluetooth serial interface on AT90USB devices
//#define BLUETOOTH
// This determines the communication speed of the printer
// 2400,9600,19200,38400,57600,115200,250000
#define BAUDRATE 115200
// Enable the Bluetooth serial interface
//#define BLUETOOTH
#define BLUETOOTH_SERIAL 1
#define BLUETOOTH_BAUD 115200
// User-specified version info of this build 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
// build by the user have been successfully uploaded into firmware.
......
......@@ -276,7 +276,6 @@
//but only if the current temperature is far enough below the target for a reliable test.
#define WATCH_TEMP_PERIOD 16 // Seconds
#define WATCH_TEMP_INCREASE 4 // Degrees Celsius
//#define THERMAL_PROTECTION_BED
......@@ -1492,7 +1491,7 @@
************************************** Buffer stuff ************************************
****************************************************************************************/
// 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 ring-buffering.
// 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 ring-buffering.
#define BLOCK_BUFFER_SIZE 16 // maximize block buffer
//The ASCII buffer for receiving from the serial:
......
#include "base.h"
#include "Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "module/vector_3.h"
#endif
#include "module/planner.h"
#include "module/stepper_indirection.h"
#include "module/stepper.h"
#include "module/temperature.h"
#include "module/ultralcd.h"
#include "Configuration_Store.h"
#if ENABLED(SDSUPPORT)
#include "module/cardreader.h"
#endif
/**
* configuration_store.cpp
*
......@@ -325,6 +312,8 @@ void Config_RetrieveSettings() {
#if HEATER_USES_AD595
EEPROM_READ_VAR(i, ad595_offset);
EEPROM_READ_VAR(i, ad595_gain);
for (int8_t h = 0; h < HOTENDS; h++)
if (ad595_gain[h] == 0) ad595_gain[h] == TEMP_SENSOR_AD595_GAIN;
#endif
#if MECH(DELTA)
......@@ -421,7 +410,7 @@ void Config_RetrieveSettings() {
updatePID();
// Report settings retrieved and length
ECHO_SV(DB, ver);
ECHO_ST(DB, ver);
ECHO_MV(" stored settings retrieved (", (unsigned long)i);
ECHO_EM(" bytes)");
}
......@@ -622,98 +611,98 @@ void Config_ResetDefault() {
// Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
if (!forReplay) {
ECHO_LM(DB, "Steps per unit:");
ECHO_LM(CFG, "Steps per unit:");
}
ECHO_SMV(DB, " M92 X", axis_steps_per_unit[X_AXIS]);
ECHO_SMV(CFG, " M92 X", axis_steps_per_unit[X_AXIS]);
ECHO_MV(" Y", axis_steps_per_unit[Y_AXIS]);
ECHO_MV(" Z", axis_steps_per_unit[Z_AXIS]);
ECHO_EMV(" E", axis_steps_per_unit[E_AXIS]);
#if EXTRUDERS > 1
for (short i = 1; i < EXTRUDERS; i++) {
ECHO_SMV(DB, " M92 T", i);
ECHO_SMV(CFG, " M92 T", i);
ECHO_EMV(" E", axis_steps_per_unit[E_AXIS + i]);
}
#endif //EXTRUDERS > 1
#if MECH(SCARA)
if (!forReplay) {
ECHO_LM(DB, "Scaling factors:");
ECHO_LM(CFG, "Scaling factors:");
}
ECHO_SMV(DB, " M365 X", axis_scaling[X_AXIS]);
ECHO_SMV(CFG, " M365 X", axis_scaling[X_AXIS]);
ECHO_MV(" Y", axis_scaling[Y_AXIS]);
ECHO_EMV(" Z", axis_scaling[Z_AXIS]);
#endif // SCARA
if (!forReplay) {
ECHO_LM(DB, "Maximum feedrates (mm/s):");
ECHO_LM(CFG, "Maximum feedrates (mm/s):");
}
ECHO_SMV(DB, " M203 X", max_feedrate[X_AXIS]);
ECHO_SMV(CFG, " M203 X", max_feedrate[X_AXIS]);
ECHO_MV(" Y", max_feedrate[Y_AXIS] );
ECHO_MV(" Z", max_feedrate[Z_AXIS] );
ECHO_EMV(" E", max_feedrate[E_AXIS]);
#if EXTRUDERS > 1
for (short i = 1; i < EXTRUDERS; i++) {
ECHO_SMV(DB, " M203 T", i);
ECHO_SMV(CFG, " M203 T", i);
ECHO_EMV(" E", max_feedrate[E_AXIS + i]);
}
#endif //EXTRUDERS > 1
if (!forReplay) {
ECHO_LM(DB, "Maximum Acceleration (mm/s2):");
ECHO_LM(CFG, "Maximum Acceleration (mm/s2):");
}
ECHO_SMV(DB, " M201 X", max_acceleration_units_per_sq_second[X_AXIS] );
ECHO_SMV(CFG, " M201 X", max_acceleration_units_per_sq_second[X_AXIS] );
ECHO_MV(" Y", max_acceleration_units_per_sq_second[Y_AXIS] );
ECHO_MV(" Z", max_acceleration_units_per_sq_second[Z_AXIS] );
ECHO_EMV(" E", max_acceleration_units_per_sq_second[E_AXIS]);
#if EXTRUDERS > 1
for (short i = 1; i < EXTRUDERS; i++) {
ECHO_SMV(DB, " M201 T", i);
for (int8_t i = 1; i < EXTRUDERS; i++) {
ECHO_SMV(CFG, " M201 T", i);
ECHO_EMV(" E", max_acceleration_units_per_sq_second[E_AXIS + i]);
}
#endif //EXTRUDERS > 1
ECHO_E;
if (!forReplay) {
ECHO_LM(DB, "Accelerations: P=printing, V=travel and T* R=retract");
ECHO_LM(CFG, "Accelerations: P=printing, V=travel and T* R=retract");
}
ECHO_SMV(DB," M204 P", acceleration);
ECHO_SMV(CFG," M204 P", acceleration);
ECHO_EMV(" V", travel_acceleration);
#if EXTRUDERS > 0
for (short i = 0; i < EXTRUDERS; i++) {
ECHO_SMV(DB, " M204 T", i);
ECHO_EMV(" R" ,retract_acceleration[i]);
for (int8_t i = 0; i < EXTRUDERS; i++) {
ECHO_SMV(CFG, " M204 T", i);
ECHO_EMV(" R", retract_acceleration[i]);
}
#endif
if (!forReplay) {
ECHO_LM(DB, "Advanced variables: S=Min feedrate (mm/s), V=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)");
ECHO_LM(CFG, "Advanced variables: S=Min feedrate (mm/s), V=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)");
}
ECHO_SMV(DB, " M205 S", minimumfeedrate );
ECHO_SMV(CFG, " M205 S", minimumfeedrate );
ECHO_MV(" V", mintravelfeedrate );
ECHO_MV(" B", minsegmenttime );
ECHO_MV(" X", max_xy_jerk );
ECHO_MV(" Z", max_z_jerk);
ECHO_EMV(" E", max_e_jerk[0]);
#if (EXTRUDERS > 1)
for(short i = 1; i < EXTRUDERS; i++) {
ECHO_SMV(DB, " M205 T", i);
for(int8_t i = 1; i < EXTRUDERS; i++) {
ECHO_SMV(CFG, " M205 T", i);
ECHO_EMV(" E" , max_e_jerk[i]);
}
#endif
if (!forReplay) {
ECHO_LM(DB, "Home offset (mm):");
ECHO_LM(CFG, "Home offset (mm):");
}
ECHO_SMV(DB, " M206 X", home_offset[X_AXIS] );
ECHO_SMV(CFG, " M206 X", home_offset[X_AXIS] );
ECHO_MV(" Y", home_offset[Y_AXIS] );
ECHO_EMV(" Z", home_offset[Z_AXIS] );
#if HOTENDS > 1
if (!forReplay) {
ECHO_LM(DB, "Hotend offset (mm):");
ECHO_LM(CFG, "Hotend offset (mm):");
}
for (int h = 0; h < HOTENDS; h++) {
ECHO_SMV(DB, " M218 T", h);
for (int8_t h = 0; h < HOTENDS; h++) {
ECHO_SMV(CFG, " M218 T", h);
ECHO_MV(" X", hotend_offset[X_AXIS][h]);
ECHO_MV(" Y", hotend_offset[Y_AXIS][h]);
ECHO_EMV(" Z", hotend_offset[Z_AXIS][h]);
......@@ -722,20 +711,20 @@ void Config_ResetDefault() {
#if HEATER_USES_AD595
if (!forReplay) {
ECHO_LM(DB, "Hotend AD595:");
ECHO_LM(CFG, "AD595 Offset and Gain:");
}
for (int h = 0; h < EXTRUDERS; h++) {
ECHO_SMV(DB, " M595 T", h);
ECHO_MV(" Offset", ad595_offset[h]);
ECHO_EMV(", Gain: ", ad595_gain[h]);
for (int8_t h = 0; h < HOTENDS; h++) {
ECHO_SMV(CFG, " M595 T", h);
ECHO_MV(" O", ad595_offset[h]);
ECHO_EMV(", G", ad595_gain[h]);
}
#endif // HEATER_USES_AD595
#if MECH(DELTA)
if (!forReplay) {
ECHO_LM(DB, "Delta Geometry adjustment:");
ECHO_LM(CFG, "Delta Geometry adjustment:");
}
ECHO_SMV(DB, " M666 A", tower_adj[0], 3);
ECHO_SMV(CFG, " M666 A", tower_adj[0], 3);
ECHO_MV(" B", tower_adj[1], 3);
ECHO_MV(" C", tower_adj[2], 3);
ECHO_MV(" I", tower_adj[3], 3);
......@@ -749,44 +738,44 @@ void Config_ResetDefault() {
ECHO_EMV(" H", max_pos[2]);
if (!forReplay) {
ECHO_LM(DB, "Endstop Offsets:");
ECHO_LM(CFG, "Endstop Offsets:");
}
ECHO_SMV(DB, " M666 X", endstop_adj[X_AXIS]);
ECHO_SMV(CFG, " M666 X", endstop_adj[X_AXIS]);
ECHO_MV(" Y", endstop_adj[Y_AXIS]);
ECHO_EMV(" Z", endstop_adj[Z_AXIS]);
if (!forReplay) {
ECHO_LM(DB, "Z-Probe Offset:");
ECHO_LM(CFG, "Z-Probe Offset:");
}
ECHO_SMV(DB, " M666 P X", z_probe_offset[0]);
ECHO_SMV(CFG, " M666 P X", z_probe_offset[0]);
ECHO_MV(" Y", z_probe_offset[1]);
ECHO_EMV(" Z", z_probe_offset[2]);
#elif ENABLED(Z_DUAL_ENDSTOPS)
if (!forReplay) {
ECHO_LM(DB, "Z2 Endstop adjustement (mm):");
ECHO_LM(CFG, "Z2 Endstop adjustement (mm):");
}
ECHO_LMV(DB, " M666 Z", z_endstop_adj );
ECHO_LMV(CFG, " M666 Z", z_endstop_adj );
#elif ENABLED(AUTO_BED_LEVELING_FEATURE)
if (!forReplay) {
ECHO_LM(DB, "Z Probe offset (mm)");
ECHO_LM(CFG, "Z Probe offset (mm)");
}
ECHO_LMV(DB, " M666 P", zprobe_zoffset);
ECHO_LMV(CFG, " M666 P", zprobe_zoffset);
#endif
#if ENABLED(ULTIPANEL)
if (!forReplay) {
ECHO_LM(DB, "Material heatup parameters:");
ECHO_LM(CFG, "Material heatup parameters:");
}
ECHO_SMV(DB, " M145 M0 H", plaPreheatHotendTemp);
ECHO_SMV(CFG, " M145 M0 H", plaPreheatHotendTemp);
ECHO_MV(" B", plaPreheatHPBTemp);
ECHO_MV(" F", plaPreheatFanSpeed);
ECHO_EM(" (Material PLA)");
ECHO_SMV(DB, " M145 M1 H", absPreheatHotendTemp);
ECHO_SMV(CFG, " M145 M1 H", absPreheatHotendTemp);
ECHO_MV(" B", absPreheatHPBTemp);
ECHO_MV(" F", absPreheatFanSpeed);
ECHO_EM(" (Material ABS)");
ECHO_SMV(DB, " M145 M2 H", gumPreheatHotendTemp);
ECHO_SMV(CFG, " M145 M2 H", gumPreheatHotendTemp);
ECHO_MV(" B", gumPreheatHPBTemp);
ECHO_MV(" F", gumPreheatFanSpeed);
ECHO_EM(" (Material GUM)");
......@@ -794,11 +783,11 @@ void Config_ResetDefault() {
#if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
if (!forReplay) {
ECHO_LM(DB, "PID settings:");
ECHO_LM(CFG, "PID settings:");
}
#if ENABLED(PIDTEMP)
for (int h = 0; h < HOTENDS; h++) {
ECHO_SMV(DB, " M301 H", h);
for (int8_t h = 0; h < HOTENDS; h++) {
ECHO_SMV(CFG, " M301 H", h);
ECHO_MV(" P", PID_PARAM(Kp, h));
ECHO_MV(" I", unscalePID_i(PID_PARAM(Ki, h)));
ECHO_MV(" D", unscalePID_d(PID_PARAM(Kd, h)));
......@@ -808,11 +797,11 @@ void Config_ResetDefault() {
ECHO_E;
}
#if ENABLED(PID_ADD_EXTRUSION_RATE)
ECHO_SMV(DB, " M301 L", lpq_len);
ECHO_SMV(CFG, " M301 L", lpq_len);
#endif
#endif
#if ENABLED(PIDTEMPBED)
ECHO_SMV(DB, " M304 P", bedKp); // for compatibility with hosts, only echos values for E0
ECHO_SMV(CFG, " M304 P", bedKp); // for compatibility with hosts, only echos values for E0
ECHO_MV(" I", unscalePID_i(bedKi));
ECHO_EMV(" D", unscalePID_d(bedKd));
#endif
......@@ -820,28 +809,28 @@ void Config_ResetDefault() {
#if ENABLED(FWRETRACT)
if (!forReplay) {
ECHO_LM(DB,"Retract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)");
ECHO_LM(CFG, "Retract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)");
}
ECHO_SMV(DB, " M207 S", retract_length);
ECHO_SMV(CFG, " M207 S", retract_length);
ECHO_MV(" F", retract_feedrate*60);
ECHO_EMV(" Z", retract_zlift);
if (!forReplay) {
ECHO_LM(DB, "Recover: S=Extra length (mm) F:Speed (mm/m)");
ECHO_LM(CFG, "Recover: S=Extra length (mm) F:Speed (mm/m)");
}
ECHO_SMV(DB, " M208 S", retract_recover_length);
ECHO_SMV(CFG, " M208 S", retract_recover_length);
ECHO_MV(" F", retract_recover_feedrate*60);
if (!forReplay) {
ECHO_LM(DB,"Auto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries");
ECHO_LM(CFG, "Auto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries");
}
ECHO_LMV(DB," M209 S", autoretract_enabled);
ECHO_LMV(CFG, " M209 S", autoretract_enabled);
#if EXTRUDERS > 1
if (!forReplay) {
ECHO_LM(DB,"Multi-extruder settings:");
ECHO_LMV(DB, " Swap retract length (mm): ", retract_length_swap);
ECHO_LMV(DB, " Swap rec. addl. length (mm): ", retract_recover_length_swap);
ECHO_LM(CFG, "Multi-extruder settings:");
ECHO_LMV(CFG, " Swap retract length (mm): ", retract_length_swap);
ECHO_LMV(CFG, " Swap rec. addl. length (mm): ", retract_recover_length_swap);
}
#endif // EXTRUDERS > 1
......@@ -849,23 +838,23 @@ void Config_ResetDefault() {
if (volumetric_enabled) {
if (!forReplay) {
ECHO_LM(DB, "Filament settings:");
ECHO_LM(CFG, "Filament settings:");
}
ECHO_LMV(DB, " M200 D", filament_size[0]);
ECHO_LMV(CFG, " M200 D", filament_size[0]);
#if EXTRUDERS > 1
ECHO_LMV(DB, " M200 T1 D", filament_size[1]);
ECHO_LMV(CFG, " M200 T1 D", filament_size[1]);
#if EXTRUDERS > 2
ECHO_LMV(DB, " M200 T2 D", filament_size[2]);
ECHO_LMV(CFG, " M200 T2 D", filament_size[2]);
#if EXTRUDERS > 3
ECHO_LMV(DB, " M200 T3 D", filament_size[3]);
ECHO_LMV(CFG, " M200 T3 D", filament_size[3]);
#endif
#endif
#endif
} else {
if (!forReplay) {
ECHO_LM(DB, "Filament settings: Disabled");
ECHO_LM(CFG, "Filament settings: Disabled");
}
}
......@@ -878,27 +867,29 @@ void Config_ResetDefault() {
#if HAS(POWER_CONSUMPTION_SENSOR)
if (!forReplay) {
ECHO_LM(DB, "Watt/h consumed:");
ECHO_LM(INFO, "Watt/h consumed:");
}
ECHO_LVM(OK, power_consumption_hour," Wh");
ECHO_LVM(INFO, power_consumption_hour," Wh");
#endif
if (!forReplay) {
ECHO_LM(DB, "Power on time:");
ECHO_LM(INFO, "Power on time:");
}
char time[30];
unsigned int day = printer_usage_seconds / 60 / 60 / 24, hours = (printer_usage_seconds / 60 / 60) % 24, minutes = (printer_usage_seconds / 60) % 60;
sprintf_P(time, PSTR(" %i " MSG_END_DAY " %i " MSG_END_HOUR " %i " MSG_END_MINUTE), day, hours, minutes);
ECHO_LV(DB, time);
ECHO_LT(INFO, time);
if (!forReplay) {
ECHO_LM(DB, "Filament printed:");
ECHO_LM(INFO, "Filament printed:");
}
char lung[30];
unsigned int kmeter = (long)printer_usage_filament / 1000 / 1000, meter = ((long)printer_usage_filament / 1000) % 1000,
centimeter = ((long)printer_usage_filament / 10) % 100, millimeter = ((long)printer_usage_filament) % 10;
unsigned int kmeter = (long)printer_usage_filament / 1000 / 1000,
meter = ((long)printer_usage_filament / 1000) % 1000,
centimeter = ((long)printer_usage_filament / 10) % 100,
millimeter = ((long)printer_usage_filament) % 10;
sprintf_P(lung, PSTR(" %i Km %i m %i cm %i mm"), kmeter, meter, centimeter, millimeter);
ECHO_LV(DB, lung);
ECHO_LT(INFO, lung);
}
#endif // !DISABLE_M503
......
#ifndef CONFIGURATION_STORE_H
#define CONFIGURATION_STORE_H
#include "base.h"
void Config_ResetDefault();
void ConfigSD_ResetDefault();
......
#ifndef CONFIGURATION_VERSION_H
#define CONFIGURATION_VERSION_H
#define BUILD_VERSION "MarlinKimbra 4.2.4 dev"
#define SHORT_BUILD_VERSION "4.2.4_dev"
#define BUILD_VERSION "MarlinKimbra 4.2.5 dev"
#define SHORT_BUILD_VERSION "4.2.5_dev"
#define STRING_DISTRIBUTION_DATE __DATE__ " " __TIME__ // build date and time
// It might also be appropriate to define a location where additional information can be found
#define FIRMWARE_URL "https://github.com/MagoKimbra/MarlinKimbra"
......
......@@ -19,6 +19,176 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Look here for descriptions of G-codes:
* - http://linuxcnc.org/handbook/gcode/g-code.html
* - http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
*
* Help us document these G-codes online:
* - http://reprap.org/wiki/G-code
* - https://github.com/MagoKimbra/MarlinKimbra/blob/master/Documentation/GCodes.md
*
* -----------------
* Implemented Codes
* -----------------
*
* "G" Codes
*
* G0 -> G1
* G1 - Coordinated Movement X Y Z E
* G2 - CW ARC
* G3 - CCW ARC
* G4 - Dwell S<seconds> or P<milliseconds>
* G10 - retract filament according to settings of M207
* G11 - retract recover filament according to settings of M208
* G28 - Home one or more axes
* G29 - Detailed Z-Probe, probes the bed at 3 or more points. Will fail if you haven't homed yet.
* G30 - Single Z Probe, probes bed at current XY location. - Bed Probe and Delta geometry Autocalibration
* G31 - Dock sled (Z_PROBE_SLED only)
* G32 - Undock sled (Z_PROBE_SLED only)
* G60 - Save current position coordinates (all axes, for active extruder).
* S<SLOT> - specifies memory slot # (0-based) to save into (default 0).
* G61 - Apply/restore saved coordinates to the active extruder.
* X Y Z E - Value to add at stored coordinates.
* F<speed> - Set Feedrate.
* S<SLOT> - specifies memory slot # (0-based) to restore from (default 0).
* G90 - Use Absolute Coordinates
* G91 - Use Relative Coordinates
* G92 - Set current position to coordinates given
*
* "M" Codes
*
* M0 - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)
* M1 - Same as M0
* M3 - Put S<value> in laser beam control
* M4 - Turn on laser beam
* M5 - Turn off laser beam
* M11 - Start/Stop printing serial mode
* M17 - Enable/Power all stepper motors
* M18 - Disable all stepper motors; same as M84
* M20 - List SD card
* M21 - Init SD card
* M22 - Release SD card
* M23 - Select SD file (M23 filename.g)
* M24 - Start/resume SD print
* M25 - Pause SD print
* M26 - Set SD position in bytes (M26 S12345)
* M27 - Report SD print status
* M28 - Start SD write (M28 filename.g)
* M29 - Stop SD write
* M30 - Delete file from SD (M30 filename.g)
* M31 - Output time since last M109 or SD card start to serial
* M32 - Select file and start SD print (Can be used _while_ printing from SD card files):
* syntax "M32 /path/filename#", or "M32 S<startpos bytes> !filename#"
* Call gcode file : "M32 P !filename#" and return to caller file after finishing (similar to #include).
* The '#' is necessary when calling from within sd files, as it stops buffer prereading
* M33 - Get the longname version of a path
* M42 - Change pin status via gcode Use M42 Px Sy to set pin x to value y, when omitting Px the onboard led will be used.
* M48 - Measure Z_Probe repeatability. M48 [P # of points] [X position] [Y position] [V_erboseness #] [E_ngage Probe] [L # of legs of travel]
* M70 - Power consumption sensor calibration
* 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<seconds> 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<seconds>. To disable set zero (default)
* M92 - Set axis_steps_per_unit - same syntax as G92
* M100 - Watch Free Memory (For Debugging Only)
* M104 - Set extruder target temp
* M105 - Read current temp
* M106 - Fan on
* M107 - Fan off
* M109 - Sxxx Wait for extruder current temp to reach target temp. Waits only when heating
* Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
* IF AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
* M110 - Set the current line number
* M111 - Set debug flags with S<mask>. See flag bits defined in Marlin.h.
* M112 - Emergency stop
* M114 - Output current position to serial port, (V)erbose for user
* M115 - Capabilities string
* M117 - Display a message on the controller screen
* M119 - Output Endstop status to serial port
* M120 - Enable endstop detection
* M121 - Disable endstop detection
* M122 - S<1=true/0=false> Enable or disable check software endstop
* M126 - Solenoid Air Valve Open (BariCUDA support by jmil)
* M127 - Solenoid Air Valve Closed (BariCUDA vent to atmospheric pressure by jmil)
* M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* M140 - Set bed target temp
* M145 - Set the heatup state H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
* M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
* M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
* Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
* M200 - set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).:D<millimeters>-
* 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: P for Printing moves, R for Retract only (no X, Y, Z) moves and T for Travel (non printing) moves (ex. M204 P800 T3000 R9000) in mm/sec^2
* 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 homing offset
* M207 - Set retract length S[positive mm] F[feedrate mm/min] Z[additional zlift/hop], stays in mm regardless of M200 setting
* M208 - Set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/min]
* M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction.
* M218 - Set hotend offset (in mm): T<extruder_number> X<offset_on_X> Y<offset_on_Y>
* M220 - Set speed factor override percentage: S<factor in percent>
* M221 - Set extrude factor override percentage: S<factor in percent>
* M222 - Set density extrusion percentage for purge: S<factor in percent>
* M226 - Wait until the specified pin reaches the state required: P<pin number> S<pin state>
* M240 - Trigger a camera to take a photograph
* M250 - Set LCD contrast C<contrast value> (value 0..63)
* M280 - Set servo position absolute. P: servo index, S: angle or microseconds
* M300 - Play beep sound S<frequency Hz> P<duration ms>
* M301 - Set PID parameters P I D and C
* M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.
* M303 - PID relay autotune S<temperature> sets the target temperature (default target temperature = 150C). H<hotend> C<cycles>
* M304 - Set bed PID parameters P I and D
* M350 - Set microstepping mode.
* M351 - Toggle MS1 MS2 pins directly.
* M380 - Activate solenoid on active extruder
* M381 - Disable all solenoids
* M400 - Finish all moves
* M401 - Lower z-probe if present
* M402 - Raise z-probe if present
* M404 - N<dia in mm> Enter the nominal filament width (3mm, 1.75mm ) or will display nominal filament width without parameters
* M405 - Turn on Filament Sensor extrusion control. Optional D<delay in cm> to set delay in centimeters between sensor and extruder
* M406 - Turn off Filament Sensor extrusion control
* M407 - Display measured filament diameter
* M410 - Quickstop. Abort all the planned moves
* M428 - Set the home_offset logically based on the current_position
* M500 - Store parameters in EEPROM
* M501 - Read parameters from EEPROM (if you need reset them after you changed them temporarily).
* M502 - Revert 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). Use S0 to leave off headings.
* M522 - Read or Write on card. M522 T<extruders> R<read> or W<write> L<list>
* M540 - Use S[0|1] to enable or disable the stop print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
* M595 - Set hotend AD595 O<offset> and S<gain>
* M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
* M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ]
* M666 - Set z probe offset or Endstop and delta geometry adjustment
* M907 - Set digital trimpot motor current using axis codes.
* M908 - Control digital trimpot directly.
*
* ************ SCARA Specific - This can change to suit future G-code regulations
* M360 - SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
* M361 - SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
* M362 - SCARA calibration: Move to cal-position PsiA (0 deg calibration)
* M363 - SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
* M364 - SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
* M365 - SCARA calibration: Scaling factor, X, Y, Z axis
* ************* SCARA End ***************
*
* M928 - Start SD logging (M928 filename.g) - ended by M29
* M997 - NPR2 Color rotate
* M999 - Restart after being stopped by error
*
* "T" Codes
*
* T0-T3 - Select a tool by index (usually an extruder) [ F<mm/min> ]
*
*/
#include "base.h"
#if ENABLED(DIGIPOT_I2C) || ENABLED(BLINKM)
......
......@@ -4,26 +4,16 @@
#include "Arduino.h"
#include "pins_arduino.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef __SAM3X8E__
#include "module/HAL.h"
#else
// Arduino < 1.0.0 does not define this, so we need to do it ourselves
#ifndef analogInputToDigitalPin
#define analogInputToDigitalPin(p) ((p) + 0xA0)
#endif
#include <util/delay.h>
#include <avr/eeprom.h>
#include "module/fastio.h"
#endif
#include "module/HAL.h"
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "module/macros.h"
#include "Boards.h"
#include "module/mechanics.h"
......@@ -47,13 +37,58 @@
#include "Configuration_Feature.h"
#endif
#include "Configuration_Store.h"
#include "language/language.h"
#include "module/language/language.h"
#include "module/conditionals.h"
#include "module/sanitycheck.h"
#include "module/thermistortables.h"
#include "module/comunication.h"
#include "module/communication/communication.h"
#include "module/MK_Main.h"
#include "module/motion/stepper.h"
#include "module/motion/stepper_indirection.h"
#include "module/motion/planner.h"
#include "module/temperature/temperature.h"
#include "module/temperature/thermistortables.h"
#include "module/lcd/ultralcd.h"
#include "module/nextion/nextion_lcd.h"
#if ENABLED(SDSUPPORT)
#include "module/sd/cardreader.h"
#endif
typedef unsigned long millis_t;
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "module/motion/vector_3.h"
#if ENABLED(AUTO_BED_LEVELING_GRID)
#include "module/motion/qr_solve.h"
#endif
#endif // AUTO_BED_LEVELING_FEATURE
#if MB(ALLIGATOR)
#include "module/alligator/external_dac.h"
#endif
#if ENABLED(USE_WATCHDOG)
#include "module/watchdog/watchdog.h"
#endif
#if HAS(BUZZER)
#include "module/lcd/buzzer.h"
#endif
#if ENABLED(BLINKM)
#include "module/blinkm/blinkm.h"
#endif
#if HAS(SERVOS)
#include "module/servo/servo.h"
#endif
#if HAS(DIGIPOTSS)
#include <SPI.h>
#endif
#if ENABLED(FIRMWARE_TEST)
#include "module/fwtest/firmware_test.h"
#endif
#endif
/*
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 <http://www.gnu.org/licenses/>.
*/
// **************************************************************************
//
// Description: *** HAL for Arduino ***
//
// **************************************************************************
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
#include "../base.h"
#include "HAL.h"
HAL::HAL() {
// ctor
}
HAL::~HAL() {
// dtor
}
// Print apparent cause of start/restart
void HAL::showStartReason() {
byte mcu = MCUSR;
if (mcu & 1) ECHO_EM(SERIAL_POWERUP);
if (mcu & 2) ECHO_EM(SERIAL_EXTERNAL_RESET);
if (mcu & 4) ECHO_EM(SERIAL_BROWNOUT_RESET);
if (mcu & 8) ECHO_EM(SERIAL_WATCHDOG_RESET);
if (mcu & 32) ECHO_EM(SERIAL_SOFTWARE_RESET);
MCUSR = 0;
}
// Return available memory
int HAL::getFreeRam() {
int freeram = 0;
InterruptProtectedBlock noInts;
uint8_t * heapptr, * stackptr;
heapptr = (uint8_t *)malloc(4); // get heap pointer
free(heapptr); // free up the memory again (sets heapptr to 0)
stackptr = (uint8_t *)(SP); // save value of stack pointer
freeram = (int)stackptr-(int)heapptr;
return freeram;
}
// Reset peripherals and cpu
void HAL::resetHardware() {}
#ifndef EXTERNALSERIAL
// Implement serial communication for one stream only!
/*
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
Modified to use only 1 queue with fixed length by Repetier
*/
ring_buffer rx_buffer = { { 0 }, 0, 0};
ring_buffer_tx tx_buffer = { { 0 }, 0, 0};
inline void rf_store_char(unsigned char c, ring_buffer *buffer) {
uint8_t i = (buffer->head + 1) & SERIAL_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 != buffer->tail) {
buffer->buffer[buffer->head] = c;
buffer->head = i;
}
}
#if !defined(USART0_RX_vect) && defined(USART1_RX_vect)
// do nothing - on the 32u4 the first USART is USART1
#else
void rfSerialEvent() __attribute__((weak));
void rfSerialEvent() {}
#define serialEvent_implemented
#if defined(USART_RX_vect)
SIGNAL(USART_RX_vect)
#elif defined(USART0_RX_vect)
SIGNAL(USART0_RX_vect)
#else
#if defined(SIG_USART0_RECV)
SIGNAL(SIG_USART0_RECV)
#elif defined(SIG_UART0_RECV)
SIGNAL(SIG_UART0_RECV)
#elif defined(SIG_UART_RECV)
SIGNAL(SIG_UART_RECV)
#else
#error "Don't know what the Data Received vector is called for the first UART"
#endif
#endif
{
#if defined(UDR0)
uint8_t c = UDR0;
#elif defined(UDR)
uint8_t c = UDR;
#else
#error UDR not defined
#endif
rf_store_char(c, &rx_buffer);
}
#endif
#if !defined(USART0_UDRE_vect) && defined(USART1_UDRE_vect)
// do nothing - on the 32u4 the first USART is USART1
#else
#if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect)
#error "Don't know what the Data Register Empty vector is called for the first UART"
#else
#if defined(UART0_UDRE_vect)
ISR(UART0_UDRE_vect)
#elif defined(UART_UDRE_vect)
ISR(UART_UDRE_vect)
#elif defined(USART0_UDRE_vect)
ISR(USART0_UDRE_vect)
#elif defined(USART_UDRE_vect)
ISR(USART_UDRE_vect)
#endif
{
if (tx_buffer.head == tx_buffer.tail) {
// Buffer empty, so disable interrupts
#if defined(UCSR0B)
bit_clear(UCSR0B, UDRIE0);
#else
bit_clear(UCSRB, UDRIE);
#endif
}
else {
// There is more data in the output buffer. Send the next byte
uint8_t c = tx_buffer.buffer[tx_buffer.tail];
#if defined(UDR0)
UDR0 = c;
#elif defined(UDR)
UDR = c;
#else
#error UDR not defined
#endif
tx_buffer.tail = (tx_buffer.tail + 1) & SERIAL_TX_BUFFER_MASK;
}
}
#endif
#endif
#if defined(BLUETOOTH) && BLUETOOTH_SERIAL > 0
#if !(defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1281__) || defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__))
#error BlueTooth option cannot be used with your mainboard
#endif
#if BLUETOOTH_SERIAL > 1 && !(defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
#error BlueTooth serial 2 or 3 can be used only with boards based on ATMega2560 or ATMega1280
#endif
#if (BLUETOOTH_SERIAL == 1)
#if defined(USART1_RX_vect)
#define SIG_USARTx_RECV USART1_RX_vect
#define USARTx_UDRE_vect USART1_UDRE_vect
#else
#define SIG_USARTx_RECV SIG_USART1_RECV
#define USARTx_UDRE_vect SIG_USART1_DATA
#endif
#define UDRx UDR1
#define UCSRxA UCSR1A
#define UCSRxB UCSR1B
#define UBRRxH UBRR1H
#define UBRRxL UBRR1L
#define U2Xx U2X1
#define UARTxENABLE ((1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1)|(1<<UDRIE1))
#define UDRIEx UDRIE1
#define RXxPIN 19
#elif (BLUETOOTH_SERIAL == 2)
#if defined(USART2_RX_vect)
#define SIG_USARTx_RECV USART2_RX_vect
#define USARTx_UDRE_vect USART2_UDRE_vect
#else
#define SIG_USARTx_RECV SIG_USART2_RECV
#define USARTx_UDRE_vect SIG_USART2_DATA
#endif
#define UDRx UDR2
#define UCSRxA UCSR2A
#define UCSRxB UCSR2B
#define UBRRxH UBRR2H
#define UBRRxL UBRR2L
#define U2Xx U2X2
#define UARTxENABLE ((1<<RXEN2)|(1<<TXEN2)|(1<<RXCIE2)|(1<<UDRIE2))
#define UDRIEx UDRIE2
#define RXxPIN 17
#elif (BLUETOOTH_SERIAL == 3)
#if defined(USART3_RX_vect)
#define SIG_USARTx_RECV USART3_RX_vect
#define USARTx_UDRE_vect USART3_UDRE_vect
#else
#define SIG_USARTx_RECV SIG_USART3_RECV
#define USARTx_UDRE_vect SIG_USART3_DATA
#endif
#define UDRx UDR3
#define UCSRxA UCSR3A
#define UCSRxB UCSR3B
#define UBRRxH UBRR3H
#define UBRRxL UBRR3L
#define U2Xx U2X3
#define UARTxENABLE ((1<<RXEN3)|(1<<TXEN3)|(1<<RXCIE3)|(1<<UDRIE3))
#define UDRIEx UDRIE3
#define RXxPIN 15
#else
#error Wrong serial port number for BlueTooth
#endif
SIGNAL(SIG_USARTx_RECV) {
uint8_t c = UDRx;
rf_store_char(c, &rx_buffer);
}
volatile uint8_t txx_buffer_tail = 0;
ISR(USARTx_UDRE_vect) {
if (tx_buffer.head == txx_buffer_tail) {
// Buffer empty, so disable interrupts
bit_clear(UCSRxB, UDRIEx);
}
else {
// There is more data in the output buffer. Send the next byte
uint8_t c = tx_buffer.buffer[txx_buffer_tail];
txx_buffer_tail = (txx_buffer_tail + 1) & SERIAL_TX_BUFFER_MASK;
UDRx = c;
}
}
#endif
// Constructors
MKHardwareSerial::MKHardwareSerial(ring_buffer *rx_buffer, ring_buffer_tx *tx_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 udrie, uint8_t u2x) {
_rx_buffer = rx_buffer;
_tx_buffer = tx_buffer;
_ubrrh = ubrrh;
_ubrrl = ubrrl;
_ucsra = ucsra;
_ucsrb = ucsrb;
_udr = udr;
_rxen = rxen;
_txen = txen;
_rxcie = rxcie;
_udrie = udrie;
_u2x = u2x;
}
// Public Methods
void MKHardwareSerial::begin(unsigned 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
try_again:
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;
}
if ((baud_setting > 4095) && use_u2x) {
use_u2x = false;
goto try_again;
}
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
*_ubrrh = baud_setting >> 8;
*_ubrrl = baud_setting;
bit_set(*_ucsrb, _rxen);
bit_set(*_ucsrb, _txen);
bit_set(*_ucsrb, _rxcie);
bit_clear(*_ucsrb, _udrie);
#if defined(BLUETOOTH) && BLUETOOTH_SERIAL > 0
WRITE(RXxPIN,1); // Pullup on RXDx
UCSRxA = (1<<U2Xx);
UBRRxH = (uint8_t)(((F_CPU / 4 / BLUETOOTH_BAUD -1) / 2) >> 8);
UBRRxL = (uint8_t)(((F_CPU / 4 / BLUETOOTH_BAUD -1) / 2) & 0xFF);
UCSRxB |= UARTxENABLE;
#endif
}
void MKHardwareSerial::end() {
// wait for transmission of outgoing data
while (_tx_buffer->head != _tx_buffer->tail)
;
bit_clear(*_ucsrb, _rxen);
bit_clear(*_ucsrb, _txen);
bit_clear(*_ucsrb, _rxcie);
bit_clear(*_ucsrb, _udrie);
#if defined(BLUETOOTH_SERIAL) && BLUETOOTH_SERIAL > 0
UCSRxB = 0;
#endif
// clear a ny received data
_rx_buffer->head = _rx_buffer->tail;
}
int MKHardwareSerial::available(void) {
return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) & SERIAL_BUFFER_MASK;
}
int MKHardwareSerial::outputUnused(void) {
return SERIAL_TX_BUFFER_SIZE - (unsigned int)((SERIAL_TX_BUFFER_SIZE + _tx_buffer->head - _tx_buffer->tail) & SERIAL_TX_BUFFER_MASK);
}
int MKHardwareSerial::peek(void) {
if (_rx_buffer->head == _rx_buffer->tail)
return -1;
return _rx_buffer->buffer[_rx_buffer->tail];
}
int MKHardwareSerial::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;
}
unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
_rx_buffer->tail = (_rx_buffer->tail + 1) & SERIAL_BUFFER_MASK;
return c;
}
void MKHardwareSerial::flush() {
while (_tx_buffer->head != _tx_buffer->tail);
#if defined(BLUETOOTH) && BLUETOOTH_SERIAL > 0
while (_tx_buffer->head != txx_buffer_tail);
#endif
}
#ifdef COMPAT_PRE1
void
#else
size_t
#endif
MKHardwareSerial::write(uint8_t c) {
uint8_t i = (_tx_buffer->head + 1) & SERIAL_TX_BUFFER_MASK;
// If the output buffer is full, there's nothing for it other than to
// wait for the interrupt handler to empty it a bit
while (i == _tx_buffer->tail) {}
#if defined(BLUETOOTH) && BLUETOOTH_SERIAL > 0
while (i == txx_buffer_tail) {}
#endif
_tx_buffer->buffer[_tx_buffer->head] = c;
_tx_buffer->head = i;
bit_set(*_ucsrb, _udrie);
#if defined(BLUETOOTH) && BLUETOOTH_SERIAL > 0
bit_set(UCSRxB, UDRIEx);
#endif
#ifndef COMPAT_PRE1
return 1;
#endif
}
// Preinstantiate Object
#if defined(UBRRH) && defined(UBRRL)
MKHardwareSerial MKSerial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X);
#elif defined(UBRR0H) && defined(UBRR0L)
MKHardwareSerial MKSerial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0);
#elif defined(USBCON)
// do nothing - Serial object and buffers are initialized in CDC code
#else
#error no serial port defined (port 0)
#endif
#endif
\ No newline at end of file
/**
* This is the main Hardware Abstraction Layer (HAL).
* To make the firmware work with different processors and toolchains,
* all hardware related code should be packed into the hal files.
*
* 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 <http://www.gnu.org/licenses/>.
*
*
* Description: *** HAL for Arduino Due ***
*
* ARDUINO_ARCH_SAM
*/
#ifndef HAL_H
#define HAL_H
#include <avr/pgmspace.h>
//#include <avr/io.h>
// Arduino < 1.0.0 does not define this, so we need to do it ourselves
#ifndef analogInputToDigitalPin
#define analogInputToDigitalPin(p) ((p) + 0xA0)
#endif
/**
* Defines & Macros
*/
// Compiler warning on unused varable.
#define UNUSED(x) (void) (x)
// Macros for bit
#define BIT(b) (1<<(b))
#define TEST(n, b) (((n)&BIT(b))!=0)
#define SET_BIT(n, b, value) (n) ^= ((-value)^(n)) & (BIT(b))
#define bit_clear(x, y) x&= ~(1<<y)
#define bit_set(x, y) x|= (1<<y)
// Macros for maths shortcuts
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define RADIANS(d) ((d)*M_PI/180.0)
#define DEGREES(r) ((r)*180.0/M_PI)
#define SIN_60 0.8660254037844386
#define COS_60 0.5
// Macros to support option testing
#define ENABLED defined
#define DISABLED !defined
#define PIN_EXISTS(PN) (defined(PN##_PIN) && PN##_PIN >= 0)
#define HAS(FE) (HAS_##FE)
#define HASNT(FE) (!(HAS_##FE))
// Macros to contrain values
#define NOLESS(v,n) do{ if (v < n) v = n; }while(0)
#define NOMORE(v,n) do{ if (v > n) v = n; }while(0)
#define COUNT(a) (sizeof(a)/sizeof(*a))
#define FORCE_INLINE __attribute__((always_inline)) inline
#ifndef CRITICAL_SECTION_START
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
#define CRITICAL_SECTION_END SREG = _sreg;
#endif
#if CPU_ARCH == ARCH_AVR
#include <avr/io.h>
#else
#define PROGMEM
#define PGM_P const char *
#define PSTR(s) s
#define pgm_read_byte_near(x) (*(uint8_t*)x)
#define pgm_read_byte(x) (*(uint8_t*)x)
#endif
#define PACK
#define FSTRINGVALUE(var,value) const char var[] PROGMEM = value;
#define FSTRINGVAR(var) static const char var[] PROGMEM;
#define FSTRINGPARAM(var) PGM_P var
#include <avr/eeprom.h>
#include <avr/wdt.h>
//#define EXTERNALSERIAL // Force using arduino serial
#ifndef EXTERNALSERIAL
#define HardwareSerial_h // Don't use standard serial console
#endif
#include <inttypes.h>
#include "Print.h"
#ifdef EXTERNALSERIAL
#define SERIAL_RX_BUFFER_SIZE 128
#endif
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#define COMPAT_PRE1
#endif
/**
* Types
*/
typedef uint32_t millis_t;
#if CPU_ARCH == ARCH_AVR
#include "fastio.h"
#else
#define READ(IO) digitalRead(IO)
#define WRITE(IO, v) digitalWrite(IO, v)
#define SET_INPUT(IO) pinMode(IO, INPUT)
#define SET_OUTPUT(IO) pinMode(IO, OUTPUT)
#endif
class InterruptProtectedBlock {
uint8_t sreg;
public:
inline void protect() {
cli();
}
inline void unprotect() {
SREG = sreg;
}
inline InterruptProtectedBlock(bool later = false) {
sreg = SREG;
if (!later) cli();
}
inline ~InterruptProtectedBlock() {
SREG = sreg;
}
};
#ifndef EXTERNALSERIAL
// Implement serial communication for one stream only!
/*
* 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
*
* Modified to use only 1 queue with fixed length by Repetier
*/
#define SERIAL_BUFFER_SIZE 128
#define SERIAL_BUFFER_MASK 127
#undef SERIAL_TX_BUFFER_SIZE
#undef SERIAL_TX_BUFFER_MASK
#ifdef BIG_OUTPUT_BUFFER
#define SERIAL_TX_BUFFER_SIZE 128
#define SERIAL_TX_BUFFER_MASK 127
#else
#define SERIAL_TX_BUFFER_SIZE 64
#define SERIAL_TX_BUFFER_MASK 63
#endif
struct ring_buffer {
uint8_t buffer[SERIAL_BUFFER_SIZE];
volatile uint8_t head;
volatile uint8_t tail;
};
struct ring_buffer_tx {
uint8_t buffer[SERIAL_TX_BUFFER_SIZE];
volatile uint8_t head;
volatile uint8_t tail;
};
class MKHardwareSerial : public Print {
public:
ring_buffer *_rx_buffer;
ring_buffer_tx *_tx_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 _udrie;
uint8_t _u2x;
public:
MKHardwareSerial(ring_buffer *rx_buffer, ring_buffer_tx *tx_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 udrie, uint8_t u2x);
void begin(unsigned long);
void end();
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
#ifdef COMPAT_PRE1
virtual void write(uint8_t);
#else
virtual size_t write(uint8_t);
#endif
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool();
int outputUnused(void); // Used for output in interrupts
};
extern MKHardwareSerial MKSerial;
#define MKSERIAL MKSerial
//extern ring_buffer x_buffer;
#define WAIT_OUT_EMPTY while(tx_buffer.head != tx_buffer.tail) {}
#else
#define MKSERIAL Serial
#endif
class HAL {
public:
HAL();
virtual ~HAL();
static inline char readFlashByte(PGM_P ptr) { return pgm_read_byte(ptr); }
static inline void serialSetBaudrate(long baud) { MKSERIAL.begin(baud); }
static inline bool serialByteAvailable() { return MKSERIAL.available() > 0; }
static inline uint8_t serialReadByte() { return MKSERIAL.read(); }
static inline void serialWriteByte(char b) { MKSERIAL.write(b); }
static inline void serialFlush() { MKSERIAL.flush(); }
static void showStartReason();
static int getFreeRam();
static void resetHardware();
protected:
private:
};
#endif // HAL_H
......@@ -27,220 +27,7 @@
* - http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
*/
#include "base.h"
#include "Marlin_main.h"
#include "module/ultralcd.h"
#include "module/nextion_lcd.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "module/vector_3.h"
#if ENABLED(AUTO_BED_LEVELING_GRID)
#include "module/qr_solve.h"
#endif
#endif // AUTO_BED_LEVELING_FEATURE
#include "module/planner.h"
#include "module/stepper_indirection.h"
#if MB(ALLIGATOR)
#include "module/external_dac.h"
#endif
#include "module/stepper.h"
#include "module/temperature.h"
#include "module/cardreader.h"
#include "Configuration_Store.h"
#if ENABLED(USE_WATCHDOG)
#include "module/watchdog.h"
#endif
#if HAS(BUZZER)
#include "module/buzzer.h"
#endif
#if ENABLED(BLINKM)
#include "module/blinkm.h"
#endif
#if HAS(SERVOS)
#include "module/servo.h"
#endif
#if HAS(DIGIPOTSS)
#include <SPI.h>
#endif
#if ENABLED(FIRMWARE_TEST)
#include "module/firmware_test.h"
#endif
/**
* Look here for descriptions of G-codes:
* - http://linuxcnc.org/handbook/gcode/g-code.html
* - http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
*
* Help us document these G-codes online:
* - http://reprap.org/wiki/G-code
* - https://github.com/MagoKimbra/MarlinKimbra/blob/master/Documentation/GCodes.md
*
* -----------------
* Implemented Codes
* -----------------
*
* "G" Codes
*
* G0 -> G1
* G1 - Coordinated Movement X Y Z E
* G2 - CW ARC
* G3 - CCW ARC
* G4 - Dwell S<seconds> or P<milliseconds>
* G10 - retract filament according to settings of M207
* G11 - retract recover filament according to settings of M208
* G28 - Home one or more axes
* G29 - Detailed Z-Probe, probes the bed at 3 or more points. Will fail if you haven't homed yet.
* G30 - Single Z Probe, probes bed at current XY location. - Bed Probe and Delta geometry Autocalibration
* G31 - Dock sled (Z_PROBE_SLED only)
* G32 - Undock sled (Z_PROBE_SLED only)
* G60 - Save current position coordinates (all axes, for active extruder).
* S<SLOT> - specifies memory slot # (0-based) to save into (default 0).
* G61 - Apply/restore saved coordinates to the active extruder.
* X Y Z E - Value to add at stored coordinates.
* F<speed> - Set Feedrate.
* S<SLOT> - specifies memory slot # (0-based) to restore from (default 0).
* G90 - Use Absolute Coordinates
* G91 - Use Relative Coordinates
* G92 - Set current position to coordinates given
*
* "M" Codes
*
* M0 - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)
* M1 - Same as M0
* M3 - Put S<value> in laser beam control
* M4 - Turn on laser beam
* M5 - Turn off laser beam
* M11 - Start/Stop printing serial mode
* M17 - Enable/Power all stepper motors
* M18 - Disable all stepper motors; same as M84
* M20 - List SD card
* M21 - Init SD card
* M22 - Release SD card
* M23 - Select SD file (M23 filename.g)
* M24 - Start/resume SD print
* M25 - Pause SD print
* M26 - Set SD position in bytes (M26 S12345)
* M27 - Report SD print status
* M28 - Start SD write (M28 filename.g)
* M29 - Stop SD write
* M30 - Delete file from SD (M30 filename.g)
* M31 - Output time since last M109 or SD card start to serial
* M32 - Select file and start SD print (Can be used _while_ printing from SD card files):
* syntax "M32 /path/filename#", or "M32 S<startpos bytes> !filename#"
* Call gcode file : "M32 P !filename#" and return to caller file after finishing (similar to #include).
* The '#' is necessary when calling from within sd files, as it stops buffer prereading
* M33 - Get the longname version of a path
* M42 - Change pin status via gcode Use M42 Px Sy to set pin x to value y, when omitting Px the onboard led will be used.
* M48 - Measure Z_Probe repeatability. M48 [P # of points] [X position] [Y position] [V_erboseness #] [E_ngage Probe] [L # of legs of travel]
* M70 - Power consumption sensor calibration
* 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<seconds> 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<seconds>. To disable set zero (default)
* M92 - Set axis_steps_per_unit - same syntax as G92
* M100 - Watch Free Memory (For Debugging Only)
* M104 - Set extruder target temp
* M105 - Read current temp
* M106 - Fan on
* M107 - Fan off
* M109 - Sxxx Wait for extruder current temp to reach target temp. Waits only when heating
* Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
* IF AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
* M110 - Set the current line number
* M111 - Set debug flags with S<mask>. See flag bits defined in Marlin.h.
* M112 - Emergency stop
* M114 - Output current position to serial port, (V)erbose for user
* M115 - Capabilities string
* M117 - Display a message on the controller screen
* M119 - Output Endstop status to serial port
* M120 - Enable endstop detection
* M121 - Disable endstop detection
* M122 - S<1=true/0=false> Enable or disable check software endstop
* M126 - Solenoid Air Valve Open (BariCUDA support by jmil)
* M127 - Solenoid Air Valve Closed (BariCUDA vent to atmospheric pressure by jmil)
* M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil)
* M140 - Set bed target temp
* M145 - Set the heatup state H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
* M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
* M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
* Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
* M200 - set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).:D<millimeters>-
* 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: P for Printing moves, R for Retract only (no X, Y, Z) moves and T for Travel (non printing) moves (ex. M204 P800 T3000 R9000) in mm/sec^2
* 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 homing offset
* M207 - Set retract length S[positive mm] F[feedrate mm/min] Z[additional zlift/hop], stays in mm regardless of M200 setting
* M208 - Set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/min]
* M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction.
* M218 - Set hotend offset (in mm): T<extruder_number> X<offset_on_X> Y<offset_on_Y>
* M220 - Set speed factor override percentage: S<factor in percent>
* M221 - Set extrude factor override percentage: S<factor in percent>
* M222 - Set density extrusion percentage for purge: S<factor in percent>
* M226 - Wait until the specified pin reaches the state required: P<pin number> S<pin state>
* M240 - Trigger a camera to take a photograph
* M250 - Set LCD contrast C<contrast value> (value 0..63)
* M280 - Set servo position absolute. P: servo index, S: angle or microseconds
* M300 - Play beep sound S<frequency Hz> P<duration ms>
* M301 - Set PID parameters P I D and C
* M302 - Allow cold extrudes, or set the minimum extrude S<temperature>.
* M303 - PID relay autotune S<temperature> sets the target temperature (default target temperature = 150C). H<hotend> C<cycles>
* M304 - Set bed PID parameters P I and D
* M350 - Set microstepping mode.
* M351 - Toggle MS1 MS2 pins directly.
* M380 - Activate solenoid on active extruder
* M381 - Disable all solenoids
* M400 - Finish all moves
* M401 - Lower z-probe if present
* M402 - Raise z-probe if present
* M404 - N<dia in mm> Enter the nominal filament width (3mm, 1.75mm ) or will display nominal filament width without parameters
* M405 - Turn on Filament Sensor extrusion control. Optional D<delay in cm> to set delay in centimeters between sensor and extruder
* M406 - Turn off Filament Sensor extrusion control
* M407 - Display measured filament diameter
* M410 - Quickstop. Abort all the planned moves
* M428 - Set the home_offset logically based on the current_position
* M500 - Store parameters in EEPROM
* M501 - Read parameters from EEPROM (if you need reset them after you changed them temporarily).
* M502 - Revert 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). Use S0 to leave off headings.
* M540 - Use S[0|1] to enable or disable the stop print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
* M595 - Set hotend AD595 offset and gain
* M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
* M605 - Set dual x-carriage movement mode: S<mode> [ X<duplication x-offset> R<duplication temp offset> ]
* M666 - Set z probe offset or Endstop and delta geometry adjustment
* M907 - Set digital trimpot motor current using axis codes.
* M908 - Control digital trimpot directly.
*
* ************ SCARA Specific - This can change to suit future G-code regulations
* M360 - SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
* M361 - SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
* M362 - SCARA calibration: Move to cal-position PsiA (0 deg calibration)
* M363 - SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
* M364 - SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
* M365 - SCARA calibration: Scaling factor, X, Y, Z axis
* ************* SCARA End ***************
*
* M928 - Start SD logging (M928 filename.g) - ended by M29
* M997 - NPR2 Color rotate
* M999 - Restart after being stopped by error
*
* "T" Codes
*
* T0-T3 - Select a tool by index (usually an extruder) [ F<mm/min> ]
*
*/
#include "../base.h"
#if ENABLED(M100_FREE_MEMORY_WATCHER)
void gcode_M100();
......@@ -306,7 +93,7 @@ static millis_t max_inactive_time = 0;
static millis_t stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME * 1000UL;
millis_t print_job_start_ms = 0; ///< Print job start time
millis_t print_job_stop_ms = 0; ///< Print job stop time
static uint8_t target_extruder;
static int8_t target_extruder;
bool no_wait_for_cooling = true;
bool target_direction;
bool software_endstops = true;
......@@ -434,7 +221,7 @@ double printer_usage_filament;
float filament_width_nominal = DEFAULT_NOMINAL_FILAMENT_DIA; //Set nominal filament width, can be changed with M404
bool filament_sensor = false; //M405 turns on filament_sensor control, M406 turns it off
float filament_width_meas = DEFAULT_MEASURED_FILAMENT_DIA; //Stores the measured filament diameter
signed char measurement_delay[MAX_MEASUREMENT_DELAY+1]; //ring buffer to delay measurement store extruder factor after subtracting 100
signed char measurement_delay[MAX_MEASUREMENT_DELAY + 1]; //ring buffer to delay measurement store extruder factor after subtracting 100
int delay_index1 = 0; //index into ring buffer
int delay_index2 = -1; //index into ring buffer - set to -1 on startup to indicate ring buffer needs to be initialized
float delay_dist = 0; //delay distance counter
......@@ -510,36 +297,12 @@ void process_next_command();
void plan_arc(float target[NUM_AXIS], float* offset, uint8_t clockwise);
bool setTargetedHotend(int code);
bool setTargetedExtruder(int code);
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
float extrude_min_temp = EXTRUDE_MINTEMP;
#endif
#ifdef __AVR__ // HAL for Due
#if ENABLED(SDSUPPORT)
#include "module/SdFatUtil.h"
int freeMemory() { return SdFatUtil::FreeRam(); }
#else
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;
}
}
#endif // !SDSUPPORT
#endif
#if ENABLED(M100_FREE_MEMORY_WATCHER)
// top_of_stack() returns the location of a variable on its stack frame. The value returned is above
// the stack once the function returns to the caller.
......@@ -634,7 +397,7 @@ bool enqueuecommand(const char* cmd) {
// This is dangerous if a mixing of serial and this happens
char* command = command_queue[cmd_queue_index_w];
strcpy(command, cmd);
ECHO_SMV(DB, SERIAL_ENQUEUEING, command);
ECHO_SMT(DB, SERIAL_ENQUEUEING, command);
ECHO_EM("\"");
cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE;
commands_in_queue++;
......@@ -824,27 +587,17 @@ void setup() {
disableStepperDrivers();
#endif
SERIAL_INIT(BAUDRATE);
HAL::serialSetBaudrate(BAUDRATE);
ECHO_EM(START);
ECHO_S(DB);
// Check startup - does nothing if bootloader sets MCUSR to 0
byte mcu = MCUSR;
if (mcu & 1) ECHO_EM(SERIAL_POWERUP);
if (mcu & 2) ECHO_EM(SERIAL_EXTERNAL_RESET);
if (mcu & 4) ECHO_EM(SERIAL_BROWNOUT_RESET);
if (mcu & 8) ECHO_EM(SERIAL_WATCHDOG_RESET);
if (mcu & 32) ECHO_EM(SERIAL_SOFTWARE_RESET);
MCUSR = 0;
ECHO_LM(DB, BUILD_VERSION);
HAL::showStartReason();
ECHO_EM(BUILD_VERSION);
#if ENABLED(STRING_DISTRIBUTION_DATE) && ENABLED(STRING_CONFIG_H_AUTHOR)
ECHO_LM(DB, SERIAL_CONFIGURATION_VER STRING_DISTRIBUTION_DATE SERIAL_AUTHOR STRING_CONFIG_H_AUTHOR);
ECHO_LM(DB, SERIAL_COMPILED __DATE__);
ECHO_EM(SERIAL_CONFIGURATION_VER STRING_DISTRIBUTION_DATE SERIAL_AUTHOR STRING_CONFIG_H_AUTHOR);
ECHO_EM(SERIAL_COMPILED __DATE__);
#endif // STRING_DISTRIBUTION_DATE
ECHO_SMV(DB, SERIAL_FREE_MEMORY, freeMemory());
ECHO_MV(SERIAL_FREE_MEMORY, HAL::getFreeRam());
ECHO_EMV(SERIAL_PLANNER_BUFFER_BYTES, (int)sizeof(block_t)*BLOCK_BUFFER_SIZE);
#if ENABLED(SDSUPPORT)
......@@ -958,8 +711,7 @@ void loop() {
}
void gcode_line_error(const char* err, bool doFlush = true) {
ECHO_S(ER);
PS_PGM(err);
ECHO_ST(ER, err);
ECHO_EV(gcode_LastN);
//Serial.println(gcode_N);
if (doFlush) FlushSerialRequestResend();
......@@ -980,7 +732,7 @@ void get_command() {
static millis_t last_command_time = 0;
millis_t ms = millis();
if (!MYSERIAL.available() && commands_in_queue == 0 && ms - last_command_time > 1000UL) {
if (!HAL::serialByteAvailable() && commands_in_queue == 0 && ms - last_command_time > 1000UL) {
ECHO_L(WT);
last_command_time = ms;
}
......@@ -989,13 +741,13 @@ void get_command() {
//
// Loop while serial characters are incoming and the queue is not full
//
while (MYSERIAL.available() > 0 && commands_in_queue < BUFSIZE) {
while (HAL::serialByteAvailable() > 0 && commands_in_queue < BUFSIZE) {
#if ENABLED(NO_TIMEOUTS)
last_command_time = ms;
#endif
serial_char = MYSERIAL.read();
serial_char = HAL::serialReadByte();
//
// If the character ends the line, or the line is full...
......@@ -1074,9 +826,9 @@ void get_command() {
serial_count = 0; //clear buffer
} else if (serial_char == '\\') { // Handle escapes
if (MYSERIAL.available() > 0 && commands_in_queue < BUFSIZE) {
if (HAL::serialByteAvailable() > 0 && commands_in_queue < BUFSIZE) {
// if we have one more character, copy it over
serial_char = MYSERIAL.read();
serial_char = HAL::serialReadByte();
command_queue[cmd_queue_index_w][serial_count++] = serial_char;
}
// otherwise do nothing
......@@ -1110,7 +862,7 @@ void get_command() {
millis_t t = (print_job_stop_ms - print_job_start_ms) / 1000;
int hours = t / 60 / 60, minutes = (t / 60) % 60;
sprintf_P(time, PSTR("%i " MSG_END_HOUR " %i " MSG_END_MINUTE), hours, minutes);
ECHO_LV(DB, time);
ECHO_LT(DB, time);
lcd_setstatus(time, true);
card.printingHasFinished();
card.checkautostart(true);
......@@ -1223,7 +975,7 @@ XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR);
#endif //DUAL_X_CARRIAGE
void print_xyz(const char* prefix, const float x, const float y, const float z, bool eol = true) {
ECHO_V(prefix);
ECHO_T(prefix);
ECHO_MV(": (", x);
ECHO_MV(", ", y);
ECHO_MV(", ", z);
......@@ -1297,7 +1049,7 @@ static void set_axis_is_at_home(AxisEnum axis) {
#endif
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "set_axis_is_at_home ", (unsigned long)axis);
ECHO_SMV(INFO, "set_axis_is_at_home ", (unsigned long)axis);
ECHO_MV(" > (home_offset[axis]==", home_offset[axis]);
print_xyz(") > current_position", current_position);
}
......@@ -1368,7 +1120,7 @@ static void clean_up_after_endstop_move() {
feedrate = homing_feedrate[Z_AXIS];
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("do_blocking_move_to", x, y, z);
}
......@@ -1410,7 +1162,7 @@ static void clean_up_after_endstop_move() {
current_position[Z_AXIS] = corrected_position.z;
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("set_bed_level_equation_lsq > current_position", current_position);
}
......@@ -1440,7 +1192,7 @@ static void clean_up_after_endstop_move() {
current_position[Z_AXIS] = corrected_position.z;
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("set_bed_level_equation_3pts > current_position", current_position);
}
......@@ -1482,14 +1234,14 @@ static void clean_up_after_endstop_move() {
sync_plan_position();
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("run_z_probe > current_position", current_position);
}
}
static void deploy_z_probe() {
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("deploy_z_probe > current_position", current_position);
}
#if HAS(SERVO_ENDSTOPS)
......@@ -1500,7 +1252,7 @@ static void clean_up_after_endstop_move() {
static void stow_z_probe(bool doRaise = true) {
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("stow_z_probe > current_position", current_position);
}
#if HAS(SERVO_ENDSTOPS)
......@@ -1510,8 +1262,8 @@ static void clean_up_after_endstop_move() {
#if Z_RAISE_AFTER_PROBING > 0
if (doRaise) {
if (debugLevel & DEBUG_INFO) {
ECHO_LMV(DB, "Raise Z (after) by ", (float)Z_RAISE_AFTER_PROBING);
ECHO_LMV(DB, "> SERVO_ENDSTOPS > do_blocking_move_to_z ", current_position[Z_AXIS] + Z_RAISE_AFTER_PROBING);
ECHO_LMV(INFO, "Raise Z (after) by ", (float)Z_RAISE_AFTER_PROBING);
ECHO_LMV(INFO, "> SERVO_ENDSTOPS > do_blocking_move_to_z ", current_position[Z_AXIS] + Z_RAISE_AFTER_PROBING);
}
do_blocking_move_to_z(current_position[Z_AXIS] + Z_RAISE_AFTER_PROBING); // this also updates current_position
st_synchronize();
......@@ -1534,10 +1286,10 @@ static void clean_up_after_endstop_move() {
// Probe bed height at position (x,y), returns the measured z value
static float probe_pt(float x, float y, float z_before, ProbeAction probe_action = ProbeDeployAndStow, int verbose_level = 1) {
if (debugLevel & DEBUG_INFO) {
ECHO_LM(DB, "probe_pt >>>");
ECHO_SMV(DB, "> ProbeAction:", (unsigned long)probe_action);
ECHO_LM(INFO, "probe_pt >>>");
ECHO_SMV(INFO, "> ProbeAction:", (unsigned long)probe_action);
print_xyz(" > current_position", current_position);
ECHO_SMV(DB, "Z Raise to z_before ", z_before);
ECHO_SMV(INFO, "Z Raise to z_before ", z_before);
ECHO_EMV(" > do_blocking_move_to_z ", z_before);
}
......@@ -1545,7 +1297,7 @@ static void clean_up_after_endstop_move() {
do_blocking_move_to_z(z_before); // this also updates current_position
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "> do_blocking_move_to_xy ", x - X_PROBE_OFFSET_FROM_EXTRUDER);
ECHO_SMV(INFO, "> do_blocking_move_to_xy ", x - X_PROBE_OFFSET_FROM_EXTRUDER);
ECHO_EMV(", ", y - Y_PROBE_OFFSET_FROM_EXTRUDER);
}
......@@ -1553,7 +1305,8 @@ static void clean_up_after_endstop_move() {
#if HASNT(Z_PROBE_SLED)
if (probe_action & ProbeDeploy) {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "> ProbeDeploy");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "> ProbeDeploy");
deploy_z_probe();
}
#endif
......@@ -1563,19 +1316,21 @@ static void clean_up_after_endstop_move() {
#if HASNT(Z_PROBE_SLED)
if (probe_action & ProbeStow) {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "> ProbeStow (stow_z_probe will do Z Raise)");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "> ProbeStow (stow_z_probe will do Z Raise)");
stow_z_probe();
}
#endif
if (verbose_level > 2) {
ECHO_SM(DB, SERIAL_BED_LEVELLING_BED);
ECHO_SM(INFO, SERIAL_BED_LEVELLING_BED);
ECHO_MV(SERIAL_BED_LEVELLING_X, x, 3);
ECHO_MV(SERIAL_BED_LEVELLING_Y, y, 3);
ECHO_EMV(SERIAL_BED_LEVELLING_Z, measured_z, 3);
}
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< probe_pt");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< probe_pt");
return measured_z;
}
......@@ -1595,7 +1350,7 @@ static void clean_up_after_endstop_move() {
((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, ">>> homeaxis(", (unsigned long)axis);
ECHO_SMV(INFO, ">>> homeaxis(", (unsigned long)axis);
ECHO_EM(")");
}
......@@ -1664,7 +1419,7 @@ static void clean_up_after_endstop_move() {
st_synchronize();
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> TRIGGER ENDSTOP > current_position", current_position);
}
......@@ -1698,7 +1453,7 @@ static void clean_up_after_endstop_move() {
sync_plan_position();
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> AFTER set_axis_is_at_home > current_position", current_position);
}
......@@ -1718,7 +1473,8 @@ static void clean_up_after_endstop_move() {
// Deploy a probe if there is one, and homing towards the bed
if (axis == Z_AXIS) {
if (axis_home_dir < 0) {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "> SERVO_LEVELING > stow_z_probe");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "> SERVO_LEVELING > stow_z_probe");
stow_z_probe();
}
}
......@@ -1728,14 +1484,15 @@ static void clean_up_after_endstop_move() {
#if HAS(SERVO_ENDSTOPS)
// Retract Servo endstop if enabled
if (servo_endstop_id[axis] >= 0) {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "> SERVO_ENDSTOPS > Stow with servo.move()");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "> SERVO_ENDSTOPS > Stow with servo.move()");
servo[servo_endstop_id[axis]].move(servo_endstop_angle[axis][1]);
}
#endif
}
}
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "<<< homeaxis(", (unsigned long)axis);
ECHO_SMV(INFO, "<<< homeaxis(", (unsigned long)axis);
ECHO_EM(")");
}
}
......@@ -1789,7 +1546,7 @@ static void clean_up_after_endstop_move() {
sync_plan_position();
destination[axis] = endstop_adj[axis];
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "> endstop_adj = ", endstop_adj[axis]);
ECHO_SMV(INFO, "> endstop_adj = ", endstop_adj[axis]);
print_xyz(" > destination", destination);
}
line_to_destination();
......@@ -1797,14 +1554,15 @@ static void clean_up_after_endstop_move() {
enable_endstops(true); // Enable endstops for next homing move
}
if (debugLevel & DEBUG_INFO) ECHO_LMV(DB, "> endstop_adj * axis_home_dir = ", endstop_adj[axis] * axis_home_dir);
if (debugLevel & DEBUG_INFO)
ECHO_LMV(INFO, "> endstop_adj * axis_home_dir = ", endstop_adj[axis] * axis_home_dir);
// Set the axis position to its home position (plus home offsets)
set_axis_is_at_home(axis);
sync_plan_position();
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> AFTER set_axis_is_at_home > current_position", current_position);
}
......@@ -1885,7 +1643,8 @@ static void clean_up_after_endstop_move() {
// Reset calibration results to zero.
void reset_bed_level() {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "reset_bed_level");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "reset_bed_level");
for (int y = 0; y < AUTO_BED_LEVELING_GRID_POINTS; y++) {
for (int x = 0; x < AUTO_BED_LEVELING_GRID_POINTS; x++) {
bed_level[x][y] = 0.0;
......@@ -2547,7 +2306,7 @@ static void clean_up_after_endstop_move() {
probe_z = probe_bed_mean / probe_count;
if (debugLevel & DEBUG_INFO) {
ECHO_SM(DB, "Bed probe heights: ");
ECHO_SM(INFO, "Bed probe heights: ");
for(int i = 0; i < probe_count; i++) {
if (probe_bed_array[i] >= 0) ECHO_M(" ");
ECHO_VM(probe_bed_array[i], " ", 4);
......@@ -2729,21 +2488,21 @@ static void clean_up_after_endstop_move() {
delta[Y_AXIS] += offset;
delta[Z_AXIS] += offset;
/*
ECHO_SMV(DB, "grid_x=", grid_x);
ECHO_MV(" grid_y=", grid_y);
ECHO_MV(" floor_x=", floor_x);
ECHO_MV(" floor_y=", floor_y);
ECHO_MV(" ratio_x=", ratio_x);
ECHO_MV(" ratio_y=", ratio_y);
ECHO_MV(" z1=", z1);
ECHO_MV(" z2=", z2);
ECHO_MV(" z3=", z3);
ECHO_MV(" z4=", z4);
ECHO_MV(" left=", left);
ECHO_MV(" right=", right);
ECHO_EMV(" offset=", offset);
*/
if (debugLevel & DEBUG_DEBUG) {
ECHO_SMV(DB, "grid_x=", grid_x);
ECHO_MV(" grid_y=", grid_y);
ECHO_MV(" floor_x=", floor_x);
ECHO_MV(" floor_y=", floor_y);
ECHO_MV(" ratio_x=", ratio_x);
ECHO_MV(" ratio_y=", ratio_y);
ECHO_MV(" z1=", z1);
ECHO_MV(" z2=", z2);
ECHO_MV(" z3=", z3);
ECHO_MV(" z4=", z4);
ECHO_MV(" left=", left);
ECHO_MV(" right=", right);
ECHO_EMV(" offset=", offset);
}
}
#endif //DELTA
......@@ -2839,7 +2598,8 @@ static void clean_up_after_endstop_move() {
* offset[in] The additional distance to move to adjust docking location
*/
static void dock_sled(bool dock, int offset=0) {
if (debugLevel & DEBUG_INFO) ECHO_LMV(DB, "dock_sled", dock);
if (debugLevel & DEBUG_INFO)
ECHO_LMV(INFO, "dock_sled", dock);
if (!axis_known_position[X_AXIS] || !axis_known_position[Y_AXIS]) {
LCD_MESSAGEPGM(MSG_POSITION_UNKNOWN);
......@@ -3044,8 +2804,7 @@ void gcode_get_destination() {
}
void unknown_command_error() {
ECHO_SMV(DB, SERIAL_UNKNOWN_COMMAND, current_command);
ECHO_M("\"\n");
ECHO_LMT(ER, SERIAL_UNKNOWN_COMMAND, current_command);
}
/**
......@@ -3159,7 +2918,8 @@ inline void gcode_G4() {
*/
inline void gcode_G28() {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "gcode_G28 >>>");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "gcode_G28 >>>");
// Wait for planner moves to finish!
st_synchronize();
......@@ -3228,7 +2988,7 @@ inline void gcode_G28() {
sync_plan_position_delta();
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("(DELTA) > current_position", current_position);
}
......@@ -3240,7 +3000,7 @@ inline void gcode_G28() {
HOMEAXIS(Z);
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> HOMEAXIS(Z) > current_position", current_position);
}
......@@ -3249,7 +3009,7 @@ inline void gcode_G28() {
// Raise Z before homing any other axes
destination[Z_AXIS] = -Z_RAISE_BEFORE_HOMING * home_dir(Z_AXIS); // Set destination away from bed
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > (home_all_axis || homeZ) > destination", destination);
}
feedrate = max_feedrate[Z_AXIS] * 60;
......@@ -3289,7 +3049,7 @@ inline void gcode_G28() {
sync_plan_position();
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> QUICK_HOME > current_position 1", current_position);
}
......@@ -3307,7 +3067,7 @@ inline void gcode_G28() {
#endif
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> QUICK_HOME > current_position 2", current_position);
}
}
......@@ -3336,7 +3096,7 @@ inline void gcode_G28() {
HOMEAXIS(X);
#endif
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> homeX", current_position);
}
}
......@@ -3346,7 +3106,7 @@ inline void gcode_G28() {
if (home_all_axis || homeY) {
HOMEAXIS(Y);
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> homeY", current_position);
}
}
......@@ -3448,13 +3208,14 @@ inline void gcode_G28() {
else if (home_all_axis || homeZ) {
HOMEAXIS(Z);
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> (home_all_axis || homeZ) > final", current_position);
}
}
#elif ENABLED(Z_SAFE_HOMING) && ENABLED(AUTO_BED_LEVELING_FEATURE)// Z Safe mode activated.
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "> Z_SAFE_HOMING >>>");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "> Z_SAFE_HOMING >>>");
if (home_all_axis) {
......@@ -3472,7 +3233,7 @@ inline void gcode_G28() {
feedrate = xy_travel_speed;
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > home_all_axis > current_position", current_position, false);
print_xyz(" > home_all_axis > destination", destination);
}
......@@ -3508,7 +3269,7 @@ inline void gcode_G28() {
feedrate = max_feedrate[Z_AXIS] * 60;
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > homeZ > current_position", current_position, false);
print_xyz(" > homeZ > destination", destination);
}
......@@ -3529,7 +3290,8 @@ inline void gcode_G28() {
ECHO_LM(DB, MSG_POSITION_UNKNOWN);
}
}
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< Z_SAFE_HOMING");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#elif ENABLED(Z_SAFE_HOMING)
if (home_all_axis || homeZ) {
......@@ -3544,7 +3306,7 @@ inline void gcode_G28() {
feedrate = xy_travel_speed;
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > home_all_axis > current_position", current_position, false);
print_xyz(" > home_all_axis > destination", destination);
}
......@@ -3563,7 +3325,8 @@ inline void gcode_G28() {
ECHO_LM(ER, MSG_POSITION_UNKNOWN);
}
}
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< Z_SAFE_HOMING");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#endif //Z_SAFE_HOMING
#endif //Z_HOME_DIR < 0
......@@ -3608,14 +3371,15 @@ inline void gcode_G28() {
gfx_cursor_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS]);
#endif
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< gcode_G28");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< gcode_G28");
}
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
void out_of_range_error(const char* p_edge) {
ECHO_M("?Probe ");
PS_PGM(p_edge);
ECHO_T(p_edge);
ECHO_EM(" position out of range.");
}
......@@ -3657,7 +3421,8 @@ inline void gcode_G28() {
*/
inline void gcode_G29() {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "gcode_G29 >>>");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "gcode_G29 >>>");
// Don't allow auto-leveling without homing first
if (!axis_known_position[X_AXIS] || !axis_known_position[Y_AXIS]) {
......@@ -3799,9 +3564,9 @@ inline void gcode_G28() {
if (debugLevel & DEBUG_INFO) {
if (probePointCounter)
ECHO_LMV(DB, "z_before = (between) ", (float)(Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS]));
ECHO_LMV(INFO, "z_before = (between) ", (float)(Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS]));
else
ECHO_LMV(DB, "z_before = (before) ", (float)Z_RAISE_BEFORE_PROBING + current_position[Z_AXIS]);
ECHO_LMV(INFO, "z_before = (before) ", (float)Z_RAISE_BEFORE_PROBING + current_position[Z_AXIS]);
}
ProbeAction act;
......@@ -3831,7 +3596,7 @@ inline void gcode_G28() {
} //yProbe
if (debugLevel & DEBUG_INFO) {
ECHO_S(DB);
ECHO_S(INFO);
print_xyz("> probing complete > current_position", current_position);
}
......@@ -3916,7 +3681,8 @@ inline void gcode_G28() {
#else // !AUTO_BED_LEVELING_GRID
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "> 3-point Leveling");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "> 3-point Leveling");
// Actions for each probe
ProbeAction p1, p2, p3;
......@@ -3947,8 +3713,8 @@ inline void gcode_G28() {
real_z = st_get_position_mm(Z_AXIS); //get the real Z (since plan_get_position is now correcting the plane)
if (debugLevel & DEBUG_INFO) {
ECHO_LMV(DB, "> BEFORE apply_rotation_xyz > z_tmp = ", z_tmp);
ECHO_LMV(DB, "> BEFORE apply_rotation_xyz > real_z = ", real_z);
ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > z_tmp = ", z_tmp);
ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > real_z = ", real_z);
}
apply_rotation_xyz(plan_bed_level_matrix, x_tmp, y_tmp, z_tmp); // Apply the correction sending the Z probe offset
......@@ -3970,7 +3736,7 @@ inline void gcode_G28() {
// added here, it could be seen as a compensating factor for the Z probe.
//
if (debugLevel & DEBUG_INFO)
ECHO_LMV(DB, "> AFTER apply_rotation_xyz > z_tmp = ", z_tmp);
ECHO_LMV(INFO, "> AFTER apply_rotation_xyz > z_tmp = ", z_tmp);
current_position[Z_AXIS] = -zprobe_zoffset + (z_tmp - real_z)
#if HAS(SERVO_ENDSTOPS) || ENABLED(Z_PROBE_SLED)
......@@ -3991,14 +3757,15 @@ inline void gcode_G28() {
#if ENABLED(Z_PROBE_END_SCRIPT)
if (debugLevel & DEBUG_INFO) {
ECHO_SM(DB, "Z Probe End Script: ");
ECHO_SM(INFO, "Z Probe End Script: ");
ECHO_EM(Z_PROBE_END_SCRIPT);
}
enqueuecommands_P(PSTR(Z_PROBE_END_SCRIPT));
st_synchronize();
#endif
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< gcode_G29");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< gcode_G29");
}
#if HASNT(Z_PROBE_SLED)
......@@ -4007,7 +3774,8 @@ inline void gcode_G28() {
*/
inline void gcode_G30() {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "gcode_G30 >>>");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "gcode_G30 >>>");
#if HAS(SERVO_ENDSTOPS)
raise_z_for_servo();
......@@ -4024,7 +3792,8 @@ inline void gcode_G28() {
ECHO_SM(DB, "Bed");
ECHO_MV(" X: ", current_position[X_AXIS] + 0.0001);
ECHO_MV(" Y: ", current_position[Y_AXIS] + 0.0001);
ECHO_EMV(" Z: ", current_position[Z_AXIS] + 0.0001);
ECHO_MV(" Z: ", current_position[Z_AXIS] + 0.0001);
ECHO_E;
clean_up_after_endstop_move();
......@@ -4034,7 +3803,8 @@ inline void gcode_G28() {
stow_z_probe(); // Retract Z Servo endstop if available
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< gcode_G30");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< gcode_G30");
}
#endif // !Z_PROBE_SLED
#endif // AUTO_BED_LEVELING_FEATURE
......@@ -4046,7 +3816,8 @@ inline void gcode_G28() {
*/
inline void gcode_G29() {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "gcode_G29 >>>");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "gcode_G29 >>>");
if (code_seen('D')) {
print_bed_level();
......@@ -4063,7 +3834,8 @@ inline void gcode_G28() {
retract_z_probe();
clean_up_after_endstop_move();
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< gcode_G29");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< gcode_G29");
}
/* G30: Delta AutoCalibration
......@@ -4074,7 +3846,8 @@ inline void gcode_G28() {
*/
inline void gcode_G30() {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "gcode_G30 >>>");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "gcode_G30 >>>");
//Zero the bed level array
reset_bed_level();
......@@ -4104,7 +3877,7 @@ inline void gcode_G28() {
ECHO_EMV(" = ", probe_value, 4);
if (debugLevel & DEBUG_INFO) {
ECHO_SMV(DB, "Carriage Positions: [", saved_position[X_AXIS]);
ECHO_SMV(INFO, "Carriage Positions: [", saved_position[X_AXIS]);
ECHO_MV(", ", saved_position[Y_AXIS]);
ECHO_MV(", ", saved_position[Z_AXIS]);
ECHO_EM("]");
......@@ -4277,7 +4050,8 @@ inline void gcode_G28() {
clean_up_after_endstop_move();
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< gcode_G30");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< gcode_G30");
}
#endif // DELTA && Z_PROBE_ENDSTOP
......@@ -4592,7 +4366,7 @@ inline void gcode_M31() {
int min = t / 60, sec = t % 60;
char time[30];
sprintf_P(time, PSTR("%i min, %i sec"), min, sec);
ECHO_LV(DB, time);
ECHO_LT(DB, time);
lcd_setstatus(time);
autotempShutdown();
}
......@@ -4704,7 +4478,8 @@ inline void gcode_M42() {
*/
inline void gcode_M48() {
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "gcode_M48 >>>");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "gcode_M48 >>>");
double sum = 0.0, mean = 0.0, sigma = 0.0, sample_set[50];
uint8_t verbose_level = 1, n_samples = 10, n_legs = 0;
......@@ -4902,7 +4677,8 @@ inline void gcode_M42() {
if (verbose_level > 0) ECHO_EMV("Mean: ", mean, 6);
ECHO_EMV("Standard Deviation: ", sigma, 6);
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, "<<< gcode_M28");
if (debugLevel & DEBUG_INFO)
ECHO_LM(INFO, "<<< gcode_M28");
}
#endif // AUTO_BED_LEVELING_FEATURE && Z_PROBE_REPEATABILITY_TEST
......@@ -5034,7 +4810,7 @@ inline void gcode_M85() {
* M92: Set axis_steps_per_unit
*/
inline void gcode_M92() {
if (setTargetedHotend(92)) return;
if (setTargetedExtruder(92)) return;
for(int8_t i = 0; i < NUM_AXIS; i++) {
if (code_seen(axis_codes[i])) {
......@@ -5230,7 +5006,7 @@ inline void gcode_M92() {
* M104: Set hot end temperature
*/
inline void gcode_M104() {
if (setTargetedHotend(104)) return;
if (setTargetedExtruder(104)) return;
if (debugLevel & DEBUG_DRYRUN) return;
#if HOTENDS == 1
......@@ -5251,7 +5027,7 @@ inline void gcode_M104() {
* M105: Read hot end and bed temperature
*/
inline void gcode_M105() {
if (setTargetedHotend(105)) return;
if (setTargetedExtruder(105)) return;
#if HAS(TEMP_0) || HAS(TEMP_BED) || ENABLED(HEATER_0_USES_MAX6675)
ECHO_S(OK);
......@@ -5280,7 +5056,7 @@ inline void gcode_M105() {
* M109: Wait for extruder(s) to reach temperature
*/
inline void gcode_M109() {
if (setTargetedHotend(109)) return;
if (setTargetedExtruder(109)) return;
if (debugLevel & DEBUG_DRYRUN) return;
#if HOTENDS == 1
......@@ -5403,36 +5179,36 @@ inline void gcode_M115() {
* M119: Output endstop states to serial output
*/
inline void gcode_M119() {
ECHO_LV(DB, SERIAL_M119_REPORT);
ECHO_LM(DB, SERIAL_M119_REPORT);
#if HAS(X_MIN)
ECHO_EMV(SERIAL_X_MIN, ((READ(X_MIN_PIN)^X_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_X_MIN, ((READ(X_MIN_PIN)^X_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(X_MAX)
ECHO_EMV(SERIAL_X_MAX, ((READ(X_MAX_PIN)^X_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_X_MAX, ((READ(X_MAX_PIN)^X_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(Y_MIN)
ECHO_EMV(SERIAL_Y_MIN, ((READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_Y_MIN, ((READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(Y_MAX)
ECHO_EMV(SERIAL_Y_MAX, ((READ(Y_MAX_PIN)^Y_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_Y_MAX, ((READ(Y_MAX_PIN)^Y_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(Z_MIN)
ECHO_EMV(SERIAL_Z_MIN, ((READ(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_Z_MIN, ((READ(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(Z_MAX)
ECHO_EMV(SERIAL_Z_MAX, ((READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_Z_MAX, ((READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(Z2_MAX)
ECHO_EMV(SERIAL_Z2_MAX, ((READ(Z2_MAX_PIN)^Z2_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_Z2_MAX, ((READ(Z2_MAX_PIN)^Z2_MAX_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(Z_PROBE)
ECHO_EMV(SERIAL_Z_PROBE, ((READ(Z_PROBE_PIN)^Z_PROBE_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_Z_PROBE, ((READ(Z_PROBE_PIN)^Z_PROBE_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(E_MIN)
ECHO_EMV(SERIAL_E_MIN, ((READ(E_MIN_PIN)^E_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_E_MIN, ((READ(E_MIN_PIN)^E_MIN_ENDSTOP_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
#if HAS(FILRUNOUT)
ECHO_EMV(SERIAL_FILRUNOUT_PIN, ((READ(FILRUNOUT_PIN)^FILRUNOUT_PIN_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
ECHO_EMT(SERIAL_FILRUNOUT_PIN, ((READ(FILRUNOUT_PIN)^FILRUNOUT_PIN_INVERTING)?SERIAL_ENDSTOP_HIT:SERIAL_ENDSTOP_OPEN));
#endif
ECHO_E;
}
......@@ -5614,7 +5390,7 @@ inline void gcode_M140() {
*/
inline void gcode_M200() {
if (setTargetedHotend(200)) return;
if (setTargetedExtruder(200)) return;
if (code_seen('D')) {
float diameter = code_value();
......@@ -5666,7 +5442,7 @@ inline void gcode_M201() {
*
*/
inline void gcode_M203() {
if (setTargetedHotend(203)) return;
if (setTargetedExtruder(203)) return;
for(int8_t i = 0; i < NUM_AXIS; i++) {
if (code_seen(axis_codes[i])) {
......@@ -5688,7 +5464,7 @@ inline void gcode_M203() {
* Also sets minimum segment time in ms (B20000) to prevent buffer under-runs and M20 minimum feedrate
*/
inline void gcode_M204() {
if (setTargetedHotend(204)) return;
if (setTargetedExtruder(204)) return;
if (code_seen('S')) { // Kept for legacy compatibility. Should NOT BE USED for new developments.
acceleration = code_value();
......@@ -5720,7 +5496,7 @@ inline void gcode_M204() {
* E = Max E Jerk (mm/s/s)
*/
inline void gcode_M205() {
if (setTargetedHotend(205)) return;
if (setTargetedExtruder(205)) return;
if (code_seen('S')) minimumfeedrate = code_value();
if (code_seen('V')) mintravelfeedrate = code_value();
......@@ -5808,7 +5584,7 @@ inline void gcode_M206() {
* M218 - set hotend offset (in mm), T<extruder_number> X<offset_on_X> Y<offset_on_Y>
*/
inline void gcode_M218() {
if (setTargetedHotend(218)) return;
if (setTargetedExtruder(218)) return;
if (code_seen('X')) hotend_offset[X_AXIS][target_extruder] = code_value();
if (code_seen('Y')) hotend_offset[Y_AXIS][target_extruder] = code_value();
......@@ -5838,7 +5614,7 @@ inline void gcode_M221() {
if (code_seen('S')) {
int sval = code_value();
if (code_seen('T')) {
if (setTargetedHotend(221)) return;
if (setTargetedExtruder(221)) return;
extruder_multiplier[target_extruder] = sval;
}
else {
......@@ -5854,7 +5630,7 @@ inline void gcode_M222() {
if (code_seen('S')) {
int sval = code_value();
if (code_seen('T')) {
if (setTargetedHotend(222)) return;
if (setTargetedExtruder(222)) return;
density_multiplier[target_extruder] = sval;
}
else {
......@@ -6449,28 +6225,27 @@ inline void gcode_M503() {
#if HEATER_USES_AD595
/**
* M595 - set Hotennd AD595 offset & Gain T<hotend_number> O<offset> G<gain>
* M595 - set Hotend AD595 offset & Gain T<hotend_number> O<offset> S<gain>
*/
inline void gcode_M595() {
if (setTargetedHotend(595)) return;
if (setTargetedExtruder(595)) return;
if (code_seen('O')) ad595_offset[target_extruder] = code_value();
if (code_seen('G')) ad595_gain[target_extruder] = code_value();
if (code_seen('S')) ad595_gain[target_extruder] = code_value();
for (int h = 0; h < HOTENDS; h++) {
// if gain == 0 you get MINTEMP!
if (ad595_gain[h] == 0) ad595_gain[h]= 1;
}
ECHO_SM(DB, MSG_HOTEND_AD595);
ECHO_E;
ECHO_LM(DB, MSG_AD595);
for (int h = 0; h < HOTENDS; h++) {
ECHO_SMV(DB, "T", h);
ECHO_MV(" Offset: ", ad595_offset[h]);
ECHO_EMV(", Gain: ", ad595_gain[h]);
}
}
#endif
#endif // HEATER_USES_AD595
#if ENABLED(FILAMENTCHANGEENABLE)
/**
......@@ -7146,7 +6921,7 @@ void process_next_command() {
current_command = command_queue[cmd_queue_index_r];
if ((debugLevel & DEBUG_ECHO)) {
ECHO_LV(DB, current_command);
ECHO_LT(DB, current_command);
}
// Sanitize the current command:
......@@ -7609,9 +7384,9 @@ ExitUnknownCommand:
void FlushSerialRequestResend() {
//char command_queue[cmd_queue_index_r][100]="Resend:";
MYSERIAL.flush();
ECHO_LV(RS, gcode_LastN + 1);
ok_to_send();
HAL::serialFlush();
ECHO_LV(RESEND, (long)(gcode_LastN + 1));
ECHO_S(OK);
}
void ok_to_send() {
......@@ -8136,7 +7911,8 @@ void idle(bool ignore_stepper_queue/*=false*/) {
* - Check for HOME button held down
* - Check if cooling fan needs to be switched on
* - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT)
* - check oozing prevent
* - Check oozing prevent
* - Read o Write Rfid
*/
void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
......@@ -8289,10 +8065,10 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
if (!filament_changing)
#endif
{
if(degTargetHotend(active_extruder) < IDLE_OOZING_MINTEMP) {
if (degTargetHotend(active_extruder) < IDLE_OOZING_MINTEMP) {
IDLE_OOZING_retract(false);
}
else if((millis() - axis_last_activity) > IDLE_OOZING_SECONDS*1000UL) {
else if ((millis() - axis_last_activity) > IDLE_OOZING_SECONDS * 1000UL) {
IDLE_OOZING_retract(true);
}
}
......@@ -8327,6 +8103,8 @@ void kill(const char* lcd_msg) {
lcd_setalertstatuspgm(lcd_msg);
#endif
HAL::resetHardware();
cli(); // Stop interrupts
disable_all_heaters();
disable_all_steppers();
......@@ -8436,7 +8214,7 @@ void Stop() {
}
}
bool setTargetedHotend(int code) {
bool setTargetedExtruder(int code) {
target_extruder = active_extruder;
if (code_seen('T')) {
target_extruder = code_value_short();
......@@ -8452,10 +8230,10 @@ bool setTargetedHotend(int code) {
float calculate_volumetric_multiplier(float diameter) {
if (!volumetric_enabled || diameter == 0) return 1.0;
float d2 = diameter * 0.5;
return 1.0 / (M_PI * d2 * d2);
return 100.0 / (M_PI * d2 * d2);
}
void calculate_volumetric_multipliers() {
for (int i = 0; i < EXTRUDERS; i++)
volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
for (int8_t e = 0; e < EXTRUDERS; e++)
volumetric_multiplier[e] = calculate_volumetric_multiplier(filament_size[e]);
}
// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.
// License: GPL
#ifndef MARLIN_H
#define MARLIN_H
#ifndef MK_H
#define MK_H
#include <math.h>
#include <stdint.h>
void get_command();
void idle(bool ignore_stepper_queue = false);
void manage_inactivity(bool ignore_stepper_queue=false);
void manage_inactivity(bool ignore_stepper_queue = false);
void FlushSerialRequestResend();
void ok_to_send();
......@@ -251,4 +254,4 @@ extern void calculate_volumetric_multipliers();
#endif
#endif //MARLIN_H
#endif // MK_H
/*
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 "../base.h"
#include "MarlinSerial.h"
#ifndef USBCON
// 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 UART_PRESENT(SERIAL_PORT)
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;
// 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(M_USARTx_RX_vect)
// fixed by Mark Sproul this is on the 644/644p
//SIGNAL(SIG_USART_RECV)
SIGNAL(M_USARTx_RX_vect) {
unsigned char c = M_UDRx;
store_char(c);
}
#endif
// Constructors ////////////////////////////////////////////////////////////////
MarlinSerial::MarlinSerial() { }
// Public Methods //////////////////////////////////////////////////////////////
void MarlinSerial::begin(long baud) {
uint16_t baud_setting;
bool useU2X = true;
#if F_CPU == 16000000UL && SERIAL_PORT == 0
// hard-coded 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) {
useU2X = false;
}
#endif
if (useU2X) {
M_UCSRxA = BIT(M_U2Xx);
baud_setting = (F_CPU / 4 / baud - 1) / 2;
} else {
M_UCSRxA = 0;
baud_setting = (F_CPU / 8 / baud - 1) / 2;
}
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
M_UBRRxH = baud_setting >> 8;
M_UBRRxL = baud_setting;
sbi(M_UCSRxB, M_RXENx);
sbi(M_UCSRxB, M_TXENx);
sbi(M_UCSRxB, M_RXCIEx);
}
void MarlinSerial::end() {
cbi(M_UCSRxB, M_RXENx);
cbi(M_UCSRxB, M_TXENx);
cbi(M_UCSRxB, M_RXCIEx);
}
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;
}
/// imports from print.h
void MarlinSerial::print(char c, int base) {
print((long) c, base);
}
void MarlinSerial::print(unsigned char b, int base) {
print((unsigned long) b, base);
}
void MarlinSerial::print(int n, int base) {
print((long) n, base);
}
void MarlinSerial::print(unsigned int n, int base) {
print((unsigned long) n, base);
}
void MarlinSerial::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 MarlinSerial::print(unsigned long n, int base) {
if (base == 0) write(n);
else printNumber(n, base);
}
void MarlinSerial::print(double n, int digits) {
printFloat(n, digits);
}
void MarlinSerial::println(void) {
print('\r');
print('\n');
}
void MarlinSerial::println(const String &s) {
print(s);
println();
}
void MarlinSerial::println(const char c[]) {
print(c);
println();
}
void MarlinSerial::println(char c, int base) {
print(c, base);
println();
}
void MarlinSerial::println(unsigned char b, int base) {
print(b, base);
println();
}
void MarlinSerial::println(int n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(unsigned int n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(long n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(unsigned long n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(double n, int digits) {
print(n, digits);
println();
}
// Private Methods /////////////////////////////////////////////////////////////
void MarlinSerial::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 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 < digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 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 //////////////////////////////////////////////////////
MarlinSerial customizedSerial;
#endif // whole file
#endif // !USBCON
// For AT90USB targets use the UART for BT interfacing
#if defined(USBCON) && ENABLED(BLUETOOTH)
HardwareSerial bluetoothSerial;
#endif
/*
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 MARLINSERIAL_H
#define MARLINSERIAL_H
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// The presence of the UBRRH register is used to detect a UART.
#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
(port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
(port == 3 && defined(UBRR3H)))
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
// requires two levels of indirection to expand macro values properly)
#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
#else
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
#endif
// Registers used by MarlinSerial class (these are expanded
// depending on selected serial port
#define M_UCSRxA SERIAL_REGNAME(UCSR,SERIAL_PORT,A) // defines M_UCSRxA to be UCSRnA where n is the serial port number
#define M_UCSRxB SERIAL_REGNAME(UCSR,SERIAL_PORT,B)
#define M_RXENx SERIAL_REGNAME(RXEN,SERIAL_PORT,)
#define M_TXENx SERIAL_REGNAME(TXEN,SERIAL_PORT,)
#define M_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,)
#define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,)
#define M_UBRRxH SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
#define M_UBRRxL SERIAL_REGNAME(UBRR,SERIAL_PORT,L)
#define M_RXCx SERIAL_REGNAME(RXC,SERIAL_PORT,)
#define M_USARTx_RX_vect SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect)
#define M_U2Xx SERIAL_REGNAME(U2X,SERIAL_PORT,)
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0
#ifndef USBCON
// 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 UART_PRESENT(SERIAL_PORT)
extern ring_buffer rx_buffer;
#endif
class MarlinSerial { //: public Stream
public:
MarlinSerial();
void begin(long);
void end();
int peek(void);
int read(void);
void flush(void);
FORCE_INLINE int available(void) {
return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE;
}
FORCE_INLINE void write(uint8_t c) {
while (!TEST(M_UCSRxA, M_UDREx))
;
M_UDRx = c;
}
FORCE_INLINE void checkRx(void) {
if (TEST(M_UCSRxA, M_RXCx)) {
unsigned char c = M_UDRx;
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;
}
}
}
private:
void printNumber(unsigned long, uint8_t);
void printFloat(double, uint8_t);
public:
FORCE_INLINE void write(const char *str) { while (*str) write(*str++); }
FORCE_INLINE void write(const uint8_t *buffer, size_t size) { while (size--) write(*buffer++); }
FORCE_INLINE void print(const String &s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
FORCE_INLINE void print(const char *str) { write(str); }
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);
};
extern MarlinSerial customizedSerial;
#endif // !USBCON
// Use the UART for Bluetooth in AT90USB configurations
#if defined(USBCON) && ENABLED(BLUETOOTH)
extern HardwareSerial bluetoothSerial;
#endif
#endif
/* 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
* <http://www.gnu.org/licenses/>.
*/
/**
* \file
* \brief configuration definitions
*/
#ifndef SdFatConfig_h
#define SdFatConfig_h
#include <stdint.h>
//------------------------------------------------------------------------------
/**
* 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
/** Number of UTF-16 characters per entry */
#define FILENAME_LENGTH 13
/**
* Defines for long (vfat) filenames
*/
/** Number of VFAT entries used. Every entry has 13 UTF-16 characters */
#define MAX_VFAT_ENTRIES (2)
/** Total size of the buffer used to store the long filenames */
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH*MAX_VFAT_ENTRIES+1)
#endif // SdFatConfig_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
* <http://www.gnu.org/licenses/>.
*/
#include "SdFatUtil.h"
//------------------------------------------------------------------------------
/** Amount of free RAM
* \return The number of free bytes.
*/
#ifdef __arm__
extern "C" char* sbrk(int incr);
int SdFatUtil::FreeRam() {
char top;
return &top - reinterpret_cast<char*>(sbrk(0));
}
#else // __arm__
extern char *__brkval;
extern char __bss_end;
/** Amount of free RAM
* \return The number of free bytes.
*/
int SdFatUtil::FreeRam() {
char top;
return __brkval ? &top - __brkval : &top - &__bss_end;
}
#endif // __arm
//------------------------------------------------------------------------------
/** %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( PGM_P str) {
for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.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( PGM_P str) {
print_P( str);
MYSERIAL.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(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( str);
}
\ No newline at end of file
/* 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
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#ifndef SdFatUtil_h
#define SdFatUtil_h
/**
* \file
* \brief Useful utility functions.
*/
#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.*/
#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
......@@ -2,7 +2,7 @@
blinkm.cpp - Library for controlling a BlinkM over i2c
Created by Tim Koster, August 21 2013.
*/
#include "../base.h"
#include "../../base.h"
#if ENABLED(BLINKM)
......
/**
* This file is part of MarlinKimbra Firmware.
*
* MarlinKimbra Firmware 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.
*
* MarlinKimbra Firmware 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 MarlinKimbra Firmware. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../../base.h"
void Com::printF(FSTRINGPARAM(ptr)) {
char c;
while ((c = HAL::readFlashByte(ptr++)) != 0)
HAL::serialWriteByte(c);
}
void Com::printVal(int value) {
print(value);
}
void Com::printVal(int8_t value) {
print(value);
}
void Com::printVal(uint8_t value) {
print(value);
}
void Com::printVal(int32_t value) {
print(value);
}
void Com::printVal(uint32_t value) {
printNumber(value);
}
void Com::printVal(float value, uint8_t digits) {
printFloat(value, digits);
}
void Com::printVal(double value, uint8_t digits) {
printFloat(value, digits);
}
void Com::print(const char* text) {
while(*text) {
HAL::serialWriteByte(*text++);
}
}
void Com::print(char c) {
HAL::serialWriteByte(c);
}
void Com::print(float number) {
printFloat(number, 6);
}
void Com::print(int value) {
print((int32_t)value);
}
void Com::print(long value) {
if(value < 0) {
HAL::serialWriteByte('-');
value = -value;
}
printNumber(value);
}
void Com::print(uint16_t value) {
printNumber(value);
}
void Com::print(uint32_t value) {
printNumber(value);
}
void Com::printNumber(uint32_t n) {
char buf[11]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[10];
*str = '\0';
do {
unsigned long m = n;
n /= 10;
*--str = '0'+(m - 10 * n);
} while(n);
print(str);
}
void Com::printArray(float *arr, uint8_t n, uint8_t digits) {
for (uint8_t i = 0; i < n; i++) {
print(" ");
printFloat(arr[i], digits);
}
}
void Com::printArray(int32_t *arr, uint8_t n) {
for (uint8_t i = 0; i < n; i++) {
print(" ");
printVal(arr[i]);
}
}
void Com::printFloat(float number, uint8_t digits) {
if (isnan(number)) {
print(TNAN);
return;
}
if (isinf(number)) {
print(TINF);
return;
}
// Handle negative numbers
if (number < 0.0) {
print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
float rounding = 0.5;
for (uint8_t i = 0; i < digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
float remainder = number - (float)int_part;
printNumber(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 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;
}
}
#ifndef COMMUNICATION_H
#define COMMUNICATION_H
class Com {
public:
#define START "start" // start for host
#define OK "ok " // ok answer for host
#define ER "Error: " // error for host
#define WT "Wait" // wait for host
#define DB "Echo: " // message for user
#define CFG "Config: " // config for host
#define INFO "Info: " // info for host
#define RESEND "Resend: " // resend for host
#define WARNING "Warning: " // warning for host
#define TNAN "NAN" // NAN for host
#define TINF "INF" // INF for host
#define PAUSE "//action:pause" // command for host that support action
#define RESUME "//action:resume" // command for host that support action
#define DISCONNECT "//action:disconnect" // command for host that support action
static void printFloat(float number, uint8_t digits);
static void printVal(int value);
static void printVal(int8_t value);
static void printVal(uint8_t value);
static void printVal(int32_t value);
static void printVal(uint32_t value);
static void printVal(float value, uint8_t digits = 2);
static void printVal(double value, uint8_t digits = 2);
static void printArray(float *arr, uint8_t n = 4, uint8_t digits = 2);
static void printArray(long *arr, uint8_t n = 4);
static void printNumber(uint32_t n);
static void print(long value);
static void print(uint16_t value);
static void print(uint32_t value);
static void print(int value);
static void print(float number);
static void print(const char *text);
static void print(char c);
static void println() { HAL::serialWriteByte('\r'); HAL::serialWriteByte('\n'); }
static void printF(FSTRINGPARAM(ptr));
protected:
private:
};
#define SERIAL_WRITE(x) HAL::serialWriteByte(x)
#define ECHO_S(srt) Com::printF(PSTR(srt))
#define ECHO_M(msg) Com::printF(PSTR(msg))
#define ECHO_T(txt) Com::print(txt)
#define ECHO_V(val, args...) Com::printVal(val, ##args)
#define ECHO_C(x) Com::print(x)
#define ECHO_E Com::println()
#define ECHO_MV(msg, val, args...) ECHO_M(msg),ECHO_V(val, ##args)
#define ECHO_VM(val, msg, args...) ECHO_V(val, ##args),ECHO_M(msg)
#define ECHO_MT(msg, txt) ECHO_M(msg),ECHO_T(txt)
#define ECHO_TM(txt, msg) ECHO_T(txt),ECHO_M(msg)
#define ECHO_SM(srt, msg) ECHO_S(srt),ECHO_M(msg)
#define ECHO_ST(srt, txt) ECHO_S(srt),ECHO_T(txt)
#define ECHO_SV(srt, val, args...) ECHO_S(srt),ECHO_V(val, ##args)
#define ECHO_SMV(srt, msg, val, args...) ECHO_S(srt),ECHO_MV(msg, val, ##args)
#define ECHO_SMT(srt, msg, txt) ECHO_S(srt),ECHO_MT(msg, txt)
#define ECHO_EM(msg) ECHO_M(msg),ECHO_E
#define ECHO_ET(txt) ECHO_T(txt),ECHO_E
#define ECHO_EV(val, args...) ECHO_V(val, ##args),ECHO_E
#define ECHO_EMV(msg, val, args...) ECHO_MV(msg, val, ##args),ECHO_E
#define ECHO_EVM(val, msg, args...) ECHO_VM(val, msg, ##args),ECHO_E
#define ECHO_EMT(msg, txt) ECHO_MT(msg, txt),ECHO_E
#define ECHO_L(srt) ECHO_S(srt),ECHO_E
#define ECHO_LM(srt, msg) ECHO_S(srt),ECHO_M(msg),ECHO_E
#define ECHO_LT(srt, txt) ECHO_S(srt),ECHO_T(txt),ECHO_E
#define ECHO_LV(srt, val, args...) ECHO_S(srt),ECHO_V(val, ##args),ECHO_E
#define ECHO_LMV(srt, msg, val, args...) ECHO_S(srt),ECHO_MV(msg, val, ##args),ECHO_E
#define ECHO_LVM(srt, val, msg, args...) ECHO_S(srt),ECHO_VM(val, msg, ##args),ECHO_E
#define ECHO_LMT(srt, msg, txt) ECHO_S(srt),ECHO_MT(msg, txt),ECHO_E
#endif
/**
* Comunication.h - serial messages functions
* Part of MarlinKimbra
*
* Author: Simone Primarosa
*/
#ifndef COMUNICATION_H
#define COMUNICATION_H
#ifdef USBCON
#include "HardwareSerial.h"
#endif
#ifndef __SAM3X8E__
#include "MarlinSerial.h"
#endif
#include "WString.h"
#ifdef USBCON
#if ENABLED(BLUETOOTH)
#define MYSERIAL bluetoothSerial
#else
#define MYSERIAL Serial
#endif // BLUETOOTH
#else
#ifdef __SAM3X8E__
#if SERIAL_PORT == -1
#define MYSERIAL SerialUSB
#elif SERIAL_PORT == 0
#define MYSERIAL Serial
#elif SERIAL_PORT == 1
#define MYSERIAL Serial1
#elif SERIAL_PORT == 2
#define MYSERIAL Serial2
#elif SERIAL_PORT == 3
#define MYSERIAL Serial3
#endif
#else
#define MYSERIAL customizedSerial
#endif
#endif
#define START "start" // start for host
#define OK "ok " // ok answer for host
#define ER "error: " // error for host
#define WT "wait" // wait for host
#define DB "echo: " // message for user
#define RS "resend: " // resend for host
#define PAUSE "//action:pause" // command for host that support action
#define RESUME "//action:resume" // command for host that support action
#define DISCONNECT "//action:disconnect" // command for host that support action
#define SERIAL_INIT(baud) MYSERIAL.begin(baud), delay(1)
#define SERIAL_WRITE(x) MYSERIAL.write(x)
#define SERIAL_PRINT(msg, args...) MYSERIAL.print(msg, ##args)
#define SERIAL_ENDL MYSERIAL.println()
FORCE_INLINE void PS_PGM(const char *str) {
char ch;
while ((ch = pgm_read_byte(str))) {
SERIAL_WRITE(ch);
str++;
}
}
#define ECHO_ENDL SERIAL_ENDL
#define ECHO_PGM(message) PS_PGM(PSTR(message))
#define ECHO_MV(msg, val, args...) ECHO_PGM(msg),ECHO_V(val, ##args)
#define ECHO_VM(val, msg, args...) ECHO_V(val, ##args),ECHO_PGM(msg)
#define ECHO_M(msg) ECHO_PGM(msg)
#define ECHO_V SERIAL_PRINT
#define ECHO_C SERIAL_WRITE
#define ECHO_S(srt) ECHO_PGM(srt)
#define ECHO_SM(srt, msg) ECHO_S(srt),ECHO_M(msg)
#define ECHO_SV(srt, val, args...) ECHO_S(srt),ECHO_V(val, ##args)
#define ECHO_SMV(srt, msg, val, args...) ECHO_S(srt),ECHO_MV(msg, val, ##args)
#define ECHO_SVM(srt, val, msg, args...) ECHO_S(srt),ECHO_VM(val, msg, ##args)
#define ECHO_E ECHO_ENDL
#define ECHO_EM(msg) ECHO_M(msg),ECHO_E
#define ECHO_EV(val, args...) ECHO_V(val, ##args),ECHO_E
#define ECHO_EMV(msg, val, args...) ECHO_MV(msg, val, ##args),ECHO_E
#define ECHO_EVM(val, msg, args...) ECHO_VM(val, msg, ##args),ECHO_E
#define ECHO_L(srt) ECHO_S(srt),ECHO_E
#define ECHO_LM(srt, msg) ECHO_S(srt),ECHO_M(msg),ECHO_E
#define ECHO_LV(srt, val) ECHO_S(srt),ECHO_V(val),ECHO_E
#define ECHO_LMV(srt, msg, val, args...) ECHO_S(srt),ECHO_MV(msg, val, ##args),ECHO_E
#define ECHO_LVM(srt, val, msg, args...) ECHO_S(srt),ECHO_VM(val, msg, ##args),ECHO_E
#endif
......@@ -435,6 +435,7 @@
*
*/
#if ENABLED(SD_DISABLED_DETECT)
#undef SD_DETECT_PIN
#define SD_DETECT_PIN -1
#endif
#if ENABLED(ULTIPANEL) && DISABLED(ELB_FULL_GRAPHIC_CONTROLLER)
......@@ -643,6 +644,7 @@
#define HAS_BTN_BACK (PIN_EXISTS(BTN_BACK))
#define HAS_POWER_SWITCH (POWER_SUPPLY > 0 && PIN_EXISTS(PS_ON))
#define HAS_MOTOR_CURRENT_PWM_XY (PIN_EXISTS(MOTOR_CURRENT_PWM_XY))
#define HAS_SDSUPPORT (ENABLED(SDSUPPORT))
#define HAS_DIGIPOTSS (PIN_EXISTS(DIGIPOTSS))
......
#include "../base.h"
#include "../../base.h"
#if ENABLED(DIGIPOT_I2C)
......
......@@ -6,7 +6,6 @@
#ifndef _FASTIO_ARDUINO_H
#define _FASTIO_ARDUINO_H
#include <avr/io.h>
/*
utility functions
......
......@@ -3,20 +3,11 @@
* By MagoKimbra
*/
#include "../base.h"
#include "../Marlin_main.h"
#include "../../base.h"
#if ENABLED(FIRMWARE_TEST)
#include "firmware_test.h"
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "temperature.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
static char serial_answer;
......
......@@ -31,7 +31,7 @@
#define STRINGIFY_(n) #n
#define STRINGIFY(n) STRINGIFY_(n)
#define PROTOCOL_VERSION "1.0"
#define PROTOCOL_VERSION "2.0"
#if MB(ULTIMAKER)|| MB(ULTIMAKER_OLD)|| MB(ULTIMAIN_2)
#define MACHINE_NAME "Ultimaker"
......
......@@ -206,6 +206,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -206,6 +206,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -152,7 +152,7 @@
#define MSG_HEATING_FAILED_LCD "Heating failed"
#define MSG_ERR_REDUNDANT_TEMP "REDUNDANT TEMP ERROR"
#define MSG_THERMAL_RUNAWAY "THERMAL RUNAWAY"
#define MSG_HOTEND_AD595 "HOTEND AD595 Offset & Gain"
#define MSG_AD595 "AD595 Offset & Gain"
#define MSG_ERR_MAXTEMP "MAXTEMP ERROR"
#define MSG_ERR_MINTEMP "MINTEMP ERROR"
#define MSG_ERR_MAXTEMP_BED "MAXTEMP BED ERROR"
......@@ -205,6 +205,21 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_TYPE "Type: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMP_HOTEND "Temperature Hotend: "
#define MSG_RFID_TEMP_BED "Temperature Bed: "
#define MSG_RFID_TEMP_USER_HOTEND "User temperature Hotend: "
#define MSG_RFID_TEMP_USER_BED "User temperatura Bed: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -152,7 +152,7 @@
#define MSG_HEATING_FAILED_LCD "Riscaldamento fallito"
#define MSG_ERR_REDUNDANT_TEMP "REDUNDANT TEMP ERROR"
#define MSG_THERMAL_RUNAWAY "THERMAL RUNAWAY"
#define MSG_HOTEND_AD595 "HOTEND AD595 Offset & Gain"
#define MSG_AD595 "AD595 Offset & Gain"
#define MSG_ERR_MAXTEMP "MAXTEMP ERROR"
#define MSG_ERR_MINTEMP "MINTEMP ERROR"
#define MSG_ERR_MAXTEMP_BED "MAXTEMP BED ERROR"
......@@ -205,6 +205,21 @@
#define MSG_RESTORING_POS "Ripristino posizione"
#define MSG_INVALID_POS_SLOT "Slot invalido, slot totali: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Bobina su E"
#define MSG_RFID_BRAND "Marca: "
#define MSG_RFID_TYPE "Tipo: "
#define MSG_RFID_COLOR "Colore: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMP_HOTEND "Temperatura Hotend: "
#define MSG_RFID_TEMP_BED "Temperatura Bed: "
#define MSG_RFID_TEMP_USER_HOTEND "Temperatura utente Hotend: "
#define MSG_RFID_TEMP_USER_BED "Temperatura utente Bed: "
#define MSG_RFID_DENSITY "Densita': "
#define MSG_RFID_SPOOL_LENGHT "Lunghezza bobina: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Dai il comando Y per andare avanti"
......
......@@ -207,6 +207,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -210,6 +210,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
......@@ -205,6 +205,17 @@
#define MSG_RESTORING_POS "Restoring position"
#define MSG_INVALID_POS_SLOT "Invalid slot, total slots: "
// Rfid module
#if ENABLED(RFID_MODULE)
#define MSG_RFID_SPOOL "Spool on E"
#define MSG_RFID_BRAND "Brand: "
#define MSG_RFID_COLOR "Color: "
#define MSG_RFID_SIZE "Size: "
#define MSG_RFID_TEMPERATURE "Temperature: "
#define MSG_RFID_DENSITY "Density: "
#define MSG_RFID_SPOOL_LENGHT "Spool Lenght: "
#endif
// Firmware Test
#if ENABLED(FIRMWARE_TEST)
#define MSG_FWTEST_YES "Put the Y command to go next"
......
#include "../base.h"
#include "../../base.h"
#if HAS(BUZZER)
#include "buzzer.h"
#include "ultralcd.h"
void buzz(long duration, uint16_t freq) {
if (freq > 0) {
......
#include "../base.h"
#include "../Marlin_main.h"
#include "../Configuration_Store.h"
#include "../../base.h"
#if ENABLED(ULTRA_LCD)
#include "cardreader.h"
#include "temperature.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "ultralcd.h"
#if HAS(BUZZER)
#include "buzzer.h"
#endif
int8_t encoderDiff; // updated from interrupt context and added to encoderPosition every LCD update
bool encoderRateMultiplierEnabled;
......
#ifndef ULTRALCD_H
#define ULTRALCD_H
#include "../Marlin_main.h"
#if ENABLED(ULTRA_LCD)
#if HAS(BUZZER)
#include "buzzer.h"
......
#ifndef MACROS_H
#define MACROS_H
// Compiler warning on unused varable.
#define UNUSED(x) (void) (x)
// Macros for bit masks
#define BIT(b) (1<<(b))
#define TEST(n,b) (((n)&BIT(b))!=0)
#define SET_BIT(n,b,value) (n) ^= ((-value)^(n)) & (BIT(b))
// Macros for maths shortcuts
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define RADIANS(d) ((d)*M_PI/180.0)
#define DEGREES(r) ((r)*180.0/M_PI)
#define SIN_60 0.8660254037844386
#define COS_60 0.5
// Macros to support option testing
#define ENABLED defined
#define DISABLED !defined
#define PIN_EXISTS(PN) (defined(PN##_PIN) && PN##_PIN >= 0)
#define HAS(FE) (HAS_##FE)
#define HASNT(FE) (!(HAS_##FE))
// Macros to contrain values
#define NOLESS(v,n) do{ if (v < n) v = n; }while(0)
#define NOMORE(v,n) do{ if (v > n) v = n; }while(0)
#define COUNT(a) (sizeof(a)/sizeof(*a))
// Function macro
#define FORCE_INLINE __attribute__((always_inline)) inline
#if DISABLED(CRITICAL_SECTION_START)
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
#define CRITICAL_SECTION_END SREG = _sreg;
#endif
#endif //__MACROS_H
......@@ -48,14 +48,8 @@
*
*/
#include "../base.h"
#include "../Marlin_main.h"
#include "../../base.h"
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
//===========================================================================
//============================= public variables ============================
......@@ -121,7 +115,7 @@ uint8_t g_uc_extruder_last_move[EXTRUDERS] = { 0 };
#endif
#if ENABLED(FILAMENT_SENSOR)
static char meas_sample; //temporary variable to hold filament measurement sample
static char meas_sample; // temporary variable to hold filament measurement sample
#endif
#if ENABLED(DUAL_X_CARRIAGE)
......
#include "qr_solve.h"
#include "../../base.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE) && ENABLED(AUTO_BED_LEVELING_GRID)
#include "qr_solve.h"
#include <stdlib.h>
#include <math.h>
......
#include "../base.h"
#if ENABLED(AUTO_BED_LEVELING_GRID)
void daxpy(int n, double da, double dx[], int incx, double dy[], int incy);
......
......@@ -22,26 +22,10 @@
/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith
and Philipp Tiefenbacher. */
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
#include "planner.h"
#include "stepper_indirection.h"
#if MB(ALLIGATOR)
#include "external_dac.h"
#endif
#include "../../base.h"
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
#include "nextion_lcd.h"
#if ENABLED(SDSUPPORT)
#include "cardreader.h"
#endif
#include "speed_lookuptable.h"
#if HAS(DIGIPOTSS)
#include <SPI.h>
#endif
......@@ -553,7 +537,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(SERIAL_STEPPER_TOO_HIGH); MYSERIAL.println(step_rate); }//(20kHz this should never happen)
if (timer < 100) { timer = 100; ECHO_M(SERIAL_STEPPER_TOO_HIGH); ECHO_T(step_rate); }//(20kHz this should never happen)
return timer;
}
......@@ -702,7 +686,7 @@ ISR(TIMER1_COMPA_vect) {
// Take multiple steps per interrupt (For high speed moves)
for (int8_t i = 0; i < step_loops; i++) {
#ifndef USBCON
customizedSerial.checkRx(); // Check for serial chars.
HAL::serialByteAvailable(); // Check for serial chars.
#endif
#if ENABLED(ADVANCE)
......
......@@ -19,7 +19,7 @@
along with Marlin. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#include "../../base.h"
#include "stepper_indirection.h"
#if ENABLED(HAVE_TMCDRIVER)
......
......@@ -16,8 +16,9 @@
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 "../../base.h"
#include <math.h>
#include "../base.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
......@@ -60,7 +61,7 @@ void vector_3::apply_rotation(matrix_3x3 matrix) {
}
void vector_3::debug(const char title[]) {
ECHO_SV(DB, title);
ECHO_ST(DB, title);
ECHO_MV(" x: ", x, 6);
ECHO_MV(" y: ", y, 6);
ECHO_EMV(" z: ", z, 6);
......@@ -117,7 +118,7 @@ matrix_3x3 matrix_3x3::transpose(matrix_3x3 original) {
}
void matrix_3x3::debug(const char title[]) {
ECHO_LV(DB, title);
ECHO_LT(DB, title);
int count = 0;
for (int i = 0; i < 3; i++) {
ECHO_S(DB);
......
......@@ -16,6 +16,7 @@
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 VECTOR_3_H
#define VECTOR_3_H
......
......@@ -15,11 +15,10 @@
*
*/
#include "../base.h"
#include "../Marlin_main.h"
#include "../../base.h"
#if ENABLED(NEXTION_GFX)
#include "stepper.h"
#include "nextion_gfx.h"
const int INSIDE = 0; // 0000
......
#include "../base.h"
#include "../Marlin_main.h"
#include "../Configuration_Store.h"
#include "../../base.h"
#if ENABLED(NEXTION)
#include "cardreader.h"
#include "temperature.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "nextion_lcd.h"
#include "nextion_gfx.h"
#include <Nextion.h>
......@@ -265,7 +254,7 @@
card.getfilename(i);
printrowsd(row, card.filenameIsDir, card.filename, card.longFilename);
} else {
printrowsd(row, false, "", "");
printrowsd(row, false, "", (char*)"");
}
}
sendCommand("ref 0");
......@@ -476,12 +465,16 @@
#endif
void lcd_init() {
delay(1000);
NextionON = nexInit();
for (uint8_t i = 0; i < 10; i++) {
NextionON = nexInit();
if (NextionON) break;
delay(1000);
}
if (!NextionON) {
ECHO_LM(DB, "Nextion LCD not connected!");
} else {
}
else {
ECHO_LM(DB, "Nextion LCD connected!");
Pstart.attachPop(ExitPopCallback);
......
......@@ -17,137 +17,136 @@
* along with the Arduino Sd2Card Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#include "Sd2Card.h"
//------------------------------------------------------------------------------
#if DISABLED(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 = BIT(SPE) | BIT(MSTR) | (spiRate >> 1);
SPSR = spiRate & 1 || spiRate == 6 ? 0 : BIT(SPI2X);
}
//------------------------------------------------------------------------------
/** SPI receive a byte */
static uint8_t spiRec() {
SPDR = 0XFF;
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
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++) {
// 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 = BIT(SPE) | BIT(MSTR) | (spiRate >> 1);
SPSR = spiRate & 1 || spiRate == 6 ? 0 : BIT(SPI2X);
}
//------------------------------------------------------------------------------
/** SPI receive a byte */
static uint8_t spiRec() {
SPDR = 0XFF;
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
buf[i] = SPDR;
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 (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
buf[i] = SPDR;
SPDR = 0XFF;
}
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
buf[nbyte] = SPDR;
}
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
buf[nbyte] = SPDR;
}
//------------------------------------------------------------------------------
/** SPI send a byte */
static void spiSend(uint8_t b) {
SPDR = b;
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
}
//------------------------------------------------------------------------------
/** 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) {
//------------------------------------------------------------------------------
/** SPI send a byte */
static void spiSend(uint8_t b) {
SPDR = b;
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
SPDR = buf[i];
}
//------------------------------------------------------------------------------
/** 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 (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
SPDR = buf[i];
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
SPDR = buf[i + 1];
}
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
SPDR = buf[i + 1];
}
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#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);
//------------------------------------------------------------------------------
/** 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;
}
// 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 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);
//------------------------------------------------------------------------------
/** 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);
fastDigitalWrite(SPI_MOSI_PIN, data & 0X80);
data <<= 1;
data <<= 1;
fastDigitalWrite(SPI_SCK_PIN, HIGH);
}
// hold SCK high for a few ns
nop;
nop;
nop;
nop;
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 */
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]);
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
......@@ -194,11 +193,13 @@ uint32_t Sd2Card::cardSize() {
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) {
}
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 {
}
else {
error(SD_CARD_ERROR_BAD_CSD);
return 0;
}
......@@ -209,9 +210,9 @@ void Sd2Card::chipSelectHigh() {
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow() {
#if DISABLED(SOFTWARE_SPI)
spiInit(spiRate_);
#endif // SOFTWARE_SPI
#if DISABLED(SOFTWARE_SPI)
spiInit(spiRate_);
#endif // SOFTWARE_SPI
digitalWrite(chipSelectPin_, LOW);
}
//------------------------------------------------------------------------------
......@@ -246,10 +247,10 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
lastBlock <<= 9;
}
if (cardCommand(CMD32, firstBlock)
|| cardCommand(CMD33, lastBlock)
|| cardCommand(CMD38, 0)) {
error(SD_CARD_ERROR_ERASE);
goto fail;
|| cardCommand(CMD33, lastBlock)
|| cardCommand(CMD38, 0)) {
error(SD_CARD_ERROR_ERASE);
goto fail;
}
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
error(SD_CARD_ERROR_ERASE_TIMEOUT);
......@@ -257,8 +258,7 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
}
chipSelectHigh();
return true;
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -297,17 +297,17 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
pinMode(SPI_MOSI_PIN, OUTPUT);
pinMode(SPI_SCK_PIN, OUTPUT);
#if DISABLED(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
#if DISABLED(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);
......@@ -322,7 +322,8 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
// check SD version
if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
type(SD_CARD_TYPE_SD1);
} else {
}
else {
// only need last byte of r7 response
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
if (status_ != 0XAA) {
......@@ -353,13 +354,13 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
}
chipSelectHigh();
#if DISABLED(SOFTWARE_SPI)
return setSckRate(sckRateID);
#else // SOFTWARE_SPI
return true;
#endif // SOFTWARE_SPI
#if DISABLED(SOFTWARE_SPI)
return setSckRate(sckRateID);
#else // SOFTWARE_SPI
return true;
#endif // SOFTWARE_SPI
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -376,28 +377,27 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
#if ENABLED(SD_CHECK_AND_RETRY)
uint8_t retryCnt = 3;
// use address if not SDHC card
if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
retry2:
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
retry2:
retryCnt --;
if (cardCommand(CMD17, blockNumber)) {
error(SD_CARD_ERROR_CMD17);
if (retryCnt > 0) goto retry;
goto fail;
}
if (!readData(dst, 512))
{
if (!readData(dst, 512)) {
if (retryCnt > 0) goto retry;
goto fail;
}
return true;
retry:
chipSelectHigh();
cardCommand(CMD12, 0);//Try sending a stop command, but ignore the result.
errorCode_ = 0;
goto retry2;
retry:
chipSelectHigh();
cardCommand(CMD12, 0);//Try sending a stop command, but ignore the result.
errorCode_ = 0;
goto retry2;
#else
// use address if not SDHC card
if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD17, blockNumber)) {
error(SD_CARD_ERROR_CMD17);
goto fail;
......@@ -405,7 +405,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
return readData(dst, 512);
#endif
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -417,7 +417,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
* \return The value one, true, is returned for success and
* the value zero, false, is returned for failure.
*/
bool Sd2Card::readData(uint8_t *dst) {
bool Sd2Card::readData(uint8_t* dst) {
chipSelectLow();
return readData(dst, 512);
}
......@@ -488,10 +488,9 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
uint16_t calcCrc = CRC_CCITT(dst, count);
uint16_t recvCrc = spiRec() << 8;
recvCrc |= spiRec();
if (calcCrc != recvCrc)
{
error(SD_CARD_ERROR_CRC);
goto fail;
if (calcCrc != recvCrc) {
error(SD_CARD_ERROR_CRC);
goto fail;
}
}
#else
......@@ -501,8 +500,7 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
#endif
chipSelectHigh();
return true;
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -515,8 +513,7 @@ bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
goto fail;
}
return readData(dst, 16);
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -532,15 +529,14 @@ bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
* the value zero, false, is returned for failure.
*/
bool Sd2Card::readStart(uint32_t blockNumber) {
if (type()!= SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD18, blockNumber)) {
error(SD_CARD_ERROR_CMD18);
goto fail;
}
chipSelectHigh();
return true;
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -558,8 +554,7 @@ bool Sd2Card::readStop() {
}
chipSelectHigh();
return true;
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -592,8 +587,7 @@ bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -626,8 +620,7 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
}
chipSelectHigh();
return true;
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -644,8 +637,7 @@ bool Sd2Card::writeData(const uint8_t* src) {
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto fail;
chipSelectHigh();
return true;
fail:
fail:
error(SD_CARD_ERROR_WRITE_MULTIPLE);
chipSelectHigh();
return false;
......@@ -664,8 +656,7 @@ bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
goto fail;
}
return true;
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -695,8 +686,7 @@ bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
}
chipSelectHigh();
return true;
fail:
fail:
chipSelectHigh();
return false;
}
......@@ -713,8 +703,7 @@ bool Sd2Card::writeStop() {
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto fail;
chipSelectHigh();
return true;
fail:
fail:
error(SD_CARD_ERROR_STOP_TRAN);
chipSelectHigh();
return false;
......
......@@ -18,13 +18,12 @@
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#ifndef Sd2Card_h
#define Sd2Card_h
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#ifndef Sd2Card_h
#define Sd2Card_h
/**
* \file
* \brief Sd2Card class for V2 SD/SDHC cards
......@@ -32,7 +31,6 @@
#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(). */
......@@ -121,35 +119,35 @@ uint8_t const SD_CARD_TYPE_SDHC = 3;
*/
//------------------------------------------------------------------------------
#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__))
#define SOFTWARE_SPI
#define SOFTWARE_SPI
#elif USE_SOFTWARE_SPI
#define SOFTWARE_SPI
#define SOFTWARE_SPI
#endif // MEGA_SOFT_SPI
//------------------------------------------------------------------------------
// SPI pin definitions - do not edit here - change in SdFatConfig.h
//
#if DISABLED(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;
// 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;
/** 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
//------------------------------------------------------------------------------
/**
......@@ -181,12 +179,12 @@ class Sd2Card {
* \return true for success or false for failure.
*/
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
bool readBlock(uint32_t block, uint8_t* dst);
/**
* Read a card's CID register. The CID contains card identification
* information such as Manufacturer ID, Product name, Product serial
* number and Manufacturing date.
* number and Manufacturing date.
*
* \param[out] cid pointer to area for returned data.
*
......@@ -206,7 +204,7 @@ class Sd2Card {
bool readCSD(csd_t* csd) {
return readRegister(CMD9, csd);
}
bool readData(uint8_t *dst);
bool readData(uint8_t* dst);
bool readStart(uint32_t blockNumber);
bool readStop();
bool setSckRate(uint8_t sckRateID);
......
......@@ -19,6 +19,10 @@
*/
// Warning this file was generated by a program.
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#ifndef Sd2PinMap_h
#define Sd2PinMap_h
#include <avr/io.h>
......@@ -313,12 +317,12 @@ static const pin_map_t digitalPinMap[] = {
};
#elif defined(__AVR_ATmega1281__)
// Waspmote
// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 41;
uint8_t const SCL_PIN = 40;
#undef MOSI_PIN
#undef MISO_PIN
// SPI port
......@@ -326,59 +330,59 @@ uint8_t const SS_PIN = 16; // B0
uint8_t const MOSI_PIN = 11; // B2
uint8_t const MISO_PIN = 12; // B3
uint8_t const SCK_PIN = 10; // B1
static const pin_map_t digitalPinMap[] = {
{&DDRE, &PINE, &PORTE, 0}, // E0 0
{&DDRE, &PINE, &PORTE, 1}, // E1 1
{&DDRE, &PINE, &PORTE, 3}, // E3 2
{&DDRE, &PINE, &PORTE, 4}, // E4 3
{&DDRC, &PINC, &PORTC, 4}, // C4 4
{&DDRC, &PINC, &PORTC, 5}, // C5 5
{&DDRC, &PINC, &PORTC, 6}, // C6 6
{&DDRC, &PINC, &PORTC, 7}, // C7 7
{&DDRA, &PINA, &PORTA, 2}, // A2 8
{&DDRA, &PINA, &PORTA, 3}, // A3 9
{&DDRA, &PINA, &PORTA, 4}, // A4 10
{&DDRD, &PIND, &PORTD, 5}, // D5 11
{&DDRD, &PIND, &PORTD, 6}, // D6 12
{&DDRC, &PINC, &PORTC, 1}, // C1 13
{&DDRF, &PINF, &PORTF, 1}, // F1 14
{&DDRF, &PINF, &PORTF, 2}, // F2 15
{&DDRF, &PINF, &PORTF, 3}, // F3 16
{&DDRF, &PINF, &PORTF, 4}, // F4 17
{&DDRF, &PINF, &PORTF, 5}, // F5 18
{&DDRF, &PINF, &PORTF, 6}, // F6 19
{&DDRF, &PINF, &PORTF, 7}, // F7 20
{&DDRF, &PINF, &PORTF, 0}, // F0 21
{&DDRA, &PINA, &PORTA, 1}, // A1 22
{&DDRD, &PIND, &PORTD, 7}, // D7 23
{&DDRE, &PINE, &PORTE, 5}, // E5 24
{&DDRA, &PINA, &PORTA, 6}, // A6 25
{&DDRE, &PINE, &PORTE, 2}, // E2 26
{&DDRA, &PINA, &PORTA, 5}, // A5 27
{&DDRC, &PINC, &PORTC, 0}, // C0 28
{&DDRB, &PINB, &PORTB, 0}, // B0 29
{&DDRB, &PINB, &PORTB, 1}, // B1 30
{&DDRB, &PINB, &PORTB, 2}, // B2 31
{&DDRB, &PINB, &PORTB, 3}, // B3 32
{&DDRB, &PINB, &PORTB, 4}, // B4 33
{&DDRB, &PINB, &PORTB, 5}, // B5 34
{&DDRA, &PINA, &PORTA, 0}, // A0 35
{&DDRB, &PINB, &PORTB, 6}, // B6 36
{&DDRB, &PINB, &PORTB, 7}, // B7 37
{&DDRE, &PINE, &PORTE, 6}, // E6 38
{&DDRE, &PINE, &PORTE, 7}, // E7 39
{&DDRD, &PIND, &PORTD, 0}, // D0 40
{&DDRD, &PIND, &PORTD, 1}, // D1 41
{&DDRC, &PINC, &PORTC, 3}, // C3 42
{&DDRD, &PIND, &PORTD, 2}, // D2 43
{&DDRD, &PIND, &PORTD, 3}, // D3 44
{&DDRA, &PINA, &PORTA, 7}, // A7 45
{&DDRC, &PINC, &PORTC, 2}, // C2 46
{&DDRD, &PIND, &PORTD, 4}, // D4 47
{&DDRG, &PING, &PORTG, 2}, // G2 48
{&DDRG, &PING, &PORTG, 1}, // G1 49
{&DDRG, &PING, &PORTG, 0}, // G0 50
{&DDRE, &PINE, &PORTE, 0}, // E0 0
{&DDRE, &PINE, &PORTE, 1}, // E1 1
{&DDRE, &PINE, &PORTE, 3}, // E3 2
{&DDRE, &PINE, &PORTE, 4}, // E4 3
{&DDRC, &PINC, &PORTC, 4}, // C4 4
{&DDRC, &PINC, &PORTC, 5}, // C5 5
{&DDRC, &PINC, &PORTC, 6}, // C6 6
{&DDRC, &PINC, &PORTC, 7}, // C7 7
{&DDRA, &PINA, &PORTA, 2}, // A2 8
{&DDRA, &PINA, &PORTA, 3}, // A3 9
{&DDRA, &PINA, &PORTA, 4}, // A4 10
{&DDRD, &PIND, &PORTD, 5}, // D5 11
{&DDRD, &PIND, &PORTD, 6}, // D6 12
{&DDRC, &PINC, &PORTC, 1}, // C1 13
{&DDRF, &PINF, &PORTF, 1}, // F1 14
{&DDRF, &PINF, &PORTF, 2}, // F2 15
{&DDRF, &PINF, &PORTF, 3}, // F3 16
{&DDRF, &PINF, &PORTF, 4}, // F4 17
{&DDRF, &PINF, &PORTF, 5}, // F5 18
{&DDRF, &PINF, &PORTF, 6}, // F6 19
{&DDRF, &PINF, &PORTF, 7}, // F7 20
{&DDRF, &PINF, &PORTF, 0}, // F0 21
{&DDRA, &PINA, &PORTA, 1}, // A1 22
{&DDRD, &PIND, &PORTD, 7}, // D7 23
{&DDRE, &PINE, &PORTE, 5}, // E5 24
{&DDRA, &PINA, &PORTA, 6}, // A6 25
{&DDRE, &PINE, &PORTE, 2}, // E2 26
{&DDRA, &PINA, &PORTA, 5}, // A5 27
{&DDRC, &PINC, &PORTC, 0}, // C0 28
{&DDRB, &PINB, &PORTB, 0}, // B0 29
{&DDRB, &PINB, &PORTB, 1}, // B1 30
{&DDRB, &PINB, &PORTB, 2}, // B2 31
{&DDRB, &PINB, &PORTB, 3}, // B3 32
{&DDRB, &PINB, &PORTB, 4}, // B4 33
{&DDRB, &PINB, &PORTB, 5}, // B5 34
{&DDRA, &PINA, &PORTA, 0}, // A0 35
{&DDRB, &PINB, &PORTB, 6}, // B6 36
{&DDRB, &PINB, &PORTB, 7}, // B7 37
{&DDRE, &PINE, &PORTE, 6}, // E6 38
{&DDRE, &PINE, &PORTE, 7}, // E7 39
{&DDRD, &PIND, &PORTD, 0}, // D0 40
{&DDRD, &PIND, &PORTD, 1}, // D1 41
{&DDRC, &PINC, &PORTC, 3}, // C3 42
{&DDRD, &PIND, &PORTD, 2}, // D2 43
{&DDRD, &PIND, &PORTD, 3}, // D3 44
{&DDRA, &PINA, &PORTA, 7}, // A7 45
{&DDRC, &PINC, &PORTC, 2}, // C2 46
{&DDRD, &PIND, &PORTD, 4}, // D4 47
{&DDRG, &PING, &PORTG, 2}, // G2 48
{&DDRG, &PING, &PORTG, 1}, // G1 49
{&DDRG, &PING, &PORTG, 0}, // G0 50
};
#else // defined(__AVR_ATmega1280__)
#error unknown chip
......@@ -393,7 +397,8 @@ static inline __attribute__((always_inline))
bool getPinMode(uint8_t pin) {
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
} else {
}
else {
return badPinNumber();
}
}
......@@ -402,10 +407,12 @@ static inline __attribute__((always_inline))
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
if (mode) {
*digitalPinMap[pin].ddr |= BIT(digitalPinMap[pin].bit);
} else {
}
else {
*digitalPinMap[pin].ddr &= ~BIT(digitalPinMap[pin].bit);
}
} else {
}
else {
badPinNumber();
}
}
......@@ -413,7 +420,8 @@ static inline __attribute__((always_inline))
bool fastDigitalRead(uint8_t pin) {
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;
} else {
}
else {
return badPinNumber();
}
}
......@@ -422,12 +430,16 @@ static inline __attribute__((always_inline))
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
if (value) {
*digitalPinMap[pin].port |= BIT(digitalPinMap[pin].bit);
} else {
}
else {
*digitalPinMap[pin].port &= ~BIT(digitalPinMap[pin].bit);
}
} else {
}
else {
badPinNumber();
}
}
#endif // Sd2PinMap_h
#endif
......@@ -18,12 +18,10 @@
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#include "../Marlin_main.h"
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#include <stdint.h>
#include "SdBaseFile.h"
//------------------------------------------------------------------------------
// pointer to cwd directory
......@@ -51,7 +49,7 @@ bool SdBaseFile::addCluster() {
bool SdBaseFile::addDirCluster() {
uint32_t block;
// max folder size
if (fileSize_/sizeof(dir_t) >= 0XFFFF) goto fail;
if (fileSize_ / sizeof(dir_t) >= 0XFFFF) goto fail;
if (!addCluster()) goto fail;
if (!vol_->cacheFlush()) goto fail;
......@@ -71,8 +69,7 @@ bool SdBaseFile::addDirCluster() {
// Increase directory file size by cluster size
fileSize_ += 512UL << vol_->clusterSizeShift_;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -81,8 +78,7 @@ bool SdBaseFile::addDirCluster() {
dir_t* SdBaseFile::cacheDirEntry(uint8_t action) {
if (!vol_->cacheRawBlock(dirBlock_, action)) goto fail;
return vol_->cache()->dir + dirIndex_;
fail:
fail:
return 0;
}
//------------------------------------------------------------------------------
......@@ -128,7 +124,7 @@ bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
}
}
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -150,7 +146,7 @@ bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
*
*/
bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
const char* path, uint32_t size) {
const char* path, uint32_t size) {
uint32_t count;
// don't allow zero length file
if (size == 0) goto fail;
......@@ -170,8 +166,7 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
flags_ |= F_FILE_DIR_DIRTY;
return sync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -194,8 +189,7 @@ bool SdBaseFile::dirEntry(dir_t* dir) {
// copy to caller's struct
memcpy(dir, p, sizeof(dir_t));
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -261,7 +255,8 @@ int16_t SdBaseFile::fgets(char* str, int16_t num, char* delim) {
str[n++] = ch;
if (!delim) {
if (ch == '\n') break;
} else {
}
else {
if (strchr(delim, ch)) break;
}
}
......@@ -321,11 +316,11 @@ void SdBaseFile::getpos(FatPos_t* pos) {
void SdBaseFile::ls(uint8_t flags, uint8_t indent) {
rewind();
int8_t status;
while ((status = lsPrintNext( flags, indent))) {
while ((status = lsPrintNext(flags, indent))) {
if (status > 1 && (flags & LS_R)) {
uint16_t index = curPosition()/32 - 1;
uint16_t index = curPosition() / 32 - 1;
SdBaseFile s;
if (s.open(this, index, O_READ)) s.ls( flags, indent + 2);
if (s.open(this, index, O_READ)) s.ls(flags, indent + 2);
seekSet(32 * (index + 1));
}
}
......@@ -333,7 +328,7 @@ void SdBaseFile::ls(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( uint8_t flags, uint8_t indent) {
int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
dir_t dir;
uint8_t w = 0;
......@@ -343,41 +338,41 @@ int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) {
// skip deleted entry and entries for . and ..
if (dir.name[0] != DIR_NAME_DELETED && dir.name[0] != '.'
&& DIR_IS_FILE_OR_SUBDIR(&dir)) break;
&& DIR_IS_FILE_OR_SUBDIR(&dir)) break;
}
// indent for dir level
for (uint8_t i = 0; i < indent; i++) MYSERIAL.write(' ');
for (uint8_t i = 0; i < indent; i++) ECHO_C(' ');
// print name
for (uint8_t i = 0; i < 11; i++) {
if (dir.name[i] == ' ')continue;
if (i == 8) {
MYSERIAL.write('.');
ECHO_C('.');
w++;
}
MYSERIAL.write(dir.name[i]);
ECHO_T(dir.name[i]);
w++;
}
if (DIR_IS_SUBDIR(&dir)) {
MYSERIAL.write('/');
ECHO_C('/');
w++;
}
if (flags & (LS_DATE | LS_SIZE)) {
while (w++ < 14) MYSERIAL.write(' ');
while (w++ < 14) ECHO_C(' ');
}
// print modify date/time if requested
if (flags & LS_DATE) {
MYSERIAL.write(' ');
printFatDate( dir.lastWriteDate);
MYSERIAL.write(' ');
printFatTime( dir.lastWriteTime);
ECHO_C(' ');
printFatDate(dir.lastWriteDate);
ECHO_C(' ');
printFatTime(dir.lastWriteTime);
}
// print size if requested
if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
MYSERIAL.write(' ');
MYSERIAL.print(dir.fileSize);
ECHO_C(' ');
ECHO_V(dir.fileSize);
}
MYSERIAL.println();
ECHO_E;
return DIR_IS_FILE(&dir) ? 1 : 2;
}
//------------------------------------------------------------------------------
......@@ -395,22 +390,28 @@ bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
if (n == 10) goto fail; // only one dot allowed
n = 10; // max index for full 8.3 name
i = 8; // place for extension
} else {
}
else {
// illegal FAT characters
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
uint8_t b;
while ((b = pgm_read_byte(p++))) if (b == c) goto fail;
#ifdef __AVR__
// store chars in flash
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
uint8_t b;
while ((b = pgm_read_byte(p++))) if (b == c) goto fail;
#else // __AVR__
// store chars in RAM
if (strchr("|<>^+=?/[];,*\"\\", c)) goto fail;
#endif // __AVR__
// 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'));
name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a'));
}
}
*ptr = str;
// must have a file name, extension is optional
return name[0] != ' ';
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -457,8 +458,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
sub = parent != &dir1 ? &dir1 : &dir2;
}
return mkdir(parent, dname);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -506,7 +506,8 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
if (parent->isRoot()) {
d.firstClusterLow = 0;
d.firstClusterHigh = 0;
} else {
}
else {
d.firstClusterLow = parent->firstCluster_ & 0XFFFF;
d.firstClusterHigh = parent->firstCluster_ >> 16;
}
......@@ -515,24 +516,23 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
// write first block
return vol_->cacheFlush();
fail:
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 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.
*
......@@ -585,10 +585,10 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
* 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];
uint8_t dname[LONG_FILENAME_LENGTH+1];
SdBaseFile dir1, dir2;
SdBaseFile *parent = dirFile;
SdBaseFile *sub = &dir1;
SdBaseFile* parent = dirFile;
SdBaseFile* sub = &dir1;
if (!dirFile) goto fail;
......@@ -612,14 +612,13 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag) {
sub = parent != &dir1 ? &dir1 : &dir2;
}
return open(parent, dname, oflag);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
// open with filename in dname
bool SdBaseFile::open(SdBaseFile* dirFile,
const uint8_t dname[11], uint8_t oflag) {
const uint8_t dname[11], uint8_t oflag) {
bool emptyFound = false;
bool fileFound = false;
uint8_t index;
......@@ -644,7 +643,8 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
}
// done if no entries follow
if (p->name[0] == DIR_NAME_FREE) break;
} else if (!memcmp(dname, p->name, 11)) {
}
else if (!memcmp(dname, p->name, 11)) {
fileFound = true;
break;
}
......@@ -652,14 +652,16 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
if (fileFound) {
// don't open existing file if O_EXCL
if (oflag & O_EXCL) goto fail;
} else {
}
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 {
}
else {
if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) goto fail;
// add and zero cluster for dirFile - first cluster is in cache for write
......@@ -677,7 +679,8 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
if (dateTime_) {
// call user date/time function
dateTime_(&p->creationDate, &p->creationTime);
} else {
}
else {
// use default date/time
p->creationDate = FAT_DEFAULT_DATE;
p->creationTime = FAT_DEFAULT_TIME;
......@@ -691,8 +694,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
}
// open entry in cache
return openCachedEntry(index, oflag);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -734,8 +736,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
}
// open cached entry
return openCachedEntry(index & 0XF, oflag);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -760,10 +761,12 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
if (DIR_IS_FILE(p)) {
fileSize_ = p->fileSize;
type_ = FAT_FILE_TYPE_NORMAL;
} else if (DIR_IS_SUBDIR(p)) {
}
else if (DIR_IS_SUBDIR(p)) {
if (!vol_->chainSize(firstCluster_, &fileSize_)) goto fail;
type_ = FAT_FILE_TYPE_SUBDIR;
} else {
}
else {
goto fail;
}
// save open flags for read/write
......@@ -774,8 +777,7 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
curPosition_ = 0;
if ((oflag & O_TRUNC) && !truncate(0)) return false;
return oflag & O_AT_END ? seekEnd(0) : true;
fail:
fail:
type_ = FAT_FILE_TYPE_CLOSED;
return false;
}
......@@ -821,8 +823,7 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
return openCachedEntry(index, oflag);
}
}
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -865,8 +866,9 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
// '..' 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;
}
else if (!file.openCachedEntry(1, O_READ)) {
goto fail;
}
// search for parent in '../..'
do {
......@@ -875,9 +877,8 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
c |= (uint32_t)entry.firstClusterHigh << 16;
} while (c != cluster);
// open parent
return open(&file, file.curPosition()/32 - 1, O_READ);
fail:
return open(&file, file.curPosition() / 32 - 1, O_READ);
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -898,11 +899,13 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
type_ = FAT_FILE_TYPE_ROOT_FIXED;
firstCluster_ = 0;
fileSize_ = 32 * vol->rootDirEntryCount();
} else if (vol->fatType() == 32) {
}
else if (vol->fatType() == 32) {
type_ = FAT_FILE_TYPE_ROOT32;
firstCluster_ = vol->rootDirStart();
if (!vol->chainSize(firstCluster_, &fileSize_)) goto fail;
} else {
}
else {
// volume is not initialized, invalid, or FAT12 without support
return false;
}
......@@ -918,8 +921,7 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
dirBlock_ = 0;
dirIndex_ = 0;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -943,31 +945,31 @@ int SdBaseFile::peek() {
* \param[in] printSlash Print '/' after directory names if true.
*/
void SdBaseFile::printDirName(const dir_t& dir,
uint8_t width, bool printSlash) {
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) {
MYSERIAL.write('.');
ECHO_C('.');
w++;
}
MYSERIAL.write(dir.name[i]);
ECHO_T(dir.name[i]);
w++;
}
if (DIR_IS_SUBDIR(&dir) && printSlash) {
MYSERIAL.write('/');
ECHO_C('/');
w++;
}
while (w < width) {
MYSERIAL.write(' ');
ECHO_C(' ');
w++;
}
}
//------------------------------------------------------------------------------
// print uint8_t with width 2
static void print2u( uint8_t v) {
if (v < 10) MYSERIAL.write('0');
MYSERIAL.print(v, DEC);
static void print2u(uint8_t v) {
if (v < 10) ECHO_C('0');
ECHO_V(v);
}
//------------------------------------------------------------------------------
/** %Print a directory date field to Serial.
......@@ -986,11 +988,11 @@ static void print2u( uint8_t v) {
* \param[in] fatDate The date field from a directory entry.
*/
void SdBaseFile::printFatDate(uint16_t fatDate) {
MYSERIAL.print(FAT_YEAR(fatDate));
MYSERIAL.write('-');
print2u( FAT_MONTH(fatDate));
MYSERIAL.write('-');
print2u( FAT_DAY(fatDate));
ECHO_T(FAT_YEAR(fatDate));
ECHO_C('-');
print2u(FAT_MONTH(fatDate));
ECHO_C('-');
print2u(FAT_DAY(fatDate));
}
//------------------------------------------------------------------------------
......@@ -1001,12 +1003,12 @@ void SdBaseFile::printFatDate(uint16_t fatDate) {
* \param[in] pr Print stream for output.
* \param[in] fatTime The time field from a directory entry.
*/
void SdBaseFile::printFatTime( uint16_t fatTime) {
print2u( FAT_HOUR(fatTime));
MYSERIAL.write(':');
print2u( FAT_MINUTE(fatTime));
MYSERIAL.write(':');
print2u( FAT_SECOND(fatTime));
void SdBaseFile::printFatTime(uint16_t fatTime) {
print2u(FAT_HOUR(fatTime));
ECHO_C(':');
print2u(FAT_MINUTE(fatTime));
ECHO_C(':');
print2u(FAT_SECOND(fatTime));
}
//------------------------------------------------------------------------------
/** Print a file's name to Serial
......@@ -1017,7 +1019,7 @@ void SdBaseFile::printFatTime( uint16_t fatTime) {
bool SdBaseFile::printName() {
char name[FILENAME_LENGTH];
if (!getFilename(name)) return false;
MYSERIAL.print(name);
ECHO_T(name);
return true;
}
//------------------------------------------------------------------------------
......@@ -1063,14 +1065,16 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
offset = curPosition_ & 0X1FF; // offset in block
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
block = vol_->rootDirStart() + (curPosition_ >> 9);
} else {
}
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 {
}
else {
// get next cluster from FAT
if (!vol_->fatGet(curCluster_, &curCluster_)) goto fail;
}
......@@ -1085,7 +1089,8 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
// no buffering needed if n == 512
if (n == 512 && block != vol_->cacheBlockNumber()) {
if (!vol_->readBlock(block, dst)) goto fail;
} else {
}
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;
......@@ -1096,8 +1101,7 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
toRead -= n;
}
return nbyte;
fail:
fail:
return -1;
}
......@@ -1116,7 +1120,7 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
int16_t n;
// if not a directory file or miss-positioned return an error
if (!isDir() || (0X1F & curPosition_)) return -1;
//If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly.
if (longFilename != NULL) longFilename[0] = '\0';
......@@ -1134,15 +1138,15 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
// Fill the long filename if we have a long filename entry.
// Long filename entries are stored before the short filename.
if (longFilename != NULL && DIR_IS_LONG_NAME(dir)) {
vfat_t *VFAT = (vfat_t*)dir;
vfat_t* VFAT = (vfat_t*)dir;
// Sanity-check the VFAT entry. The first cluster is always set to zero. And the sequence number should be higher than 0
if (VFAT->firstClusterLow == 0 && (VFAT->sequenceNumber & 0x1F) > 0 && (VFAT->sequenceNumber & 0x1F) <= MAX_VFAT_ENTRIES) {
// TODO: Store the filename checksum to verify if a none-long filename aware system modified the file table.
n = ((VFAT->sequenceNumber & 0x1F) - 1) * FILENAME_LENGTH;
for (uint8_t i=0; i<FILENAME_LENGTH; i++)
longFilename[n+i] = (i < 5) ? VFAT->name1[i] : (i < 11) ? VFAT->name2[i-5] : VFAT->name3[i-11];
for (uint8_t i = 0; i < FILENAME_LENGTH; i++)
longFilename[n + i] = (i < 5) ? VFAT->name1[i] : (i < 11) ? VFAT->name2[i - 5] : VFAT->name3[i - 11];
// If this VFAT entry is the last one, add a NUL terminator at the end of the string
if (VFAT->sequenceNumber & 0x40) longFilename[n+FILENAME_LENGTH] = '\0';
if (VFAT->sequenceNumber & 0x40) longFilename[n + FILENAME_LENGTH] = '\0';
}
}
// Return if normal file or subdirectory
......@@ -1169,8 +1173,7 @@ dir_t* SdBaseFile::readDirCache() {
// return pointer to entry
return vol_->cache()->dir + i;
fail:
fail:
return 0;
}
//------------------------------------------------------------------------------
......@@ -1205,8 +1208,7 @@ bool SdBaseFile::remove() {
// write entry to SD
return vol_->cacheFlush();
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1231,8 +1233,7 @@ bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
SdBaseFile file;
if (!file.open(dirFile, path, O_WRITE)) goto fail;
return file.remove();
fail:
fail:
// can't set iostate - static function
return false;
}
......@@ -1275,7 +1276,8 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
if (!file.open(dirFile, newPath, O_CREAT | O_EXCL | O_WRITE)) {
goto restore;
}
} else {
}
else {
// don't create missing path prefix components
if (!file.mkdir(dirFile, newPath, false)) {
goto restore;
......@@ -1314,14 +1316,14 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
}
return vol_->cacheFlush();
restore:
restore:
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
if (!d) goto fail;
// restore entry
d->name[0] = entry.name[0];
vol_->cacheFlush();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1361,8 +1363,7 @@ bool SdBaseFile::rmdir() {
type_ = FAT_FILE_TYPE_NORMAL;
flags_ |= O_WRITE;
return remove();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1387,7 +1388,7 @@ bool SdBaseFile::rmRfStar() {
rewind();
while (curPosition_ < fileSize_) {
// remember position
index = curPosition_/32;
index = curPosition_ / 32;
dir_t* p = readDirCache();
if (!p) goto fail;
......@@ -1405,14 +1406,15 @@ bool SdBaseFile::rmRfStar() {
if (f.isSubDir()) {
// recursively delete
if (!f.rmRfStar()) goto fail;
} else {
}
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;
if (curPosition_ != (32 * (index + 1))) {
if (!seekSet(32 * (index + 1))) goto fail;
}
}
// don't try to delete root
......@@ -1420,8 +1422,7 @@ bool SdBaseFile::rmRfStar() {
if (!rmdir()) goto fail;
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1468,7 +1469,8 @@ bool SdBaseFile::seekSet(uint32_t pos) {
if (nNew < nCur || curPosition_ == 0) {
// must follow chain from first cluster
curCluster_ = firstCluster_;
} else {
}
else {
// advance from curPosition
nNew -= nCur;
}
......@@ -1477,10 +1479,10 @@ bool SdBaseFile::seekSet(uint32_t pos) {
}
curPosition_ = pos;
done:
done:
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1523,7 +1525,7 @@ bool SdBaseFile::sync() {
}
return vol_->cacheFlush();
fail:
fail:
writeError = true;
return false;
}
......@@ -1563,7 +1565,7 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
// write back entry
return vol_->cacheFlush();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1601,22 +1603,22 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
* 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) {
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;
|| 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;
......@@ -1640,8 +1642,7 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
d->lastWriteTime = dirTime;
}
return vol_->cacheFlush();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1677,7 +1678,8 @@ bool SdBaseFile::truncate(uint32_t length) {
// free all clusters
if (!vol_->freeChain(firstCluster_)) goto fail;
firstCluster_ = 0;
} else {
}
else {
uint32_t toFree;
if (!vol_->fatGet(curCluster_, &toFree)) goto fail;
......@@ -1699,7 +1701,7 @@ bool SdBaseFile::truncate(uint32_t length) {
// set file to correct position
return seekSet(newPos);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -1742,16 +1744,19 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
if (firstCluster_ == 0) {
// allocate first cluster of file
if (!addCluster()) goto fail;
} else {
}
else {
curCluster_ = firstCluster_;
}
} else {
}
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 {
}
else {
curCluster_ = next;
}
}
......@@ -1771,13 +1776,15 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
vol_->cacheSetBlockNumber(0XFFFFFFFF, false);
}
if (!vol_->writeBlock(block, src)) goto fail;
} else {
}
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 {
}
else {
// rewrite part of block
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto fail;
}
......@@ -1792,7 +1799,8 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
// update fileSize and insure sync will update dir entry
fileSize_ = curPosition_;
flags_ |= F_FILE_DIR_DIRTY;
} else if (dateTime_ && nbyte) {
}
else if (dateTime_ && nbyte) {
// insure sync will update modified date and time
flags_ |= F_FILE_DIR_DIRTY;
}
......@@ -1802,7 +1810,7 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
}
return nbyte;
fail:
fail:
// return for write error
writeError = true;
return -1;
......@@ -1810,7 +1818,7 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
//------------------------------------------------------------------------------
// suppress cpplint warnings with NOLINT comment
#if ALLOW_DEPRECATED_FUNCTIONS && DISABLED(DOXYGEN)
void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT
void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT
#endif // ALLOW_DEPRECATED_FUNCTIONS
......
......@@ -17,6 +17,11 @@
* along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#ifndef SdBaseFile_h
#define SdBaseFile_h
/**
......@@ -154,7 +159,7 @@ static inline uint8_t FAT_HOUR(uint16_t fatTime) {
* \return Extracted minute [0,59]
*/
static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
return(fatTime >> 5) & 0X3F;
return (fatTime >> 5) & 0X3F;
}
/** second part of FAT directory time field
* Note second/2 is stored in packed time.
......@@ -164,7 +169,7 @@ static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
* \return Extracted second [0,58]
*/
static inline uint8_t FAT_SECOND(uint16_t fatTime) {
return 2*(fatTime & 0X1F);
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;
......@@ -180,7 +185,7 @@ class SdBaseFile {
/** Create an instance. */
SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
SdBaseFile(const char* path, uint8_t oflag);
~SdBaseFile() {if(isOpen()) close();}
~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
......@@ -201,7 +206,7 @@ class SdBaseFile {
bool close();
bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
bool createContiguous(SdBaseFile* dirFile,
const char* path, uint32_t size);
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. */
......@@ -262,7 +267,7 @@ class SdBaseFile {
bool isRoot() const {
return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
}
void ls( uint8_t flags = 0, uint8_t indent = 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) {
......@@ -275,7 +280,7 @@ class SdBaseFile {
bool openRoot(SdVolume* vol);
int peek();
static void printFatDate(uint16_t fatDate);
static void printFatTime( uint16_t fatTime);
static void printFatTime(uint16_t fatTime);
bool printName();
int16_t read();
int16_t read(void* buf, uint16_t nbyte);
......@@ -305,7 +310,7 @@ class SdBaseFile {
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);
uint8_t hour, uint8_t minute, uint8_t second);
/** Type of file. You should use isFile() or isDir() instead of type()
* if possible.
*
......@@ -316,7 +321,7 @@ class SdBaseFile {
/** \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;
......@@ -348,7 +353,7 @@ class SdBaseFile {
bool addCluster();
bool addDirCluster();
dir_t* cacheDirEntry(uint8_t action);
int8_t lsPrintNext( 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);
......@@ -356,10 +361,10 @@ class SdBaseFile {
dir_t* readDirCache();
//------------------------------------------------------------------------------
// to be deleted
static void printDirName( const dir_t& dir,
uint8_t width, bool printSlash);
//------------------------------------------------------------------------------
// Deprecated functions - suppress cpplint warnings with NOLINT comment
static void printDirName(const dir_t& dir,
uint8_t width, bool printSlash);
//------------------------------------------------------------------------------
// Deprecated functions - suppress cpplint warnings with NOLINT comment
#if ALLOW_DEPRECATED_FUNCTIONS && DISABLED(DOXYGEN)
public:
/** \deprecated Use:
......@@ -371,16 +376,16 @@ class SdBaseFile {
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.
*/
/** \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) {
const char* path, uint32_t size) {
return createContiguous(&dirFile, path, size);
}
/** \deprecated Use:
......@@ -418,7 +423,7 @@ class SdBaseFile {
* \return true for success or false for failure.
*/
bool open(SdBaseFile& dirFile, // NOLINT
const char* path, uint8_t oflag) {
const char* path, uint8_t oflag) {
return open(&dirFile, path, oflag);
}
/** \deprecated Do not use in new apps
......@@ -461,8 +466,8 @@ class SdBaseFile {
static bool remove(SdBaseFile& dirFile, const char* path) { // NOLINT
return remove(&dirFile, path);
}
//------------------------------------------------------------------------------
// rest are private
//------------------------------------------------------------------------------
// rest are private
private:
static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT
static void oldToNew(uint16_t* date, uint16_t* time) {
......@@ -475,4 +480,5 @@ class SdBaseFile {
#endif // ALLOW_DEPRECATED_FUNCTIONS
};
#endif // SdBaseFile_h
#endif
/* 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
* <http://www.gnu.org/licenses/>.
*/
/**
* \file
* \brief configuration definitions
*/
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#ifndef SdFatConfig_h
#define SdFatConfig_h
#include <stdint.h>
//------------------------------------------------------------------------------
/**
* 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
/** Number of UTF-16 characters per entry */
#define FILENAME_LENGTH 13
/**
* Defines for long (vfat) filenames
*/
/** Number of VFAT entries used. Every entry has 13 UTF-16 characters */
#define MAX_VFAT_ENTRIES (2)
/** Total size of the buffer used to store the long filenames */
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * MAX_VFAT_ENTRIES + 1)
#endif // SdFatConfig_h
#endif
......@@ -17,6 +17,11 @@
* along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#ifndef SdFatStructs_h
#define SdFatStructs_h
......@@ -52,9 +57,9 @@ struct partitionTable {
*/
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.
*/
* 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
......@@ -337,7 +342,7 @@ struct fat32_boot {
* 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.
* Bits 8-15 -- Reserved.
*/
uint16_t fat32Flags;
/**
......@@ -465,29 +470,29 @@ uint32_t const FAT32MASK = 0X0FFFFFFF;
* \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
*
* 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
* 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
*
* 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
* 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 {
......@@ -545,7 +550,7 @@ struct directoryEntry {
*
* directoryVFATEntries are found in the same list as normal directoryEntry.
* But have the attribute field set to DIR_ATT_LONG_NAME.
*
*
* Long filenames are saved in multiple directoryVFATEntries.
* Each entry containing 13 UTF-16 characters.
*/
......@@ -638,3 +643,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
......@@ -18,11 +18,9 @@
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#include "../Marlin_main.h"
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#include "SdFile.h"
/** Create a file object and open it in the current working directory.
*
......@@ -58,15 +56,13 @@ int16_t SdFile::write(const void* buf, uint16_t nbyte) {
* Use writeError to check for errors.
*/
#if ARDUINO >= 100
size_t SdFile::write(uint8_t b)
{
size_t SdFile::write(uint8_t b) {
return SdBaseFile::write(&b, 1);
}
}
#else
void SdFile::write(uint8_t b)
{
void SdFile::write(uint8_t b) {
SdBaseFile::write(&b, 1);
}
}
#endif
//------------------------------------------------------------------------------
/** Write a string to a file. Used by the Arduino Print class.
......@@ -93,4 +89,6 @@ void SdFile::writeln_P(PGM_P str) {
write_P(str);
write_P(PSTR("\r\n"));
}
#endif
......@@ -21,6 +21,10 @@
* \file
* \brief SdFile class
*/
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#include "SdBaseFile.h"
#include <Print.h>
#ifndef SdFile_h
......@@ -35,14 +39,17 @@ class SdFile : public SdBaseFile, public Print {
SdFile() {}
SdFile(const char* name, uint8_t oflag);
#if ARDUINO >= 100
size_t write(uint8_t b);
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);
void writeln_P(PGM_P str);
};
#endif // SdFile_h
#endif
......@@ -17,6 +17,11 @@
* along with the Arduino Sd2Card Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#ifndef SdInfo_h
#define SdInfo_h
#include <stdint.h>
......@@ -115,13 +120,13 @@ typedef struct CID {
/** Manufacturing date month */
unsigned char mdt_month : 4;
/** Manufacturing date year low digit */
unsigned char mdt_year_low :4;
unsigned char mdt_year_low : 4;
// byte 15
/** not used always 1 */
unsigned char always1 : 1;
/** CRC7 checksum */
unsigned char crc : 7;
}cid_t;
} cid_t;
//------------------------------------------------------------------------------
/** CSD for version 1.00 cards */
typedef struct CSDV1 {
......@@ -143,7 +148,7 @@ typedef struct CSDV1 {
unsigned char c_size_high : 2;
unsigned char reserved2 : 2;
unsigned char dsr_imp : 1;
unsigned char read_blk_misalign :1;
unsigned char read_blk_misalign : 1;
unsigned char write_blk_misalign : 1;
unsigned char read_bl_partial : 1;
// byte 7
......@@ -151,7 +156,7 @@ typedef struct CSDV1 {
// byte 8
unsigned char vdd_r_curr_max : 3;
unsigned char vdd_r_curr_min : 3;
unsigned char c_size_low :2;
unsigned char c_size_low : 2;
// byte 9
unsigned char c_size_mult_high : 2;
unsigned char vdd_w_cur_max : 3;
......@@ -183,7 +188,7 @@ typedef struct CSDV1 {
// byte 15
unsigned char always1 : 1;
unsigned char crc : 7;
}csd1_t;
} csd1_t;
//------------------------------------------------------------------------------
/** CSD for version 2.00 cards */
typedef struct CSDV2 {
......@@ -209,7 +214,7 @@ typedef struct CSDV2 {
unsigned char reserved2 : 4;
unsigned char dsr_imp : 1;
/** fixed to 0 */
unsigned char read_blk_misalign :1;
unsigned char read_blk_misalign : 1;
/** fixed to 0 */
unsigned char write_blk_misalign : 1;
/** fixed to 0 - no partial read */
......@@ -265,7 +270,7 @@ typedef struct CSDV2 {
unsigned char always1 : 1;
/** checksum */
unsigned char crc : 7;
}csd2_t;
} csd2_t;
//------------------------------------------------------------------------------
/** union of old and new style CSD register */
union csd_t {
......@@ -273,3 +278,5 @@ union csd_t {
csd2_t v2;
};
#endif // SdInfo_h
#endif
......@@ -18,20 +18,19 @@
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#include "../Marlin_main.h"
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#include "SdVolume.h"
//------------------------------------------------------------------------------
#if !USE_MULTIPLE_CARDS
// raw block cache
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
// raw block cache
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
......@@ -53,7 +52,8 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
// don't save new start location
setStart = false;
} else {
}
else {
// start at likely place for free cluster
bgnCluster = allocSearchStart_;
......@@ -78,7 +78,8 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
if (f != 0) {
// cluster in use try next cluster as bgnCluster
bgnCluster = endCluster + 1;
} else if ((endCluster - bgnCluster + 1) == count) {
}
else if ((endCluster - bgnCluster + 1) == count) {
// done - found space
break;
}
......@@ -102,8 +103,7 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
if (setStart) allocSearchStart_ = bgnCluster + 1;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -122,8 +122,7 @@ bool SdVolume::cacheFlush() {
cacheDirty_ = 0;
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -135,8 +134,7 @@ bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
}
if (dirty) cacheDirty_ = true;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -149,8 +147,7 @@ bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
} while (!isEOC(cluster));
*size = s;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -176,9 +173,11 @@ bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
}
if (fatType_ == 16) {
lba = fatStartBlock_ + (cluster >> 8);
} else if (fatType_ == 32) {
}
else if (fatType_ == 32) {
lba = fatStartBlock_ + (cluster >> 7);
} else {
}
else {
goto fail;
}
if (lba != cacheBlockNumber_) {
......@@ -186,12 +185,12 @@ bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
}
if (fatType_ == 16) {
*value = cacheBuffer_.fat16[cluster & 0XFF];
} else {
}
else {
*value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -234,23 +233,25 @@ bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
}
if (fatType_ == 16) {
lba = fatStartBlock_ + (cluster >> 8);
} else if (fatType_ == 32) {
}
else if (fatType_ == 32) {
lba = fatStartBlock_ + (cluster >> 7);
} else {
}
else {
goto fail;
}
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
// store entry
if (fatType_ == 16) {
cacheBuffer_.fat16[cluster & 0XFF] = value;
} else {
}
else {
cacheBuffer_.fat32[cluster & 0X7F] = value;
}
// mirror second FAT
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -271,8 +272,7 @@ bool SdVolume::freeChain(uint32_t cluster) {
} while (!isEOC(cluster));
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
......@@ -287,9 +287,11 @@ int32_t SdVolume::freeClusterCount() {
if (fatType_ == 16) {
n = 256;
} else if (fatType_ == 32) {
}
else if (fatType_ == 32) {
n = 128;
} else {
}
else {
// put FAT12 here
return -1;
}
......@@ -301,7 +303,8 @@ int32_t SdVolume::freeClusterCount() {
for (uint16_t i = 0; i < n; i++) {
if (cacheBuffer_.fat16[i] == 0) free++;
}
} else {
}
else {
for (uint16_t i = 0; i < n; i++) {
if (cacheBuffer_.fat32[i] == 0) free++;
}
......@@ -341,10 +344,10 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
if (part) {
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) {
part_t* p = &cacheBuffer_.mbr.part[part - 1];
if ((p->boot & 0X7F) != 0 ||
p->totalSectors < 100 ||
p->firstSector == 0) {
// not a valid partition
goto fail;
}
......@@ -353,11 +356,11 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
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
goto fail;
fbs->fatCount == 0 ||
fbs->reservedSectorCount == 0 ||
fbs->sectorsPerCluster == 0) {
// not valid FAT volume
goto fail;
}
fatCount_ = fbs->fatCount;
blocksPerCluster_ = fbs->sectorsPerCluster;
......@@ -368,7 +371,7 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
if (clusterSizeShift_++ > 7) goto fail;
}
blocksPerFat_ = fbs->sectorsPerFat16 ?
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount;
......@@ -379,11 +382,12 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_;
// data start for FAT16 and FAT32
dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511)/512);
dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511) / 512);
// total blocks for FAT16 or FAT32
totalBlocks = fbs->totalSectors16 ?
fbs->totalSectors16 : fbs->totalSectors32;
fbs->totalSectors16 : fbs->totalSectors32;
// total data blocks
clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
......@@ -394,15 +398,16 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
if (clusterCount_ < 4085) {
fatType_ = 12;
if (!FAT12_SUPPORT) goto fail;
} else if (clusterCount_ < 65525) {
}
else if (clusterCount_ < 65525) {
fatType_ = 16;
} else {
}
else {
rootDirStart_ = fbs->fat32RootCluster;
fatType_ = 32;
}
return true;
fail:
fail:
return false;
}
#endif
\ No newline at end of file
......@@ -18,6 +18,9 @@
* <http://www.gnu.org/licenses/>.
*/
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#ifndef SdVolume_h
#define SdVolume_h
/**
......@@ -116,7 +119,7 @@ class SdVolume {
* \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;
......@@ -153,12 +156,15 @@ class SdVolume {
//----------------------------------------------------------------------------
bool allocContiguous(uint32_t count, uint32_t* curCluster);
uint8_t blockOfCluster(uint32_t position) const {
return (position >> 9) & (blocksPerCluster_ - 1);}
return (position >> 9) & (blocksPerCluster_ - 1);
}
uint32_t clusterStartBlock(uint32_t cluster) const {
return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
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_;}
return clusterStartBlock(cluster) + blockOfCluster(position);
}
cache_t* cache() {return &cacheBuffer_;}
uint32_t cacheBlockNumber() {return cacheBlockNumber_;}
#if USE_MULTIPLE_CARDS
bool cacheFlush();
......@@ -186,11 +192,12 @@ class SdVolume {
return cluster >= FAT32EOC_MIN;
}
bool readBlock(uint32_t block, uint8_t* dst) {
return sdCard_->readBlock(block, 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 && DISABLED(DOXYGEN)
public:
......@@ -210,3 +217,4 @@ class SdVolume {
#endif // ALLOW_DEPRECATED_FUNCTIONS
};
#endif // SdVolume
#endif
#include "../base.h"
#include "../Marlin_main.h"
#include "../../base.h"
#if ENABLED(SDSUPPORT)
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
#include "nextion_lcd.h"
#include "cardreader.h"
CardReader::CardReader() {
......@@ -86,7 +76,7 @@ void CardReader::lsDive(const char* prepend, SdFile parent, const char* const ma
SdFile dir;
if (!dir.open(parent, lfilename, O_READ)) {
if (lsAction == LS_SerialPrint) {
ECHO_LMV(ER, SERIAL_SD_CANT_OPEN_SUBDIR, lfilename);
ECHO_LMT(ER, SERIAL_SD_CANT_OPEN_SUBDIR, lfilename);
}
}
lsDive(path, dir);
......@@ -95,8 +85,9 @@ void CardReader::lsDive(const char* prepend, SdFile parent, const char* const ma
else {
char pn0 = p.name[0];
if (pn0 == DIR_NAME_FREE) break;
if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
if (longFilename[0] == '.') continue;
if (pn0 == DIR_NAME_DELETED || pn0 == '.' || pn0 == '_') continue;
char lf0 = longFilename[0];
if (lf0 == '.' || lf0 == '_') continue;
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
......@@ -109,9 +100,8 @@ void CardReader::lsDive(const char* prepend, SdFile parent, const char* const ma
nrFiles++;
break;
case LS_SerialPrint:
createFilename(filename, p);
ECHO_V(prepend);
ECHO_EV(filename);
ECHO_T(prepend);
ECHO_ET(longFilename);
break;
case LS_GetFilename:
createFilename(filename, p);
......@@ -168,7 +158,7 @@ void CardReader::ls() {
// Print /LongNamePart to serial output
ECHO_C('/');
ECHO_V(longFilename[0] ? longFilename : "???");
ECHO_M(longFilename[0] ? longFilename : "???");
// If the filename was printed then that's it
if (!filenameIsDir) break;
// ECHO_M("Opening dir: "); ECHO_EV(segment);
......@@ -176,7 +166,7 @@ void CardReader::ls() {
SdFile dir;
if (!dir.open(diveDir, segment, O_READ)) {
ECHO_E;
ECHO_SMV(DB, SERIAL_SD_CANT_OPEN_SUBDIR, segment);
ECHO_SMT(ER, SERIAL_SD_CANT_OPEN_SUBDIR, segment);
break;
}
......@@ -207,7 +197,7 @@ void CardReader::initsd() {
&& !card.init(SPI_SPEED, LCD_SDSS)
#endif
) {
ECHO_LM(DB, SERIAL_SD_INIT_FAIL);
ECHO_LM(ER, SERIAL_SD_INIT_FAIL);
}
else if (!volume.init(&card)) {
ECHO_LM(ER, SERIAL_SD_VOL_INIT_FAIL);
......@@ -284,25 +274,25 @@ void CardReader::openFile(char* name, bool read, bool replace_current/*=true*/,
return;
}
ECHO_SMV(DB, "SUBROUTINE CALL target:\"", name);
ECHO_SMT(DB, "SUBROUTINE CALL target:\"", name);
ECHO_M("\" parent:\"");
//store current filename and position
getAbsFilename(filenames[file_subcall_ctr]);
ECHO_V(filenames[file_subcall_ctr]);
ECHO_T(filenames[file_subcall_ctr]);
ECHO_EMV("\" pos", sdpos);
filespos[file_subcall_ctr] = sdpos;
file_subcall_ctr++;
}
else {
ECHO_LMV(DB, "Now doing file: ", name);
ECHO_LMT(INFO, "Now doing file: ", name);
}
file.close();
}
else { // opening fresh file
file_subcall_ctr = 0; // resetting procedure depth in case user cancels print while in procedure
ECHO_LMV(DB, "Now fresh file: ", name);
ECHO_LMT(INFO, "Now fresh file: ", name);
}
sdprinting = false;
SdFile myDir;
......@@ -317,10 +307,9 @@ void CardReader::openFile(char* name, bool read, bool replace_current/*=true*/,
char subdirname[FILENAME_LENGTH];
strncpy(subdirname, dirname_start, dirname_end - dirname_start);
subdirname[dirname_end - dirname_start] = 0;
ECHO_EV(subdirname);
ECHO_ET(subdirname);
if (!myDir.open(curDir, subdirname, O_READ)) {
ECHO_SMV(ER, SERIAL_SD_OPEN_FILE_FAIL, subdirname);
ECHO_EM(".");
ECHO_LMT(ER, SERIAL_SD_OPEN_FILE_FAIL, subdirname);
return;
}
else {
......@@ -336,29 +325,57 @@ void CardReader::openFile(char* name, bool read, bool replace_current/*=true*/,
break;
}
}
} else //relative path
}
else { //relative path
curDir = &workDir;
}
char newName[FILENAME_LENGTH + 2];
if (strlen((char *)fname) >= 9) {
// Generate 8.3 from longfile name
char *pExt, szExt[5];
if ((pExt = strchr((char *)fname, '.')) != NULL) {
strncpy(szExt, pExt, 4);
szExt[4] = 0;
if (pExt > (char*)fname + 6) pExt = (char*)fname + 6;
}
else {
szExt[0] = 0;
pExt = (char*)fname + 6;
}
uint8_t cb = pExt - (char *)fname;
memcpy(newName, fname, cb);
newName[cb] = 0;
strcat(newName, "~1");
strcat(newName, szExt);
}
else {
memcpy(newName, fname, FILENAME_LENGTH + 2);
}
if (read) {
if (file.open(curDir, fname, O_READ)) {
if (file.open(curDir, newName, O_READ)) {
filesize = file.fileSize();
ECHO_MV(SERIAL_SD_FILE_OPENED, fname);
ECHO_MT(SERIAL_SD_FILE_OPENED, fname);
ECHO_EMV(SERIAL_SD_SIZE, filesize);
sdpos = 0;
ECHO_EM(SERIAL_SD_FILE_SELECTED);
getfilename(0, fname);
getfilename(0, newName);
if(lcd_status) lcd_setstatus(longFilename[0] ? longFilename : fname);
} else {
ECHO_MV(SERIAL_SD_OPEN_FILE_FAIL, fname);
ECHO_PGM(".\n");
}
} else { //write
if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
ECHO_SMV(ER, SERIAL_SD_OPEN_FILE_FAIL, fname);
ECHO_EM(".");
} else {
else {
ECHO_LMT(ER, SERIAL_SD_OPEN_FILE_FAIL, fname);
}
}
else { //write
if (!file.open(curDir, newName, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
ECHO_LMT(ER, SERIAL_SD_OPEN_FILE_FAIL, fname);
}
else {
saving = true;
ECHO_LMV(DB, SERIAL_SD_WRITE_TO_FILE, name);
ECHO_LMT(DB, SERIAL_SD_WRITE_TO_FILE, name);
if (lcd_status) lcd_setstatus(fname);
}
}
......@@ -366,11 +383,14 @@ void CardReader::openFile(char* name, bool read, bool replace_current/*=true*/,
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;
......@@ -380,28 +400,31 @@ void CardReader::removeFile(char* name) {
char subdirname[FILENAME_LENGTH];
strncpy(subdirname, dirname_start, dirname_end - dirname_start);
subdirname[dirname_end - dirname_start] = 0;
ECHO_EV(subdirname);
ECHO_ET(subdirname);
if (!myDir.open(curDir, subdirname, O_READ)) {
ECHO_SMV(DB, SERIAL_SD_OPEN_FILE_FAIL, subdirname);
ECHO_EM(".");
ECHO_LMT(ER, SERIAL_SD_OPEN_FILE_FAIL, subdirname);
return;
}
curDir = &myDir;
dirname_start = dirname_end + 1;
} else { // the remainder after all /fsa/fdsa/ is the filename
}
else { // the remainder after all /fsa/fdsa/ is the filename
fname = dirname_start;
break;
}
}
} else // relative path
}
else { // relative path
curDir = &workDir;
}
if (file.remove(curDir, fname)) {
ECHO_EMV(SERIAL_SD_FILE_DELETED, fname);
ECHO_EMT(SERIAL_SD_FILE_DELETED, fname);
sdpos = 0;
} else {
ECHO_MV(SERIAL_SD_FILE_DELETION_ERR, fname);
ECHO_C('.');
}
else {
ECHO_EMT(SERIAL_SD_FILE_DELETION_ERR, fname);
}
}
......@@ -409,7 +432,8 @@ void CardReader::getStatus() {
if (cardOK) {
ECHO_MV(SERIAL_SD_PRINTING_BYTE, sdpos);
ECHO_EMV(SERIAL_SD_SLASH, filesize);
} else
}
else
ECHO_EM(SERIAL_SD_NOT_PRINTING);
}
......@@ -417,6 +441,7 @@ 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;
......@@ -432,18 +457,24 @@ void CardReader::write_command(char* buf) {
}
void CardReader::checkautostart(bool force) {
if (!force && (!autostart_stilltocheck || next_autostart_ms >= millis()))
if (!force && (!autostart_stilltocheck || next_autostart_ms < millis()))
return;
autostart_stilltocheck = false;
if (!cardOK) {
initsd();
if (!cardOK) return; // fail
}
char autoname[10];
sprintf_P(autoname, PSTR("auto%i.g"), autostart_index);
for (int8_t i = 0; i < (int8_t)strlen(autoname); i++) autoname[i] = tolower(autoname[i]);
dir_t p;
root.rewind();
bool found = false;
while (root.readDir(p, NULL) > 0) {
for (int8_t i = 0; i < (int8_t)strlen((char*)p.name); i++) p.name[i] = tolower(p.name[i]);
......@@ -465,6 +496,7 @@ void CardReader::closeFile(bool store_location) {
file.sync();
file.close();
saving = logging = false;
if (store_location) {
//future: store printer state, filename and position for continuing a stopped print
// so one can unplug the printer and continue printing the next day.
......@@ -593,8 +625,9 @@ void CardReader::chdir(const char* relpath) {
SdFile* parent = &root;
if (workDir.isOpen()) parent = &workDir;
if (!newfile.open(*parent, relpath, O_READ)) {
ECHO_LMV(DB, SERIAL_SD_CANT_ENTER_SUBDIR, relpath);
} else {
ECHO_LMT(DB, SERIAL_SD_CANT_ENTER_SUBDIR, relpath);
}
else {
if (workDirDepth < MAX_DIR_DEPTH) {
++workDirDepth;
for (int d = workDirDepth; d--;) workDirParents[d + 1] = workDirParents[d];
......@@ -621,7 +654,8 @@ void CardReader::printingHasFinished() {
openFile(filenames[file_subcall_ctr], true, true);
setIndex(filespos[file_subcall_ctr]);
startFileprint();
} else {
}
else {
file.close();
sdprinting = false;
if (SD_FINISHED_STEPPERRELEASE) {
......
......@@ -6,6 +6,7 @@
#define MAX_DIR_DEPTH 10 // Maximum folder depth
#include "SdFile.h"
enum LsAction { LS_SerialPrint, LS_Count, LS_GetFilename };
class CardReader {
......
/*
servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
Copyright (c) 2009 Michael Margolis. 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
*/
/*
A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently written using the write() method
Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
The methods are:
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin ) - Attaches a servo motor to an i/o pin.
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
default min is 544, max is 2400
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
move(pin, angle) - Sequence of attach(pin), write(angle).
With DEACTIVATE_SERVOS_AFTER_MOVE it waits SERVO_DEACTIVATION_DELAY and detaches.
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
*/
#include "../base.h"
#if HAS(SERVOS)
#include "servo.h"
#define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009
#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
//#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER)
static ServoInfo_t servo_info[MAX_SERVOS]; // static array of servo info structures
static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
uint8_t ServoCount = 0; // the total number of attached servos
// convenience macros
#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
#define SERVO(_timer,_channel) (servo_info[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
/************ static functions common to all instances ***********************/
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA) {
if (Channel[timer] < 0)
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
else {
if (SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive)
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
}
Channel[timer]++; // increment to the next channel
if (SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
*OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
}
else {
// finished all channels so wait for the refresh period to expire before starting over
if ( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
else
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
}
}
#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
// Interrupt handlers for Arduino
#ifdef _useTimer1
SIGNAL (TIMER1_COMPA_vect) { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
#endif
#ifdef _useTimer3
SIGNAL (TIMER3_COMPA_vect) { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
#endif
#ifdef _useTimer4
SIGNAL (TIMER4_COMPA_vect) { handle_interrupts(_timer4, &TCNT4, &OCR4A); }
#endif
#if ENABLED(_useTimer5)
SIGNAL (TIMER5_COMPA_vect) { handle_interrupts(_timer5, &TCNT5, &OCR5A); }
#endif
#else //!WIRING
// Interrupt handlers for Wiring
#ifdef _useTimer1
void Timer1Service() { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
#endif
#ifdef _useTimer3
void Timer3Service() { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
#endif
#endif //!WIRING
static void initISR(timer16_Sequence_t timer) {
#ifdef _useTimer1
if (timer == _timer1) {
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
TIFR |= _BV(OCF1A); // clear any pending interrupts;
TIMSK |= _BV(OCIE1A); // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
TIMSK1 |= _BV(OCIE1A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif
#ifdef _useTimer3
if (timer == _timer3) {
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#ifdef __AVR_ATmega128__
TIFR |= _BV(OCF3A); // clear any pending interrupts;
ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt
#else
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
}
#endif
#ifdef _useTimer4
if (timer == _timer4) {
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt
}
#endif
#ifdef _useTimer5
if (timer == _timer5) {
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt
}
#endif
}
static void finISR(timer16_Sequence_t timer) {
// Disable use of the given timer
#ifdef WIRING
if (timer == _timer1) {
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK1
#else
TIMSK
#endif
&= ~_BV(OCIE1A); // disable timer 1 output compare interrupt
timerDetach(TIMER1OUTCOMPAREA_INT);
}
else if (timer == _timer3) {
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
TIMSK3
#else
ETIMSK
#endif
&= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
timerDetach(TIMER3OUTCOMPAREA_INT);
}
#else //!WIRING
// For arduino - in future: call here to a currently undefined function to reset the timer
#endif
}
static boolean isTimerActive(timer16_Sequence_t timer) {
// returns true if any servo is active on this timer
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
if (SERVO(timer,channel).Pin.isActive)
return true;
}
return false;
}
/****************** end of static functions ******************************/
Servo::Servo() {
if (ServoCount < MAX_SERVOS) {
this->servoIndex = ServoCount++; // assign a servo index to this instance
servo_info[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
}
else
this->servoIndex = INVALID_SERVO; // too many servos
}
int8_t Servo::attach(int pin) {
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
}
int8_t Servo::attach(int pin, int min, int max) {
if (this->servoIndex >= MAX_SERVOS) return -1;
if (pin > 0) servo_info[this->servoIndex].Pin.nbr = pin;
pinMode(servo_info[this->servoIndex].Pin.nbr, OUTPUT); // set servo pin to output
// todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
this->min = (MIN_PULSE_WIDTH - min) / 4; //resolution of min/max is 4 uS
this->max = (MAX_PULSE_WIDTH - max) / 4;
// initialize the timer if it has not already been initialized
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (!isTimerActive(timer)) initISR(timer);
servo_info[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
return this->servoIndex;
}
void Servo::detach() {
servo_info[this->servoIndex].Pin.isActive = false;
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (!isTimerActive(timer)) finISR(timer);
}
void Servo::write(int value) {
// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < MIN_PULSE_WIDTH) {
if (value < 0) value = 0;
if (value > 180) value = 180;
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
}
this->writeMicroseconds(value);
}
void Servo::writeMicroseconds(int value) {
// calculate and store the values for the given channel
byte channel = this->servoIndex;
if (channel < MAX_SERVOS) { // ensure channel is valid
if (value < SERVO_MIN()) // ensure pulse width is valid
value = SERVO_MIN();
else if (value > SERVO_MAX())
value = SERVO_MAX();
value = value - TRIM_DURATION;
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead
uint8_t oldSREG = SREG;
cli();
servo_info[channel].ticks = value;
SREG = oldSREG;
}
}
// return the value as degrees
int Servo::read() { return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180); }
int Servo::readMicroseconds() {
return (this->servoIndex == INVALID_SERVO) ? 0 : ticksToUs(servo_info[this->servoIndex].ticks) + TRIM_DURATION;
}
bool Servo::attached() { return servo_info[this->servoIndex].Pin.isActive; }
void Servo::move(int value) {
if (this->attach(0) >= 0) {
this->write(value);
#if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
delay(SERVO_DEACTIVATION_DELAY);
this->detach();
#endif
}
}
#endif
/*
Copyright (c) 2013 Arduino LLC. 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
*/
/*
* Defines for 16 bit timers used with Servo library
*
* If _useTimerX is defined then TimerX is a 16 bit timer on the current board
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
* _Nbr_16timers indicates how many 16 bit timers are available.
*/
/**
* AVR Only definitions
* --------------------
*/
// Say which 16 bit timers can be used and in what order
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define _useTimer5
#define _useTimer3
#define _useTimer4
typedef enum { _timer5, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t;
#elif defined(__AVR_ATmega32U4__)
#define _useTimer3
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t;
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#define _useTimer3
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t;
#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
#define _useTimer3
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t;
#else // everything else
typedef enum { _Nbr_16timers } timer16_Sequence_t;
#endif
/*
Copyright (c) 2013 Arduino LLC. 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
*/
#include "../../base.h"
#if HAS(SERVOS)
#include <avr/interrupt.h>
#include <Arduino.h>
#include "servo.h"
#define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009
#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
static servo_t servos[MAX_SERVOS]; // static array of servo structures
uint8_t ServoCount = 0; // the total number of attached servos
static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
// convenience macros
#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
#define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
/************ static functions common to all instances ***********************/
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
{
if( Channel[timer] < 0 )
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
else{
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
}
Channel[timer]++; // increment to the next channel
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
*OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
}
else {
// finished all channels so wait for the refresh period to expire before starting over
if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
else
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
}
}
#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
// Interrupt handlers for Arduino
#if defined(_useTimer1)
SIGNAL (TIMER1_COMPA_vect)
{
handle_interrupts(_timer1, &TCNT1, &OCR1A);
}
#endif
#if defined(_useTimer3)
SIGNAL (TIMER3_COMPA_vect)
{
handle_interrupts(_timer3, &TCNT3, &OCR3A);
}
#endif
#if defined(_useTimer4)
SIGNAL (TIMER4_COMPA_vect)
{
handle_interrupts(_timer4, &TCNT4, &OCR4A);
}
#endif
#if defined(_useTimer5)
SIGNAL (TIMER5_COMPA_vect)
{
handle_interrupts(_timer5, &TCNT5, &OCR5A);
}
#endif
#elif defined WIRING
// Interrupt handlers for Wiring
#if defined(_useTimer1)
void Timer1Service()
{
handle_interrupts(_timer1, &TCNT1, &OCR1A);
}
#endif
#if defined(_useTimer3)
void Timer3Service()
{
handle_interrupts(_timer3, &TCNT3, &OCR3A);
}
#endif
#endif
static void initISR(timer16_Sequence_t timer)
{
#if defined (_useTimer1)
if(timer == _timer1) {
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
TIFR |= _BV(OCF1A); // clear any pending interrupts;
TIMSK |= _BV(OCIE1A) ; // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
#endif
#if defined(WIRING)
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif
#if defined (_useTimer3)
if(timer == _timer3) {
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#if defined(__AVR_ATmega128__)
TIFR |= _BV(OCF3A); // clear any pending interrupts;
ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt
#else
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt
#endif
#if defined(WIRING)
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
}
#endif
#if defined (_useTimer4)
if(timer == _timer4) {
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt
}
#endif
#if defined (_useTimer5)
if(timer == _timer5) {
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt
}
#endif
}
static void finISR(timer16_Sequence_t timer)
{
//disable use of the given timer
#if defined WIRING // Wiring
if(timer == _timer1) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
TIMSK1 &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
#else
TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
#endif
timerDetach(TIMER1OUTCOMPAREA_INT);
}
else if(timer == _timer3) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
TIMSK3 &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
#else
ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
#endif
timerDetach(TIMER3OUTCOMPAREA_INT);
}
#else
//For arduino - in future: call here to a currently undefined function to reset the timer
#endif
}
static boolean isTimerActive(timer16_Sequence_t timer)
{
// returns true if any servo is active on this timer
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
if(SERVO(timer,channel).Pin.isActive == true)
return true;
}
return false;
}
/****************** end of static functions ******************************/
Servo::Servo()
{
if (ServoCount < MAX_SERVOS) {
this->servoIndex = ServoCount++; // assign a servo index to this instance
servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values
}
else {
this->servoIndex = INVALID_SERVO; // too many servos
}
}
uint8_t Servo::attach(int pin)
{
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
}
uint8_t Servo::attach(int pin, int min, int max)
{
timer16_Sequence_t timer;
if (this->servoIndex < MAX_SERVOS) {
pinMode(pin, OUTPUT); // set servo pin to output
servos[this->servoIndex].Pin.nbr = pin;
// todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
this->max = (MAX_PULSE_WIDTH - max)/4;
// initialize the timer if it has not already been initialized
timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (isTimerActive(timer) == false) {
initISR(timer);
}
servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
}
return this->servoIndex;
}
void Servo::detach()
{
timer16_Sequence_t timer;
servos[this->servoIndex].Pin.isActive = false;
timer = SERVO_INDEX_TO_TIMER(servoIndex);
if(isTimerActive(timer) == false) {
finISR(timer);
}
}
void Servo::write(int value)
{
// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < MIN_PULSE_WIDTH)
{
if (value < 0)
value = 0;
else if (value > 180)
value = 180;
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
}
writeMicroseconds(value);
}
void Servo::writeMicroseconds(int value)
{
// calculate and store the values for the given channel
byte channel = this->servoIndex;
if( (channel < MAX_SERVOS) ) // ensure channel is valid
{
if (value < SERVO_MIN()) // ensure pulse width is valid
value = SERVO_MIN();
else if (value > SERVO_MAX())
value = SERVO_MAX();
value = value - TRIM_DURATION;
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead
uint8_t oldSREG = SREG;
cli();
servos[channel].ticks = value;
SREG = oldSREG;
}
}
int Servo::read() // return the value as degrees
{
return map(readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
}
int Servo::readMicroseconds()
{
unsigned int pulsewidth;
if (this->servoIndex != INVALID_SERVO)
pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION;
else
pulsewidth = 0;
return pulsewidth;
}
bool Servo::attached()
{
return servos[this->servoIndex].Pin.isActive;
}
#endif
......@@ -18,84 +18,55 @@
*/
/*
A servo is activated by creating an instance of the Servo class passing
the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently
written using the write() method.
A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently written using the write() method
Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
The sequence used to seize timers is defined in timers.h
Note that analogWrite of PWM on pins associated with the timer are
disabled when the first servo is attached.
Timers are seized as needed in groups of 12 servos - 24 servos use two
timers, 48 servos will use four.
The sequence used to sieze timers is defined in timers.h
The methods are:
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin ) - Attaches a servo motor to an i/o pin.
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
default min is 544, max is 2400
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
move(angle) - Sequence of attach(0), write(angle),
With DEACTIVATE_SERVOS_AFTER_MOVE wait SERVO_DEACTIVATION_DELAY and detach.
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin ) - Attaches a servo motor to an i/o pin.
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
default min is 544, max is 2400
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
*/
#ifndef SERVO_H
#define SERVO_H
#include <inttypes.h>
/*
* Defines for 16 bit timers used with Servo library
*
* If _useTimerX is defined then TimerX is a 16 bit timer on the current board
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
* _Nbr_16timers indicates how many 16 bit timers are available.
*
*/
// Say which 16 bit timers can be used and in what order
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define _useTimer5
//#define _useTimer1
#define _useTimer3
#define _useTimer4
//typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ;
typedef enum { _timer5, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ;
#elif defined(__AVR_ATmega32U4__)
//#define _useTimer1
#define _useTimer3
//typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ;
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#define _useTimer3
//#define _useTimer1
//typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__) ||defined(__AVR_ATmega2561__)
#define _useTimer3
//#define _useTimer1
//typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
#else // everything else
//#define _useTimer1
//typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ;
typedef enum { _Nbr_16timers } timer16_Sequence_t ;
#endif
// Architecture specific include
#include "ServoTimers.h"
#define Servo_VERSION 2 // software version of this library
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
......@@ -109,28 +80,25 @@ typedef struct {
typedef struct {
ServoPin_t Pin;
unsigned int ticks;
} ServoInfo_t;
class Servo {
public:
Servo();
int8_t attach(int pin); // attach the given pin to the next free channel, set pinMode, return channel number (-1 on fail)
int8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
void detach();
void write(int value); // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // write pulse width in microseconds
void move(int value); // attach the servo, then move to value
// if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
// if DEACTIVATE_SERVOS_AFTER_MOVE wait SERVO_DEACTIVATION_DELAY, then detach
int read(); // returns current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
bool attached(); // return true if this servo is attached, otherwise false
private:
uint8_t servoIndex; // index into the channel data for this servo
int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
volatile unsigned int ticks;
} servo_t;
class Servo
{
public:
Servo();
uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
void detach();
void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // returns current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
bool attached(); // return true if this servo is attached, otherwise false
private:
uint8_t servoIndex; // index into the channel data for this servo
int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
};
#endif
......@@ -18,28 +18,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
#include "ultralcd.h"
#include "nextion_lcd.h"
#include "planner.h"
#include "stepper_indirection.h"
#if MB(ALLIGATOR)
#include "external_dac.h"
#endif
#include "stepper.h"
#include "../../base.h"
#include "temperature.h"
#include "thermistortables.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#endif
#if ENABLED(SDSUPPORT)
#include "Sd2PinMap.h"
#endif
//===========================================================================
//================================== macros =================================
......@@ -203,7 +183,7 @@ static void updateTemperaturesFromRawValues();
#endif
#if ENABLED(FILAMENT_SENSOR)
static int meas_shift_index; //used to point to a delayed sample in buffer for filament width sensor
static int meas_shift_index; // used to point to a delayed sample in buffer for filament width sensor
#endif
#if ENABLED(HEATER_0_USES_MAX6675)
......@@ -276,7 +256,7 @@ void autotempShutdown() {
if (temp_meas_ready) { // temp sample ready
updateTemperaturesFromRawValues();
input = (hotend<0)?current_temperature_bed:current_temperature[hotend];
input = (hotend < 0) ? current_temperature_bed:current_temperature[hotend];
max = max(max, input);
min = min(min, input);
......@@ -308,7 +288,7 @@ void autotempShutdown() {
t_low = t2 - t1;
if (cycles > 0) {
long max_pow = hotend < 0 ? MAX_BED_POWER : PID_MAX;
bias += (d*(t_high - t_low))/(t_low + t_high);
bias += (d * (t_high - t_low)) / (t_low + t_high);
bias = constrain(bias, 20, max_pow - 20);
d = (bias > max_pow / 2) ? max_pow - 1 - bias : bias;
......@@ -489,7 +469,7 @@ inline void _temp_error(int h, const char* serial_msg, const char* lcd_msg) {
static bool killed = false;
if (IsRunning()) {
ECHO_S(ER);
PS_PGM(serial_msg);
Com::printF(serial_msg);
ECHO_M(SERIAL_STOPPED_HEATER);
if (h >= 0) ECHO_EV((int)h); else ECHO_EM(SERIAL_HEATER_BED);
#if ENABLED(ULTRA_LCD)
......@@ -810,7 +790,11 @@ static float analog2temp(int raw, uint8_t h) {
}
#if HEATER_USES_AD595
return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * ad595_gain[h]) + ad595_offset[h];
#ifdef __SAM3X8E__
return ((raw * ((3.3 * 100.0) / 1024.0) / OVERSAMPLENR) * ad595_gain[h]) + ad595_offset[h];
#else
return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * ad595_gain[h]) + ad595_offset[h];
#endif
#else
return 0;
#endif
......@@ -839,9 +823,11 @@ static float analog2tempBed(int raw) {
return celsius;
#elif ENABLED(BED_USES_AD595)
return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
#ifdef __SAM3X8E__
return ((raw * ((3.3 * 100.0) / 1024.0) / OVERSAMPLENR) * ad595_gain[h]) + ad595_offset[h];
#else
return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
#endif
#else
UNUSED(raw);
return 0;
......
#include "../base.h"
#include "../../base.h"
#if ENABLED(USE_WATCHDOG)
......@@ -24,8 +24,7 @@ void watchdog_init() {
// Watchdog timer interrupt, called if main program blocks >1sec and manual reset is enabled.
#if ENABLED(WATCHDOG_RESET_MANUAL)
ISR(WDT_vect) {
SERIAL_ERROR_START;
SERIAL_ERRORLNPGM("Something is wrong, please turn off the printer.");
ECHO_LM(ER, "Something is wrong, please turn off the printer.");
kill(PSTR("ERR:Please Reset")); //kill blocks //16 characters so it fits on a 16x2 display
while (1); //wait for user or serial reset
}
......
#include "../base.h"
#ifndef WATCHDOG_H
#define WATCHDOG_H
#include "Marlin_main.h"
#include <avr/wdt.h>
// Initialize watchdog with a 4 second interrupt time
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment