style
This commit is contained in:
parent
27e860e945
commit
11f1a44d40
|
|
@ -6,23 +6,23 @@
|
||||||
#ifdef BLINKM
|
#ifdef BLINKM
|
||||||
|
|
||||||
#if (ARDUINO >= 100)
|
#if (ARDUINO >= 100)
|
||||||
# include "Arduino.h"
|
# include "Arduino.h"
|
||||||
#else
|
#else
|
||||||
# include "WProgram.h"
|
# include "WProgram.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "BlinkM.h"
|
#include "BlinkM.h"
|
||||||
|
|
||||||
void SendColors(byte red, byte grn, byte blu)
|
void SendColors(byte red, byte grn, byte blu)
|
||||||
{
|
{
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
Wire.beginTransmission(0x09);
|
Wire.beginTransmission(0x09);
|
||||||
Wire.write('o'); //to disable ongoing script, only needs to be used once
|
Wire.write('o'); //to disable ongoing script, only needs to be used once
|
||||||
Wire.write('n');
|
Wire.write('n');
|
||||||
Wire.write(red);
|
Wire.write(red);
|
||||||
Wire.write(grn);
|
Wire.write(grn);
|
||||||
Wire.write(blu);
|
Wire.write(blu);
|
||||||
Wire.endTransmission();
|
Wire.endTransmission();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //BLINKM
|
#endif //BLINKM
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
Library header file for BlinkM library
|
Library header file for BlinkM library
|
||||||
*/
|
*/
|
||||||
#if (ARDUINO >= 100)
|
#if (ARDUINO >= 100)
|
||||||
# include "Arduino.h"
|
# include "Arduino.h"
|
||||||
#else
|
#else
|
||||||
# include "WProgram.h"
|
# include "WProgram.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Wire.h"
|
#include "Wire.h"
|
||||||
|
|
|
||||||
|
|
@ -128,14 +128,14 @@
|
||||||
#define BANG_MAX 255 // limits current to nozzle while in bang-bang mode; 255=full current
|
#define BANG_MAX 255 // limits current to nozzle while in bang-bang mode; 255=full current
|
||||||
#define PID_MAX BANG_MAX // limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
|
#define PID_MAX BANG_MAX // limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
//#define PID_DEBUG // Sends debug data to the serial port.
|
//#define PID_DEBUG // Sends debug data to the serial port.
|
||||||
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
|
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
|
||||||
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
|
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
|
||||||
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
|
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
|
||||||
// is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
|
// is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
|
||||||
#define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term
|
#define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term
|
||||||
#define K1 0.95 //smoothing factor within the PID
|
#define K1 0.95 //smoothing factor within the PID
|
||||||
#define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine
|
#define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine
|
||||||
|
|
||||||
// If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it
|
// If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it
|
||||||
// Ultimaker
|
// Ultimaker
|
||||||
|
|
@ -215,22 +215,22 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
||||||
#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
|
#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
|
||||||
|
|
||||||
#ifndef ENDSTOPPULLUPS
|
#ifndef ENDSTOPPULLUPS
|
||||||
// fine endstop settings: Individual pullups. will be ignored if ENDSTOPPULLUPS is defined
|
// fine endstop settings: Individual pullups. will be ignored if ENDSTOPPULLUPS is defined
|
||||||
// #define ENDSTOPPULLUP_XMAX
|
// #define ENDSTOPPULLUP_XMAX
|
||||||
// #define ENDSTOPPULLUP_YMAX
|
// #define ENDSTOPPULLUP_YMAX
|
||||||
// #define ENDSTOPPULLUP_ZMAX
|
// #define ENDSTOPPULLUP_ZMAX
|
||||||
// #define ENDSTOPPULLUP_XMIN
|
// #define ENDSTOPPULLUP_XMIN
|
||||||
// #define ENDSTOPPULLUP_YMIN
|
// #define ENDSTOPPULLUP_YMIN
|
||||||
// #define ENDSTOPPULLUP_ZMIN
|
// #define ENDSTOPPULLUP_ZMIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENDSTOPPULLUPS
|
#ifdef ENDSTOPPULLUPS
|
||||||
#define ENDSTOPPULLUP_XMAX
|
#define ENDSTOPPULLUP_XMAX
|
||||||
#define ENDSTOPPULLUP_YMAX
|
#define ENDSTOPPULLUP_YMAX
|
||||||
#define ENDSTOPPULLUP_ZMAX
|
#define ENDSTOPPULLUP_ZMAX
|
||||||
#define ENDSTOPPULLUP_XMIN
|
#define ENDSTOPPULLUP_XMIN
|
||||||
#define ENDSTOPPULLUP_YMIN
|
#define ENDSTOPPULLUP_YMIN
|
||||||
#define ENDSTOPPULLUP_ZMIN
|
#define ENDSTOPPULLUP_ZMIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins.
|
// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins.
|
||||||
|
|
@ -243,7 +243,7 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
||||||
|
|
||||||
// Disable max endstops for compatibility with endstop checking routine
|
// Disable max endstops for compatibility with endstop checking routine
|
||||||
#if defined(COREXY) && !defined(DISABLE_MAX_ENDSTOPS)
|
#if defined(COREXY) && !defined(DISABLE_MAX_ENDSTOPS)
|
||||||
#define DISABLE_MAX_ENDSTOPS
|
#define DISABLE_MAX_ENDSTOPS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
|
// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
|
||||||
|
|
@ -300,58 +300,58 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
||||||
// Probe 3 arbitrary points on the bed (that aren't colinear)
|
// Probe 3 arbitrary points on the bed (that aren't colinear)
|
||||||
// You must specify the X & Y coordinates of all 3 points
|
// You must specify the X & Y coordinates of all 3 points
|
||||||
|
|
||||||
#define AUTO_BED_LEVELING_GRID
|
#define AUTO_BED_LEVELING_GRID
|
||||||
// with AUTO_BED_LEVELING_GRID, the bed is sampled in a
|
// with AUTO_BED_LEVELING_GRID, the bed is sampled in a
|
||||||
// AUTO_BED_LEVELING_GRID_POINTSxAUTO_BED_LEVELING_GRID_POINTS grid
|
// AUTO_BED_LEVELING_GRID_POINTSxAUTO_BED_LEVELING_GRID_POINTS grid
|
||||||
// and least squares solution is calculated
|
// and least squares solution is calculated
|
||||||
// Note: this feature occupies 10'206 byte
|
// Note: this feature occupies 10'206 byte
|
||||||
#ifdef AUTO_BED_LEVELING_GRID
|
#ifdef AUTO_BED_LEVELING_GRID
|
||||||
|
|
||||||
// set the rectangle in which to probe
|
// set the rectangle in which to probe
|
||||||
#define LEFT_PROBE_BED_POSITION 15
|
#define LEFT_PROBE_BED_POSITION 15
|
||||||
#define RIGHT_PROBE_BED_POSITION 170
|
#define RIGHT_PROBE_BED_POSITION 170
|
||||||
#define BACK_PROBE_BED_POSITION 180
|
#define BACK_PROBE_BED_POSITION 180
|
||||||
#define FRONT_PROBE_BED_POSITION 20
|
#define FRONT_PROBE_BED_POSITION 20
|
||||||
|
|
||||||
// set the number of grid points per dimension
|
// set the number of grid points per dimension
|
||||||
// I wouldn't see a reason to go above 3 (=9 probing points on the bed)
|
// I wouldn't see a reason to go above 3 (=9 probing points on the bed)
|
||||||
#define AUTO_BED_LEVELING_GRID_POINTS 2
|
#define AUTO_BED_LEVELING_GRID_POINTS 2
|
||||||
|
|
||||||
|
|
||||||
#else // not AUTO_BED_LEVELING_GRID
|
#else // not AUTO_BED_LEVELING_GRID
|
||||||
// with no grid, just probe 3 arbitrary points. A simple cross-product
|
// with no grid, just probe 3 arbitrary points. A simple cross-product
|
||||||
// is used to esimate the plane of the print bed
|
// is used to esimate the plane of the print bed
|
||||||
|
|
||||||
#define ABL_PROBE_PT_1_X 15
|
#define ABL_PROBE_PT_1_X 15
|
||||||
#define ABL_PROBE_PT_1_Y 180
|
#define ABL_PROBE_PT_1_Y 180
|
||||||
#define ABL_PROBE_PT_2_X 15
|
#define ABL_PROBE_PT_2_X 15
|
||||||
#define ABL_PROBE_PT_2_Y 20
|
#define ABL_PROBE_PT_2_Y 20
|
||||||
#define ABL_PROBE_PT_3_X 170
|
#define ABL_PROBE_PT_3_X 170
|
||||||
#define ABL_PROBE_PT_3_Y 20
|
#define ABL_PROBE_PT_3_Y 20
|
||||||
|
|
||||||
#endif // AUTO_BED_LEVELING_GRID
|
#endif // AUTO_BED_LEVELING_GRID
|
||||||
|
|
||||||
|
|
||||||
// these are the offsets to the probe relative to the extruder tip (Hotend - Probe)
|
// these are the offsets to the probe relative to the extruder tip (Hotend - Probe)
|
||||||
// X and Y offsets must be integers
|
// X and Y offsets must be integers
|
||||||
#define X_PROBE_OFFSET_FROM_EXTRUDER -25
|
#define X_PROBE_OFFSET_FROM_EXTRUDER -25
|
||||||
#define Y_PROBE_OFFSET_FROM_EXTRUDER -29
|
#define Y_PROBE_OFFSET_FROM_EXTRUDER -29
|
||||||
#define Z_PROBE_OFFSET_FROM_EXTRUDER -12.35
|
#define Z_PROBE_OFFSET_FROM_EXTRUDER -12.35
|
||||||
|
|
||||||
#define Z_RAISE_BEFORE_HOMING 4 // (in mm) Raise Z before homing (G28) for Probe Clearance.
|
#define Z_RAISE_BEFORE_HOMING 4 // (in mm) Raise Z before homing (G28) for Probe Clearance.
|
||||||
// Be sure you have this distance over your Z_MAX_POS in case
|
// Be sure you have this distance over your Z_MAX_POS in case
|
||||||
|
|
||||||
#define XY_TRAVEL_SPEED 8000 // X and Y axis travel speed between probes, in mm/min
|
#define XY_TRAVEL_SPEED 8000 // X and Y axis travel speed between probes, in mm/min
|
||||||
|
|
||||||
#define Z_RAISE_BEFORE_PROBING 15 //How much the extruder will be raised before traveling to the first probing point.
|
#define Z_RAISE_BEFORE_PROBING 15 //How much the extruder will be raised before traveling to the first probing point.
|
||||||
#define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when traveling from between next probing points
|
#define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when traveling from between next probing points
|
||||||
|
|
||||||
//#define Z_PROBE_SLED // turn on if you have a z-probe mounted on a sled like those designed by Charles Bell
|
//#define Z_PROBE_SLED // turn on if you have a z-probe mounted on a sled like those designed by Charles Bell
|
||||||
//#define SLED_DOCKING_OFFSET 5 // the extra distance the X axis must travel to pickup the sled. 0 should be fine but you can push it further if you'd like.
|
//#define SLED_DOCKING_OFFSET 5 // the extra distance the X axis must travel to pickup the sled. 0 should be fine but you can push it further if you'd like.
|
||||||
|
|
||||||
//If defined, the Probe servo will be turned on only during movement and then turned off to avoid jerk
|
//If defined, the Probe servo will be turned on only during movement and then turned off to avoid jerk
|
||||||
//The value is the delay to turn the servo off after powered on - depends on the servo speed; 300ms is good value, but you can try lower it.
|
//The value is the delay to turn the servo off after powered on - depends on the servo speed; 300ms is good value, but you can try lower it.
|
||||||
// You MUST HAVE the SERVO_ENDSTOPS defined to use here a value higher than zero otherwise your code will not compile.
|
// You MUST HAVE the SERVO_ENDSTOPS defined to use here a value higher than zero otherwise your code will not compile.
|
||||||
|
|
||||||
// #define PROBE_SERVO_DEACTIVATION_DELAY 300
|
// #define PROBE_SERVO_DEACTIVATION_DELAY 300
|
||||||
|
|
||||||
|
|
@ -359,42 +359,42 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
||||||
//If you have enabled the Bed Auto Leveling and are using the same Z Probe for Z Homing,
|
//If you have enabled the Bed Auto Leveling and are using the same Z Probe for Z Homing,
|
||||||
//it is highly recommended you let this Z_SAFE_HOMING enabled!
|
//it is highly recommended you let this Z_SAFE_HOMING enabled!
|
||||||
|
|
||||||
//#define Z_SAFE_HOMING // This feature is meant to avoid Z homing with probe outside the bed area.
|
//#define Z_SAFE_HOMING // This feature is meant to avoid Z homing with probe outside the bed area.
|
||||||
// When defined, it will:
|
// When defined, it will:
|
||||||
// - Allow Z homing only after X and Y homing AND stepper drivers still enabled
|
// - Allow Z homing only after X and Y homing AND stepper drivers still enabled
|
||||||
// - If stepper drivers timeout, it will need X and Y homing again before Z homing
|
// - If stepper drivers timeout, it will need X and Y homing again before Z homing
|
||||||
// - Position the probe in a defined XY point before Z Homing when homing all axis (G28)
|
// - Position the probe in a defined XY point before Z Homing when homing all axis (G28)
|
||||||
// - Block Z homing only when the probe is outside bed area.
|
// - Block Z homing only when the probe is outside bed area.
|
||||||
|
|
||||||
#ifdef Z_SAFE_HOMING
|
#ifdef Z_SAFE_HOMING
|
||||||
|
|
||||||
#define Z_SAFE_HOMING_X_POINT (X_MAX_LENGTH/2) // X point for Z homing when homing all axis (G28)
|
#define Z_SAFE_HOMING_X_POINT (X_MAX_LENGTH/2) // X point for Z homing when homing all axis (G28)
|
||||||
#define Z_SAFE_HOMING_Y_POINT (Y_MAX_LENGTH/2) // Y point for Z homing when homing all axis (G28)
|
#define Z_SAFE_HOMING_Y_POINT (Y_MAX_LENGTH/2) // Y point for Z homing when homing all axis (G28)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef AUTO_BED_LEVELING_GRID // Check if Probe_Offset * Grid Points is greater than Probing Range
|
#ifdef AUTO_BED_LEVELING_GRID // Check if Probe_Offset * Grid Points is greater than Probing Range
|
||||||
#if X_PROBE_OFFSET_FROM_EXTRUDER < 0
|
#if X_PROBE_OFFSET_FROM_EXTRUDER < 0
|
||||||
#if (-(X_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION))
|
#if (-(X_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION))
|
||||||
#error "The X axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
#error "The X axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if ((X_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION))
|
#if ((X_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION))
|
||||||
#error "The X axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
#error "The X axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if Y_PROBE_OFFSET_FROM_EXTRUDER < 0
|
#if Y_PROBE_OFFSET_FROM_EXTRUDER < 0
|
||||||
#if (-(Y_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION))
|
#if (-(Y_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION))
|
||||||
#error "The Y axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
#error "The Y axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if ((Y_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION))
|
#if ((Y_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION))
|
||||||
#error "The Y axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
#error "The Y axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // ENABLE_AUTO_BED_LEVELING
|
#endif // ENABLE_AUTO_BED_LEVELING
|
||||||
|
|
||||||
|
|
@ -426,9 +426,9 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
||||||
// Custom M code points
|
// Custom M code points
|
||||||
#define CUSTOM_M_CODES
|
#define CUSTOM_M_CODES
|
||||||
#ifdef CUSTOM_M_CODES
|
#ifdef CUSTOM_M_CODES
|
||||||
#define CUSTOM_M_CODE_SET_Z_PROBE_OFFSET 851
|
#define CUSTOM_M_CODE_SET_Z_PROBE_OFFSET 851
|
||||||
#define Z_PROBE_OFFSET_RANGE_MIN -15
|
#define Z_PROBE_OFFSET_RANGE_MIN -15
|
||||||
#define Z_PROBE_OFFSET_RANGE_MAX -5
|
#define Z_PROBE_OFFSET_RANGE_MAX -5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -515,17 +515,17 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
||||||
// (unsigned char*)EEPROM_CALIBRATION_STATUS
|
// (unsigned char*)EEPROM_CALIBRATION_STATUS
|
||||||
enum CalibrationStatus
|
enum CalibrationStatus
|
||||||
{
|
{
|
||||||
// Freshly assembled, needs to peform a self-test and the XYZ calibration.
|
// Freshly assembled, needs to peform a self-test and the XYZ calibration.
|
||||||
CALIBRATION_STATUS_ASSEMBLED = 255,
|
CALIBRATION_STATUS_ASSEMBLED = 255,
|
||||||
|
|
||||||
// For the wizard: self test has been performed, now the XYZ calibration is needed.
|
// For the wizard: self test has been performed, now the XYZ calibration is needed.
|
||||||
CALIBRATION_STATUS_XYZ_CALIBRATION = 250,
|
CALIBRATION_STATUS_XYZ_CALIBRATION = 250,
|
||||||
|
|
||||||
// For the wizard: factory assembled, needs to run Z calibration.
|
// For the wizard: factory assembled, needs to run Z calibration.
|
||||||
CALIBRATION_STATUS_Z_CALIBRATION = 240,
|
CALIBRATION_STATUS_Z_CALIBRATION = 240,
|
||||||
|
|
||||||
// The XYZ calibration has been performed, now it remains to run the V2Calibration.gcode.
|
// The XYZ calibration has been performed, now it remains to run the V2Calibration.gcode.
|
||||||
CALIBRATION_STATUS_LIVE_ADJUST = 230,
|
CALIBRATION_STATUS_LIVE_ADJUST = 230,
|
||||||
|
|
||||||
// Calibrated, ready to print.
|
// Calibrated, ready to print.
|
||||||
CALIBRATION_STATUS_CALIBRATED = 1,
|
CALIBRATION_STATUS_CALIBRATED = 1,
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,10 @@ static bool EEPROM_writeData(uint8_t* pos, uint8_t* value, uint8_t size, const c
|
||||||
#endif //DEBUG_EEPROM_WRITE
|
#endif //DEBUG_EEPROM_WRITE
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_EEPROM_WRITE
|
#ifdef DEBUG_EEPROM_WRITE
|
||||||
printf_P(PSTR("EEPROM_WRITE_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
|
printf_P(PSTR("EEPROM_WRITE_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
|
||||||
#endif //DEBUG_EEPROM_WRITE
|
#endif //DEBUG_EEPROM_WRITE
|
||||||
while (size--)
|
while (size--)
|
||||||
{
|
{
|
||||||
|
|
||||||
eeprom_update_byte(pos, *value);
|
eeprom_update_byte(pos, *value);
|
||||||
if (eeprom_read_byte(pos) != *value) {
|
if (eeprom_read_byte(pos) != *value) {
|
||||||
|
|
@ -38,9 +38,9 @@ static bool EEPROM_writeData(uint8_t* pos, uint8_t* value, uint8_t size, const c
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos++;
|
pos++;
|
||||||
value++;
|
value++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ static void EEPROM_readData(uint8_t* pos, uint8_t* value, uint8_t size, const ch
|
||||||
#endif //DEBUG_EEPROM_READ
|
#endif //DEBUG_EEPROM_READ
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_EEPROM_READ
|
#ifdef DEBUG_EEPROM_READ
|
||||||
printf_P(PSTR("EEPROM_READ_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
|
printf_P(PSTR("EEPROM_READ_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
|
||||||
#endif //DEBUG_EEPROM_READ
|
#endif //DEBUG_EEPROM_READ
|
||||||
while(size--)
|
while(size--)
|
||||||
{
|
{
|
||||||
|
|
@ -66,102 +66,102 @@ static void EEPROM_readData(uint8_t* pos, uint8_t* value, uint8_t size, const ch
|
||||||
#ifdef EEPROM_SETTINGS
|
#ifdef EEPROM_SETTINGS
|
||||||
void Config_StoreSettings()
|
void Config_StoreSettings()
|
||||||
{
|
{
|
||||||
strcpy(cs.version,"000"); //!< invalidate data first @TODO use erase to save one erase cycle
|
strcpy(cs.version,"000"); //!< invalidate data first @TODO use erase to save one erase cycle
|
||||||
|
|
||||||
if (EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base),reinterpret_cast<uint8_t*>(&cs),sizeof(cs),0), "cs, invalid version")
|
if (EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base),reinterpret_cast<uint8_t*>(&cs),sizeof(cs),0), "cs, invalid version")
|
||||||
{
|
{
|
||||||
strcpy(cs.version,EEPROM_VERSION); //!< validate data if write succeed
|
strcpy(cs.version,EEPROM_VERSION); //!< validate data if write succeed
|
||||||
EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), reinterpret_cast<uint8_t*>(cs.version), sizeof(cs.version), "cs.version valid");
|
EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), reinterpret_cast<uint8_t*>(cs.version), sizeof(cs.version), "cs.version valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNPGM("Settings Stored");
|
SERIAL_ECHOLNPGM("Settings Stored");
|
||||||
}
|
}
|
||||||
#endif //EEPROM_SETTINGS
|
#endif //EEPROM_SETTINGS
|
||||||
|
|
||||||
|
|
||||||
#ifndef DISABLE_M503
|
#ifndef DISABLE_M503
|
||||||
void Config_PrintSettings(uint8_t level)
|
void Config_PrintSettings(uint8_t level)
|
||||||
{ // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
|
{ // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
|
||||||
#ifdef TMC2130
|
#ifdef TMC2130
|
||||||
printf_P(PSTR(
|
printf_P(PSTR(
|
||||||
"%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
|
"%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||||
"%SMaximum feedrates - normal (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
"%SMaximum feedrates - normal (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||||
"%SMaximum feedrates - stealth (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
"%SMaximum feedrates - stealth (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||||
"%SMaximum acceleration - normal (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
"%SMaximum acceleration - normal (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
||||||
"%SMaximum acceleration - stealth (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
"%SMaximum acceleration - stealth (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
||||||
"%SAcceleration: S=acceleration, T=retract acceleration\n%S M204 S%.2f T%.2f\n"
|
"%SAcceleration: S=acceleration, T=retract acceleration\n%S M204 S%.2f T%.2f\n"
|
||||||
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
|
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||||
"%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
|
"%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
|
||||||
),
|
),
|
||||||
echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
|
echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
|
||||||
echomagic, echomagic, cs.max_feedrate_normal[X_AXIS], cs.max_feedrate_normal[Y_AXIS], cs.max_feedrate_normal[Z_AXIS], cs.max_feedrate_normal[E_AXIS],
|
echomagic, echomagic, cs.max_feedrate_normal[X_AXIS], cs.max_feedrate_normal[Y_AXIS], cs.max_feedrate_normal[Z_AXIS], cs.max_feedrate_normal[E_AXIS],
|
||||||
echomagic, echomagic, cs.max_feedrate_silent[X_AXIS], cs.max_feedrate_silent[Y_AXIS], cs.max_feedrate_silent[Z_AXIS], cs.max_feedrate_silent[E_AXIS],
|
echomagic, echomagic, cs.max_feedrate_silent[X_AXIS], cs.max_feedrate_silent[Y_AXIS], cs.max_feedrate_silent[Z_AXIS], cs.max_feedrate_silent[E_AXIS],
|
||||||
echomagic, echomagic, cs.max_acceleration_units_per_sq_second_normal[X_AXIS], cs.max_acceleration_units_per_sq_second_normal[Y_AXIS], cs.max_acceleration_units_per_sq_second_normal[Z_AXIS], cs.max_acceleration_units_per_sq_second_normal[E_AXIS],
|
echomagic, echomagic, cs.max_acceleration_units_per_sq_second_normal[X_AXIS], cs.max_acceleration_units_per_sq_second_normal[Y_AXIS], cs.max_acceleration_units_per_sq_second_normal[Z_AXIS], cs.max_acceleration_units_per_sq_second_normal[E_AXIS],
|
||||||
echomagic, echomagic, cs.max_acceleration_units_per_sq_second_silent[X_AXIS], cs.max_acceleration_units_per_sq_second_silent[Y_AXIS], cs.max_acceleration_units_per_sq_second_silent[Z_AXIS], cs.max_acceleration_units_per_sq_second_silent[E_AXIS],
|
echomagic, echomagic, cs.max_acceleration_units_per_sq_second_silent[X_AXIS], cs.max_acceleration_units_per_sq_second_silent[Y_AXIS], cs.max_acceleration_units_per_sq_second_silent[Z_AXIS], cs.max_acceleration_units_per_sq_second_silent[E_AXIS],
|
||||||
echomagic, echomagic, cs.acceleration, cs.retract_acceleration,
|
echomagic, echomagic, cs.acceleration, cs.retract_acceleration,
|
||||||
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
||||||
echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
|
echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
|
||||||
#else //TMC2130
|
#else //TMC2130
|
||||||
printf_P(PSTR(
|
printf_P(PSTR(
|
||||||
"%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
|
"%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||||
"%SMaximum feedrates (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
"%SMaximum feedrates (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||||
"%SMaximum acceleration (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
"%SMaximum acceleration (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
||||||
"%SAcceleration: S=acceleration, T=retract acceleration\n%S M204 S%.2f T%.2f\n"
|
"%SAcceleration: S=acceleration, T=retract acceleration\n%S M204 S%.2f T%.2f\n"
|
||||||
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
|
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||||
"%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
|
"%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
|
||||||
),
|
),
|
||||||
echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
|
echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
|
||||||
echomagic, echomagic, max_feedrate[X_AXIS], max_feedrate[Y_AXIS], max_feedrate[Z_AXIS], max_feedrate[E_AXIS],
|
echomagic, echomagic, max_feedrate[X_AXIS], max_feedrate[Y_AXIS], max_feedrate[Z_AXIS], max_feedrate[E_AXIS],
|
||||||
echomagic, echomagic, max_acceleration_units_per_sq_second[X_AXIS], max_acceleration_units_per_sq_second[Y_AXIS], max_acceleration_units_per_sq_second[Z_AXIS], max_acceleration_units_per_sq_second[E_AXIS],
|
echomagic, echomagic, max_acceleration_units_per_sq_second[X_AXIS], max_acceleration_units_per_sq_second[Y_AXIS], max_acceleration_units_per_sq_second[Z_AXIS], max_acceleration_units_per_sq_second[E_AXIS],
|
||||||
echomagic, echomagic, cs.acceleration, cs.retract_acceleration,
|
echomagic, echomagic, cs.acceleration, cs.retract_acceleration,
|
||||||
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
||||||
echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
|
echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
|
||||||
#endif //TMC2130
|
#endif //TMC2130
|
||||||
);
|
);
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
printf_P(PSTR("%SPID settings:\n%S M301 P%.2f I%.2f D%.2f\n"),
|
printf_P(PSTR("%SPID settings:\n%S M301 P%.2f I%.2f D%.2f\n"),
|
||||||
echomagic, echomagic, cs.Kp, unscalePID_i(cs.Ki), unscalePID_d(cs.Kd));
|
echomagic, echomagic, cs.Kp, unscalePID_i(cs.Ki), unscalePID_d(cs.Kd));
|
||||||
#endif
|
#endif
|
||||||
#ifdef PIDTEMPBED
|
#ifdef PIDTEMPBED
|
||||||
printf_P(PSTR("%SPID heatbed settings:\n%S M304 P%.2f I%.2f D%.2f\n"),
|
printf_P(PSTR("%SPID heatbed settings:\n%S M304 P%.2f I%.2f D%.2f\n"),
|
||||||
echomagic, echomagic, cs.bedKp, unscalePID_i(cs.bedKi), unscalePID_d(cs.bedKd));
|
echomagic, echomagic, cs.bedKp, unscalePID_i(cs.bedKi), unscalePID_d(cs.bedKd));
|
||||||
#endif
|
#endif
|
||||||
#ifdef FWRETRACT
|
#ifdef FWRETRACT
|
||||||
printf_P(PSTR(
|
printf_P(PSTR(
|
||||||
"%SRetract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)\n%S M207 S%.2f F%.2f Z%.2f\n"
|
"%SRetract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)\n%S M207 S%.2f F%.2f Z%.2f\n"
|
||||||
"%SRecover: S=Extra length (mm) F:Speed (mm/m)\n%S M208 S%.2f F%.2f\n"
|
"%SRecover: S=Extra length (mm) F:Speed (mm/m)\n%S M208 S%.2f F%.2f\n"
|
||||||
"%SAuto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries\n%S M209 S%d\n"
|
"%SAuto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries\n%S M209 S%d\n"
|
||||||
),
|
),
|
||||||
echomagic, echomagic, cs.retract_length, cs.retract_feedrate*60, cs.retract_zlift,
|
echomagic, echomagic, cs.retract_length, cs.retract_feedrate*60, cs.retract_zlift,
|
||||||
echomagic, echomagic, cs.retract_recover_length, cs.retract_recover_feedrate*60,
|
echomagic, echomagic, cs.retract_recover_length, cs.retract_recover_feedrate*60,
|
||||||
echomagic, echomagic, (cs.autoretract_enabled ? 1 : 0)
|
echomagic, echomagic, (cs.autoretract_enabled ? 1 : 0)
|
||||||
);
|
);
|
||||||
#if EXTRUDERS > 1
|
#if EXTRUDERS > 1
|
||||||
printf_P(PSTR("%SMulti-extruder settings:\n%S Swap retract length (mm): %.2f\n%S Swap rec. addl. length (mm): %.2f\n"),
|
printf_P(PSTR("%SMulti-extruder settings:\n%S Swap retract length (mm): %.2f\n%S Swap rec. addl. length (mm): %.2f\n"),
|
||||||
echomagic, echomagic, retract_length_swap, echomagic, retract_recover_length_swap);
|
echomagic, echomagic, retract_length_swap, echomagic, retract_recover_length_swap);
|
||||||
#endif
|
#endif
|
||||||
if (cs.volumetric_enabled) {
|
if (cs.volumetric_enabled) {
|
||||||
printf_P(PSTR("%SFilament settings:\n%S M200 D%.2f\n"),
|
printf_P(PSTR("%SFilament settings:\n%S M200 D%.2f\n"),
|
||||||
echomagic, echomagic, cs.filament_size[0]);
|
echomagic, echomagic, cs.filament_size[0]);
|
||||||
#if EXTRUDERS > 1
|
#if EXTRUDERS > 1
|
||||||
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
||||||
echomagic, echomagic, cs.filament_size[1]);
|
echomagic, echomagic, cs.filament_size[1]);
|
||||||
#if EXTRUDERS > 2
|
#if EXTRUDERS > 2
|
||||||
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
||||||
echomagic, echomagic, cs.filament_size[2]);
|
echomagic, echomagic, cs.filament_size[2]);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
printf_P(PSTR("%SFilament settings: Disabled\n"), echomagic);
|
printf_P(PSTR("%SFilament settings: Disabled\n"), echomagic);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (level >= 10) {
|
if (level >= 10) {
|
||||||
#ifdef LIN_ADVANCE
|
#ifdef LIN_ADVANCE
|
||||||
printf_P(PSTR("%SLinear advance settings:\n M900 K%.2f E/D = %.2f\n"),
|
printf_P(PSTR("%SLinear advance settings:\n M900 K%.2f E/D = %.2f\n"),
|
||||||
echomagic, extruder_advance_k, advance_ed_ratio);
|
echomagic, extruder_advance_k, advance_ed_ratio);
|
||||||
#endif //LIN_ADVANCE
|
#endif //LIN_ADVANCE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -170,17 +170,17 @@ void Config_PrintSettings(uint8_t level)
|
||||||
|
|
||||||
static_assert (EXTRUDERS == 1, "ConfigurationStore M500_conf not implemented for more extruders, fix filament_size array size.");
|
static_assert (EXTRUDERS == 1, "ConfigurationStore M500_conf not implemented for more extruders, fix filament_size array size.");
|
||||||
static_assert (NUM_AXIS == 4, "ConfigurationStore M500_conf not implemented for more axis."
|
static_assert (NUM_AXIS == 4, "ConfigurationStore M500_conf not implemented for more axis."
|
||||||
"Fix axis_steps_per_unit max_feedrate_normal max_acceleration_units_per_sq_second_normal max_jerk max_feedrate_silent"
|
"Fix axis_steps_per_unit max_feedrate_normal max_acceleration_units_per_sq_second_normal max_jerk max_feedrate_silent"
|
||||||
" max_acceleration_units_per_sq_second_silent array size.");
|
" max_acceleration_units_per_sq_second_silent array size.");
|
||||||
#ifdef ENABLE_AUTO_BED_LEVELING
|
#ifdef ENABLE_AUTO_BED_LEVELING
|
||||||
static_assert (false, "zprobe_zoffset was not initialized in printers in field to -(Z_PROBE_OFFSET_FROM_EXTRUDER), so it contains"
|
static_assert (false, "zprobe_zoffset was not initialized in printers in field to -(Z_PROBE_OFFSET_FROM_EXTRUDER), so it contains"
|
||||||
"0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf");
|
"0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static_assert (sizeof(M500_conf) == 188, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
|
static_assert (sizeof(M500_conf) == 188, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
|
||||||
"or if you added members in the end of struct, ensure that historically uninitialized values will be initialized."
|
"or if you added members in the end of struct, ensure that historically uninitialized values will be initialized."
|
||||||
"If this is caused by change to more then 8bit processor, decide whether make this struct packed to save EEPROM,"
|
"If this is caused by change to more then 8bit processor, decide whether make this struct packed to save EEPROM,"
|
||||||
"leave as it is to keep fast code, or reorder struct members to pack more tightly.");
|
"leave as it is to keep fast code, or reorder struct members to pack more tightly.");
|
||||||
|
|
||||||
static const M500_conf default_conf PROGMEM =
|
static const M500_conf default_conf PROGMEM =
|
||||||
{
|
{
|
||||||
|
|
@ -210,11 +210,11 @@ static const M500_conf default_conf PROGMEM =
|
||||||
RETRACT_RECOVER_LENGTH,
|
RETRACT_RECOVER_LENGTH,
|
||||||
RETRACT_RECOVER_FEEDRATE,
|
RETRACT_RECOVER_FEEDRATE,
|
||||||
false,
|
false,
|
||||||
{DEFAULT_NOMINAL_FILAMENT_DIA,
|
{ DEFAULT_NOMINAL_FILAMENT_DIA,
|
||||||
#if EXTRUDERS > 1
|
#if EXTRUDERS > 1
|
||||||
DEFAULT_NOMINAL_FILAMENT_DIA,
|
DEFAULT_NOMINAL_FILAMENT_DIA,
|
||||||
#if EXTRUDERS > 2
|
#if EXTRUDERS > 2
|
||||||
DEFAULT_NOMINAL_FILAMENT_DIA,
|
DEFAULT_NOMINAL_FILAMENT_DIA,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
|
|
@ -227,7 +227,7 @@ static const M500_conf default_conf PROGMEM =
|
||||||
//! @retval false Failed. Default settings has been retrieved, because of older version or corrupted data.
|
//! @retval false Failed. Default settings has been retrieved, because of older version or corrupted data.
|
||||||
bool Config_RetrieveSettings()
|
bool Config_RetrieveSettings()
|
||||||
{
|
{
|
||||||
bool previous_settings_retrieved = true;
|
bool previous_settings_retrieved = true;
|
||||||
char ver[4]=EEPROM_VERSION;
|
char ver[4]=EEPROM_VERSION;
|
||||||
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), reinterpret_cast<uint8_t*>(cs.version), sizeof(cs.version), "cs.version"); //read stored version
|
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), reinterpret_cast<uint8_t*>(cs.version), sizeof(cs.version), "cs.version"); //read stored version
|
||||||
// SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << cs.version << "]");
|
// SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << cs.version << "]");
|
||||||
|
|
@ -237,12 +237,12 @@ bool Config_RetrieveSettings()
|
||||||
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base), reinterpret_cast<uint8_t*>(&cs), sizeof(cs), "cs");
|
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base), reinterpret_cast<uint8_t*>(&cs), sizeof(cs), "cs");
|
||||||
|
|
||||||
|
|
||||||
if (cs.max_jerk[X_AXIS] > DEFAULT_XJERK) cs.max_jerk[X_AXIS] = DEFAULT_XJERK;
|
if (cs.max_jerk[X_AXIS] > DEFAULT_XJERK) cs.max_jerk[X_AXIS] = DEFAULT_XJERK;
|
||||||
if (cs.max_jerk[Y_AXIS] > DEFAULT_YJERK) cs.max_jerk[Y_AXIS] = DEFAULT_YJERK;
|
if (cs.max_jerk[Y_AXIS] > DEFAULT_YJERK) cs.max_jerk[Y_AXIS] = DEFAULT_YJERK;
|
||||||
calculate_extruder_multipliers();
|
calculate_extruder_multipliers();
|
||||||
|
|
||||||
|
|
||||||
//if max_feedrate_silent and max_acceleration_units_per_sq_second_silent were never stored to eeprom, use default values:
|
//if max_feedrate_silent and max_acceleration_units_per_sq_second_silent were never stored to eeprom, use default values:
|
||||||
{
|
{
|
||||||
const uint32_t erased = 0xffffffff;
|
const uint32_t erased = 0xffffffff;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
@ -258,47 +258,47 @@ bool Config_RetrieveSettings()
|
||||||
{
|
{
|
||||||
memcpy_P(&cs.max_feedrate_silent,&default_conf.max_feedrate_silent, sizeof(cs.max_feedrate_silent));
|
memcpy_P(&cs.max_feedrate_silent,&default_conf.max_feedrate_silent, sizeof(cs.max_feedrate_silent));
|
||||||
memcpy_P(&cs.max_acceleration_units_per_sq_second_silent,&default_conf.max_acceleration_units_per_sq_second_silent,
|
memcpy_P(&cs.max_acceleration_units_per_sq_second_silent,&default_conf.max_acceleration_units_per_sq_second_silent,
|
||||||
sizeof(cs.max_acceleration_units_per_sq_second_silent));
|
sizeof(cs.max_acceleration_units_per_sq_second_silent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TMC2130
|
#ifdef TMC2130
|
||||||
for (uint8_t j = X_AXIS; j <= Y_AXIS; j++)
|
for (uint8_t j = X_AXIS; j <= Y_AXIS; j++)
|
||||||
{
|
{
|
||||||
if (cs.max_feedrate_normal[j] > NORMAL_MAX_FEEDRATE_XY)
|
if (cs.max_feedrate_normal[j] > NORMAL_MAX_FEEDRATE_XY)
|
||||||
cs.max_feedrate_normal[j] = NORMAL_MAX_FEEDRATE_XY;
|
cs.max_feedrate_normal[j] = NORMAL_MAX_FEEDRATE_XY;
|
||||||
if (cs.max_feedrate_silent[j] > SILENT_MAX_FEEDRATE_XY)
|
if (cs.max_feedrate_silent[j] > SILENT_MAX_FEEDRATE_XY)
|
||||||
cs.max_feedrate_silent[j] = SILENT_MAX_FEEDRATE_XY;
|
cs.max_feedrate_silent[j] = SILENT_MAX_FEEDRATE_XY;
|
||||||
if (cs.max_acceleration_units_per_sq_second_normal[j] > NORMAL_MAX_ACCEL_XY)
|
if (cs.max_acceleration_units_per_sq_second_normal[j] > NORMAL_MAX_ACCEL_XY)
|
||||||
cs.max_acceleration_units_per_sq_second_normal[j] = NORMAL_MAX_ACCEL_XY;
|
cs.max_acceleration_units_per_sq_second_normal[j] = NORMAL_MAX_ACCEL_XY;
|
||||||
if (cs.max_acceleration_units_per_sq_second_silent[j] > SILENT_MAX_ACCEL_XY)
|
if (cs.max_acceleration_units_per_sq_second_silent[j] > SILENT_MAX_ACCEL_XY)
|
||||||
cs.max_acceleration_units_per_sq_second_silent[j] = SILENT_MAX_ACCEL_XY;
|
cs.max_acceleration_units_per_sq_second_silent[j] = SILENT_MAX_ACCEL_XY;
|
||||||
}
|
}
|
||||||
#endif //TMC2130
|
#endif //TMC2130
|
||||||
|
|
||||||
reset_acceleration_rates();
|
reset_acceleration_rates();
|
||||||
|
|
||||||
// Call updatePID (similar to when we have processed M301)
|
// Call updatePID (similar to when we have processed M301)
|
||||||
updatePID();
|
updatePID();
|
||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNPGM("Stored settings retrieved");
|
SERIAL_ECHOLNPGM("Stored settings retrieved");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Config_ResetDefault();
|
Config_ResetDefault();
|
||||||
//Return false to inform user that eeprom version was changed and firmware is using default hardcoded settings now.
|
//Return false to inform user that eeprom version was changed and firmware is using default hardcoded settings now.
|
||||||
//In case that storing to eeprom was not used yet, do not inform user that hardcoded settings are used.
|
//In case that storing to eeprom was not used yet, do not inform user that hardcoded settings are used.
|
||||||
if (eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[0]))) != 0xFF ||
|
if (eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[0]))) != 0xFF ||
|
||||||
eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[1]))) != 0xFF ||
|
eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[1]))) != 0xFF ||
|
||||||
eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[2]))) != 0xFF)
|
eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[2]))) != 0xFF)
|
||||||
{
|
{
|
||||||
previous_settings_retrieved = false;
|
previous_settings_retrieved = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef EEPROM_CHITCHAT
|
#ifdef EEPROM_CHITCHAT
|
||||||
Config_PrintSettings();
|
Config_PrintSettings();
|
||||||
#endif
|
#endif
|
||||||
return previous_settings_retrieved;
|
return previous_settings_retrieved;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -306,7 +306,7 @@ void Config_ResetDefault()
|
||||||
{
|
{
|
||||||
memcpy_P(&cs,&default_conf, sizeof(cs));
|
memcpy_P(&cs,&default_conf, sizeof(cs));
|
||||||
|
|
||||||
// steps per sq second need to be updated to agree with the units per sq second
|
// steps per sq second need to be updated to agree with the units per sq second
|
||||||
reset_acceleration_rates();
|
reset_acceleration_rates();
|
||||||
|
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
|
|
@ -316,9 +316,9 @@ void Config_ResetDefault()
|
||||||
#endif//PID_ADD_EXTRUSION_RATE
|
#endif//PID_ADD_EXTRUSION_RATE
|
||||||
#endif//PIDTEMP
|
#endif//PIDTEMP
|
||||||
|
|
||||||
calculate_extruder_multipliers();
|
calculate_extruder_multipliers();
|
||||||
|
|
||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,20 @@ void Config_StoreSettings();
|
||||||
bool Config_RetrieveSettings();
|
bool Config_RetrieveSettings();
|
||||||
#else
|
#else
|
||||||
FORCE_INLINE void Config_StoreSettings() {}
|
FORCE_INLINE void Config_StoreSettings() {}
|
||||||
FORCE_INLINE void Config_RetrieveSettings() { Config_ResetDefault(); Config_PrintSettings(); }
|
FORCE_INLINE void Config_RetrieveSettings() {
|
||||||
|
Config_ResetDefault();
|
||||||
|
Config_PrintSettings();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline uint8_t calibration_status() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS); }
|
inline uint8_t calibration_status() {
|
||||||
inline void calibration_status_store(uint8_t status) { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS, status); }
|
return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS);
|
||||||
inline bool calibration_status_pinda() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA); }
|
}
|
||||||
|
inline void calibration_status_store(uint8_t status) {
|
||||||
|
eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS, status);
|
||||||
|
}
|
||||||
|
inline bool calibration_status_pinda() {
|
||||||
|
return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA);
|
||||||
|
}
|
||||||
|
|
||||||
#endif//CONFIG_STORE_H
|
#endif//CONFIG_STORE_H
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
#ifdef BED_LIMIT_SWITCHING
|
#ifdef BED_LIMIT_SWITCHING
|
||||||
#define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS
|
#define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS
|
||||||
#endif
|
#endif
|
||||||
#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control
|
#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control
|
||||||
|
|
||||||
|
|
@ -19,12 +19,12 @@
|
||||||
//#define WATCH_TEMP_INCREASE 10 //Heat up at least 10 degree in 20 seconds
|
//#define WATCH_TEMP_INCREASE 10 //Heat up at least 10 degree in 20 seconds
|
||||||
|
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
// this adds an experimental additional term to the heating power, proportional to the extrusion speed.
|
// this adds an experimental additional term to the heating power, proportional to the extrusion speed.
|
||||||
// if Kc is chosen well, the additional required power due to increased melting should be compensated.
|
// if Kc is chosen well, the additional required power due to increased melting should be compensated.
|
||||||
#define PID_ADD_EXTRUSION_RATE
|
#define PID_ADD_EXTRUSION_RATE
|
||||||
#ifdef PID_ADD_EXTRUSION_RATE
|
#ifdef PID_ADD_EXTRUSION_RATE
|
||||||
#define DEFAULT_Kc (1) //heating power=Kc*(e_speed)
|
#define DEFAULT_Kc (1) //heating power=Kc*(e_speed)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
// on an Ultimaker, some initial testing worked with M109 S215 B260 F1 in the start.gcode
|
// on an Ultimaker, some initial testing worked with M109 S215 B260 F1 in the start.gcode
|
||||||
//#define AUTOTEMP
|
//#define AUTOTEMP
|
||||||
#ifdef AUTOTEMP
|
#ifdef AUTOTEMP
|
||||||
#define AUTOTEMP_OLDWEIGHT 0.98
|
#define AUTOTEMP_OLDWEIGHT 0.98
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Show Temperature ADC value
|
//Show Temperature ADC value
|
||||||
|
|
@ -83,46 +83,46 @@
|
||||||
//// AUTOSET LOCATIONS OF LIMIT SWITCHES
|
//// AUTOSET LOCATIONS OF LIMIT SWITCHES
|
||||||
//// Added by ZetaPhoenix 09-15-2012
|
//// Added by ZetaPhoenix 09-15-2012
|
||||||
#ifdef MANUAL_HOME_POSITIONS // Use manual limit switch locations
|
#ifdef MANUAL_HOME_POSITIONS // Use manual limit switch locations
|
||||||
#define X_HOME_POS MANUAL_X_HOME_POS
|
#define X_HOME_POS MANUAL_X_HOME_POS
|
||||||
#define Y_HOME_POS MANUAL_Y_HOME_POS
|
#define Y_HOME_POS MANUAL_Y_HOME_POS
|
||||||
#define Z_HOME_POS MANUAL_Z_HOME_POS
|
#define Z_HOME_POS MANUAL_Z_HOME_POS
|
||||||
#else //Set min/max homing switch positions based upon homing direction and min/max travel limits
|
#else //Set min/max homing switch positions based upon homing direction and min/max travel limits
|
||||||
//X axis
|
//X axis
|
||||||
#if X_HOME_DIR == -1
|
#if X_HOME_DIR == -1
|
||||||
#ifdef BED_CENTER_AT_0_0
|
#ifdef BED_CENTER_AT_0_0
|
||||||
#define X_HOME_POS X_MAX_LENGTH * -0.5
|
#define X_HOME_POS X_MAX_LENGTH * -0.5
|
||||||
#else
|
#else
|
||||||
#define X_HOME_POS X_MIN_POS
|
#define X_HOME_POS X_MIN_POS
|
||||||
#endif //BED_CENTER_AT_0_0
|
#endif //BED_CENTER_AT_0_0
|
||||||
#else
|
#else
|
||||||
#ifdef BED_CENTER_AT_0_0
|
#ifdef BED_CENTER_AT_0_0
|
||||||
#define X_HOME_POS X_MAX_LENGTH * 0.5
|
#define X_HOME_POS X_MAX_LENGTH * 0.5
|
||||||
#else
|
#else
|
||||||
#define X_HOME_POS X_MAX_POS
|
#define X_HOME_POS X_MAX_POS
|
||||||
#endif //BED_CENTER_AT_0_0
|
#endif //BED_CENTER_AT_0_0
|
||||||
#endif //X_HOME_DIR == -1
|
#endif //X_HOME_DIR == -1
|
||||||
|
|
||||||
//Y axis
|
//Y axis
|
||||||
#if Y_HOME_DIR == -1
|
#if Y_HOME_DIR == -1
|
||||||
#ifdef BED_CENTER_AT_0_0
|
#ifdef BED_CENTER_AT_0_0
|
||||||
#define Y_HOME_POS Y_MAX_LENGTH * -0.5
|
#define Y_HOME_POS Y_MAX_LENGTH * -0.5
|
||||||
#else
|
#else
|
||||||
#define Y_HOME_POS Y_MIN_POS
|
#define Y_HOME_POS Y_MIN_POS
|
||||||
#endif //BED_CENTER_AT_0_0
|
#endif //BED_CENTER_AT_0_0
|
||||||
#else
|
#else
|
||||||
#ifdef BED_CENTER_AT_0_0
|
#ifdef BED_CENTER_AT_0_0
|
||||||
#define Y_HOME_POS Y_MAX_LENGTH * 0.5
|
#define Y_HOME_POS Y_MAX_LENGTH * 0.5
|
||||||
#else
|
#else
|
||||||
#define Y_HOME_POS Y_MAX_POS
|
#define Y_HOME_POS Y_MAX_POS
|
||||||
#endif //BED_CENTER_AT_0_0
|
#endif //BED_CENTER_AT_0_0
|
||||||
#endif //Y_HOME_DIR == -1
|
#endif //Y_HOME_DIR == -1
|
||||||
|
|
||||||
// Z axis
|
// Z axis
|
||||||
#if Z_HOME_DIR == -1 //BED_CENTER_AT_0_0 not used
|
#if Z_HOME_DIR == -1 //BED_CENTER_AT_0_0 not used
|
||||||
#define Z_HOME_POS Z_MIN_POS
|
#define Z_HOME_POS Z_MIN_POS
|
||||||
#else
|
#else
|
||||||
#define Z_HOME_POS Z_MAX_POS
|
#define Z_HOME_POS Z_MAX_POS
|
||||||
#endif //Z_HOME_DIR == -1
|
#endif //Z_HOME_DIR == -1
|
||||||
#endif //End auto min/max positions
|
#endif //End auto min/max positions
|
||||||
//END AUTOSET LOCATIONS OF LIMIT SWITCHES -ZP
|
//END AUTOSET LOCATIONS OF LIMIT SWITCHES -ZP
|
||||||
|
|
||||||
|
|
@ -135,8 +135,8 @@
|
||||||
//#define Z_DUAL_STEPPER_DRIVERS
|
//#define Z_DUAL_STEPPER_DRIVERS
|
||||||
|
|
||||||
#ifdef Z_DUAL_STEPPER_DRIVERS
|
#ifdef Z_DUAL_STEPPER_DRIVERS
|
||||||
#undef EXTRUDERS
|
#undef EXTRUDERS
|
||||||
#define EXTRUDERS 1
|
#define EXTRUDERS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Same again but for Y Axis.
|
// Same again but for Y Axis.
|
||||||
|
|
@ -146,12 +146,12 @@
|
||||||
#define INVERT_Y2_VS_Y_DIR 1
|
#define INVERT_Y2_VS_Y_DIR 1
|
||||||
|
|
||||||
#ifdef Y_DUAL_STEPPER_DRIVERS
|
#ifdef Y_DUAL_STEPPER_DRIVERS
|
||||||
#undef EXTRUDERS
|
#undef EXTRUDERS
|
||||||
#define EXTRUDERS 1
|
#define EXTRUDERS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (Z_DUAL_STEPPER_DRIVERS) && defined (Y_DUAL_STEPPER_DRIVERS)
|
#if defined (Z_DUAL_STEPPER_DRIVERS) && defined (Y_DUAL_STEPPER_DRIVERS)
|
||||||
#error "You cannot have dual drivers for both Y and Z"
|
#error "You cannot have dual drivers for both Y and Z"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
|
//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
|
||||||
|
|
@ -235,28 +235,28 @@
|
||||||
* - SDSORT_CACHE_NAMES will retain the sorted file listing in RAM. (Expensive!)
|
* - SDSORT_CACHE_NAMES will retain the sorted file listing in RAM. (Expensive!)
|
||||||
* - SDSORT_DYNAMIC_RAM only uses RAM when the SD menu is visible. (Use with caution!)
|
* - SDSORT_DYNAMIC_RAM only uses RAM when the SD menu is visible. (Use with caution!)
|
||||||
*/
|
*/
|
||||||
#define SDCARD_SORT_ALPHA //Alphabetical sorting of SD files menu
|
#define SDCARD_SORT_ALPHA //Alphabetical sorting of SD files menu
|
||||||
|
|
||||||
// SD Card Sorting options
|
// SD Card Sorting options
|
||||||
// In current firmware Prusa Firmware version,
|
// In current firmware Prusa Firmware version,
|
||||||
// SDSORT_CACHE_NAMES and SDSORT_DYNAMIC_RAM is not supported and must be set to 0.
|
// SDSORT_CACHE_NAMES and SDSORT_DYNAMIC_RAM is not supported and must be set to 0.
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
#define SD_SORT_TIME 0
|
#define SD_SORT_TIME 0
|
||||||
#define SD_SORT_ALPHA 1
|
#define SD_SORT_ALPHA 1
|
||||||
#define SD_SORT_NONE 2
|
#define SD_SORT_NONE 2
|
||||||
|
|
||||||
#define SDSORT_LIMIT 100 // Maximum number of sorted items (10-256).
|
#define SDSORT_LIMIT 100 // Maximum number of sorted items (10-256).
|
||||||
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
|
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
|
||||||
#define SDSORT_GCODE 0 // Allow turning sorting on/off with LCD and M34 g-code.
|
#define SDSORT_GCODE 0 // Allow turning sorting on/off with LCD and M34 g-code.
|
||||||
#define SDSORT_USES_RAM 0 // Pre-allocate a static array for faster pre-sorting.
|
#define SDSORT_USES_RAM 0 // Pre-allocate a static array for faster pre-sorting.
|
||||||
#define SDSORT_USES_STACK 0 // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
|
#define SDSORT_USES_STACK 0 // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
|
||||||
#define SDSORT_CACHE_NAMES 0 // Keep sorted items in RAM longer for speedy performance. Most expensive option.
|
#define SDSORT_CACHE_NAMES 0 // Keep sorted items in RAM longer for speedy performance. Most expensive option.
|
||||||
#define SDSORT_DYNAMIC_RAM 0 // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
|
#define SDSORT_DYNAMIC_RAM 0 // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SDCARD_SORT_ALPHA)
|
#if defined(SDCARD_SORT_ALPHA)
|
||||||
#define HAS_FOLDER_SORTING (FOLDER_SORTING || SDSORT_GCODE)
|
#define HAS_FOLDER_SORTING (FOLDER_SORTING || SDSORT_GCODE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
|
// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
|
||||||
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
|
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
|
||||||
|
|
@ -266,13 +266,13 @@
|
||||||
// does not respect endstops!
|
// does not respect endstops!
|
||||||
#define BABYSTEPPING
|
#define BABYSTEPPING
|
||||||
#ifdef BABYSTEPPING
|
#ifdef BABYSTEPPING
|
||||||
#define BABYSTEP_XY //not only z, but also XY in the menu. more clutter, more functions
|
#define BABYSTEP_XY //not only z, but also XY in the menu. more clutter, more functions
|
||||||
#define BABYSTEP_INVERT_Z 0 //1 for inverse movements in Z
|
#define BABYSTEP_INVERT_Z 0 //1 for inverse movements in Z
|
||||||
#define BABYSTEP_Z_MULTIPLICATOR 2 //faster z movements
|
#define BABYSTEP_Z_MULTIPLICATOR 2 //faster z movements
|
||||||
|
|
||||||
#ifdef COREXY
|
#ifdef COREXY
|
||||||
#error BABYSTEPPING not implemented for COREXY yet.
|
#error BABYSTEPPING not implemented for COREXY yet.
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -285,34 +285,34 @@
|
||||||
#define LIN_ADVANCE
|
#define LIN_ADVANCE
|
||||||
|
|
||||||
#ifdef LIN_ADVANCE
|
#ifdef LIN_ADVANCE
|
||||||
#define LIN_ADVANCE_K 0 //Try around 45 for PLA, around 25 for ABS.
|
#define LIN_ADVANCE_K 0 //Try around 45 for PLA, around 25 for ABS.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some Slicers produce Gcode with randomly jumping extrusion widths occasionally.
|
* Some Slicers produce Gcode with randomly jumping extrusion widths occasionally.
|
||||||
* For example within a 0.4mm perimeter it may produce a single segment of 0.05mm width.
|
* For example within a 0.4mm perimeter it may produce a single segment of 0.05mm width.
|
||||||
* While this is harmless for normal printing (the fluid nature of the filament will
|
* While this is harmless for normal printing (the fluid nature of the filament will
|
||||||
* close this very, very tiny gap), it throws off the LIN_ADVANCE pressure adaption.
|
* close this very, very tiny gap), it throws off the LIN_ADVANCE pressure adaption.
|
||||||
*
|
*
|
||||||
* For this case LIN_ADVANCE_E_D_RATIO can be used to set the extrusion:distance ratio
|
* For this case LIN_ADVANCE_E_D_RATIO can be used to set the extrusion:distance ratio
|
||||||
* to a fixed value. Note that using a fixed ratio will lead to wrong nozzle pressures
|
* to a fixed value. Note that using a fixed ratio will lead to wrong nozzle pressures
|
||||||
* if the slicer is using variable widths or layer heights within one print!
|
* if the slicer is using variable widths or layer heights within one print!
|
||||||
*
|
*
|
||||||
* This option sets the default E:D ratio at startup. Use `M900` to override this value.
|
* This option sets the default E:D ratio at startup. Use `M900` to override this value.
|
||||||
*
|
*
|
||||||
* Example: `M900 W0.4 H0.2 D1.75`, where:
|
* Example: `M900 W0.4 H0.2 D1.75`, where:
|
||||||
* - W is the extrusion width in mm
|
* - W is the extrusion width in mm
|
||||||
* - H is the layer height in mm
|
* - H is the layer height in mm
|
||||||
* - D is the filament diameter in mm
|
* - D is the filament diameter in mm
|
||||||
*
|
*
|
||||||
* Example: `M900 R0.0458` to set the ratio directly.
|
* Example: `M900 R0.0458` to set the ratio directly.
|
||||||
*
|
*
|
||||||
* Set to 0 to auto-detect the ratio based on given Gcode G1 print moves.
|
* Set to 0 to auto-detect the ratio based on given Gcode G1 print moves.
|
||||||
*
|
*
|
||||||
* Slic3r (including Prusa Slic3r) produces Gcode compatible with the automatic mode.
|
* Slic3r (including Prusa Slic3r) produces Gcode compatible with the automatic mode.
|
||||||
* Cura (as of this writing) may produce Gcode incompatible with the automatic mode.
|
* Cura (as of this writing) may produce Gcode incompatible with the automatic mode.
|
||||||
*/
|
*/
|
||||||
#define LIN_ADVANCE_E_D_RATIO 0 // The calculated ratio (or 0) according to the formula W * H / ((D / 2) ^ 2 * PI)
|
#define LIN_ADVANCE_E_D_RATIO 0 // The calculated ratio (or 0) according to the formula W * H / ((D / 2) ^ 2 * PI)
|
||||||
// Example: 0.4 * 0.2 / ((1.75 / 2) ^ 2 * PI) = 0.033260135
|
// Example: 0.4 * 0.2 / ((1.75 / 2) ^ 2 * PI) = 0.033260135
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Arc interpretation settings:
|
// Arc interpretation settings:
|
||||||
|
|
@ -331,17 +331,17 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
||||||
// Power Signal Control Definitions
|
// Power Signal Control Definitions
|
||||||
// By default use ATX definition
|
// By default use ATX definition
|
||||||
#ifndef POWER_SUPPLY
|
#ifndef POWER_SUPPLY
|
||||||
#define POWER_SUPPLY 1
|
#define POWER_SUPPLY 1
|
||||||
#endif
|
#endif
|
||||||
// 1 = ATX
|
// 1 = ATX
|
||||||
#if (POWER_SUPPLY == 1)
|
#if (POWER_SUPPLY == 1)
|
||||||
#define PS_ON_AWAKE LOW
|
#define PS_ON_AWAKE LOW
|
||||||
#define PS_ON_ASLEEP HIGH
|
#define PS_ON_ASLEEP HIGH
|
||||||
#endif
|
#endif
|
||||||
// 2 = X-Box 360 203W
|
// 2 = X-Box 360 203W
|
||||||
#if (POWER_SUPPLY == 2)
|
#if (POWER_SUPPLY == 2)
|
||||||
#define PS_ON_AWAKE HIGH
|
#define PS_ON_AWAKE HIGH
|
||||||
#define PS_ON_ASLEEP LOW
|
#define PS_ON_ASLEEP LOW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Control heater 0 and heater 1 in parallel.
|
// Control heater 0 and heater 1 in parallel.
|
||||||
|
|
@ -354,9 +354,9 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
||||||
// The number of linear motions that can be in the plan at any give time.
|
// 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.
|
||||||
#if defined SDSUPPORT
|
#if defined SDSUPPORT
|
||||||
#define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller
|
#define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller
|
||||||
#else
|
#else
|
||||||
#define BLOCK_BUFFER_SIZE 16 // maximize block buffer
|
#define BLOCK_BUFFER_SIZE 16 // maximize block buffer
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -377,23 +377,23 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
||||||
|
|
||||||
#define FWRETRACT //ONLY PARTIALLY TESTED
|
#define FWRETRACT //ONLY PARTIALLY TESTED
|
||||||
#ifdef FWRETRACT
|
#ifdef FWRETRACT
|
||||||
#define MIN_RETRACT 0.1 //minimum extruded mm to accept a automatic gcode retraction attempt
|
#define MIN_RETRACT 0.1 //minimum extruded mm to accept a automatic gcode retraction attempt
|
||||||
#define RETRACT_LENGTH 3 //default retract length (positive mm)
|
#define RETRACT_LENGTH 3 //default retract length (positive mm)
|
||||||
#define RETRACT_LENGTH_SWAP 13 //default swap retract length (positive mm), for extruder change
|
#define RETRACT_LENGTH_SWAP 13 //default swap retract length (positive mm), for extruder change
|
||||||
#define RETRACT_FEEDRATE 45 //default feedrate for retracting (mm/s)
|
#define RETRACT_FEEDRATE 45 //default feedrate for retracting (mm/s)
|
||||||
#define RETRACT_ZLIFT 0 //default retract Z-lift
|
#define RETRACT_ZLIFT 0 //default retract Z-lift
|
||||||
#define RETRACT_RECOVER_LENGTH 0 //default additional recover length (mm, added to retract length when recovering)
|
#define RETRACT_RECOVER_LENGTH 0 //default additional recover length (mm, added to retract length when recovering)
|
||||||
#define RETRACT_RECOVER_LENGTH_SWAP 0 //default additional swap recover length (mm, added to retract length when recovering from extruder change)
|
#define RETRACT_RECOVER_LENGTH_SWAP 0 //default additional swap recover length (mm, added to retract length when recovering from extruder change)
|
||||||
#define RETRACT_RECOVER_FEEDRATE 8 //default feedrate for recovering from retraction (mm/s)
|
#define RETRACT_RECOVER_FEEDRATE 8 //default feedrate for recovering from retraction (mm/s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//adds support for experimental filament exchange support M600; requires display
|
//adds support for experimental filament exchange support M600; requires display
|
||||||
|
|
||||||
|
|
||||||
#ifdef FILAMENTCHANGEENABLE
|
#ifdef FILAMENTCHANGEENABLE
|
||||||
#ifdef EXTRUDER_RUNOUT_PREVENT
|
#ifdef EXTRUDER_RUNOUT_PREVENT
|
||||||
#error EXTRUDER_RUNOUT_PREVENT currently incompatible with FILAMENTCHANGE
|
#error EXTRUDER_RUNOUT_PREVENT currently incompatible with FILAMENTCHANGE
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
@ -401,65 +401,65 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
#if EXTRUDERS > 1 && defined TEMP_SENSOR_1_AS_REDUNDANT
|
#if EXTRUDERS > 1 && defined TEMP_SENSOR_1_AS_REDUNDANT
|
||||||
#error "You cannot use TEMP_SENSOR_1_AS_REDUNDANT if EXTRUDERS > 1"
|
#error "You cannot use TEMP_SENSOR_1_AS_REDUNDANT if EXTRUDERS > 1"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if EXTRUDERS > 1 && defined HEATERS_PARALLEL
|
#if EXTRUDERS > 1 && defined HEATERS_PARALLEL
|
||||||
#error "You cannot use HEATERS_PARALLEL if EXTRUDERS > 1"
|
#error "You cannot use HEATERS_PARALLEL if EXTRUDERS > 1"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TEMP_SENSOR_0 > 0
|
#if TEMP_SENSOR_0 > 0
|
||||||
#define THERMISTORHEATER_0 TEMP_SENSOR_0
|
#define THERMISTORHEATER_0 TEMP_SENSOR_0
|
||||||
#define HEATER_0_USES_THERMISTOR
|
#define HEATER_0_USES_THERMISTOR
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_1 > 0
|
#if TEMP_SENSOR_1 > 0
|
||||||
#define THERMISTORHEATER_1 TEMP_SENSOR_1
|
#define THERMISTORHEATER_1 TEMP_SENSOR_1
|
||||||
#define HEATER_1_USES_THERMISTOR
|
#define HEATER_1_USES_THERMISTOR
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_2 > 0
|
#if TEMP_SENSOR_2 > 0
|
||||||
#define THERMISTORHEATER_2 TEMP_SENSOR_2
|
#define THERMISTORHEATER_2 TEMP_SENSOR_2
|
||||||
#define HEATER_2_USES_THERMISTOR
|
#define HEATER_2_USES_THERMISTOR
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_BED > 0
|
#if TEMP_SENSOR_BED > 0
|
||||||
#define THERMISTORBED TEMP_SENSOR_BED
|
#define THERMISTORBED TEMP_SENSOR_BED
|
||||||
#define BED_USES_THERMISTOR
|
#define BED_USES_THERMISTOR
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_PINDA > 0
|
#if TEMP_SENSOR_PINDA > 0
|
||||||
#define THERMISTORPINDA TEMP_SENSOR_PINDA
|
#define THERMISTORPINDA TEMP_SENSOR_PINDA
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_AMBIENT > 0
|
#if TEMP_SENSOR_AMBIENT > 0
|
||||||
#define THERMISTORAMBIENT TEMP_SENSOR_AMBIENT
|
#define THERMISTORAMBIENT TEMP_SENSOR_AMBIENT
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_0 == -1
|
#if TEMP_SENSOR_0 == -1
|
||||||
#define HEATER_0_USES_AD595
|
#define HEATER_0_USES_AD595
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_1 == -1
|
#if TEMP_SENSOR_1 == -1
|
||||||
#define HEATER_1_USES_AD595
|
#define HEATER_1_USES_AD595
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_2 == -1
|
#if TEMP_SENSOR_2 == -1
|
||||||
#define HEATER_2_USES_AD595
|
#define HEATER_2_USES_AD595
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_BED == -1
|
#if TEMP_SENSOR_BED == -1
|
||||||
#define BED_USES_AD595
|
#define BED_USES_AD595
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_0 == -2
|
#if TEMP_SENSOR_0 == -2
|
||||||
#define HEATER_0_USES_MAX6675
|
#define HEATER_0_USES_MAX6675
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_0 == 0
|
#if TEMP_SENSOR_0 == 0
|
||||||
#undef HEATER_0_MINTEMP
|
#undef HEATER_0_MINTEMP
|
||||||
#undef HEATER_0_MAXTEMP
|
#undef HEATER_0_MAXTEMP
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_1 == 0
|
#if TEMP_SENSOR_1 == 0
|
||||||
#undef HEATER_1_MINTEMP
|
#undef HEATER_1_MINTEMP
|
||||||
#undef HEATER_1_MAXTEMP
|
#undef HEATER_1_MAXTEMP
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_2 == 0
|
#if TEMP_SENSOR_2 == 0
|
||||||
#undef HEATER_2_MINTEMP
|
#undef HEATER_2_MINTEMP
|
||||||
#undef HEATER_2_MAXTEMP
|
#undef HEATER_2_MAXTEMP
|
||||||
#endif
|
#endif
|
||||||
#if TEMP_SENSOR_BED == 0
|
#if TEMP_SENSOR_BED == 0
|
||||||
#undef BED_MINTEMP
|
#undef BED_MINTEMP
|
||||||
#undef BED_MAXTEMP
|
#undef BED_MAXTEMP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -54,13 +54,13 @@
|
||||||
//#include "WString.h"
|
//#include "WString.h"
|
||||||
|
|
||||||
#ifdef AT90USB
|
#ifdef AT90USB
|
||||||
#ifdef BTENABLED
|
#ifdef BTENABLED
|
||||||
#define MYSERIAL bt
|
#define MYSERIAL bt
|
||||||
#else
|
|
||||||
#define MYSERIAL Serial
|
|
||||||
#endif // BTENABLED
|
|
||||||
#else
|
#else
|
||||||
#define MYSERIAL MSerial
|
#define MYSERIAL Serial
|
||||||
|
#endif // BTENABLED
|
||||||
|
#else
|
||||||
|
#define MYSERIAL MSerial
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
|
@ -113,12 +113,12 @@ void serial_echopair_P(const char *s_P, unsigned long v);
|
||||||
//Things to write to serial from Program memory. Saves 400 to 2k of RAM.
|
//Things to write to serial from Program memory. Saves 400 to 2k of RAM.
|
||||||
FORCE_INLINE void serialprintPGM(const char *str)
|
FORCE_INLINE void serialprintPGM(const char *str)
|
||||||
{
|
{
|
||||||
char ch=pgm_read_byte(str);
|
char ch=pgm_read_byte(str);
|
||||||
while(ch)
|
while(ch)
|
||||||
{
|
{
|
||||||
MYSERIAL.write(ch);
|
MYSERIAL.write(ch);
|
||||||
ch=pgm_read_byte(++str);
|
ch=pgm_read_byte(++str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_buffer_empty();
|
bool is_buffer_empty();
|
||||||
|
|
@ -129,47 +129,47 @@ void ramming();
|
||||||
void manage_inactivity(bool ignore_stepper_queue=false);
|
void manage_inactivity(bool ignore_stepper_queue=false);
|
||||||
|
|
||||||
#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
|
#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1
|
||||||
#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)
|
#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON)
|
||||||
#define disable_x() { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }
|
#define disable_x() { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }
|
||||||
#else
|
#else
|
||||||
#define enable_x() ;
|
#define enable_x() ;
|
||||||
#define disable_x() ;
|
#define disable_x() ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
|
#if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
|
||||||
#ifdef Y_DUAL_STEPPER_DRIVERS
|
#ifdef Y_DUAL_STEPPER_DRIVERS
|
||||||
#define enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, Y_ENABLE_ON); }
|
#define enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, Y_ENABLE_ON); }
|
||||||
#define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
|
#define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
|
||||||
#else
|
|
||||||
#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
|
|
||||||
#define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#define enable_y() ;
|
#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
|
||||||
#define disable_y() ;
|
#define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define enable_y() ;
|
||||||
|
#define disable_y() ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
|
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
|
||||||
#if defined(Z_AXIS_ALWAYS_ON)
|
#if defined(Z_AXIS_ALWAYS_ON)
|
||||||
#ifdef Z_DUAL_STEPPER_DRIVERS
|
#ifdef Z_DUAL_STEPPER_DRIVERS
|
||||||
#define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
|
#define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
|
||||||
#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||||
#else
|
|
||||||
#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
|
||||||
#define disable_z() {}
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef Z_DUAL_STEPPER_DRIVERS
|
|
||||||
#define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
|
|
||||||
#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
|
||||||
#else
|
|
||||||
#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
|
||||||
#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#define enable_z() {}
|
#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
||||||
#define disable_z() {}
|
#define disable_z() {}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef Z_DUAL_STEPPER_DRIVERS
|
||||||
|
#define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
|
||||||
|
#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||||
|
#else
|
||||||
|
#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
||||||
|
#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define enable_z() {}
|
||||||
|
#define disable_z() {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -190,27 +190,27 @@ void manage_inactivity(bool ignore_stepper_queue=false);
|
||||||
|
|
||||||
|
|
||||||
#if defined(E0_ENABLE_PIN) && (E0_ENABLE_PIN > -1)
|
#if defined(E0_ENABLE_PIN) && (E0_ENABLE_PIN > -1)
|
||||||
#define enable_e0() WRITE(E0_ENABLE_PIN, E_ENABLE_ON)
|
#define enable_e0() WRITE(E0_ENABLE_PIN, E_ENABLE_ON)
|
||||||
#define disable_e0() WRITE(E0_ENABLE_PIN,!E_ENABLE_ON)
|
#define disable_e0() WRITE(E0_ENABLE_PIN,!E_ENABLE_ON)
|
||||||
#else
|
#else
|
||||||
#define enable_e0() /* nothing */
|
#define enable_e0() /* nothing */
|
||||||
#define disable_e0() /* nothing */
|
#define disable_e0() /* nothing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (EXTRUDERS > 1) && defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1)
|
#if (EXTRUDERS > 1) && defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1)
|
||||||
#define enable_e1() WRITE(E1_ENABLE_PIN, E_ENABLE_ON)
|
#define enable_e1() WRITE(E1_ENABLE_PIN, E_ENABLE_ON)
|
||||||
#define disable_e1() WRITE(E1_ENABLE_PIN,!E_ENABLE_ON)
|
#define disable_e1() WRITE(E1_ENABLE_PIN,!E_ENABLE_ON)
|
||||||
#else
|
#else
|
||||||
#define enable_e1() /* nothing */
|
#define enable_e1() /* nothing */
|
||||||
#define disable_e1() /* nothing */
|
#define disable_e1() /* nothing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (EXTRUDERS > 2) && defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1)
|
#if (EXTRUDERS > 2) && defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1)
|
||||||
#define enable_e2() WRITE(E2_ENABLE_PIN, E_ENABLE_ON)
|
#define enable_e2() WRITE(E2_ENABLE_PIN, E_ENABLE_ON)
|
||||||
#define disable_e2() WRITE(E2_ENABLE_PIN,!E_ENABLE_ON)
|
#define disable_e2() WRITE(E2_ENABLE_PIN,!E_ENABLE_ON)
|
||||||
#else
|
#else
|
||||||
#define enable_e2() /* nothing */
|
#define enable_e2() /* nothing */
|
||||||
#define disable_e2() /* nothing */
|
#define disable_e2() /* nothing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -262,15 +262,17 @@ void refresh_cmd_timeout(void);
|
||||||
extern volatile unsigned long timer0_millis;
|
extern volatile unsigned long timer0_millis;
|
||||||
// An unsynchronized equivalent to a standard Arduino millis() function.
|
// An unsynchronized equivalent to a standard Arduino millis() function.
|
||||||
// To be used inside an interrupt routine.
|
// To be used inside an interrupt routine.
|
||||||
FORCE_INLINE unsigned long millis_nc() { return timer0_millis; }
|
FORCE_INLINE unsigned long millis_nc() {
|
||||||
|
return timer0_millis;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FAST_PWM_FAN
|
#ifdef FAST_PWM_FAN
|
||||||
void setPwmFrequency(uint8_t pin, int val);
|
void setPwmFrequency(uint8_t pin, int val);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CRITICAL_SECTION_START
|
#ifndef CRITICAL_SECTION_START
|
||||||
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
|
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
|
||||||
#define CRITICAL_SECTION_END SREG = _sreg;
|
#define CRITICAL_SECTION_END SREG = _sreg;
|
||||||
#endif //CRITICAL_SECTION_START
|
#endif //CRITICAL_SECTION_START
|
||||||
|
|
||||||
extern float homing_feedrate[];
|
extern float homing_feedrate[];
|
||||||
|
|
|
||||||
|
|
@ -31,21 +31,21 @@ uint8_t selectedSerialPort = 0;
|
||||||
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)
|
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)
|
||||||
|
|
||||||
#if UART_PRESENT(SERIAL_PORT)
|
#if UART_PRESENT(SERIAL_PORT)
|
||||||
ring_buffer rx_buffer = { { 0 }, 0, 0 };
|
ring_buffer rx_buffer = { { 0 }, 0, 0 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE void store_char(unsigned char c)
|
FORCE_INLINE void store_char(unsigned char c)
|
||||||
{
|
{
|
||||||
int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
|
int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
|
||||||
|
|
||||||
// if we should be storing the received character into the location
|
// if we should be storing the received character into the location
|
||||||
// just before the tail (meaning that the head would advance to the
|
// just before the tail (meaning that the head would advance to the
|
||||||
// current location of the tail), we're about to overflow the buffer
|
// current location of the tail), we're about to overflow the buffer
|
||||||
// and so we don't write the character or advance the head.
|
// and so we don't write the character or advance the head.
|
||||||
if (i != rx_buffer.tail) {
|
if (i != rx_buffer.tail) {
|
||||||
rx_buffer.buffer[rx_buffer.head] = c;
|
rx_buffer.buffer[rx_buffer.head] = c;
|
||||||
rx_buffer.head = i;
|
rx_buffer.head = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -57,44 +57,44 @@ FORCE_INLINE void store_char(unsigned char c)
|
||||||
// As the serial line is not fully utilized, the CPU load is likely around 1%.
|
// As the serial line is not fully utilized, the CPU load is likely around 1%.
|
||||||
ISR(M_USARTx_RX_vect)
|
ISR(M_USARTx_RX_vect)
|
||||||
{
|
{
|
||||||
// Test for a framing error.
|
// Test for a framing error.
|
||||||
if (M_UCSRxA & (1<<M_FEx))
|
if (M_UCSRxA & (1<<M_FEx))
|
||||||
{
|
{
|
||||||
// Characters received with the framing errors will be ignored.
|
// Characters received with the framing errors will be ignored.
|
||||||
// Dummy register read (discard)
|
// Dummy register read (discard)
|
||||||
(void)(*(char *)M_UDRx);
|
(void)(*(char *)M_UDRx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Read the input register.
|
// Read the input register.
|
||||||
unsigned char c = M_UDRx;
|
unsigned char c = M_UDRx;
|
||||||
if (selectedSerialPort == 0)
|
if (selectedSerialPort == 0)
|
||||||
store_char(c);
|
store_char(c);
|
||||||
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
UDR1 = c;
|
UDR1 = c;
|
||||||
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef SNMM
|
#ifndef SNMM
|
||||||
ISR(USART1_RX_vect)
|
ISR(USART1_RX_vect)
|
||||||
{
|
{
|
||||||
// Test for a framing error.
|
// Test for a framing error.
|
||||||
if (UCSR1A & (1<<FE1))
|
if (UCSR1A & (1<<FE1))
|
||||||
{
|
{
|
||||||
// Characters received with the framing errors will be ignored.
|
// Characters received with the framing errors will be ignored.
|
||||||
// Dummy register read (discard)
|
// Dummy register read (discard)
|
||||||
(void)(*(char *)UDR1);
|
(void)(*(char *)UDR1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Read the input register.
|
// Read the input register.
|
||||||
unsigned char c = UDR1;
|
unsigned char c = UDR1;
|
||||||
if (selectedSerialPort == 1)
|
if (selectedSerialPort == 1)
|
||||||
store_char(c);
|
store_char(c);
|
||||||
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
M_UDRx = c;
|
M_UDRx = c;
|
||||||
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -103,66 +103,66 @@ ISR(USART1_RX_vect)
|
||||||
|
|
||||||
void MarlinSerial::begin(long baud)
|
void MarlinSerial::begin(long baud)
|
||||||
{
|
{
|
||||||
uint16_t baud_setting;
|
uint16_t baud_setting;
|
||||||
bool useU2X = true;
|
bool useU2X = true;
|
||||||
|
|
||||||
#if F_CPU == 16000000UL && SERIAL_PORT == 0
|
#if F_CPU == 16000000UL && SERIAL_PORT == 0
|
||||||
// hard-coded exception for compatibility with the bootloader shipped
|
// hard-coded exception for compatibility with the bootloader shipped
|
||||||
// with the Duemilanove and previous boards and the firmware on the 8U2
|
// with the Duemilanove and previous boards and the firmware on the 8U2
|
||||||
// on the Uno and Mega 2560.
|
// on the Uno and Mega 2560.
|
||||||
if (baud == 57600) {
|
if (baud == 57600) {
|
||||||
useU2X = false;
|
useU2X = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// set up the first (original serial port)
|
// set up the first (original serial port)
|
||||||
if (useU2X) {
|
if (useU2X) {
|
||||||
M_UCSRxA = 1 << M_U2Xx;
|
M_UCSRxA = 1 << M_U2Xx;
|
||||||
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||||
} else {
|
} else {
|
||||||
M_UCSRxA = 0;
|
M_UCSRxA = 0;
|
||||||
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
||||||
M_UBRRxH = baud_setting >> 8;
|
M_UBRRxH = baud_setting >> 8;
|
||||||
M_UBRRxL = baud_setting;
|
M_UBRRxL = baud_setting;
|
||||||
|
|
||||||
sbi(M_UCSRxB, M_RXENx);
|
sbi(M_UCSRxB, M_RXENx);
|
||||||
sbi(M_UCSRxB, M_TXENx);
|
sbi(M_UCSRxB, M_TXENx);
|
||||||
sbi(M_UCSRxB, M_RXCIEx);
|
sbi(M_UCSRxB, M_RXCIEx);
|
||||||
|
|
||||||
#ifndef SNMM
|
#ifndef SNMM
|
||||||
|
|
||||||
if (selectedSerialPort == 1) { //set up also the second serial port
|
if (selectedSerialPort == 1) { //set up also the second serial port
|
||||||
if (useU2X) {
|
if (useU2X) {
|
||||||
UCSR1A = 1 << U2X1;
|
UCSR1A = 1 << U2X1;
|
||||||
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||||
} else {
|
} else {
|
||||||
UCSR1A = 0;
|
UCSR1A = 0;
|
||||||
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
||||||
UBRR1H = baud_setting >> 8;
|
UBRR1H = baud_setting >> 8;
|
||||||
UBRR1L = baud_setting;
|
UBRR1L = baud_setting;
|
||||||
|
|
||||||
sbi(UCSR1B, RXEN1);
|
sbi(UCSR1B, RXEN1);
|
||||||
sbi(UCSR1B, TXEN1);
|
sbi(UCSR1B, TXEN1);
|
||||||
sbi(UCSR1B, RXCIE1);
|
sbi(UCSR1B, RXCIE1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::end()
|
void MarlinSerial::end()
|
||||||
{
|
{
|
||||||
cbi(M_UCSRxB, M_RXENx);
|
cbi(M_UCSRxB, M_RXENx);
|
||||||
cbi(M_UCSRxB, M_TXENx);
|
cbi(M_UCSRxB, M_TXENx);
|
||||||
cbi(M_UCSRxB, M_RXCIEx);
|
cbi(M_UCSRxB, M_RXCIEx);
|
||||||
|
|
||||||
#ifndef SNMM
|
#ifndef SNMM
|
||||||
cbi(UCSR1B, RXEN1);
|
cbi(UCSR1B, RXEN1);
|
||||||
cbi(UCSR1B, TXEN1);
|
cbi(UCSR1B, TXEN1);
|
||||||
cbi(UCSR1B, RXCIE1);
|
cbi(UCSR1B, RXCIE1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,33 +170,33 @@ void MarlinSerial::end()
|
||||||
|
|
||||||
int MarlinSerial::peek(void)
|
int MarlinSerial::peek(void)
|
||||||
{
|
{
|
||||||
if (rx_buffer.head == rx_buffer.tail) {
|
if (rx_buffer.head == rx_buffer.tail) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
return rx_buffer.buffer[rx_buffer.tail];
|
return rx_buffer.buffer[rx_buffer.tail];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MarlinSerial::read(void)
|
int MarlinSerial::read(void)
|
||||||
{
|
{
|
||||||
// if the head isn't ahead of the tail, we don't have any characters
|
// if the head isn't ahead of the tail, we don't have any characters
|
||||||
if (rx_buffer.head == rx_buffer.tail) {
|
if (rx_buffer.head == rx_buffer.tail) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
unsigned char c = rx_buffer.buffer[rx_buffer.tail];
|
unsigned char c = rx_buffer.buffer[rx_buffer.tail];
|
||||||
rx_buffer.tail = (unsigned int)(rx_buffer.tail + 1) % RX_BUFFER_SIZE;
|
rx_buffer.tail = (unsigned int)(rx_buffer.tail + 1) % RX_BUFFER_SIZE;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::flush()
|
void MarlinSerial::flush()
|
||||||
{
|
{
|
||||||
// don't reverse this or there may be problems if the RX interrupt
|
// 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
|
// 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
|
// 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
|
// may be written to rx_buffer_tail, making it appear as if the buffer
|
||||||
// were full, not empty.
|
// were full, not empty.
|
||||||
rx_buffer.head = rx_buffer.tail;
|
rx_buffer.head = rx_buffer.tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -209,54 +209,54 @@ void MarlinSerial::flush()
|
||||||
|
|
||||||
void MarlinSerial::print(char c, int base)
|
void MarlinSerial::print(char c, int base)
|
||||||
{
|
{
|
||||||
print((long) c, base);
|
print((long) c, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::print(unsigned char b, int base)
|
void MarlinSerial::print(unsigned char b, int base)
|
||||||
{
|
{
|
||||||
print((unsigned long) b, base);
|
print((unsigned long) b, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::print(int n, int base)
|
void MarlinSerial::print(int n, int base)
|
||||||
{
|
{
|
||||||
print((long) n, base);
|
print((long) n, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::print(unsigned int n, int base)
|
void MarlinSerial::print(unsigned int n, int base)
|
||||||
{
|
{
|
||||||
print((unsigned long) n, base);
|
print((unsigned long) n, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::print(long n, int base)
|
void MarlinSerial::print(long n, int base)
|
||||||
{
|
{
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
write(n);
|
write(n);
|
||||||
} else if (base == 10) {
|
} else if (base == 10) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
print('-');
|
print('-');
|
||||||
n = -n;
|
n = -n;
|
||||||
|
}
|
||||||
|
printNumber(n, 10);
|
||||||
|
} else {
|
||||||
|
printNumber(n, base);
|
||||||
}
|
}
|
||||||
printNumber(n, 10);
|
|
||||||
} else {
|
|
||||||
printNumber(n, base);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::print(unsigned long n, int base)
|
void MarlinSerial::print(unsigned long n, int base)
|
||||||
{
|
{
|
||||||
if (base == 0) write(n);
|
if (base == 0) write(n);
|
||||||
else printNumber(n, base);
|
else printNumber(n, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::print(double n, int digits)
|
void MarlinSerial::print(double n, int digits)
|
||||||
{
|
{
|
||||||
printFloat(n, digits);
|
printFloat(n, digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(void)
|
void MarlinSerial::println(void)
|
||||||
{
|
{
|
||||||
print('\r');
|
print('\r');
|
||||||
print('\n');
|
print('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void MarlinSerial::println(const String &s)
|
/*void MarlinSerial::println(const String &s)
|
||||||
|
|
@ -267,108 +267,108 @@ void MarlinSerial::println(void)
|
||||||
|
|
||||||
void MarlinSerial::println(const char c[])
|
void MarlinSerial::println(const char c[])
|
||||||
{
|
{
|
||||||
print(c);
|
print(c);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(char c, int base)
|
void MarlinSerial::println(char c, int base)
|
||||||
{
|
{
|
||||||
print(c, base);
|
print(c, base);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(unsigned char b, int base)
|
void MarlinSerial::println(unsigned char b, int base)
|
||||||
{
|
{
|
||||||
print(b, base);
|
print(b, base);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(int n, int base)
|
void MarlinSerial::println(int n, int base)
|
||||||
{
|
{
|
||||||
print(n, base);
|
print(n, base);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(unsigned int n, int base)
|
void MarlinSerial::println(unsigned int n, int base)
|
||||||
{
|
{
|
||||||
print(n, base);
|
print(n, base);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(long n, int base)
|
void MarlinSerial::println(long n, int base)
|
||||||
{
|
{
|
||||||
print(n, base);
|
print(n, base);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(unsigned long n, int base)
|
void MarlinSerial::println(unsigned long n, int base)
|
||||||
{
|
{
|
||||||
print(n, base);
|
print(n, base);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::println(double n, int digits)
|
void MarlinSerial::println(double n, int digits)
|
||||||
{
|
{
|
||||||
print(n, digits);
|
print(n, digits);
|
||||||
println();
|
println();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private Methods /////////////////////////////////////////////////////////////
|
// Private Methods /////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void MarlinSerial::printNumber(unsigned long n, uint8_t base)
|
void MarlinSerial::printNumber(unsigned long n, uint8_t base)
|
||||||
{
|
{
|
||||||
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
print('0');
|
print('0');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
buf[i++] = n % base;
|
buf[i++] = n % base;
|
||||||
n /= base;
|
n /= base;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i > 0; i--)
|
for (; i > 0; i--)
|
||||||
print((char) (buf[i - 1] < 10 ?
|
print((char) (buf[i - 1] < 10 ?
|
||||||
'0' + buf[i - 1] :
|
'0' + buf[i - 1] :
|
||||||
'A' + buf[i - 1] - 10));
|
'A' + buf[i - 1] - 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarlinSerial::printFloat(double number, uint8_t digits)
|
void MarlinSerial::printFloat(double number, uint8_t digits)
|
||||||
{
|
{
|
||||||
// Handle negative numbers
|
// Handle negative numbers
|
||||||
if (number < 0.0)
|
if (number < 0.0)
|
||||||
{
|
{
|
||||||
print('-');
|
print('-');
|
||||||
number = -number;
|
number = -number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||||
double rounding = 0.5;
|
double rounding = 0.5;
|
||||||
for (uint8_t i=0; i<digits; ++i)
|
for (uint8_t i=0; i<digits; ++i)
|
||||||
rounding /= 10.0;
|
rounding /= 10.0;
|
||||||
|
|
||||||
number += rounding;
|
number += rounding;
|
||||||
|
|
||||||
// Extract the integer part of the number and print it
|
// Extract the integer part of the number and print it
|
||||||
unsigned long int_part = (unsigned long)number;
|
unsigned long int_part = (unsigned long)number;
|
||||||
double remainder = number - (double)int_part;
|
double remainder = number - (double)int_part;
|
||||||
print(int_part);
|
print(int_part);
|
||||||
|
|
||||||
// Print the decimal point, but only if there are digits beyond
|
// Print the decimal point, but only if there are digits beyond
|
||||||
if (digits > 0)
|
if (digits > 0)
|
||||||
print(".");
|
print(".");
|
||||||
|
|
||||||
// Extract digits from the remainder one at a time
|
// Extract digits from the remainder one at a time
|
||||||
while (digits-- > 0)
|
while (digits-- > 0)
|
||||||
{
|
{
|
||||||
remainder *= 10.0;
|
remainder *= 10.0;
|
||||||
int toPrint = int(remainder);
|
int toPrint = int(remainder);
|
||||||
print(toPrint);
|
print(toPrint);
|
||||||
remainder -= toPrint;
|
remainder -= toPrint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Preinstantiate Objects //////////////////////////////////////////////////////
|
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
@ -380,6 +380,6 @@ MarlinSerial MSerial;
|
||||||
|
|
||||||
// For AT90USB targets use the UART for BT interfacing
|
// For AT90USB targets use the UART for BT interfacing
|
||||||
#if defined(AT90USB) && defined (BTENABLED)
|
#if defined(AT90USB) && defined (BTENABLED)
|
||||||
HardwareSerial bt;
|
HardwareSerial bt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,19 +77,19 @@ extern uint8_t selectedSerialPort;
|
||||||
|
|
||||||
struct ring_buffer
|
struct ring_buffer
|
||||||
{
|
{
|
||||||
unsigned char buffer[RX_BUFFER_SIZE];
|
unsigned char buffer[RX_BUFFER_SIZE];
|
||||||
int head;
|
int head;
|
||||||
int tail;
|
int tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if UART_PRESENT(SERIAL_PORT)
|
#if UART_PRESENT(SERIAL_PORT)
|
||||||
extern ring_buffer rx_buffer;
|
extern ring_buffer rx_buffer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class MarlinSerial //: public Stream
|
class MarlinSerial //: public Stream
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void begin(long);
|
static void begin(long);
|
||||||
static void end();
|
static void end();
|
||||||
static int peek(void);
|
static int peek(void);
|
||||||
|
|
@ -98,7 +98,7 @@ class MarlinSerial //: public Stream
|
||||||
|
|
||||||
static FORCE_INLINE int available(void)
|
static FORCE_INLINE int available(void)
|
||||||
{
|
{
|
||||||
return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE;
|
return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
FORCE_INLINE void write(uint8_t c)
|
FORCE_INLINE void write(uint8_t c)
|
||||||
|
|
@ -109,19 +109,19 @@ class MarlinSerial //: public Stream
|
||||||
M_UDRx = c;
|
M_UDRx = c;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
static void write(uint8_t c)
|
static void write(uint8_t c)
|
||||||
{
|
{
|
||||||
if (selectedSerialPort == 0)
|
if (selectedSerialPort == 0)
|
||||||
{
|
{
|
||||||
while (!((M_UCSRxA) & (1 << M_UDREx)));
|
while (!((M_UCSRxA) & (1 << M_UDREx)));
|
||||||
M_UDRx = c;
|
M_UDRx = c;
|
||||||
}
|
}
|
||||||
else if (selectedSerialPort == 1)
|
else if (selectedSerialPort == 1)
|
||||||
{
|
{
|
||||||
while (!((UCSR1A) & (1 << UDRE1)));
|
while (!((UCSR1A) & (1 << UDRE1)));
|
||||||
UDR1 = c;
|
UDR1 = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkRx(void)
|
static void checkRx(void)
|
||||||
{
|
{
|
||||||
|
|
@ -145,7 +145,7 @@ class MarlinSerial //: public Stream
|
||||||
}
|
}
|
||||||
//selectedSerialPort = 0;
|
//selectedSerialPort = 0;
|
||||||
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
UDR1 = c;
|
UDR1 = c;
|
||||||
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +169,7 @@ class MarlinSerial //: public Stream
|
||||||
}
|
}
|
||||||
//selectedSerialPort = 1;
|
//selectedSerialPort = 1;
|
||||||
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
#ifdef DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
M_UDRx = c;
|
M_UDRx = c;
|
||||||
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,36 +177,36 @@ class MarlinSerial //: public Stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void printNumber(unsigned long, uint8_t);
|
static void printNumber(unsigned long, uint8_t);
|
||||||
static void printFloat(double, uint8_t);
|
static void printFloat(double, uint8_t);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static FORCE_INLINE void write(const char *str)
|
static FORCE_INLINE void write(const char *str)
|
||||||
{
|
{
|
||||||
while (*str)
|
while (*str)
|
||||||
write(*str++);
|
write(*str++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static FORCE_INLINE void write(const uint8_t *buffer, size_t size)
|
static FORCE_INLINE void write(const uint8_t *buffer, size_t size)
|
||||||
{
|
{
|
||||||
while (size--)
|
while (size--)
|
||||||
write(*buffer++);
|
write(*buffer++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static FORCE_INLINE void print(const String &s)
|
/* static FORCE_INLINE void print(const String &s)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)s.length(); i++) {
|
for (int i = 0; i < (int)s.length(); i++) {
|
||||||
write(s[i]);
|
write(s[i]);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
static FORCE_INLINE void print(const char *str)
|
static FORCE_INLINE void print(const char *str)
|
||||||
{
|
{
|
||||||
write(str);
|
write(str);
|
||||||
}
|
}
|
||||||
static void print(char, int = BYTE);
|
static void print(char, int = BYTE);
|
||||||
static void print(unsigned char, int = BYTE);
|
static void print(unsigned char, int = BYTE);
|
||||||
|
|
@ -233,7 +233,7 @@ extern MarlinSerial MSerial;
|
||||||
|
|
||||||
// Use the UART for BT in AT90USB configurations
|
// Use the UART for BT in AT90USB configurations
|
||||||
#if defined(AT90USB) && defined (BTENABLED)
|
#if defined(AT90USB) && defined (BTENABLED)
|
||||||
extern HardwareSerial bt;
|
extern HardwareSerial bt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
12181
Firmware/Marlin_main.cpp
12181
Firmware/Marlin_main.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -160,101 +160,115 @@ uint8_t const SPI_SCK_PIN = SOFT_SPI_SCK_PIN;
|
||||||
* \brief Raw access to SD and SDHC flash memory cards.
|
* \brief Raw access to SD and SDHC flash memory cards.
|
||||||
*/
|
*/
|
||||||
class Sd2Card {
|
class Sd2Card {
|
||||||
public:
|
public:
|
||||||
/** Construct an instance of Sd2Card. */
|
/** Construct an instance of Sd2Card. */
|
||||||
Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0), flash_air_compatible_(false) {}
|
Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0), flash_air_compatible_(false) {}
|
||||||
uint32_t cardSize();
|
uint32_t cardSize();
|
||||||
bool erase(uint32_t firstBlock, uint32_t lastBlock);
|
bool erase(uint32_t firstBlock, uint32_t lastBlock);
|
||||||
bool eraseSingleBlockEnable();
|
bool eraseSingleBlockEnable();
|
||||||
/**
|
/**
|
||||||
* Set SD error code.
|
* Set SD error code.
|
||||||
* \param[in] code value for error code.
|
* \param[in] code value for error code.
|
||||||
*/
|
*/
|
||||||
void error(uint8_t code) {errorCode_ = code;}
|
void error(uint8_t code) {
|
||||||
/**
|
errorCode_ = code;
|
||||||
* \return error code for last error. See Sd2Card.h for a list of error codes.
|
}
|
||||||
*/
|
/**
|
||||||
int errorCode() const {return errorCode_;}
|
* \return error code for last error. See Sd2Card.h for a list of error codes.
|
||||||
/** \return error data for last error. */
|
*/
|
||||||
int errorData() const {return status_;}
|
int errorCode() const {
|
||||||
/**
|
return errorCode_;
|
||||||
* Initialize an SD flash memory card with default clock rate and chip
|
}
|
||||||
* select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
|
/** \return error data for last error. */
|
||||||
*
|
int errorData() const {
|
||||||
* \return true for success or false for failure.
|
return status_;
|
||||||
*/
|
}
|
||||||
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
|
/**
|
||||||
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
|
* Initialize an SD flash memory card with default clock rate and chip
|
||||||
bool readBlock(uint32_t block, uint8_t* dst);
|
* select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
|
||||||
/**
|
*
|
||||||
* Read a card's CID register. The CID contains card identification
|
* \return true for success or false for failure.
|
||||||
* information such as Manufacturer ID, Product name, Product serial
|
*/
|
||||||
* number and Manufacturing date.
|
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
|
||||||
*
|
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
|
||||||
* \param[out] cid pointer to area for returned data.
|
bool readBlock(uint32_t block, uint8_t* dst);
|
||||||
*
|
/**
|
||||||
* \return true for success or false for failure.
|
* Read a card's CID register. The CID contains card identification
|
||||||
*/
|
* information such as Manufacturer ID, Product name, Product serial
|
||||||
bool readCID(cid_t* cid) {
|
* number and Manufacturing date.
|
||||||
return readRegister(CMD10, cid);
|
*
|
||||||
}
|
* \param[out] cid pointer to area for returned data.
|
||||||
/**
|
*
|
||||||
* Read a card's CSD register. The CSD contains Card-Specific Data that
|
* \return true for success or false for failure.
|
||||||
* provides information regarding access to the card's contents.
|
*/
|
||||||
*
|
bool readCID(cid_t* cid) {
|
||||||
* \param[out] csd pointer to area for returned data.
|
return readRegister(CMD10, cid);
|
||||||
*
|
}
|
||||||
* \return true for success or false for failure.
|
/**
|
||||||
*/
|
* Read a card's CSD register. The CSD contains Card-Specific Data that
|
||||||
bool readCSD(csd_t* csd) {
|
* provides information regarding access to the card's contents.
|
||||||
return readRegister(CMD9, csd);
|
*
|
||||||
}
|
* \param[out] csd pointer to area for returned data.
|
||||||
bool readData(uint8_t *dst);
|
*
|
||||||
bool readStart(uint32_t blockNumber);
|
* \return true for success or false for failure.
|
||||||
bool readStop();
|
*/
|
||||||
bool setSckRate(uint8_t sckRateID);
|
bool readCSD(csd_t* csd) {
|
||||||
/** Return the card type: SD V1, SD V2 or SDHC
|
return readRegister(CMD9, csd);
|
||||||
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
|
}
|
||||||
*/
|
bool readData(uint8_t *dst);
|
||||||
int type() const {return type_;}
|
bool readStart(uint32_t blockNumber);
|
||||||
bool writeBlock(uint32_t blockNumber, const uint8_t* src);
|
bool readStop();
|
||||||
bool writeData(const uint8_t* src);
|
bool setSckRate(uint8_t sckRateID);
|
||||||
bool writeStart(uint32_t blockNumber, uint32_t eraseCount);
|
/** Return the card type: SD V1, SD V2 or SDHC
|
||||||
bool writeStop();
|
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
|
||||||
|
*/
|
||||||
|
int type() const {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
bool writeBlock(uint32_t blockNumber, const uint8_t* src);
|
||||||
|
bool writeData(const uint8_t* src);
|
||||||
|
bool writeStart(uint32_t blockNumber, uint32_t eraseCount);
|
||||||
|
bool writeStop();
|
||||||
|
|
||||||
// Toshiba FlashAir support
|
// Toshiba FlashAir support
|
||||||
uint8_t readExtMemory(uint8_t mio, uint8_t func, uint32_t addr, uint16_t count, uint8_t* dst);
|
uint8_t readExtMemory(uint8_t mio, uint8_t func, uint32_t addr, uint16_t count, uint8_t* dst);
|
||||||
|
|
||||||
void setFlashAirCompatible(bool flashAirCompatible) { flash_air_compatible_ = flashAirCompatible; }
|
void setFlashAirCompatible(bool flashAirCompatible) {
|
||||||
bool getFlashAirCompatible() const { return flash_air_compatible_; }
|
flash_air_compatible_ = flashAirCompatible;
|
||||||
|
}
|
||||||
|
bool getFlashAirCompatible() const {
|
||||||
|
return flash_air_compatible_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
uint8_t chipSelectPin_;
|
uint8_t chipSelectPin_;
|
||||||
uint8_t errorCode_;
|
uint8_t errorCode_;
|
||||||
uint8_t spiRate_;
|
uint8_t spiRate_;
|
||||||
uint8_t status_;
|
uint8_t status_;
|
||||||
uint8_t type_;
|
uint8_t type_;
|
||||||
bool flash_air_compatible_;
|
bool flash_air_compatible_;
|
||||||
// private functions
|
// private functions
|
||||||
uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {
|
uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {
|
||||||
cardCommand(CMD55, 0);
|
cardCommand(CMD55, 0);
|
||||||
return cardCommand(cmd, arg);
|
return cardCommand(cmd, arg);
|
||||||
}
|
}
|
||||||
uint8_t cardCommand(uint8_t cmd, uint32_t arg);
|
uint8_t cardCommand(uint8_t cmd, uint32_t arg);
|
||||||
|
|
||||||
bool readData(uint8_t* dst, uint16_t count);
|
bool readData(uint8_t* dst, uint16_t count);
|
||||||
bool readRegister(uint8_t cmd, void* buf);
|
bool readRegister(uint8_t cmd, void* buf);
|
||||||
void chipSelectHigh();
|
void chipSelectHigh();
|
||||||
void chipSelectLow();
|
void chipSelectLow();
|
||||||
void type(uint8_t value) {type_ = value;}
|
void type(uint8_t value) {
|
||||||
bool waitNotBusy(uint16_t timeoutMillis);
|
type_ = value;
|
||||||
bool writeData(uint8_t token, const uint8_t* src);
|
}
|
||||||
|
bool waitNotBusy(uint16_t timeoutMillis);
|
||||||
|
bool writeData(uint8_t token, const uint8_t* src);
|
||||||
|
|
||||||
|
|
||||||
// Toshiba FlashAir support
|
// Toshiba FlashAir support
|
||||||
uint8_t waitStartBlock(void);
|
uint8_t waitStartBlock(void);
|
||||||
uint8_t readExt(uint32_t arg, uint8_t* dst, uint16_t count);
|
uint8_t readExt(uint32_t arg, uint8_t* dst, uint16_t count);
|
||||||
};
|
};
|
||||||
#endif // Sd2Card_h
|
#endif // Sd2Card_h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,10 @@
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** struct for mapping digital pins */
|
/** struct for mapping digital pins */
|
||||||
struct pin_map_t {
|
struct pin_map_t {
|
||||||
volatile uint8_t* ddr;
|
volatile uint8_t* ddr;
|
||||||
volatile uint8_t* pin;
|
volatile uint8_t* pin;
|
||||||
volatile uint8_t* port;
|
volatile uint8_t* port;
|
||||||
uint8_t bit;
|
uint8_t bit;
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#if defined(__AVR_ATmega1280__)\
|
#if defined(__AVR_ATmega1280__)\
|
||||||
|
|
@ -50,76 +50,76 @@ uint8_t const MISO_PIN = 50; // B3
|
||||||
uint8_t const SCK_PIN = 52; // B1
|
uint8_t const SCK_PIN = 52; // B1
|
||||||
|
|
||||||
static const pin_map_t digitalPinMap[] = {
|
static const pin_map_t digitalPinMap[] = {
|
||||||
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
||||||
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
||||||
{&DDRE, &PINE, &PORTE, 4}, // E4 2
|
{&DDRE, &PINE, &PORTE, 4}, // E4 2
|
||||||
{&DDRE, &PINE, &PORTE, 5}, // E5 3
|
{&DDRE, &PINE, &PORTE, 5}, // E5 3
|
||||||
{&DDRG, &PING, &PORTG, 5}, // G5 4
|
{&DDRG, &PING, &PORTG, 5}, // G5 4
|
||||||
{&DDRE, &PINE, &PORTE, 3}, // E3 5
|
{&DDRE, &PINE, &PORTE, 3}, // E3 5
|
||||||
{&DDRH, &PINH, &PORTH, 3}, // H3 6
|
{&DDRH, &PINH, &PORTH, 3}, // H3 6
|
||||||
{&DDRH, &PINH, &PORTH, 4}, // H4 7
|
{&DDRH, &PINH, &PORTH, 4}, // H4 7
|
||||||
{&DDRH, &PINH, &PORTH, 5}, // H5 8
|
{&DDRH, &PINH, &PORTH, 5}, // H5 8
|
||||||
{&DDRH, &PINH, &PORTH, 6}, // H6 9
|
{&DDRH, &PINH, &PORTH, 6}, // H6 9
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
||||||
{&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
|
{&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
|
||||||
{&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
|
{&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
|
||||||
{&DDRH, &PINH, &PORTH, 1}, // H1 16
|
{&DDRH, &PINH, &PORTH, 1}, // H1 16
|
||||||
{&DDRH, &PINH, &PORTH, 0}, // H0 17
|
{&DDRH, &PINH, &PORTH, 0}, // H0 17
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 18
|
{&DDRD, &PIND, &PORTD, 3}, // D3 18
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 19
|
{&DDRD, &PIND, &PORTD, 2}, // D2 19
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 20
|
{&DDRD, &PIND, &PORTD, 1}, // D1 20
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 21
|
{&DDRD, &PIND, &PORTD, 0}, // D0 21
|
||||||
{&DDRA, &PINA, &PORTA, 0}, // A0 22
|
{&DDRA, &PINA, &PORTA, 0}, // A0 22
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 23
|
{&DDRA, &PINA, &PORTA, 1}, // A1 23
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 24
|
{&DDRA, &PINA, &PORTA, 2}, // A2 24
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 25
|
{&DDRA, &PINA, &PORTA, 3}, // A3 25
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 26
|
{&DDRA, &PINA, &PORTA, 4}, // A4 26
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 28
|
{&DDRA, &PINA, &PORTA, 6}, // A6 28
|
||||||
{&DDRA, &PINA, &PORTA, 7}, // A7 29
|
{&DDRA, &PINA, &PORTA, 7}, // A7 29
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 30
|
{&DDRC, &PINC, &PORTC, 7}, // C7 30
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 31
|
{&DDRC, &PINC, &PORTC, 6}, // C6 31
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 32
|
{&DDRC, &PINC, &PORTC, 5}, // C5 32
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 33
|
{&DDRC, &PINC, &PORTC, 4}, // C4 33
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 34
|
{&DDRC, &PINC, &PORTC, 3}, // C3 34
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 35
|
{&DDRC, &PINC, &PORTC, 2}, // C2 35
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 36
|
{&DDRC, &PINC, &PORTC, 1}, // C1 36
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 37
|
{&DDRC, &PINC, &PORTC, 0}, // C0 37
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 38
|
{&DDRD, &PIND, &PORTD, 7}, // D7 38
|
||||||
{&DDRG, &PING, &PORTG, 2}, // G2 39
|
{&DDRG, &PING, &PORTG, 2}, // G2 39
|
||||||
{&DDRG, &PING, &PORTG, 1}, // G1 40
|
{&DDRG, &PING, &PORTG, 1}, // G1 40
|
||||||
{&DDRG, &PING, &PORTG, 0}, // G0 41
|
{&DDRG, &PING, &PORTG, 0}, // G0 41
|
||||||
{&DDRL, &PINL, &PORTL, 7}, // L7 42
|
{&DDRL, &PINL, &PORTL, 7}, // L7 42
|
||||||
{&DDRL, &PINL, &PORTL, 6}, // L6 43
|
{&DDRL, &PINL, &PORTL, 6}, // L6 43
|
||||||
{&DDRL, &PINL, &PORTL, 5}, // L5 44
|
{&DDRL, &PINL, &PORTL, 5}, // L5 44
|
||||||
{&DDRL, &PINL, &PORTL, 4}, // L4 45
|
{&DDRL, &PINL, &PORTL, 4}, // L4 45
|
||||||
{&DDRL, &PINL, &PORTL, 3}, // L3 46
|
{&DDRL, &PINL, &PORTL, 3}, // L3 46
|
||||||
{&DDRL, &PINL, &PORTL, 2}, // L2 47
|
{&DDRL, &PINL, &PORTL, 2}, // L2 47
|
||||||
{&DDRL, &PINL, &PORTL, 1}, // L1 48
|
{&DDRL, &PINL, &PORTL, 1}, // L1 48
|
||||||
{&DDRL, &PINL, &PORTL, 0}, // L0 49
|
{&DDRL, &PINL, &PORTL, 0}, // L0 49
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 50
|
{&DDRB, &PINB, &PORTB, 3}, // B3 50
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 51
|
{&DDRB, &PINB, &PORTB, 2}, // B2 51
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 52
|
{&DDRB, &PINB, &PORTB, 1}, // B1 52
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 53
|
{&DDRB, &PINB, &PORTB, 0}, // B0 53
|
||||||
{&DDRF, &PINF, &PORTF, 0}, // F0 54
|
{&DDRF, &PINF, &PORTF, 0}, // F0 54
|
||||||
{&DDRF, &PINF, &PORTF, 1}, // F1 55
|
{&DDRF, &PINF, &PORTF, 1}, // F1 55
|
||||||
{&DDRF, &PINF, &PORTF, 2}, // F2 56
|
{&DDRF, &PINF, &PORTF, 2}, // F2 56
|
||||||
{&DDRF, &PINF, &PORTF, 3}, // F3 57
|
{&DDRF, &PINF, &PORTF, 3}, // F3 57
|
||||||
{&DDRF, &PINF, &PORTF, 4}, // F4 58
|
{&DDRF, &PINF, &PORTF, 4}, // F4 58
|
||||||
{&DDRF, &PINF, &PORTF, 5}, // F5 59
|
{&DDRF, &PINF, &PORTF, 5}, // F5 59
|
||||||
{&DDRF, &PINF, &PORTF, 6}, // F6 60
|
{&DDRF, &PINF, &PORTF, 6}, // F6 60
|
||||||
{&DDRF, &PINF, &PORTF, 7}, // F7 61
|
{&DDRF, &PINF, &PORTF, 7}, // F7 61
|
||||||
{&DDRK, &PINK, &PORTK, 0}, // K0 62
|
{&DDRK, &PINK, &PORTK, 0}, // K0 62
|
||||||
{&DDRK, &PINK, &PORTK, 1}, // K1 63
|
{&DDRK, &PINK, &PORTK, 1}, // K1 63
|
||||||
{&DDRK, &PINK, &PORTK, 2}, // K2 64
|
{&DDRK, &PINK, &PORTK, 2}, // K2 64
|
||||||
{&DDRK, &PINK, &PORTK, 3}, // K3 65
|
{&DDRK, &PINK, &PORTK, 3}, // K3 65
|
||||||
{&DDRK, &PINK, &PORTK, 4}, // K4 66
|
{&DDRK, &PINK, &PORTK, 4}, // K4 66
|
||||||
{&DDRK, &PINK, &PORTK, 5}, // K5 67
|
{&DDRK, &PINK, &PORTK, 5}, // K5 67
|
||||||
{&DDRK, &PINK, &PORTK, 6}, // K6 68
|
{&DDRK, &PINK, &PORTK, 6}, // K6 68
|
||||||
{&DDRK, &PINK, &PORTK, 7} // K7 69
|
{&DDRK, &PINK, &PORTK, 7} // K7 69
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#elif defined(__AVR_ATmega644P__)\
|
#elif defined(__AVR_ATmega644P__)\
|
||||||
|
|
@ -138,38 +138,38 @@ uint8_t const MISO_PIN = 6; // B6
|
||||||
uint8_t const SCK_PIN = 7; // B7
|
uint8_t const SCK_PIN = 7; // B7
|
||||||
|
|
||||||
static const pin_map_t digitalPinMap[] = {
|
static const pin_map_t digitalPinMap[] = {
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
||||||
{&DDRA, &PINA, &PORTA, 7}, // A7 24
|
{&DDRA, &PINA, &PORTA, 7}, // A7 24
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 26
|
{&DDRA, &PINA, &PORTA, 5}, // A5 26
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 27
|
{&DDRA, &PINA, &PORTA, 4}, // A4 27
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 28
|
{&DDRA, &PINA, &PORTA, 3}, // A3 28
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 29
|
{&DDRA, &PINA, &PORTA, 2}, // A2 29
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 30
|
{&DDRA, &PINA, &PORTA, 1}, // A1 30
|
||||||
{&DDRA, &PINA, &PORTA, 0} // A0 31
|
{&DDRA, &PINA, &PORTA, 0} // A0 31
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#elif defined(__AVR_ATmega32U4__)
|
#elif defined(__AVR_ATmega32U4__)
|
||||||
|
|
@ -186,31 +186,31 @@ uint8_t const MISO_PIN = 3; // B3
|
||||||
uint8_t const SCK_PIN = 1; // B1
|
uint8_t const SCK_PIN = 1; // B1
|
||||||
|
|
||||||
static const pin_map_t digitalPinMap[] = {
|
static const pin_map_t digitalPinMap[] = {
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 4
|
{&DDRB, &PINB, &PORTB, 7}, // B7 4
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 5
|
{&DDRD, &PIND, &PORTD, 0}, // D0 5
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 6
|
{&DDRD, &PIND, &PORTD, 1}, // D1 6
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 7
|
{&DDRD, &PIND, &PORTD, 2}, // D2 7
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 8
|
{&DDRD, &PIND, &PORTD, 3}, // D3 8
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 9
|
{&DDRC, &PINC, &PORTC, 6}, // C6 9
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 10
|
{&DDRC, &PINC, &PORTC, 7}, // C7 10
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 11
|
{&DDRD, &PIND, &PORTD, 6}, // D6 11
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 12
|
{&DDRD, &PIND, &PORTD, 7}, // D7 12
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 13
|
{&DDRB, &PINB, &PORTB, 4}, // B4 13
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 14
|
{&DDRB, &PINB, &PORTB, 5}, // B5 14
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 15
|
{&DDRB, &PINB, &PORTB, 6}, // B6 15
|
||||||
{&DDRF, &PINF, &PORTF, 7}, // F7 16
|
{&DDRF, &PINF, &PORTF, 7}, // F7 16
|
||||||
{&DDRF, &PINF, &PORTF, 6}, // F6 17
|
{&DDRF, &PINF, &PORTF, 6}, // F6 17
|
||||||
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
||||||
{&DDRF, &PINF, &PORTF, 4}, // F4 19
|
{&DDRF, &PINF, &PORTF, 4}, // F4 19
|
||||||
{&DDRF, &PINF, &PORTF, 1}, // F1 20
|
{&DDRF, &PINF, &PORTF, 1}, // F1 20
|
||||||
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 22
|
{&DDRD, &PIND, &PORTD, 4}, // D4 22
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 23
|
{&DDRD, &PIND, &PORTD, 5}, // D5 23
|
||||||
{&DDRE, &PINE, &PORTE, 6} // E6 24
|
{&DDRE, &PINE, &PORTE, 6} // E6 24
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#elif defined(__AVR_AT90USB646__)\
|
#elif defined(__AVR_AT90USB646__)\
|
||||||
|
|
@ -228,52 +228,52 @@ uint8_t const MISO_PIN = 23; // B3
|
||||||
uint8_t const SCK_PIN = 21; // B1
|
uint8_t const SCK_PIN = 21; // B1
|
||||||
|
|
||||||
static const pin_map_t digitalPinMap[] = {
|
static const pin_map_t digitalPinMap[] = {
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||||
{&DDRE, &PINE, &PORTE, 0}, // E0 8
|
{&DDRE, &PINE, &PORTE, 0}, // E0 8
|
||||||
{&DDRE, &PINE, &PORTE, 1}, // E1 9
|
{&DDRE, &PINE, &PORTE, 1}, // E1 9
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 10
|
{&DDRC, &PINC, &PORTC, 0}, // C0 10
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 11
|
{&DDRC, &PINC, &PORTC, 1}, // C1 11
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 12
|
{&DDRC, &PINC, &PORTC, 2}, // C2 12
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 13
|
{&DDRC, &PINC, &PORTC, 3}, // C3 13
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 14
|
{&DDRC, &PINC, &PORTC, 4}, // C4 14
|
||||||
{&DDRC, &PINC, &PORTC, 5}, // C5 15
|
{&DDRC, &PINC, &PORTC, 5}, // C5 15
|
||||||
{&DDRC, &PINC, &PORTC, 6}, // C6 16
|
{&DDRC, &PINC, &PORTC, 6}, // C6 16
|
||||||
{&DDRC, &PINC, &PORTC, 7}, // C7 17
|
{&DDRC, &PINC, &PORTC, 7}, // C7 17
|
||||||
{&DDRE, &PINE, &PORTE, 6}, // E6 18
|
{&DDRE, &PINE, &PORTE, 6}, // E6 18
|
||||||
{&DDRE, &PINE, &PORTE, 7}, // E7 19
|
{&DDRE, &PINE, &PORTE, 7}, // E7 19
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 20
|
{&DDRB, &PINB, &PORTB, 0}, // B0 20
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 21
|
{&DDRB, &PINB, &PORTB, 1}, // B1 21
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 22
|
{&DDRB, &PINB, &PORTB, 2}, // B2 22
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 23
|
{&DDRB, &PINB, &PORTB, 3}, // B3 23
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 24
|
{&DDRB, &PINB, &PORTB, 4}, // B4 24
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 25
|
{&DDRB, &PINB, &PORTB, 5}, // B5 25
|
||||||
{&DDRB, &PINB, &PORTB, 6}, // B6 26
|
{&DDRB, &PINB, &PORTB, 6}, // B6 26
|
||||||
{&DDRB, &PINB, &PORTB, 7}, // B7 27
|
{&DDRB, &PINB, &PORTB, 7}, // B7 27
|
||||||
{&DDRA, &PINA, &PORTA, 0}, // A0 28
|
{&DDRA, &PINA, &PORTA, 0}, // A0 28
|
||||||
{&DDRA, &PINA, &PORTA, 1}, // A1 29
|
{&DDRA, &PINA, &PORTA, 1}, // A1 29
|
||||||
{&DDRA, &PINA, &PORTA, 2}, // A2 30
|
{&DDRA, &PINA, &PORTA, 2}, // A2 30
|
||||||
{&DDRA, &PINA, &PORTA, 3}, // A3 31
|
{&DDRA, &PINA, &PORTA, 3}, // A3 31
|
||||||
{&DDRA, &PINA, &PORTA, 4}, // A4 32
|
{&DDRA, &PINA, &PORTA, 4}, // A4 32
|
||||||
{&DDRA, &PINA, &PORTA, 5}, // A5 33
|
{&DDRA, &PINA, &PORTA, 5}, // A5 33
|
||||||
{&DDRA, &PINA, &PORTA, 6}, // A6 34
|
{&DDRA, &PINA, &PORTA, 6}, // A6 34
|
||||||
{&DDRA, &PINA, &PORTA, 7}, // A7 35
|
{&DDRA, &PINA, &PORTA, 7}, // A7 35
|
||||||
{&DDRE, &PINE, &PORTE, 4}, // E4 36
|
{&DDRE, &PINE, &PORTE, 4}, // E4 36
|
||||||
{&DDRE, &PINE, &PORTE, 5}, // E5 37
|
{&DDRE, &PINE, &PORTE, 5}, // E5 37
|
||||||
{&DDRF, &PINF, &PORTF, 0}, // F0 38
|
{&DDRF, &PINF, &PORTF, 0}, // F0 38
|
||||||
{&DDRF, &PINF, &PORTF, 1}, // F1 39
|
{&DDRF, &PINF, &PORTF, 1}, // F1 39
|
||||||
{&DDRF, &PINF, &PORTF, 2}, // F2 40
|
{&DDRF, &PINF, &PORTF, 2}, // F2 40
|
||||||
{&DDRF, &PINF, &PORTF, 3}, // F3 41
|
{&DDRF, &PINF, &PORTF, 3}, // F3 41
|
||||||
{&DDRF, &PINF, &PORTF, 4}, // F4 42
|
{&DDRF, &PINF, &PORTF, 4}, // F4 42
|
||||||
{&DDRF, &PINF, &PORTF, 5}, // F5 43
|
{&DDRF, &PINF, &PORTF, 5}, // F5 43
|
||||||
{&DDRF, &PINF, &PORTF, 6}, // F6 44
|
{&DDRF, &PINF, &PORTF, 6}, // F6 44
|
||||||
{&DDRF, &PINF, &PORTF, 7} // F7 45
|
{&DDRF, &PINF, &PORTF, 7} // F7 45
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
#elif defined(__AVR_ATmega168__)\
|
#elif defined(__AVR_ATmega168__)\
|
||||||
|
|
@ -292,26 +292,26 @@ uint8_t const MISO_PIN = 12; // B4
|
||||||
uint8_t const SCK_PIN = 13; // B5
|
uint8_t const SCK_PIN = 13; // B5
|
||||||
|
|
||||||
static const pin_map_t digitalPinMap[] = {
|
static const pin_map_t digitalPinMap[] = {
|
||||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||||
{&DDRB, &PINB, &PORTB, 0}, // B0 8
|
{&DDRB, &PINB, &PORTB, 0}, // B0 8
|
||||||
{&DDRB, &PINB, &PORTB, 1}, // B1 9
|
{&DDRB, &PINB, &PORTB, 1}, // B1 9
|
||||||
{&DDRB, &PINB, &PORTB, 2}, // B2 10
|
{&DDRB, &PINB, &PORTB, 2}, // B2 10
|
||||||
{&DDRB, &PINB, &PORTB, 3}, // B3 11
|
{&DDRB, &PINB, &PORTB, 3}, // B3 11
|
||||||
{&DDRB, &PINB, &PORTB, 4}, // B4 12
|
{&DDRB, &PINB, &PORTB, 4}, // B4 12
|
||||||
{&DDRB, &PINB, &PORTB, 5}, // B5 13
|
{&DDRB, &PINB, &PORTB, 5}, // B5 13
|
||||||
{&DDRC, &PINC, &PORTC, 0}, // C0 14
|
{&DDRC, &PINC, &PORTC, 0}, // C0 14
|
||||||
{&DDRC, &PINC, &PORTC, 1}, // C1 15
|
{&DDRC, &PINC, &PORTC, 1}, // C1 15
|
||||||
{&DDRC, &PINC, &PORTC, 2}, // C2 16
|
{&DDRC, &PINC, &PORTC, 2}, // C2 16
|
||||||
{&DDRC, &PINC, &PORTC, 3}, // C3 17
|
{&DDRC, &PINC, &PORTC, 3}, // C3 17
|
||||||
{&DDRC, &PINC, &PORTC, 4}, // C4 18
|
{&DDRC, &PINC, &PORTC, 4}, // C4 18
|
||||||
{&DDRC, &PINC, &PORTC, 5} // C5 19
|
{&DDRC, &PINC, &PORTC, 5} // C5 19
|
||||||
};
|
};
|
||||||
#else // defined(__AVR_ATmega1280__)
|
#else // defined(__AVR_ATmega1280__)
|
||||||
#error unknown chip
|
#error unknown chip
|
||||||
|
|
@ -320,47 +320,47 @@ static const pin_map_t digitalPinMap[] = {
|
||||||
static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);
|
static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);
|
||||||
|
|
||||||
uint8_t badPinNumber(void)
|
uint8_t badPinNumber(void)
|
||||||
__attribute__((error("Pin number is too large or not a constant")));
|
__attribute__((error("Pin number is too large or not a constant")));
|
||||||
|
|
||||||
static inline __attribute__((always_inline))
|
static inline __attribute__((always_inline))
|
||||||
bool getPinMode(uint8_t pin) {
|
bool getPinMode(uint8_t pin) {
|
||||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
||||||
return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
|
return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
|
||||||
} else {
|
|
||||||
return badPinNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static inline __attribute__((always_inline))
|
|
||||||
void setPinMode(uint8_t pin, uint8_t mode) {
|
|
||||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
|
||||||
if (mode) {
|
|
||||||
*digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit;
|
|
||||||
} else {
|
} else {
|
||||||
*digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit);
|
return badPinNumber();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
badPinNumber();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static inline __attribute__((always_inline))
|
static inline __attribute__((always_inline))
|
||||||
bool fastDigitalRead(uint8_t pin) {
|
void setPinMode(uint8_t pin, uint8_t mode) {
|
||||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
||||||
return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;
|
if (mode) {
|
||||||
} else {
|
*digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit;
|
||||||
return badPinNumber();
|
} else {
|
||||||
}
|
*digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit);
|
||||||
}
|
}
|
||||||
static inline __attribute__((always_inline))
|
|
||||||
void fastDigitalWrite(uint8_t pin, uint8_t value) {
|
|
||||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
|
||||||
if (value) {
|
|
||||||
*digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit;
|
|
||||||
} else {
|
} else {
|
||||||
*digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit);
|
badPinNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
return badPinNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void fastDigitalWrite(uint8_t pin, uint8_t value) {
|
||||||
|
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
||||||
|
if (value) {
|
||||||
|
*digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit;
|
||||||
|
} else {
|
||||||
|
*digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
badPinNumber();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
badPinNumber();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif // Sd2PinMap_h
|
#endif // Sd2PinMap_h
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -36,11 +36,11 @@
|
||||||
* do not use in user apps
|
* do not use in user apps
|
||||||
*/
|
*/
|
||||||
struct filepos_t {
|
struct filepos_t {
|
||||||
/** stream position */
|
/** stream position */
|
||||||
uint32_t position;
|
uint32_t position;
|
||||||
/** cluster for position */
|
/** cluster for position */
|
||||||
uint32_t cluster;
|
uint32_t cluster;
|
||||||
filepos_t() : position(0), cluster(0) {}
|
filepos_t() : position(0), cluster(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// use the gnu style oflag in open()
|
// use the gnu style oflag in open()
|
||||||
|
|
@ -108,7 +108,7 @@ uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED;
|
||||||
* \return Packed date for dir_t entry.
|
* \return Packed date for dir_t entry.
|
||||||
*/
|
*/
|
||||||
static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
|
static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
|
||||||
return (year - 1980) << 9 | month << 5 | day;
|
return (year - 1980) << 9 | month << 5 | day;
|
||||||
}
|
}
|
||||||
/** year part of FAT directory date field
|
/** year part of FAT directory date field
|
||||||
* \param[in] fatDate Date in packed dir format.
|
* \param[in] fatDate Date in packed dir format.
|
||||||
|
|
@ -116,7 +116,7 @@ static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
|
||||||
* \return Extracted year [1980,2107]
|
* \return Extracted year [1980,2107]
|
||||||
*/
|
*/
|
||||||
static inline uint16_t FAT_YEAR(uint16_t fatDate) {
|
static inline uint16_t FAT_YEAR(uint16_t fatDate) {
|
||||||
return 1980 + (fatDate >> 9);
|
return 1980 + (fatDate >> 9);
|
||||||
}
|
}
|
||||||
/** month part of FAT directory date field
|
/** month part of FAT directory date field
|
||||||
* \param[in] fatDate Date in packed dir format.
|
* \param[in] fatDate Date in packed dir format.
|
||||||
|
|
@ -124,7 +124,7 @@ static inline uint16_t FAT_YEAR(uint16_t fatDate) {
|
||||||
* \return Extracted month [1,12]
|
* \return Extracted month [1,12]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_MONTH(uint16_t fatDate) {
|
static inline uint8_t FAT_MONTH(uint16_t fatDate) {
|
||||||
return (fatDate >> 5) & 0XF;
|
return (fatDate >> 5) & 0XF;
|
||||||
}
|
}
|
||||||
/** day part of FAT directory date field
|
/** day part of FAT directory date field
|
||||||
* \param[in] fatDate Date in packed dir format.
|
* \param[in] fatDate Date in packed dir format.
|
||||||
|
|
@ -132,7 +132,7 @@ static inline uint8_t FAT_MONTH(uint16_t fatDate) {
|
||||||
* \return Extracted day [1,31]
|
* \return Extracted day [1,31]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_DAY(uint16_t fatDate) {
|
static inline uint8_t FAT_DAY(uint16_t fatDate) {
|
||||||
return fatDate & 0X1F;
|
return fatDate & 0X1F;
|
||||||
}
|
}
|
||||||
/** time field for FAT directory entry
|
/** time field for FAT directory entry
|
||||||
* \param[in] hour [0,23]
|
* \param[in] hour [0,23]
|
||||||
|
|
@ -142,7 +142,7 @@ static inline uint8_t FAT_DAY(uint16_t fatDate) {
|
||||||
* \return Packed time for dir_t entry.
|
* \return Packed time for dir_t entry.
|
||||||
*/
|
*/
|
||||||
static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
|
static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
|
||||||
return hour << 11 | minute << 5 | second >> 1;
|
return hour << 11 | minute << 5 | second >> 1;
|
||||||
}
|
}
|
||||||
/** hour part of FAT directory time field
|
/** hour part of FAT directory time field
|
||||||
* \param[in] fatTime Time in packed dir format.
|
* \param[in] fatTime Time in packed dir format.
|
||||||
|
|
@ -150,7 +150,7 @@ static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
|
||||||
* \return Extracted hour [0,23]
|
* \return Extracted hour [0,23]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_HOUR(uint16_t fatTime) {
|
static inline uint8_t FAT_HOUR(uint16_t fatTime) {
|
||||||
return fatTime >> 11;
|
return fatTime >> 11;
|
||||||
}
|
}
|
||||||
/** minute part of FAT directory time field
|
/** minute part of FAT directory time field
|
||||||
* \param[in] fatTime Time in packed dir format.
|
* \param[in] fatTime Time in packed dir format.
|
||||||
|
|
@ -158,7 +158,7 @@ static inline uint8_t FAT_HOUR(uint16_t fatTime) {
|
||||||
* \return Extracted minute [0,59]
|
* \return Extracted minute [0,59]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
||||||
return(fatTime >> 5) & 0X3F;
|
return(fatTime >> 5) & 0X3F;
|
||||||
}
|
}
|
||||||
/** second part of FAT directory time field
|
/** second part of FAT directory time field
|
||||||
* Note second/2 is stored in packed time.
|
* Note second/2 is stored in packed time.
|
||||||
|
|
@ -168,7 +168,7 @@ static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
||||||
* \return Extracted second [0,58]
|
* \return Extracted second [0,58]
|
||||||
*/
|
*/
|
||||||
static inline uint8_t FAT_SECOND(uint16_t fatTime) {
|
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 */
|
/** Default date for file timestamps is 1 Jan 2000 */
|
||||||
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
|
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
|
||||||
|
|
@ -180,302 +180,340 @@ uint16_t const FAT_DEFAULT_TIME = (1 << 11);
|
||||||
* \brief Base class for SdFile with Print and C++ streams.
|
* \brief Base class for SdFile with Print and C++ streams.
|
||||||
*/
|
*/
|
||||||
class SdBaseFile {
|
class SdBaseFile {
|
||||||
public:
|
public:
|
||||||
/** Create an instance. */
|
/** Create an instance. */
|
||||||
SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
|
SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
|
||||||
SdBaseFile(const char* path, uint8_t oflag);
|
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
|
/**
|
||||||
* for true after calls to print() and/or write().
|
* writeError is set to true if an error occurs during a write().
|
||||||
*/
|
* Set writeError to false before calling print() and/or write() and check
|
||||||
bool writeError;
|
* for true after calls to print() and/or write().
|
||||||
//----------------------------------------------------------------------------
|
*/
|
||||||
// helpers for stream classes
|
bool writeError;
|
||||||
/** get position for streams
|
//----------------------------------------------------------------------------
|
||||||
* \param[out] pos struct to receive position
|
// helpers for stream classes
|
||||||
*/
|
/** get position for streams
|
||||||
void getpos(filepos_t* pos);
|
* \param[out] pos struct to receive position
|
||||||
/** set position for streams
|
*/
|
||||||
* \param[out] pos struct with value for new position
|
void getpos(filepos_t* pos);
|
||||||
*/
|
/** set position for streams
|
||||||
void setpos(filepos_t* pos);
|
* \param[out] pos struct with value for new position
|
||||||
//----------------------------------------------------------------------------
|
*/
|
||||||
bool close();
|
void setpos(filepos_t* pos);
|
||||||
bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
|
//----------------------------------------------------------------------------
|
||||||
bool createContiguous(SdBaseFile* dirFile,
|
bool close();
|
||||||
const char* path, uint32_t size);
|
bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
|
||||||
/** \return The current cluster number for a file or directory. */
|
bool createContiguous(SdBaseFile* dirFile,
|
||||||
uint32_t curCluster() const {return curCluster_;}
|
const char* path, uint32_t size);
|
||||||
/** \return The current position for a file or directory. */
|
/** \return The current cluster number for a file or directory. */
|
||||||
uint32_t curPosition() const {return curPosition_;}
|
uint32_t curCluster() const {
|
||||||
/** \return Current working directory */
|
return curCluster_;
|
||||||
static SdBaseFile* cwd() {return cwd_;}
|
}
|
||||||
/** Set the date/time callback function
|
/** \return The current position for a file or directory. */
|
||||||
*
|
uint32_t curPosition() const {
|
||||||
* \param[in] dateTime The user's call back function. The callback
|
return curPosition_;
|
||||||
* function is of the form:
|
}
|
||||||
*
|
/** \return Current working directory */
|
||||||
* \code
|
static SdBaseFile* cwd() {
|
||||||
* void dateTime(uint16_t* date, uint16_t* time) {
|
return cwd_;
|
||||||
* uint16_t year;
|
}
|
||||||
* uint8_t month, day, hour, minute, second;
|
/** Set the date/time callback function
|
||||||
*
|
*
|
||||||
* // User gets date and time from GPS or real-time clock here
|
* \param[in] dateTime The user's call back function. The callback
|
||||||
*
|
* function is of the form:
|
||||||
* // return date using FAT_DATE macro to format fields
|
*
|
||||||
* *date = FAT_DATE(year, month, day);
|
* \code
|
||||||
*
|
* void dateTime(uint16_t* date, uint16_t* time) {
|
||||||
* // return time using FAT_TIME macro to format fields
|
* uint16_t year;
|
||||||
* *time = FAT_TIME(hour, minute, second);
|
* uint8_t month, day, hour, minute, second;
|
||||||
* }
|
*
|
||||||
* \endcode
|
* // User gets date and time from GPS or real-time clock here
|
||||||
*
|
*
|
||||||
* Sets the function that is called when a file is created or when
|
* // return date using FAT_DATE macro to format fields
|
||||||
* a file's directory entry is modified by sync(). All timestamps,
|
* *date = FAT_DATE(year, month, day);
|
||||||
* access, creation, and modify, are set when a file is created.
|
*
|
||||||
* sync() maintains the last access date and last modify date/time.
|
* // return time using FAT_TIME macro to format fields
|
||||||
*
|
* *time = FAT_TIME(hour, minute, second);
|
||||||
* See the timestamp() function.
|
* }
|
||||||
*/
|
* \endcode
|
||||||
static void dateTimeCallback(
|
*
|
||||||
void (*dateTime)(uint16_t* date, uint16_t* time)) {
|
* Sets the function that is called when a file is created or when
|
||||||
dateTime_ = dateTime;
|
* a file's directory entry is modified by sync(). All timestamps,
|
||||||
}
|
* access, creation, and modify, are set when a file is created.
|
||||||
/** Cancel the date/time callback function. */
|
* sync() maintains the last access date and last modify date/time.
|
||||||
static void dateTimeCallbackCancel() {dateTime_ = 0;}
|
*
|
||||||
bool dirEntry(dir_t* dir);
|
* See the timestamp() function.
|
||||||
static void dirName(const dir_t& dir, char* name);
|
*/
|
||||||
bool exists(const char* name);
|
static void dateTimeCallback(
|
||||||
int16_t fgets(char* str, int16_t num, char* delim = 0);
|
void (*dateTime)(uint16_t* date, uint16_t* time)) {
|
||||||
/** \return The total number of bytes in a file or directory. */
|
dateTime_ = dateTime;
|
||||||
uint32_t fileSize() const {return fileSize_;}
|
}
|
||||||
/** \return The first cluster number for a file or directory. */
|
/** Cancel the date/time callback function. */
|
||||||
uint32_t firstCluster() const {return firstCluster_;}
|
static void dateTimeCallbackCancel() {
|
||||||
bool getFilename(char* name);
|
dateTime_ = 0;
|
||||||
/** \return True if this is a directory else false. */
|
}
|
||||||
bool isDir() const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
|
bool dirEntry(dir_t* dir);
|
||||||
/** \return True if this is a normal file else false. */
|
static void dirName(const dir_t& dir, char* name);
|
||||||
bool isFile() const {return type_ == FAT_FILE_TYPE_NORMAL;}
|
bool exists(const char* name);
|
||||||
/** \return True if this is an open file/directory else false. */
|
int16_t fgets(char* str, int16_t num, char* delim = 0);
|
||||||
bool isOpen() const {return type_ != FAT_FILE_TYPE_CLOSED;}
|
/** \return The total number of bytes in a file or directory. */
|
||||||
/** \return True if this is a subdirectory else false. */
|
uint32_t fileSize() const {
|
||||||
bool isSubDir() const {return type_ == FAT_FILE_TYPE_SUBDIR;}
|
return fileSize_;
|
||||||
/** \return True if this is the root directory. */
|
}
|
||||||
bool isRoot() const {
|
/** \return The first cluster number for a file or directory. */
|
||||||
return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
|
uint32_t firstCluster() const {
|
||||||
}
|
return firstCluster_;
|
||||||
void ls( uint8_t flags = 0, uint8_t indent = 0);
|
}
|
||||||
bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
|
bool getFilename(char* name);
|
||||||
// alias for backward compactability
|
/** \return True if this is a directory else false. */
|
||||||
bool makeDir(SdBaseFile* dir, const char* path) {
|
bool isDir() const {
|
||||||
return mkdir(dir, path, false);
|
return type_ >= FAT_FILE_TYPE_MIN_DIR;
|
||||||
}
|
}
|
||||||
bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
|
/** \return True if this is a normal file else false. */
|
||||||
bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
|
bool isFile() const {
|
||||||
bool open(const char* path, uint8_t oflag = O_READ);
|
return type_ == FAT_FILE_TYPE_NORMAL;
|
||||||
bool openNext(SdBaseFile* dirFile, uint8_t oflag);
|
}
|
||||||
bool openRoot(SdVolume* vol);
|
/** \return True if this is an open file/directory else false. */
|
||||||
int peek();
|
bool isOpen() const {
|
||||||
static void printFatDate(uint16_t fatDate);
|
return type_ != FAT_FILE_TYPE_CLOSED;
|
||||||
static void printFatTime( uint16_t fatTime);
|
}
|
||||||
bool printName();
|
/** \return True if this is a subdirectory else false. */
|
||||||
int16_t read();
|
bool isSubDir() const {
|
||||||
int16_t read(void* buf, uint16_t nbyte);
|
return type_ == FAT_FILE_TYPE_SUBDIR;
|
||||||
int8_t readDir(dir_t* dir, char* longFilename);
|
}
|
||||||
static bool remove(SdBaseFile* dirFile, const char* path);
|
/** \return True if this is the root directory. */
|
||||||
bool remove();
|
bool isRoot() const {
|
||||||
/** Set the file's current position to zero. */
|
return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
|
||||||
void rewind() {seekSet(0);}
|
}
|
||||||
bool rename(SdBaseFile* dirFile, const char* newPath);
|
void ls( uint8_t flags = 0, uint8_t indent = 0);
|
||||||
bool rmdir();
|
bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
|
||||||
// for backward compatibility
|
// alias for backward compactability
|
||||||
bool rmDir() {return rmdir();}
|
bool makeDir(SdBaseFile* dir, const char* path) {
|
||||||
bool rmRfStar();
|
return mkdir(dir, path, false);
|
||||||
/** Set the files position to current position + \a pos. See seekSet().
|
}
|
||||||
* \param[in] offset The new position in bytes from the current position.
|
bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
|
||||||
* \return true for success or false for failure.
|
bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
|
||||||
*/
|
bool open(const char* path, uint8_t oflag = O_READ);
|
||||||
bool seekCur(int32_t offset) {
|
bool openNext(SdBaseFile* dirFile, uint8_t oflag);
|
||||||
return seekSet(curPosition_ + offset);
|
bool openRoot(SdVolume* vol);
|
||||||
}
|
int peek();
|
||||||
/** Set the files position to end-of-file + \a offset. See seekSet().
|
static void printFatDate(uint16_t fatDate);
|
||||||
* \param[in] offset The new position in bytes from end-of-file.
|
static void printFatTime( uint16_t fatTime);
|
||||||
* \return true for success or false for failure.
|
bool printName();
|
||||||
*/
|
int16_t read();
|
||||||
bool seekEnd(int32_t offset = 0) {return seekSet(fileSize_ + offset);}
|
int16_t read(void* buf, uint16_t nbyte);
|
||||||
bool seekSet(uint32_t pos);
|
int8_t readDir(dir_t* dir, char* longFilename);
|
||||||
bool sync();
|
static bool remove(SdBaseFile* dirFile, const char* path);
|
||||||
bool timestamp(SdBaseFile* file);
|
bool remove();
|
||||||
bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
|
/** Set the file's current position to zero. */
|
||||||
uint8_t hour, uint8_t minute, uint8_t second);
|
void rewind() {
|
||||||
/** Type of file. You should use isFile() or isDir() instead of type()
|
seekSet(0);
|
||||||
* if possible.
|
}
|
||||||
*
|
bool rename(SdBaseFile* dirFile, const char* newPath);
|
||||||
* \return The file or directory type.
|
bool rmdir();
|
||||||
*/
|
// for backward compatibility
|
||||||
uint8_t type() const {return type_;}
|
bool rmDir() {
|
||||||
bool truncate(uint32_t size);
|
return rmdir();
|
||||||
/** \return SdVolume that contains this file. */
|
}
|
||||||
SdVolume* volume() const {return vol_;}
|
bool rmRfStar();
|
||||||
int16_t write(const void* buf, uint16_t nbyte);
|
/** Set the files position to current position + \a pos. See seekSet().
|
||||||
|
* \param[in] offset The new position in bytes from the current position.
|
||||||
|
* \return true for success or false for failure.
|
||||||
|
*/
|
||||||
|
bool seekCur(int32_t offset) {
|
||||||
|
return seekSet(curPosition_ + offset);
|
||||||
|
}
|
||||||
|
/** Set the files position to end-of-file + \a offset. See seekSet().
|
||||||
|
* \param[in] offset The new position in bytes from end-of-file.
|
||||||
|
* \return true for success or false for failure.
|
||||||
|
*/
|
||||||
|
bool seekEnd(int32_t offset = 0) {
|
||||||
|
return seekSet(fileSize_ + offset);
|
||||||
|
}
|
||||||
|
bool seekSet(uint32_t pos);
|
||||||
|
bool sync();
|
||||||
|
bool timestamp(SdBaseFile* file);
|
||||||
|
bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
|
||||||
|
uint8_t hour, uint8_t minute, uint8_t second);
|
||||||
|
/** Type of file. You should use isFile() or isDir() instead of type()
|
||||||
|
* if possible.
|
||||||
|
*
|
||||||
|
* \return The file or directory type.
|
||||||
|
*/
|
||||||
|
uint8_t type() const {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
bool truncate(uint32_t size);
|
||||||
|
/** \return SdVolume that contains this file. */
|
||||||
|
SdVolume* volume() const {
|
||||||
|
return vol_;
|
||||||
|
}
|
||||||
|
int16_t write(const void* buf, uint16_t nbyte);
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
// allow SdFat to set cwd_
|
// allow SdFat to set cwd_
|
||||||
friend class SdFat;
|
friend class SdFat;
|
||||||
// global pointer to cwd dir
|
// global pointer to cwd dir
|
||||||
static SdBaseFile* cwd_;
|
static SdBaseFile* cwd_;
|
||||||
// data time callback function
|
// data time callback function
|
||||||
static void (*dateTime_)(uint16_t* date, uint16_t* time);
|
static void (*dateTime_)(uint16_t* date, uint16_t* time);
|
||||||
// bits defined in flags_
|
// bits defined in flags_
|
||||||
// should be 0X0F
|
// should be 0X0F
|
||||||
static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
|
static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
|
||||||
// sync of directory entry required
|
// sync of directory entry required
|
||||||
static uint8_t const F_FILE_DIR_DIRTY = 0X80;
|
static uint8_t const F_FILE_DIR_DIRTY = 0X80;
|
||||||
|
|
||||||
// private data
|
// private data
|
||||||
uint8_t flags_; // See above for definition of flags_ bits
|
uint8_t flags_; // See above for definition of flags_ bits
|
||||||
uint8_t fstate_; // error and eof indicator
|
uint8_t fstate_; // error and eof indicator
|
||||||
uint8_t type_; // type of file see above for values
|
uint8_t type_; // type of file see above for values
|
||||||
uint32_t curCluster_; // cluster for current file position
|
uint32_t curCluster_; // cluster for current file position
|
||||||
uint32_t curPosition_; // current file position in bytes from beginning
|
uint32_t curPosition_; // current file position in bytes from beginning
|
||||||
uint32_t dirBlock_; // block for this files directory entry
|
uint32_t dirBlock_; // block for this files directory entry
|
||||||
uint8_t dirIndex_; // index of directory entry in dirBlock
|
uint8_t dirIndex_; // index of directory entry in dirBlock
|
||||||
uint32_t fileSize_; // file size in bytes
|
uint32_t fileSize_; // file size in bytes
|
||||||
uint32_t firstCluster_; // first cluster of file
|
uint32_t firstCluster_; // first cluster of file
|
||||||
SdVolume* vol_; // volume where file is located
|
SdVolume* vol_; // volume where file is located
|
||||||
|
|
||||||
/** experimental don't use */
|
/** experimental don't use */
|
||||||
bool openParent(SdBaseFile* dir);
|
bool openParent(SdBaseFile* dir);
|
||||||
// private functions
|
// private functions
|
||||||
bool addCluster();
|
bool addCluster();
|
||||||
bool addDirCluster();
|
bool addDirCluster();
|
||||||
dir_t* cacheDirEntry(uint8_t action);
|
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);
|
static bool make83Name(const char* str, uint8_t* name, const char** ptr);
|
||||||
bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
|
bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
|
||||||
bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
|
bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
|
||||||
bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
|
bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
|
||||||
dir_t* readDirCache();
|
dir_t* readDirCache();
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// to be deleted
|
// to be deleted
|
||||||
static void printDirName( const dir_t& dir,
|
static void printDirName( const dir_t& dir,
|
||||||
uint8_t width, bool printSlash);
|
uint8_t width, bool printSlash);
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Deprecated functions - suppress cpplint warnings with NOLINT comment
|
// Deprecated functions - suppress cpplint warnings with NOLINT comment
|
||||||
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
|
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
|
||||||
public:
|
public:
|
||||||
/** \deprecated Use:
|
/** \deprecated Use:
|
||||||
* bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
|
* bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
|
||||||
* \param[out] bgnBlock the first block address for the file.
|
* \param[out] bgnBlock the first block address for the file.
|
||||||
* \param[out] endBlock the last block address for the file.
|
* \param[out] endBlock the last block address for the file.
|
||||||
* \return true for success or false for failure.
|
* \return true for success or false for failure.
|
||||||
*/
|
*/
|
||||||
bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT
|
bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT
|
||||||
return contiguousRange(&bgnBlock, &endBlock);
|
return contiguousRange(&bgnBlock, &endBlock);
|
||||||
}
|
}
|
||||||
/** \deprecated Use:
|
/** \deprecated Use:
|
||||||
* bool createContiguous(SdBaseFile* dirFile,
|
* bool createContiguous(SdBaseFile* dirFile,
|
||||||
* const char* path, uint32_t size)
|
* const char* path, uint32_t size)
|
||||||
* \param[in] dirFile The directory where the file will be created.
|
* \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] path A path with a valid DOS 8.3 file name.
|
||||||
* \param[in] size The desired file size.
|
* \param[in] size The desired file size.
|
||||||
* \return true for success or false for failure.
|
* \return true for success or false for failure.
|
||||||
*/
|
*/
|
||||||
bool createContiguous(SdBaseFile& dirFile, // NOLINT
|
bool createContiguous(SdBaseFile& dirFile, // NOLINT
|
||||||
const char* path, uint32_t size) {
|
const char* path, uint32_t size) {
|
||||||
return createContiguous(&dirFile, path, size);
|
return createContiguous(&dirFile, path, size);
|
||||||
}
|
}
|
||||||
/** \deprecated Use:
|
/** \deprecated Use:
|
||||||
* static void dateTimeCallback(
|
* static void dateTimeCallback(
|
||||||
* void (*dateTime)(uint16_t* date, uint16_t* time));
|
* void (*dateTime)(uint16_t* date, uint16_t* time));
|
||||||
* \param[in] dateTime The user's call back function.
|
* \param[in] dateTime The user's call back function.
|
||||||
*/
|
*/
|
||||||
static void dateTimeCallback(
|
static void dateTimeCallback(
|
||||||
void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT
|
void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT
|
||||||
oldDateTime_ = dateTime;
|
oldDateTime_ = dateTime;
|
||||||
dateTime_ = dateTime ? oldToNew : 0;
|
dateTime_ = dateTime ? oldToNew : 0;
|
||||||
}
|
}
|
||||||
/** \deprecated Use: bool dirEntry(dir_t* dir);
|
/** \deprecated Use: bool dirEntry(dir_t* dir);
|
||||||
* \param[out] dir Location for return of the file's directory entry.
|
* \param[out] dir Location for return of the file's directory entry.
|
||||||
* \return true for success or false for failure.
|
* \return true for success or false for failure.
|
||||||
*/
|
*/
|
||||||
bool dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT
|
bool dirEntry(dir_t& dir) {
|
||||||
/** \deprecated Use:
|
return dirEntry(&dir); // NOLINT
|
||||||
* bool mkdir(SdBaseFile* dir, const char* path);
|
}
|
||||||
* \param[in] dir An open SdFat instance for the directory that will contain
|
/** \deprecated Use:
|
||||||
* the new directory.
|
* bool mkdir(SdBaseFile* dir, const char* path);
|
||||||
* \param[in] path A path with a valid 8.3 DOS name for the new directory.
|
* \param[in] dir An open SdFat instance for the directory that will contain
|
||||||
* \return true for success or false for failure.
|
* the new directory.
|
||||||
*/
|
* \param[in] path A path with a valid 8.3 DOS name for the new directory.
|
||||||
bool mkdir(SdBaseFile& dir, const char* path) { // NOLINT
|
* \return true for success or false for failure.
|
||||||
return mkdir(&dir, path);
|
*/
|
||||||
}
|
bool mkdir(SdBaseFile& dir, const char* path) { // NOLINT
|
||||||
/** \deprecated Use:
|
return mkdir(&dir, path);
|
||||||
* bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
|
}
|
||||||
* \param[in] dirFile An open SdFat instance for the directory containing the
|
/** \deprecated Use:
|
||||||
* file to be opened.
|
* bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
|
||||||
* \param[in] path A path with a valid 8.3 DOS name for the file.
|
* \param[in] dirFile An open SdFat instance for the directory containing the
|
||||||
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
* file to be opened.
|
||||||
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
|
* \param[in] path A path with a valid 8.3 DOS name for the file.
|
||||||
* \return true for success or false for failure.
|
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
||||||
*/
|
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
|
||||||
bool open(SdBaseFile& dirFile, // NOLINT
|
* \return true for success or false for failure.
|
||||||
const char* path, uint8_t oflag) {
|
*/
|
||||||
return open(&dirFile, path, oflag);
|
bool open(SdBaseFile& dirFile, // NOLINT
|
||||||
}
|
const char* path, uint8_t oflag) {
|
||||||
/** \deprecated Do not use in new apps
|
return open(&dirFile, path, oflag);
|
||||||
* \param[in] dirFile An open SdFat instance for the directory containing the
|
}
|
||||||
* file to be opened.
|
/** \deprecated Do not use in new apps
|
||||||
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
|
* \param[in] dirFile An open SdFat instance for the directory containing the
|
||||||
* \return true for success or false for failure.
|
* file to be opened.
|
||||||
*/
|
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
|
||||||
bool open(SdBaseFile& dirFile, const char* path) { // NOLINT
|
* \return true for success or false for failure.
|
||||||
return open(dirFile, path, O_RDWR);
|
*/
|
||||||
}
|
bool open(SdBaseFile& dirFile, const char* path) { // NOLINT
|
||||||
/** \deprecated Use:
|
return open(dirFile, path, O_RDWR);
|
||||||
* bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
|
}
|
||||||
* \param[in] dirFile An open SdFat instance for the directory.
|
/** \deprecated Use:
|
||||||
* \param[in] index The \a index of the directory entry for the file to be
|
* bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
|
||||||
* opened. The value for \a index is (directory file position)/32.
|
* \param[in] dirFile An open SdFat instance for the directory.
|
||||||
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
* \param[in] index The \a index of the directory entry for the file to be
|
||||||
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
|
* opened. The value for \a index is (directory file position)/32.
|
||||||
* \return true for success or false for failure.
|
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
||||||
*/
|
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
|
||||||
bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT
|
* \return true for success or false for failure.
|
||||||
return open(&dirFile, index, oflag);
|
*/
|
||||||
}
|
bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT
|
||||||
/** \deprecated Use: bool openRoot(SdVolume* vol);
|
return open(&dirFile, index, oflag);
|
||||||
* \param[in] vol The FAT volume containing the root directory to be opened.
|
}
|
||||||
* \return true for success or false for failure.
|
/** \deprecated Use: bool openRoot(SdVolume* vol);
|
||||||
*/
|
* \param[in] vol The FAT volume containing the root directory to be opened.
|
||||||
bool openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT
|
* \return true for success or false for failure.
|
||||||
/** \deprecated Use: int8_t readDir(dir_t* dir);
|
*/
|
||||||
* \param[out] dir The dir_t struct that will receive the data.
|
bool openRoot(SdVolume& vol) {
|
||||||
* \return bytes read for success zero for eof or -1 for failure.
|
return openRoot(&vol); // NOLINT
|
||||||
*/
|
}
|
||||||
int8_t readDir(dir_t& dir, char* longFilename) {return readDir(&dir, longFilename);} // NOLINT
|
/** \deprecated Use: int8_t readDir(dir_t* dir);
|
||||||
/** \deprecated Use:
|
* \param[out] dir The dir_t struct that will receive the data.
|
||||||
* static uint8_t remove(SdBaseFile* dirFile, const char* path);
|
* \return bytes read for success zero for eof or -1 for failure.
|
||||||
* \param[in] dirFile The directory that contains the file.
|
*/
|
||||||
* \param[in] path The name of the file to be removed.
|
int8_t readDir(dir_t& dir, char* longFilename) {
|
||||||
* \return true for success or false for failure.
|
return readDir(&dir, longFilename); // NOLINT
|
||||||
*/
|
}
|
||||||
static bool remove(SdBaseFile& dirFile, const char* path) { // NOLINT
|
/** \deprecated Use:
|
||||||
return remove(&dirFile, path);
|
* static uint8_t remove(SdBaseFile* dirFile, const char* path);
|
||||||
}
|
* \param[in] dirFile The directory that contains the file.
|
||||||
|
* \param[in] path The name of the file to be removed.
|
||||||
|
* \return true for success or false for failure.
|
||||||
|
*/
|
||||||
|
static bool remove(SdBaseFile& dirFile, const char* path) { // NOLINT
|
||||||
|
return remove(&dirFile, path);
|
||||||
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// rest are private
|
// rest are private
|
||||||
private:
|
private:
|
||||||
static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT
|
static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT
|
||||||
static void oldToNew(uint16_t* date, uint16_t* time) {
|
static void oldToNew(uint16_t* date, uint16_t* time) {
|
||||||
uint16_t d;
|
uint16_t d;
|
||||||
uint16_t t;
|
uint16_t t;
|
||||||
oldDateTime_(d, t);
|
oldDateTime_(d, t);
|
||||||
*date = d;
|
*date = d;
|
||||||
*time = t;
|
*time = t;
|
||||||
}
|
}
|
||||||
#endif // ALLOW_DEPRECATED_FUNCTIONS
|
#endif // ALLOW_DEPRECATED_FUNCTIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,55 +48,55 @@ uint8_t const EXTENDED_BOOT_SIG = 0X29;
|
||||||
* The MBR partition table has four entries.
|
* The MBR partition table has four entries.
|
||||||
*/
|
*/
|
||||||
struct partitionTable {
|
struct partitionTable {
|
||||||
/**
|
/**
|
||||||
* Boot Indicator . Indicates whether the volume is the active
|
* Boot Indicator . Indicates whether the volume is the active
|
||||||
* partition. Legal values include: 0X00. Do not use for booting.
|
* partition. Legal values include: 0X00. Do not use for booting.
|
||||||
* 0X80 Active partition.
|
* 0X80 Active partition.
|
||||||
*/
|
*/
|
||||||
uint8_t boot;
|
uint8_t boot;
|
||||||
/**
|
/**
|
||||||
* Head part of Cylinder-head-sector address of the first block in
|
* 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.
|
* the partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||||
*/
|
*/
|
||||||
uint8_t beginHead;
|
uint8_t beginHead;
|
||||||
/**
|
/**
|
||||||
* Sector part of Cylinder-head-sector address of the first block in
|
* Sector part of Cylinder-head-sector address of the first block in
|
||||||
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
||||||
*/
|
*/
|
||||||
unsigned beginSector : 6;
|
unsigned beginSector : 6;
|
||||||
/** High bits cylinder for first block in partition. */
|
/** High bits cylinder for first block in partition. */
|
||||||
unsigned beginCylinderHigh : 2;
|
unsigned beginCylinderHigh : 2;
|
||||||
/**
|
/**
|
||||||
* Combine beginCylinderLow with beginCylinderHigh. Legal values
|
* Combine beginCylinderLow with beginCylinderHigh. Legal values
|
||||||
* are 0-1023. Only used in old PC BIOS.
|
* are 0-1023. Only used in old PC BIOS.
|
||||||
*/
|
*/
|
||||||
uint8_t beginCylinderLow;
|
uint8_t beginCylinderLow;
|
||||||
/**
|
/**
|
||||||
* Partition type. See defines that begin with PART_TYPE_ for
|
* Partition type. See defines that begin with PART_TYPE_ for
|
||||||
* some Microsoft partition types.
|
* some Microsoft partition types.
|
||||||
*/
|
*/
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
/**
|
/**
|
||||||
* head part of cylinder-head-sector address of the last sector in the
|
* head part of cylinder-head-sector address of the last sector in the
|
||||||
* partition. Legal values are 0-255. Only used in old PC BIOS.
|
* partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||||
*/
|
*/
|
||||||
uint8_t endHead;
|
uint8_t endHead;
|
||||||
/**
|
/**
|
||||||
* Sector part of cylinder-head-sector address of the last sector in
|
* Sector part of cylinder-head-sector address of the last sector in
|
||||||
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
||||||
*/
|
*/
|
||||||
unsigned endSector : 6;
|
unsigned endSector : 6;
|
||||||
/** High bits of end cylinder */
|
/** High bits of end cylinder */
|
||||||
unsigned endCylinderHigh : 2;
|
unsigned endCylinderHigh : 2;
|
||||||
/**
|
/**
|
||||||
* Combine endCylinderLow with endCylinderHigh. Legal values
|
* Combine endCylinderLow with endCylinderHigh. Legal values
|
||||||
* are 0-1023. Only used in old PC BIOS.
|
* are 0-1023. Only used in old PC BIOS.
|
||||||
*/
|
*/
|
||||||
uint8_t endCylinderLow;
|
uint8_t endCylinderLow;
|
||||||
/** Logical block address of the first block in the partition. */
|
/** Logical block address of the first block in the partition. */
|
||||||
uint32_t firstSector;
|
uint32_t firstSector;
|
||||||
/** Length of the partition, in blocks. */
|
/** Length of the partition, in blocks. */
|
||||||
uint32_t totalSectors;
|
uint32_t totalSectors;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for partitionTable */
|
/** Type name for partitionTable */
|
||||||
typedef struct partitionTable part_t;
|
typedef struct partitionTable part_t;
|
||||||
|
|
@ -109,18 +109,18 @@ typedef struct partitionTable part_t;
|
||||||
* The first block of a storage device that is formatted with a MBR.
|
* The first block of a storage device that is formatted with a MBR.
|
||||||
*/
|
*/
|
||||||
struct masterBootRecord {
|
struct masterBootRecord {
|
||||||
/** Code Area for master boot program. */
|
/** Code Area for master boot program. */
|
||||||
uint8_t codeArea[440];
|
uint8_t codeArea[440];
|
||||||
/** Optional Windows NT disk signature. May contain boot code. */
|
/** Optional Windows NT disk signature. May contain boot code. */
|
||||||
uint32_t diskSignature;
|
uint32_t diskSignature;
|
||||||
/** Usually zero but may be more boot code. */
|
/** Usually zero but may be more boot code. */
|
||||||
uint16_t usuallyZero;
|
uint16_t usuallyZero;
|
||||||
/** Partition tables. */
|
/** Partition tables. */
|
||||||
part_t part[4];
|
part_t part[4];
|
||||||
/** First MBR signature byte. Must be 0X55 */
|
/** First MBR signature byte. Must be 0X55 */
|
||||||
uint8_t mbrSig0;
|
uint8_t mbrSig0;
|
||||||
/** Second MBR signature byte. Must be 0XAA */
|
/** Second MBR signature byte. Must be 0XAA */
|
||||||
uint8_t mbrSig1;
|
uint8_t mbrSig1;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for masterBootRecord */
|
/** Type name for masterBootRecord */
|
||||||
typedef struct masterBootRecord mbr_t;
|
typedef struct masterBootRecord mbr_t;
|
||||||
|
|
@ -132,123 +132,123 @@ typedef struct masterBootRecord mbr_t;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct fat_boot {
|
struct fat_boot {
|
||||||
/**
|
/**
|
||||||
* The first three bytes of the boot sector must be valid,
|
* The first three bytes of the boot sector must be valid,
|
||||||
* executable x 86-based CPU instructions. This includes a
|
* executable x 86-based CPU instructions. This includes a
|
||||||
* jump instruction that skips the next nonexecutable bytes.
|
* jump instruction that skips the next nonexecutable bytes.
|
||||||
*/
|
*/
|
||||||
uint8_t jump[3];
|
uint8_t jump[3];
|
||||||
/**
|
/**
|
||||||
* This is typically a string of characters that identifies
|
* This is typically a string of characters that identifies
|
||||||
* the operating system that formatted the volume.
|
* the operating system that formatted the volume.
|
||||||
*/
|
*/
|
||||||
char oemId[8];
|
char oemId[8];
|
||||||
/**
|
/**
|
||||||
* The size of a hardware sector. Valid decimal values for this
|
* The size of a hardware sector. Valid decimal values for this
|
||||||
* field are 512, 1024, 2048, and 4096. For most disks used in
|
* field are 512, 1024, 2048, and 4096. For most disks used in
|
||||||
* the United States, the value of this field is 512.
|
* the United States, the value of this field is 512.
|
||||||
*/
|
*/
|
||||||
uint16_t bytesPerSector;
|
uint16_t bytesPerSector;
|
||||||
/**
|
/**
|
||||||
* Number of sectors per allocation unit. This value must be a
|
* Number of sectors per allocation unit. This value must be a
|
||||||
* power of 2 that is greater than 0. The legal values are
|
* power of 2 that is greater than 0. The legal values are
|
||||||
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
|
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
|
||||||
*/
|
*/
|
||||||
uint8_t sectorsPerCluster;
|
uint8_t sectorsPerCluster;
|
||||||
/**
|
/**
|
||||||
* The number of sectors preceding the start of the first FAT,
|
* The number of sectors preceding the start of the first FAT,
|
||||||
* including the boot sector. The value of this field is always 1.
|
* including the boot sector. The value of this field is always 1.
|
||||||
*/
|
*/
|
||||||
uint16_t reservedSectorCount;
|
uint16_t reservedSectorCount;
|
||||||
/**
|
/**
|
||||||
* The number of copies of the FAT on the volume.
|
* The number of copies of the FAT on the volume.
|
||||||
* The value of this field is always 2.
|
* The value of this field is always 2.
|
||||||
*/
|
*/
|
||||||
uint8_t fatCount;
|
uint8_t fatCount;
|
||||||
/**
|
/**
|
||||||
* For FAT12 and FAT16 volumes, this field contains the count of
|
* For FAT12 and FAT16 volumes, this field contains the count of
|
||||||
* 32-byte directory entries in the root directory. For FAT32 volumes,
|
* 32-byte directory entries in the root directory. For FAT32 volumes,
|
||||||
* this field must be set to 0. For FAT12 and FAT16 volumes, this
|
* this field must be set to 0. For FAT12 and FAT16 volumes, this
|
||||||
* value should always specify a count that when multiplied by 32
|
* value should always specify a count that when multiplied by 32
|
||||||
* results in a multiple of bytesPerSector. FAT16 volumes should
|
* results in a multiple of bytesPerSector. FAT16 volumes should
|
||||||
* use the value 512.
|
* use the value 512.
|
||||||
*/
|
*/
|
||||||
uint16_t rootDirEntryCount;
|
uint16_t rootDirEntryCount;
|
||||||
/**
|
/**
|
||||||
* This field is the old 16-bit total count of sectors on the volume.
|
* This field is the old 16-bit total count of sectors on the volume.
|
||||||
* This count includes the count of all sectors in all four regions
|
* This count includes the count of all sectors in all four regions
|
||||||
* of the volume. This field can be 0; if it is 0, then totalSectors32
|
* of the volume. This field can be 0; if it is 0, then totalSectors32
|
||||||
* must be nonzero. For FAT32 volumes, this field must be 0. For
|
* must be nonzero. For FAT32 volumes, this field must be 0. For
|
||||||
* FAT12 and FAT16 volumes, this field contains the sector count, and
|
* FAT12 and FAT16 volumes, this field contains the sector count, and
|
||||||
* totalSectors32 is 0 if the total sector count fits
|
* totalSectors32 is 0 if the total sector count fits
|
||||||
* (is less than 0x10000).
|
* (is less than 0x10000).
|
||||||
*/
|
*/
|
||||||
uint16_t totalSectors16;
|
uint16_t totalSectors16;
|
||||||
/**
|
/**
|
||||||
* This dates back to the old MS-DOS 1.x media determination and is
|
* This dates back to the old MS-DOS 1.x media determination and is
|
||||||
* no longer usually used for anything. 0xF8 is the standard value
|
* no longer usually used for anything. 0xF8 is the standard value
|
||||||
* for fixed (nonremovable) media. For removable media, 0xF0 is
|
* for fixed (nonremovable) media. For removable media, 0xF0 is
|
||||||
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
||||||
*/
|
*/
|
||||||
uint8_t mediaType;
|
uint8_t mediaType;
|
||||||
/**
|
/**
|
||||||
* Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
|
* Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
|
||||||
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
||||||
* contains the FAT size count.
|
* contains the FAT size count.
|
||||||
*/
|
*/
|
||||||
uint16_t sectorsPerFat16;
|
uint16_t sectorsPerFat16;
|
||||||
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
||||||
uint16_t sectorsPerTrack;
|
uint16_t sectorsPerTrack;
|
||||||
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
||||||
uint16_t headCount;
|
uint16_t headCount;
|
||||||
/**
|
/**
|
||||||
* Count of hidden sectors preceding the partition that contains this
|
* Count of hidden sectors preceding the partition that contains this
|
||||||
* FAT volume. This field is generally only relevant for media
|
* FAT volume. This field is generally only relevant for media
|
||||||
* visible on interrupt 0x13.
|
* visible on interrupt 0x13.
|
||||||
*/
|
*/
|
||||||
uint32_t hidddenSectors;
|
uint32_t hidddenSectors;
|
||||||
/**
|
/**
|
||||||
* This field is the new 32-bit total count of sectors on the volume.
|
* This field is the new 32-bit total count of sectors on the volume.
|
||||||
* This count includes the count of all sectors in all four regions
|
* This count includes the count of all sectors in all four regions
|
||||||
* of the volume. This field can be 0; if it is 0, then
|
* of the volume. This field can be 0; if it is 0, then
|
||||||
* totalSectors16 must be nonzero.
|
* totalSectors16 must be nonzero.
|
||||||
*/
|
*/
|
||||||
uint32_t totalSectors32;
|
uint32_t totalSectors32;
|
||||||
/**
|
/**
|
||||||
* Related to the BIOS physical drive number. Floppy drives are
|
* Related to the BIOS physical drive number. Floppy drives are
|
||||||
* identified as 0x00 and physical hard disks are identified as
|
* identified as 0x00 and physical hard disks are identified as
|
||||||
* 0x80, regardless of the number of physical disk drives.
|
* 0x80, regardless of the number of physical disk drives.
|
||||||
* Typically, this value is set prior to issuing an INT 13h BIOS
|
* Typically, this value is set prior to issuing an INT 13h BIOS
|
||||||
* call to specify the device to access. The value is only
|
* call to specify the device to access. The value is only
|
||||||
* relevant if the device is a boot device.
|
* relevant if the device is a boot device.
|
||||||
*/
|
*/
|
||||||
uint8_t driveNumber;
|
uint8_t driveNumber;
|
||||||
/** used by Windows NT - should be zero for FAT */
|
/** used by Windows NT - should be zero for FAT */
|
||||||
uint8_t reserved1;
|
uint8_t reserved1;
|
||||||
/** 0X29 if next three fields are valid */
|
/** 0X29 if next three fields are valid */
|
||||||
uint8_t bootSignature;
|
uint8_t bootSignature;
|
||||||
/**
|
/**
|
||||||
* A random serial number created when formatting a disk,
|
* A random serial number created when formatting a disk,
|
||||||
* which helps to distinguish between disks.
|
* which helps to distinguish between disks.
|
||||||
* Usually generated by combining date and time.
|
* Usually generated by combining date and time.
|
||||||
*/
|
*/
|
||||||
uint32_t volumeSerialNumber;
|
uint32_t volumeSerialNumber;
|
||||||
/**
|
/**
|
||||||
* A field once used to store the volume label. The volume label
|
* A field once used to store the volume label. The volume label
|
||||||
* is now stored as a special file in the root directory.
|
* is now stored as a special file in the root directory.
|
||||||
*/
|
*/
|
||||||
char volumeLabel[11];
|
char volumeLabel[11];
|
||||||
/**
|
/**
|
||||||
* A field with a value of either FAT, FAT12 or FAT16,
|
* A field with a value of either FAT, FAT12 or FAT16,
|
||||||
* depending on the disk format.
|
* depending on the disk format.
|
||||||
*/
|
*/
|
||||||
char fileSystemType[8];
|
char fileSystemType[8];
|
||||||
/** X86 boot code */
|
/** X86 boot code */
|
||||||
uint8_t bootCode[448];
|
uint8_t bootCode[448];
|
||||||
/** must be 0X55 */
|
/** must be 0X55 */
|
||||||
uint8_t bootSectorSig0;
|
uint8_t bootSectorSig0;
|
||||||
/** must be 0XAA */
|
/** must be 0XAA */
|
||||||
uint8_t bootSectorSig1;
|
uint8_t bootSectorSig1;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for FAT Boot Sector */
|
/** Type name for FAT Boot Sector */
|
||||||
typedef struct fat_boot fat_boot_t;
|
typedef struct fat_boot fat_boot_t;
|
||||||
|
|
@ -260,149 +260,149 @@ typedef struct fat_boot fat_boot_t;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct fat32_boot {
|
struct fat32_boot {
|
||||||
/**
|
/**
|
||||||
* The first three bytes of the boot sector must be valid,
|
* The first three bytes of the boot sector must be valid,
|
||||||
* executable x 86-based CPU instructions. This includes a
|
* executable x 86-based CPU instructions. This includes a
|
||||||
* jump instruction that skips the next nonexecutable bytes.
|
* jump instruction that skips the next nonexecutable bytes.
|
||||||
*/
|
*/
|
||||||
uint8_t jump[3];
|
uint8_t jump[3];
|
||||||
/**
|
/**
|
||||||
* This is typically a string of characters that identifies
|
* This is typically a string of characters that identifies
|
||||||
* the operating system that formatted the volume.
|
* the operating system that formatted the volume.
|
||||||
*/
|
*/
|
||||||
char oemId[8];
|
char oemId[8];
|
||||||
/**
|
/**
|
||||||
* The size of a hardware sector. Valid decimal values for this
|
* The size of a hardware sector. Valid decimal values for this
|
||||||
* field are 512, 1024, 2048, and 4096. For most disks used in
|
* field are 512, 1024, 2048, and 4096. For most disks used in
|
||||||
* the United States, the value of this field is 512.
|
* the United States, the value of this field is 512.
|
||||||
*/
|
*/
|
||||||
uint16_t bytesPerSector;
|
uint16_t bytesPerSector;
|
||||||
/**
|
/**
|
||||||
* Number of sectors per allocation unit. This value must be a
|
* Number of sectors per allocation unit. This value must be a
|
||||||
* power of 2 that is greater than 0. The legal values are
|
* power of 2 that is greater than 0. The legal values are
|
||||||
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
|
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
|
||||||
*/
|
*/
|
||||||
uint8_t sectorsPerCluster;
|
uint8_t sectorsPerCluster;
|
||||||
/**
|
/**
|
||||||
* The number of sectors preceding the start of the first FAT,
|
* The number of sectors preceding the start of the first FAT,
|
||||||
* including the boot sector. Must not be zero
|
* including the boot sector. Must not be zero
|
||||||
*/
|
*/
|
||||||
uint16_t reservedSectorCount;
|
uint16_t reservedSectorCount;
|
||||||
/**
|
/**
|
||||||
* The number of copies of the FAT on the volume.
|
* The number of copies of the FAT on the volume.
|
||||||
* The value of this field is always 2.
|
* The value of this field is always 2.
|
||||||
*/
|
*/
|
||||||
uint8_t fatCount;
|
uint8_t fatCount;
|
||||||
/**
|
/**
|
||||||
* FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
|
* FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
|
||||||
*/
|
*/
|
||||||
uint16_t rootDirEntryCount;
|
uint16_t rootDirEntryCount;
|
||||||
/**
|
/**
|
||||||
* For FAT32 volumes, this field must be 0.
|
* For FAT32 volumes, this field must be 0.
|
||||||
*/
|
*/
|
||||||
uint16_t totalSectors16;
|
uint16_t totalSectors16;
|
||||||
/**
|
/**
|
||||||
* This dates back to the old MS-DOS 1.x media determination and is
|
* This dates back to the old MS-DOS 1.x media determination and is
|
||||||
* no longer usually used for anything. 0xF8 is the standard value
|
* no longer usually used for anything. 0xF8 is the standard value
|
||||||
* for fixed (nonremovable) media. For removable media, 0xF0 is
|
* for fixed (nonremovable) media. For removable media, 0xF0 is
|
||||||
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
||||||
*/
|
*/
|
||||||
uint8_t mediaType;
|
uint8_t mediaType;
|
||||||
/**
|
/**
|
||||||
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
||||||
* contains the FAT size count.
|
* contains the FAT size count.
|
||||||
*/
|
*/
|
||||||
uint16_t sectorsPerFat16;
|
uint16_t sectorsPerFat16;
|
||||||
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
||||||
uint16_t sectorsPerTrack;
|
uint16_t sectorsPerTrack;
|
||||||
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
||||||
uint16_t headCount;
|
uint16_t headCount;
|
||||||
/**
|
/**
|
||||||
* Count of hidden sectors preceding the partition that contains this
|
* Count of hidden sectors preceding the partition that contains this
|
||||||
* FAT volume. This field is generally only relevant for media
|
* FAT volume. This field is generally only relevant for media
|
||||||
* visible on interrupt 0x13.
|
* visible on interrupt 0x13.
|
||||||
*/
|
*/
|
||||||
uint32_t hidddenSectors;
|
uint32_t hidddenSectors;
|
||||||
/**
|
/**
|
||||||
* Contains the total number of sectors in the FAT32 volume.
|
* Contains the total number of sectors in the FAT32 volume.
|
||||||
*/
|
*/
|
||||||
uint32_t totalSectors32;
|
uint32_t totalSectors32;
|
||||||
/**
|
/**
|
||||||
* Count of sectors occupied by one FAT on FAT32 volumes.
|
* Count of sectors occupied by one FAT on FAT32 volumes.
|
||||||
*/
|
*/
|
||||||
uint32_t sectorsPerFat32;
|
uint32_t sectorsPerFat32;
|
||||||
/**
|
/**
|
||||||
* This field is only defined for FAT32 media and does not exist on
|
* This field is only defined for FAT32 media and does not exist on
|
||||||
* FAT12 and FAT16 media.
|
* FAT12 and FAT16 media.
|
||||||
* Bits 0-3 -- Zero-based number of active FAT.
|
* Bits 0-3 -- Zero-based number of active FAT.
|
||||||
* Only valid if mirroring is disabled.
|
* Only valid if mirroring is disabled.
|
||||||
* Bits 4-6 -- Reserved.
|
* Bits 4-6 -- Reserved.
|
||||||
* Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
|
* 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
|
* -- 1 means only one FAT is active; it is the one referenced
|
||||||
* in bits 0-3.
|
* in bits 0-3.
|
||||||
* Bits 8-15 -- Reserved.
|
* Bits 8-15 -- Reserved.
|
||||||
*/
|
*/
|
||||||
uint16_t fat32Flags;
|
uint16_t fat32Flags;
|
||||||
/**
|
/**
|
||||||
* FAT32 version. High byte is major revision number.
|
* FAT32 version. High byte is major revision number.
|
||||||
* Low byte is minor revision number. Only 0.0 define.
|
* Low byte is minor revision number. Only 0.0 define.
|
||||||
*/
|
*/
|
||||||
uint16_t fat32Version;
|
uint16_t fat32Version;
|
||||||
/**
|
/**
|
||||||
* Cluster number of the first cluster of the root directory for FAT32.
|
* Cluster number of the first cluster of the root directory for FAT32.
|
||||||
* This usually 2 but not required to be 2.
|
* This usually 2 but not required to be 2.
|
||||||
*/
|
*/
|
||||||
uint32_t fat32RootCluster;
|
uint32_t fat32RootCluster;
|
||||||
/**
|
/**
|
||||||
* Sector number of FSINFO structure in the reserved area of the
|
* Sector number of FSINFO structure in the reserved area of the
|
||||||
* FAT32 volume. Usually 1.
|
* FAT32 volume. Usually 1.
|
||||||
*/
|
*/
|
||||||
uint16_t fat32FSInfo;
|
uint16_t fat32FSInfo;
|
||||||
/**
|
/**
|
||||||
* If nonzero, indicates the sector number in the reserved area
|
* If nonzero, indicates the sector number in the reserved area
|
||||||
* of the volume of a copy of the boot record. Usually 6.
|
* of the volume of a copy of the boot record. Usually 6.
|
||||||
* No value other than 6 is recommended.
|
* No value other than 6 is recommended.
|
||||||
*/
|
*/
|
||||||
uint16_t fat32BackBootBlock;
|
uint16_t fat32BackBootBlock;
|
||||||
/**
|
/**
|
||||||
* Reserved for future expansion. Code that formats FAT32 volumes
|
* Reserved for future expansion. Code that formats FAT32 volumes
|
||||||
* should always set all of the bytes of this field to 0.
|
* should always set all of the bytes of this field to 0.
|
||||||
*/
|
*/
|
||||||
uint8_t fat32Reserved[12];
|
uint8_t fat32Reserved[12];
|
||||||
/**
|
/**
|
||||||
* Related to the BIOS physical drive number. Floppy drives are
|
* Related to the BIOS physical drive number. Floppy drives are
|
||||||
* identified as 0x00 and physical hard disks are identified as
|
* identified as 0x00 and physical hard disks are identified as
|
||||||
* 0x80, regardless of the number of physical disk drives.
|
* 0x80, regardless of the number of physical disk drives.
|
||||||
* Typically, this value is set prior to issuing an INT 13h BIOS
|
* Typically, this value is set prior to issuing an INT 13h BIOS
|
||||||
* call to specify the device to access. The value is only
|
* call to specify the device to access. The value is only
|
||||||
* relevant if the device is a boot device.
|
* relevant if the device is a boot device.
|
||||||
*/
|
*/
|
||||||
uint8_t driveNumber;
|
uint8_t driveNumber;
|
||||||
/** used by Windows NT - should be zero for FAT */
|
/** used by Windows NT - should be zero for FAT */
|
||||||
uint8_t reserved1;
|
uint8_t reserved1;
|
||||||
/** 0X29 if next three fields are valid */
|
/** 0X29 if next three fields are valid */
|
||||||
uint8_t bootSignature;
|
uint8_t bootSignature;
|
||||||
/**
|
/**
|
||||||
* A random serial number created when formatting a disk,
|
* A random serial number created when formatting a disk,
|
||||||
* which helps to distinguish between disks.
|
* which helps to distinguish between disks.
|
||||||
* Usually generated by combining date and time.
|
* Usually generated by combining date and time.
|
||||||
*/
|
*/
|
||||||
uint32_t volumeSerialNumber;
|
uint32_t volumeSerialNumber;
|
||||||
/**
|
/**
|
||||||
* A field once used to store the volume label. The volume label
|
* A field once used to store the volume label. The volume label
|
||||||
* is now stored as a special file in the root directory.
|
* is now stored as a special file in the root directory.
|
||||||
*/
|
*/
|
||||||
char volumeLabel[11];
|
char volumeLabel[11];
|
||||||
/**
|
/**
|
||||||
* A text field with a value of FAT32.
|
* A text field with a value of FAT32.
|
||||||
*/
|
*/
|
||||||
char fileSystemType[8];
|
char fileSystemType[8];
|
||||||
/** X86 boot code */
|
/** X86 boot code */
|
||||||
uint8_t bootCode[420];
|
uint8_t bootCode[420];
|
||||||
/** must be 0X55 */
|
/** must be 0X55 */
|
||||||
uint8_t bootSectorSig0;
|
uint8_t bootSectorSig0;
|
||||||
/** must be 0XAA */
|
/** must be 0XAA */
|
||||||
uint8_t bootSectorSig1;
|
uint8_t bootSectorSig1;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for FAT32 Boot Sector */
|
/** Type name for FAT32 Boot Sector */
|
||||||
typedef struct fat32_boot fat32_boot_t;
|
typedef struct fat32_boot fat32_boot_t;
|
||||||
|
|
@ -418,31 +418,31 @@ uint32_t const FSINFO_STRUCT_SIG = 0x61417272;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct fat32_fsinfo {
|
struct fat32_fsinfo {
|
||||||
/** must be 0X52, 0X52, 0X61, 0X41 */
|
/** must be 0X52, 0X52, 0X61, 0X41 */
|
||||||
uint32_t leadSignature;
|
uint32_t leadSignature;
|
||||||
/** must be zero */
|
/** must be zero */
|
||||||
uint8_t reserved1[480];
|
uint8_t reserved1[480];
|
||||||
/** must be 0X72, 0X72, 0X41, 0X61 */
|
/** must be 0X72, 0X72, 0X41, 0X61 */
|
||||||
uint32_t structSignature;
|
uint32_t structSignature;
|
||||||
/**
|
/**
|
||||||
* Contains the last known free cluster count on the volume.
|
* Contains the last known free cluster count on the volume.
|
||||||
* If the value is 0xFFFFFFFF, then the free count is unknown
|
* If the value is 0xFFFFFFFF, then the free count is unknown
|
||||||
* and must be computed. Any other value can be used, but is
|
* and must be computed. Any other value can be used, but is
|
||||||
* not necessarily correct. It should be range checked at least
|
* not necessarily correct. It should be range checked at least
|
||||||
* to make sure it is <= volume cluster count.
|
* to make sure it is <= volume cluster count.
|
||||||
*/
|
*/
|
||||||
uint32_t freeCount;
|
uint32_t freeCount;
|
||||||
/**
|
/**
|
||||||
* This is a hint for the FAT driver. It indicates the cluster
|
* This is a hint for the FAT driver. It indicates the cluster
|
||||||
* number at which the driver should start looking for free clusters.
|
* number at which the driver should start looking for free clusters.
|
||||||
* If the value is 0xFFFFFFFF, then there is no hint and the driver
|
* If the value is 0xFFFFFFFF, then there is no hint and the driver
|
||||||
* should start looking at cluster 2.
|
* should start looking at cluster 2.
|
||||||
*/
|
*/
|
||||||
uint32_t nextFree;
|
uint32_t nextFree;
|
||||||
/** must be zero */
|
/** must be zero */
|
||||||
uint8_t reserved2[12];
|
uint8_t reserved2[12];
|
||||||
/** must be 0X00, 0X00, 0X55, 0XAA */
|
/** must be 0X00, 0X00, 0X55, 0XAA */
|
||||||
uint8_t tailSignature[4];
|
uint8_t tailSignature[4];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/** Type name for FAT32 FSINFO Sector */
|
/** Type name for FAT32 FSINFO Sector */
|
||||||
typedef struct fat32_fsinfo fat32_fsinfo_t;
|
typedef struct fat32_fsinfo fat32_fsinfo_t;
|
||||||
|
|
@ -494,53 +494,53 @@ uint32_t const FAT32MASK = 0X0FFFFFFF;
|
||||||
* The valid time range is from Midnight 00:00:00 to 23:59:58.
|
* The valid time range is from Midnight 00:00:00 to 23:59:58.
|
||||||
*/
|
*/
|
||||||
struct directoryEntry {
|
struct directoryEntry {
|
||||||
/** Short 8.3 name.
|
/** Short 8.3 name.
|
||||||
*
|
*
|
||||||
* The first eight bytes contain the file name with blank fill.
|
* The first eight bytes contain the file name with blank fill.
|
||||||
* The last three bytes contain the file extension with blank fill.
|
* The last three bytes contain the file extension with blank fill.
|
||||||
*/
|
*/
|
||||||
uint8_t name[11];
|
uint8_t name[11];
|
||||||
/** Entry attributes.
|
/** Entry attributes.
|
||||||
*
|
*
|
||||||
* The upper two bits of the attribute byte are reserved and should
|
* The upper two bits of the attribute byte are reserved and should
|
||||||
* always be set to 0 when a file is created and never modified or
|
* always be set to 0 when a file is created and never modified or
|
||||||
* looked at after that. See defines that begin with DIR_ATT_.
|
* looked at after that. See defines that begin with DIR_ATT_.
|
||||||
*/
|
*/
|
||||||
uint8_t attributes;
|
uint8_t attributes;
|
||||||
/**
|
/**
|
||||||
* Reserved for use by Windows NT. Set value to 0 when a file is
|
* Reserved for use by Windows NT. Set value to 0 when a file is
|
||||||
* created and never modify or look at it after that.
|
* created and never modify or look at it after that.
|
||||||
*/
|
*/
|
||||||
uint8_t reservedNT;
|
uint8_t reservedNT;
|
||||||
/**
|
/**
|
||||||
* The granularity of the seconds part of creationTime is 2 seconds
|
* The granularity of the seconds part of creationTime is 2 seconds
|
||||||
* so this field is a count of tenths of a second and its valid
|
* so this field is a count of tenths of a second and its valid
|
||||||
* value range is 0-199 inclusive. (WHG note - seems to be hundredths)
|
* value range is 0-199 inclusive. (WHG note - seems to be hundredths)
|
||||||
*/
|
*/
|
||||||
uint8_t creationTimeTenths;
|
uint8_t creationTimeTenths;
|
||||||
/** Time file was created. */
|
/** Time file was created. */
|
||||||
uint16_t creationTime;
|
uint16_t creationTime;
|
||||||
/** Date file was created. */
|
/** Date file was created. */
|
||||||
uint16_t creationDate;
|
uint16_t creationDate;
|
||||||
/**
|
/**
|
||||||
* Last access date. Note that there is no last access time, only
|
* Last access date. Note that there is no last access time, only
|
||||||
* a date. This is the date of last read or write. In the case of
|
* a date. This is the date of last read or write. In the case of
|
||||||
* a write, this should be set to the same date as lastWriteDate.
|
* a write, this should be set to the same date as lastWriteDate.
|
||||||
*/
|
*/
|
||||||
uint16_t lastAccessDate;
|
uint16_t lastAccessDate;
|
||||||
/**
|
/**
|
||||||
* High word of this entry's first cluster number (always 0 for a
|
* High word of this entry's first cluster number (always 0 for a
|
||||||
* FAT12 or FAT16 volume).
|
* FAT12 or FAT16 volume).
|
||||||
*/
|
*/
|
||||||
uint16_t firstClusterHigh;
|
uint16_t firstClusterHigh;
|
||||||
/** Time of last write. File creation is considered a write. */
|
/** Time of last write. File creation is considered a write. */
|
||||||
uint16_t lastWriteTime;
|
uint16_t lastWriteTime;
|
||||||
/** Date of last write. File creation is considered a write. */
|
/** Date of last write. File creation is considered a write. */
|
||||||
uint16_t lastWriteDate;
|
uint16_t lastWriteDate;
|
||||||
/** Low word of this entry's first cluster number. */
|
/** Low word of this entry's first cluster number. */
|
||||||
uint16_t firstClusterLow;
|
uint16_t firstClusterLow;
|
||||||
/** 32-bit unsigned holding this file's size in bytes. */
|
/** 32-bit unsigned holding this file's size in bytes. */
|
||||||
uint32_t fileSize;
|
uint32_t fileSize;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
/**
|
/**
|
||||||
* \struct directoryVFATEntry
|
* \struct directoryVFATEntry
|
||||||
|
|
@ -553,26 +553,26 @@ struct directoryEntry {
|
||||||
* Each entry containing 13 UTF-16 characters.
|
* Each entry containing 13 UTF-16 characters.
|
||||||
*/
|
*/
|
||||||
struct directoryVFATEntry {
|
struct directoryVFATEntry {
|
||||||
/**
|
/**
|
||||||
* Sequence number. Consists of 2 parts:
|
* Sequence number. Consists of 2 parts:
|
||||||
* bit 6: indicates first long filename block for the next file
|
* bit 6: indicates first long filename block for the next file
|
||||||
* bit 0-4: the position of this long filename block (first block is 1)
|
* bit 0-4: the position of this long filename block (first block is 1)
|
||||||
*/
|
*/
|
||||||
uint8_t sequenceNumber;
|
uint8_t sequenceNumber;
|
||||||
/** First set of UTF-16 characters */
|
/** First set of UTF-16 characters */
|
||||||
uint16_t name1[5];//UTF-16
|
uint16_t name1[5];//UTF-16
|
||||||
/** attributes (at the same location as in directoryEntry), always 0x0F */
|
/** attributes (at the same location as in directoryEntry), always 0x0F */
|
||||||
uint8_t attributes;
|
uint8_t attributes;
|
||||||
/** Reserved for use by Windows NT. Always 0. */
|
/** Reserved for use by Windows NT. Always 0. */
|
||||||
uint8_t reservedNT;
|
uint8_t reservedNT;
|
||||||
/** Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation. */
|
/** Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation. */
|
||||||
uint8_t checksum;
|
uint8_t checksum;
|
||||||
/** Second set of UTF-16 characters */
|
/** Second set of UTF-16 characters */
|
||||||
uint16_t name2[6];//UTF-16
|
uint16_t name2[6];//UTF-16
|
||||||
/** firstClusterLow is always zero for longFilenames */
|
/** firstClusterLow is always zero for longFilenames */
|
||||||
uint16_t firstClusterLow;
|
uint16_t firstClusterLow;
|
||||||
/** Third set of UTF-16 characters */
|
/** Third set of UTF-16 characters */
|
||||||
uint16_t name3[2];//UTF-16
|
uint16_t name3[2];//UTF-16
|
||||||
} PACKED;
|
} PACKED;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Definitions for directory entries
|
// Definitions for directory entries
|
||||||
|
|
@ -612,7 +612,7 @@ uint8_t const DIR_ATT_DEFINED_BITS = 0X3F;
|
||||||
* \return true if the entry is for part of a long name else false.
|
* \return true if the entry is for part of a long name else false.
|
||||||
*/
|
*/
|
||||||
static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
|
static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
|
||||||
return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
|
return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
|
||||||
}
|
}
|
||||||
/** Mask for file/subdirectory tests */
|
/** Mask for file/subdirectory tests */
|
||||||
uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
|
uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
|
||||||
|
|
@ -622,7 +622,7 @@ uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
|
||||||
* \return true if the entry is for a normal file else false.
|
* \return true if the entry is for a normal file else false.
|
||||||
*/
|
*/
|
||||||
static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
|
static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
|
||||||
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
|
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
|
||||||
}
|
}
|
||||||
/** Directory entry is for a subdirectory
|
/** Directory entry is for a subdirectory
|
||||||
* \param[in] dir Pointer to a directory entry.
|
* \param[in] dir Pointer to a directory entry.
|
||||||
|
|
@ -630,7 +630,7 @@ static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
|
||||||
* \return true if the entry is for a subdirectory else false.
|
* \return true if the entry is for a subdirectory else false.
|
||||||
*/
|
*/
|
||||||
static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
|
static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
|
||||||
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
|
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
|
||||||
}
|
}
|
||||||
/** Directory entry is for a file or subdirectory
|
/** Directory entry is for a file or subdirectory
|
||||||
* \param[in] dir Pointer to a directory entry.
|
* \param[in] dir Pointer to a directory entry.
|
||||||
|
|
@ -638,7 +638,7 @@ static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
|
||||||
* \return true if the entry is for a normal file or subdirectory else false.
|
* \return true if the entry is for a normal file or subdirectory else false.
|
||||||
*/
|
*/
|
||||||
static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
|
static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
|
||||||
return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
|
return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
|
||||||
}
|
}
|
||||||
#endif // SdFatStructs_h
|
#endif // SdFatStructs_h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@
|
||||||
#ifdef __arm__
|
#ifdef __arm__
|
||||||
extern "C" char* sbrk(int incr);
|
extern "C" char* sbrk(int incr);
|
||||||
int SdFatUtil::FreeRam() {
|
int SdFatUtil::FreeRam() {
|
||||||
char top;
|
char top;
|
||||||
return &top - reinterpret_cast<char*>(sbrk(0));
|
return &top - reinterpret_cast<char*>(sbrk(0));
|
||||||
}
|
}
|
||||||
#else // __arm__
|
#else // __arm__
|
||||||
extern char *__brkval;
|
extern char *__brkval;
|
||||||
|
|
@ -39,32 +39,32 @@ extern char __bss_end;
|
||||||
* \return The number of free bytes.
|
* \return The number of free bytes.
|
||||||
*/
|
*/
|
||||||
int SdFatUtil::FreeRam() {
|
int SdFatUtil::FreeRam() {
|
||||||
char top;
|
char top;
|
||||||
return __brkval ? &top - __brkval : &top - &__bss_end;
|
return __brkval ? &top - __brkval : &top - &__bss_end;
|
||||||
}
|
}
|
||||||
#endif // __arm
|
#endif // __arm
|
||||||
|
|
||||||
void SdFatUtil::set_stack_guard()
|
void SdFatUtil::set_stack_guard()
|
||||||
{
|
{
|
||||||
uint32_t *stack_guard;
|
uint32_t *stack_guard;
|
||||||
|
|
||||||
stack_guard = (uint32_t*)&__bss_end;
|
stack_guard = (uint32_t*)&__bss_end;
|
||||||
*stack_guard = STACK_GUARD_TEST_VALUE;
|
*stack_guard = STACK_GUARD_TEST_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SdFatUtil::test_stack_integrity()
|
bool SdFatUtil::test_stack_integrity()
|
||||||
{
|
{
|
||||||
uint32_t* stack_guard = (uint32_t*)&__bss_end;
|
uint32_t* stack_guard = (uint32_t*)&__bss_end;
|
||||||
return (*stack_guard == STACK_GUARD_TEST_VALUE);
|
return (*stack_guard == STACK_GUARD_TEST_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SdFatUtil::get_stack_guard_test_value()
|
uint32_t SdFatUtil::get_stack_guard_test_value()
|
||||||
{
|
{
|
||||||
uint32_t* stack_guard;
|
uint32_t* stack_guard;
|
||||||
uint32_t output;
|
uint32_t output;
|
||||||
stack_guard = (uint32_t*)&__bss_end;
|
stack_guard = (uint32_t*)&__bss_end;
|
||||||
output = *stack_guard;
|
output = *stack_guard;
|
||||||
return(output);
|
return(output);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** %Print a string in flash memory.
|
/** %Print a string in flash memory.
|
||||||
|
|
@ -73,7 +73,7 @@ uint32_t SdFatUtil::get_stack_guard_test_value()
|
||||||
* \param[in] str Pointer to string stored in flash memory.
|
* \param[in] str Pointer to string stored in flash memory.
|
||||||
*/
|
*/
|
||||||
void SdFatUtil::print_P( PGM_P str) {
|
void SdFatUtil::print_P( PGM_P str) {
|
||||||
for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c);
|
for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** %Print a string in flash memory followed by a CR/LF.
|
/** %Print a string in flash memory followed by a CR/LF.
|
||||||
|
|
@ -82,8 +82,8 @@ void SdFatUtil::print_P( PGM_P str) {
|
||||||
* \param[in] str Pointer to string stored in flash memory.
|
* \param[in] str Pointer to string stored in flash memory.
|
||||||
*/
|
*/
|
||||||
void SdFatUtil::println_P( PGM_P str) {
|
void SdFatUtil::println_P( PGM_P str) {
|
||||||
print_P( str);
|
print_P( str);
|
||||||
MYSERIAL.println();
|
MYSERIAL.println();
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** %Print a string in flash memory to Serial.
|
/** %Print a string in flash memory to Serial.
|
||||||
|
|
@ -91,7 +91,7 @@ void SdFatUtil::println_P( PGM_P str) {
|
||||||
* \param[in] str Pointer to string stored in flash memory.
|
* \param[in] str Pointer to string stored in flash memory.
|
||||||
*/
|
*/
|
||||||
void SdFatUtil::SerialPrint_P(PGM_P str) {
|
void SdFatUtil::SerialPrint_P(PGM_P str) {
|
||||||
print_P(str);
|
print_P(str);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** %Print a string in flash memory to Serial followed by a CR/LF.
|
/** %Print a string in flash memory to Serial followed by a CR/LF.
|
||||||
|
|
@ -99,6 +99,6 @@ void SdFatUtil::SerialPrint_P(PGM_P str) {
|
||||||
* \param[in] str Pointer to string stored in flash memory.
|
* \param[in] str Pointer to string stored in flash memory.
|
||||||
*/
|
*/
|
||||||
void SdFatUtil::SerialPrintln_P(PGM_P str) {
|
void SdFatUtil::SerialPrintln_P(PGM_P str) {
|
||||||
println_P( str);
|
println_P( str);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -34,14 +34,14 @@
|
||||||
#define PgmPrintln(x) SerialPrintln_P(PSTR(x))
|
#define PgmPrintln(x) SerialPrintln_P(PSTR(x))
|
||||||
|
|
||||||
namespace SdFatUtil {
|
namespace SdFatUtil {
|
||||||
int FreeRam();
|
int FreeRam();
|
||||||
void print_P( PGM_P str);
|
void print_P( PGM_P str);
|
||||||
void println_P( PGM_P str);
|
void println_P( PGM_P str);
|
||||||
void SerialPrint_P(PGM_P str);
|
void SerialPrint_P(PGM_P str);
|
||||||
void SerialPrintln_P(PGM_P str);
|
void SerialPrintln_P(PGM_P str);
|
||||||
void set_stack_guard();
|
void set_stack_guard();
|
||||||
bool test_stack_integrity();
|
bool test_stack_integrity();
|
||||||
uint32_t get_stack_guard_test_value();
|
uint32_t get_stack_guard_test_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace SdFatUtil; // NOLINT
|
using namespace SdFatUtil; // NOLINT
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int16_t SdFile::write(const void* buf, uint16_t nbyte) {
|
int16_t SdFile::write(const void* buf, uint16_t nbyte) {
|
||||||
return SdBaseFile::write(buf, nbyte);
|
return SdBaseFile::write(buf, nbyte);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Write a byte to a file. Required by the Arduino Print class.
|
/** Write a byte to a file. Required by the Arduino Print class.
|
||||||
|
|
@ -71,7 +71,7 @@ void SdFile::write(uint8_t b)
|
||||||
* Use writeError to check for errors.
|
* Use writeError to check for errors.
|
||||||
*/
|
*/
|
||||||
void SdFile::write(const char* str) {
|
void SdFile::write(const char* str) {
|
||||||
SdBaseFile::write(str, strlen(str));
|
SdBaseFile::write(str, strlen(str));
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Write a PROGMEM string to a file.
|
/** Write a PROGMEM string to a file.
|
||||||
|
|
@ -79,7 +79,7 @@ void SdFile::write(const char* str) {
|
||||||
* Use writeError to check for errors.
|
* Use writeError to check for errors.
|
||||||
*/
|
*/
|
||||||
void SdFile::write_P(PGM_P str) {
|
void SdFile::write_P(PGM_P str) {
|
||||||
for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
|
for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Write a PROGMEM string followed by CR/LF to a file.
|
/** Write a PROGMEM string followed by CR/LF to a file.
|
||||||
|
|
@ -87,8 +87,8 @@ void SdFile::write_P(PGM_P str) {
|
||||||
* Use writeError to check for errors.
|
* Use writeError to check for errors.
|
||||||
*/
|
*/
|
||||||
void SdFile::writeln_P(PGM_P str) {
|
void SdFile::writeln_P(PGM_P str) {
|
||||||
write_P(str);
|
write_P(str);
|
||||||
write_P(PSTR("\r\n"));
|
write_P(PSTR("\r\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,20 +33,20 @@
|
||||||
* \class SdFile
|
* \class SdFile
|
||||||
* \brief SdBaseFile with Print.
|
* \brief SdBaseFile with Print.
|
||||||
*/
|
*/
|
||||||
class SdFile : public SdBaseFile/*, public Print*/ {
|
class SdFile : public SdBaseFile { /*, public Print*/
|
||||||
public:
|
public:
|
||||||
SdFile() {}
|
SdFile() {}
|
||||||
SdFile(const char* name, uint8_t oflag);
|
SdFile(const char* name, uint8_t oflag);
|
||||||
#if ARDUINO >= 100
|
#if ARDUINO >= 100
|
||||||
size_t write(uint8_t b);
|
size_t write(uint8_t b);
|
||||||
#else
|
#else
|
||||||
void write(uint8_t b);
|
void write(uint8_t b);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int16_t write(const void* buf, uint16_t nbyte);
|
int16_t write(const void* buf, uint16_t nbyte);
|
||||||
void write(const char* str);
|
void write(const char* str);
|
||||||
void write_P(PGM_P str);
|
void write_P(PGM_P str);
|
||||||
void writeln_P(PGM_P str);
|
void writeln_P(PGM_P str);
|
||||||
};
|
};
|
||||||
#endif // SdFile_h
|
#endif // SdFile_h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,188 +98,188 @@ uint8_t const DATA_RES_ACCEPTED = 0X05;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Card IDentification (CID) register */
|
/** Card IDentification (CID) register */
|
||||||
typedef struct CID {
|
typedef struct CID {
|
||||||
// byte 0
|
// byte 0
|
||||||
/** Manufacturer ID */
|
/** Manufacturer ID */
|
||||||
unsigned char mid;
|
unsigned char mid;
|
||||||
// byte 1-2
|
// byte 1-2
|
||||||
/** OEM/Application ID */
|
/** OEM/Application ID */
|
||||||
char oid[2];
|
char oid[2];
|
||||||
// byte 3-7
|
// byte 3-7
|
||||||
/** Product name */
|
/** Product name */
|
||||||
char pnm[5];
|
char pnm[5];
|
||||||
// byte 8
|
// byte 8
|
||||||
/** Product revision least significant digit */
|
/** Product revision least significant digit */
|
||||||
unsigned char prv_m : 4;
|
unsigned char prv_m : 4;
|
||||||
/** Product revision most significant digit */
|
/** Product revision most significant digit */
|
||||||
unsigned char prv_n : 4;
|
unsigned char prv_n : 4;
|
||||||
// byte 9-12
|
// byte 9-12
|
||||||
/** Product serial number */
|
/** Product serial number */
|
||||||
uint32_t psn;
|
uint32_t psn;
|
||||||
// byte 13
|
// byte 13
|
||||||
/** Manufacturing date year low digit */
|
/** Manufacturing date year low digit */
|
||||||
unsigned char mdt_year_high : 4;
|
unsigned char mdt_year_high : 4;
|
||||||
/** not used */
|
/** not used */
|
||||||
unsigned char reserved : 4;
|
unsigned char reserved : 4;
|
||||||
// byte 14
|
// byte 14
|
||||||
/** Manufacturing date month */
|
/** Manufacturing date month */
|
||||||
unsigned char mdt_month : 4;
|
unsigned char mdt_month : 4;
|
||||||
/** Manufacturing date year low digit */
|
/** Manufacturing date year low digit */
|
||||||
unsigned char mdt_year_low :4;
|
unsigned char mdt_year_low :4;
|
||||||
// byte 15
|
// byte 15
|
||||||
/** not used always 1 */
|
/** not used always 1 */
|
||||||
unsigned char always1 : 1;
|
unsigned char always1 : 1;
|
||||||
/** CRC7 checksum */
|
/** CRC7 checksum */
|
||||||
unsigned char crc : 7;
|
unsigned char crc : 7;
|
||||||
}cid_t;
|
} cid_t;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** CSD for version 1.00 cards */
|
/** CSD for version 1.00 cards */
|
||||||
typedef struct CSDV1 {
|
typedef struct CSDV1 {
|
||||||
// byte 0
|
// byte 0
|
||||||
unsigned char reserved1 : 6;
|
unsigned char reserved1 : 6;
|
||||||
unsigned char csd_ver : 2;
|
unsigned char csd_ver : 2;
|
||||||
// byte 1
|
// byte 1
|
||||||
unsigned char taac;
|
unsigned char taac;
|
||||||
// byte 2
|
// byte 2
|
||||||
unsigned char nsac;
|
unsigned char nsac;
|
||||||
// byte 3
|
// byte 3
|
||||||
unsigned char tran_speed;
|
unsigned char tran_speed;
|
||||||
// byte 4
|
// byte 4
|
||||||
unsigned char ccc_high;
|
unsigned char ccc_high;
|
||||||
// byte 5
|
// byte 5
|
||||||
unsigned char read_bl_len : 4;
|
unsigned char read_bl_len : 4;
|
||||||
unsigned char ccc_low : 4;
|
unsigned char ccc_low : 4;
|
||||||
// byte 6
|
// byte 6
|
||||||
unsigned char c_size_high : 2;
|
unsigned char c_size_high : 2;
|
||||||
unsigned char reserved2 : 2;
|
unsigned char reserved2 : 2;
|
||||||
unsigned char dsr_imp : 1;
|
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 write_blk_misalign : 1;
|
||||||
unsigned char read_bl_partial : 1;
|
unsigned char read_bl_partial : 1;
|
||||||
// byte 7
|
// byte 7
|
||||||
unsigned char c_size_mid;
|
unsigned char c_size_mid;
|
||||||
// byte 8
|
// byte 8
|
||||||
unsigned char vdd_r_curr_max : 3;
|
unsigned char vdd_r_curr_max : 3;
|
||||||
unsigned char vdd_r_curr_min : 3;
|
unsigned char vdd_r_curr_min : 3;
|
||||||
unsigned char c_size_low :2;
|
unsigned char c_size_low :2;
|
||||||
// byte 9
|
// byte 9
|
||||||
unsigned char c_size_mult_high : 2;
|
unsigned char c_size_mult_high : 2;
|
||||||
unsigned char vdd_w_cur_max : 3;
|
unsigned char vdd_w_cur_max : 3;
|
||||||
unsigned char vdd_w_curr_min : 3;
|
unsigned char vdd_w_curr_min : 3;
|
||||||
// byte 10
|
// byte 10
|
||||||
unsigned char sector_size_high : 6;
|
unsigned char sector_size_high : 6;
|
||||||
unsigned char erase_blk_en : 1;
|
unsigned char erase_blk_en : 1;
|
||||||
unsigned char c_size_mult_low : 1;
|
unsigned char c_size_mult_low : 1;
|
||||||
// byte 11
|
// byte 11
|
||||||
unsigned char wp_grp_size : 7;
|
unsigned char wp_grp_size : 7;
|
||||||
unsigned char sector_size_low : 1;
|
unsigned char sector_size_low : 1;
|
||||||
// byte 12
|
// byte 12
|
||||||
unsigned char write_bl_len_high : 2;
|
unsigned char write_bl_len_high : 2;
|
||||||
unsigned char r2w_factor : 3;
|
unsigned char r2w_factor : 3;
|
||||||
unsigned char reserved3 : 2;
|
unsigned char reserved3 : 2;
|
||||||
unsigned char wp_grp_enable : 1;
|
unsigned char wp_grp_enable : 1;
|
||||||
// byte 13
|
// byte 13
|
||||||
unsigned char reserved4 : 5;
|
unsigned char reserved4 : 5;
|
||||||
unsigned char write_partial : 1;
|
unsigned char write_partial : 1;
|
||||||
unsigned char write_bl_len_low : 2;
|
unsigned char write_bl_len_low : 2;
|
||||||
// byte 14
|
// byte 14
|
||||||
unsigned char reserved5: 2;
|
unsigned char reserved5: 2;
|
||||||
unsigned char file_format : 2;
|
unsigned char file_format : 2;
|
||||||
unsigned char tmp_write_protect : 1;
|
unsigned char tmp_write_protect : 1;
|
||||||
unsigned char perm_write_protect : 1;
|
unsigned char perm_write_protect : 1;
|
||||||
unsigned char copy : 1;
|
unsigned char copy : 1;
|
||||||
/** Indicates the file format on the card */
|
/** Indicates the file format on the card */
|
||||||
unsigned char file_format_grp : 1;
|
unsigned char file_format_grp : 1;
|
||||||
// byte 15
|
// byte 15
|
||||||
unsigned char always1 : 1;
|
unsigned char always1 : 1;
|
||||||
unsigned char crc : 7;
|
unsigned char crc : 7;
|
||||||
}csd1_t;
|
} csd1_t;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** CSD for version 2.00 cards */
|
/** CSD for version 2.00 cards */
|
||||||
typedef struct CSDV2 {
|
typedef struct CSDV2 {
|
||||||
// byte 0
|
// byte 0
|
||||||
unsigned char reserved1 : 6;
|
unsigned char reserved1 : 6;
|
||||||
unsigned char csd_ver : 2;
|
unsigned char csd_ver : 2;
|
||||||
// byte 1
|
// byte 1
|
||||||
/** fixed to 0X0E */
|
/** fixed to 0X0E */
|
||||||
unsigned char taac;
|
unsigned char taac;
|
||||||
// byte 2
|
// byte 2
|
||||||
/** fixed to 0 */
|
/** fixed to 0 */
|
||||||
unsigned char nsac;
|
unsigned char nsac;
|
||||||
// byte 3
|
// byte 3
|
||||||
unsigned char tran_speed;
|
unsigned char tran_speed;
|
||||||
// byte 4
|
// byte 4
|
||||||
unsigned char ccc_high;
|
unsigned char ccc_high;
|
||||||
// byte 5
|
// byte 5
|
||||||
/** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
|
/** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
|
||||||
unsigned char read_bl_len : 4;
|
unsigned char read_bl_len : 4;
|
||||||
unsigned char ccc_low : 4;
|
unsigned char ccc_low : 4;
|
||||||
// byte 6
|
// byte 6
|
||||||
/** not used */
|
/** not used */
|
||||||
unsigned char reserved2 : 4;
|
unsigned char reserved2 : 4;
|
||||||
unsigned char dsr_imp : 1;
|
unsigned char dsr_imp : 1;
|
||||||
/** fixed to 0 */
|
/** fixed to 0 */
|
||||||
unsigned char read_blk_misalign :1;
|
unsigned char read_blk_misalign :1;
|
||||||
/** fixed to 0 */
|
/** fixed to 0 */
|
||||||
unsigned char write_blk_misalign : 1;
|
unsigned char write_blk_misalign : 1;
|
||||||
/** fixed to 0 - no partial read */
|
/** fixed to 0 - no partial read */
|
||||||
unsigned char read_bl_partial : 1;
|
unsigned char read_bl_partial : 1;
|
||||||
// byte 7
|
// byte 7
|
||||||
/** not used */
|
/** not used */
|
||||||
unsigned char reserved3 : 2;
|
unsigned char reserved3 : 2;
|
||||||
/** high part of card size */
|
/** high part of card size */
|
||||||
unsigned char c_size_high : 6;
|
unsigned char c_size_high : 6;
|
||||||
// byte 8
|
// byte 8
|
||||||
/** middle part of card size */
|
/** middle part of card size */
|
||||||
unsigned char c_size_mid;
|
unsigned char c_size_mid;
|
||||||
// byte 9
|
// byte 9
|
||||||
/** low part of card size */
|
/** low part of card size */
|
||||||
unsigned char c_size_low;
|
unsigned char c_size_low;
|
||||||
// byte 10
|
// byte 10
|
||||||
/** sector size is fixed at 64 KB */
|
/** sector size is fixed at 64 KB */
|
||||||
unsigned char sector_size_high : 6;
|
unsigned char sector_size_high : 6;
|
||||||
/** fixed to 1 - erase single is supported */
|
/** fixed to 1 - erase single is supported */
|
||||||
unsigned char erase_blk_en : 1;
|
unsigned char erase_blk_en : 1;
|
||||||
/** not used */
|
/** not used */
|
||||||
unsigned char reserved4 : 1;
|
unsigned char reserved4 : 1;
|
||||||
// byte 11
|
// byte 11
|
||||||
unsigned char wp_grp_size : 7;
|
unsigned char wp_grp_size : 7;
|
||||||
/** sector size is fixed at 64 KB */
|
/** sector size is fixed at 64 KB */
|
||||||
unsigned char sector_size_low : 1;
|
unsigned char sector_size_low : 1;
|
||||||
// byte 12
|
// byte 12
|
||||||
/** write_bl_len fixed for 512 byte blocks */
|
/** write_bl_len fixed for 512 byte blocks */
|
||||||
unsigned char write_bl_len_high : 2;
|
unsigned char write_bl_len_high : 2;
|
||||||
/** fixed value of 2 */
|
/** fixed value of 2 */
|
||||||
unsigned char r2w_factor : 3;
|
unsigned char r2w_factor : 3;
|
||||||
/** not used */
|
/** not used */
|
||||||
unsigned char reserved5 : 2;
|
unsigned char reserved5 : 2;
|
||||||
/** fixed value of 0 - no write protect groups */
|
/** fixed value of 0 - no write protect groups */
|
||||||
unsigned char wp_grp_enable : 1;
|
unsigned char wp_grp_enable : 1;
|
||||||
// byte 13
|
// byte 13
|
||||||
unsigned char reserved6 : 5;
|
unsigned char reserved6 : 5;
|
||||||
/** always zero - no partial block read*/
|
/** always zero - no partial block read*/
|
||||||
unsigned char write_partial : 1;
|
unsigned char write_partial : 1;
|
||||||
/** write_bl_len fixed for 512 byte blocks */
|
/** write_bl_len fixed for 512 byte blocks */
|
||||||
unsigned char write_bl_len_low : 2;
|
unsigned char write_bl_len_low : 2;
|
||||||
// byte 14
|
// byte 14
|
||||||
unsigned char reserved7: 2;
|
unsigned char reserved7: 2;
|
||||||
/** Do not use always 0 */
|
/** Do not use always 0 */
|
||||||
unsigned char file_format : 2;
|
unsigned char file_format : 2;
|
||||||
unsigned char tmp_write_protect : 1;
|
unsigned char tmp_write_protect : 1;
|
||||||
unsigned char perm_write_protect : 1;
|
unsigned char perm_write_protect : 1;
|
||||||
unsigned char copy : 1;
|
unsigned char copy : 1;
|
||||||
/** Do not use always 0 */
|
/** Do not use always 0 */
|
||||||
unsigned char file_format_grp : 1;
|
unsigned char file_format_grp : 1;
|
||||||
// byte 15
|
// byte 15
|
||||||
/** not used always 1 */
|
/** not used always 1 */
|
||||||
unsigned char always1 : 1;
|
unsigned char always1 : 1;
|
||||||
/** checksum */
|
/** checksum */
|
||||||
unsigned char crc : 7;
|
unsigned char crc : 7;
|
||||||
}csd2_t;
|
} csd2_t;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** union of old and new style CSD register */
|
/** union of old and new style CSD register */
|
||||||
union csd_t {
|
union csd_t {
|
||||||
csd1_t v1;
|
csd1_t v1;
|
||||||
csd2_t v2;
|
csd2_t v2;
|
||||||
};
|
};
|
||||||
#endif // SdInfo_h
|
#endif // SdInfo_h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,244 +33,244 @@ uint32_t SdVolume::cacheMirrorBlock_; // mirror block for second FAT
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// find a contiguous group of clusters
|
// find a contiguous group of clusters
|
||||||
bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
|
||||||
// start of group
|
// start of group
|
||||||
uint32_t bgnCluster;
|
uint32_t bgnCluster;
|
||||||
// end of group
|
// end of group
|
||||||
uint32_t endCluster;
|
uint32_t endCluster;
|
||||||
// last cluster of FAT
|
// last cluster of FAT
|
||||||
uint32_t fatEnd = clusterCount_ + 1;
|
uint32_t fatEnd = clusterCount_ + 1;
|
||||||
|
|
||||||
// flag to save place to start next search
|
// flag to save place to start next search
|
||||||
bool setStart;
|
bool setStart;
|
||||||
|
|
||||||
// set search start cluster
|
// set search start cluster
|
||||||
if (*curCluster) {
|
if (*curCluster) {
|
||||||
// try to make file contiguous
|
// try to make file contiguous
|
||||||
bgnCluster = *curCluster + 1;
|
bgnCluster = *curCluster + 1;
|
||||||
|
|
||||||
// don't save new start location
|
// don't save new start location
|
||||||
setStart = false;
|
setStart = false;
|
||||||
} else {
|
} else {
|
||||||
// start at likely place for free cluster
|
// start at likely place for free cluster
|
||||||
bgnCluster = allocSearchStart_;
|
bgnCluster = allocSearchStart_;
|
||||||
|
|
||||||
// save next search start if one cluster
|
// save next search start if one cluster
|
||||||
setStart = count == 1;
|
setStart = count == 1;
|
||||||
}
|
|
||||||
// end of group
|
|
||||||
endCluster = bgnCluster;
|
|
||||||
|
|
||||||
// search the FAT for free clusters
|
|
||||||
for (uint32_t n = 0;; n++, endCluster++) {
|
|
||||||
// can't find space checked all clusters
|
|
||||||
if (n >= clusterCount_) goto fail;
|
|
||||||
|
|
||||||
// past end - start from beginning of FAT
|
|
||||||
if (endCluster > fatEnd) {
|
|
||||||
bgnCluster = endCluster = 2;
|
|
||||||
}
|
}
|
||||||
uint32_t f;
|
// end of group
|
||||||
if (!fatGet(endCluster, &f)) goto fail;
|
endCluster = bgnCluster;
|
||||||
|
|
||||||
if (f != 0) {
|
// search the FAT for free clusters
|
||||||
// cluster in use try next cluster as bgnCluster
|
for (uint32_t n = 0;; n++, endCluster++) {
|
||||||
bgnCluster = endCluster + 1;
|
// can't find space checked all clusters
|
||||||
} else if ((endCluster - bgnCluster + 1) == count) {
|
if (n >= clusterCount_) goto fail;
|
||||||
// done - found space
|
|
||||||
break;
|
// past end - start from beginning of FAT
|
||||||
|
if (endCluster > fatEnd) {
|
||||||
|
bgnCluster = endCluster = 2;
|
||||||
|
}
|
||||||
|
uint32_t f;
|
||||||
|
if (!fatGet(endCluster, &f)) goto fail;
|
||||||
|
|
||||||
|
if (f != 0) {
|
||||||
|
// cluster in use try next cluster as bgnCluster
|
||||||
|
bgnCluster = endCluster + 1;
|
||||||
|
} else if ((endCluster - bgnCluster + 1) == count) {
|
||||||
|
// done - found space
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
// mark end of chain
|
||||||
// mark end of chain
|
if (!fatPutEOC(endCluster)) goto fail;
|
||||||
if (!fatPutEOC(endCluster)) goto fail;
|
|
||||||
|
|
||||||
// link clusters
|
// link clusters
|
||||||
while (endCluster > bgnCluster) {
|
while (endCluster > bgnCluster) {
|
||||||
if (!fatPut(endCluster - 1, endCluster)) goto fail;
|
if (!fatPut(endCluster - 1, endCluster)) goto fail;
|
||||||
endCluster--;
|
endCluster--;
|
||||||
}
|
}
|
||||||
if (*curCluster != 0) {
|
if (*curCluster != 0) {
|
||||||
// connect chains
|
// connect chains
|
||||||
if (!fatPut(*curCluster, bgnCluster)) goto fail;
|
if (!fatPut(*curCluster, bgnCluster)) goto fail;
|
||||||
}
|
}
|
||||||
// return first cluster number to caller
|
// return first cluster number to caller
|
||||||
*curCluster = bgnCluster;
|
*curCluster = bgnCluster;
|
||||||
|
|
||||||
// remember possible next free cluster
|
// remember possible next free cluster
|
||||||
if (setStart) allocSearchStart_ = bgnCluster + 1;
|
if (setStart) allocSearchStart_ = bgnCluster + 1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool SdVolume::cacheFlush() {
|
bool SdVolume::cacheFlush() {
|
||||||
if (cacheDirty_) {
|
if (cacheDirty_) {
|
||||||
if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
|
if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
// mirror FAT tables
|
||||||
|
if (cacheMirrorBlock_) {
|
||||||
|
if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
cacheMirrorBlock_ = 0;
|
||||||
|
}
|
||||||
|
cacheDirty_ = 0;
|
||||||
}
|
}
|
||||||
// mirror FAT tables
|
return true;
|
||||||
if (cacheMirrorBlock_) {
|
|
||||||
if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
cacheMirrorBlock_ = 0;
|
|
||||||
}
|
|
||||||
cacheDirty_ = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
|
bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
|
||||||
if (cacheBlockNumber_ != blockNumber) {
|
if (cacheBlockNumber_ != blockNumber) {
|
||||||
if (!cacheFlush()) goto fail;
|
if (!cacheFlush()) goto fail;
|
||||||
if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto fail;
|
if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto fail;
|
||||||
cacheBlockNumber_ = blockNumber;
|
cacheBlockNumber_ = blockNumber;
|
||||||
}
|
}
|
||||||
if (dirty) cacheDirty_ = true;
|
if (dirty) cacheDirty_ = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// return the size in bytes of a cluster chain
|
// return the size in bytes of a cluster chain
|
||||||
bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
|
bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
|
||||||
uint32_t s = 0;
|
uint32_t s = 0;
|
||||||
do {
|
do {
|
||||||
if (!fatGet(cluster, &cluster)) goto fail;
|
if (!fatGet(cluster, &cluster)) goto fail;
|
||||||
s += 512UL << clusterSizeShift_;
|
s += 512UL << clusterSizeShift_;
|
||||||
} while (!isEOC(cluster));
|
} while (!isEOC(cluster));
|
||||||
*size = s;
|
*size = s;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Fetch a FAT entry
|
// Fetch a FAT entry
|
||||||
bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
||||||
uint32_t lba;
|
uint32_t lba;
|
||||||
if (cluster > (clusterCount_ + 1)) goto fail;
|
if (cluster > (clusterCount_ + 1)) goto fail;
|
||||||
if (FAT12_SUPPORT && fatType_ == 12) {
|
if (FAT12_SUPPORT && fatType_ == 12) {
|
||||||
uint16_t index = cluster;
|
uint16_t index = cluster;
|
||||||
index += index >> 1;
|
index += index >> 1;
|
||||||
lba = fatStartBlock_ + (index >> 9);
|
lba = fatStartBlock_ + (index >> 9);
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
|
||||||
index &= 0X1FF;
|
index &= 0X1FF;
|
||||||
uint16_t tmp = cacheBuffer_.data[index];
|
uint16_t tmp = cacheBuffer_.data[index];
|
||||||
index++;
|
index++;
|
||||||
if (index == 512) {
|
if (index == 512) {
|
||||||
if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto fail;
|
||||||
index = 0;
|
index = 0;
|
||||||
|
}
|
||||||
|
tmp |= cacheBuffer_.data[index] << 8;
|
||||||
|
*value = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (fatType_ == 16) {
|
||||||
|
lba = fatStartBlock_ + (cluster >> 8);
|
||||||
|
} else if (fatType_ == 32) {
|
||||||
|
lba = fatStartBlock_ + (cluster >> 7);
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (lba != cacheBlockNumber_) {
|
||||||
|
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
|
||||||
|
}
|
||||||
|
if (fatType_ == 16) {
|
||||||
|
*value = cacheBuffer_.fat16[cluster & 0XFF];
|
||||||
|
} else {
|
||||||
|
*value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
|
||||||
}
|
}
|
||||||
tmp |= cacheBuffer_.data[index] << 8;
|
|
||||||
*value = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
if (fatType_ == 16) {
|
|
||||||
lba = fatStartBlock_ + (cluster >> 8);
|
|
||||||
} else if (fatType_ == 32) {
|
|
||||||
lba = fatStartBlock_ + (cluster >> 7);
|
|
||||||
} else {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (lba != cacheBlockNumber_) {
|
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto fail;
|
|
||||||
}
|
|
||||||
if (fatType_ == 16) {
|
|
||||||
*value = cacheBuffer_.fat16[cluster & 0XFF];
|
|
||||||
} else {
|
|
||||||
*value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Store a FAT entry
|
// Store a FAT entry
|
||||||
bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
||||||
uint32_t lba;
|
uint32_t lba;
|
||||||
// error if reserved cluster
|
// error if reserved cluster
|
||||||
if (cluster < 2) goto fail;
|
if (cluster < 2) goto fail;
|
||||||
|
|
||||||
// error if not in FAT
|
// error if not in FAT
|
||||||
if (cluster > (clusterCount_ + 1)) goto fail;
|
if (cluster > (clusterCount_ + 1)) goto fail;
|
||||||
|
|
||||||
if (FAT12_SUPPORT && fatType_ == 12) {
|
if (FAT12_SUPPORT && fatType_ == 12) {
|
||||||
uint16_t index = cluster;
|
uint16_t index = cluster;
|
||||||
index += index >> 1;
|
index += index >> 1;
|
||||||
lba = fatStartBlock_ + (index >> 9);
|
lba = fatStartBlock_ + (index >> 9);
|
||||||
|
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
||||||
|
// mirror second FAT
|
||||||
|
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
||||||
|
index &= 0X1FF;
|
||||||
|
uint8_t tmp = value;
|
||||||
|
if (cluster & 1) {
|
||||||
|
tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4;
|
||||||
|
}
|
||||||
|
cacheBuffer_.data[index] = tmp;
|
||||||
|
index++;
|
||||||
|
if (index == 512) {
|
||||||
|
lba++;
|
||||||
|
index = 0;
|
||||||
|
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
||||||
|
// mirror second FAT
|
||||||
|
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
||||||
|
}
|
||||||
|
tmp = value >> 4;
|
||||||
|
if (!(cluster & 1)) {
|
||||||
|
tmp = ((cacheBuffer_.data[index] & 0XF0)) | tmp >> 4;
|
||||||
|
}
|
||||||
|
cacheBuffer_.data[index] = tmp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (fatType_ == 16) {
|
||||||
|
lba = fatStartBlock_ + (cluster >> 8);
|
||||||
|
} else if (fatType_ == 32) {
|
||||||
|
lba = fatStartBlock_ + (cluster >> 7);
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
||||||
|
// store entry
|
||||||
|
if (fatType_ == 16) {
|
||||||
|
cacheBuffer_.fat16[cluster & 0XFF] = value;
|
||||||
|
} else {
|
||||||
|
cacheBuffer_.fat32[cluster & 0X7F] = value;
|
||||||
|
}
|
||||||
// mirror second FAT
|
// mirror second FAT
|
||||||
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
||||||
index &= 0X1FF;
|
|
||||||
uint8_t tmp = value;
|
|
||||||
if (cluster & 1) {
|
|
||||||
tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4;
|
|
||||||
}
|
|
||||||
cacheBuffer_.data[index] = tmp;
|
|
||||||
index++;
|
|
||||||
if (index == 512) {
|
|
||||||
lba++;
|
|
||||||
index = 0;
|
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
|
||||||
// mirror second FAT
|
|
||||||
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
|
||||||
}
|
|
||||||
tmp = value >> 4;
|
|
||||||
if (!(cluster & 1)) {
|
|
||||||
tmp = ((cacheBuffer_.data[index] & 0XF0)) | tmp >> 4;
|
|
||||||
}
|
|
||||||
cacheBuffer_.data[index] = tmp;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
if (fatType_ == 16) {
|
|
||||||
lba = fatStartBlock_ + (cluster >> 8);
|
|
||||||
} else if (fatType_ == 32) {
|
|
||||||
lba = fatStartBlock_ + (cluster >> 7);
|
|
||||||
} else {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto fail;
|
|
||||||
// store entry
|
|
||||||
if (fatType_ == 16) {
|
|
||||||
cacheBuffer_.fat16[cluster & 0XFF] = value;
|
|
||||||
} else {
|
|
||||||
cacheBuffer_.fat32[cluster & 0X7F] = value;
|
|
||||||
}
|
|
||||||
// mirror second FAT
|
|
||||||
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// free a cluster chain
|
// free a cluster chain
|
||||||
bool SdVolume::freeChain(uint32_t cluster) {
|
bool SdVolume::freeChain(uint32_t cluster) {
|
||||||
uint32_t next;
|
uint32_t next;
|
||||||
|
|
||||||
// clear free cluster location
|
// clear free cluster location
|
||||||
allocSearchStart_ = 2;
|
allocSearchStart_ = 2;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!fatGet(cluster, &next)) goto fail;
|
if (!fatGet(cluster, &next)) goto fail;
|
||||||
|
|
||||||
// free cluster
|
// free cluster
|
||||||
if (!fatPut(cluster, 0)) goto fail;
|
if (!fatPut(cluster, 0)) goto fail;
|
||||||
|
|
||||||
cluster = next;
|
cluster = next;
|
||||||
} while (!isEOC(cluster));
|
} while (!isEOC(cluster));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Volume free space in clusters.
|
/** Volume free space in clusters.
|
||||||
|
|
@ -278,33 +278,33 @@ bool SdVolume::freeChain(uint32_t cluster) {
|
||||||
* \return Count of free clusters for success or -1 if an error occurs.
|
* \return Count of free clusters for success or -1 if an error occurs.
|
||||||
*/
|
*/
|
||||||
int32_t SdVolume::freeClusterCount() {
|
int32_t SdVolume::freeClusterCount() {
|
||||||
uint32_t free = 0;
|
uint32_t free = 0;
|
||||||
uint16_t n;
|
uint16_t n;
|
||||||
uint32_t todo = clusterCount_ + 2;
|
uint32_t todo = clusterCount_ + 2;
|
||||||
|
|
||||||
if (fatType_ == 16) {
|
|
||||||
n = 256;
|
|
||||||
} else if (fatType_ == 32) {
|
|
||||||
n = 128;
|
|
||||||
} else {
|
|
||||||
// put FAT12 here
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t lba = fatStartBlock_; todo; todo -= n, lba++) {
|
|
||||||
if (!cacheRawBlock(lba, CACHE_FOR_READ)) return -1;
|
|
||||||
if (todo < n) n = todo;
|
|
||||||
if (fatType_ == 16) {
|
if (fatType_ == 16) {
|
||||||
for (uint16_t i = 0; i < n; i++) {
|
n = 256;
|
||||||
if (cacheBuffer_.fat16[i] == 0) free++;
|
} else if (fatType_ == 32) {
|
||||||
}
|
n = 128;
|
||||||
} else {
|
} else {
|
||||||
for (uint16_t i = 0; i < n; i++) {
|
// put FAT12 here
|
||||||
if (cacheBuffer_.fat32[i] == 0) free++;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return free;
|
for (uint32_t lba = fatStartBlock_; todo; todo -= n, lba++) {
|
||||||
|
if (!cacheRawBlock(lba, CACHE_FOR_READ)) return -1;
|
||||||
|
if (todo < n) n = todo;
|
||||||
|
if (fatType_ == 16) {
|
||||||
|
for (uint16_t i = 0; i < n; i++) {
|
||||||
|
if (cacheBuffer_.fat16[i] == 0) free++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint16_t i = 0; i < n; i++) {
|
||||||
|
if (cacheBuffer_.fat32[i] == 0) free++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return free;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Initialize a FAT volume.
|
/** Initialize a FAT volume.
|
||||||
|
|
@ -322,84 +322,84 @@ int32_t SdVolume::freeClusterCount() {
|
||||||
* FAT file system in the specified partition or an I/O error.
|
* FAT file system in the specified partition or an I/O error.
|
||||||
*/
|
*/
|
||||||
bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
bool SdVolume::init(Sd2Card* dev, uint8_t part) {
|
||||||
uint32_t totalBlocks;
|
uint32_t totalBlocks;
|
||||||
uint32_t volumeStartBlock = 0;
|
uint32_t volumeStartBlock = 0;
|
||||||
fat32_boot_t* fbs;
|
fat32_boot_t* fbs;
|
||||||
|
|
||||||
sdCard_ = dev;
|
sdCard_ = dev;
|
||||||
fatType_ = 0;
|
fatType_ = 0;
|
||||||
allocSearchStart_ = 2;
|
allocSearchStart_ = 2;
|
||||||
cacheDirty_ = 0; // cacheFlush() will write block if true
|
cacheDirty_ = 0; // cacheFlush() will write block if true
|
||||||
cacheMirrorBlock_ = 0;
|
cacheMirrorBlock_ = 0;
|
||||||
cacheBlockNumber_ = 0XFFFFFFFF;
|
cacheBlockNumber_ = 0XFFFFFFFF;
|
||||||
|
|
||||||
// if part == 0 assume super floppy with FAT boot sector in block zero
|
// if part == 0 assume super floppy with FAT boot sector in block zero
|
||||||
// if part > 0 assume mbr volume with partition table
|
// if part > 0 assume mbr volume with partition table
|
||||||
if (part) {
|
if (part) {
|
||||||
if (part > 4)goto fail;
|
if (part > 4)goto fail;
|
||||||
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
||||||
part_t* p = &cacheBuffer_.mbr.part[part-1];
|
part_t* p = &cacheBuffer_.mbr.part[part-1];
|
||||||
if ((p->boot & 0X7F) !=0 ||
|
if ((p->boot & 0X7F) !=0 ||
|
||||||
p->totalSectors < 100 ||
|
p->totalSectors < 100 ||
|
||||||
p->firstSector == 0) {
|
p->firstSector == 0) {
|
||||||
// not a valid partition
|
// not a valid partition
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
volumeStartBlock = p->firstSector;
|
||||||
}
|
}
|
||||||
volumeStartBlock = p->firstSector;
|
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
||||||
}
|
fbs = &cacheBuffer_.fbs32;
|
||||||
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto fail;
|
if (fbs->bytesPerSector != 512 ||
|
||||||
fbs = &cacheBuffer_.fbs32;
|
fbs->fatCount == 0 ||
|
||||||
if (fbs->bytesPerSector != 512 ||
|
fbs->reservedSectorCount == 0 ||
|
||||||
fbs->fatCount == 0 ||
|
fbs->sectorsPerCluster == 0) {
|
||||||
fbs->reservedSectorCount == 0 ||
|
// not valid FAT volume
|
||||||
fbs->sectorsPerCluster == 0) {
|
goto fail;
|
||||||
// not valid FAT volume
|
}
|
||||||
goto fail;
|
fatCount_ = fbs->fatCount;
|
||||||
}
|
blocksPerCluster_ = fbs->sectorsPerCluster;
|
||||||
fatCount_ = fbs->fatCount;
|
// determine shift that is same as multiply by blocksPerCluster_
|
||||||
blocksPerCluster_ = fbs->sectorsPerCluster;
|
clusterSizeShift_ = 0;
|
||||||
// determine shift that is same as multiply by blocksPerCluster_
|
while (blocksPerCluster_ != (1 << clusterSizeShift_)) {
|
||||||
clusterSizeShift_ = 0;
|
// error if not power of 2
|
||||||
while (blocksPerCluster_ != (1 << clusterSizeShift_)) {
|
if (clusterSizeShift_++ > 7) goto fail;
|
||||||
// error if not power of 2
|
}
|
||||||
if (clusterSizeShift_++ > 7) goto fail;
|
blocksPerFat_ = fbs->sectorsPerFat16 ?
|
||||||
}
|
|
||||||
blocksPerFat_ = fbs->sectorsPerFat16 ?
|
|
||||||
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
|
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
|
||||||
|
|
||||||
fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount;
|
fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount;
|
||||||
|
|
||||||
// count for FAT16 zero for FAT32
|
// count for FAT16 zero for FAT32
|
||||||
rootDirEntryCount_ = fbs->rootDirEntryCount;
|
rootDirEntryCount_ = fbs->rootDirEntryCount;
|
||||||
|
|
||||||
// directory start for FAT16 dataStart for FAT32
|
// directory start for FAT16 dataStart for FAT32
|
||||||
rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_;
|
rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_;
|
||||||
|
|
||||||
// data start for FAT16 and FAT32
|
// 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
|
// total blocks for FAT16 or FAT32
|
||||||
totalBlocks = fbs->totalSectors16 ?
|
totalBlocks = fbs->totalSectors16 ?
|
||||||
fbs->totalSectors16 : fbs->totalSectors32;
|
fbs->totalSectors16 : fbs->totalSectors32;
|
||||||
// total data blocks
|
// total data blocks
|
||||||
clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
|
clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
|
||||||
|
|
||||||
// divide by cluster size to get cluster count
|
// divide by cluster size to get cluster count
|
||||||
clusterCount_ >>= clusterSizeShift_;
|
clusterCount_ >>= clusterSizeShift_;
|
||||||
|
|
||||||
// FAT type is determined by cluster count
|
// FAT type is determined by cluster count
|
||||||
if (clusterCount_ < 4085) {
|
if (clusterCount_ < 4085) {
|
||||||
fatType_ = 12;
|
fatType_ = 12;
|
||||||
if (!FAT12_SUPPORT) goto fail;
|
if (!FAT12_SUPPORT) goto fail;
|
||||||
} else if (clusterCount_ < 65525) {
|
} else if (clusterCount_ < 65525) {
|
||||||
fatType_ = 16;
|
fatType_ = 16;
|
||||||
} else {
|
} else {
|
||||||
rootDirStart_ = fbs->fat32RootCluster;
|
rootDirStart_ = fbs->fat32RootCluster;
|
||||||
fatType_ = 32;
|
fatType_ = 32;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -35,22 +35,22 @@
|
||||||
* \brief Cache for an SD data block
|
* \brief Cache for an SD data block
|
||||||
*/
|
*/
|
||||||
union cache_t {
|
union cache_t {
|
||||||
/** Used to access cached file data blocks. */
|
/** Used to access cached file data blocks. */
|
||||||
uint8_t data[512];
|
uint8_t data[512];
|
||||||
/** Used to access cached FAT16 entries. */
|
/** Used to access cached FAT16 entries. */
|
||||||
uint16_t fat16[256];
|
uint16_t fat16[256];
|
||||||
/** Used to access cached FAT32 entries. */
|
/** Used to access cached FAT32 entries. */
|
||||||
uint32_t fat32[128];
|
uint32_t fat32[128];
|
||||||
/** Used to access cached directory entries. */
|
/** Used to access cached directory entries. */
|
||||||
dir_t dir[16];
|
dir_t dir[16];
|
||||||
/** Used to access a cached Master Boot Record. */
|
/** Used to access a cached Master Boot Record. */
|
||||||
mbr_t mbr;
|
mbr_t mbr;
|
||||||
/** Used to access to a cached FAT boot sector. */
|
/** Used to access to a cached FAT boot sector. */
|
||||||
fat_boot_t fbs;
|
fat_boot_t fbs;
|
||||||
/** Used to access to a cached FAT32 boot sector. */
|
/** Used to access to a cached FAT32 boot sector. */
|
||||||
fat32_boot_t fbs32;
|
fat32_boot_t fbs32;
|
||||||
/** Used to access to a cached FAT32 FSINFO sector. */
|
/** Used to access to a cached FAT32 FSINFO sector. */
|
||||||
fat32_fsinfo_t fsinfo;
|
fat32_fsinfo_t fsinfo;
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
|
|
@ -58,156 +58,194 @@ union cache_t {
|
||||||
* \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
|
* \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
|
||||||
*/
|
*/
|
||||||
class SdVolume {
|
class SdVolume {
|
||||||
public:
|
public:
|
||||||
/** Create an instance of SdVolume */
|
/** Create an instance of SdVolume */
|
||||||
SdVolume() : fatType_(0) {}
|
SdVolume() : fatType_(0) {}
|
||||||
/** Clear the cache and returns a pointer to the cache. Used by the WaveRP
|
/** Clear the cache and returns a pointer to the cache. Used by the WaveRP
|
||||||
* recorder to do raw write to the SD card. Not for normal apps.
|
* recorder to do raw write to the SD card. Not for normal apps.
|
||||||
* \return A pointer to the cache buffer or zero if an error occurs.
|
* \return A pointer to the cache buffer or zero if an error occurs.
|
||||||
*/
|
*/
|
||||||
cache_t* cacheClear() {
|
cache_t* cacheClear() {
|
||||||
if (!cacheFlush()) return 0;
|
if (!cacheFlush()) return 0;
|
||||||
cacheBlockNumber_ = 0XFFFFFFFF;
|
cacheBlockNumber_ = 0XFFFFFFFF;
|
||||||
return &cacheBuffer_;
|
return &cacheBuffer_;
|
||||||
}
|
}
|
||||||
/** Initialize a FAT volume. Try partition one first then try super
|
/** Initialize a FAT volume. Try partition one first then try super
|
||||||
* floppy format.
|
* floppy format.
|
||||||
*
|
*
|
||||||
* \param[in] dev The Sd2Card where the volume is located.
|
* \param[in] dev The Sd2Card where the volume is located.
|
||||||
*
|
*
|
||||||
* \return The value one, true, is returned for success and
|
* \return The value one, true, is returned for success and
|
||||||
* the value zero, false, is returned for failure. Reasons for
|
* the value zero, false, is returned for failure. Reasons for
|
||||||
* failure include not finding a valid partition, not finding a valid
|
* failure include not finding a valid partition, not finding a valid
|
||||||
* FAT file system or an I/O error.
|
* FAT file system or an I/O error.
|
||||||
*/
|
*/
|
||||||
bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
|
bool init(Sd2Card* dev) {
|
||||||
bool init(Sd2Card* dev, uint8_t part);
|
return init(dev, 1) ? true : init(dev, 0);
|
||||||
|
}
|
||||||
|
bool init(Sd2Card* dev, uint8_t part);
|
||||||
|
|
||||||
// inline functions that return volume info
|
// inline functions that return volume info
|
||||||
/** \return The volume's cluster size in blocks. */
|
/** \return The volume's cluster size in blocks. */
|
||||||
uint8_t blocksPerCluster() const {return blocksPerCluster_;}
|
uint8_t blocksPerCluster() const {
|
||||||
/** \return The number of blocks in one FAT. */
|
return blocksPerCluster_;
|
||||||
uint32_t blocksPerFat() const {return blocksPerFat_;}
|
}
|
||||||
/** \return The total number of clusters in the volume. */
|
/** \return The number of blocks in one FAT. */
|
||||||
uint32_t clusterCount() const {return clusterCount_;}
|
uint32_t blocksPerFat() const {
|
||||||
/** \return The shift count required to multiply by blocksPerCluster. */
|
return blocksPerFat_;
|
||||||
uint8_t clusterSizeShift() const {return clusterSizeShift_;}
|
}
|
||||||
/** \return The logical block number for the start of file data. */
|
/** \return The total number of clusters in the volume. */
|
||||||
uint32_t dataStartBlock() const {return dataStartBlock_;}
|
uint32_t clusterCount() const {
|
||||||
/** \return The number of FAT structures on the volume. */
|
return clusterCount_;
|
||||||
uint8_t fatCount() const {return fatCount_;}
|
}
|
||||||
/** \return The logical block number for the start of the first FAT. */
|
/** \return The shift count required to multiply by blocksPerCluster. */
|
||||||
uint32_t fatStartBlock() const {return fatStartBlock_;}
|
uint8_t clusterSizeShift() const {
|
||||||
/** \return The FAT type of the volume. Values are 12, 16 or 32. */
|
return clusterSizeShift_;
|
||||||
uint8_t fatType() const {return fatType_;}
|
}
|
||||||
int32_t freeClusterCount();
|
/** \return The logical block number for the start of file data. */
|
||||||
/** \return The number of entries in the root directory for FAT16 volumes. */
|
uint32_t dataStartBlock() const {
|
||||||
uint32_t rootDirEntryCount() const {return rootDirEntryCount_;}
|
return dataStartBlock_;
|
||||||
/** \return The logical block number for the start of the root directory
|
}
|
||||||
on FAT16 volumes or the first cluster number on FAT32 volumes. */
|
/** \return The number of FAT structures on the volume. */
|
||||||
uint32_t rootDirStart() const {return rootDirStart_;}
|
uint8_t fatCount() const {
|
||||||
/** Sd2Card object for this volume
|
return fatCount_;
|
||||||
* \return pointer to Sd2Card object.
|
}
|
||||||
*/
|
/** \return The logical block number for the start of the first FAT. */
|
||||||
Sd2Card* sdCard() {return sdCard_;}
|
uint32_t fatStartBlock() const {
|
||||||
/** Debug access to FAT table
|
return fatStartBlock_;
|
||||||
*
|
}
|
||||||
* \param[in] n cluster number.
|
/** \return The FAT type of the volume. Values are 12, 16 or 32. */
|
||||||
* \param[out] v value of entry
|
uint8_t fatType() const {
|
||||||
* \return true for success or false for failure
|
return fatType_;
|
||||||
*/
|
}
|
||||||
bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
|
int32_t freeClusterCount();
|
||||||
|
/** \return The number of entries in the root directory for FAT16 volumes. */
|
||||||
|
uint32_t rootDirEntryCount() const {
|
||||||
|
return rootDirEntryCount_;
|
||||||
|
}
|
||||||
|
/** \return The logical block number for the start of the root directory
|
||||||
|
on FAT16 volumes or the first cluster number on FAT32 volumes. */
|
||||||
|
uint32_t rootDirStart() const {
|
||||||
|
return rootDirStart_;
|
||||||
|
}
|
||||||
|
/** Sd2Card object for this volume
|
||||||
|
* \return pointer to Sd2Card object.
|
||||||
|
*/
|
||||||
|
Sd2Card* sdCard() {
|
||||||
|
return sdCard_;
|
||||||
|
}
|
||||||
|
/** Debug access to FAT table
|
||||||
|
*
|
||||||
|
* \param[in] n cluster number.
|
||||||
|
* \param[out] v value of entry
|
||||||
|
* \return true for success or false for failure
|
||||||
|
*/
|
||||||
|
bool dbgFat(uint32_t n, uint32_t* v) {
|
||||||
|
return fatGet(n, v);
|
||||||
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
// Allow SdBaseFile access to SdVolume private data.
|
// Allow SdBaseFile access to SdVolume private data.
|
||||||
friend class SdBaseFile;
|
friend class SdBaseFile;
|
||||||
|
|
||||||
// value for dirty argument in cacheRawBlock to indicate read from cache
|
// value for dirty argument in cacheRawBlock to indicate read from cache
|
||||||
static bool const CACHE_FOR_READ = false;
|
static bool const CACHE_FOR_READ = false;
|
||||||
// value for dirty argument in cacheRawBlock to indicate write to cache
|
// value for dirty argument in cacheRawBlock to indicate write to cache
|
||||||
static bool const CACHE_FOR_WRITE = true;
|
static bool const CACHE_FOR_WRITE = true;
|
||||||
|
|
||||||
#if USE_MULTIPLE_CARDS
|
#if USE_MULTIPLE_CARDS
|
||||||
cache_t cacheBuffer_; // 512 byte cache for device blocks
|
cache_t cacheBuffer_; // 512 byte cache for device blocks
|
||||||
uint32_t cacheBlockNumber_; // Logical number of block in the cache
|
uint32_t cacheBlockNumber_; // Logical number of block in the cache
|
||||||
Sd2Card* sdCard_; // Sd2Card object for cache
|
Sd2Card* sdCard_; // Sd2Card object for cache
|
||||||
bool cacheDirty_; // cacheFlush() will write block if true
|
bool cacheDirty_; // cacheFlush() will write block if true
|
||||||
uint32_t cacheMirrorBlock_; // block number for mirror FAT
|
uint32_t cacheMirrorBlock_; // block number for mirror FAT
|
||||||
#else // USE_MULTIPLE_CARDS
|
#else // USE_MULTIPLE_CARDS
|
||||||
static cache_t cacheBuffer_; // 512 byte cache for device blocks
|
static cache_t cacheBuffer_; // 512 byte cache for device blocks
|
||||||
static uint32_t cacheBlockNumber_; // Logical number of block in the cache
|
static uint32_t cacheBlockNumber_; // Logical number of block in the cache
|
||||||
static Sd2Card* sdCard_; // Sd2Card object for cache
|
static Sd2Card* sdCard_; // Sd2Card object for cache
|
||||||
static bool cacheDirty_; // cacheFlush() will write block if true
|
static bool cacheDirty_; // cacheFlush() will write block if true
|
||||||
static uint32_t cacheMirrorBlock_; // block number for mirror FAT
|
static uint32_t cacheMirrorBlock_; // block number for mirror FAT
|
||||||
#endif // USE_MULTIPLE_CARDS
|
#endif // USE_MULTIPLE_CARDS
|
||||||
uint32_t allocSearchStart_; // start cluster for alloc search
|
uint32_t allocSearchStart_; // start cluster for alloc search
|
||||||
uint8_t blocksPerCluster_; // cluster size in blocks
|
uint8_t blocksPerCluster_; // cluster size in blocks
|
||||||
uint32_t blocksPerFat_; // FAT size in blocks
|
uint32_t blocksPerFat_; // FAT size in blocks
|
||||||
uint32_t clusterCount_; // clusters in one FAT
|
uint32_t clusterCount_; // clusters in one FAT
|
||||||
uint8_t clusterSizeShift_; // shift to convert cluster count to block count
|
uint8_t clusterSizeShift_; // shift to convert cluster count to block count
|
||||||
uint32_t dataStartBlock_; // first data block number
|
uint32_t dataStartBlock_; // first data block number
|
||||||
uint8_t fatCount_; // number of FATs on volume
|
uint8_t fatCount_; // number of FATs on volume
|
||||||
uint32_t fatStartBlock_; // start block for first FAT
|
uint32_t fatStartBlock_; // start block for first FAT
|
||||||
uint8_t fatType_; // volume type (12, 16, OR 32)
|
uint8_t fatType_; // volume type (12, 16, OR 32)
|
||||||
uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir
|
uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir
|
||||||
uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32
|
uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool allocContiguous(uint32_t count, uint32_t* curCluster);
|
bool allocContiguous(uint32_t count, uint32_t* curCluster);
|
||||||
uint8_t blockOfCluster(uint32_t position) const {
|
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_);}
|
uint32_t clusterStartBlock(uint32_t cluster) const {
|
||||||
uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
|
return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);
|
||||||
return clusterStartBlock(cluster) + blockOfCluster(position);}
|
}
|
||||||
cache_t *cache() {return &cacheBuffer_;}
|
uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
|
||||||
uint32_t cacheBlockNumber() {return cacheBlockNumber_;}
|
return clusterStartBlock(cluster) + blockOfCluster(position);
|
||||||
|
}
|
||||||
|
cache_t *cache() {
|
||||||
|
return &cacheBuffer_;
|
||||||
|
}
|
||||||
|
uint32_t cacheBlockNumber() {
|
||||||
|
return cacheBlockNumber_;
|
||||||
|
}
|
||||||
#if USE_MULTIPLE_CARDS
|
#if USE_MULTIPLE_CARDS
|
||||||
bool cacheFlush();
|
bool cacheFlush();
|
||||||
bool cacheRawBlock(uint32_t blockNumber, bool dirty);
|
bool cacheRawBlock(uint32_t blockNumber, bool dirty);
|
||||||
#else // USE_MULTIPLE_CARDS
|
#else // USE_MULTIPLE_CARDS
|
||||||
static bool cacheFlush();
|
static bool cacheFlush();
|
||||||
static bool cacheRawBlock(uint32_t blockNumber, bool dirty);
|
static bool cacheRawBlock(uint32_t blockNumber, bool dirty);
|
||||||
#endif // USE_MULTIPLE_CARDS
|
#endif // USE_MULTIPLE_CARDS
|
||||||
// used by SdBaseFile write to assign cache to SD location
|
// used by SdBaseFile write to assign cache to SD location
|
||||||
void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) {
|
void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) {
|
||||||
cacheDirty_ = dirty;
|
cacheDirty_ = dirty;
|
||||||
cacheBlockNumber_ = blockNumber;
|
cacheBlockNumber_ = blockNumber;
|
||||||
}
|
}
|
||||||
void cacheSetDirty() {cacheDirty_ |= CACHE_FOR_WRITE;}
|
void cacheSetDirty() {
|
||||||
bool chainSize(uint32_t beginCluster, uint32_t* size);
|
cacheDirty_ |= CACHE_FOR_WRITE;
|
||||||
bool fatGet(uint32_t cluster, uint32_t* value);
|
}
|
||||||
bool fatPut(uint32_t cluster, uint32_t value);
|
bool chainSize(uint32_t beginCluster, uint32_t* size);
|
||||||
bool fatPutEOC(uint32_t cluster) {
|
bool fatGet(uint32_t cluster, uint32_t* value);
|
||||||
return fatPut(cluster, 0x0FFFFFFF);
|
bool fatPut(uint32_t cluster, uint32_t value);
|
||||||
}
|
bool fatPutEOC(uint32_t cluster) {
|
||||||
bool freeChain(uint32_t cluster);
|
return fatPut(cluster, 0x0FFFFFFF);
|
||||||
bool isEOC(uint32_t cluster) const {
|
}
|
||||||
if (FAT12_SUPPORT && fatType_ == 12) return cluster >= FAT12EOC_MIN;
|
bool freeChain(uint32_t cluster);
|
||||||
if (fatType_ == 16) return cluster >= FAT16EOC_MIN;
|
bool isEOC(uint32_t cluster) const {
|
||||||
return cluster >= FAT32EOC_MIN;
|
if (FAT12_SUPPORT && fatType_ == 12) return cluster >= FAT12EOC_MIN;
|
||||||
}
|
if (fatType_ == 16) return cluster >= FAT16EOC_MIN;
|
||||||
bool readBlock(uint32_t block, uint8_t* dst) {
|
return cluster >= FAT32EOC_MIN;
|
||||||
return sdCard_->readBlock(block, dst);}
|
}
|
||||||
bool writeBlock(uint32_t block, const uint8_t* dst) {
|
bool readBlock(uint32_t block, uint8_t* dst) {
|
||||||
return sdCard_->writeBlock(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
|
// Deprecated functions - suppress cpplint warnings with NOLINT comment
|
||||||
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
|
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
|
||||||
public:
|
public:
|
||||||
/** \deprecated Use: bool SdVolume::init(Sd2Card* dev);
|
/** \deprecated Use: bool SdVolume::init(Sd2Card* dev);
|
||||||
* \param[in] dev The SD card where the volume is located.
|
* \param[in] dev The SD card where the volume is located.
|
||||||
* \return true for success or false for failure.
|
* \return true for success or false for failure.
|
||||||
*/
|
*/
|
||||||
bool init(Sd2Card& dev) {return init(&dev);} // NOLINT
|
bool init(Sd2Card& dev) {
|
||||||
/** \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol);
|
return init(&dev); // NOLINT
|
||||||
* \param[in] dev The SD card where the volume is located.
|
}
|
||||||
* \param[in] part The partition to be used.
|
/** \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol);
|
||||||
* \return true for success or false for failure.
|
* \param[in] dev The SD card where the volume is located.
|
||||||
*/
|
* \param[in] part The partition to be used.
|
||||||
bool init(Sd2Card& dev, uint8_t part) { // NOLINT
|
* \return true for success or false for failure.
|
||||||
return init(&dev, part);
|
*/
|
||||||
}
|
bool init(Sd2Card& dev, uint8_t part) { // NOLINT
|
||||||
|
return init(&dev, part);
|
||||||
|
}
|
||||||
#endif // ALLOW_DEPRECATED_FUNCTIONS
|
#endif // ALLOW_DEPRECATED_FUNCTIONS
|
||||||
};
|
};
|
||||||
#endif // SdVolume
|
#endif // SdVolume
|
||||||
|
|
|
||||||
|
|
@ -76,27 +76,27 @@ uint8_t ServoCount = 0; // the total number
|
||||||
|
|
||||||
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
|
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
|
||||||
{
|
{
|
||||||
if( Channel[timer] < 0 )
|
if( Channel[timer] < 0 )
|
||||||
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
|
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
|
||||||
else{
|
else {
|
||||||
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
|
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
|
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel[timer]++; // increment to the next channel
|
Channel[timer]++; // increment to the next channel
|
||||||
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
||||||
*OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
|
*OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
|
||||||
if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated
|
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
|
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// finished all channels so wait for the refresh period to expire before starting over
|
// 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
|
if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
|
||||||
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
|
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
|
||||||
else
|
else
|
||||||
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
|
*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
|
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
|
#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
|
||||||
|
|
@ -104,28 +104,28 @@ static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t
|
||||||
#if defined(_useTimer1)
|
#if defined(_useTimer1)
|
||||||
SIGNAL (TIMER1_COMPA_vect)
|
SIGNAL (TIMER1_COMPA_vect)
|
||||||
{
|
{
|
||||||
handle_interrupts(_timer1, &TCNT1, &OCR1A);
|
handle_interrupts(_timer1, &TCNT1, &OCR1A);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_useTimer3)
|
#if defined(_useTimer3)
|
||||||
SIGNAL (TIMER3_COMPA_vect)
|
SIGNAL (TIMER3_COMPA_vect)
|
||||||
{
|
{
|
||||||
handle_interrupts(_timer3, &TCNT3, &OCR3A);
|
handle_interrupts(_timer3, &TCNT3, &OCR3A);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_useTimer4)
|
#if defined(_useTimer4)
|
||||||
SIGNAL (TIMER4_COMPA_vect)
|
SIGNAL (TIMER4_COMPA_vect)
|
||||||
{
|
{
|
||||||
handle_interrupts(_timer4, &TCNT4, &OCR4A);
|
handle_interrupts(_timer4, &TCNT4, &OCR4A);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_useTimer5)
|
#if defined(_useTimer5)
|
||||||
SIGNAL (TIMER5_COMPA_vect)
|
SIGNAL (TIMER5_COMPA_vect)
|
||||||
{
|
{
|
||||||
handle_interrupts(_timer5, &TCNT5, &OCR5A);
|
handle_interrupts(_timer5, &TCNT5, &OCR5A);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -134,13 +134,13 @@ SIGNAL (TIMER5_COMPA_vect)
|
||||||
#if defined(_useTimer1)
|
#if defined(_useTimer1)
|
||||||
void Timer1Service()
|
void Timer1Service()
|
||||||
{
|
{
|
||||||
handle_interrupts(_timer1, &TCNT1, &OCR1A);
|
handle_interrupts(_timer1, &TCNT1, &OCR1A);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(_useTimer3)
|
#if defined(_useTimer3)
|
||||||
void Timer3Service()
|
void Timer3Service()
|
||||||
{
|
{
|
||||||
handle_interrupts(_timer3, &TCNT3, &OCR3A);
|
handle_interrupts(_timer3, &TCNT3, &OCR3A);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -149,60 +149,60 @@ void Timer3Service()
|
||||||
static void initISR(timer16_Sequence_t timer)
|
static void initISR(timer16_Sequence_t timer)
|
||||||
{
|
{
|
||||||
#if defined (_useTimer1)
|
#if defined (_useTimer1)
|
||||||
if(timer == _timer1) {
|
if(timer == _timer1) {
|
||||||
TCCR1A = 0; // normal counting mode
|
TCCR1A = 0; // normal counting mode
|
||||||
TCCR1B = _BV(CS11); // set prescaler of 8
|
TCCR1B = _BV(CS11); // set prescaler of 8
|
||||||
TCNT1 = 0; // clear the timer count
|
TCNT1 = 0; // clear the timer count
|
||||||
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
|
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
|
||||||
TIFR |= _BV(OCF1A); // clear any pending interrupts;
|
TIFR |= _BV(OCF1A); // clear any pending interrupts;
|
||||||
TIMSK |= _BV(OCIE1A) ; // enable the output compare interrupt
|
TIMSK |= _BV(OCIE1A) ; // enable the output compare interrupt
|
||||||
#else
|
#else
|
||||||
// here if not ATmega8 or ATmega128
|
// here if not ATmega8 or ATmega128
|
||||||
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
|
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
|
||||||
TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
|
TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
|
||||||
#endif
|
#endif
|
||||||
#if defined(WIRING)
|
#if defined(WIRING)
|
||||||
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (_useTimer3)
|
#if defined (_useTimer3)
|
||||||
if(timer == _timer3) {
|
if(timer == _timer3) {
|
||||||
TCCR3A = 0; // normal counting mode
|
TCCR3A = 0; // normal counting mode
|
||||||
TCCR3B = _BV(CS31); // set prescaler of 8
|
TCCR3B = _BV(CS31); // set prescaler of 8
|
||||||
TCNT3 = 0; // clear the timer count
|
TCNT3 = 0; // clear the timer count
|
||||||
#if defined(__AVR_ATmega128__)
|
#if defined(__AVR_ATmega128__)
|
||||||
TIFR |= _BV(OCF3A); // clear any pending interrupts;
|
TIFR |= _BV(OCF3A); // clear any pending interrupts;
|
||||||
ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt
|
ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt
|
||||||
#else
|
#else
|
||||||
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
|
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
|
||||||
TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt
|
TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt
|
||||||
#endif
|
#endif
|
||||||
#if defined(WIRING)
|
#if defined(WIRING)
|
||||||
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (_useTimer4)
|
#if defined (_useTimer4)
|
||||||
if(timer == _timer4) {
|
if(timer == _timer4) {
|
||||||
TCCR4A = 0; // normal counting mode
|
TCCR4A = 0; // normal counting mode
|
||||||
TCCR4B = _BV(CS41); // set prescaler of 8
|
TCCR4B = _BV(CS41); // set prescaler of 8
|
||||||
TCNT4 = 0; // clear the timer count
|
TCNT4 = 0; // clear the timer count
|
||||||
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
||||||
TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt
|
TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (_useTimer5)
|
#if defined (_useTimer5)
|
||||||
if(timer == _timer5) {
|
if(timer == _timer5) {
|
||||||
TCCR5A = 0; // normal counting mode
|
TCCR5A = 0; // normal counting mode
|
||||||
TCCR5B = _BV(CS51); // set prescaler of 8
|
TCCR5B = _BV(CS51); // set prescaler of 8
|
||||||
TCNT5 = 0; // clear the timer count
|
TCNT5 = 0; // clear the timer count
|
||||||
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
||||||
TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt
|
TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,22 +210,22 @@ static void finISR(timer16_Sequence_t timer)
|
||||||
{
|
{
|
||||||
//disable use of the given timer
|
//disable use of the given timer
|
||||||
#if defined WIRING // Wiring
|
#if defined WIRING // Wiring
|
||||||
if(timer == _timer1) {
|
if(timer == _timer1) {
|
||||||
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
||||||
TIMSK1 &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
|
TIMSK1 &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
|
||||||
#else
|
#else
|
||||||
TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
|
TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
|
||||||
#endif
|
#endif
|
||||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
timerDetach(TIMER1OUTCOMPAREA_INT);
|
||||||
}
|
}
|
||||||
else if(timer == _timer3) {
|
else if(timer == _timer3) {
|
||||||
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
||||||
TIMSK3 &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
|
TIMSK3 &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
|
||||||
#else
|
#else
|
||||||
ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
|
ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
|
||||||
#endif
|
#endif
|
||||||
timerDetach(TIMER3OUTCOMPAREA_INT);
|
timerDetach(TIMER3OUTCOMPAREA_INT);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//For arduino - in future: call here to a currently undefined function to reset the timer
|
//For arduino - in future: call here to a currently undefined function to reset the timer
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -233,12 +233,12 @@ static void finISR(timer16_Sequence_t timer)
|
||||||
|
|
||||||
static boolean isTimerActive(timer16_Sequence_t timer)
|
static boolean isTimerActive(timer16_Sequence_t timer)
|
||||||
{
|
{
|
||||||
// returns true if any servo is active on this timer
|
// returns true if any servo is active on this timer
|
||||||
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
|
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
|
||||||
if(SERVO(timer,channel).Pin.isActive == true)
|
if(SERVO(timer,channel).Pin.isActive == true)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -246,99 +246,100 @@ static boolean isTimerActive(timer16_Sequence_t timer)
|
||||||
|
|
||||||
Servo::Servo()
|
Servo::Servo()
|
||||||
{
|
{
|
||||||
if( ServoCount < MAX_SERVOS) {
|
if( ServoCount < MAX_SERVOS) {
|
||||||
this->servoIndex = ServoCount++; // assign a servo index to this instance
|
this->servoIndex = ServoCount++; // assign a servo index to this instance
|
||||||
servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
|
servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this->servoIndex = INVALID_SERVO ; // too many servos
|
this->servoIndex = INVALID_SERVO ; // too many servos
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Servo::attach(int pin)
|
uint8_t Servo::attach(int pin)
|
||||||
{
|
{
|
||||||
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
|
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Servo::attach(int pin, int min, int max)
|
uint8_t Servo::attach(int pin, int min, int max)
|
||||||
{
|
{
|
||||||
if(this->servoIndex < MAX_SERVOS ) {
|
if(this->servoIndex < MAX_SERVOS ) {
|
||||||
#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
||||||
if (pin > 0) this->pin = pin; else pin = this->pin;
|
if (pin > 0) this->pin = pin;
|
||||||
|
else pin = this->pin;
|
||||||
#endif
|
#endif
|
||||||
pinMode( pin, OUTPUT) ; // set servo pin to output
|
pinMode( pin, OUTPUT) ; // set servo pin to output
|
||||||
servos[this->servoIndex].Pin.nbr = pin;
|
servos[this->servoIndex].Pin.nbr = pin;
|
||||||
// todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
|
// 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->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
|
||||||
this->max = (MAX_PULSE_WIDTH - max)/4;
|
this->max = (MAX_PULSE_WIDTH - max)/4;
|
||||||
// initialize the timer if it has not already been initialized
|
// initialize the timer if it has not already been initialized
|
||||||
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
||||||
if(isTimerActive(timer) == false)
|
if(isTimerActive(timer) == false)
|
||||||
initISR(timer);
|
initISR(timer);
|
||||||
servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
|
servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
|
||||||
}
|
}
|
||||||
return this->servoIndex ;
|
return this->servoIndex ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servo::detach()
|
void Servo::detach()
|
||||||
{
|
{
|
||||||
servos[this->servoIndex].Pin.isActive = false;
|
servos[this->servoIndex].Pin.isActive = false;
|
||||||
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
||||||
if(isTimerActive(timer) == false) {
|
if(isTimerActive(timer) == false) {
|
||||||
finISR(timer);
|
finISR(timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servo::write(int value)
|
void Servo::write(int value)
|
||||||
{
|
{
|
||||||
if(value < MIN_PULSE_WIDTH)
|
if(value < MIN_PULSE_WIDTH)
|
||||||
{ // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
|
{ // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
|
||||||
if(value < 0) value = 0;
|
if(value < 0) value = 0;
|
||||||
if(value > 180) value = 180;
|
if(value > 180) value = 180;
|
||||||
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
|
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
|
||||||
}
|
}
|
||||||
this->writeMicroseconds(value);
|
this->writeMicroseconds(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servo::writeMicroseconds(int value)
|
void Servo::writeMicroseconds(int value)
|
||||||
{
|
{
|
||||||
// calculate and store the values for the given channel
|
// calculate and store the values for the given channel
|
||||||
byte channel = this->servoIndex;
|
byte channel = this->servoIndex;
|
||||||
if( (channel < MAX_SERVOS) ) // ensure channel is valid
|
if( (channel < MAX_SERVOS) ) // ensure channel is valid
|
||||||
{
|
{
|
||||||
if( value < SERVO_MIN() ) // ensure pulse width is valid
|
if( value < SERVO_MIN() ) // ensure pulse width is valid
|
||||||
value = SERVO_MIN();
|
value = SERVO_MIN();
|
||||||
else if( value > SERVO_MAX() )
|
else if( value > SERVO_MAX() )
|
||||||
value = SERVO_MAX();
|
value = SERVO_MAX();
|
||||||
|
|
||||||
value = value - TRIM_DURATION;
|
value = value - TRIM_DURATION;
|
||||||
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
|
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
|
||||||
|
|
||||||
uint8_t oldSREG = SREG;
|
uint8_t oldSREG = SREG;
|
||||||
cli();
|
cli();
|
||||||
servos[channel].ticks = value;
|
servos[channel].ticks = value;
|
||||||
SREG = oldSREG;
|
SREG = oldSREG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Servo::read() // return the value as degrees
|
int Servo::read() // return the value as degrees
|
||||||
{
|
{
|
||||||
return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
|
return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Servo::readMicroseconds()
|
int Servo::readMicroseconds()
|
||||||
{
|
{
|
||||||
unsigned int pulsewidth;
|
unsigned int pulsewidth;
|
||||||
if( this->servoIndex != INVALID_SERVO )
|
if( this->servoIndex != INVALID_SERVO )
|
||||||
pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009
|
pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009
|
||||||
else
|
else
|
||||||
pulsewidth = 0;
|
pulsewidth = 0;
|
||||||
|
|
||||||
return pulsewidth;
|
return pulsewidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Servo::attached()
|
bool Servo::attached()
|
||||||
{
|
{
|
||||||
return servos[this->servoIndex].Pin.isActive ;
|
return servos[this->servoIndex].Pin.isActive ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -102,34 +102,34 @@ typedef enum { _Nbr_16timers } timer16_Sequence_t ;
|
||||||
#define INVALID_SERVO 255 // flag indicating an invalid servo index
|
#define INVALID_SERVO 255 // flag indicating an invalid servo index
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t nbr :6 ; // a pin number from 0 to 63
|
uint8_t nbr :6 ; // a pin number from 0 to 63
|
||||||
uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
|
uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
|
||||||
} ServoPin_t ;
|
} ServoPin_t ;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ServoPin_t Pin;
|
ServoPin_t Pin;
|
||||||
unsigned int ticks;
|
unsigned int ticks;
|
||||||
} servo_t;
|
} servo_t;
|
||||||
|
|
||||||
class Servo
|
class Servo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Servo();
|
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); // 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.
|
uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
|
||||||
void detach();
|
void detach();
|
||||||
void write(int value); // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
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 writeMicroseconds(int value); // Write pulse width in microseconds
|
||||||
int read(); // returns current pulse width as an angle between 0 and 180 degrees
|
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)
|
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
|
bool attached(); // return true if this servo is attached, otherwise false
|
||||||
#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
||||||
int pin; // store the hardware pin of the servo
|
int pin; // store the hardware pin of the servo
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
uint8_t servoIndex; // index into the channel data for this servo
|
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 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
|
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,17 @@ class Timer
|
||||||
public:
|
public:
|
||||||
Timer();
|
Timer();
|
||||||
void start();
|
void start();
|
||||||
void stop(){m_isRunning = false;}
|
void stop() {
|
||||||
bool running(){return m_isRunning;}
|
m_isRunning = false;
|
||||||
|
}
|
||||||
|
bool running() {
|
||||||
|
return m_isRunning;
|
||||||
|
}
|
||||||
bool expired(T msPeriod);
|
bool expired(T msPeriod);
|
||||||
protected:
|
protected:
|
||||||
T started(){return m_started;}
|
T started() {
|
||||||
|
return m_started;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
bool m_isRunning;
|
bool m_isRunning;
|
||||||
T m_started;
|
T m_started;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
class TimerRemaining : public LongTimer
|
class TimerRemaining : public LongTimer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimerRemaining() : m_period(){}
|
TimerRemaining() : m_period() {}
|
||||||
void start() = delete;
|
void start() = delete;
|
||||||
bool expired(unsigned long msPeriod) = delete;
|
bool expired(unsigned long msPeriod) = delete;
|
||||||
/**
|
/**
|
||||||
|
|
@ -34,10 +34,10 @@ public:
|
||||||
*/
|
*/
|
||||||
unsigned long remaining()
|
unsigned long remaining()
|
||||||
{
|
{
|
||||||
if (!running()) return 0;
|
if (!running()) return 0;
|
||||||
if (expired()) return 0;
|
if (expired()) return 0;
|
||||||
const unsigned long now = millis();
|
const unsigned long now = millis();
|
||||||
return (started() + m_period - now);
|
return (started() + m_period - now);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Timer has expired.
|
* @brief Timer has expired.
|
||||||
|
|
|
||||||
101
Firmware/adc.c
101
Firmware/adc.c
|
|
@ -12,21 +12,21 @@ uint16_t adc_sim_mask;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ADC_CALLBACK
|
#ifdef ADC_CALLBACK
|
||||||
extern void ADC_CALLBACK(void);
|
extern void ADC_CALLBACK(void);
|
||||||
#endif //ADC_CALLBACK
|
#endif //ADC_CALLBACK
|
||||||
|
|
||||||
|
|
||||||
void adc_init(void)
|
void adc_init(void)
|
||||||
{
|
{
|
||||||
printf_P(PSTR("adc_init\n"));
|
printf_P(PSTR("adc_init\n"));
|
||||||
adc_sim_mask = 0x00;
|
adc_sim_mask = 0x00;
|
||||||
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
|
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
|
||||||
ADMUX |= (1 << REFS0);
|
ADMUX |= (1 << REFS0);
|
||||||
ADCSRA |= (1 << ADEN);
|
ADCSRA |= (1 << ADEN);
|
||||||
// ADCSRA |= (1 << ADIF) | (1 << ADSC);
|
// ADCSRA |= (1 << ADIF) | (1 << ADSC);
|
||||||
DIDR0 = (ADC_CHAN_MSK & 0xff);
|
DIDR0 = (ADC_CHAN_MSK & 0xff);
|
||||||
DIDR2 = (ADC_CHAN_MSK >> 8);
|
DIDR2 = (ADC_CHAN_MSK >> 8);
|
||||||
adc_reset();
|
adc_reset();
|
||||||
// adc_sim_mask = 0b0101;
|
// adc_sim_mask = 0b0101;
|
||||||
// adc_sim_mask = 0b100101;
|
// adc_sim_mask = 0b100101;
|
||||||
// adc_values[0] = 1023 * 16;
|
// adc_values[0] = 1023 * 16;
|
||||||
|
|
@ -36,59 +36,60 @@ void adc_init(void)
|
||||||
|
|
||||||
void adc_reset(void)
|
void adc_reset(void)
|
||||||
{
|
{
|
||||||
adc_state = 0;
|
adc_state = 0;
|
||||||
adc_count = 0;
|
adc_count = 0;
|
||||||
uint8_t i; for (i = 0; i < ADC_CHAN_CNT; i++)
|
uint8_t i;
|
||||||
if ((adc_sim_mask & (1 << i)) == 0)
|
for (i = 0; i < ADC_CHAN_CNT; i++)
|
||||||
adc_values[i] = 0;
|
if ((adc_sim_mask & (1 << i)) == 0)
|
||||||
|
adc_values[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_setmux(uint8_t ch)
|
void adc_setmux(uint8_t ch)
|
||||||
{
|
{
|
||||||
ch &= 0x0f;
|
ch &= 0x0f;
|
||||||
if (ch & 0x08) ADCSRB |= (1 << MUX5);
|
if (ch & 0x08) ADCSRB |= (1 << MUX5);
|
||||||
else ADCSRB &= ~(1 << MUX5);
|
else ADCSRB &= ~(1 << MUX5);
|
||||||
ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07);
|
ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t adc_chan(uint8_t index)
|
uint8_t adc_chan(uint8_t index)
|
||||||
{
|
{
|
||||||
uint8_t chan = 0;
|
uint8_t chan = 0;
|
||||||
uint16_t mask = 1;
|
uint16_t mask = 1;
|
||||||
while (mask)
|
while (mask)
|
||||||
{
|
{
|
||||||
if ((mask & ADC_CHAN_MSK) && (index-- == 0)) break;
|
if ((mask & ADC_CHAN_MSK) && (index-- == 0)) break;
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
chan++;
|
chan++;
|
||||||
}
|
}
|
||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_cycle(void)
|
void adc_cycle(void)
|
||||||
{
|
{
|
||||||
if (adc_state & 0x80)
|
if (adc_state & 0x80)
|
||||||
{
|
{
|
||||||
uint8_t index = adc_state & 0x0f;
|
uint8_t index = adc_state & 0x0f;
|
||||||
if ((adc_sim_mask & (1 << index)) == 0)
|
if ((adc_sim_mask & (1 << index)) == 0)
|
||||||
adc_values[index] += ADC;
|
adc_values[index] += ADC;
|
||||||
if (++index >= ADC_CHAN_CNT)
|
if (++index >= ADC_CHAN_CNT)
|
||||||
{
|
{
|
||||||
index = 0;
|
index = 0;
|
||||||
adc_count++;
|
adc_count++;
|
||||||
if (adc_count >= ADC_OVRSAMPL)
|
if (adc_count >= ADC_OVRSAMPL)
|
||||||
{
|
{
|
||||||
#ifdef ADC_CALLBACK
|
#ifdef ADC_CALLBACK
|
||||||
ADC_CALLBACK();
|
ADC_CALLBACK();
|
||||||
#endif //ADC_CALLBACK
|
#endif //ADC_CALLBACK
|
||||||
adc_reset();
|
adc_reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adc_setmux(adc_chan(index));
|
adc_setmux(adc_chan(index));
|
||||||
adc_state = index;
|
adc_state = index;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ADCSRA |= (1 << ADSC); //start conversion
|
ADCSRA |= (1 << ADSC); //start conversion
|
||||||
adc_state |= 0x80;
|
adc_state |= 0x80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,45 +11,45 @@ extern FILE _uartout;
|
||||||
|
|
||||||
void bootapp_print_vars(void)
|
void bootapp_print_vars(void)
|
||||||
{
|
{
|
||||||
fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr);
|
fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr);
|
||||||
fprintf_P(uartout, PSTR("boot_dst_addr =0x%08lx\n"), boot_dst_addr);
|
fprintf_P(uartout, PSTR("boot_dst_addr =0x%08lx\n"), boot_dst_addr);
|
||||||
fprintf_P(uartout, PSTR("boot_copy_size =0x%04x\n"), boot_copy_size);
|
fprintf_P(uartout, PSTR("boot_copy_size =0x%04x\n"), boot_copy_size);
|
||||||
fprintf_P(uartout, PSTR("boot_reserved =0x%02x\n"), boot_reserved);
|
fprintf_P(uartout, PSTR("boot_reserved =0x%02x\n"), boot_reserved);
|
||||||
fprintf_P(uartout, PSTR("boot_app_flags =0x%02x\n"), boot_app_flags);
|
fprintf_P(uartout, PSTR("boot_app_flags =0x%02x\n"), boot_app_flags);
|
||||||
fprintf_P(uartout, PSTR("boot_app_magic =0x%08lx\n"), boot_app_magic);
|
fprintf_P(uartout, PSTR("boot_app_magic =0x%08lx\n"), boot_app_magic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
|
void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
|
||||||
{
|
{
|
||||||
cli();
|
cli();
|
||||||
boot_app_magic = BOOT_APP_MAGIC;
|
boot_app_magic = BOOT_APP_MAGIC;
|
||||||
boot_app_flags |= BOOT_APP_FLG_COPY;
|
boot_app_flags |= BOOT_APP_FLG_COPY;
|
||||||
boot_app_flags |= BOOT_APP_FLG_ERASE;
|
boot_app_flags |= BOOT_APP_FLG_ERASE;
|
||||||
/* uint16_t ui; for (ui = 0; ui < size; ui++)
|
/* uint16_t ui; for (ui = 0; ui < size; ui++)
|
||||||
{
|
{
|
||||||
uint8_t uc = ram_array[ui+rptr];
|
uint8_t uc = ram_array[ui+rptr];
|
||||||
if (pgm_read_byte(ui+fptr) & uc != uc)
|
if (pgm_read_byte(ui+fptr) & uc != uc)
|
||||||
{
|
{
|
||||||
boot_app_flags |= BOOT_APP_FLG_ERASE;
|
boot_app_flags |= BOOT_APP_FLG_ERASE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
boot_copy_size = (uint16_t)size;
|
boot_copy_size = (uint16_t)size;
|
||||||
boot_src_addr = (uint32_t)rptr;
|
boot_src_addr = (uint32_t)rptr;
|
||||||
boot_dst_addr = (uint32_t)fptr;
|
boot_dst_addr = (uint32_t)fptr;
|
||||||
bootapp_print_vars();
|
bootapp_print_vars();
|
||||||
wdt_enable(WDTO_15MS);
|
wdt_enable(WDTO_15MS);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bootapp_reboot_user0(uint8_t reserved)
|
void bootapp_reboot_user0(uint8_t reserved)
|
||||||
{
|
{
|
||||||
cli();
|
cli();
|
||||||
boot_app_magic = BOOT_APP_MAGIC;
|
boot_app_magic = BOOT_APP_MAGIC;
|
||||||
boot_app_flags = BOOT_APP_FLG_USER0;
|
boot_app_flags = BOOT_APP_FLG_USER0;
|
||||||
boot_reserved = reserved;
|
boot_reserved = reserved;
|
||||||
bootapp_print_vars();
|
bootapp_print_vars();
|
||||||
wdt_enable(WDTO_15MS);
|
wdt_enable(WDTO_15MS);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -10,155 +10,185 @@ enum LsAction {LS_SerialPrint,LS_Count,LS_GetFilename};
|
||||||
class CardReader
|
class CardReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CardReader();
|
CardReader();
|
||||||
|
|
||||||
void initsd();
|
void initsd();
|
||||||
void write_command(char *buf);
|
void write_command(char *buf);
|
||||||
void write_command_no_newline(char *buf);
|
void write_command_no_newline(char *buf);
|
||||||
//files auto[0-9].g on the sd card are performed in a row
|
//files auto[0-9].g on the sd card are performed in a row
|
||||||
//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
|
//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
|
||||||
|
|
||||||
void checkautostart(bool x);
|
void checkautostart(bool x);
|
||||||
void openFile(const char* name,bool read,bool replace_current=true);
|
void openFile(const char* name,bool read,bool replace_current=true);
|
||||||
void openLogFile(const char* name);
|
void openLogFile(const char* name);
|
||||||
void removeFile(const char* name);
|
void removeFile(const char* name);
|
||||||
void closefile(bool store_location=false);
|
void closefile(bool store_location=false);
|
||||||
void release();
|
void release();
|
||||||
void startFileprint();
|
void startFileprint();
|
||||||
void pauseSDPrint();
|
void pauseSDPrint();
|
||||||
uint32_t getFileSize();
|
uint32_t getFileSize();
|
||||||
void getStatus();
|
void getStatus();
|
||||||
void printingHasFinished();
|
void printingHasFinished();
|
||||||
|
|
||||||
void getfilename(uint16_t nr, const char* const match=NULL);
|
void getfilename(uint16_t nr, const char* const match=NULL);
|
||||||
void getfilename_simple(uint32_t position, const char * const match = NULL);
|
void getfilename_simple(uint32_t position, const char * const match = NULL);
|
||||||
uint16_t getnrfilenames();
|
uint16_t getnrfilenames();
|
||||||
|
|
||||||
void getAbsFilename(char *t);
|
void getAbsFilename(char *t);
|
||||||
void getDirName(char* name, uint8_t level);
|
void getDirName(char* name, uint8_t level);
|
||||||
uint16_t getWorkDirDepth();
|
uint16_t getWorkDirDepth();
|
||||||
|
|
||||||
|
|
||||||
void ls();
|
void ls();
|
||||||
void chdir(const char * relpath);
|
void chdir(const char * relpath);
|
||||||
void updir();
|
void updir();
|
||||||
void setroot();
|
void setroot();
|
||||||
|
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
void presort();
|
void presort();
|
||||||
#ifdef SDSORT_QUICKSORT
|
#ifdef SDSORT_QUICKSORT
|
||||||
void swap(uint8_t left, uint8_t right);
|
void swap(uint8_t left, uint8_t right);
|
||||||
void quicksort(uint8_t left, uint8_t right);
|
void quicksort(uint8_t left, uint8_t right);
|
||||||
#endif //SDSORT_QUICKSORT
|
#endif //SDSORT_QUICKSORT
|
||||||
void getfilename_sorted(const uint16_t nr);
|
void getfilename_sorted(const uint16_t nr);
|
||||||
#if SDSORT_GCODE
|
#if SDSORT_GCODE
|
||||||
FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }
|
FORCE_INLINE void setSortOn(bool b) {
|
||||||
FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); }
|
sort_alpha = b;
|
||||||
//FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
|
presort();
|
||||||
#endif
|
}
|
||||||
#endif
|
FORCE_INLINE void setSortFolders(int i) {
|
||||||
|
sort_folders = i;
|
||||||
|
presort();
|
||||||
|
}
|
||||||
|
//FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
|
FORCE_INLINE bool isFileOpen() {
|
||||||
FORCE_INLINE bool eof() { return sdpos>=filesize ;};
|
return file.isOpen();
|
||||||
FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();};
|
}
|
||||||
FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);};
|
FORCE_INLINE bool eof() {
|
||||||
FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;};
|
return sdpos>=filesize ;
|
||||||
FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;};
|
};
|
||||||
FORCE_INLINE uint32_t get_sdpos() { if (!isFileOpen()) return 0; else return(sdpos); };
|
FORCE_INLINE int16_t get() {
|
||||||
|
sdpos = file.curPosition();
|
||||||
|
return (int16_t)file.read();
|
||||||
|
};
|
||||||
|
FORCE_INLINE void setIndex(long index) {
|
||||||
|
sdpos = index;
|
||||||
|
file.seekSet(index);
|
||||||
|
};
|
||||||
|
FORCE_INLINE uint8_t percentDone() {
|
||||||
|
if(!isFileOpen()) return 0;
|
||||||
|
if(filesize) return sdpos/((filesize+99)/100);
|
||||||
|
else return 0;
|
||||||
|
};
|
||||||
|
FORCE_INLINE char* getWorkDirName() {
|
||||||
|
workDir.getFilename(filename);
|
||||||
|
return filename;
|
||||||
|
};
|
||||||
|
FORCE_INLINE uint32_t get_sdpos() {
|
||||||
|
if (!isFileOpen()) return 0;
|
||||||
|
else return(sdpos);
|
||||||
|
};
|
||||||
|
|
||||||
bool ToshibaFlashAir_isEnabled() const { return card.getFlashAirCompatible(); }
|
bool ToshibaFlashAir_isEnabled() const {
|
||||||
void ToshibaFlashAir_enable(bool enable) { card.setFlashAirCompatible(enable); }
|
return card.getFlashAirCompatible();
|
||||||
bool ToshibaFlashAir_GetIP(uint8_t *ip);
|
}
|
||||||
|
void ToshibaFlashAir_enable(bool enable) {
|
||||||
|
card.setFlashAirCompatible(enable);
|
||||||
|
}
|
||||||
|
bool ToshibaFlashAir_GetIP(uint8_t *ip);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool saving;
|
bool saving;
|
||||||
bool logging;
|
bool logging;
|
||||||
bool sdprinting ;
|
bool sdprinting ;
|
||||||
bool cardOK ;
|
bool cardOK ;
|
||||||
bool paused ;
|
bool paused ;
|
||||||
char filename[13];
|
char filename[13];
|
||||||
uint16_t creationTime, creationDate;
|
uint16_t creationTime, creationDate;
|
||||||
uint32_t cluster, position;
|
uint32_t cluster, position;
|
||||||
char longFilename[LONG_FILENAME_LENGTH];
|
char longFilename[LONG_FILENAME_LENGTH];
|
||||||
bool filenameIsDir;
|
bool filenameIsDir;
|
||||||
int lastnr; //last number of the autostart;
|
int lastnr; //last number of the autostart;
|
||||||
private:
|
private:
|
||||||
SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH];
|
SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH];
|
||||||
uint16_t workDirDepth;
|
uint16_t workDirDepth;
|
||||||
|
|
||||||
// Sort files and folders alphabetically.
|
// Sort files and folders alphabetically.
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
uint16_t sort_count; // Count of sorted items in the current directory
|
uint16_t sort_count; // Count of sorted items in the current directory
|
||||||
#if SDSORT_GCODE
|
#if SDSORT_GCODE
|
||||||
bool sort_alpha; // Flag to enable / disable the feature
|
bool sort_alpha; // Flag to enable / disable the feature
|
||||||
int sort_folders; // Flag to enable / disable folder sorting
|
int sort_folders; // Flag to enable / disable folder sorting
|
||||||
//bool sort_reverse; // Flag to enable / disable reverse sorting
|
//bool sort_reverse; // Flag to enable / disable reverse sorting
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// By default the sort index is static
|
// By default the sort index is static
|
||||||
#if SDSORT_DYNAMIC_RAM
|
#if SDSORT_DYNAMIC_RAM
|
||||||
uint8_t *sort_order;
|
uint8_t *sort_order;
|
||||||
#else
|
#else
|
||||||
uint8_t sort_order[SDSORT_LIMIT];
|
uint8_t sort_order[SDSORT_LIMIT];
|
||||||
#endif
|
#endif
|
||||||
// Cache filenames to speed up SD menus.
|
// Cache filenames to speed up SD menus.
|
||||||
#if SDSORT_USES_RAM
|
#if SDSORT_USES_RAM
|
||||||
|
|
||||||
// If using dynamic ram for names, allocate on the heap.
|
// If using dynamic ram for names, allocate on the heap.
|
||||||
#if SDSORT_CACHE_NAMES
|
#if SDSORT_CACHE_NAMES
|
||||||
#if SDSORT_DYNAMIC_RAM
|
#if SDSORT_DYNAMIC_RAM
|
||||||
char **sortshort, **sortnames;
|
char **sortshort, **sortnames;
|
||||||
#else
|
#else
|
||||||
char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
|
char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
|
||||||
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
||||||
#endif
|
#endif
|
||||||
#elif !SDSORT_USES_STACK
|
#elif !SDSORT_USES_STACK
|
||||||
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
||||||
uint16_t creation_time[SDSORT_LIMIT];
|
uint16_t creation_time[SDSORT_LIMIT];
|
||||||
uint16_t creation_date[SDSORT_LIMIT];
|
uint16_t creation_date[SDSORT_LIMIT];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Folder sorting uses an isDir array when caching items.
|
// Folder sorting uses an isDir array when caching items.
|
||||||
#if HAS_FOLDER_SORTING
|
#if HAS_FOLDER_SORTING
|
||||||
#if SDSORT_DYNAMIC_RAM
|
#if SDSORT_DYNAMIC_RAM
|
||||||
uint8_t *isDir;
|
uint8_t *isDir;
|
||||||
#elif (SDSORT_CACHE_NAMES) || !(SDSORT_USES_STACK)
|
#elif (SDSORT_CACHE_NAMES) || !(SDSORT_USES_STACK)
|
||||||
uint8_t isDir[(SDSORT_LIMIT + 7) >> 3];
|
uint8_t isDir[(SDSORT_LIMIT + 7) >> 3];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SDSORT_USES_RAM
|
#endif // SDSORT_USES_RAM
|
||||||
|
|
||||||
#endif // SDCARD_SORT_ALPHA
|
#endif // SDCARD_SORT_ALPHA
|
||||||
|
|
||||||
#ifdef DEBUG_SD_SPEED_TEST
|
#ifdef DEBUG_SD_SPEED_TEST
|
||||||
public:
|
public:
|
||||||
#endif //DEBUG_SD_SPEED_TEST
|
#endif //DEBUG_SD_SPEED_TEST
|
||||||
Sd2Card card;
|
Sd2Card card;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SdVolume volume;
|
SdVolume volume;
|
||||||
SdFile file;
|
SdFile file;
|
||||||
#define SD_PROCEDURE_DEPTH 1
|
#define SD_PROCEDURE_DEPTH 1
|
||||||
#define MAXPATHNAMELENGTH (13*MAX_DIR_DEPTH+MAX_DIR_DEPTH+1)
|
#define MAXPATHNAMELENGTH (13*MAX_DIR_DEPTH+MAX_DIR_DEPTH+1)
|
||||||
uint8_t file_subcall_ctr;
|
uint8_t file_subcall_ctr;
|
||||||
uint32_t filespos[SD_PROCEDURE_DEPTH];
|
uint32_t filespos[SD_PROCEDURE_DEPTH];
|
||||||
char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
||||||
uint32_t filesize;
|
uint32_t filesize;
|
||||||
//int16_t n;
|
//int16_t n;
|
||||||
unsigned long autostart_atmillis;
|
unsigned long autostart_atmillis;
|
||||||
uint32_t sdpos ;
|
uint32_t sdpos ;
|
||||||
|
|
||||||
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
|
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
|
||||||
|
|
||||||
LsAction lsAction; //stored for recursion.
|
LsAction lsAction; //stored for recursion.
|
||||||
int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
|
int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
|
||||||
char* diveDirName;
|
char* diveDirName;
|
||||||
|
|
||||||
void diveSubfolder (const char *fileName, SdFile& dir);
|
void diveSubfolder (const char *fileName, SdFile& dir);
|
||||||
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL);
|
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL);
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
void flush_presort();
|
void flush_presort();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
extern CardReader card;
|
extern CardReader card;
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ void enquecommand(const char *cmd, bool from_progmem)
|
||||||
|
|
||||||
bool cmd_buffer_empty()
|
bool cmd_buffer_empty()
|
||||||
{
|
{
|
||||||
return (buflen == 0);
|
return (buflen == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enquecommand_front(const char *cmd, bool from_progmem)
|
void enquecommand_front(const char *cmd, bool from_progmem)
|
||||||
|
|
@ -361,172 +361,172 @@ bool is_buffer_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc_commands() {
|
void proc_commands() {
|
||||||
if (buflen)
|
if (buflen)
|
||||||
{
|
{
|
||||||
process_commands();
|
process_commands();
|
||||||
if (!cmdbuffer_front_already_processed)
|
if (!cmdbuffer_front_already_processed)
|
||||||
cmdqueue_pop_front();
|
cmdqueue_pop_front();
|
||||||
cmdbuffer_front_already_processed = false;
|
cmdbuffer_front_already_processed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_command()
|
void get_command()
|
||||||
{
|
{
|
||||||
// Test and reserve space for the new command string.
|
// Test and reserve space for the new command string.
|
||||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE - 1, true))
|
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE - 1, true))
|
||||||
return;
|
|
||||||
|
|
||||||
if (MYSERIAL.available() == RX_BUFFER_SIZE - 1) { //compare number of chars buffered in rx buffer with rx buffer size
|
|
||||||
MYSERIAL.flush();
|
|
||||||
SERIAL_ECHOLNPGM("Full RX Buffer"); //if buffer was full, there is danger that reading of last gcode will not be completed
|
|
||||||
}
|
|
||||||
|
|
||||||
// start of serial line processing loop
|
|
||||||
while (MYSERIAL.available() > 0 && !saved_printing) { //is print is saved (crash detection or filament detection), dont process data from serial line
|
|
||||||
|
|
||||||
char serial_char = MYSERIAL.read();
|
|
||||||
/* if (selectedSerialPort == 1)
|
|
||||||
{
|
|
||||||
selectedSerialPort = 0;
|
|
||||||
MYSERIAL.write(serial_char); // for debuging serial line 2 in farm_mode
|
|
||||||
selectedSerialPort = 1;
|
|
||||||
} */ //RP - removed
|
|
||||||
TimeSent = millis();
|
|
||||||
TimeNow = millis();
|
|
||||||
|
|
||||||
if (serial_char < 0)
|
|
||||||
// Ignore extended ASCII characters. These characters have no meaning in the G-code apart from the file names
|
|
||||||
// and Marlin does not support such file names anyway.
|
|
||||||
// Serial characters with a highest bit set to 1 are generated when the USB cable is unplugged, leading
|
|
||||||
// to a hang-up of the print process from an SD card.
|
|
||||||
continue;
|
|
||||||
if(serial_char == '\n' ||
|
|
||||||
serial_char == '\r' ||
|
|
||||||
serial_count >= (MAX_CMD_SIZE - 1) )
|
|
||||||
{
|
|
||||||
if(!serial_count) { //if empty line
|
|
||||||
comment_mode = false; //for new command
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
|
||||||
if(!comment_mode){
|
|
||||||
|
|
||||||
gcode_N = 0;
|
if (MYSERIAL.available() == RX_BUFFER_SIZE - 1) { //compare number of chars buffered in rx buffer with rx buffer size
|
||||||
|
MYSERIAL.flush();
|
||||||
// Line numbers must be first in buffer
|
SERIAL_ECHOLNPGM("Full RX Buffer"); //if buffer was full, there is danger that reading of last gcode will not be completed
|
||||||
|
|
||||||
if ((strstr(cmdbuffer+bufindw+CMDHDRSIZE, "PRUSA") == NULL) &&
|
|
||||||
(cmdbuffer[bufindw+CMDHDRSIZE] == 'N')) {
|
|
||||||
|
|
||||||
// Line number met. When sending a G-code over a serial line, each line may be stamped with its index,
|
|
||||||
// and Marlin tests, whether the successive lines are stamped with an increasing line number ID
|
|
||||||
gcode_N = (strtol(cmdbuffer+bufindw+CMDHDRSIZE+1, NULL, 10));
|
|
||||||
if(gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer+bufindw+CMDHDRSIZE, PSTR("M110")) == NULL) ) {
|
|
||||||
// M110 - set current line number.
|
|
||||||
// Line numbers not sent in succession.
|
|
||||||
SERIAL_ERROR_START;
|
|
||||||
SERIAL_ERRORRPGM(_n("Line Number is not Last Line Number+1, Last Line: "));////MSG_ERR_LINE_NO c=0 r=0
|
|
||||||
SERIAL_ERRORLN(gcode_LastN);
|
|
||||||
//Serial.println(gcode_N);
|
|
||||||
FlushSerialRequestResend();
|
|
||||||
serial_count = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*')) != NULL)
|
|
||||||
{
|
|
||||||
byte checksum = 0;
|
|
||||||
char *p = cmdbuffer+bufindw+CMDHDRSIZE;
|
|
||||||
while (p != strchr_pointer)
|
|
||||||
checksum = checksum^(*p++);
|
|
||||||
if (int(strtol(strchr_pointer+1, NULL, 10)) != int(checksum)) {
|
|
||||||
SERIAL_ERROR_START;
|
|
||||||
SERIAL_ERRORRPGM(_i("checksum mismatch, Last Line: "));////MSG_ERR_CHECKSUM_MISMATCH c=0 r=0
|
|
||||||
SERIAL_ERRORLN(gcode_LastN);
|
|
||||||
FlushSerialRequestResend();
|
|
||||||
serial_count = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If no errors, remove the checksum and continue parsing.
|
|
||||||
*strchr_pointer = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SERIAL_ERROR_START;
|
|
||||||
SERIAL_ERRORRPGM(_i("No Checksum with line number, Last Line: "));////MSG_ERR_NO_CHECKSUM c=0 r=0
|
|
||||||
SERIAL_ERRORLN(gcode_LastN);
|
|
||||||
FlushSerialRequestResend();
|
|
||||||
serial_count = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't parse N again with code_seen('N')
|
|
||||||
cmdbuffer[bufindw + CMDHDRSIZE] = '$';
|
|
||||||
//if no errors, continue parsing
|
|
||||||
gcode_LastN = gcode_N;
|
|
||||||
}
|
|
||||||
// if we don't receive 'N' but still see '*'
|
|
||||||
if ((cmdbuffer[bufindw + CMDHDRSIZE] != 'N') && (cmdbuffer[bufindw + CMDHDRSIZE] != '$') && (strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
|
|
||||||
{
|
|
||||||
|
|
||||||
SERIAL_ERROR_START;
|
|
||||||
SERIAL_ERRORRPGM(_n("No Line Number with checksum, Last Line: "));////MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM c=0 r=0
|
|
||||||
SERIAL_ERRORLN(gcode_LastN);
|
|
||||||
FlushSerialRequestResend();
|
|
||||||
serial_count = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'G')) != NULL) {
|
|
||||||
if (! IS_SD_PRINTING) {
|
|
||||||
usb_printing_counter = 10;
|
|
||||||
is_usb_printing = true;
|
|
||||||
}
|
|
||||||
if (Stopped == true) {
|
|
||||||
int gcode = strtol(strchr_pointer+1, NULL, 10);
|
|
||||||
if (gcode >= 0 && gcode <= 3) {
|
|
||||||
SERIAL_ERRORLNRPGM(_T(MSG_ERR_STOPPED));
|
|
||||||
LCD_MESSAGERPGM(_T(MSG_STOPPED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // end of 'G' command
|
|
||||||
|
|
||||||
//If command was e-stop process now
|
|
||||||
if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
|
|
||||||
kill("", 2);
|
|
||||||
|
|
||||||
// Store the current line into buffer, move to the next line.
|
|
||||||
// Store type of entry
|
|
||||||
cmdbuffer[bufindw] = gcode_N ? CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR : CMDBUFFER_CURRENT_TYPE_USB;
|
|
||||||
#ifdef CMDBUFFER_DEBUG
|
|
||||||
SERIAL_ECHO_START;
|
|
||||||
SERIAL_ECHOPGM("Storing a command line to buffer: ");
|
|
||||||
SERIAL_ECHO(cmdbuffer+bufindw+CMDHDRSIZE);
|
|
||||||
SERIAL_ECHOLNPGM("");
|
|
||||||
#endif /* CMDBUFFER_DEBUG */
|
|
||||||
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
|
||||||
if (bufindw == sizeof(cmdbuffer))
|
|
||||||
bufindw = 0;
|
|
||||||
++ buflen;
|
|
||||||
#ifdef CMDBUFFER_DEBUG
|
|
||||||
SERIAL_ECHOPGM("Number of commands in the buffer: ");
|
|
||||||
SERIAL_ECHO(buflen);
|
|
||||||
SERIAL_ECHOLNPGM("");
|
|
||||||
#endif /* CMDBUFFER_DEBUG */
|
|
||||||
} // end of 'not comment mode'
|
|
||||||
serial_count = 0; //clear buffer
|
|
||||||
// Don't call cmdqueue_could_enqueue_back if there are no characters waiting
|
|
||||||
// in the queue, as this function will reserve the memory.
|
|
||||||
if (MYSERIAL.available() == 0 || ! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
|
|
||||||
return;
|
|
||||||
} // end of "end of line" processing
|
|
||||||
else {
|
|
||||||
// Not an "end of line" symbol. Store the new character into a buffer.
|
|
||||||
if(serial_char == ';') comment_mode = true;
|
|
||||||
if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
|
||||||
}
|
}
|
||||||
} // end of serial line processing loop
|
|
||||||
|
|
||||||
if(farm_mode){
|
// start of serial line processing loop
|
||||||
|
while (MYSERIAL.available() > 0 && !saved_printing) { //is print is saved (crash detection or filament detection), dont process data from serial line
|
||||||
|
|
||||||
|
char serial_char = MYSERIAL.read();
|
||||||
|
/* if (selectedSerialPort == 1)
|
||||||
|
{
|
||||||
|
selectedSerialPort = 0;
|
||||||
|
MYSERIAL.write(serial_char); // for debuging serial line 2 in farm_mode
|
||||||
|
selectedSerialPort = 1;
|
||||||
|
} */ //RP - removed
|
||||||
|
TimeSent = millis();
|
||||||
|
TimeNow = millis();
|
||||||
|
|
||||||
|
if (serial_char < 0)
|
||||||
|
// Ignore extended ASCII characters. These characters have no meaning in the G-code apart from the file names
|
||||||
|
// and Marlin does not support such file names anyway.
|
||||||
|
// Serial characters with a highest bit set to 1 are generated when the USB cable is unplugged, leading
|
||||||
|
// to a hang-up of the print process from an SD card.
|
||||||
|
continue;
|
||||||
|
if(serial_char == '\n' ||
|
||||||
|
serial_char == '\r' ||
|
||||||
|
serial_count >= (MAX_CMD_SIZE - 1) )
|
||||||
|
{
|
||||||
|
if(!serial_count) { //if empty line
|
||||||
|
comment_mode = false; //for new command
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
||||||
|
if(!comment_mode) {
|
||||||
|
|
||||||
|
gcode_N = 0;
|
||||||
|
|
||||||
|
// Line numbers must be first in buffer
|
||||||
|
|
||||||
|
if ((strstr(cmdbuffer+bufindw+CMDHDRSIZE, "PRUSA") == NULL) &&
|
||||||
|
(cmdbuffer[bufindw+CMDHDRSIZE] == 'N')) {
|
||||||
|
|
||||||
|
// Line number met. When sending a G-code over a serial line, each line may be stamped with its index,
|
||||||
|
// and Marlin tests, whether the successive lines are stamped with an increasing line number ID
|
||||||
|
gcode_N = (strtol(cmdbuffer+bufindw+CMDHDRSIZE+1, NULL, 10));
|
||||||
|
if(gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer+bufindw+CMDHDRSIZE, PSTR("M110")) == NULL) ) {
|
||||||
|
// M110 - set current line number.
|
||||||
|
// Line numbers not sent in succession.
|
||||||
|
SERIAL_ERROR_START;
|
||||||
|
SERIAL_ERRORRPGM(_n("Line Number is not Last Line Number+1, Last Line: "));////MSG_ERR_LINE_NO c=0 r=0
|
||||||
|
SERIAL_ERRORLN(gcode_LastN);
|
||||||
|
//Serial.println(gcode_N);
|
||||||
|
FlushSerialRequestResend();
|
||||||
|
serial_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*')) != NULL)
|
||||||
|
{
|
||||||
|
byte checksum = 0;
|
||||||
|
char *p = cmdbuffer+bufindw+CMDHDRSIZE;
|
||||||
|
while (p != strchr_pointer)
|
||||||
|
checksum = checksum^(*p++);
|
||||||
|
if (int(strtol(strchr_pointer+1, NULL, 10)) != int(checksum)) {
|
||||||
|
SERIAL_ERROR_START;
|
||||||
|
SERIAL_ERRORRPGM(_i("checksum mismatch, Last Line: "));////MSG_ERR_CHECKSUM_MISMATCH c=0 r=0
|
||||||
|
SERIAL_ERRORLN(gcode_LastN);
|
||||||
|
FlushSerialRequestResend();
|
||||||
|
serial_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If no errors, remove the checksum and continue parsing.
|
||||||
|
*strchr_pointer = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SERIAL_ERROR_START;
|
||||||
|
SERIAL_ERRORRPGM(_i("No Checksum with line number, Last Line: "));////MSG_ERR_NO_CHECKSUM c=0 r=0
|
||||||
|
SERIAL_ERRORLN(gcode_LastN);
|
||||||
|
FlushSerialRequestResend();
|
||||||
|
serial_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't parse N again with code_seen('N')
|
||||||
|
cmdbuffer[bufindw + CMDHDRSIZE] = '$';
|
||||||
|
//if no errors, continue parsing
|
||||||
|
gcode_LastN = gcode_N;
|
||||||
|
}
|
||||||
|
// if we don't receive 'N' but still see '*'
|
||||||
|
if ((cmdbuffer[bufindw + CMDHDRSIZE] != 'N') && (cmdbuffer[bufindw + CMDHDRSIZE] != '$') && (strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
|
||||||
|
{
|
||||||
|
|
||||||
|
SERIAL_ERROR_START;
|
||||||
|
SERIAL_ERRORRPGM(_n("No Line Number with checksum, Last Line: "));////MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM c=0 r=0
|
||||||
|
SERIAL_ERRORLN(gcode_LastN);
|
||||||
|
FlushSerialRequestResend();
|
||||||
|
serial_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'G')) != NULL) {
|
||||||
|
if (! IS_SD_PRINTING) {
|
||||||
|
usb_printing_counter = 10;
|
||||||
|
is_usb_printing = true;
|
||||||
|
}
|
||||||
|
if (Stopped == true) {
|
||||||
|
int gcode = strtol(strchr_pointer+1, NULL, 10);
|
||||||
|
if (gcode >= 0 && gcode <= 3) {
|
||||||
|
SERIAL_ERRORLNRPGM(_T(MSG_ERR_STOPPED));
|
||||||
|
LCD_MESSAGERPGM(_T(MSG_STOPPED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end of 'G' command
|
||||||
|
|
||||||
|
//If command was e-stop process now
|
||||||
|
if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
|
||||||
|
kill("", 2);
|
||||||
|
|
||||||
|
// Store the current line into buffer, move to the next line.
|
||||||
|
// Store type of entry
|
||||||
|
cmdbuffer[bufindw] = gcode_N ? CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR : CMDBUFFER_CURRENT_TYPE_USB;
|
||||||
|
#ifdef CMDBUFFER_DEBUG
|
||||||
|
SERIAL_ECHO_START;
|
||||||
|
SERIAL_ECHOPGM("Storing a command line to buffer: ");
|
||||||
|
SERIAL_ECHO(cmdbuffer+bufindw+CMDHDRSIZE);
|
||||||
|
SERIAL_ECHOLNPGM("");
|
||||||
|
#endif /* CMDBUFFER_DEBUG */
|
||||||
|
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
||||||
|
if (bufindw == sizeof(cmdbuffer))
|
||||||
|
bufindw = 0;
|
||||||
|
++ buflen;
|
||||||
|
#ifdef CMDBUFFER_DEBUG
|
||||||
|
SERIAL_ECHOPGM("Number of commands in the buffer: ");
|
||||||
|
SERIAL_ECHO(buflen);
|
||||||
|
SERIAL_ECHOLNPGM("");
|
||||||
|
#endif /* CMDBUFFER_DEBUG */
|
||||||
|
} // end of 'not comment mode'
|
||||||
|
serial_count = 0; //clear buffer
|
||||||
|
// Don't call cmdqueue_could_enqueue_back if there are no characters waiting
|
||||||
|
// in the queue, as this function will reserve the memory.
|
||||||
|
if (MYSERIAL.available() == 0 || ! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
|
||||||
|
return;
|
||||||
|
} // end of "end of line" processing
|
||||||
|
else {
|
||||||
|
// Not an "end of line" symbol. Store the new character into a buffer.
|
||||||
|
if(serial_char == ';') comment_mode = true;
|
||||||
|
if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
||||||
|
}
|
||||||
|
} // end of serial line processing loop
|
||||||
|
|
||||||
|
if(farm_mode) {
|
||||||
TimeNow = millis();
|
TimeNow = millis();
|
||||||
if ( ((TimeNow - TimeSent) > 800) && (serial_count > 0) ) {
|
if ( ((TimeNow - TimeSent) > 800) && (serial_count > 0) ) {
|
||||||
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0;
|
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0;
|
||||||
|
|
@ -544,82 +544,82 @@ void get_command()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SDSUPPORT
|
#ifdef SDSUPPORT
|
||||||
if(!card.sdprinting || serial_count!=0){
|
if(!card.sdprinting || serial_count!=0) {
|
||||||
// If there is a half filled buffer from serial line, wait until return before
|
// If there is a half filled buffer from serial line, wait until return before
|
||||||
// continuing with the serial line.
|
// continuing with the serial line.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//'#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible
|
//'#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible
|
||||||
// if it occurs, stop_buffering is triggered and the buffer is ran dry.
|
// if it occurs, stop_buffering is triggered and the buffer is ran dry.
|
||||||
// this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing
|
// this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing
|
||||||
|
|
||||||
static bool stop_buffering=false;
|
static bool stop_buffering=false;
|
||||||
if(buflen==0) stop_buffering=false;
|
if(buflen==0) stop_buffering=false;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
char lo;
|
char lo;
|
||||||
char hi;
|
char hi;
|
||||||
} lohi;
|
} lohi;
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
} sd_count;
|
} sd_count;
|
||||||
sd_count.value = 0;
|
sd_count.value = 0;
|
||||||
// Reads whole lines from the SD card. Never leaves a half-filled line in the cmdbuffer.
|
// Reads whole lines from the SD card. Never leaves a half-filled line in the cmdbuffer.
|
||||||
while( !card.eof() && !stop_buffering) {
|
while( !card.eof() && !stop_buffering) {
|
||||||
int16_t n=card.get();
|
int16_t n=card.get();
|
||||||
char serial_char = (char)n;
|
char serial_char = (char)n;
|
||||||
if(serial_char == '\n' ||
|
if(serial_char == '\n' ||
|
||||||
serial_char == '\r' ||
|
serial_char == '\r' ||
|
||||||
((serial_char == '#' || serial_char == ':') && comment_mode == false) ||
|
((serial_char == '#' || serial_char == ':') && comment_mode == false) ||
|
||||||
serial_count >= (MAX_CMD_SIZE - 1) || n==-1)
|
serial_count >= (MAX_CMD_SIZE - 1) || n==-1)
|
||||||
{
|
|
||||||
if(card.eof()){
|
|
||||||
SERIAL_PROTOCOLLNRPGM(_n("Done printing file"));////MSG_FILE_PRINTED c=0 r=0
|
|
||||||
stoptime=millis();
|
|
||||||
char time[30];
|
|
||||||
unsigned long t=(stoptime-starttime-pause_time)/1000;
|
|
||||||
pause_time = 0;
|
|
||||||
int hours, minutes;
|
|
||||||
minutes=(t/60)%60;
|
|
||||||
hours=t/60/60;
|
|
||||||
save_statistics(total_filament_used, t);
|
|
||||||
sprintf_P(time, PSTR("%i hours %i minutes"),hours, minutes);
|
|
||||||
SERIAL_ECHO_START;
|
|
||||||
SERIAL_ECHOLN(time);
|
|
||||||
lcd_setstatus(time);
|
|
||||||
card.printingHasFinished();
|
|
||||||
card.checkautostart(true);
|
|
||||||
|
|
||||||
if (farm_mode)
|
|
||||||
{
|
{
|
||||||
prusa_statistics(6);
|
if(card.eof()) {
|
||||||
lcd_commands_type = LCD_COMMAND_FARM_MODE_CONFIRM;
|
SERIAL_PROTOCOLLNRPGM(_n("Done printing file"));////MSG_FILE_PRINTED c=0 r=0
|
||||||
}
|
stoptime=millis();
|
||||||
|
char time[30];
|
||||||
|
unsigned long t=(stoptime-starttime-pause_time)/1000;
|
||||||
|
pause_time = 0;
|
||||||
|
int hours, minutes;
|
||||||
|
minutes=(t/60)%60;
|
||||||
|
hours=t/60/60;
|
||||||
|
save_statistics(total_filament_used, t);
|
||||||
|
sprintf_P(time, PSTR("%i hours %i minutes"),hours, minutes);
|
||||||
|
SERIAL_ECHO_START;
|
||||||
|
SERIAL_ECHOLN(time);
|
||||||
|
lcd_setstatus(time);
|
||||||
|
card.printingHasFinished();
|
||||||
|
card.checkautostart(true);
|
||||||
|
|
||||||
}
|
if (farm_mode)
|
||||||
if(serial_char=='#')
|
{
|
||||||
stop_buffering=true;
|
prusa_statistics(6);
|
||||||
|
lcd_commands_type = LCD_COMMAND_FARM_MODE_CONFIRM;
|
||||||
|
}
|
||||||
|
|
||||||
if(!serial_count)
|
}
|
||||||
{
|
if(serial_char=='#')
|
||||||
// This is either an empty line, or a line with just a comment.
|
stop_buffering=true;
|
||||||
// Continue to the following line, and continue accumulating the number of bytes
|
|
||||||
// read from the sdcard into sd_count,
|
if(!serial_count)
|
||||||
// so that the lenght of the already read empty lines and comments will be added
|
{
|
||||||
// to the following non-empty line.
|
// This is either an empty line, or a line with just a comment.
|
||||||
comment_mode = false;
|
// Continue to the following line, and continue accumulating the number of bytes
|
||||||
continue; //if empty line
|
// read from the sdcard into sd_count,
|
||||||
}
|
// so that the lenght of the already read empty lines and comments will be added
|
||||||
// The new command buffer could be updated non-atomically, because it is not yet considered
|
// to the following non-empty line.
|
||||||
// to be inside the active queue.
|
comment_mode = false;
|
||||||
sd_count.value = (card.get_sdpos()+1) - sdpos_atomic;
|
continue; //if empty line
|
||||||
cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_SDCARD;
|
}
|
||||||
cmdbuffer[bufindw+1] = sd_count.lohi.lo;
|
// The new command buffer could be updated non-atomically, because it is not yet considered
|
||||||
cmdbuffer[bufindw+2] = sd_count.lohi.hi;
|
// to be inside the active queue.
|
||||||
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
sd_count.value = (card.get_sdpos()+1) - sdpos_atomic;
|
||||||
// Calculate the length before disabling the interrupts.
|
cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_SDCARD;
|
||||||
uint8_t len = strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
cmdbuffer[bufindw+1] = sd_count.lohi.lo;
|
||||||
|
cmdbuffer[bufindw+2] = sd_count.lohi.hi;
|
||||||
|
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
||||||
|
// Calculate the length before disabling the interrupts.
|
||||||
|
uint8_t len = strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
||||||
|
|
||||||
// SERIAL_ECHOPGM("SD cmd(");
|
// SERIAL_ECHOPGM("SD cmd(");
|
||||||
// MYSERIAL.print(sd_count.value, DEC);
|
// MYSERIAL.print(sd_count.value, DEC);
|
||||||
|
|
@ -629,34 +629,34 @@ void get_command()
|
||||||
// MYSERIAL.print(cmdbuffer);
|
// MYSERIAL.print(cmdbuffer);
|
||||||
// SERIAL_ECHOPGM("buflen:");
|
// SERIAL_ECHOPGM("buflen:");
|
||||||
// MYSERIAL.print(buflen+1);
|
// MYSERIAL.print(buflen+1);
|
||||||
sd_count.value = 0;
|
sd_count.value = 0;
|
||||||
|
|
||||||
cli();
|
cli();
|
||||||
// This block locks the interrupts globally for 3.56 us,
|
// This block locks the interrupts globally for 3.56 us,
|
||||||
// which corresponds to a maximum repeat frequency of 280.70 kHz.
|
// which corresponds to a maximum repeat frequency of 280.70 kHz.
|
||||||
// This blocking is safe in the context of a 10kHz stepper driver interrupt
|
// This blocking is safe in the context of a 10kHz stepper driver interrupt
|
||||||
// or a 115200 Bd serial line receive interrupt, which will not trigger faster than 12kHz.
|
// or a 115200 Bd serial line receive interrupt, which will not trigger faster than 12kHz.
|
||||||
++ buflen;
|
++ buflen;
|
||||||
bufindw += len;
|
bufindw += len;
|
||||||
sdpos_atomic = card.get_sdpos()+1;
|
sdpos_atomic = card.get_sdpos()+1;
|
||||||
if (bufindw == sizeof(cmdbuffer))
|
if (bufindw == sizeof(cmdbuffer))
|
||||||
bufindw = 0;
|
bufindw = 0;
|
||||||
sei();
|
sei();
|
||||||
|
|
||||||
comment_mode = false; //for new command
|
comment_mode = false; //for new command
|
||||||
serial_count = 0; //clear buffer
|
serial_count = 0; //clear buffer
|
||||||
// The following line will reserve buffer space if available.
|
// The following line will reserve buffer space if available.
|
||||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
|
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(serial_char == ';') comment_mode = true;
|
||||||
|
else if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if(serial_char == ';') comment_mode = true;
|
|
||||||
else if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //SDSUPPORT
|
#endif //SDSUPPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t cmdqueue_calc_sd_length()
|
uint16_t cmdqueue_calc_sd_length()
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,24 @@ extern void get_command();
|
||||||
extern uint16_t cmdqueue_calc_sd_length();
|
extern uint16_t cmdqueue_calc_sd_length();
|
||||||
|
|
||||||
// Return True if a character was found
|
// Return True if a character was found
|
||||||
static inline bool code_seen(char code) { return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
|
static inline bool code_seen(char code) {
|
||||||
static inline bool code_seen(const char *code) { return (strchr_pointer = strstr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
|
return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL;
|
||||||
static inline float code_value() { return strtod(strchr_pointer+1, NULL);}
|
}
|
||||||
static inline long code_value_long() { return strtol(strchr_pointer+1, NULL, 10); }
|
static inline bool code_seen(const char *code) {
|
||||||
static inline int16_t code_value_short() { return int16_t(strtol(strchr_pointer+1, NULL, 10)); };
|
return (strchr_pointer = strstr(CMDBUFFER_CURRENT_STRING, code)) != NULL;
|
||||||
static inline uint8_t code_value_uint8() { return uint8_t(strtol(strchr_pointer+1, NULL, 10)); };
|
}
|
||||||
|
static inline float code_value() {
|
||||||
|
return strtod(strchr_pointer+1, NULL);
|
||||||
|
}
|
||||||
|
static inline long code_value_long() {
|
||||||
|
return strtol(strchr_pointer+1, NULL, 10);
|
||||||
|
}
|
||||||
|
static inline int16_t code_value_short() {
|
||||||
|
return int16_t(strtol(strchr_pointer+1, NULL, 10));
|
||||||
|
};
|
||||||
|
static inline uint8_t code_value_uint8() {
|
||||||
|
return uint8_t(strtol(strchr_pointer+1, NULL, 10));
|
||||||
|
};
|
||||||
|
|
||||||
static inline float code_value_float()
|
static inline float code_value_float()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,110 +9,110 @@ char conv[8];
|
||||||
|
|
||||||
char *ftostr3(const float &x)
|
char *ftostr3(const float &x)
|
||||||
{
|
{
|
||||||
return itostr3((int)x);
|
return itostr3((int)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *itostr2(const uint8_t &x)
|
char *itostr2(const uint8_t &x)
|
||||||
{
|
{
|
||||||
//sprintf(conv,"%5.1f",x);
|
//sprintf(conv,"%5.1f",x);
|
||||||
int xx = x;
|
int xx = x;
|
||||||
conv[0] = (xx / 10) % 10 + '0';
|
conv[0] = (xx / 10) % 10 + '0';
|
||||||
conv[1] = (xx) % 10 + '0';
|
conv[1] = (xx) % 10 + '0';
|
||||||
conv[2] = 0;
|
conv[2] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert float to string with 123.4 format, dropping sign
|
// Convert float to string with 123.4 format, dropping sign
|
||||||
char *ftostr31(const float &x)
|
char *ftostr31(const float &x)
|
||||||
{
|
{
|
||||||
int xx = x * 10;
|
int xx = x * 10;
|
||||||
conv[0] = (xx >= 0) ? '+' : '-';
|
conv[0] = (xx >= 0) ? '+' : '-';
|
||||||
xx = abs(xx);
|
xx = abs(xx);
|
||||||
conv[1] = (xx / 1000) % 10 + '0';
|
conv[1] = (xx / 1000) % 10 + '0';
|
||||||
conv[2] = (xx / 100) % 10 + '0';
|
conv[2] = (xx / 100) % 10 + '0';
|
||||||
conv[3] = (xx / 10) % 10 + '0';
|
conv[3] = (xx / 10) % 10 + '0';
|
||||||
conv[4] = '.';
|
conv[4] = '.';
|
||||||
conv[5] = (xx) % 10 + '0';
|
conv[5] = (xx) % 10 + '0';
|
||||||
conv[6] = 0;
|
conv[6] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert float to string with 123.4 format
|
// Convert float to string with 123.4 format
|
||||||
char *ftostr31ns(const float &x)
|
char *ftostr31ns(const float &x)
|
||||||
{
|
{
|
||||||
int xx = x * 10;
|
int xx = x * 10;
|
||||||
//conv[0]=(xx>=0)?'+':'-';
|
//conv[0]=(xx>=0)?'+':'-';
|
||||||
xx = abs(xx);
|
xx = abs(xx);
|
||||||
conv[0] = (xx / 1000) % 10 + '0';
|
conv[0] = (xx / 1000) % 10 + '0';
|
||||||
conv[1] = (xx / 100) % 10 + '0';
|
conv[1] = (xx / 100) % 10 + '0';
|
||||||
conv[2] = (xx / 10) % 10 + '0';
|
conv[2] = (xx / 10) % 10 + '0';
|
||||||
conv[3] = '.';
|
conv[3] = '.';
|
||||||
conv[4] = (xx) % 10 + '0';
|
conv[4] = (xx) % 10 + '0';
|
||||||
conv[5] = 0;
|
conv[5] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ftostr32(const float &x)
|
char *ftostr32(const float &x)
|
||||||
{
|
{
|
||||||
long xx = x * 100;
|
long xx = x * 100;
|
||||||
if (xx >= 0)
|
if (xx >= 0)
|
||||||
conv[0] = (xx / 10000) % 10 + '0';
|
conv[0] = (xx / 10000) % 10 + '0';
|
||||||
else
|
else
|
||||||
conv[0] = '-';
|
conv[0] = '-';
|
||||||
xx = abs(xx);
|
xx = abs(xx);
|
||||||
conv[1] = (xx / 1000) % 10 + '0';
|
conv[1] = (xx / 1000) % 10 + '0';
|
||||||
conv[2] = (xx / 100) % 10 + '0';
|
conv[2] = (xx / 100) % 10 + '0';
|
||||||
conv[3] = '.';
|
conv[3] = '.';
|
||||||
conv[4] = (xx / 10) % 10 + '0';
|
conv[4] = (xx / 10) % 10 + '0';
|
||||||
conv[5] = (xx) % 10 + '0';
|
conv[5] = (xx) % 10 + '0';
|
||||||
conv[6] = 0;
|
conv[6] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Convert float to rj string with 123.45 format
|
//// Convert float to rj string with 123.45 format
|
||||||
char *ftostr32ns(const float &x) {
|
char *ftostr32ns(const float &x) {
|
||||||
long xx = abs(x);
|
long xx = abs(x);
|
||||||
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
|
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
|
||||||
conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
||||||
conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : '0';
|
conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : '0';
|
||||||
conv[3] = '.';
|
conv[3] = '.';
|
||||||
conv[4] = (xx / 10) % 10 + '0';
|
conv[4] = (xx / 10) % 10 + '0';
|
||||||
conv[5] = xx % 10 + '0';
|
conv[5] = xx % 10 + '0';
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Convert float to string with 1.234 format
|
// Convert float to string with 1.234 format
|
||||||
char *ftostr43(const float &x, uint8_t offset)
|
char *ftostr43(const float &x, uint8_t offset)
|
||||||
{
|
{
|
||||||
const size_t maxOffset = sizeof(conv)/sizeof(conv[0]) - 6;
|
const size_t maxOffset = sizeof(conv)/sizeof(conv[0]) - 6;
|
||||||
if (offset>maxOffset) offset = maxOffset;
|
if (offset>maxOffset) offset = maxOffset;
|
||||||
long xx = x * 1000;
|
long xx = x * 1000;
|
||||||
if (xx >= 0)
|
if (xx >= 0)
|
||||||
conv[offset] = (xx / 1000) % 10 + '0';
|
conv[offset] = (xx / 1000) % 10 + '0';
|
||||||
else
|
else
|
||||||
conv[offset] = '-';
|
conv[offset] = '-';
|
||||||
xx = abs(xx);
|
xx = abs(xx);
|
||||||
conv[offset + 1] = '.';
|
conv[offset + 1] = '.';
|
||||||
conv[offset + 2] = (xx / 100) % 10 + '0';
|
conv[offset + 2] = (xx / 100) % 10 + '0';
|
||||||
conv[offset + 3] = (xx / 10) % 10 + '0';
|
conv[offset + 3] = (xx / 10) % 10 + '0';
|
||||||
conv[offset + 4] = (xx) % 10 + '0';
|
conv[offset + 4] = (xx) % 10 + '0';
|
||||||
conv[offset + 5] = 0;
|
conv[offset + 5] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Float to string with 1.23 format
|
//Float to string with 1.23 format
|
||||||
char *ftostr12ns(const float &x)
|
char *ftostr12ns(const float &x)
|
||||||
{
|
{
|
||||||
long xx = x * 100;
|
long xx = x * 100;
|
||||||
|
|
||||||
xx = abs(xx);
|
xx = abs(xx);
|
||||||
conv[0] = (xx / 100) % 10 + '0';
|
conv[0] = (xx / 100) % 10 + '0';
|
||||||
conv[1] = '.';
|
conv[1] = '.';
|
||||||
conv[2] = (xx / 10) % 10 + '0';
|
conv[2] = (xx / 10) % 10 + '0';
|
||||||
conv[3] = (xx) % 10 + '0';
|
conv[3] = (xx) % 10 + '0';
|
||||||
conv[4] = 0;
|
conv[4] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Float to string with 1.234 format
|
//Float to string with 1.234 format
|
||||||
|
|
@ -135,158 +135,158 @@ char *ftostr13ns(const float &x)
|
||||||
|
|
||||||
// convert float to space-padded string with -_23.4_ format
|
// convert float to space-padded string with -_23.4_ format
|
||||||
char *ftostr32sp(const float &x) {
|
char *ftostr32sp(const float &x) {
|
||||||
long xx = abs(x * 100);
|
long xx = abs(x * 100);
|
||||||
uint8_t dig;
|
uint8_t dig;
|
||||||
|
|
||||||
if (x < 0) { // negative val = -_0
|
if (x < 0) { // negative val = -_0
|
||||||
conv[0] = '-';
|
conv[0] = '-';
|
||||||
dig = (xx / 1000) % 10;
|
dig = (xx / 1000) % 10;
|
||||||
conv[1] = dig ? '0' + dig : ' ';
|
conv[1] = dig ? '0' + dig : ' ';
|
||||||
}
|
|
||||||
else { // positive val = __0
|
|
||||||
dig = (xx / 10000) % 10;
|
|
||||||
if (dig) {
|
|
||||||
conv[0] = '0' + dig;
|
|
||||||
conv[1] = '0' + (xx / 1000) % 10;
|
|
||||||
}
|
}
|
||||||
else {
|
else { // positive val = __0
|
||||||
conv[0] = ' ';
|
dig = (xx / 10000) % 10;
|
||||||
dig = (xx / 1000) % 10;
|
if (dig) {
|
||||||
conv[1] = dig ? '0' + dig : ' ';
|
conv[0] = '0' + dig;
|
||||||
|
conv[1] = '0' + (xx / 1000) % 10;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
conv[0] = ' ';
|
||||||
|
dig = (xx / 1000) % 10;
|
||||||
|
conv[1] = dig ? '0' + dig : ' ';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
conv[2] = '0' + (xx / 100) % 10; // lsd always
|
conv[2] = '0' + (xx / 100) % 10; // lsd always
|
||||||
|
|
||||||
dig = xx % 10;
|
dig = xx % 10;
|
||||||
if (dig) { // 2 decimal places
|
if (dig) { // 2 decimal places
|
||||||
conv[5] = '0' + dig;
|
conv[5] = '0' + dig;
|
||||||
conv[4] = '0' + (xx / 10) % 10;
|
conv[4] = '0' + (xx / 10) % 10;
|
||||||
conv[3] = '.';
|
conv[3] = '.';
|
||||||
}
|
|
||||||
else { // 1 or 0 decimal place
|
|
||||||
dig = (xx / 10) % 10;
|
|
||||||
if (dig) {
|
|
||||||
conv[4] = '0' + dig;
|
|
||||||
conv[3] = '.';
|
|
||||||
}
|
}
|
||||||
else {
|
else { // 1 or 0 decimal place
|
||||||
conv[3] = conv[4] = ' ';
|
dig = (xx / 10) % 10;
|
||||||
|
if (dig) {
|
||||||
|
conv[4] = '0' + dig;
|
||||||
|
conv[3] = '.';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
conv[3] = conv[4] = ' ';
|
||||||
|
}
|
||||||
|
conv[5] = ' ';
|
||||||
}
|
}
|
||||||
conv[5] = ' ';
|
conv[6] = '\0';
|
||||||
}
|
return conv;
|
||||||
conv[6] = '\0';
|
|
||||||
return conv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *itostr31(const int &xx)
|
char *itostr31(const int &xx)
|
||||||
{
|
{
|
||||||
conv[0] = (xx >= 0) ? '+' : '-';
|
conv[0] = (xx >= 0) ? '+' : '-';
|
||||||
conv[1] = (xx / 1000) % 10 + '0';
|
conv[1] = (xx / 1000) % 10 + '0';
|
||||||
conv[2] = (xx / 100) % 10 + '0';
|
conv[2] = (xx / 100) % 10 + '0';
|
||||||
conv[3] = (xx / 10) % 10 + '0';
|
conv[3] = (xx / 10) % 10 + '0';
|
||||||
conv[4] = '.';
|
conv[4] = '.';
|
||||||
conv[5] = (xx) % 10 + '0';
|
conv[5] = (xx) % 10 + '0';
|
||||||
conv[6] = 0;
|
conv[6] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert int to rj string with 123 or -12 format
|
// Convert int to rj string with 123 or -12 format
|
||||||
char *itostr3(const int &x)
|
char *itostr3(const int &x)
|
||||||
{
|
{
|
||||||
int xx = x;
|
int xx = x;
|
||||||
if (xx < 0) {
|
if (xx < 0) {
|
||||||
conv[0] = '-';
|
conv[0] = '-';
|
||||||
xx = -xx;
|
xx = -xx;
|
||||||
} else if (xx >= 100)
|
} else if (xx >= 100)
|
||||||
conv[0] = (xx / 100) % 10 + '0';
|
conv[0] = (xx / 100) % 10 + '0';
|
||||||
else
|
else
|
||||||
conv[0] = ' ';
|
conv[0] = ' ';
|
||||||
if (xx >= 10)
|
if (xx >= 10)
|
||||||
conv[1] = (xx / 10) % 10 + '0';
|
conv[1] = (xx / 10) % 10 + '0';
|
||||||
else
|
else
|
||||||
conv[1] = ' ';
|
conv[1] = ' ';
|
||||||
conv[2] = (xx) % 10 + '0';
|
conv[2] = (xx) % 10 + '0';
|
||||||
conv[3] = 0;
|
conv[3] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert int to lj string with 123 format
|
// Convert int to lj string with 123 format
|
||||||
char *itostr3left(const int &xx)
|
char *itostr3left(const int &xx)
|
||||||
{
|
{
|
||||||
if (xx >= 100)
|
if (xx >= 100)
|
||||||
{
|
{
|
||||||
conv[0] = (xx / 100) % 10 + '0';
|
conv[0] = (xx / 100) % 10 + '0';
|
||||||
conv[1] = (xx / 10) % 10 + '0';
|
conv[1] = (xx / 10) % 10 + '0';
|
||||||
conv[2] = (xx) % 10 + '0';
|
conv[2] = (xx) % 10 + '0';
|
||||||
conv[3] = 0;
|
conv[3] = 0;
|
||||||
}
|
}
|
||||||
else if (xx >= 10)
|
else if (xx >= 10)
|
||||||
{
|
{
|
||||||
conv[0] = (xx / 10) % 10 + '0';
|
conv[0] = (xx / 10) % 10 + '0';
|
||||||
conv[1] = (xx) % 10 + '0';
|
conv[1] = (xx) % 10 + '0';
|
||||||
conv[2] = 0;
|
conv[2] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
conv[0] = (xx) % 10 + '0';
|
conv[0] = (xx) % 10 + '0';
|
||||||
conv[1] = 0;
|
conv[1] = 0;
|
||||||
}
|
}
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert int to rj string with 1234 format
|
// Convert int to rj string with 1234 format
|
||||||
char *itostr4(const int &xx) {
|
char *itostr4(const int &xx) {
|
||||||
conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
||||||
conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
|
conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
|
||||||
conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
|
conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
|
||||||
conv[3] = xx % 10 + '0';
|
conv[3] = xx % 10 + '0';
|
||||||
conv[4] = 0;
|
conv[4] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert float to rj string with 12345 format
|
// Convert float to rj string with 12345 format
|
||||||
char *ftostr5(const float &x) {
|
char *ftostr5(const float &x) {
|
||||||
long xx = abs(x);
|
long xx = abs(x);
|
||||||
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
|
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
|
||||||
conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
||||||
conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
|
conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
|
||||||
conv[3] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
|
conv[3] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
|
||||||
conv[4] = xx % 10 + '0';
|
conv[4] = xx % 10 + '0';
|
||||||
conv[5] = 0;
|
conv[5] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert float to string with +1234.5 format
|
// Convert float to string with +1234.5 format
|
||||||
char *ftostr51(const float &x)
|
char *ftostr51(const float &x)
|
||||||
{
|
{
|
||||||
long xx = x * 10;
|
long xx = x * 10;
|
||||||
conv[0] = (xx >= 0) ? '+' : '-';
|
conv[0] = (xx >= 0) ? '+' : '-';
|
||||||
xx = abs(xx);
|
xx = abs(xx);
|
||||||
conv[1] = (xx / 10000) % 10 + '0';
|
conv[1] = (xx / 10000) % 10 + '0';
|
||||||
conv[2] = (xx / 1000) % 10 + '0';
|
conv[2] = (xx / 1000) % 10 + '0';
|
||||||
conv[3] = (xx / 100) % 10 + '0';
|
conv[3] = (xx / 100) % 10 + '0';
|
||||||
conv[4] = (xx / 10) % 10 + '0';
|
conv[4] = (xx / 10) % 10 + '0';
|
||||||
conv[5] = '.';
|
conv[5] = '.';
|
||||||
conv[6] = (xx) % 10 + '0';
|
conv[6] = (xx) % 10 + '0';
|
||||||
conv[7] = 0;
|
conv[7] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert float to string with +123.45 format
|
// Convert float to string with +123.45 format
|
||||||
char *ftostr52(const float &x)
|
char *ftostr52(const float &x)
|
||||||
{
|
{
|
||||||
long xx = x * 100;
|
long xx = x * 100;
|
||||||
conv[0] = (xx >= 0) ? '+' : '-';
|
conv[0] = (xx >= 0) ? '+' : '-';
|
||||||
xx = abs(xx);
|
xx = abs(xx);
|
||||||
conv[1] = (xx / 10000) % 10 + '0';
|
conv[1] = (xx / 10000) % 10 + '0';
|
||||||
conv[2] = (xx / 1000) % 10 + '0';
|
conv[2] = (xx / 1000) % 10 + '0';
|
||||||
conv[3] = (xx / 100) % 10 + '0';
|
conv[3] = (xx / 100) % 10 + '0';
|
||||||
conv[4] = '.';
|
conv[4] = '.';
|
||||||
conv[5] = (xx / 10) % 10 + '0';
|
conv[5] = (xx / 10) % 10 + '0';
|
||||||
conv[6] = (xx) % 10 + '0';
|
conv[6] = (xx) % 10 + '0';
|
||||||
conv[7] = 0;
|
conv[7] = 0;
|
||||||
return conv;
|
return conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,17 +198,17 @@ void fsensor_disable(void)
|
||||||
|
|
||||||
void fsensor_autoload_set(bool State)
|
void fsensor_autoload_set(bool State)
|
||||||
{
|
{
|
||||||
if (!State) fsensor_autoload_check_stop();
|
if (!State) fsensor_autoload_check_stop();
|
||||||
fsensor_autoload_enabled = State;
|
fsensor_autoload_enabled = State;
|
||||||
eeprom_update_byte((unsigned char *)EEPROM_FSENS_AUTOLOAD_ENABLED, fsensor_autoload_enabled);
|
eeprom_update_byte((unsigned char *)EEPROM_FSENS_AUTOLOAD_ENABLED, fsensor_autoload_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pciSetup(byte pin)
|
void pciSetup(byte pin)
|
||||||
{
|
{
|
||||||
// !!! "digitalPinTo?????bit()" does not provide the correct results for some MCU pins
|
// !!! "digitalPinTo?????bit()" does not provide the correct results for some MCU pins
|
||||||
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
|
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
|
||||||
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
|
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
|
||||||
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
|
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsensor_autoload_check_start(void)
|
void fsensor_autoload_check_start(void)
|
||||||
|
|
@ -294,9 +294,9 @@ bool fsensor_check_autoload(void)
|
||||||
if ((fsensor_autoload_c >= 12) && (fsensor_autoload_sum > 20))
|
if ((fsensor_autoload_c >= 12) && (fsensor_autoload_sum > 20))
|
||||||
{
|
{
|
||||||
if (mmu_enabled) {
|
if (mmu_enabled) {
|
||||||
mmu_command(MMU_CMD_FS);
|
mmu_command(MMU_CMD_FS);
|
||||||
fsensor_autoload_check_stop();
|
fsensor_autoload_check_stop();
|
||||||
fsensor_autoload_enabled = false;
|
fsensor_autoload_enabled = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -379,73 +379,73 @@ bool fsensor_oq_result(void)
|
||||||
|
|
||||||
ISR(FSENSOR_INT_PIN_VECT)
|
ISR(FSENSOR_INT_PIN_VECT)
|
||||||
{
|
{
|
||||||
if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
|
if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
|
||||||
fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
|
fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
|
||||||
static bool _lock = false;
|
static bool _lock = false;
|
||||||
if (_lock) return;
|
if (_lock) return;
|
||||||
_lock = true;
|
_lock = true;
|
||||||
int st_cnt = fsensor_st_cnt;
|
int st_cnt = fsensor_st_cnt;
|
||||||
fsensor_st_cnt = 0;
|
fsensor_st_cnt = 0;
|
||||||
sei();
|
sei();
|
||||||
uint8_t old_err_cnt = fsensor_err_cnt;
|
uint8_t old_err_cnt = fsensor_err_cnt;
|
||||||
uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y();
|
uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y();
|
||||||
if (!pat9125_res)
|
if (!pat9125_res)
|
||||||
{
|
|
||||||
fsensor_disable();
|
|
||||||
fsensor_not_responding = true;
|
|
||||||
printf_P(ERRMSG_PAT9125_NOT_RESP, 1);
|
|
||||||
}
|
|
||||||
if (st_cnt != 0)
|
|
||||||
{ //movement
|
|
||||||
if (st_cnt > 0) //positive movement
|
|
||||||
{
|
{
|
||||||
if (pat9125_y < 0)
|
fsensor_disable();
|
||||||
{
|
fsensor_not_responding = true;
|
||||||
if (fsensor_err_cnt)
|
printf_P(ERRMSG_PAT9125_NOT_RESP, 1);
|
||||||
fsensor_err_cnt += 2;
|
|
||||||
else
|
|
||||||
fsensor_err_cnt++;
|
|
||||||
}
|
|
||||||
else if (pat9125_y > 0)
|
|
||||||
{
|
|
||||||
if (fsensor_err_cnt)
|
|
||||||
fsensor_err_cnt--;
|
|
||||||
}
|
|
||||||
else //(pat9125_y == 0)
|
|
||||||
if (((fsensor_dy_old <= 0) || (fsensor_err_cnt)) && (st_cnt > (fsensor_chunk_len >> 1)))
|
|
||||||
fsensor_err_cnt++;
|
|
||||||
if (fsensor_oq_meassure)
|
|
||||||
{
|
|
||||||
if (fsensor_oq_skipchunk)
|
|
||||||
{
|
|
||||||
fsensor_oq_skipchunk--;
|
|
||||||
fsensor_err_cnt = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (st_cnt == fsensor_chunk_len)
|
|
||||||
{
|
|
||||||
if (pat9125_y > 0) if (fsensor_oq_yd_min > pat9125_y) fsensor_oq_yd_min = (fsensor_oq_yd_min + pat9125_y) / 2;
|
|
||||||
if (pat9125_y >= 0) if (fsensor_oq_yd_max < pat9125_y) fsensor_oq_yd_max = (fsensor_oq_yd_max + pat9125_y) / 2;
|
|
||||||
}
|
|
||||||
fsensor_oq_samples++;
|
|
||||||
fsensor_oq_st_sum += st_cnt;
|
|
||||||
if (pat9125_y > 0) fsensor_oq_yd_sum += pat9125_y;
|
|
||||||
if (fsensor_err_cnt > old_err_cnt)
|
|
||||||
fsensor_oq_er_sum += (fsensor_err_cnt - old_err_cnt);
|
|
||||||
if (fsensor_oq_er_max < fsensor_err_cnt)
|
|
||||||
fsensor_oq_er_max = fsensor_err_cnt;
|
|
||||||
fsensor_oq_sh_sum += pat9125_s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else //negative movement
|
if (st_cnt != 0)
|
||||||
{
|
{ //movement
|
||||||
|
if (st_cnt > 0) //positive movement
|
||||||
|
{
|
||||||
|
if (pat9125_y < 0)
|
||||||
|
{
|
||||||
|
if (fsensor_err_cnt)
|
||||||
|
fsensor_err_cnt += 2;
|
||||||
|
else
|
||||||
|
fsensor_err_cnt++;
|
||||||
|
}
|
||||||
|
else if (pat9125_y > 0)
|
||||||
|
{
|
||||||
|
if (fsensor_err_cnt)
|
||||||
|
fsensor_err_cnt--;
|
||||||
|
}
|
||||||
|
else //(pat9125_y == 0)
|
||||||
|
if (((fsensor_dy_old <= 0) || (fsensor_err_cnt)) && (st_cnt > (fsensor_chunk_len >> 1)))
|
||||||
|
fsensor_err_cnt++;
|
||||||
|
if (fsensor_oq_meassure)
|
||||||
|
{
|
||||||
|
if (fsensor_oq_skipchunk)
|
||||||
|
{
|
||||||
|
fsensor_oq_skipchunk--;
|
||||||
|
fsensor_err_cnt = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (st_cnt == fsensor_chunk_len)
|
||||||
|
{
|
||||||
|
if (pat9125_y > 0) if (fsensor_oq_yd_min > pat9125_y) fsensor_oq_yd_min = (fsensor_oq_yd_min + pat9125_y) / 2;
|
||||||
|
if (pat9125_y >= 0) if (fsensor_oq_yd_max < pat9125_y) fsensor_oq_yd_max = (fsensor_oq_yd_max + pat9125_y) / 2;
|
||||||
|
}
|
||||||
|
fsensor_oq_samples++;
|
||||||
|
fsensor_oq_st_sum += st_cnt;
|
||||||
|
if (pat9125_y > 0) fsensor_oq_yd_sum += pat9125_y;
|
||||||
|
if (fsensor_err_cnt > old_err_cnt)
|
||||||
|
fsensor_oq_er_sum += (fsensor_err_cnt - old_err_cnt);
|
||||||
|
if (fsensor_oq_er_max < fsensor_err_cnt)
|
||||||
|
fsensor_oq_er_max = fsensor_err_cnt;
|
||||||
|
fsensor_oq_sh_sum += pat9125_s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //negative movement
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //no movement
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{ //no movement
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_FSENSOR_LOG
|
#ifdef DEBUG_FSENSOR_LOG
|
||||||
if (fsensor_log)
|
if (fsensor_log)
|
||||||
|
|
@ -464,26 +464,34 @@ ISR(FSENSOR_INT_PIN_VECT)
|
||||||
|
|
||||||
void fsensor_st_block_begin(block_t* bl)
|
void fsensor_st_block_begin(block_t* bl)
|
||||||
{
|
{
|
||||||
if (!fsensor_enabled) return;
|
if (!fsensor_enabled) return;
|
||||||
if (((fsensor_st_cnt > 0) && (bl->direction_bits & 0x8)) ||
|
if (((fsensor_st_cnt > 0) && (bl->direction_bits & 0x8)) ||
|
||||||
((fsensor_st_cnt < 0) && !(bl->direction_bits & 0x8)))
|
((fsensor_st_cnt < 0) && !(bl->direction_bits & 0x8)))
|
||||||
{
|
{
|
||||||
// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
|
// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
|
||||||
if (PIN_GET(FSENSOR_INT_PIN)) {PIN_VAL(FSENSOR_INT_PIN, LOW);}
|
if (PIN_GET(FSENSOR_INT_PIN)) {
|
||||||
else {PIN_VAL(FSENSOR_INT_PIN, HIGH);}
|
PIN_VAL(FSENSOR_INT_PIN, LOW);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
PIN_VAL(FSENSOR_INT_PIN, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsensor_st_block_chunk(block_t* bl, int cnt)
|
void fsensor_st_block_chunk(block_t* bl, int cnt)
|
||||||
{
|
{
|
||||||
if (!fsensor_enabled) return;
|
if (!fsensor_enabled) return;
|
||||||
fsensor_st_cnt += (bl->direction_bits & 0x8)?-cnt:cnt;
|
fsensor_st_cnt += (bl->direction_bits & 0x8)?-cnt:cnt;
|
||||||
if ((fsensor_st_cnt >= fsensor_chunk_len) || (fsensor_st_cnt <= -fsensor_chunk_len))
|
if ((fsensor_st_cnt >= fsensor_chunk_len) || (fsensor_st_cnt <= -fsensor_chunk_len))
|
||||||
{
|
{
|
||||||
// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
|
// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
|
||||||
if (PIN_GET(FSENSOR_INT_PIN)) {PIN_VAL(FSENSOR_INT_PIN, LOW);}
|
if (PIN_GET(FSENSOR_INT_PIN)) {
|
||||||
else {PIN_VAL(FSENSOR_INT_PIN, HIGH);}
|
PIN_VAL(FSENSOR_INT_PIN, LOW);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
PIN_VAL(FSENSOR_INT_PIN, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! @brief filament sensor update (perform M600 on filament runout)
|
//! @brief filament sensor update (perform M600 on filament runout)
|
||||||
|
|
@ -552,10 +560,10 @@ void fsensor_setup_interrupt(void)
|
||||||
digitalWrite(FSENSOR_INT_PIN, LOW);
|
digitalWrite(FSENSOR_INT_PIN, LOW);
|
||||||
fsensor_int_pin_old = 0;
|
fsensor_int_pin_old = 0;
|
||||||
|
|
||||||
//pciSetup(FSENSOR_INT_PIN);
|
//pciSetup(FSENSOR_INT_PIN);
|
||||||
// !!! "pciSetup()" does not provide the correct results for some MCU pins
|
// !!! "pciSetup()" does not provide the correct results for some MCU pins
|
||||||
// so interrupt registers settings:
|
// so interrupt registers settings:
|
||||||
FSENSOR_INT_PIN_PCMSK_REG |= bit(FSENSOR_INT_PIN_PCMSK_BIT); // enable corresponding PinChangeInterrupt (individual pin)
|
FSENSOR_INT_PIN_PCMSK_REG |= bit(FSENSOR_INT_PIN_PCMSK_BIT); // enable corresponding PinChangeInterrupt (individual pin)
|
||||||
PCIFR |= bit(FSENSOR_INT_PIN_PCICR_BIT); // clear previous occasional interrupt (set of pins)
|
PCIFR |= bit(FSENSOR_INT_PIN_PCICR_BIT); // clear previous occasional interrupt (set of pins)
|
||||||
PCICR |= bit(FSENSOR_INT_PIN_PCICR_BIT); // enable corresponding PinChangeInterrupt (set of pins)
|
PCICR |= bit(FSENSOR_INT_PIN_PCICR_BIT); // enable corresponding PinChangeInterrupt (set of pins)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,22 @@ uint8_t lang_selected = 0;
|
||||||
|
|
||||||
#if (LANG_MODE == 0) //primary language only
|
#if (LANG_MODE == 0) //primary language only
|
||||||
|
|
||||||
uint8_t lang_select(uint8_t lang) { return 0; }
|
uint8_t lang_select(uint8_t lang) {
|
||||||
uint8_t lang_get_count() { return 1; }
|
return 0;
|
||||||
uint16_t lang_get_code(uint8_t lang) { return LANG_CODE_EN; }
|
}
|
||||||
const char* lang_get_name_by_code(uint16_t code) { return _n("English"); }
|
uint8_t lang_get_count() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
uint16_t lang_get_code(uint8_t lang) {
|
||||||
|
return LANG_CODE_EN;
|
||||||
|
}
|
||||||
|
const char* lang_get_name_by_code(uint16_t code) {
|
||||||
|
return _n("English");
|
||||||
|
}
|
||||||
void lang_reset(void) { }
|
void lang_reset(void) { }
|
||||||
uint8_t lang_is_selected(void) { return 1; }
|
uint8_t lang_is_selected(void) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#else //(LANG_MODE == 0) //secondary languages in progmem or xflash
|
#else //(LANG_MODE == 0) //secondary languages in progmem or xflash
|
||||||
|
|
||||||
|
|
@ -37,227 +47,235 @@ lang_table_t* lang_table = 0;
|
||||||
|
|
||||||
const char* lang_get_translation(const char* s)
|
const char* lang_get_translation(const char* s)
|
||||||
{
|
{
|
||||||
if (lang_selected == 0) return s + 2; //primary language selected, return orig. str.
|
if (lang_selected == 0) return s + 2; //primary language selected, return orig. str.
|
||||||
if (lang_table == 0) return s + 2; //sec. lang table not found, return orig. str.
|
if (lang_table == 0) return s + 2; //sec. lang table not found, return orig. str.
|
||||||
uint16_t ui = pgm_read_word(((uint16_t*)s)); //read string id
|
uint16_t ui = pgm_read_word(((uint16_t*)s)); //read string id
|
||||||
if (ui == 0xffff) return s + 2; //translation not found, return orig. str.
|
if (ui == 0xffff) return s + 2; //translation not found, return orig. str.
|
||||||
ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16 + ui*2)))); //read relative offset
|
ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16 + ui*2)))); //read relative offset
|
||||||
if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0) //read first character
|
if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0) //read first character
|
||||||
return s + 2;//zero length string == not translated, return orig. str.
|
return s + 2;//zero length string == not translated, return orig. str.
|
||||||
return (const char*)((char*)lang_table + ui); //return calculated pointer
|
return (const char*)((char*)lang_table + ui); //return calculated pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t lang_select(uint8_t lang)
|
uint8_t lang_select(uint8_t lang)
|
||||||
{
|
{
|
||||||
if (lang == LANG_ID_PRI) //primary language
|
if (lang == LANG_ID_PRI) //primary language
|
||||||
{
|
{
|
||||||
lang_table = 0;
|
lang_table = 0;
|
||||||
lang_selected = lang;
|
lang_selected = lang;
|
||||||
}
|
}
|
||||||
#ifdef W25X20CL
|
#ifdef W25X20CL
|
||||||
if (lang_get_code(lang) == lang_get_code(LANG_ID_SEC)) lang = LANG_ID_SEC;
|
if (lang_get_code(lang) == lang_get_code(LANG_ID_SEC)) lang = LANG_ID_SEC;
|
||||||
if (lang == LANG_ID_SEC) //current secondary language
|
if (lang == LANG_ID_SEC) //current secondary language
|
||||||
{
|
{
|
||||||
if (pgm_read_dword(((uint32_t*)_SEC_LANG_TABLE)) == LANG_MAGIC) //magic valid
|
if (pgm_read_dword(((uint32_t*)_SEC_LANG_TABLE)) == LANG_MAGIC) //magic valid
|
||||||
{
|
{
|
||||||
if (lang_check(_SEC_LANG_TABLE))
|
if (lang_check(_SEC_LANG_TABLE))
|
||||||
if (pgm_read_dword(((uint32_t*)(_SEC_LANG_TABLE + 12))) == pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE)))) //signature valid
|
if (pgm_read_dword(((uint32_t*)(_SEC_LANG_TABLE + 12))) == pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE)))) //signature valid
|
||||||
{
|
{
|
||||||
lang_table = (lang_table_t*)(_SEC_LANG_TABLE); // set table pointer
|
lang_table = (lang_table_t*)(_SEC_LANG_TABLE); // set table pointer
|
||||||
lang_selected = lang; // set language id
|
lang_selected = lang; // set language id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else //W25X20CL
|
#else //W25X20CL
|
||||||
if (lang == LANG_ID_SEC)
|
if (lang == LANG_ID_SEC)
|
||||||
{
|
{
|
||||||
uint16_t table = _SEC_LANG_TABLE;
|
uint16_t table = _SEC_LANG_TABLE;
|
||||||
if (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid
|
if (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid
|
||||||
{
|
{
|
||||||
if (lang_check(table))
|
if (lang_check(table))
|
||||||
if (pgm_read_dword(((uint32_t*)(table + 12))) == pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE)))) //signature valid
|
if (pgm_read_dword(((uint32_t*)(table + 12))) == pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE)))) //signature valid
|
||||||
{
|
{
|
||||||
lang_table = table; // set table pointer
|
lang_table = table; // set table pointer
|
||||||
lang_selected = lang; // set language id
|
lang_selected = lang; // set language id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif //W25X20CL
|
#endif //W25X20CL
|
||||||
if (lang_selected == lang)
|
if (lang_selected == lang)
|
||||||
{
|
{
|
||||||
eeprom_update_byte((unsigned char*)EEPROM_LANG, lang_selected);
|
eeprom_update_byte((unsigned char*)EEPROM_LANG, lang_selected);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t lang_check(uint16_t addr)
|
uint8_t lang_check(uint16_t addr)
|
||||||
{
|
{
|
||||||
uint16_t sum = 0;
|
uint16_t sum = 0;
|
||||||
uint16_t size = pgm_read_word((uint16_t*)(addr + 4));
|
uint16_t size = pgm_read_word((uint16_t*)(addr + 4));
|
||||||
uint16_t lt_sum = pgm_read_word((uint16_t*)(addr + 8));
|
uint16_t lt_sum = pgm_read_word((uint16_t*)(addr + 8));
|
||||||
uint16_t i; for (i = 0; i < size; i++)
|
uint16_t i;
|
||||||
sum += (uint16_t)pgm_read_byte((uint8_t*)(addr + i)) << ((i & 1)?0:8);
|
for (i = 0; i < size; i++)
|
||||||
sum -= lt_sum; //subtract checksum
|
sum += (uint16_t)pgm_read_byte((uint8_t*)(addr + i)) << ((i & 1)?0:8);
|
||||||
sum = (sum >> 8) | ((sum & 0xff) << 8); //swap bytes
|
sum -= lt_sum; //subtract checksum
|
||||||
return (sum == lt_sum);
|
sum = (sum >> 8) | ((sum & 0xff) << 8); //swap bytes
|
||||||
|
return (sum == lt_sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t lang_get_count()
|
uint8_t lang_get_count()
|
||||||
{
|
{
|
||||||
if (pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE))) == 0xffffffff)
|
if (pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE))) == 0xffffffff)
|
||||||
return 1; //signature not set - only primary language will be available
|
return 1; //signature not set - only primary language will be available
|
||||||
#ifdef W25X20CL
|
#ifdef W25X20CL
|
||||||
W25X20CL_SPI_ENTER();
|
W25X20CL_SPI_ENTER();
|
||||||
uint8_t count = 2; //count = 1+n (primary + secondary + all in xflash)
|
uint8_t count = 2; //count = 1+n (primary + secondary + all in xflash)
|
||||||
uint32_t addr = 0x00000; //start of xflash
|
uint32_t addr = 0x00000; //start of xflash
|
||||||
lang_table_header_t header; //table header structure
|
lang_table_header_t header; //table header structure
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
||||||
if (header.magic != LANG_MAGIC) break; //break if magic not valid
|
if (header.magic != LANG_MAGIC) break; //break if magic not valid
|
||||||
addr += header.size; //calc address of next table
|
addr += header.size; //calc address of next table
|
||||||
count++; //inc counter
|
count++; //inc counter
|
||||||
}
|
}
|
||||||
#else //W25X20CL
|
#else //W25X20CL
|
||||||
uint16_t table = _SEC_LANG_TABLE;
|
uint16_t table = _SEC_LANG_TABLE;
|
||||||
uint8_t count = 1; //count = 1 (primary)
|
uint8_t count = 1; //count = 1 (primary)
|
||||||
while (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid
|
while (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid
|
||||||
{
|
{
|
||||||
table += pgm_read_word((uint16_t*)(table + 4));
|
table += pgm_read_word((uint16_t*)(table + 4));
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
#endif //W25X20CL
|
#endif //W25X20CL
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset)
|
uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset)
|
||||||
{
|
{
|
||||||
if (lang == LANG_ID_PRI) return 0; //primary lang not supported for this function
|
if (lang == LANG_ID_PRI) return 0; //primary lang not supported for this function
|
||||||
#ifdef W25X20CL
|
#ifdef W25X20CL
|
||||||
if (lang == LANG_ID_SEC)
|
if (lang == LANG_ID_SEC)
|
||||||
{
|
{
|
||||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||||
memcpy_P(header, (lang_table_t*)(_SEC_LANG_TABLE), sizeof(lang_table_header_t)); //read table header from progmem
|
memcpy_P(header, (lang_table_t*)(_SEC_LANG_TABLE), sizeof(lang_table_header_t)); //read table header from progmem
|
||||||
if (offset) *offset = ui;
|
if (offset) *offset = ui;
|
||||||
return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
|
return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
|
||||||
}
|
}
|
||||||
W25X20CL_SPI_ENTER();
|
W25X20CL_SPI_ENTER();
|
||||||
uint32_t addr = 0x00000; //start of xflash
|
uint32_t addr = 0x00000; //start of xflash
|
||||||
lang--;
|
lang--;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
w25x20cl_rd_data(addr, (uint8_t*)(header), sizeof(lang_table_header_t)); //read table header from xflash
|
w25x20cl_rd_data(addr, (uint8_t*)(header), sizeof(lang_table_header_t)); //read table header from xflash
|
||||||
if (header->magic != LANG_MAGIC) break; //break if not valid
|
if (header->magic != LANG_MAGIC) break; //break if not valid
|
||||||
if (offset) *offset = addr;
|
if (offset) *offset = addr;
|
||||||
if (--lang == 0) return 1;
|
if (--lang == 0) return 1;
|
||||||
addr += header->size; //calc address of next table
|
addr += header->size; //calc address of next table
|
||||||
}
|
}
|
||||||
#else //W25X20CL
|
#else //W25X20CL
|
||||||
if (lang == LANG_ID_SEC)
|
if (lang == LANG_ID_SEC)
|
||||||
{
|
{
|
||||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||||
memcpy_P(header, ui, sizeof(lang_table_header_t)); //read table header from progmem
|
memcpy_P(header, ui, sizeof(lang_table_header_t)); //read table header from progmem
|
||||||
if (offset) *offset = ui;
|
if (offset) *offset = ui;
|
||||||
return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
|
return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
|
||||||
}
|
}
|
||||||
#endif //W25X20CL
|
#endif //W25X20CL
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t lang_get_code(uint8_t lang)
|
uint16_t lang_get_code(uint8_t lang)
|
||||||
{
|
{
|
||||||
if (lang == LANG_ID_PRI) return LANG_CODE_EN; //primary lang = EN
|
if (lang == LANG_ID_PRI) return LANG_CODE_EN; //primary lang = EN
|
||||||
#ifdef W25X20CL
|
#ifdef W25X20CL
|
||||||
if (lang == LANG_ID_SEC)
|
if (lang == LANG_ID_SEC)
|
||||||
{
|
{
|
||||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||||
if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return LANG_CODE_XX; //magic not valid
|
if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return LANG_CODE_XX; //magic not valid
|
||||||
return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem
|
return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem
|
||||||
}
|
}
|
||||||
W25X20CL_SPI_ENTER();
|
W25X20CL_SPI_ENTER();
|
||||||
uint32_t addr = 0x00000; //start of xflash
|
uint32_t addr = 0x00000; //start of xflash
|
||||||
lang_table_header_t header; //table header structure
|
lang_table_header_t header; //table header structure
|
||||||
lang--;
|
lang--;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
||||||
if (header.magic != LANG_MAGIC) break; //break if not valid
|
if (header.magic != LANG_MAGIC) break; //break if not valid
|
||||||
if (--lang == 0) return header.code;
|
if (--lang == 0) return header.code;
|
||||||
addr += header.size; //calc address of next table
|
addr += header.size; //calc address of next table
|
||||||
}
|
}
|
||||||
#else //W25X20CL
|
#else //W25X20CL
|
||||||
uint16_t table = _SEC_LANG_TABLE;
|
uint16_t table = _SEC_LANG_TABLE;
|
||||||
uint8_t count = 1; //count = 1 (primary)
|
uint8_t count = 1; //count = 1 (primary)
|
||||||
while (pgm_read_dword((uint32_t*)table) == LANG_MAGIC) //magic valid
|
while (pgm_read_dword((uint32_t*)table) == LANG_MAGIC) //magic valid
|
||||||
{
|
{
|
||||||
if (count == lang) return pgm_read_word(((uint16_t*)(table + 10))); //read language code
|
if (count == lang) return pgm_read_word(((uint16_t*)(table + 10))); //read language code
|
||||||
table += pgm_read_word((uint16_t*)(table + 4));
|
table += pgm_read_word((uint16_t*)(table + 4));
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
#endif //W25X20CL
|
#endif //W25X20CL
|
||||||
return LANG_CODE_XX;
|
return LANG_CODE_XX;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* lang_get_name_by_code(uint16_t code)
|
const char* lang_get_name_by_code(uint16_t code)
|
||||||
{
|
{
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case LANG_CODE_EN: return _n("English");
|
case LANG_CODE_EN:
|
||||||
case LANG_CODE_CZ: return _n("Cestina");
|
return _n("English");
|
||||||
case LANG_CODE_DE: return _n("Deutsch");
|
case LANG_CODE_CZ:
|
||||||
case LANG_CODE_ES: return _n("Espanol");
|
return _n("Cestina");
|
||||||
case LANG_CODE_FR: return _n("Francais");
|
case LANG_CODE_DE:
|
||||||
case LANG_CODE_IT: return _n("Italiano");
|
return _n("Deutsch");
|
||||||
case LANG_CODE_PL: return _n("Polski");
|
case LANG_CODE_ES:
|
||||||
}
|
return _n("Espanol");
|
||||||
return _n("??");
|
case LANG_CODE_FR:
|
||||||
|
return _n("Francais");
|
||||||
|
case LANG_CODE_IT:
|
||||||
|
return _n("Italiano");
|
||||||
|
case LANG_CODE_PL:
|
||||||
|
return _n("Polski");
|
||||||
|
}
|
||||||
|
return _n("??");
|
||||||
}
|
}
|
||||||
|
|
||||||
void lang_reset(void)
|
void lang_reset(void)
|
||||||
{
|
{
|
||||||
lang_selected = 0;
|
lang_selected = 0;
|
||||||
eeprom_update_byte((unsigned char*)EEPROM_LANG, LANG_ID_FORCE_SELECTION);
|
eeprom_update_byte((unsigned char*)EEPROM_LANG, LANG_ID_FORCE_SELECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t lang_is_selected(void)
|
uint8_t lang_is_selected(void)
|
||||||
{
|
{
|
||||||
uint8_t lang_eeprom = eeprom_read_byte((unsigned char*)EEPROM_LANG);
|
uint8_t lang_eeprom = eeprom_read_byte((unsigned char*)EEPROM_LANG);
|
||||||
return (lang_eeprom != LANG_ID_FORCE_SELECTION) && (lang_eeprom == lang_selected);
|
return (lang_eeprom != LANG_ID_FORCE_SELECTION) && (lang_eeprom == lang_selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_SEC_LANG
|
#ifdef DEBUG_SEC_LANG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
const char* lang_get_sec_lang_str_by_id(uint16_t id)
|
const char* lang_get_sec_lang_str_by_id(uint16_t id)
|
||||||
{
|
{
|
||||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||||
return ui + pgm_read_word(((uint16_t*)(ui + 16 + id * 2))); //read relative offset and return calculated pointer
|
return ui + pgm_read_word(((uint16_t*)(ui + 16 + id * 2))); //read relative offset and return calculated pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t lang_print_sec_lang(FILE* out)
|
uint16_t lang_print_sec_lang(FILE* out)
|
||||||
{
|
{
|
||||||
printf_P(_n("&_SEC_LANG = 0x%04x\n"), &_SEC_LANG);
|
printf_P(_n("&_SEC_LANG = 0x%04x\n"), &_SEC_LANG);
|
||||||
printf_P(_n("sizeof(_SEC_LANG) = 0x%04x\n"), sizeof(_SEC_LANG));
|
printf_P(_n("sizeof(_SEC_LANG) = 0x%04x\n"), sizeof(_SEC_LANG));
|
||||||
uint16_t ptr_lang_table0 = ((uint16_t)(&_SEC_LANG) + 0xff) & 0xff00;
|
uint16_t ptr_lang_table0 = ((uint16_t)(&_SEC_LANG) + 0xff) & 0xff00;
|
||||||
printf_P(_n("&_lang_table0 = 0x%04x\n"), ptr_lang_table0);
|
printf_P(_n("&_lang_table0 = 0x%04x\n"), ptr_lang_table0);
|
||||||
uint32_t _lt_magic = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 0)));
|
uint32_t _lt_magic = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 0)));
|
||||||
uint16_t _lt_size = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 4)));
|
uint16_t _lt_size = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 4)));
|
||||||
uint16_t _lt_count = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 6)));
|
uint16_t _lt_count = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 6)));
|
||||||
uint16_t _lt_chsum = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 8)));
|
uint16_t _lt_chsum = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 8)));
|
||||||
uint16_t _lt_resv0 = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 10)));
|
uint16_t _lt_resv0 = pgm_read_word(((uint16_t*)(ptr_lang_table0 + 10)));
|
||||||
uint32_t _lt_resv1 = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 12)));
|
uint32_t _lt_resv1 = pgm_read_dword(((uint32_t*)(ptr_lang_table0 + 12)));
|
||||||
printf_P(_n(" _lt_magic = 0x%08lx %S\n"), _lt_magic, (_lt_magic==LANG_MAGIC)?_n("OK"):_n("NA"));
|
printf_P(_n(" _lt_magic = 0x%08lx %S\n"), _lt_magic, (_lt_magic==LANG_MAGIC)?_n("OK"):_n("NA"));
|
||||||
printf_P(_n(" _lt_size = 0x%04x (%d)\n"), _lt_size, _lt_size);
|
printf_P(_n(" _lt_size = 0x%04x (%d)\n"), _lt_size, _lt_size);
|
||||||
printf_P(_n(" _lt_count = 0x%04x (%d)\n"), _lt_count, _lt_count);
|
printf_P(_n(" _lt_count = 0x%04x (%d)\n"), _lt_count, _lt_count);
|
||||||
printf_P(_n(" _lt_chsum = 0x%04x\n"), _lt_chsum);
|
printf_P(_n(" _lt_chsum = 0x%04x\n"), _lt_chsum);
|
||||||
printf_P(_n(" _lt_resv0 = 0x%04x\n"), _lt_resv0);
|
printf_P(_n(" _lt_resv0 = 0x%04x\n"), _lt_resv0);
|
||||||
printf_P(_n(" _lt_resv1 = 0x%08lx\n"), _lt_resv1);
|
printf_P(_n(" _lt_resv1 = 0x%08lx\n"), _lt_resv1);
|
||||||
if (_lt_magic != LANG_MAGIC) return 0;
|
if (_lt_magic != LANG_MAGIC) return 0;
|
||||||
puts_P(_n(" strings:\n"));
|
puts_P(_n(" strings:\n"));
|
||||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||||
for (ui = 0; ui < _lt_count; ui++)
|
for (ui = 0; ui < _lt_count; ui++)
|
||||||
fprintf_P(out, _n(" %3d %S\n"), ui, lang_get_sec_lang_str_by_id(ui));
|
fprintf_P(out, _n(" %3d %S\n"), ui, lang_get_sec_lang_str_by_id(ui));
|
||||||
return _lt_count;
|
return _lt_count;
|
||||||
}
|
}
|
||||||
#endif //DEBUG_SEC_LANG
|
#endif //DEBUG_SEC_LANG
|
||||||
|
|
||||||
|
|
@ -266,7 +284,7 @@ uint16_t lang_print_sec_lang(FILE* out)
|
||||||
|
|
||||||
void lang_boot_update_start(uint8_t lang)
|
void lang_boot_update_start(uint8_t lang)
|
||||||
{
|
{
|
||||||
uint8_t cnt = lang_get_count();
|
uint8_t cnt = lang_get_count();
|
||||||
if ((lang < 2) || (lang > cnt)) return; //only languages from xflash can be selected
|
if ((lang < 2) || (lang > cnt)) return; //only languages from xflash can be selected
|
||||||
bootapp_reboot_user0(lang << 4);
|
bootapp_reboot_user0(lang << 4);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@
|
||||||
#define PROTOCOL_VERSION "1.0"
|
#define PROTOCOL_VERSION "1.0"
|
||||||
|
|
||||||
#ifndef CUSTOM_MENDEL_NAME
|
#ifndef CUSTOM_MENDEL_NAME
|
||||||
#define MACHINE_NAME "Mendel"
|
#define MACHINE_NAME "Mendel"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MACHINE_UUID
|
#ifndef MACHINE_UUID
|
||||||
#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
|
#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MSG_FW_VERSION "Firmware"
|
#define MSG_FW_VERSION "Firmware"
|
||||||
|
|
@ -49,19 +49,19 @@
|
||||||
/** @brief lang_table_header_t structure - (size= 16byte) */
|
/** @brief lang_table_header_t structure - (size= 16byte) */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t magic; //+0
|
uint32_t magic; //+0
|
||||||
uint16_t size; //+4
|
uint16_t size; //+4
|
||||||
uint16_t count; //+6
|
uint16_t count; //+6
|
||||||
uint16_t checksum; //+8
|
uint16_t checksum; //+8
|
||||||
uint16_t code; //+10
|
uint16_t code; //+10
|
||||||
uint32_t signature; //+12
|
uint32_t signature; //+12
|
||||||
} lang_table_header_t;
|
} lang_table_header_t;
|
||||||
|
|
||||||
/** @brief lang_table_t structure - (size= 16byte + 2*count) */
|
/** @brief lang_table_t structure - (size= 16byte + 2*count) */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
lang_table_header_t header;
|
lang_table_header_t header;
|
||||||
uint16_t table[];
|
uint16_t table[];
|
||||||
} lang_table_t;
|
} lang_table_t;
|
||||||
|
|
||||||
/** @name Language indices into their particular symbol tables.*/
|
/** @name Language indices into their particular symbol tables.*/
|
||||||
|
|
|
||||||
1111
Firmware/lcd.cpp
1111
Firmware/lcd.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -44,22 +44,22 @@ static_assert(sizeof(menu_data)>= sizeof(menu_data_edit_t),"menu_data_edit_t doe
|
||||||
|
|
||||||
void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
|
void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
|
||||||
{
|
{
|
||||||
asm("cli");
|
asm("cli");
|
||||||
if (menu_menu != menu)
|
if (menu_menu != menu)
|
||||||
{
|
{
|
||||||
menu_menu = menu;
|
menu_menu = menu;
|
||||||
lcd_encoder = encoder;
|
lcd_encoder = encoder;
|
||||||
asm("sei");
|
asm("sei");
|
||||||
if (reset_menu_state)
|
if (reset_menu_state)
|
||||||
{
|
{
|
||||||
// Resets the global shared C union.
|
// Resets the global shared C union.
|
||||||
// This ensures, that the menu entered will find out, that it shall initialize itself.
|
// This ensures, that the menu entered will find out, that it shall initialize itself.
|
||||||
memset(&menu_data, 0, sizeof(menu_data));
|
memset(&menu_data, 0, sizeof(menu_data));
|
||||||
}
|
}
|
||||||
if (feedback) lcd_quick_feedback();
|
if (feedback) lcd_quick_feedback();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
asm("sei");
|
asm("sei");
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_start(void)
|
void menu_start(void)
|
||||||
|
|
@ -67,83 +67,83 @@ void menu_start(void)
|
||||||
if (lcd_encoder > 0x8000) lcd_encoder = 0;
|
if (lcd_encoder > 0x8000) lcd_encoder = 0;
|
||||||
if (lcd_encoder < 0) lcd_encoder = 0;
|
if (lcd_encoder < 0) lcd_encoder = 0;
|
||||||
if (lcd_encoder < menu_top)
|
if (lcd_encoder < menu_top)
|
||||||
menu_top = lcd_encoder;
|
menu_top = lcd_encoder;
|
||||||
menu_line = menu_top;
|
menu_line = menu_top;
|
||||||
menu_clicked = LCD_CLICKED;
|
menu_clicked = LCD_CLICKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_end(void)
|
void menu_end(void)
|
||||||
{
|
{
|
||||||
if (lcd_encoder >= menu_item)
|
if (lcd_encoder >= menu_item)
|
||||||
lcd_encoder = menu_item - 1;
|
lcd_encoder = menu_item - 1;
|
||||||
if (((uint8_t)lcd_encoder) >= menu_top + LCD_HEIGHT)
|
if (((uint8_t)lcd_encoder) >= menu_top + LCD_HEIGHT)
|
||||||
{
|
{
|
||||||
menu_top = lcd_encoder - LCD_HEIGHT + 1;
|
menu_top = lcd_encoder - LCD_HEIGHT + 1;
|
||||||
lcd_draw_update = 1;
|
lcd_draw_update = 1;
|
||||||
menu_line = menu_top - 1;
|
menu_line = menu_top - 1;
|
||||||
menu_row = -1;
|
menu_row = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_back(void)
|
void menu_back(void)
|
||||||
{
|
{
|
||||||
if (menu_depth > 0)
|
if (menu_depth > 0)
|
||||||
{
|
{
|
||||||
menu_depth--;
|
menu_depth--;
|
||||||
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, true);
|
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void menu_back_no_reset(void)
|
static void menu_back_no_reset(void)
|
||||||
{
|
{
|
||||||
if (menu_depth > 0)
|
if (menu_depth > 0)
|
||||||
{
|
{
|
||||||
menu_depth--;
|
menu_depth--;
|
||||||
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, false);
|
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_back_if_clicked(void)
|
void menu_back_if_clicked(void)
|
||||||
{
|
{
|
||||||
if (lcd_clicked())
|
if (lcd_clicked())
|
||||||
menu_back();
|
menu_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_back_if_clicked_fb(void)
|
void menu_back_if_clicked_fb(void)
|
||||||
{
|
{
|
||||||
if (lcd_clicked())
|
if (lcd_clicked())
|
||||||
{
|
{
|
||||||
lcd_quick_feedback();
|
lcd_quick_feedback();
|
||||||
menu_back();
|
menu_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_submenu(menu_func_t submenu)
|
void menu_submenu(menu_func_t submenu)
|
||||||
{
|
{
|
||||||
if (menu_depth <= MENU_DEPTH_MAX)
|
if (menu_depth <= MENU_DEPTH_MAX)
|
||||||
{
|
{
|
||||||
menu_stack[menu_depth].menu = menu_menu;
|
menu_stack[menu_depth].menu = menu_menu;
|
||||||
menu_stack[menu_depth++].position = lcd_encoder;
|
menu_stack[menu_depth++].position = lcd_encoder;
|
||||||
menu_goto(submenu, 0, true, true);
|
menu_goto(submenu, 0, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void menu_submenu_no_reset(menu_func_t submenu)
|
static void menu_submenu_no_reset(menu_func_t submenu)
|
||||||
{
|
{
|
||||||
if (menu_depth <= MENU_DEPTH_MAX)
|
if (menu_depth <= MENU_DEPTH_MAX)
|
||||||
{
|
{
|
||||||
menu_stack[menu_depth].menu = menu_menu;
|
menu_stack[menu_depth].menu = menu_menu;
|
||||||
menu_stack[menu_depth++].position = lcd_encoder;
|
menu_stack[menu_depth++].position = lcd_encoder;
|
||||||
menu_goto(submenu, 0, true, false);
|
menu_goto(submenu, 0, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t menu_item_ret(void)
|
uint8_t menu_item_ret(void)
|
||||||
{
|
{
|
||||||
lcd_beeper_quick_feedback();
|
lcd_beeper_quick_feedback();
|
||||||
lcd_draw_update = 2;
|
lcd_draw_update = 2;
|
||||||
lcd_button_pressed = false;
|
lcd_button_pressed = false;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -169,8 +169,8 @@ int menu_draw_item_printf_P(char type_char, const char* format, ...)
|
||||||
static int menu_draw_item_puts_P(char type_char, const char* str)
|
static int menu_draw_item_puts_P(char type_char, const char* str)
|
||||||
{
|
{
|
||||||
lcd_set_cursor(0, menu_row);
|
lcd_set_cursor(0, menu_row);
|
||||||
int cnt = lcd_printf_P(PSTR("%c%-18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
|
int cnt = lcd_printf_P(PSTR("%c%-18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -184,83 +184,83 @@ int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, )
|
||||||
|
|
||||||
void menu_item_dummy(void)
|
void menu_item_dummy(void)
|
||||||
{
|
{
|
||||||
menu_item++;
|
menu_item++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t menu_item_text_P(const char* str)
|
uint8_t menu_item_text_P(const char* str)
|
||||||
{
|
{
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
return menu_item_ret();
|
return menu_item_ret();
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu)
|
uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu)
|
||||||
{
|
{
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update) menu_draw_item_puts_P(LCD_STR_ARROW_RIGHT[0], str);
|
if (lcd_draw_update) menu_draw_item_puts_P(LCD_STR_ARROW_RIGHT[0], str);
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
{
|
{
|
||||||
menu_submenu(submenu);
|
menu_submenu(submenu);
|
||||||
return menu_item_ret();
|
return menu_item_ret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t menu_item_back_P(const char* str)
|
uint8_t menu_item_back_P(const char* str)
|
||||||
{
|
{
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update) menu_draw_item_puts_P(LCD_STR_UPLEVEL[0], str);
|
if (lcd_draw_update) menu_draw_item_puts_P(LCD_STR_UPLEVEL[0], str);
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
{
|
{
|
||||||
menu_back();
|
menu_back();
|
||||||
return menu_item_ret();
|
return menu_item_ret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t menu_item_function_P(const char* str, menu_func_t func)
|
uint8_t menu_item_function_P(const char* str, menu_func_t func)
|
||||||
{
|
{
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
{
|
{
|
||||||
menu_clicked = false;
|
menu_clicked = false;
|
||||||
lcd_consume_click();
|
lcd_consume_click();
|
||||||
lcd_update_enabled = 0;
|
lcd_update_enabled = 0;
|
||||||
if (func) func();
|
if (func) func();
|
||||||
lcd_update_enabled = 1;
|
lcd_update_enabled = 1;
|
||||||
return menu_item_ret();
|
return menu_item_ret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t menu_item_gcode_P(const char* str, const char* str_gcode)
|
uint8_t menu_item_gcode_P(const char* str, const char* str_gcode)
|
||||||
{
|
{
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
{
|
{
|
||||||
if (str_gcode) enquecommand_P(str_gcode);
|
if (str_gcode) enquecommand_P(str_gcode);
|
||||||
return menu_item_ret();
|
return menu_item_ret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -280,12 +280,12 @@ static void menu_draw_P(char chr, const char* str, int16_t val);
|
||||||
template<>
|
template<>
|
||||||
void menu_draw_P<int16_t*>(char chr, const char* str, int16_t val)
|
void menu_draw_P<int16_t*>(char chr, const char* str, int16_t val)
|
||||||
{
|
{
|
||||||
int text_len = strlen_P(str);
|
int text_len = strlen_P(str);
|
||||||
if (text_len > 15) text_len = 15;
|
if (text_len > 15) text_len = 15;
|
||||||
char spaces[21];
|
char spaces[21];
|
||||||
strcpy_P(spaces, menu_20x_space);
|
strcpy_P(spaces, menu_20x_space);
|
||||||
spaces[15 - text_len] = 0;
|
spaces[15 - text_len] = 0;
|
||||||
lcd_printf_P(menu_fmt_int3, chr, str, spaces, val);
|
lcd_printf_P(menu_fmt_int3, chr, str, spaces, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
@ -312,67 +312,67 @@ void menu_draw_P<uint8_t*>(char chr, const char* str, int16_t val)
|
||||||
//draw up to 12 chars of text, ':' and float number in format +123.0
|
//draw up to 12 chars of text, ':' and float number in format +123.0
|
||||||
void menu_draw_float31(char chr, const char* str, float val)
|
void menu_draw_float31(char chr, const char* str, float val)
|
||||||
{
|
{
|
||||||
int text_len = strlen_P(str);
|
int text_len = strlen_P(str);
|
||||||
if (text_len > 12) text_len = 12;
|
if (text_len > 12) text_len = 12;
|
||||||
char spaces[21];
|
char spaces[21];
|
||||||
strcpy_P(spaces, menu_20x_space);
|
strcpy_P(spaces, menu_20x_space);
|
||||||
spaces[12 - text_len] = 0;
|
spaces[12 - text_len] = 0;
|
||||||
lcd_printf_P(menu_fmt_float31, chr, str, spaces, val);
|
lcd_printf_P(menu_fmt_float31, chr, str, spaces, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw up to 12 chars of text, ':' and float number in format +1.234
|
//draw up to 12 chars of text, ':' and float number in format +1.234
|
||||||
void menu_draw_float13(char chr, const char* str, float val)
|
void menu_draw_float13(char chr, const char* str, float val)
|
||||||
{
|
{
|
||||||
int text_len = strlen_P(str);
|
int text_len = strlen_P(str);
|
||||||
if (text_len > 12) text_len = 12;
|
if (text_len > 12) text_len = 12;
|
||||||
char spaces[21];
|
char spaces[21];
|
||||||
strcpy_P(spaces, menu_20x_space);
|
strcpy_P(spaces, menu_20x_space);
|
||||||
spaces[12 - text_len] = 0;
|
spaces[12 - text_len] = 0;
|
||||||
lcd_printf_P(menu_fmt_float13, chr, str, spaces, val);
|
lcd_printf_P(menu_fmt_float13, chr, str, spaces, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void _menu_edit_P(void)
|
static void _menu_edit_P(void)
|
||||||
{
|
{
|
||||||
menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
|
menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
|
||||||
if (lcd_draw_update)
|
if (lcd_draw_update)
|
||||||
{
|
{
|
||||||
if (lcd_encoder < _md->minEditValue) lcd_encoder = _md->minEditValue;
|
if (lcd_encoder < _md->minEditValue) lcd_encoder = _md->minEditValue;
|
||||||
if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
|
if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
|
||||||
lcd_set_cursor(0, 1);
|
lcd_set_cursor(0, 1);
|
||||||
menu_draw_P<T>(' ', _md->editLabel, (int)lcd_encoder);
|
menu_draw_P<T>(' ', _md->editLabel, (int)lcd_encoder);
|
||||||
}
|
}
|
||||||
if (LCD_CLICKED)
|
if (LCD_CLICKED)
|
||||||
{
|
{
|
||||||
*((T)(_md->editValue)) = lcd_encoder;
|
*((T)(_md->editValue)) = lcd_encoder;
|
||||||
menu_back_no_reset();
|
menu_back_no_reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val)
|
uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val)
|
||||||
{
|
{
|
||||||
menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
|
menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update)
|
if (lcd_draw_update)
|
||||||
{
|
{
|
||||||
lcd_set_cursor(0, menu_row);
|
lcd_set_cursor(0, menu_row);
|
||||||
menu_draw_P<T>((lcd_encoder == menu_item)?'>':' ', str, *pval);
|
menu_draw_P<T>((lcd_encoder == menu_item)?'>':' ', str, *pval);
|
||||||
}
|
}
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
{
|
{
|
||||||
menu_submenu_no_reset(_menu_edit_P<T>);
|
menu_submenu_no_reset(_menu_edit_P<T>);
|
||||||
_md->editLabel = str;
|
_md->editLabel = str;
|
||||||
_md->editValue = pval;
|
_md->editValue = pval;
|
||||||
_md->minEditValue = min_val;
|
_md->minEditValue = min_val;
|
||||||
_md->maxEditValue = max_val;
|
_md->maxEditValue = max_val;
|
||||||
lcd_encoder = *pval;
|
lcd_encoder = *pval;
|
||||||
return menu_item_ret();
|
return menu_item_ret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template uint8_t menu_item_edit_P<int16_t*>(const char* str, int16_t *pval, int16_t min_val, int16_t max_val);
|
template uint8_t menu_item_edit_P<int16_t*>(const char* str, int16_t *pval, int16_t min_val, int16_t max_val);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -13,9 +13,9 @@ extern const float bed_skew_angle_extreme;
|
||||||
// Is the world2machine correction activated?
|
// Is the world2machine correction activated?
|
||||||
enum World2MachineCorrectionMode
|
enum World2MachineCorrectionMode
|
||||||
{
|
{
|
||||||
WORLD2MACHINE_CORRECTION_NONE = 0,
|
WORLD2MACHINE_CORRECTION_NONE = 0,
|
||||||
WORLD2MACHINE_CORRECTION_SHIFT = 1,
|
WORLD2MACHINE_CORRECTION_SHIFT = 1,
|
||||||
WORLD2MACHINE_CORRECTION_SKEW = 2,
|
WORLD2MACHINE_CORRECTION_SKEW = 2,
|
||||||
};
|
};
|
||||||
extern uint8_t world2machine_correction_mode;
|
extern uint8_t world2machine_correction_mode;
|
||||||
// 2x2 transformation matrix from the world coordinates to the machine coordinates.
|
// 2x2 transformation matrix from the world coordinates to the machine coordinates.
|
||||||
|
|
@ -34,22 +34,22 @@ extern void world2machine_update_current();
|
||||||
|
|
||||||
inline void world2machine(float &x, float &y)
|
inline void world2machine(float &x, float &y)
|
||||||
{
|
{
|
||||||
if (world2machine_correction_mode == WORLD2MACHINE_CORRECTION_NONE) {
|
if (world2machine_correction_mode == WORLD2MACHINE_CORRECTION_NONE) {
|
||||||
// No correction.
|
// No correction.
|
||||||
} else {
|
} else {
|
||||||
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SKEW) {
|
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SKEW) {
|
||||||
// Firs the skew & rotation correction.
|
// Firs the skew & rotation correction.
|
||||||
float out_x = world2machine_rotation_and_skew[0][0] * x + world2machine_rotation_and_skew[0][1] * y;
|
float out_x = world2machine_rotation_and_skew[0][0] * x + world2machine_rotation_and_skew[0][1] * y;
|
||||||
float out_y = world2machine_rotation_and_skew[1][0] * x + world2machine_rotation_and_skew[1][1] * y;
|
float out_y = world2machine_rotation_and_skew[1][0] * x + world2machine_rotation_and_skew[1][1] * y;
|
||||||
x = out_x;
|
x = out_x;
|
||||||
y = out_y;
|
y = out_y;
|
||||||
}
|
}
|
||||||
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SHIFT) {
|
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SHIFT) {
|
||||||
// Then add the offset.
|
// Then add the offset.
|
||||||
x += world2machine_shift[0];
|
x += world2machine_shift[0];
|
||||||
y += world2machine_shift[1];
|
y += world2machine_shift[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void world2machine(const float &x, const float &y, float &out_x, float &out_y)
|
inline void world2machine(const float &x, const float &y, float &out_x, float &out_y)
|
||||||
|
|
@ -61,48 +61,48 @@ inline void world2machine(const float &x, const float &y, float &out_x, float &o
|
||||||
|
|
||||||
inline void machine2world(float x, float y, float &out_x, float &out_y)
|
inline void machine2world(float x, float y, float &out_x, float &out_y)
|
||||||
{
|
{
|
||||||
if (world2machine_correction_mode == WORLD2MACHINE_CORRECTION_NONE) {
|
if (world2machine_correction_mode == WORLD2MACHINE_CORRECTION_NONE) {
|
||||||
// No correction.
|
// No correction.
|
||||||
out_x = x;
|
out_x = x;
|
||||||
out_y = y;
|
out_y = y;
|
||||||
} else {
|
} else {
|
||||||
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SHIFT) {
|
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SHIFT) {
|
||||||
// Then add the offset.
|
// Then add the offset.
|
||||||
x -= world2machine_shift[0];
|
x -= world2machine_shift[0];
|
||||||
y -= world2machine_shift[1];
|
y -= world2machine_shift[1];
|
||||||
}
|
}
|
||||||
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SKEW) {
|
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SKEW) {
|
||||||
// Firs the skew & rotation correction.
|
// Firs the skew & rotation correction.
|
||||||
out_x = world2machine_rotation_and_skew_inv[0][0] * x + world2machine_rotation_and_skew_inv[0][1] * y;
|
out_x = world2machine_rotation_and_skew_inv[0][0] * x + world2machine_rotation_and_skew_inv[0][1] * y;
|
||||||
out_y = world2machine_rotation_and_skew_inv[1][0] * x + world2machine_rotation_and_skew_inv[1][1] * y;
|
out_y = world2machine_rotation_and_skew_inv[1][0] * x + world2machine_rotation_and_skew_inv[1][1] * y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void machine2world(float &x, float &y)
|
inline void machine2world(float &x, float &y)
|
||||||
{
|
{
|
||||||
if (world2machine_correction_mode == WORLD2MACHINE_CORRECTION_NONE) {
|
if (world2machine_correction_mode == WORLD2MACHINE_CORRECTION_NONE) {
|
||||||
// No correction.
|
// No correction.
|
||||||
} else {
|
} else {
|
||||||
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SHIFT) {
|
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SHIFT) {
|
||||||
// Then add the offset.
|
// Then add the offset.
|
||||||
x -= world2machine_shift[0];
|
x -= world2machine_shift[0];
|
||||||
y -= world2machine_shift[1];
|
y -= world2machine_shift[1];
|
||||||
}
|
}
|
||||||
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SKEW) {
|
if (world2machine_correction_mode & WORLD2MACHINE_CORRECTION_SKEW) {
|
||||||
// Firs the skew & rotation correction.
|
// Firs the skew & rotation correction.
|
||||||
float out_x = world2machine_rotation_and_skew_inv[0][0] * x + world2machine_rotation_and_skew_inv[0][1] * y;
|
float out_x = world2machine_rotation_and_skew_inv[0][0] * x + world2machine_rotation_and_skew_inv[0][1] * y;
|
||||||
float out_y = world2machine_rotation_and_skew_inv[1][0] * x + world2machine_rotation_and_skew_inv[1][1] * y;
|
float out_y = world2machine_rotation_and_skew_inv[1][0] * x + world2machine_rotation_and_skew_inv[1][1] * y;
|
||||||
x = out_x;
|
x = out_x;
|
||||||
y = out_y;
|
y = out_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool world2machine_clamp(float &x, float &y)
|
inline bool world2machine_clamp(float &x, float &y)
|
||||||
{
|
{
|
||||||
bool clamped = false;
|
bool clamped = false;
|
||||||
float tmpx, tmpy;
|
float tmpx, tmpy;
|
||||||
world2machine(x, y, tmpx, tmpy);
|
world2machine(x, y, tmpx, tmpy);
|
||||||
if (tmpx < X_MIN_POS) {
|
if (tmpx < X_MIN_POS) {
|
||||||
tmpx = X_MIN_POS;
|
tmpx = X_MIN_POS;
|
||||||
|
|
@ -137,14 +137,14 @@ extern void go_home_with_z_lift();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum BedSkewOffsetDetectionResultType {
|
enum BedSkewOffsetDetectionResultType {
|
||||||
// Detection failed, some point was not found.
|
// Detection failed, some point was not found.
|
||||||
BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND = -1, //!< Point not found.
|
BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND = -1, //!< Point not found.
|
||||||
BED_SKEW_OFFSET_DETECTION_FITTING_FAILED = -2, //!< Fitting failed
|
BED_SKEW_OFFSET_DETECTION_FITTING_FAILED = -2, //!< Fitting failed
|
||||||
|
|
||||||
// Detection finished with success.
|
// Detection finished with success.
|
||||||
BED_SKEW_OFFSET_DETECTION_PERFECT = 0, //!< Perfect.
|
BED_SKEW_OFFSET_DETECTION_PERFECT = 0, //!< Perfect.
|
||||||
BED_SKEW_OFFSET_DETECTION_SKEW_MILD = 1, //!< Mildly skewed.
|
BED_SKEW_OFFSET_DETECTION_SKEW_MILD = 1, //!< Mildly skewed.
|
||||||
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2 //!< Extremely skewed.
|
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2 //!< Extremely skewed.
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask);
|
extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
mesh_bed_leveling mbl;
|
mesh_bed_leveling mbl;
|
||||||
|
|
||||||
mesh_bed_leveling::mesh_bed_leveling() { reset(); }
|
mesh_bed_leveling::mesh_bed_leveling() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
void mesh_bed_leveling::reset() {
|
void mesh_bed_leveling::reset() {
|
||||||
active = 0;
|
active = 0;
|
||||||
|
|
@ -116,16 +118,16 @@ void mesh_bed_leveling::upsample_3x3()
|
||||||
if (i == idx1)
|
if (i == idx1)
|
||||||
continue;
|
continue;
|
||||||
float x = get_x(i);
|
float x = get_x(i);
|
||||||
#ifdef MBL_BILINEAR
|
#ifdef MBL_BILINEAR
|
||||||
z_values[j][i] = (x < x1) ?
|
z_values[j][i] = (x < x1) ?
|
||||||
((z_values[j][idx0] * (x - x0) + z_values[j][idx1] * (x1 - x)) / (x1 - x0)) :
|
((z_values[j][idx0] * (x - x0) + z_values[j][idx1] * (x1 - x)) / (x1 - x0)) :
|
||||||
((z_values[j][idx1] * (x - x1) + z_values[j][idx2] * (x2 - x)) / (x2 - x1));
|
((z_values[j][idx1] * (x - x1) + z_values[j][idx2] * (x2 - x)) / (x2 - x1));
|
||||||
#else
|
#else
|
||||||
z_values[j][i] =
|
z_values[j][i] =
|
||||||
z_values[j][idx0] * (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2)) +
|
z_values[j][idx0] * (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2)) +
|
||||||
z_values[j][idx1] * (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2)) +
|
z_values[j][idx1] * (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2)) +
|
||||||
z_values[j][idx2] * (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1));
|
z_values[j][idx2] * (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -143,36 +145,36 @@ void mesh_bed_leveling::upsample_3x3()
|
||||||
if (j == idx1)
|
if (j == idx1)
|
||||||
continue;
|
continue;
|
||||||
float y = get_y(j);
|
float y = get_y(j);
|
||||||
#ifdef MBL_BILINEAR
|
#ifdef MBL_BILINEAR
|
||||||
z_values[j][i] = (y < y1) ?
|
z_values[j][i] = (y < y1) ?
|
||||||
((z_values[idx0][i] * (y - y0) + z_values[idx1][i] * (y1 - y)) / (y1 - y0)) :
|
((z_values[idx0][i] * (y - y0) + z_values[idx1][i] * (y1 - y)) / (y1 - y0)) :
|
||||||
((z_values[idx1][i] * (y - y1) + z_values[idx2][i] * (y2 - y)) / (y2 - y1));
|
((z_values[idx1][i] * (y - y1) + z_values[idx2][i] * (y2 - y)) / (y2 - y1));
|
||||||
#else
|
#else
|
||||||
z_values[j][i] =
|
z_values[j][i] =
|
||||||
z_values[idx0][i] * (y - y1) * (y - y2) / ((y0 - y1) * (y0 - y2)) +
|
z_values[idx0][i] * (y - y1) * (y - y2) / ((y0 - y1) * (y0 - y2)) +
|
||||||
z_values[idx1][i] * (y - y0) * (y - y2) / ((y1 - y0) * (y1 - y2)) +
|
z_values[idx1][i] * (y - y0) * (y - y2) / ((y1 - y0) * (y1 - y2)) +
|
||||||
z_values[idx2][i] * (y - y0) * (y - y1) / ((y2 - y0) * (y2 - y1));
|
z_values[idx2][i] * (y - y0) * (y - y1) / ((y2 - y0) * (y2 - y1));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Relax the non-measured points.
|
// Relax the non-measured points.
|
||||||
const float weight = 0.2f;
|
const float weight = 0.2f;
|
||||||
for (uint8_t iter = 0; iter < 20; ++ iter) {
|
for (uint8_t iter = 0; iter < 20; ++ iter) {
|
||||||
for (int8_t j = 1; j < 6; ++ j) {
|
for (int8_t j = 1; j < 6; ++ j) {
|
||||||
for (int8_t i = 1; i < 6; ++ i) {
|
for (int8_t i = 1; i < 6; ++ i) {
|
||||||
if (i == 3 || j == 3)
|
if (i == 3 || j == 3)
|
||||||
continue;
|
continue;
|
||||||
if ((i % 3) == 0 && (j % 3) == 0)
|
if ((i % 3) == 0 && (j % 3) == 0)
|
||||||
continue;
|
continue;
|
||||||
float avg = 0.25f * (z_values[j][i-1]+z_values[j][i+1]+z_values[j-1][i]+z_values[j+1][i]);
|
float avg = 0.25f * (z_values[j][i-1]+z_values[j][i+1]+z_values[j-1][i]+z_values[j+1][i]);
|
||||||
z_values[j][i] = (1.f-weight)*z_values[j][i] + weight*avg;
|
z_values[j][i] = (1.f-weight)*z_values[j][i] + weight*avg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,21 @@ public:
|
||||||
void upsample_3x3();
|
void upsample_3x3();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); }
|
static float get_x(int i) {
|
||||||
static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); }
|
return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i);
|
||||||
|
}
|
||||||
|
static float get_y(int i) {
|
||||||
|
return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i);
|
||||||
|
}
|
||||||
|
|
||||||
// Measurement point for the Z probe.
|
// Measurement point for the Z probe.
|
||||||
// If use_default=true, then the default positions for a correctly built printer are used.
|
// If use_default=true, then the default positions for a correctly built printer are used.
|
||||||
// Otherwise a correction matrix is pulled from the EEPROM if available.
|
// Otherwise a correction matrix is pulled from the EEPROM if available.
|
||||||
static void get_meas_xy(int ix, int iy, float &x, float &y, bool use_default);
|
static void get_meas_xy(int ix, int iy, float &x, float &y, bool use_default);
|
||||||
|
|
||||||
void set_z(int ix, int iy, float z) { z_values[iy][ix] = z; }
|
void set_z(int ix, int iy, float z) {
|
||||||
|
z_values[iy][ix] = z;
|
||||||
|
}
|
||||||
|
|
||||||
int select_x_index(float x) {
|
int select_x_index(float x) {
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
|
||||||
389
Firmware/mmu.cpp
389
Firmware/mmu.cpp
|
|
@ -424,7 +424,7 @@ void mmu_loop(void)
|
||||||
mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
|
mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
|
||||||
mmu_state = 2;
|
mmu_state = 2;
|
||||||
} else if (((mmu_last_response + 500) < millis()) && mmuFSensorLoading) {
|
} else if (((mmu_last_response + 500) < millis()) && mmuFSensorLoading) {
|
||||||
if (!fsensor_enabled) fsensor_enable();
|
if (!fsensor_enabled) fsensor_enable();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 2: //response to command P0
|
case 2: //response to command P0
|
||||||
|
|
@ -432,10 +432,10 @@ void mmu_loop(void)
|
||||||
{
|
{
|
||||||
fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
|
fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
|
||||||
if (!mmu_finda && CHECK_FINDA && fsensor_enabled) {
|
if (!mmu_finda && CHECK_FINDA && fsensor_enabled) {
|
||||||
fsensor_stop_and_save_print();
|
fsensor_stop_and_save_print();
|
||||||
enquecommand_front_P(PSTR("FSENSOR_RECOVER")); //then recover
|
enquecommand_front_P(PSTR("FSENSOR_RECOVER")); //then recover
|
||||||
if (lcd_autoDepleteEnabled()) enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command
|
if (lcd_autoDepleteEnabled()) enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command
|
||||||
else enquecommand_front_P(PSTR("M600")); //save print and run M600 command
|
else enquecommand_front_P(PSTR("M600")); //save print and run M600 command
|
||||||
}
|
}
|
||||||
mmu_state = 1;
|
mmu_state = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -503,16 +503,16 @@ int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament)
|
||||||
void mmu_command(uint8_t cmd)
|
void mmu_command(uint8_t cmd)
|
||||||
{
|
{
|
||||||
#ifdef TMC2130
|
#ifdef TMC2130
|
||||||
if ((cmd >= MMU_CMD_T0) && (cmd <= MMU_CMD_T4))
|
if ((cmd >= MMU_CMD_T0) && (cmd <= MMU_CMD_T4))
|
||||||
{
|
{
|
||||||
//disable extruder motor
|
//disable extruder motor
|
||||||
tmc2130_set_pwr(E_AXIS, 0);
|
tmc2130_set_pwr(E_AXIS, 0);
|
||||||
//printf_P(PSTR("E-axis disabled\n"));
|
//printf_P(PSTR("E-axis disabled\n"));
|
||||||
}
|
}
|
||||||
#endif //TMC2130
|
#endif //TMC2130
|
||||||
|
|
||||||
mmu_cmd = cmd;
|
mmu_cmd = cmd;
|
||||||
mmu_ready = false;
|
mmu_ready = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mmu_get_response(void)
|
bool mmu_get_response(void)
|
||||||
|
|
@ -537,120 +537,120 @@ bool mmu_get_response(void)
|
||||||
|
|
||||||
void manage_response(bool move_axes, bool turn_off_nozzle)
|
void manage_response(bool move_axes, bool turn_off_nozzle)
|
||||||
{
|
{
|
||||||
bool response = false;
|
bool response = false;
|
||||||
mmu_print_saved = false;
|
mmu_print_saved = false;
|
||||||
bool lcd_update_was_enabled = false;
|
bool lcd_update_was_enabled = false;
|
||||||
float hotend_temp_bckp = degTargetHotend(active_extruder);
|
float hotend_temp_bckp = degTargetHotend(active_extruder);
|
||||||
float z_position_bckp = current_position[Z_AXIS];
|
float z_position_bckp = current_position[Z_AXIS];
|
||||||
float x_position_bckp = current_position[X_AXIS];
|
float x_position_bckp = current_position[X_AXIS];
|
||||||
float y_position_bckp = current_position[Y_AXIS];
|
float y_position_bckp = current_position[Y_AXIS];
|
||||||
uint8_t screen = 0; //used for showing multiscreen messages
|
uint8_t screen = 0; //used for showing multiscreen messages
|
||||||
while(!response)
|
while(!response)
|
||||||
{
|
{
|
||||||
response = mmu_get_response(); //wait for "ok" from mmu
|
response = mmu_get_response(); //wait for "ok" from mmu
|
||||||
if (!response) { //no "ok" was received in reserved time frame, user will fix the issue on mmu unit
|
if (!response) { //no "ok" was received in reserved time frame, user will fix the issue on mmu unit
|
||||||
if (!mmu_print_saved) { //first occurence, we are saving current position, park print head in certain position and disable nozzle heater
|
if (!mmu_print_saved) { //first occurence, we are saving current position, park print head in certain position and disable nozzle heater
|
||||||
if (lcd_update_enabled) {
|
if (lcd_update_enabled) {
|
||||||
lcd_update_was_enabled = true;
|
lcd_update_was_enabled = true;
|
||||||
lcd_update_enable(false);
|
lcd_update_enable(false);
|
||||||
}
|
}
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
mmu_print_saved = true;
|
mmu_print_saved = true;
|
||||||
printf_P(PSTR("MMU not responding\n"));
|
printf_P(PSTR("MMU not responding\n"));
|
||||||
hotend_temp_bckp = degTargetHotend(active_extruder);
|
hotend_temp_bckp = degTargetHotend(active_extruder);
|
||||||
if (move_axes) {
|
if (move_axes) {
|
||||||
z_position_bckp = current_position[Z_AXIS];
|
z_position_bckp = current_position[Z_AXIS];
|
||||||
x_position_bckp = current_position[X_AXIS];
|
x_position_bckp = current_position[X_AXIS];
|
||||||
y_position_bckp = current_position[Y_AXIS];
|
y_position_bckp = current_position[Y_AXIS];
|
||||||
|
|
||||||
//lift z
|
//lift z
|
||||||
current_position[Z_AXIS] += Z_PAUSE_LIFT;
|
current_position[Z_AXIS] += Z_PAUSE_LIFT;
|
||||||
if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
|
if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
|
||||||
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
|
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
|
|
||||||
//Move XY to side
|
//Move XY to side
|
||||||
current_position[X_AXIS] = X_PAUSE_POS;
|
current_position[X_AXIS] = X_PAUSE_POS;
|
||||||
current_position[Y_AXIS] = Y_PAUSE_POS;
|
current_position[Y_AXIS] = Y_PAUSE_POS;
|
||||||
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
|
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
}
|
}
|
||||||
if (turn_off_nozzle) {
|
if (turn_off_nozzle) {
|
||||||
//set nozzle target temperature to 0
|
//set nozzle target temperature to 0
|
||||||
setAllTargetHotends(0);
|
setAllTargetHotends(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//first three lines are used for printing multiscreen message; last line contains measured and target nozzle temperature
|
//first three lines are used for printing multiscreen message; last line contains measured and target nozzle temperature
|
||||||
if (screen == 0) { //screen 0
|
if (screen == 0) { //screen 0
|
||||||
lcd_display_message_fullscreen_P(_i("MMU needs user attention."));
|
lcd_display_message_fullscreen_P(_i("MMU needs user attention."));
|
||||||
screen++;
|
screen++;
|
||||||
}
|
}
|
||||||
else if (screen == 1) { //screen 1
|
else if (screen == 1) { //screen 1
|
||||||
if((degTargetHotend(active_extruder) == 0) && turn_off_nozzle) lcd_display_message_fullscreen_P(_i("Press the knob to resume nozzle temperature."));
|
if((degTargetHotend(active_extruder) == 0) && turn_off_nozzle) lcd_display_message_fullscreen_P(_i("Press the knob to resume nozzle temperature."));
|
||||||
else lcd_display_message_fullscreen_P(_i("Fix the issue and then press button on MMU unit."));
|
else lcd_display_message_fullscreen_P(_i("Fix the issue and then press button on MMU unit."));
|
||||||
screen = 0;
|
screen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcd_set_degree();
|
lcd_set_degree();
|
||||||
lcd_set_cursor(0, 4); //line 4
|
lcd_set_cursor(0, 4); //line 4
|
||||||
//Print the hotend temperature (9 chars total) and fill rest of the line with space
|
//Print the hotend temperature (9 chars total) and fill rest of the line with space
|
||||||
int chars = lcd_printf_P(_N("%c%3d/%d%c"), LCD_STR_THERMOMETER[0],(int)(degHotend(active_extruder) + 0.5), (int)(degTargetHotend(active_extruder) + 0.5), LCD_STR_DEGREE[0]);
|
int chars = lcd_printf_P(_N("%c%3d/%d%c"), LCD_STR_THERMOMETER[0],(int)(degHotend(active_extruder) + 0.5), (int)(degTargetHotend(active_extruder) + 0.5), LCD_STR_DEGREE[0]);
|
||||||
lcd_space(9 - chars);
|
lcd_space(9 - chars);
|
||||||
|
|
||||||
|
|
||||||
//5 seconds delay
|
//5 seconds delay
|
||||||
for (uint8_t i = 0; i < 50; i++) {
|
for (uint8_t i = 0; i < 50; i++) {
|
||||||
if (lcd_clicked()) {
|
if (lcd_clicked()) {
|
||||||
setTargetHotend(hotend_temp_bckp, active_extruder);
|
setTargetHotend(hotend_temp_bckp, active_extruder);
|
||||||
if (mmuFSensorLoading) {
|
if (mmuFSensorLoading) {
|
||||||
if (!fsensor_enabled) fsensor_enable();
|
if (!fsensor_enabled) fsensor_enable();
|
||||||
if (!fsensor_autoload_enabled) fsensor_autoload_enabled = true;
|
if (!fsensor_autoload_enabled) fsensor_autoload_enabled = true;
|
||||||
fsensor_autoload_check_stop();
|
fsensor_autoload_check_stop();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay_keep_alive(100);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
delay_keep_alive(100);
|
|
||||||
}
|
}
|
||||||
}
|
else if (mmu_print_saved) {
|
||||||
else if (mmu_print_saved) {
|
printf_P(PSTR("MMU starts responding\n"));
|
||||||
printf_P(PSTR("MMU starts responding\n"));
|
if (turn_off_nozzle)
|
||||||
if (turn_off_nozzle)
|
{
|
||||||
{
|
lcd_clear();
|
||||||
lcd_clear();
|
setTargetHotend(hotend_temp_bckp, active_extruder);
|
||||||
setTargetHotend(hotend_temp_bckp, active_extruder);
|
if (((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5)) {
|
||||||
if (((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5)) {
|
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature..."));
|
||||||
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature..."));
|
delay_keep_alive(3000);
|
||||||
delay_keep_alive(3000);
|
}
|
||||||
|
while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5)
|
||||||
|
{
|
||||||
|
delay_keep_alive(1000);
|
||||||
|
lcd_wait_for_heater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (move_axes) {
|
||||||
|
lcd_clear();
|
||||||
|
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming position..."));
|
||||||
|
current_position[X_AXIS] = x_position_bckp;
|
||||||
|
current_position[Y_AXIS] = y_position_bckp;
|
||||||
|
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
|
||||||
|
st_synchronize();
|
||||||
|
current_position[Z_AXIS] = z_position_bckp;
|
||||||
|
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
|
||||||
|
st_synchronize();
|
||||||
|
} else {
|
||||||
|
lcd_clear();
|
||||||
|
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming..."));
|
||||||
|
delay_keep_alive(1000); //delay just for showing MMU OK message for a while in case that there are no xyz movements
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5)
|
}
|
||||||
{
|
if (lcd_update_was_enabled) lcd_update_enable(true);
|
||||||
delay_keep_alive(1000);
|
|
||||||
lcd_wait_for_heater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (move_axes) {
|
|
||||||
lcd_clear();
|
|
||||||
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming position..."));
|
|
||||||
current_position[X_AXIS] = x_position_bckp;
|
|
||||||
current_position[Y_AXIS] = y_position_bckp;
|
|
||||||
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
|
|
||||||
st_synchronize();
|
|
||||||
current_position[Z_AXIS] = z_position_bckp;
|
|
||||||
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
|
|
||||||
st_synchronize();
|
|
||||||
} else {
|
|
||||||
lcd_clear();
|
|
||||||
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming..."));
|
|
||||||
delay_keep_alive(1000); //delay just for showing MMU OK message for a while in case that there are no xyz movements
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lcd_update_was_enabled) lcd_update_enable(true);
|
|
||||||
#ifdef TMC2130
|
#ifdef TMC2130
|
||||||
//enable extruder motor (disabled in mmu_command, start of T-code processing)
|
//enable extruder motor (disabled in mmu_command, start of T-code processing)
|
||||||
tmc2130_set_pwr(E_AXIS, 1);
|
tmc2130_set_pwr(E_AXIS, 1);
|
||||||
//printf_P(PSTR("E-axis enabled\n"));
|
//printf_P(PSTR("E-axis enabled\n"));
|
||||||
#endif //TMC2130
|
#endif //TMC2130
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -748,12 +748,12 @@ void mmu_M600_load_filament(bool automatic)
|
||||||
// mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
|
// mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
|
||||||
mmu_command(MMU_CMD_T0 + tmp_extruder);
|
mmu_command(MMU_CMD_T0 + tmp_extruder);
|
||||||
|
|
||||||
manage_response(false, true);
|
manage_response(false, true);
|
||||||
mmu_command(MMU_CMD_C0);
|
mmu_command(MMU_CMD_C0);
|
||||||
mmu_extruder = tmp_extruder; //filament change is finished
|
mmu_extruder = tmp_extruder; //filament change is finished
|
||||||
mmu_load_to_nozzle();
|
mmu_load_to_nozzle();
|
||||||
load_filament_final_feed();
|
load_filament_final_feed();
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1031,12 +1031,12 @@ void extr_unload()
|
||||||
lcd_return_to_status();
|
lcd_return_to_status();
|
||||||
max_feedrate[E_AXIS] = 50;
|
max_feedrate[E_AXIS] = 50;
|
||||||
#endif //SNMM
|
#endif //SNMM
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
show_preheat_nozzle_warning();
|
show_preheat_nozzle_warning();
|
||||||
}
|
}
|
||||||
//lcd_return_to_status();
|
//lcd_return_to_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
//wrapper functions for loading filament
|
//wrapper functions for loading filament
|
||||||
|
|
@ -1092,27 +1092,27 @@ void extr_adj_4()
|
||||||
|
|
||||||
void mmu_load_to_nozzle_0()
|
void mmu_load_to_nozzle_0()
|
||||||
{
|
{
|
||||||
lcd_mmu_load_to_nozzle(0);
|
lcd_mmu_load_to_nozzle(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmu_load_to_nozzle_1()
|
void mmu_load_to_nozzle_1()
|
||||||
{
|
{
|
||||||
lcd_mmu_load_to_nozzle(1);
|
lcd_mmu_load_to_nozzle(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmu_load_to_nozzle_2()
|
void mmu_load_to_nozzle_2()
|
||||||
{
|
{
|
||||||
lcd_mmu_load_to_nozzle(2);
|
lcd_mmu_load_to_nozzle(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmu_load_to_nozzle_3()
|
void mmu_load_to_nozzle_3()
|
||||||
{
|
{
|
||||||
lcd_mmu_load_to_nozzle(3);
|
lcd_mmu_load_to_nozzle(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmu_load_to_nozzle_4()
|
void mmu_load_to_nozzle_4()
|
||||||
{
|
{
|
||||||
lcd_mmu_load_to_nozzle(4);
|
lcd_mmu_load_to_nozzle(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmu_eject_fil_0()
|
void mmu_eject_fil_0()
|
||||||
|
|
@ -1186,37 +1186,37 @@ void extr_change_3()
|
||||||
//wrapper functions for unloading filament
|
//wrapper functions for unloading filament
|
||||||
void extr_unload_all()
|
void extr_unload_all()
|
||||||
{
|
{
|
||||||
if (degHotend0() > EXTRUDE_MINTEMP)
|
if (degHotend0() > EXTRUDE_MINTEMP)
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
{
|
||||||
change_extr(i);
|
for (int i = 0; i < 4; i++)
|
||||||
extr_unload();
|
{
|
||||||
|
change_extr(i);
|
||||||
|
extr_unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
show_preheat_nozzle_warning();
|
||||||
|
lcd_return_to_status();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
show_preheat_nozzle_warning();
|
|
||||||
lcd_return_to_status();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//unloading just used filament (for snmm)
|
//unloading just used filament (for snmm)
|
||||||
void extr_unload_used()
|
void extr_unload_used()
|
||||||
{
|
{
|
||||||
if (degHotend0() > EXTRUDE_MINTEMP) {
|
if (degHotend0() > EXTRUDE_MINTEMP) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (snmm_filaments_used & (1 << i)) {
|
if (snmm_filaments_used & (1 << i)) {
|
||||||
change_extr(i);
|
change_extr(i);
|
||||||
extr_unload();
|
extr_unload();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
snmm_filaments_used = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
show_preheat_nozzle_warning();
|
||||||
|
lcd_return_to_status();
|
||||||
}
|
}
|
||||||
snmm_filaments_used = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
show_preheat_nozzle_warning();
|
|
||||||
lcd_return_to_status();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif //SNMM
|
#endif //SNMM
|
||||||
|
|
||||||
|
|
@ -1263,33 +1263,34 @@ void mmu_show_warning()
|
||||||
|
|
||||||
void lcd_mmu_load_to_nozzle(uint8_t filament_nr)
|
void lcd_mmu_load_to_nozzle(uint8_t filament_nr)
|
||||||
{
|
{
|
||||||
if (degHotend0() > EXTRUDE_MINTEMP)
|
if (degHotend0() > EXTRUDE_MINTEMP)
|
||||||
{
|
{
|
||||||
tmp_extruder = filament_nr;
|
tmp_extruder = filament_nr;
|
||||||
lcd_update_enable(false);
|
lcd_update_enable(false);
|
||||||
lcd_clear();
|
lcd_clear();
|
||||||
lcd_set_cursor(0, 1); lcd_puts_P(_T(MSG_LOADING_FILAMENT));
|
lcd_set_cursor(0, 1);
|
||||||
lcd_print(" ");
|
lcd_puts_P(_T(MSG_LOADING_FILAMENT));
|
||||||
lcd_print(tmp_extruder + 1);
|
lcd_print(" ");
|
||||||
mmu_command(MMU_CMD_T0 + tmp_extruder);
|
lcd_print(tmp_extruder + 1);
|
||||||
manage_response(true, true);
|
mmu_command(MMU_CMD_T0 + tmp_extruder);
|
||||||
mmu_command(MMU_CMD_C0);
|
manage_response(true, true);
|
||||||
mmu_extruder = tmp_extruder; //filament change is finished
|
mmu_command(MMU_CMD_C0);
|
||||||
mmu_load_to_nozzle();
|
mmu_extruder = tmp_extruder; //filament change is finished
|
||||||
load_filament_final_feed();
|
mmu_load_to_nozzle();
|
||||||
st_synchronize();
|
load_filament_final_feed();
|
||||||
custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
|
st_synchronize();
|
||||||
lcd_setstatuspgm(_T(MSG_LOADING_FILAMENT));
|
custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
|
||||||
lcd_return_to_status();
|
lcd_setstatuspgm(_T(MSG_LOADING_FILAMENT));
|
||||||
lcd_update_enable(true);
|
lcd_return_to_status();
|
||||||
lcd_load_filament_color_check();
|
lcd_update_enable(true);
|
||||||
lcd_setstatuspgm(_T(WELCOME_MSG));
|
lcd_load_filament_color_check();
|
||||||
custom_message_type = CUSTOM_MSG_TYPE_STATUS;
|
lcd_setstatuspgm(_T(WELCOME_MSG));
|
||||||
}
|
custom_message_type = CUSTOM_MSG_TYPE_STATUS;
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
show_preheat_nozzle_warning();
|
{
|
||||||
}
|
show_preheat_nozzle_warning();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmu_eject_filament(uint8_t filament, bool recover)
|
void mmu_eject_filament(uint8_t filament, bool recover)
|
||||||
|
|
@ -1319,14 +1320,14 @@ void mmu_eject_filament(uint8_t filament, bool recover)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
show_preheat_nozzle_warning();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
show_preheat_nozzle_warning();
|
puts_P(PSTR("Filament nr out of range!"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
puts_P(PSTR("Filament nr out of range!"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,120 +26,126 @@
|
||||||
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
|
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
|
||||||
// segment is configured in settings.mm_per_arc_segment.
|
// segment is configured in settings.mm_per_arc_segment.
|
||||||
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1,
|
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1,
|
||||||
uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder)
|
uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder)
|
||||||
{
|
{
|
||||||
// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();
|
// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();
|
||||||
// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc
|
// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc
|
||||||
float center_axis0 = position[axis_0] + offset[axis_0];
|
float center_axis0 = position[axis_0] + offset[axis_0];
|
||||||
float center_axis1 = position[axis_1] + offset[axis_1];
|
float center_axis1 = position[axis_1] + offset[axis_1];
|
||||||
float linear_travel = target[axis_linear] - position[axis_linear];
|
float linear_travel = target[axis_linear] - position[axis_linear];
|
||||||
float extruder_travel = target[E_AXIS] - position[E_AXIS];
|
float extruder_travel = target[E_AXIS] - position[E_AXIS];
|
||||||
float r_axis0 = -offset[axis_0]; // Radius vector from center to current location
|
float r_axis0 = -offset[axis_0]; // Radius vector from center to current location
|
||||||
float r_axis1 = -offset[axis_1];
|
float r_axis1 = -offset[axis_1];
|
||||||
float rt_axis0 = target[axis_0] - center_axis0;
|
float rt_axis0 = target[axis_0] - center_axis0;
|
||||||
float rt_axis1 = target[axis_1] - center_axis1;
|
float rt_axis1 = target[axis_1] - center_axis1;
|
||||||
|
|
||||||
// CCW angle between position and target from circle center. Only one atan2() trig computation required.
|
// CCW angle between position and target from circle center. Only one atan2() trig computation required.
|
||||||
float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
|
float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
|
||||||
if (angular_travel < 0) { angular_travel += 2*M_PI; }
|
if (angular_travel < 0) {
|
||||||
if (isclockwise) { angular_travel -= 2*M_PI; }
|
angular_travel += 2*M_PI;
|
||||||
|
}
|
||||||
//20141002:full circle for G03 did not work, e.g. G03 X80 Y80 I20 J0 F2000 is giving an Angle of zero so head is not moving
|
if (isclockwise) {
|
||||||
//to compensate when start pos = target pos && angle is zero -> angle = 2Pi
|
angular_travel -= 2*M_PI;
|
||||||
if (position[axis_0] == target[axis_0] && position[axis_1] == target[axis_1] && angular_travel == 0)
|
|
||||||
{
|
|
||||||
angular_travel += 2*M_PI;
|
|
||||||
}
|
|
||||||
//end fix G03
|
|
||||||
|
|
||||||
float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
|
|
||||||
if (millimeters_of_travel < 0.001) { return; }
|
|
||||||
uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT);
|
|
||||||
if(segments == 0) segments = 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Multiply inverse feed_rate to compensate for the fact that this movement is approximated
|
|
||||||
// by a number of discrete segments. The inverse feed_rate should be correct for the sum of
|
|
||||||
// all segments.
|
|
||||||
if (invert_feed_rate) { feed_rate *= segments; }
|
|
||||||
*/
|
|
||||||
float theta_per_segment = angular_travel/segments;
|
|
||||||
float linear_per_segment = linear_travel/segments;
|
|
||||||
float extruder_per_segment = extruder_travel/segments;
|
|
||||||
|
|
||||||
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
|
||||||
and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
|
|
||||||
r_T = [cos(phi) -sin(phi);
|
|
||||||
sin(phi) cos(phi] * r ;
|
|
||||||
|
|
||||||
For arc generation, the center of the circle is the axis of rotation and the radius vector is
|
|
||||||
defined from the circle center to the initial position. Each line segment is formed by successive
|
|
||||||
vector rotations. This requires only two cos() and sin() computations to form the rotation
|
|
||||||
matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
|
|
||||||
all double numbers are single precision on the Arduino. (True double precision will not have
|
|
||||||
round off issues for CNC applications.) Single precision error can accumulate to be greater than
|
|
||||||
tool precision in some cases. Therefore, arc path correction is implemented.
|
|
||||||
|
|
||||||
Small angle approximation may be used to reduce computation overhead further. This approximation
|
|
||||||
holds for everything, but very small circles and large mm_per_arc_segment values. In other words,
|
|
||||||
theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
|
|
||||||
to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for
|
|
||||||
numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
|
|
||||||
issue for CNC machines with the single precision Arduino calculations.
|
|
||||||
|
|
||||||
This approximation also allows mc_arc to immediately insert a line segment into the planner
|
|
||||||
without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
|
|
||||||
a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead.
|
|
||||||
This is important when there are successive arc motions.
|
|
||||||
*/
|
|
||||||
// Vector rotation matrix values
|
|
||||||
float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
|
|
||||||
float sin_T = theta_per_segment;
|
|
||||||
|
|
||||||
float arc_target[4];
|
|
||||||
float sin_Ti;
|
|
||||||
float cos_Ti;
|
|
||||||
float r_axisi;
|
|
||||||
uint16_t i;
|
|
||||||
int8_t count = 0;
|
|
||||||
|
|
||||||
// Initialize the linear axis
|
|
||||||
arc_target[axis_linear] = position[axis_linear];
|
|
||||||
|
|
||||||
// Initialize the extruder axis
|
|
||||||
arc_target[E_AXIS] = position[E_AXIS];
|
|
||||||
|
|
||||||
for (i = 1; i<segments; i++) { // Increment (segments-1)
|
|
||||||
|
|
||||||
if (count < N_ARC_CORRECTION) {
|
|
||||||
// Apply vector rotation matrix
|
|
||||||
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
|
||||||
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
|
||||||
r_axis1 = r_axisi;
|
|
||||||
count++;
|
|
||||||
} else {
|
|
||||||
// Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
|
|
||||||
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
|
||||||
cos_Ti = cos(i*theta_per_segment);
|
|
||||||
sin_Ti = sin(i*theta_per_segment);
|
|
||||||
r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
|
|
||||||
r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
|
|
||||||
count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update arc_target location
|
//20141002:full circle for G03 did not work, e.g. G03 X80 Y80 I20 J0 F2000 is giving an Angle of zero so head is not moving
|
||||||
arc_target[axis_0] = center_axis0 + r_axis0;
|
//to compensate when start pos = target pos && angle is zero -> angle = 2Pi
|
||||||
arc_target[axis_1] = center_axis1 + r_axis1;
|
if (position[axis_0] == target[axis_0] && position[axis_1] == target[axis_1] && angular_travel == 0)
|
||||||
arc_target[axis_linear] += linear_per_segment;
|
{
|
||||||
arc_target[E_AXIS] += extruder_per_segment;
|
angular_travel += 2*M_PI;
|
||||||
|
}
|
||||||
|
//end fix G03
|
||||||
|
|
||||||
clamp_to_software_endstops(arc_target);
|
float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
|
||||||
plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, extruder);
|
if (millimeters_of_travel < 0.001) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT);
|
||||||
|
if(segments == 0) segments = 1;
|
||||||
|
|
||||||
}
|
/*
|
||||||
// Ensure last segment arrives at target location.
|
// Multiply inverse feed_rate to compensate for the fact that this movement is approximated
|
||||||
plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, extruder);
|
// by a number of discrete segments. The inverse feed_rate should be correct for the sum of
|
||||||
|
// all segments.
|
||||||
|
if (invert_feed_rate) { feed_rate *= segments; }
|
||||||
|
*/
|
||||||
|
float theta_per_segment = angular_travel/segments;
|
||||||
|
float linear_per_segment = linear_travel/segments;
|
||||||
|
float extruder_per_segment = extruder_travel/segments;
|
||||||
|
|
||||||
// plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled);
|
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
||||||
|
and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
|
||||||
|
r_T = [cos(phi) -sin(phi);
|
||||||
|
sin(phi) cos(phi] * r ;
|
||||||
|
|
||||||
|
For arc generation, the center of the circle is the axis of rotation and the radius vector is
|
||||||
|
defined from the circle center to the initial position. Each line segment is formed by successive
|
||||||
|
vector rotations. This requires only two cos() and sin() computations to form the rotation
|
||||||
|
matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
|
||||||
|
all double numbers are single precision on the Arduino. (True double precision will not have
|
||||||
|
round off issues for CNC applications.) Single precision error can accumulate to be greater than
|
||||||
|
tool precision in some cases. Therefore, arc path correction is implemented.
|
||||||
|
|
||||||
|
Small angle approximation may be used to reduce computation overhead further. This approximation
|
||||||
|
holds for everything, but very small circles and large mm_per_arc_segment values. In other words,
|
||||||
|
theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
|
||||||
|
to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for
|
||||||
|
numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
|
||||||
|
issue for CNC machines with the single precision Arduino calculations.
|
||||||
|
|
||||||
|
This approximation also allows mc_arc to immediately insert a line segment into the planner
|
||||||
|
without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
|
||||||
|
a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead.
|
||||||
|
This is important when there are successive arc motions.
|
||||||
|
*/
|
||||||
|
// Vector rotation matrix values
|
||||||
|
float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
|
||||||
|
float sin_T = theta_per_segment;
|
||||||
|
|
||||||
|
float arc_target[4];
|
||||||
|
float sin_Ti;
|
||||||
|
float cos_Ti;
|
||||||
|
float r_axisi;
|
||||||
|
uint16_t i;
|
||||||
|
int8_t count = 0;
|
||||||
|
|
||||||
|
// Initialize the linear axis
|
||||||
|
arc_target[axis_linear] = position[axis_linear];
|
||||||
|
|
||||||
|
// Initialize the extruder axis
|
||||||
|
arc_target[E_AXIS] = position[E_AXIS];
|
||||||
|
|
||||||
|
for (i = 1; i<segments; i++) { // Increment (segments-1)
|
||||||
|
|
||||||
|
if (count < N_ARC_CORRECTION) {
|
||||||
|
// Apply vector rotation matrix
|
||||||
|
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
||||||
|
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
||||||
|
r_axis1 = r_axisi;
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
// Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
|
||||||
|
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
||||||
|
cos_Ti = cos(i*theta_per_segment);
|
||||||
|
sin_Ti = sin(i*theta_per_segment);
|
||||||
|
r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
|
||||||
|
r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update arc_target location
|
||||||
|
arc_target[axis_0] = center_axis0 + r_axis0;
|
||||||
|
arc_target[axis_1] = center_axis1 + r_axis1;
|
||||||
|
arc_target[axis_linear] += linear_per_segment;
|
||||||
|
arc_target[E_AXIS] += extruder_per_segment;
|
||||||
|
|
||||||
|
clamp_to_software_endstops(arc_target);
|
||||||
|
plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, extruder);
|
||||||
|
|
||||||
|
}
|
||||||
|
// Ensure last segment arrives at target location.
|
||||||
|
plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, extruder);
|
||||||
|
|
||||||
|
// plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
||||||
// for vector transformation direction.
|
// for vector transformation direction.
|
||||||
void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1,
|
void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1,
|
||||||
unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise, uint8_t extruder);
|
unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise, uint8_t extruder);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
#define OPTIBOOT_CUSTOMVER 0
|
#define OPTIBOOT_CUSTOMVER 0
|
||||||
#define OPTIBOOT_MINVER 2
|
#define OPTIBOOT_MINVER 2
|
||||||
static unsigned const int __attribute__((section(".version")))
|
static unsigned const int __attribute__((section(".version")))
|
||||||
optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
|
optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
|
||||||
|
|
||||||
/* Watchdog settings */
|
/* Watchdog settings */
|
||||||
#define WATCHDOG_OFF (0)
|
#define WATCHDOG_OFF (0)
|
||||||
|
|
@ -38,54 +38,55 @@ static unsigned const int __attribute__((section(".version")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void watchdogConfig(uint8_t x) {
|
static void watchdogConfig(uint8_t x) {
|
||||||
WDTCSR = _BV(WDCE) | _BV(WDE);
|
WDTCSR = _BV(WDCE) | _BV(WDE);
|
||||||
WDTCSR = x;
|
WDTCSR = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void watchdogReset() {
|
static void watchdogReset() {
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"wdr\n"
|
"wdr\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RECV_READY ((UCSR0A & _BV(RXC0)) != 0)
|
#define RECV_READY ((UCSR0A & _BV(RXC0)) != 0)
|
||||||
|
|
||||||
static uint8_t getch(void) {
|
static uint8_t getch(void) {
|
||||||
uint8_t ch;
|
uint8_t ch;
|
||||||
while(! RECV_READY) ;
|
while(! RECV_READY) ;
|
||||||
if (!(UCSR0A & _BV(FE0))) {
|
if (!(UCSR0A & _BV(FE0))) {
|
||||||
/*
|
/*
|
||||||
* A Framing Error indicates (probably) that something is talking
|
* A Framing Error indicates (probably) that something is talking
|
||||||
* to us at the wrong bit rate. Assume that this is because it
|
* to us at the wrong bit rate. Assume that this is because it
|
||||||
* expects to be talking to the application, and DON'T reset the
|
* expects to be talking to the application, and DON'T reset the
|
||||||
* watchdog. This should cause the bootloader to abort and run
|
* watchdog. This should cause the bootloader to abort and run
|
||||||
* the application "soon", if it keeps happening. (Note that we
|
* the application "soon", if it keeps happening. (Note that we
|
||||||
* don't care that an invalid char is returned...)
|
* don't care that an invalid char is returned...)
|
||||||
*/
|
*/
|
||||||
watchdogReset();
|
watchdogReset();
|
||||||
}
|
}
|
||||||
ch = UDR0;
|
ch = UDR0;
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void putch(char ch) {
|
static void putch(char ch) {
|
||||||
while (!(UCSR0A & _BV(UDRE0)));
|
while (!(UCSR0A & _BV(UDRE0)));
|
||||||
UDR0 = ch;
|
UDR0 = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verifySpace() {
|
static void verifySpace() {
|
||||||
if (getch() != CRC_EOP) {
|
if (getch() != CRC_EOP) {
|
||||||
putch(STK_FAILED);
|
putch(STK_FAILED);
|
||||||
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
|
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
|
||||||
while (1) // and busy-loop so that WD causes
|
while (1) // and busy-loop so that WD causes
|
||||||
; // a reset and app start.
|
; // a reset and app start.
|
||||||
}
|
}
|
||||||
putch(STK_INSYNC);
|
putch(STK_INSYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getNch(uint8_t count) {
|
static void getNch(uint8_t count) {
|
||||||
do getch(); while (--count);
|
do getch();
|
||||||
verifySpace();
|
while (--count);
|
||||||
|
verifySpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef uint16_t pagelen_t;
|
typedef uint16_t pagelen_t;
|
||||||
|
|
@ -99,211 +100,211 @@ extern struct block_t *block_buffer;
|
||||||
|
|
||||||
void optiboot_w25x20cl_enter()
|
void optiboot_w25x20cl_enter()
|
||||||
{
|
{
|
||||||
if (boot_app_flags & BOOT_APP_FLG_USER0) return;
|
if (boot_app_flags & BOOT_APP_FLG_USER0) return;
|
||||||
uint8_t ch;
|
uint8_t ch;
|
||||||
uint8_t rampz = 0;
|
uint8_t rampz = 0;
|
||||||
register uint16_t address = 0;
|
register uint16_t address = 0;
|
||||||
register pagelen_t length;
|
register pagelen_t length;
|
||||||
// Use the planner's queue for the receive / transmit buffers.
|
// Use the planner's queue for the receive / transmit buffers.
|
||||||
// uint8_t *buff = (uint8_t*)block_buffer;
|
// uint8_t *buff = (uint8_t*)block_buffer;
|
||||||
uint8_t buff[260];
|
uint8_t buff[260];
|
||||||
// bitmap of pages to be written. Bit is set to 1 if the page has already been erased.
|
// bitmap of pages to be written. Bit is set to 1 if the page has already been erased.
|
||||||
uint8_t pages_erased = 0;
|
uint8_t pages_erased = 0;
|
||||||
|
|
||||||
// Handshake sequence: Initialize the serial line, flush serial line, send magic, receive magic.
|
// Handshake sequence: Initialize the serial line, flush serial line, send magic, receive magic.
|
||||||
// If the magic is not received on time, or it is not received correctly, continue to the application.
|
// If the magic is not received on time, or it is not received correctly, continue to the application.
|
||||||
{
|
{
|
||||||
watchdogReset();
|
|
||||||
unsigned long boot_timeout = 2000000;
|
|
||||||
unsigned long boot_timer = 0;
|
|
||||||
const char *ptr = entry_magic_send;
|
|
||||||
const char *end = strlen_P(entry_magic_send) + ptr;
|
|
||||||
// Initialize the serial line.
|
|
||||||
UCSR0A |= (1 << U2X0);
|
|
||||||
UBRR0L = (((float)(F_CPU))/(((float)(115200))*8.0)-1.0+0.5);
|
|
||||||
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
|
|
||||||
// Flush the serial line.
|
|
||||||
while (RECV_READY) {
|
|
||||||
watchdogReset();
|
|
||||||
// Dummy register read (discard)
|
|
||||||
(void)(*(char *)UDR0);
|
|
||||||
}
|
|
||||||
// Send the initial magic string.
|
|
||||||
while (ptr != end)
|
|
||||||
putch(pgm_read_byte(ptr ++));
|
|
||||||
watchdogReset();
|
|
||||||
// Wait for one second until a magic string (constant entry_magic) is received
|
|
||||||
// from the serial line.
|
|
||||||
ptr = entry_magic_receive;
|
|
||||||
end = strlen_P(entry_magic_receive) + ptr;
|
|
||||||
while (ptr != end) {
|
|
||||||
while (! RECV_READY) {
|
|
||||||
watchdogReset();
|
watchdogReset();
|
||||||
delayMicroseconds(1);
|
unsigned long boot_timeout = 2000000;
|
||||||
if (++ boot_timer > boot_timeout)
|
unsigned long boot_timer = 0;
|
||||||
// Timeout expired, continue with the application.
|
const char *ptr = entry_magic_send;
|
||||||
return;
|
const char *end = strlen_P(entry_magic_send) + ptr;
|
||||||
}
|
// Initialize the serial line.
|
||||||
ch = UDR0;
|
UCSR0A |= (1 << U2X0);
|
||||||
if (pgm_read_byte(ptr ++) != ch)
|
UBRR0L = (((float)(F_CPU))/(((float)(115200))*8.0)-1.0+0.5);
|
||||||
// Magic was not received correctly, continue with the application
|
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
|
||||||
return;
|
// Flush the serial line.
|
||||||
watchdogReset();
|
while (RECV_READY) {
|
||||||
}
|
watchdogReset();
|
||||||
// Send the cfm magic string.
|
// Dummy register read (discard)
|
||||||
ptr = entry_magic_cfm;
|
(void)(*(char *)UDR0);
|
||||||
while (ptr != end)
|
|
||||||
putch(pgm_read_byte(ptr ++));
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_init();
|
|
||||||
w25x20cl_init();
|
|
||||||
watchdogConfig(WATCHDOG_OFF);
|
|
||||||
|
|
||||||
/* Forever loop: exits by causing WDT reset */
|
|
||||||
for (;;) {
|
|
||||||
/* get character from UART */
|
|
||||||
ch = getch();
|
|
||||||
|
|
||||||
if(ch == STK_GET_PARAMETER) {
|
|
||||||
unsigned char which = getch();
|
|
||||||
verifySpace();
|
|
||||||
/*
|
|
||||||
* Send optiboot version as "SW version"
|
|
||||||
* Note that the references to memory are optimized away.
|
|
||||||
*/
|
|
||||||
if (which == STK_SW_MINOR) {
|
|
||||||
putch(optiboot_version & 0xFF);
|
|
||||||
} else if (which == STK_SW_MAJOR) {
|
|
||||||
putch(optiboot_version >> 8);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* GET PARAMETER returns a generic 0x03 reply for
|
|
||||||
* other parameters - enough to keep Avrdude happy
|
|
||||||
*/
|
|
||||||
putch(0x03);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(ch == STK_SET_DEVICE) {
|
|
||||||
// SET DEVICE is ignored
|
|
||||||
getNch(20);
|
|
||||||
}
|
|
||||||
else if(ch == STK_SET_DEVICE_EXT) {
|
|
||||||
// SET DEVICE EXT is ignored
|
|
||||||
getNch(5);
|
|
||||||
}
|
|
||||||
else if(ch == STK_LOAD_ADDRESS) {
|
|
||||||
// LOAD ADDRESS
|
|
||||||
uint16_t newAddress;
|
|
||||||
// Workaround for the infamous ';' bug in the Prusa3D usb to serial converter.
|
|
||||||
// Send the binary data by nibbles to avoid transmitting the ';' character.
|
|
||||||
newAddress = getch();
|
|
||||||
newAddress |= getch();
|
|
||||||
newAddress |= (((uint16_t)getch()) << 8);
|
|
||||||
newAddress |= (((uint16_t)getch()) << 8);
|
|
||||||
// Transfer top bit to LSB in rampz
|
|
||||||
if (newAddress & 0x8000)
|
|
||||||
rampz |= 0x01;
|
|
||||||
else
|
|
||||||
rampz &= 0xFE;
|
|
||||||
newAddress += newAddress; // Convert from word address to byte address
|
|
||||||
address = newAddress;
|
|
||||||
verifySpace();
|
|
||||||
}
|
|
||||||
else if(ch == STK_UNIVERSAL) {
|
|
||||||
// LOAD_EXTENDED_ADDRESS is needed in STK_UNIVERSAL for addressing more than 128kB
|
|
||||||
if ( AVR_OP_LOAD_EXT_ADDR == getch() ) {
|
|
||||||
// get address
|
|
||||||
getch(); // get '0'
|
|
||||||
rampz = (rampz & 0x01) | ((getch() << 1) & 0xff); // get address and put it in rampz
|
|
||||||
getNch(1); // get last '0'
|
|
||||||
// response
|
|
||||||
putch(0x00);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// everything else is ignored
|
|
||||||
getNch(3);
|
|
||||||
putch(0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Write memory, length is big endian and is in bytes */
|
|
||||||
else if(ch == STK_PROG_PAGE) {
|
|
||||||
// PROGRAM PAGE - we support flash programming only, not EEPROM
|
|
||||||
uint8_t desttype;
|
|
||||||
uint8_t *bufPtr;
|
|
||||||
pagelen_t savelength;
|
|
||||||
// Read the page length, with the length transferred each nibble separately to work around
|
|
||||||
// the Prusa's USB to serial infamous semicolon issue.
|
|
||||||
length = ((pagelen_t)getch()) << 8;
|
|
||||||
length |= ((pagelen_t)getch()) << 8;
|
|
||||||
length |= getch();
|
|
||||||
length |= getch();
|
|
||||||
|
|
||||||
savelength = length;
|
|
||||||
// Read the destination type. It should always be 'F' as flash.
|
|
||||||
desttype = getch();
|
|
||||||
|
|
||||||
// read a page worth of contents
|
|
||||||
bufPtr = buff;
|
|
||||||
do *bufPtr++ = getch();
|
|
||||||
while (--length);
|
|
||||||
|
|
||||||
// Read command terminator, start reply
|
|
||||||
verifySpace();
|
|
||||||
if (desttype == 'E') {
|
|
||||||
while (1) ; // Error: wait for WDT
|
|
||||||
} else {
|
|
||||||
uint32_t addr = (((uint32_t)rampz) << 16) | address;
|
|
||||||
// During a single bootloader run, only erase a 64kB block once.
|
|
||||||
// An 8bit bitmask 'pages_erased' covers 512kB of FLASH memory.
|
|
||||||
if (address == 0 && (pages_erased & (1 << addr)) == 0) {
|
|
||||||
w25x20cl_wait_busy();
|
|
||||||
w25x20cl_enable_wr();
|
|
||||||
w25x20cl_block64_erase(addr);
|
|
||||||
pages_erased |= (1 << addr);
|
|
||||||
}
|
}
|
||||||
w25x20cl_wait_busy();
|
// Send the initial magic string.
|
||||||
w25x20cl_enable_wr();
|
while (ptr != end)
|
||||||
w25x20cl_page_program(addr, buff, savelength);
|
putch(pgm_read_byte(ptr ++));
|
||||||
w25x20cl_wait_busy();
|
watchdogReset();
|
||||||
w25x20cl_disable_wr();
|
// Wait for one second until a magic string (constant entry_magic) is received
|
||||||
}
|
// from the serial line.
|
||||||
|
ptr = entry_magic_receive;
|
||||||
|
end = strlen_P(entry_magic_receive) + ptr;
|
||||||
|
while (ptr != end) {
|
||||||
|
while (! RECV_READY) {
|
||||||
|
watchdogReset();
|
||||||
|
delayMicroseconds(1);
|
||||||
|
if (++ boot_timer > boot_timeout)
|
||||||
|
// Timeout expired, continue with the application.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ch = UDR0;
|
||||||
|
if (pgm_read_byte(ptr ++) != ch)
|
||||||
|
// Magic was not received correctly, continue with the application
|
||||||
|
return;
|
||||||
|
watchdogReset();
|
||||||
|
}
|
||||||
|
// Send the cfm magic string.
|
||||||
|
ptr = entry_magic_cfm;
|
||||||
|
while (ptr != end)
|
||||||
|
putch(pgm_read_byte(ptr ++));
|
||||||
}
|
}
|
||||||
/* Read memory block mode, length is big endian. */
|
|
||||||
else if(ch == STK_READ_PAGE) {
|
spi_init();
|
||||||
uint32_t addr = (((uint32_t)rampz) << 16) | address;
|
w25x20cl_init();
|
||||||
register pagelen_t i;
|
watchdogConfig(WATCHDOG_OFF);
|
||||||
// Read the page length, with the length transferred each nibble separately to work around
|
|
||||||
// the Prusa's USB to serial infamous semicolon issue.
|
/* Forever loop: exits by causing WDT reset */
|
||||||
length = ((pagelen_t)getch()) << 8;
|
for (;;) {
|
||||||
length |= ((pagelen_t)getch()) << 8;
|
/* get character from UART */
|
||||||
length |= getch();
|
ch = getch();
|
||||||
length |= getch();
|
|
||||||
// Read the destination type. It should always be 'F' as flash. It is not checked.
|
if(ch == STK_GET_PARAMETER) {
|
||||||
(void)getch();
|
unsigned char which = getch();
|
||||||
verifySpace();
|
verifySpace();
|
||||||
w25x20cl_wait_busy();
|
/*
|
||||||
w25x20cl_rd_data(addr, buff, length);
|
* Send optiboot version as "SW version"
|
||||||
for (i = 0; i < length; ++ i)
|
* Note that the references to memory are optimized away.
|
||||||
putch(buff[i]);
|
*/
|
||||||
|
if (which == STK_SW_MINOR) {
|
||||||
|
putch(optiboot_version & 0xFF);
|
||||||
|
} else if (which == STK_SW_MAJOR) {
|
||||||
|
putch(optiboot_version >> 8);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* GET PARAMETER returns a generic 0x03 reply for
|
||||||
|
* other parameters - enough to keep Avrdude happy
|
||||||
|
*/
|
||||||
|
putch(0x03);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(ch == STK_SET_DEVICE) {
|
||||||
|
// SET DEVICE is ignored
|
||||||
|
getNch(20);
|
||||||
|
}
|
||||||
|
else if(ch == STK_SET_DEVICE_EXT) {
|
||||||
|
// SET DEVICE EXT is ignored
|
||||||
|
getNch(5);
|
||||||
|
}
|
||||||
|
else if(ch == STK_LOAD_ADDRESS) {
|
||||||
|
// LOAD ADDRESS
|
||||||
|
uint16_t newAddress;
|
||||||
|
// Workaround for the infamous ';' bug in the Prusa3D usb to serial converter.
|
||||||
|
// Send the binary data by nibbles to avoid transmitting the ';' character.
|
||||||
|
newAddress = getch();
|
||||||
|
newAddress |= getch();
|
||||||
|
newAddress |= (((uint16_t)getch()) << 8);
|
||||||
|
newAddress |= (((uint16_t)getch()) << 8);
|
||||||
|
// Transfer top bit to LSB in rampz
|
||||||
|
if (newAddress & 0x8000)
|
||||||
|
rampz |= 0x01;
|
||||||
|
else
|
||||||
|
rampz &= 0xFE;
|
||||||
|
newAddress += newAddress; // Convert from word address to byte address
|
||||||
|
address = newAddress;
|
||||||
|
verifySpace();
|
||||||
|
}
|
||||||
|
else if(ch == STK_UNIVERSAL) {
|
||||||
|
// LOAD_EXTENDED_ADDRESS is needed in STK_UNIVERSAL for addressing more than 128kB
|
||||||
|
if ( AVR_OP_LOAD_EXT_ADDR == getch() ) {
|
||||||
|
// get address
|
||||||
|
getch(); // get '0'
|
||||||
|
rampz = (rampz & 0x01) | ((getch() << 1) & 0xff); // get address and put it in rampz
|
||||||
|
getNch(1); // get last '0'
|
||||||
|
// response
|
||||||
|
putch(0x00);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// everything else is ignored
|
||||||
|
getNch(3);
|
||||||
|
putch(0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Write memory, length is big endian and is in bytes */
|
||||||
|
else if(ch == STK_PROG_PAGE) {
|
||||||
|
// PROGRAM PAGE - we support flash programming only, not EEPROM
|
||||||
|
uint8_t desttype;
|
||||||
|
uint8_t *bufPtr;
|
||||||
|
pagelen_t savelength;
|
||||||
|
// Read the page length, with the length transferred each nibble separately to work around
|
||||||
|
// the Prusa's USB to serial infamous semicolon issue.
|
||||||
|
length = ((pagelen_t)getch()) << 8;
|
||||||
|
length |= ((pagelen_t)getch()) << 8;
|
||||||
|
length |= getch();
|
||||||
|
length |= getch();
|
||||||
|
|
||||||
|
savelength = length;
|
||||||
|
// Read the destination type. It should always be 'F' as flash.
|
||||||
|
desttype = getch();
|
||||||
|
|
||||||
|
// read a page worth of contents
|
||||||
|
bufPtr = buff;
|
||||||
|
do *bufPtr++ = getch();
|
||||||
|
while (--length);
|
||||||
|
|
||||||
|
// Read command terminator, start reply
|
||||||
|
verifySpace();
|
||||||
|
if (desttype == 'E') {
|
||||||
|
while (1) ; // Error: wait for WDT
|
||||||
|
} else {
|
||||||
|
uint32_t addr = (((uint32_t)rampz) << 16) | address;
|
||||||
|
// During a single bootloader run, only erase a 64kB block once.
|
||||||
|
// An 8bit bitmask 'pages_erased' covers 512kB of FLASH memory.
|
||||||
|
if (address == 0 && (pages_erased & (1 << addr)) == 0) {
|
||||||
|
w25x20cl_wait_busy();
|
||||||
|
w25x20cl_enable_wr();
|
||||||
|
w25x20cl_block64_erase(addr);
|
||||||
|
pages_erased |= (1 << addr);
|
||||||
|
}
|
||||||
|
w25x20cl_wait_busy();
|
||||||
|
w25x20cl_enable_wr();
|
||||||
|
w25x20cl_page_program(addr, buff, savelength);
|
||||||
|
w25x20cl_wait_busy();
|
||||||
|
w25x20cl_disable_wr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Read memory block mode, length is big endian. */
|
||||||
|
else if(ch == STK_READ_PAGE) {
|
||||||
|
uint32_t addr = (((uint32_t)rampz) << 16) | address;
|
||||||
|
register pagelen_t i;
|
||||||
|
// Read the page length, with the length transferred each nibble separately to work around
|
||||||
|
// the Prusa's USB to serial infamous semicolon issue.
|
||||||
|
length = ((pagelen_t)getch()) << 8;
|
||||||
|
length |= ((pagelen_t)getch()) << 8;
|
||||||
|
length |= getch();
|
||||||
|
length |= getch();
|
||||||
|
// Read the destination type. It should always be 'F' as flash. It is not checked.
|
||||||
|
(void)getch();
|
||||||
|
verifySpace();
|
||||||
|
w25x20cl_wait_busy();
|
||||||
|
w25x20cl_rd_data(addr, buff, length);
|
||||||
|
for (i = 0; i < length; ++ i)
|
||||||
|
putch(buff[i]);
|
||||||
|
}
|
||||||
|
/* Get device signature bytes */
|
||||||
|
else if(ch == STK_READ_SIGN) {
|
||||||
|
// READ SIGN - return what Avrdude wants to hear
|
||||||
|
verifySpace();
|
||||||
|
putch(W25X20CL_SIGNATURE_0);
|
||||||
|
putch(W25X20CL_SIGNATURE_1);
|
||||||
|
putch(W25X20CL_SIGNATURE_2);
|
||||||
|
}
|
||||||
|
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
|
||||||
|
// Adaboot no-wait mod
|
||||||
|
watchdogConfig(WATCHDOG_16MS);
|
||||||
|
verifySpace();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// This covers the response to commands like STK_ENTER_PROGMODE
|
||||||
|
verifySpace();
|
||||||
|
}
|
||||||
|
putch(STK_OK);
|
||||||
}
|
}
|
||||||
/* Get device signature bytes */
|
|
||||||
else if(ch == STK_READ_SIGN) {
|
|
||||||
// READ SIGN - return what Avrdude wants to hear
|
|
||||||
verifySpace();
|
|
||||||
putch(W25X20CL_SIGNATURE_0);
|
|
||||||
putch(W25X20CL_SIGNATURE_1);
|
|
||||||
putch(W25X20CL_SIGNATURE_2);
|
|
||||||
}
|
|
||||||
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
|
|
||||||
// Adaboot no-wait mod
|
|
||||||
watchdogConfig(WATCHDOG_16MS);
|
|
||||||
verifySpace();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// This covers the response to commands like STK_ENTER_PROGMODE
|
|
||||||
verifySpace();
|
|
||||||
}
|
|
||||||
putch(STK_OK);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,9 @@ uint8_t pat9125_s = 0;
|
||||||
|
|
||||||
// Init sequence, address & value.
|
// Init sequence, address & value.
|
||||||
const PROGMEM uint8_t pat9125_init_seq1[] = {
|
const PROGMEM uint8_t pat9125_init_seq1[] = {
|
||||||
// Disable write protect.
|
// Disable write protect.
|
||||||
PAT9125_WP, 0x5a,
|
PAT9125_WP, 0x5a,
|
||||||
// Set the X resolution to zero to let the sensor know that it could safely ignore movement in the X axis.
|
// Set the X resolution to zero to let the sensor know that it could safely ignore movement in the X axis.
|
||||||
PAT9125_RES_X, PAT9125_XRES,
|
PAT9125_RES_X, PAT9125_XRES,
|
||||||
// Set the Y resolution to a maximum (or nearly a maximum).
|
// Set the Y resolution to a maximum (or nearly a maximum).
|
||||||
PAT9125_RES_Y, PAT9125_YRES,
|
PAT9125_RES_Y, PAT9125_YRES,
|
||||||
|
|
@ -65,33 +65,33 @@ const PROGMEM uint8_t pat9125_init_seq1[] = {
|
||||||
|
|
||||||
// Init sequence, address & value.
|
// Init sequence, address & value.
|
||||||
const PROGMEM uint8_t pat9125_init_seq2[] = {
|
const PROGMEM uint8_t pat9125_init_seq2[] = {
|
||||||
// Magic sequence to enforce full frame rate of the sensor.
|
// Magic sequence to enforce full frame rate of the sensor.
|
||||||
0x06, 0x028,
|
0x06, 0x028,
|
||||||
0x33, 0x0d0,
|
0x33, 0x0d0,
|
||||||
0x36, 0x0c2,
|
0x36, 0x0c2,
|
||||||
0x3e, 0x001,
|
0x3e, 0x001,
|
||||||
0x3f, 0x015,
|
0x3f, 0x015,
|
||||||
0x41, 0x032,
|
0x41, 0x032,
|
||||||
0x42, 0x03b,
|
0x42, 0x03b,
|
||||||
0x43, 0x0f2,
|
0x43, 0x0f2,
|
||||||
0x44, 0x03b,
|
0x44, 0x03b,
|
||||||
0x45, 0x0f2,
|
0x45, 0x0f2,
|
||||||
0x46, 0x022,
|
0x46, 0x022,
|
||||||
0x47, 0x03b,
|
0x47, 0x03b,
|
||||||
0x48, 0x0f2,
|
0x48, 0x0f2,
|
||||||
0x49, 0x03b,
|
0x49, 0x03b,
|
||||||
0x4a, 0x0f0,
|
0x4a, 0x0f0,
|
||||||
0x58, 0x098,
|
0x58, 0x098,
|
||||||
0x59, 0x00c,
|
0x59, 0x00c,
|
||||||
0x5a, 0x008,
|
0x5a, 0x008,
|
||||||
0x5b, 0x00c,
|
0x5b, 0x00c,
|
||||||
0x5c, 0x008,
|
0x5c, 0x008,
|
||||||
0x61, 0x010,
|
0x61, 0x010,
|
||||||
0x67, 0x09b,
|
0x67, 0x09b,
|
||||||
0x6e, 0x022,
|
0x6e, 0x022,
|
||||||
0x71, 0x007,
|
0x71, 0x007,
|
||||||
0x72, 0x008,
|
0x72, 0x008,
|
||||||
// stopper
|
// stopper
|
||||||
0x0ff
|
0x0ff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -107,176 +107,176 @@ extern FILE _uartout;
|
||||||
uint8_t pat9125_init(void)
|
uint8_t pat9125_init(void)
|
||||||
{
|
{
|
||||||
#ifdef PAT9125_SWSPI
|
#ifdef PAT9125_SWSPI
|
||||||
swspi_init();
|
swspi_init();
|
||||||
#endif //PAT9125_SWSPI
|
#endif //PAT9125_SWSPI
|
||||||
#ifdef PAT9125_SWI2C
|
#ifdef PAT9125_SWI2C
|
||||||
swi2c_init();
|
swi2c_init();
|
||||||
#endif //PAT9125_SWI2C
|
#endif //PAT9125_SWI2C
|
||||||
// Verify that the sensor responds with its correct product ID.
|
// Verify that the sensor responds with its correct product ID.
|
||||||
pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
|
pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
|
||||||
pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
|
pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
|
||||||
if ((pat9125_PID1 != 0x31) || (pat9125_PID2 != 0x91))
|
if ((pat9125_PID1 != 0x31) || (pat9125_PID2 != 0x91))
|
||||||
{
|
{
|
||||||
pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
|
pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
|
||||||
pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
|
pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
|
||||||
if ((pat9125_PID1 != 0x31) || (pat9125_PID2 != 0x91))
|
if ((pat9125_PID1 != 0x31) || (pat9125_PID2 != 0x91))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PAT9125_NEW_INIT
|
#ifdef PAT9125_NEW_INIT
|
||||||
// Switch to bank0, not allowed to perform OTS_RegWriteRead.
|
// Switch to bank0, not allowed to perform OTS_RegWriteRead.
|
||||||
pat9125_wr_reg(PAT9125_BANK_SELECTION, 0);
|
pat9125_wr_reg(PAT9125_BANK_SELECTION, 0);
|
||||||
// Software reset (i.e. set bit7 to 1). It will reset to 0 automatically.
|
// Software reset (i.e. set bit7 to 1). It will reset to 0 automatically.
|
||||||
// After the reset, OTS_RegWriteRead is not allowed.
|
// After the reset, OTS_RegWriteRead is not allowed.
|
||||||
pat9125_wr_reg(PAT9125_CONFIG, 0x97);
|
pat9125_wr_reg(PAT9125_CONFIG, 0x97);
|
||||||
// Wait until the sensor reboots.
|
// Wait until the sensor reboots.
|
||||||
// Delay 1ms.
|
// Delay 1ms.
|
||||||
_delay_us(1000);
|
_delay_us(1000);
|
||||||
{
|
{
|
||||||
const uint8_t *ptr = pat9125_init_seq1;
|
const uint8_t *ptr = pat9125_init_seq1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const uint8_t addr = pgm_read_byte_near(ptr ++);
|
const uint8_t addr = pgm_read_byte_near(ptr ++);
|
||||||
if (addr == 0x0ff)
|
if (addr == 0x0ff)
|
||||||
break;
|
break;
|
||||||
if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++)))
|
if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++)))
|
||||||
// Verification of the register write failed.
|
// Verification of the register write failed.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delay 10ms.
|
// Delay 10ms.
|
||||||
_delay_ms(10);
|
_delay_ms(10);
|
||||||
// Switch to bank1, not allowed to perform OTS_RegWrite.
|
// Switch to bank1, not allowed to perform OTS_RegWrite.
|
||||||
pat9125_wr_reg(PAT9125_BANK_SELECTION, 0x01);
|
pat9125_wr_reg(PAT9125_BANK_SELECTION, 0x01);
|
||||||
{
|
{
|
||||||
const uint8_t *ptr = pat9125_init_seq2;
|
const uint8_t *ptr = pat9125_init_seq2;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const uint8_t addr = pgm_read_byte_near(ptr ++);
|
const uint8_t addr = pgm_read_byte_near(ptr ++);
|
||||||
if (addr == 0x0ff)
|
if (addr == 0x0ff)
|
||||||
break;
|
break;
|
||||||
if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++)))
|
if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++)))
|
||||||
// Verification of the register write failed.
|
// Verification of the register write failed.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Switch to bank0, not allowed to perform OTS_RegWriteRead.
|
// Switch to bank0, not allowed to perform OTS_RegWriteRead.
|
||||||
pat9125_wr_reg(PAT9125_BANK_SELECTION, 0x00);
|
pat9125_wr_reg(PAT9125_BANK_SELECTION, 0x00);
|
||||||
// Enable write protect.
|
// Enable write protect.
|
||||||
pat9125_wr_reg(PAT9125_WP, 0x00);
|
pat9125_wr_reg(PAT9125_WP, 0x00);
|
||||||
|
|
||||||
pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
|
pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
|
||||||
pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
|
pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
|
||||||
#endif //PAT9125_NEW_INIT
|
#endif //PAT9125_NEW_INIT
|
||||||
|
|
||||||
pat9125_wr_reg(PAT9125_RES_X, PAT9125_XRES);
|
pat9125_wr_reg(PAT9125_RES_X, PAT9125_XRES);
|
||||||
pat9125_wr_reg(PAT9125_RES_Y, PAT9125_YRES);
|
pat9125_wr_reg(PAT9125_RES_Y, PAT9125_YRES);
|
||||||
fprintf_P(uartout, PSTR("PAT9125_RES_X=%hhu\n"), pat9125_rd_reg(PAT9125_RES_X));
|
fprintf_P(uartout, PSTR("PAT9125_RES_X=%hhu\n"), pat9125_rd_reg(PAT9125_RES_X));
|
||||||
fprintf_P(uartout, PSTR("PAT9125_RES_Y=%hhu\n"), pat9125_rd_reg(PAT9125_RES_Y));
|
fprintf_P(uartout, PSTR("PAT9125_RES_Y=%hhu\n"), pat9125_rd_reg(PAT9125_RES_Y));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pat9125_update(void)
|
uint8_t pat9125_update(void)
|
||||||
{
|
{
|
||||||
if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
|
if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
|
||||||
{
|
{
|
||||||
uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
|
uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
|
||||||
pat9125_b = pat9125_rd_reg(PAT9125_FRAME);
|
pat9125_b = pat9125_rd_reg(PAT9125_FRAME);
|
||||||
pat9125_s = pat9125_rd_reg(PAT9125_SHUTTER);
|
pat9125_s = pat9125_rd_reg(PAT9125_SHUTTER);
|
||||||
if (pat9125_PID1 == 0xff) return 0;
|
if (pat9125_PID1 == 0xff) return 0;
|
||||||
if (ucMotion & 0x80)
|
if (ucMotion & 0x80)
|
||||||
{
|
{
|
||||||
uint8_t ucXL = pat9125_rd_reg(PAT9125_DELTA_XL);
|
uint8_t ucXL = pat9125_rd_reg(PAT9125_DELTA_XL);
|
||||||
uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
|
uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
|
||||||
uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
|
uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
|
||||||
if (pat9125_PID1 == 0xff) return 0;
|
if (pat9125_PID1 == 0xff) return 0;
|
||||||
int16_t iDX = ucXL | ((ucXYH << 4) & 0xf00);
|
int16_t iDX = ucXL | ((ucXYH << 4) & 0xf00);
|
||||||
int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
|
int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
|
||||||
if (iDX & 0x800) iDX -= 4096;
|
if (iDX & 0x800) iDX -= 4096;
|
||||||
if (iDY & 0x800) iDY -= 4096;
|
if (iDY & 0x800) iDY -= 4096;
|
||||||
pat9125_x += iDX;
|
pat9125_x += iDX;
|
||||||
pat9125_y -= iDY; //negative number, because direction switching does not work
|
pat9125_y -= iDY; //negative number, because direction switching does not work
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pat9125_update_y(void)
|
uint8_t pat9125_update_y(void)
|
||||||
{
|
{
|
||||||
if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
|
if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
|
||||||
{
|
{
|
||||||
uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
|
uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
|
||||||
if (pat9125_PID1 == 0xff) return 0;
|
if (pat9125_PID1 == 0xff) return 0;
|
||||||
if (ucMotion & 0x80)
|
if (ucMotion & 0x80)
|
||||||
{
|
{
|
||||||
uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
|
uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
|
||||||
uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
|
uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
|
||||||
if (pat9125_PID1 == 0xff) return 0;
|
if (pat9125_PID1 == 0xff) return 0;
|
||||||
int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
|
int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
|
||||||
if (iDY & 0x800) iDY -= 4096;
|
if (iDY & 0x800) iDY -= 4096;
|
||||||
pat9125_y -= iDY; //negative number, because direction switching does not work
|
pat9125_y -= iDY; //negative number, because direction switching does not work
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pat9125_update_y2(void)
|
uint8_t pat9125_update_y2(void)
|
||||||
{
|
{
|
||||||
if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
|
if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
|
||||||
{
|
{
|
||||||
uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
|
uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
|
||||||
if (pat9125_PID1 == 0xff) return 0; //NOACK error
|
if (pat9125_PID1 == 0xff) return 0; //NOACK error
|
||||||
if (ucMotion & 0x80)
|
if (ucMotion & 0x80)
|
||||||
{
|
{
|
||||||
int8_t dy = pat9125_rd_reg(PAT9125_DELTA_YL);
|
int8_t dy = pat9125_rd_reg(PAT9125_DELTA_YL);
|
||||||
if (pat9125_PID1 == 0xff) return 0; //NOACK error
|
if (pat9125_PID1 == 0xff) return 0; //NOACK error
|
||||||
pat9125_y -= dy; //negative number, because direction switching does not work
|
pat9125_y -= dy; //negative number, because direction switching does not work
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pat9125_rd_reg(uint8_t addr)
|
uint8_t pat9125_rd_reg(uint8_t addr)
|
||||||
{
|
{
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
#ifdef PAT9125_SWSPI
|
#ifdef PAT9125_SWSPI
|
||||||
swspi_start();
|
swspi_start();
|
||||||
swspi_tx(addr & 0x7f);
|
swspi_tx(addr & 0x7f);
|
||||||
data = swspi_rx();
|
data = swspi_rx();
|
||||||
swspi_stop();
|
swspi_stop();
|
||||||
#endif //PAT9125_SWSPI
|
#endif //PAT9125_SWSPI
|
||||||
#ifdef PAT9125_SWI2C
|
#ifdef PAT9125_SWI2C
|
||||||
if (!swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
|
if (!swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
|
||||||
{
|
{
|
||||||
pat9125_PID1 = 0xff;
|
pat9125_PID1 = 0xff;
|
||||||
pat9125_PID2 = 0xff;
|
pat9125_PID2 = 0xff;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif //PAT9125_SWI2C
|
#endif //PAT9125_SWI2C
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pat9125_wr_reg(uint8_t addr, uint8_t data)
|
void pat9125_wr_reg(uint8_t addr, uint8_t data)
|
||||||
{
|
{
|
||||||
#ifdef PAT9125_SWSPI
|
#ifdef PAT9125_SWSPI
|
||||||
swspi_start();
|
swspi_start();
|
||||||
swspi_tx(addr | 0x80);
|
swspi_tx(addr | 0x80);
|
||||||
swspi_tx(data);
|
swspi_tx(data);
|
||||||
swspi_stop();
|
swspi_stop();
|
||||||
#endif //PAT9125_SWSPI
|
#endif //PAT9125_SWSPI
|
||||||
#ifdef PAT9125_SWI2C
|
#ifdef PAT9125_SWI2C
|
||||||
if (!swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
|
if (!swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
|
||||||
{
|
{
|
||||||
pat9125_PID1 = 0xff;
|
pat9125_PID1 = 0xff;
|
||||||
pat9125_PID2 = 0xff;
|
pat9125_PID2 = 0xff;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif //PAT9125_SWI2C
|
#endif //PAT9125_SWI2C
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data)
|
uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data)
|
||||||
{
|
{
|
||||||
pat9125_wr_reg(addr, data);
|
pat9125_wr_reg(addr, data);
|
||||||
return pat9125_rd_reg(addr) == data;
|
return pat9125_rd_reg(addr) == data;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,44 +42,44 @@
|
||||||
//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those!
|
//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those!
|
||||||
#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN,
|
#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN,
|
||||||
#if EXTRUDERS > 1
|
#if EXTRUDERS > 1
|
||||||
#define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, HEATER_1_PIN,
|
#define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, HEATER_1_PIN,
|
||||||
#else
|
#else
|
||||||
#define _E1_PINS
|
#define _E1_PINS
|
||||||
#endif
|
#endif
|
||||||
#if EXTRUDERS > 2
|
#if EXTRUDERS > 2
|
||||||
#define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, HEATER_2_PIN,
|
#define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, HEATER_2_PIN,
|
||||||
#else
|
#else
|
||||||
#define _E2_PINS
|
#define _E2_PINS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef X_STOP_PIN
|
#ifdef X_STOP_PIN
|
||||||
#if X_HOME_DIR < 0
|
#if X_HOME_DIR < 0
|
||||||
#define X_MIN_PIN X_STOP_PIN
|
#define X_MIN_PIN X_STOP_PIN
|
||||||
#define X_MAX_PIN -1
|
#define X_MAX_PIN -1
|
||||||
#else
|
#else
|
||||||
#define X_MIN_PIN -1
|
#define X_MIN_PIN -1
|
||||||
#define X_MAX_PIN X_STOP_PIN
|
#define X_MAX_PIN X_STOP_PIN
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Y_STOP_PIN
|
#ifdef Y_STOP_PIN
|
||||||
#if Y_HOME_DIR < 0
|
#if Y_HOME_DIR < 0
|
||||||
#define Y_MIN_PIN Y_STOP_PIN
|
#define Y_MIN_PIN Y_STOP_PIN
|
||||||
#define Y_MAX_PIN -1
|
#define Y_MAX_PIN -1
|
||||||
#else
|
#else
|
||||||
#define Y_MIN_PIN -1
|
#define Y_MIN_PIN -1
|
||||||
#define Y_MAX_PIN Y_STOP_PIN
|
#define Y_MAX_PIN Y_STOP_PIN
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Z_STOP_PIN
|
#ifdef Z_STOP_PIN
|
||||||
#if Z_HOME_DIR < 0
|
#if Z_HOME_DIR < 0
|
||||||
#define Z_MIN_PIN Z_STOP_PIN
|
#define Z_MIN_PIN Z_STOP_PIN
|
||||||
#define Z_MAX_PIN -1
|
#define Z_MAX_PIN -1
|
||||||
#else
|
#else
|
||||||
#define Z_MIN_PIN -1
|
#define Z_MIN_PIN -1
|
||||||
#define Z_MAX_PIN Z_STOP_PIN
|
#define Z_MAX_PIN Z_STOP_PIN
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DISABLE_MAX_ENDSTOPS
|
#ifdef DISABLE_MAX_ENDSTOPS
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#define KNOWN_BOARD
|
#define KNOWN_BOARD
|
||||||
#ifndef __AVR_ATmega2560__
|
#ifndef __AVR_ATmega2560__
|
||||||
#error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu.
|
#error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TMC2130
|
#define TMC2130
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#define KNOWN_BOARD
|
#define KNOWN_BOARD
|
||||||
#ifndef __AVR_ATmega2560__
|
#ifndef __AVR_ATmega2560__
|
||||||
#error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu.
|
#error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PINDA_THERMISTOR
|
#define PINDA_THERMISTOR
|
||||||
|
|
@ -65,8 +65,8 @@
|
||||||
#define E0_MS2_PIN 66
|
#define E0_MS2_PIN 66
|
||||||
|
|
||||||
#ifdef SNMM
|
#ifdef SNMM
|
||||||
#define E_MUX0_PIN 17
|
#define E_MUX0_PIN 17
|
||||||
#define E_MUX1_PIN 16
|
#define E_MUX1_PIN 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#define KNOWN_BOARD
|
#define KNOWN_BOARD
|
||||||
#ifndef __AVR_ATmega2560__
|
#ifndef __AVR_ATmega2560__
|
||||||
#error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu.
|
#error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PINDA_THERMISTOR
|
#define PINDA_THERMISTOR
|
||||||
|
|
@ -65,8 +65,8 @@
|
||||||
#define E0_MS2_PIN 66
|
#define E0_MS2_PIN 66
|
||||||
|
|
||||||
#ifdef SNMM
|
#ifdef SNMM
|
||||||
#define E_MUX0_PIN 17
|
#define E_MUX0_PIN 17
|
||||||
#define E_MUX1_PIN 16
|
#define E_MUX1_PIN 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1390
Firmware/planner.cpp
1390
Firmware/planner.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -48,79 +48,79 @@ enum BlockFlag {
|
||||||
|
|
||||||
union dda_isteps_t
|
union dda_isteps_t
|
||||||
{
|
{
|
||||||
int32_t wide;
|
int32_t wide;
|
||||||
struct {
|
struct {
|
||||||
int16_t lo;
|
int16_t lo;
|
||||||
int16_t hi;
|
int16_t hi;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union dda_usteps_t
|
union dda_usteps_t
|
||||||
{
|
{
|
||||||
uint32_t wide;
|
uint32_t wide;
|
||||||
struct {
|
struct {
|
||||||
uint16_t lo;
|
uint16_t lo;
|
||||||
uint16_t hi;
|
uint16_t hi;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in
|
// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in
|
||||||
// the source g-code and may never actually be reached if acceleration management is active.
|
// the source g-code and may never actually be reached if acceleration management is active.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// Fields used by the bresenham algorithm for tracing the line
|
// Fields used by the bresenham algorithm for tracing the line
|
||||||
// steps_x.y,z, step_event_count, acceleration_rate, direction_bits and active_extruder are set by plan_buffer_line().
|
// steps_x.y,z, step_event_count, acceleration_rate, direction_bits and active_extruder are set by plan_buffer_line().
|
||||||
dda_isteps_t steps_x, steps_y, steps_z, steps_e; // Step count along each axis
|
dda_isteps_t steps_x, steps_y, steps_z, steps_e; // Step count along each axis
|
||||||
dda_usteps_t step_event_count; // The number of step events required to complete this block
|
dda_usteps_t step_event_count; // The number of step events required to complete this block
|
||||||
long acceleration_rate; // The acceleration rate used for acceleration calculation
|
long acceleration_rate; // The acceleration rate used for acceleration calculation
|
||||||
unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
|
unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
|
||||||
unsigned char active_extruder; // Selects the active extruder
|
unsigned char active_extruder; // Selects the active extruder
|
||||||
// accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller.
|
// accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller.
|
||||||
long accelerate_until; // The index of the step event on which to stop acceleration
|
long accelerate_until; // The index of the step event on which to stop acceleration
|
||||||
long decelerate_after; // The index of the step event on which to start decelerating
|
long decelerate_after; // The index of the step event on which to start decelerating
|
||||||
|
|
||||||
// Fields used by the motion planner to manage acceleration
|
// Fields used by the motion planner to manage acceleration
|
||||||
// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis
|
// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis
|
||||||
// The nominal speed for this block in mm/sec.
|
// The nominal speed for this block in mm/sec.
|
||||||
// This speed may or may not be reached due to the jerk and acceleration limits.
|
// This speed may or may not be reached due to the jerk and acceleration limits.
|
||||||
float nominal_speed;
|
float nominal_speed;
|
||||||
// Entry speed at previous-current junction in mm/sec, respecting the acceleration and jerk limits.
|
// Entry speed at previous-current junction in mm/sec, respecting the acceleration and jerk limits.
|
||||||
// The entry speed limit of the current block equals the exit speed of the preceding block.
|
// The entry speed limit of the current block equals the exit speed of the preceding block.
|
||||||
float entry_speed;
|
float entry_speed;
|
||||||
// Maximum allowable junction entry speed in mm/sec. This value is also a maximum exit speed of the previous block.
|
// Maximum allowable junction entry speed in mm/sec. This value is also a maximum exit speed of the previous block.
|
||||||
float max_entry_speed;
|
float max_entry_speed;
|
||||||
// The total travel of this block in mm
|
// The total travel of this block in mm
|
||||||
float millimeters;
|
float millimeters;
|
||||||
// acceleration mm/sec^2
|
// acceleration mm/sec^2
|
||||||
float acceleration;
|
float acceleration;
|
||||||
|
|
||||||
// Bit flags defined by the BlockFlag enum.
|
// Bit flags defined by the BlockFlag enum.
|
||||||
uint8_t flag;
|
uint8_t flag;
|
||||||
|
|
||||||
// Settings for the trapezoid generator (runs inside an interrupt handler).
|
// Settings for the trapezoid generator (runs inside an interrupt handler).
|
||||||
// Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts.
|
// Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts.
|
||||||
//FIXME nominal_rate, initial_rate and final_rate are limited to uint16_t by MultiU24X24toH16 in the stepper interrupt anyway!
|
//FIXME nominal_rate, initial_rate and final_rate are limited to uint16_t by MultiU24X24toH16 in the stepper interrupt anyway!
|
||||||
unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec
|
unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec
|
||||||
unsigned long initial_rate; // The jerk-adjusted step rate at start of block
|
unsigned long initial_rate; // The jerk-adjusted step rate at start of block
|
||||||
unsigned long final_rate; // The minimal rate at exit
|
unsigned long final_rate; // The minimal rate at exit
|
||||||
unsigned long acceleration_st; // acceleration steps/sec^2
|
unsigned long acceleration_st; // acceleration steps/sec^2
|
||||||
//FIXME does it have to be unsigned long? Probably uint8_t would be just fine.
|
//FIXME does it have to be unsigned long? Probably uint8_t would be just fine.
|
||||||
unsigned long fan_speed;
|
unsigned long fan_speed;
|
||||||
volatile char busy;
|
volatile char busy;
|
||||||
|
|
||||||
|
|
||||||
// Pre-calculated division for the calculate_trapezoid_for_block() routine to run faster.
|
// Pre-calculated division for the calculate_trapezoid_for_block() routine to run faster.
|
||||||
float speed_factor;
|
float speed_factor;
|
||||||
|
|
||||||
#ifdef LIN_ADVANCE
|
#ifdef LIN_ADVANCE
|
||||||
bool use_advance_lead;
|
bool use_advance_lead;
|
||||||
unsigned long abs_adv_steps_multiplier8; // Factorised by 2^8 to avoid float
|
unsigned long abs_adv_steps_multiplier8; // Factorised by 2^8 to avoid float
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t sdlen;
|
uint16_t sdlen;
|
||||||
} block_t;
|
} block_t;
|
||||||
|
|
||||||
#ifdef LIN_ADVANCE
|
#ifdef LIN_ADVANCE
|
||||||
extern float extruder_advance_k, advance_ed_ratio;
|
extern float extruder_advance_k, advance_ed_ratio;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_AUTO_BED_LEVELING
|
#ifdef ENABLE_AUTO_BED_LEVELING
|
||||||
|
|
@ -171,10 +171,10 @@ extern uint8_t maxlimit_status;
|
||||||
|
|
||||||
|
|
||||||
#ifdef AUTOTEMP
|
#ifdef AUTOTEMP
|
||||||
extern bool autotemp_enabled;
|
extern bool autotemp_enabled;
|
||||||
extern float autotemp_max;
|
extern float autotemp_max;
|
||||||
extern float autotemp_min;
|
extern float autotemp_min;
|
||||||
extern float autotemp_factor;
|
extern float autotemp_factor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -191,9 +191,9 @@ extern volatile unsigned char block_buffer_tail;
|
||||||
// available for new blocks.
|
// available for new blocks.
|
||||||
FORCE_INLINE void plan_discard_current_block()
|
FORCE_INLINE void plan_discard_current_block()
|
||||||
{
|
{
|
||||||
if (block_buffer_head != block_buffer_tail) {
|
if (block_buffer_head != block_buffer_tail) {
|
||||||
block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1);
|
block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the current block. This is the block to be exectuted by the stepper routine.
|
// Gets the current block. This is the block to be exectuted by the stepper routine.
|
||||||
|
|
@ -202,17 +202,17 @@ FORCE_INLINE void plan_discard_current_block()
|
||||||
// Returns NULL if buffer empty
|
// Returns NULL if buffer empty
|
||||||
FORCE_INLINE block_t *plan_get_current_block()
|
FORCE_INLINE block_t *plan_get_current_block()
|
||||||
{
|
{
|
||||||
if (block_buffer_head == block_buffer_tail) {
|
if (block_buffer_head == block_buffer_tail) {
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
block_t *block = &block_buffer[block_buffer_tail];
|
block_t *block = &block_buffer[block_buffer_tail];
|
||||||
block->busy = true;
|
block->busy = true;
|
||||||
return(block);
|
return(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the buffer has a queued block, false otherwise
|
// Returns true if the buffer has a queued block, false otherwise
|
||||||
FORCE_INLINE bool blocks_queued() {
|
FORCE_INLINE bool blocks_queued() {
|
||||||
return (block_buffer_head != block_buffer_tail);
|
return (block_buffer_head != block_buffer_tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
//return the nr of buffered moves
|
//return the nr of buffered moves
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -6,15 +6,15 @@ void daxpy ( int n, double da, double dx[], int incx, double dy[], int incy );
|
||||||
double ddot ( int n, double dx[], int incx, double dy[], int incy );
|
double ddot ( int n, double dx[], int incx, double dy[], int incy );
|
||||||
double dnrm2 ( int n, double x[], int incx );
|
double dnrm2 ( int n, double x[], int incx );
|
||||||
void dqrank ( double a[], int lda, int m, int n, double tol, int *kr,
|
void dqrank ( double a[], int lda, int m, int n, double tol, int *kr,
|
||||||
int jpvt[], double qraux[] );
|
int jpvt[], double qraux[] );
|
||||||
void dqrdc ( double a[], int lda, int n, int p, double qraux[], int jpvt[],
|
void dqrdc ( double a[], int lda, int n, int p, double qraux[], int jpvt[],
|
||||||
double work[], int job );
|
double work[], int job );
|
||||||
int dqrls ( double a[], int lda, int m, int n, double tol, int *kr, double b[],
|
int dqrls ( double a[], int lda, int m, int n, double tol, int *kr, double b[],
|
||||||
double x[], double rsd[], int jpvt[], double qraux[], int itask );
|
double x[], double rsd[], int jpvt[], double qraux[], int itask );
|
||||||
void dqrlss ( double a[], int lda, int m, int n, int kr, double b[], double x[],
|
void dqrlss ( double a[], int lda, int m, int n, int kr, double b[], double x[],
|
||||||
double rsd[], int jpvt[], double qraux[] );
|
double rsd[], int jpvt[], double qraux[] );
|
||||||
int dqrsl ( double a[], int lda, int n, int k, double qraux[], double y[],
|
int dqrsl ( double a[], int lda, int n, int k, double qraux[], double y[],
|
||||||
double qy[], double qty[], double b[], double rsd[], double ab[], int job );
|
double qy[], double qty[], double b[], double rsd[], double ab[], int job );
|
||||||
void dscal ( int n, double sa, double x[], int incx );
|
void dscal ( int n, double sa, double x[], int incx );
|
||||||
void dswap ( int n, double x[], int incx, double y[], int incy );
|
void dswap ( int n, double x[], int incx, double y[], int incy );
|
||||||
double *qr_solve ( int m, int n, double a[], double b[] );
|
double *qr_solve ( int m, int n, double a[], double b[] );
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
void rbuf_ini(uint8_t* ptr, uint8_t l)
|
void rbuf_ini(uint8_t* ptr, uint8_t l)
|
||||||
{
|
{
|
||||||
ptr[0] = l;
|
ptr[0] = l;
|
||||||
ptr[1] = 0;
|
ptr[1] = 0;
|
||||||
ptr[2] = 0;
|
ptr[2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//lock/unlock macros
|
//lock/unlock macros
|
||||||
|
|
@ -20,17 +20,17 @@ void rbuf_ini(uint8_t* ptr, uint8_t l)
|
||||||
int rbuf_put(uint8_t* ptr, uint8_t b)
|
int rbuf_put(uint8_t* ptr, uint8_t b)
|
||||||
{
|
{
|
||||||
//#ifdef _NO_ASM
|
//#ifdef _NO_ASM
|
||||||
_lock(); //lock
|
_lock(); //lock
|
||||||
uint8_t buf_w = ptr[1]; //get write index
|
uint8_t buf_w = ptr[1]; //get write index
|
||||||
uint8_t buf_r = ptr[2]; //get read index
|
uint8_t buf_r = ptr[2]; //get read index
|
||||||
_unlock(); //unlock
|
_unlock(); //unlock
|
||||||
ptr[4 + buf_w] = b; //store byte to buffer
|
ptr[4 + buf_w] = b; //store byte to buffer
|
||||||
buf_w++; //incerment write index
|
buf_w++; //incerment write index
|
||||||
uint8_t buf_l = ptr[0]; //get length
|
uint8_t buf_l = ptr[0]; //get length
|
||||||
if (buf_w >= buf_l) buf_w = 0; //rotate write index
|
if (buf_w >= buf_l) buf_w = 0; //rotate write index
|
||||||
if (buf_w == buf_r) return -1; //return -1 to signal buffer full
|
if (buf_w == buf_r) return -1; //return -1 to signal buffer full
|
||||||
ptr[1] = buf_w; //store write index
|
ptr[1] = buf_w; //store write index
|
||||||
return 0; //return 0 to signal success
|
return 0; //return 0 to signal success
|
||||||
//#else //_NO_ASM
|
//#else //_NO_ASM
|
||||||
// TODO - optimized assembler version
|
// TODO - optimized assembler version
|
||||||
// asm("movw r26, r24");
|
// asm("movw r26, r24");
|
||||||
|
|
@ -47,17 +47,17 @@ int rbuf_put(uint8_t* ptr, uint8_t b)
|
||||||
int rbuf_get(uint8_t* ptr)
|
int rbuf_get(uint8_t* ptr)
|
||||||
{
|
{
|
||||||
//#ifdef _NO_ASM
|
//#ifdef _NO_ASM
|
||||||
_lock(); //lock
|
_lock(); //lock
|
||||||
uint8_t buf_w = ptr[1]; //get write index
|
uint8_t buf_w = ptr[1]; //get write index
|
||||||
uint8_t buf_r = ptr[2]; //get read index
|
uint8_t buf_r = ptr[2]; //get read index
|
||||||
_unlock(); //unlock
|
_unlock(); //unlock
|
||||||
if (buf_r == buf_w) return -1; //return -1 to signal buffer empty
|
if (buf_r == buf_w) return -1; //return -1 to signal buffer empty
|
||||||
int ret = ptr[4 + buf_r]; //get byte from buffer
|
int ret = ptr[4 + buf_r]; //get byte from buffer
|
||||||
buf_r++; //increment read index
|
buf_r++; //increment read index
|
||||||
uint8_t buf_l = ptr[0]; //get length
|
uint8_t buf_l = ptr[0]; //get length
|
||||||
if (buf_r >= buf_l) buf_r = 0; //rotate read index
|
if (buf_r >= buf_l) buf_r = 0; //rotate read index
|
||||||
ptr[2] = buf_r; //store read index
|
ptr[2] = buf_r; //store read index
|
||||||
return ret; //return byte (0-255)
|
return ret; //return byte (0-255)
|
||||||
// return 0; //return 0 to signal success
|
// return 0; //return 0 to signal success
|
||||||
//#else //_NO_ASM
|
//#else //_NO_ASM
|
||||||
// TODO - optimized assembler version
|
// TODO - optimized assembler version
|
||||||
|
|
|
||||||
240
Firmware/sm4.c
240
Firmware/sm4.c
|
|
@ -47,148 +47,180 @@ uint16_t sm4_cpu_time = 0;
|
||||||
|
|
||||||
uint8_t sm4_get_dir(uint8_t axis)
|
uint8_t sm4_get_dir(uint8_t axis)
|
||||||
{
|
{
|
||||||
switch (axis)
|
switch (axis)
|
||||||
{
|
{
|
||||||
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
||||||
case 0: return (PORTL & 2)?0:1;
|
case 0:
|
||||||
case 1: return (PORTL & 1)?0:1;
|
return (PORTL & 2)?0:1;
|
||||||
case 2: return (PORTL & 4)?0:1;
|
case 1:
|
||||||
case 3: return (PORTL & 64)?1:0;
|
return (PORTL & 1)?0:1;
|
||||||
|
case 2:
|
||||||
|
return (PORTL & 4)?0:1;
|
||||||
|
case 3:
|
||||||
|
return (PORTL & 64)?1:0;
|
||||||
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
||||||
case 0: return (PORTL & 1)?1:0;
|
case 0:
|
||||||
case 1: return (PORTL & 2)?0:1;
|
return (PORTL & 1)?1:0;
|
||||||
case 2: return (PORTL & 4)?1:0;
|
case 1:
|
||||||
case 3: return (PORTL & 64)?0:1;
|
return (PORTL & 2)?0:1;
|
||||||
|
case 2:
|
||||||
|
return (PORTL & 4)?1:0;
|
||||||
|
case 3:
|
||||||
|
return (PORTL & 64)?0:1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sm4_set_dir(uint8_t axis, uint8_t dir)
|
void sm4_set_dir(uint8_t axis, uint8_t dir)
|
||||||
{
|
{
|
||||||
switch (axis)
|
switch (axis)
|
||||||
{
|
{
|
||||||
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
||||||
case 0: if (!dir) PORTL |= 2; else PORTL &= ~2; break;
|
case 0:
|
||||||
case 1: if (!dir) PORTL |= 1; else PORTL &= ~1; break;
|
if (!dir) PORTL |= 2;
|
||||||
case 2: if (!dir) PORTL |= 4; else PORTL &= ~4; break;
|
else PORTL &= ~2;
|
||||||
case 3: if (dir) PORTL |= 64; else PORTL &= ~64; break;
|
break;
|
||||||
|
case 1:
|
||||||
|
if (!dir) PORTL |= 1;
|
||||||
|
else PORTL &= ~1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!dir) PORTL |= 4;
|
||||||
|
else PORTL &= ~4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (dir) PORTL |= 64;
|
||||||
|
else PORTL &= ~64;
|
||||||
|
break;
|
||||||
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
||||||
case 0: if (dir) PORTL |= 1; else PORTL &= ~1; break;
|
case 0:
|
||||||
case 1: if (!dir) PORTL |= 2; else PORTL &= ~2; break;
|
if (dir) PORTL |= 1;
|
||||||
case 2: if (dir) PORTL |= 4; else PORTL &= ~4; break;
|
else PORTL &= ~1;
|
||||||
case 3: if (!dir) PORTL |= 64; else PORTL &= ~64; break;
|
break;
|
||||||
|
case 1:
|
||||||
|
if (!dir) PORTL |= 2;
|
||||||
|
else PORTL &= ~2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (dir) PORTL |= 4;
|
||||||
|
else PORTL &= ~4;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (!dir) PORTL |= 64;
|
||||||
|
else PORTL &= ~64;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
asm("nop");
|
asm("nop");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t sm4_get_dir_bits(void)
|
uint8_t sm4_get_dir_bits(void)
|
||||||
{
|
{
|
||||||
register uint8_t dir_bits = 0;
|
register uint8_t dir_bits = 0;
|
||||||
register uint8_t portL = PORTL;
|
register uint8_t portL = PORTL;
|
||||||
//TODO -optimize in asm
|
//TODO -optimize in asm
|
||||||
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
||||||
if (portL & 2) dir_bits |= 1;
|
if (portL & 2) dir_bits |= 1;
|
||||||
if (portL & 1) dir_bits |= 2;
|
if (portL & 1) dir_bits |= 2;
|
||||||
if (portL & 4) dir_bits |= 4;
|
if (portL & 4) dir_bits |= 4;
|
||||||
if (portL & 64) dir_bits |= 8;
|
if (portL & 64) dir_bits |= 8;
|
||||||
dir_bits ^= 0x07; //invert XYZ, do not invert E
|
dir_bits ^= 0x07; //invert XYZ, do not invert E
|
||||||
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
||||||
if (portL & 1) dir_bits |= 1;
|
if (portL & 1) dir_bits |= 1;
|
||||||
if (portL & 2) dir_bits |= 2;
|
if (portL & 2) dir_bits |= 2;
|
||||||
if (portL & 4) dir_bits |= 4;
|
if (portL & 4) dir_bits |= 4;
|
||||||
if (portL & 64) dir_bits |= 8;
|
if (portL & 64) dir_bits |= 8;
|
||||||
dir_bits ^= 0x0a; //invert YE, do not invert XZ
|
dir_bits ^= 0x0a; //invert YE, do not invert XZ
|
||||||
#endif
|
#endif
|
||||||
return dir_bits;
|
return dir_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sm4_set_dir_bits(uint8_t dir_bits)
|
void sm4_set_dir_bits(uint8_t dir_bits)
|
||||||
{
|
{
|
||||||
register uint8_t portL = PORTL;
|
register uint8_t portL = PORTL;
|
||||||
portL &= 0xb8; //set direction bits to zero
|
portL &= 0xb8; //set direction bits to zero
|
||||||
//TODO -optimize in asm
|
//TODO -optimize in asm
|
||||||
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
|
||||||
dir_bits ^= 0x07; //invert XYZ, do not invert E
|
dir_bits ^= 0x07; //invert XYZ, do not invert E
|
||||||
if (dir_bits & 1) portL |= 2; //set X direction bit
|
if (dir_bits & 1) portL |= 2; //set X direction bit
|
||||||
if (dir_bits & 2) portL |= 1; //set Y direction bit
|
if (dir_bits & 2) portL |= 1; //set Y direction bit
|
||||||
if (dir_bits & 4) portL |= 4; //set Z direction bit
|
if (dir_bits & 4) portL |= 4; //set Z direction bit
|
||||||
if (dir_bits & 8) portL |= 64; //set E direction bit
|
if (dir_bits & 8) portL |= 64; //set E direction bit
|
||||||
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
#elif ((MOTHERBOARD == BOARD_EINSY_1_0a))
|
||||||
dir_bits ^= 0x0a; //invert YE, do not invert XZ
|
dir_bits ^= 0x0a; //invert YE, do not invert XZ
|
||||||
if (dir_bits & 1) portL |= 1; //set X direction bit
|
if (dir_bits & 1) portL |= 1; //set X direction bit
|
||||||
if (dir_bits & 2) portL |= 2; //set Y direction bit
|
if (dir_bits & 2) portL |= 2; //set Y direction bit
|
||||||
if (dir_bits & 4) portL |= 4; //set Z direction bit
|
if (dir_bits & 4) portL |= 4; //set Z direction bit
|
||||||
if (dir_bits & 8) portL |= 64; //set E direction bit
|
if (dir_bits & 8) portL |= 64; //set E direction bit
|
||||||
#endif
|
#endif
|
||||||
PORTL = portL;
|
PORTL = portL;
|
||||||
asm("nop");
|
asm("nop");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sm4_do_step(uint8_t axes_mask)
|
void sm4_do_step(uint8_t axes_mask)
|
||||||
{
|
{
|
||||||
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3) || (MOTHERBOARD == BOARD_EINSY_1_0a))
|
#if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3) || (MOTHERBOARD == BOARD_EINSY_1_0a))
|
||||||
register uint8_t portC = PORTC & 0xf0;
|
register uint8_t portC = PORTC & 0xf0;
|
||||||
PORTC = portC | (axes_mask & 0x0f); //set step signals by mask
|
PORTC = portC | (axes_mask & 0x0f); //set step signals by mask
|
||||||
asm("nop");
|
asm("nop");
|
||||||
PORTC = portC; //set step signals to zero
|
PORTC = portC; //set step signals to zero
|
||||||
asm("nop");
|
asm("nop");
|
||||||
#endif //((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3) || (MOTHERBOARD == BOARD_EINSY_1_0a))
|
#endif //((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3) || (MOTHERBOARD == BOARD_EINSY_1_0a))
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t sm4_line_xyze_ui(uint16_t dx, uint16_t dy, uint16_t dz, uint16_t de)
|
uint16_t sm4_line_xyze_ui(uint16_t dx, uint16_t dy, uint16_t dz, uint16_t de)
|
||||||
{
|
{
|
||||||
uint16_t dd = (uint16_t)(sqrt((float)(((uint32_t)dx)*dx + ((uint32_t)dy*dy) + ((uint32_t)dz*dz) + ((uint32_t)de*de))) + 0.5);
|
uint16_t dd = (uint16_t)(sqrt((float)(((uint32_t)dx)*dx + ((uint32_t)dy*dy) + ((uint32_t)dz*dz) + ((uint32_t)de*de))) + 0.5);
|
||||||
uint16_t nd = dd;
|
uint16_t nd = dd;
|
||||||
uint16_t cx = dd;
|
uint16_t cx = dd;
|
||||||
uint16_t cy = dd;
|
uint16_t cy = dd;
|
||||||
uint16_t cz = dd;
|
uint16_t cz = dd;
|
||||||
uint16_t ce = dd;
|
uint16_t ce = dd;
|
||||||
uint16_t x = 0;
|
uint16_t x = 0;
|
||||||
uint16_t y = 0;
|
uint16_t y = 0;
|
||||||
uint16_t z = 0;
|
uint16_t z = 0;
|
||||||
uint16_t e = 0;
|
uint16_t e = 0;
|
||||||
while (nd)
|
while (nd)
|
||||||
{
|
{
|
||||||
if (sm4_stop_cb && (*sm4_stop_cb)()) break;
|
if (sm4_stop_cb && (*sm4_stop_cb)()) break;
|
||||||
uint8_t sm = 0; //step mask
|
uint8_t sm = 0; //step mask
|
||||||
if (cx <= dx)
|
if (cx <= dx)
|
||||||
{
|
{
|
||||||
sm |= 1;
|
sm |= 1;
|
||||||
cx += dd;
|
cx += dd;
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
if (cy <= dy)
|
if (cy <= dy)
|
||||||
{
|
{
|
||||||
sm |= 2;
|
sm |= 2;
|
||||||
cy += dd;
|
cy += dd;
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
if (cz <= dz)
|
if (cz <= dz)
|
||||||
{
|
{
|
||||||
sm |= 4;
|
sm |= 4;
|
||||||
cz += dd;
|
cz += dd;
|
||||||
z++;
|
z++;
|
||||||
}
|
}
|
||||||
if (ce <= de)
|
if (ce <= de)
|
||||||
{
|
{
|
||||||
sm |= 4;
|
sm |= 4;
|
||||||
ce += dd;
|
ce += dd;
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
cx -= dx;
|
cx -= dx;
|
||||||
cy -= dy;
|
cy -= dy;
|
||||||
cz -= dz;
|
cz -= dz;
|
||||||
ce -= de;
|
ce -= de;
|
||||||
sm4_do_step(sm);
|
sm4_do_step(sm);
|
||||||
uint16_t delay = SM4_DEFDELAY;
|
uint16_t delay = SM4_DEFDELAY;
|
||||||
if (sm4_calc_delay_cb) delay = (*sm4_calc_delay_cb)(nd, dd);
|
if (sm4_calc_delay_cb) delay = (*sm4_calc_delay_cb)(nd, dd);
|
||||||
if (delay) delayMicroseconds(delay);
|
if (delay) delayMicroseconds(delay);
|
||||||
nd--;
|
nd--;
|
||||||
}
|
}
|
||||||
if (sm4_update_pos_cb) (*sm4_update_pos_cb)(x, y, z, e);
|
if (sm4_update_pos_cb) (*sm4_update_pos_cb)(x, y, z, e);
|
||||||
return nd;
|
return nd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,107 +21,107 @@ static void Sound_DoSound_Alert(bool bOnce);
|
||||||
|
|
||||||
void Sound_Init(void)
|
void Sound_Init(void)
|
||||||
{
|
{
|
||||||
SET_OUTPUT(BEEPER);
|
SET_OUTPUT(BEEPER);
|
||||||
eSoundMode=(eSOUND_MODE)eeprom_read_byte((uint8_t*)EEPROM_SOUND_MODE);
|
eSoundMode=(eSOUND_MODE)eeprom_read_byte((uint8_t*)EEPROM_SOUND_MODE);
|
||||||
if(eSoundMode==e_SOUND_MODE_NULL)
|
if(eSoundMode==e_SOUND_MODE_NULL)
|
||||||
Sound_Default(); // je potreba provest i ulozeni do EEPROM
|
Sound_Default(); // je potreba provest i ulozeni do EEPROM
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound_Default(void)
|
void Sound_Default(void)
|
||||||
{
|
{
|
||||||
eSoundMode=e_SOUND_MODE_DEFAULT;
|
eSoundMode=e_SOUND_MODE_DEFAULT;
|
||||||
Sound_SaveMode();
|
Sound_SaveMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound_SaveMode(void)
|
void Sound_SaveMode(void)
|
||||||
{
|
{
|
||||||
eeprom_update_byte((uint8_t*)EEPROM_SOUND_MODE,(uint8_t)eSoundMode);
|
eeprom_update_byte((uint8_t*)EEPROM_SOUND_MODE,(uint8_t)eSoundMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound_CycleState(void)
|
void Sound_CycleState(void)
|
||||||
{
|
{
|
||||||
switch(eSoundMode)
|
switch(eSoundMode)
|
||||||
{
|
{
|
||||||
case e_SOUND_MODE_LOUD:
|
case e_SOUND_MODE_LOUD:
|
||||||
eSoundMode=e_SOUND_MODE_ONCE;
|
eSoundMode=e_SOUND_MODE_ONCE;
|
||||||
break;
|
break;
|
||||||
case e_SOUND_MODE_ONCE:
|
case e_SOUND_MODE_ONCE:
|
||||||
eSoundMode=e_SOUND_MODE_SILENT;
|
eSoundMode=e_SOUND_MODE_SILENT;
|
||||||
break;
|
break;
|
||||||
case e_SOUND_MODE_SILENT:
|
case e_SOUND_MODE_SILENT:
|
||||||
eSoundMode=e_SOUND_MODE_MUTE;
|
eSoundMode=e_SOUND_MODE_MUTE;
|
||||||
break;
|
break;
|
||||||
case e_SOUND_MODE_MUTE:
|
case e_SOUND_MODE_MUTE:
|
||||||
eSoundMode=e_SOUND_MODE_LOUD;
|
eSoundMode=e_SOUND_MODE_LOUD;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
eSoundMode=e_SOUND_MODE_LOUD;
|
eSoundMode=e_SOUND_MODE_LOUD;
|
||||||
}
|
}
|
||||||
Sound_SaveMode();
|
Sound_SaveMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound_MakeSound(eSOUND_TYPE eSoundType)
|
void Sound_MakeSound(eSOUND_TYPE eSoundType)
|
||||||
{
|
{
|
||||||
switch(eSoundMode)
|
switch(eSoundMode)
|
||||||
{
|
{
|
||||||
case e_SOUND_MODE_LOUD:
|
case e_SOUND_MODE_LOUD:
|
||||||
if(eSoundType==e_SOUND_TYPE_ButtonEcho)
|
if(eSoundType==e_SOUND_TYPE_ButtonEcho)
|
||||||
Sound_DoSound_Echo();
|
Sound_DoSound_Echo();
|
||||||
if(eSoundType==e_SOUND_TYPE_StandardPrompt)
|
if(eSoundType==e_SOUND_TYPE_StandardPrompt)
|
||||||
Sound_DoSound_Prompt();
|
Sound_DoSound_Prompt();
|
||||||
if(eSoundType==e_SOUND_TYPE_StandardAlert)
|
if(eSoundType==e_SOUND_TYPE_StandardAlert)
|
||||||
Sound_DoSound_Alert(false);
|
Sound_DoSound_Alert(false);
|
||||||
break;
|
break;
|
||||||
case e_SOUND_MODE_ONCE:
|
case e_SOUND_MODE_ONCE:
|
||||||
if(eSoundType==e_SOUND_TYPE_ButtonEcho)
|
if(eSoundType==e_SOUND_TYPE_ButtonEcho)
|
||||||
Sound_DoSound_Echo();
|
Sound_DoSound_Echo();
|
||||||
if(eSoundType==e_SOUND_TYPE_StandardPrompt)
|
if(eSoundType==e_SOUND_TYPE_StandardPrompt)
|
||||||
Sound_DoSound_Prompt();
|
Sound_DoSound_Prompt();
|
||||||
if(eSoundType==e_SOUND_TYPE_StandardAlert)
|
if(eSoundType==e_SOUND_TYPE_StandardAlert)
|
||||||
Sound_DoSound_Alert(true);
|
Sound_DoSound_Alert(true);
|
||||||
break;
|
break;
|
||||||
case e_SOUND_MODE_SILENT:
|
case e_SOUND_MODE_SILENT:
|
||||||
if(eSoundType==e_SOUND_TYPE_StandardAlert)
|
if(eSoundType==e_SOUND_TYPE_StandardAlert)
|
||||||
Sound_DoSound_Alert(true);
|
Sound_DoSound_Alert(true);
|
||||||
break;
|
break;
|
||||||
case e_SOUND_MODE_MUTE:
|
case e_SOUND_MODE_MUTE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void Sound_DoSound_Echo(void)
|
static void Sound_DoSound_Echo(void)
|
||||||
{
|
{
|
||||||
uint8_t nI;
|
uint8_t nI;
|
||||||
|
|
||||||
for(nI=0;nI<10;nI++)
|
for(nI=0; nI<10; nI++)
|
||||||
{
|
{
|
||||||
WRITE(BEEPER,HIGH);
|
WRITE(BEEPER,HIGH);
|
||||||
delayMicroseconds(100);
|
delayMicroseconds(100);
|
||||||
WRITE(BEEPER,LOW);
|
WRITE(BEEPER,LOW);
|
||||||
delayMicroseconds(100);
|
delayMicroseconds(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Sound_DoSound_Prompt(void)
|
static void Sound_DoSound_Prompt(void)
|
||||||
{
|
{
|
||||||
WRITE(BEEPER,HIGH);
|
WRITE(BEEPER,HIGH);
|
||||||
delay_keep_alive(500);
|
delay_keep_alive(500);
|
||||||
WRITE(BEEPER,LOW);
|
WRITE(BEEPER,LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Sound_DoSound_Alert(bool bOnce)
|
static void Sound_DoSound_Alert(bool bOnce)
|
||||||
{
|
{
|
||||||
uint8_t nI,nMax;
|
uint8_t nI,nMax;
|
||||||
|
|
||||||
nMax=bOnce?1:3;
|
nMax=bOnce?1:3;
|
||||||
for(nI=0;nI<nMax;nI++)
|
for(nI=0; nI<nMax; nI++)
|
||||||
{
|
{
|
||||||
WRITE(BEEPER,HIGH);
|
WRITE(BEEPER,HIGH);
|
||||||
delay_keep_alive(200);
|
delay_keep_alive(200);
|
||||||
WRITE(BEEPER,LOW);
|
WRITE(BEEPER,LOW);
|
||||||
delay_keep_alive(500);
|
delay_keep_alive(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,13 @@
|
||||||
|
|
||||||
#define e_SOUND_MODE_NULL 0xFF
|
#define e_SOUND_MODE_NULL 0xFF
|
||||||
typedef enum
|
typedef enum
|
||||||
{e_SOUND_MODE_LOUD,e_SOUND_MODE_ONCE,e_SOUND_MODE_SILENT,e_SOUND_MODE_MUTE} eSOUND_MODE;
|
{e_SOUND_MODE_LOUD,e_SOUND_MODE_ONCE,e_SOUND_MODE_SILENT,e_SOUND_MODE_MUTE} eSOUND_MODE;
|
||||||
#define e_SOUND_MODE_DEFAULT e_SOUND_MODE_LOUD
|
#define e_SOUND_MODE_DEFAULT e_SOUND_MODE_LOUD
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{e_SOUND_TYPE_ButtonEcho,e_SOUND_TYPE_EncoderEcho,e_SOUND_TYPE_StandardPrompt,e_SOUND_TYPE_StandardConfirm,e_SOUND_TYPE_StandardWarning,e_SOUND_TYPE_StandardAlert} eSOUND_TYPE;
|
{e_SOUND_TYPE_ButtonEcho,e_SOUND_TYPE_EncoderEcho,e_SOUND_TYPE_StandardPrompt,e_SOUND_TYPE_StandardConfirm,e_SOUND_TYPE_StandardWarning,e_SOUND_TYPE_StandardAlert} eSOUND_TYPE;
|
||||||
typedef enum
|
typedef enum
|
||||||
{e_SOUND_CLASS_Echo,e_SOUND_CLASS_Prompt,e_SOUND_CLASS_Confirm,e_SOUND_CLASS_Warning,e_SOUND_CLASS_Alert} eSOUND_CLASS;
|
{e_SOUND_CLASS_Echo,e_SOUND_CLASS_Prompt,e_SOUND_CLASS_Confirm,e_SOUND_CLASS_Warning,e_SOUND_CLASS_Alert} eSOUND_CLASS;
|
||||||
|
|
||||||
|
|
||||||
extern eSOUND_MODE eSoundMode;
|
extern eSOUND_MODE eSoundMode;
|
||||||
|
|
|
||||||
|
|
@ -6,145 +6,145 @@
|
||||||
#if F_CPU == 16000000
|
#if F_CPU == 16000000
|
||||||
|
|
||||||
const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\
|
const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {\
|
||||||
{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135},
|
{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135},
|
||||||
{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32},
|
{ 961, 105}, { 856, 85}, { 771, 69}, { 702, 58}, { 644, 49}, { 595, 42}, { 553, 37}, { 516, 32},
|
||||||
{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14},
|
{ 484, 28}, { 456, 25}, { 431, 23}, { 408, 20}, { 388, 19}, { 369, 16}, { 353, 16}, { 337, 14},
|
||||||
{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8},
|
{ 323, 13}, { 310, 11}, { 299, 11}, { 288, 11}, { 277, 9}, { 268, 9}, { 259, 8}, { 251, 8},
|
||||||
{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5},
|
{ 243, 8}, { 235, 7}, { 228, 6}, { 222, 6}, { 216, 6}, { 210, 6}, { 204, 5}, { 199, 5},
|
||||||
{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3},
|
{ 194, 5}, { 189, 4}, { 185, 4}, { 181, 4}, { 177, 4}, { 173, 4}, { 169, 4}, { 165, 3},
|
||||||
{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2},
|
{ 162, 3}, { 159, 4}, { 155, 3}, { 152, 3}, { 149, 2}, { 147, 3}, { 144, 3}, { 141, 2},
|
||||||
{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2},
|
{ 139, 3}, { 136, 2}, { 134, 2}, { 132, 3}, { 129, 2}, { 127, 2}, { 125, 2}, { 123, 2},
|
||||||
{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1},
|
{ 121, 2}, { 119, 1}, { 118, 2}, { 116, 2}, { 114, 1}, { 113, 2}, { 111, 2}, { 109, 1},
|
||||||
{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1},
|
{ 108, 2}, { 106, 1}, { 105, 2}, { 103, 1}, { 102, 1}, { 101, 1}, { 100, 2}, { 98, 1},
|
||||||
{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1},
|
{ 97, 1}, { 96, 1}, { 95, 2}, { 93, 1}, { 92, 1}, { 91, 1}, { 90, 1}, { 89, 1},
|
||||||
{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1},
|
{ 88, 1}, { 87, 1}, { 86, 1}, { 85, 1}, { 84, 1}, { 83, 0}, { 83, 1}, { 82, 1},
|
||||||
{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0},
|
{ 81, 1}, { 80, 1}, { 79, 1}, { 78, 0}, { 78, 1}, { 77, 1}, { 76, 1}, { 75, 0},
|
||||||
{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1},
|
{ 75, 1}, { 74, 1}, { 73, 1}, { 72, 0}, { 72, 1}, { 71, 1}, { 70, 0}, { 70, 1},
|
||||||
{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0},
|
{ 69, 0}, { 69, 1}, { 68, 1}, { 67, 0}, { 67, 1}, { 66, 0}, { 66, 1}, { 65, 0},
|
||||||
{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1},
|
{ 65, 1}, { 64, 1}, { 63, 0}, { 63, 1}, { 62, 0}, { 62, 1}, { 61, 0}, { 61, 1},
|
||||||
{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0},
|
{ 60, 0}, { 60, 0}, { 60, 1}, { 59, 0}, { 59, 1}, { 58, 0}, { 58, 1}, { 57, 0},
|
||||||
{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0},
|
{ 57, 1}, { 56, 0}, { 56, 0}, { 56, 1}, { 55, 0}, { 55, 1}, { 54, 0}, { 54, 0},
|
||||||
{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0},
|
{ 54, 1}, { 53, 0}, { 53, 0}, { 53, 1}, { 52, 0}, { 52, 0}, { 52, 1}, { 51, 0},
|
||||||
{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1},
|
{ 51, 0}, { 51, 1}, { 50, 0}, { 50, 0}, { 50, 1}, { 49, 0}, { 49, 0}, { 49, 1},
|
||||||
{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0},
|
{ 48, 0}, { 48, 0}, { 48, 1}, { 47, 0}, { 47, 0}, { 47, 0}, { 47, 1}, { 46, 0},
|
||||||
{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0},
|
{ 46, 0}, { 46, 1}, { 45, 0}, { 45, 0}, { 45, 0}, { 45, 1}, { 44, 0}, { 44, 0},
|
||||||
{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0},
|
{ 44, 0}, { 44, 1}, { 43, 0}, { 43, 0}, { 43, 0}, { 43, 1}, { 42, 0}, { 42, 0},
|
||||||
{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0},
|
{ 42, 0}, { 42, 1}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 0}, { 41, 1}, { 40, 0},
|
||||||
{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0},
|
{ 40, 0}, { 40, 0}, { 40, 0}, { 40, 1}, { 39, 0}, { 39, 0}, { 39, 0}, { 39, 0},
|
||||||
{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0},
|
{ 39, 1}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 0}, { 38, 1}, { 37, 0}, { 37, 0},
|
||||||
{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0},
|
{ 37, 0}, { 37, 0}, { 37, 0}, { 37, 1}, { 36, 0}, { 36, 0}, { 36, 0}, { 36, 0},
|
||||||
{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1},
|
{ 36, 1}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 0}, { 35, 1},
|
||||||
{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0},
|
{ 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 0}, { 34, 1}, { 33, 0}, { 33, 0},
|
||||||
{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0},
|
{ 33, 0}, { 33, 0}, { 33, 0}, { 33, 0}, { 33, 1}, { 32, 0}, { 32, 0}, { 32, 0},
|
||||||
{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0},
|
{ 32, 0}, { 32, 0}, { 32, 0}, { 32, 0}, { 32, 1}, { 31, 0}, { 31, 0}, { 31, 0},
|
||||||
{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0}
|
{ 31, 0}, { 31, 0}, { 31, 0}, { 31, 1}, { 30, 0}, { 30, 0}, { 30, 0}, { 30, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\
|
const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {\
|
||||||
{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894},
|
{ 62500, 12500}, { 50000, 8334}, { 41666, 5952}, { 35714, 4464}, { 31250, 3473}, { 27777, 2777}, { 25000, 2273}, { 22727, 1894},
|
||||||
{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657},
|
{ 20833, 1603}, { 19230, 1373}, { 17857, 1191}, { 16666, 1041}, { 15625, 920}, { 14705, 817}, { 13888, 731}, { 13157, 657},
|
||||||
{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331},
|
{ 12500, 596}, { 11904, 541}, { 11363, 494}, { 10869, 453}, { 10416, 416}, { 10000, 385}, { 9615, 356}, { 9259, 331},
|
||||||
{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198},
|
{ 8928, 308}, { 8620, 287}, { 8333, 269}, { 8064, 252}, { 7812, 237}, { 7575, 223}, { 7352, 210}, { 7142, 198},
|
||||||
{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132},
|
{ 6944, 188}, { 6756, 178}, { 6578, 168}, { 6410, 160}, { 6250, 153}, { 6097, 145}, { 5952, 139}, { 5813, 132},
|
||||||
{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94},
|
{ 5681, 126}, { 5555, 121}, { 5434, 115}, { 5319, 111}, { 5208, 106}, { 5102, 102}, { 5000, 99}, { 4901, 94},
|
||||||
{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71},
|
{ 4807, 91}, { 4716, 87}, { 4629, 84}, { 4545, 81}, { 4464, 79}, { 4385, 75}, { 4310, 73}, { 4237, 71},
|
||||||
{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55},
|
{ 4166, 68}, { 4098, 66}, { 4032, 64}, { 3968, 62}, { 3906, 60}, { 3846, 59}, { 3787, 56}, { 3731, 55},
|
||||||
{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44},
|
{ 3676, 53}, { 3623, 52}, { 3571, 50}, { 3521, 49}, { 3472, 48}, { 3424, 46}, { 3378, 45}, { 3333, 44},
|
||||||
{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36},
|
{ 3289, 43}, { 3246, 41}, { 3205, 41}, { 3164, 39}, { 3125, 39}, { 3086, 38}, { 3048, 36}, { 3012, 36},
|
||||||
{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30},
|
{ 2976, 35}, { 2941, 35}, { 2906, 33}, { 2873, 33}, { 2840, 32}, { 2808, 31}, { 2777, 30}, { 2747, 30},
|
||||||
{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25},
|
{ 2717, 29}, { 2688, 29}, { 2659, 28}, { 2631, 27}, { 2604, 27}, { 2577, 26}, { 2551, 26}, { 2525, 25},
|
||||||
{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22},
|
{ 2500, 25}, { 2475, 25}, { 2450, 23}, { 2427, 24}, { 2403, 23}, { 2380, 22}, { 2358, 22}, { 2336, 22},
|
||||||
{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18},
|
{ 2314, 21}, { 2293, 21}, { 2272, 20}, { 2252, 20}, { 2232, 20}, { 2212, 20}, { 2192, 19}, { 2173, 18},
|
||||||
{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16},
|
{ 2155, 19}, { 2136, 18}, { 2118, 18}, { 2100, 17}, { 2083, 17}, { 2066, 17}, { 2049, 17}, { 2032, 16},
|
||||||
{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15},
|
{ 2016, 16}, { 2000, 16}, { 1984, 16}, { 1968, 15}, { 1953, 16}, { 1937, 14}, { 1923, 15}, { 1908, 15},
|
||||||
{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13},
|
{ 1893, 14}, { 1879, 14}, { 1865, 14}, { 1851, 13}, { 1838, 14}, { 1824, 13}, { 1811, 13}, { 1798, 13},
|
||||||
{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11},
|
{ 1785, 12}, { 1773, 13}, { 1760, 12}, { 1748, 12}, { 1736, 12}, { 1724, 12}, { 1712, 12}, { 1700, 11},
|
||||||
{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10},
|
{ 1689, 12}, { 1677, 11}, { 1666, 11}, { 1655, 11}, { 1644, 11}, { 1633, 10}, { 1623, 11}, { 1612, 10},
|
||||||
{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9},
|
{ 1602, 10}, { 1592, 10}, { 1582, 10}, { 1572, 10}, { 1562, 10}, { 1552, 9}, { 1543, 10}, { 1533, 9},
|
||||||
{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8},
|
{ 1524, 9}, { 1515, 9}, { 1506, 9}, { 1497, 9}, { 1488, 9}, { 1479, 9}, { 1470, 9}, { 1461, 8},
|
||||||
{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8},
|
{ 1453, 8}, { 1445, 9}, { 1436, 8}, { 1428, 8}, { 1420, 8}, { 1412, 8}, { 1404, 8}, { 1396, 8},
|
||||||
{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7},
|
{ 1388, 7}, { 1381, 8}, { 1373, 7}, { 1366, 8}, { 1358, 7}, { 1351, 7}, { 1344, 8}, { 1336, 7},
|
||||||
{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7},
|
{ 1329, 7}, { 1322, 7}, { 1315, 7}, { 1308, 6}, { 1302, 7}, { 1295, 7}, { 1288, 6}, { 1282, 7},
|
||||||
{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6},
|
{ 1275, 6}, { 1269, 7}, { 1262, 6}, { 1256, 6}, { 1250, 7}, { 1243, 6}, { 1237, 6}, { 1231, 6},
|
||||||
{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5},
|
{ 1225, 6}, { 1219, 6}, { 1213, 6}, { 1207, 6}, { 1201, 5}, { 1196, 6}, { 1190, 6}, { 1184, 5},
|
||||||
{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5},
|
{ 1179, 6}, { 1173, 5}, { 1168, 6}, { 1162, 5}, { 1157, 5}, { 1152, 6}, { 1146, 5}, { 1141, 5},
|
||||||
{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5},
|
{ 1136, 5}, { 1131, 5}, { 1126, 5}, { 1121, 5}, { 1116, 5}, { 1111, 5}, { 1106, 5}, { 1101, 5},
|
||||||
{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4},
|
{ 1096, 5}, { 1091, 5}, { 1086, 4}, { 1082, 5}, { 1077, 5}, { 1072, 4}, { 1068, 5}, { 1063, 4},
|
||||||
{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4},
|
{ 1059, 5}, { 1054, 4}, { 1050, 4}, { 1046, 5}, { 1041, 4}, { 1037, 4}, { 1033, 5}, { 1028, 4},
|
||||||
{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4},
|
{ 1024, 4}, { 1020, 4}, { 1016, 4}, { 1012, 4}, { 1008, 4}, { 1004, 4}, { 1000, 4}, { 996, 4},
|
||||||
{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3}
|
{ 992, 4}, { 988, 4}, { 984, 4}, { 980, 4}, { 976, 4}, { 972, 4}, { 968, 3}, { 965, 3}
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif F_CPU == 20000000
|
#elif F_CPU == 20000000
|
||||||
|
|
||||||
const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {
|
const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {
|
||||||
{62500, 54055}, {8445, 3917}, {4528, 1434}, {3094, 745}, {2349, 456}, {1893, 307}, {1586, 222}, {1364, 167},
|
{62500, 54055}, {8445, 3917}, {4528, 1434}, {3094, 745}, {2349, 456}, {1893, 307}, {1586, 222}, {1364, 167},
|
||||||
{1197, 131}, {1066, 105}, {961, 86}, {875, 72}, {803, 61}, {742, 53}, {689, 45}, {644, 40},
|
{1197, 131}, {1066, 105}, {961, 86}, {875, 72}, {803, 61}, {742, 53}, {689, 45}, {644, 40},
|
||||||
{604, 35}, {569, 32}, {537, 28}, {509, 25}, {484, 23}, {461, 21}, {440, 19}, {421, 17},
|
{604, 35}, {569, 32}, {537, 28}, {509, 25}, {484, 23}, {461, 21}, {440, 19}, {421, 17},
|
||||||
{404, 16}, {388, 15}, {373, 14}, {359, 13}, {346, 12}, {334, 11}, {323, 10}, {313, 10},
|
{404, 16}, {388, 15}, {373, 14}, {359, 13}, {346, 12}, {334, 11}, {323, 10}, {313, 10},
|
||||||
{303, 9}, {294, 9}, {285, 8}, {277, 7}, {270, 8}, {262, 7}, {255, 6}, {249, 6},
|
{303, 9}, {294, 9}, {285, 8}, {277, 7}, {270, 8}, {262, 7}, {255, 6}, {249, 6},
|
||||||
{243, 6}, {237, 6}, {231, 5}, {226, 5}, {221, 5}, {216, 5}, {211, 4}, {207, 5},
|
{243, 6}, {237, 6}, {231, 5}, {226, 5}, {221, 5}, {216, 5}, {211, 4}, {207, 5},
|
||||||
{202, 4}, {198, 4}, {194, 4}, {190, 3}, {187, 4}, {183, 3}, {180, 3}, {177, 4},
|
{202, 4}, {198, 4}, {194, 4}, {190, 3}, {187, 4}, {183, 3}, {180, 3}, {177, 4},
|
||||||
{173, 3}, {170, 3}, {167, 2}, {165, 3}, {162, 3}, {159, 2}, {157, 3}, {154, 2},
|
{173, 3}, {170, 3}, {167, 2}, {165, 3}, {162, 3}, {159, 2}, {157, 3}, {154, 2},
|
||||||
{152, 3}, {149, 2}, {147, 2}, {145, 2}, {143, 2}, {141, 2}, {139, 2}, {137, 2},
|
{152, 3}, {149, 2}, {147, 2}, {145, 2}, {143, 2}, {141, 2}, {139, 2}, {137, 2},
|
||||||
{135, 2}, {133, 2}, {131, 2}, {129, 1}, {128, 2}, {126, 2}, {124, 1}, {123, 2},
|
{135, 2}, {133, 2}, {131, 2}, {129, 1}, {128, 2}, {126, 2}, {124, 1}, {123, 2},
|
||||||
{121, 1}, {120, 2}, {118, 1}, {117, 1}, {116, 2}, {114, 1}, {113, 1}, {112, 2},
|
{121, 1}, {120, 2}, {118, 1}, {117, 1}, {116, 2}, {114, 1}, {113, 1}, {112, 2},
|
||||||
{110, 1}, {109, 1}, {108, 1}, {107, 2}, {105, 1}, {104, 1}, {103, 1}, {102, 1},
|
{110, 1}, {109, 1}, {108, 1}, {107, 2}, {105, 1}, {104, 1}, {103, 1}, {102, 1},
|
||||||
{101, 1}, {100, 1}, {99, 1}, {98, 1}, {97, 1}, {96, 1}, {95, 1}, {94, 1},
|
{101, 1}, {100, 1}, {99, 1}, {98, 1}, {97, 1}, {96, 1}, {95, 1}, {94, 1},
|
||||||
{93, 1}, {92, 1}, {91, 0}, {91, 1}, {90, 1}, {89, 1}, {88, 1}, {87, 0},
|
{93, 1}, {92, 1}, {91, 0}, {91, 1}, {90, 1}, {89, 1}, {88, 1}, {87, 0},
|
||||||
{87, 1}, {86, 1}, {85, 1}, {84, 0}, {84, 1}, {83, 1}, {82, 1}, {81, 0},
|
{87, 1}, {86, 1}, {85, 1}, {84, 0}, {84, 1}, {83, 1}, {82, 1}, {81, 0},
|
||||||
{81, 1}, {80, 1}, {79, 0}, {79, 1}, {78, 0}, {78, 1}, {77, 1}, {76, 0},
|
{81, 1}, {80, 1}, {79, 0}, {79, 1}, {78, 0}, {78, 1}, {77, 1}, {76, 0},
|
||||||
{76, 1}, {75, 0}, {75, 1}, {74, 1}, {73, 0}, {73, 1}, {72, 0}, {72, 1},
|
{76, 1}, {75, 0}, {75, 1}, {74, 1}, {73, 0}, {73, 1}, {72, 0}, {72, 1},
|
||||||
{71, 0}, {71, 1}, {70, 0}, {70, 1}, {69, 0}, {69, 1}, {68, 0}, {68, 1},
|
{71, 0}, {71, 1}, {70, 0}, {70, 1}, {69, 0}, {69, 1}, {68, 0}, {68, 1},
|
||||||
{67, 0}, {67, 1}, {66, 0}, {66, 1}, {65, 0}, {65, 0}, {65, 1}, {64, 0},
|
{67, 0}, {67, 1}, {66, 0}, {66, 1}, {65, 0}, {65, 0}, {65, 1}, {64, 0},
|
||||||
{64, 1}, {63, 0}, {63, 1}, {62, 0}, {62, 0}, {62, 1}, {61, 0}, {61, 1},
|
{64, 1}, {63, 0}, {63, 1}, {62, 0}, {62, 0}, {62, 1}, {61, 0}, {61, 1},
|
||||||
{60, 0}, {60, 0}, {60, 1}, {59, 0}, {59, 0}, {59, 1}, {58, 0}, {58, 0},
|
{60, 0}, {60, 0}, {60, 1}, {59, 0}, {59, 0}, {59, 1}, {58, 0}, {58, 0},
|
||||||
{58, 1}, {57, 0}, {57, 0}, {57, 1}, {56, 0}, {56, 0}, {56, 1}, {55, 0},
|
{58, 1}, {57, 0}, {57, 0}, {57, 1}, {56, 0}, {56, 0}, {56, 1}, {55, 0},
|
||||||
{55, 0}, {55, 1}, {54, 0}, {54, 0}, {54, 1}, {53, 0}, {53, 0}, {53, 0},
|
{55, 0}, {55, 1}, {54, 0}, {54, 0}, {54, 1}, {53, 0}, {53, 0}, {53, 0},
|
||||||
{53, 1}, {52, 0}, {52, 0}, {52, 1}, {51, 0}, {51, 0}, {51, 0}, {51, 1},
|
{53, 1}, {52, 0}, {52, 0}, {52, 1}, {51, 0}, {51, 0}, {51, 0}, {51, 1},
|
||||||
{50, 0}, {50, 0}, {50, 0}, {50, 1}, {49, 0}, {49, 0}, {49, 0}, {49, 1},
|
{50, 0}, {50, 0}, {50, 0}, {50, 1}, {49, 0}, {49, 0}, {49, 0}, {49, 1},
|
||||||
{48, 0}, {48, 0}, {48, 0}, {48, 1}, {47, 0}, {47, 0}, {47, 0}, {47, 1},
|
{48, 0}, {48, 0}, {48, 0}, {48, 1}, {47, 0}, {47, 0}, {47, 0}, {47, 1},
|
||||||
{46, 0}, {46, 0}, {46, 0}, {46, 0}, {46, 1}, {45, 0}, {45, 0}, {45, 0},
|
{46, 0}, {46, 0}, {46, 0}, {46, 0}, {46, 1}, {45, 0}, {45, 0}, {45, 0},
|
||||||
{45, 1}, {44, 0}, {44, 0}, {44, 0}, {44, 0}, {44, 1}, {43, 0}, {43, 0},
|
{45, 1}, {44, 0}, {44, 0}, {44, 0}, {44, 0}, {44, 1}, {43, 0}, {43, 0},
|
||||||
{43, 0}, {43, 0}, {43, 1}, {42, 0}, {42, 0}, {42, 0}, {42, 0}, {42, 0},
|
{43, 0}, {43, 0}, {43, 1}, {42, 0}, {42, 0}, {42, 0}, {42, 0}, {42, 0},
|
||||||
{42, 1}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 1}, {40, 0},
|
{42, 1}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 0}, {41, 1}, {40, 0},
|
||||||
{40, 0}, {40, 0}, {40, 0}, {40, 1}, {39, 0}, {39, 0}, {39, 0}, {39, 0},
|
{40, 0}, {40, 0}, {40, 0}, {40, 1}, {39, 0}, {39, 0}, {39, 0}, {39, 0},
|
||||||
{39, 0}, {39, 0}, {39, 1}, {38, 0}, {38, 0}, {38, 0}, {38, 0}, {38, 0},
|
{39, 0}, {39, 0}, {39, 1}, {38, 0}, {38, 0}, {38, 0}, {38, 0}, {38, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {
|
const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {
|
||||||
{62500, 10417}, {52083, 7441}, {44642, 5580}, {39062, 4340}, {34722, 3472}, {31250, 2841}, {28409, 2368}, {26041, 2003},
|
{62500, 10417}, {52083, 7441}, {44642, 5580}, {39062, 4340}, {34722, 3472}, {31250, 2841}, {28409, 2368}, {26041, 2003},
|
||||||
{24038, 1717}, {22321, 1488}, {20833, 1302}, {19531, 1149}, {18382, 1021}, {17361, 914}, {16447, 822}, {15625, 745},
|
{24038, 1717}, {22321, 1488}, {20833, 1302}, {19531, 1149}, {18382, 1021}, {17361, 914}, {16447, 822}, {15625, 745},
|
||||||
{14880, 676}, {14204, 618}, {13586, 566}, {13020, 520}, {12500, 481}, {12019, 445}, {11574, 414}, {11160, 385},
|
{14880, 676}, {14204, 618}, {13586, 566}, {13020, 520}, {12500, 481}, {12019, 445}, {11574, 414}, {11160, 385},
|
||||||
{10775, 359}, {10416, 336}, {10080, 315}, {9765, 296}, {9469, 278}, {9191, 263}, {8928, 248}, {8680, 235},
|
{10775, 359}, {10416, 336}, {10080, 315}, {9765, 296}, {9469, 278}, {9191, 263}, {8928, 248}, {8680, 235},
|
||||||
{8445, 222}, {8223, 211}, {8012, 200}, {7812, 191}, {7621, 181}, {7440, 173}, {7267, 165}, {7102, 158},
|
{8445, 222}, {8223, 211}, {8012, 200}, {7812, 191}, {7621, 181}, {7440, 173}, {7267, 165}, {7102, 158},
|
||||||
{6944, 151}, {6793, 145}, {6648, 138}, {6510, 133}, {6377, 127}, {6250, 123}, {6127, 118}, {6009, 113},
|
{6944, 151}, {6793, 145}, {6648, 138}, {6510, 133}, {6377, 127}, {6250, 123}, {6127, 118}, {6009, 113},
|
||||||
{5896, 109}, {5787, 106}, {5681, 101}, {5580, 98}, {5482, 95}, {5387, 91}, {5296, 88}, {5208, 86},
|
{5896, 109}, {5787, 106}, {5681, 101}, {5580, 98}, {5482, 95}, {5387, 91}, {5296, 88}, {5208, 86},
|
||||||
{5122, 82}, {5040, 80}, {4960, 78}, {4882, 75}, {4807, 73}, {4734, 70}, {4664, 69}, {4595, 67},
|
{5122, 82}, {5040, 80}, {4960, 78}, {4882, 75}, {4807, 73}, {4734, 70}, {4664, 69}, {4595, 67},
|
||||||
{4528, 64}, {4464, 63}, {4401, 61}, {4340, 60}, {4280, 58}, {4222, 56}, {4166, 55}, {4111, 53},
|
{4528, 64}, {4464, 63}, {4401, 61}, {4340, 60}, {4280, 58}, {4222, 56}, {4166, 55}, {4111, 53},
|
||||||
{4058, 52}, {4006, 51}, {3955, 49}, {3906, 48}, {3858, 48}, {3810, 45}, {3765, 45}, {3720, 44},
|
{4058, 52}, {4006, 51}, {3955, 49}, {3906, 48}, {3858, 48}, {3810, 45}, {3765, 45}, {3720, 44},
|
||||||
{3676, 43}, {3633, 42}, {3591, 40}, {3551, 40}, {3511, 39}, {3472, 38}, {3434, 38}, {3396, 36},
|
{3676, 43}, {3633, 42}, {3591, 40}, {3551, 40}, {3511, 39}, {3472, 38}, {3434, 38}, {3396, 36},
|
||||||
{3360, 36}, {3324, 35}, {3289, 34}, {3255, 34}, {3221, 33}, {3188, 32}, {3156, 31}, {3125, 31},
|
{3360, 36}, {3324, 35}, {3289, 34}, {3255, 34}, {3221, 33}, {3188, 32}, {3156, 31}, {3125, 31},
|
||||||
{3094, 31}, {3063, 30}, {3033, 29}, {3004, 28}, {2976, 28}, {2948, 28}, {2920, 27}, {2893, 27},
|
{3094, 31}, {3063, 30}, {3033, 29}, {3004, 28}, {2976, 28}, {2948, 28}, {2920, 27}, {2893, 27},
|
||||||
{2866, 26}, {2840, 25}, {2815, 25}, {2790, 25}, {2765, 24}, {2741, 24}, {2717, 24}, {2693, 23},
|
{2866, 26}, {2840, 25}, {2815, 25}, {2790, 25}, {2765, 24}, {2741, 24}, {2717, 24}, {2693, 23},
|
||||||
{2670, 22}, {2648, 22}, {2626, 22}, {2604, 22}, {2582, 21}, {2561, 21}, {2540, 20}, {2520, 20},
|
{2670, 22}, {2648, 22}, {2626, 22}, {2604, 22}, {2582, 21}, {2561, 21}, {2540, 20}, {2520, 20},
|
||||||
{2500, 20}, {2480, 20}, {2460, 19}, {2441, 19}, {2422, 19}, {2403, 18}, {2385, 18}, {2367, 18},
|
{2500, 20}, {2480, 20}, {2460, 19}, {2441, 19}, {2422, 19}, {2403, 18}, {2385, 18}, {2367, 18},
|
||||||
{2349, 17}, {2332, 18}, {2314, 17}, {2297, 16}, {2281, 17}, {2264, 16}, {2248, 16}, {2232, 16},
|
{2349, 17}, {2332, 18}, {2314, 17}, {2297, 16}, {2281, 17}, {2264, 16}, {2248, 16}, {2232, 16},
|
||||||
{2216, 16}, {2200, 15}, {2185, 15}, {2170, 15}, {2155, 15}, {2140, 15}, {2125, 14}, {2111, 14},
|
{2216, 16}, {2200, 15}, {2185, 15}, {2170, 15}, {2155, 15}, {2140, 15}, {2125, 14}, {2111, 14},
|
||||||
{2097, 14}, {2083, 14}, {2069, 14}, {2055, 13}, {2042, 13}, {2029, 13}, {2016, 13}, {2003, 13},
|
{2097, 14}, {2083, 14}, {2069, 14}, {2055, 13}, {2042, 13}, {2029, 13}, {2016, 13}, {2003, 13},
|
||||||
{1990, 13}, {1977, 12}, {1965, 12}, {1953, 13}, {1940, 11}, {1929, 12}, {1917, 12}, {1905, 12},
|
{1990, 13}, {1977, 12}, {1965, 12}, {1953, 13}, {1940, 11}, {1929, 12}, {1917, 12}, {1905, 12},
|
||||||
{1893, 11}, {1882, 11}, {1871, 11}, {1860, 11}, {1849, 11}, {1838, 11}, {1827, 11}, {1816, 10},
|
{1893, 11}, {1882, 11}, {1871, 11}, {1860, 11}, {1849, 11}, {1838, 11}, {1827, 11}, {1816, 10},
|
||||||
{1806, 11}, {1795, 10}, {1785, 10}, {1775, 10}, {1765, 10}, {1755, 10}, {1745, 9}, {1736, 10},
|
{1806, 11}, {1795, 10}, {1785, 10}, {1775, 10}, {1765, 10}, {1755, 10}, {1745, 9}, {1736, 10},
|
||||||
{1726, 9}, {1717, 10}, {1707, 9}, {1698, 9}, {1689, 9}, {1680, 9}, {1671, 9}, {1662, 9},
|
{1726, 9}, {1717, 10}, {1707, 9}, {1698, 9}, {1689, 9}, {1680, 9}, {1671, 9}, {1662, 9},
|
||||||
{1653, 9}, {1644, 8}, {1636, 9}, {1627, 8}, {1619, 9}, {1610, 8}, {1602, 8}, {1594, 8},
|
{1653, 9}, {1644, 8}, {1636, 9}, {1627, 8}, {1619, 9}, {1610, 8}, {1602, 8}, {1594, 8},
|
||||||
{1586, 8}, {1578, 8}, {1570, 8}, {1562, 8}, {1554, 7}, {1547, 8}, {1539, 8}, {1531, 7},
|
{1586, 8}, {1578, 8}, {1570, 8}, {1562, 8}, {1554, 7}, {1547, 8}, {1539, 8}, {1531, 7},
|
||||||
{1524, 8}, {1516, 7}, {1509, 7}, {1502, 7}, {1495, 7}, {1488, 7}, {1481, 7}, {1474, 7},
|
{1524, 8}, {1516, 7}, {1509, 7}, {1502, 7}, {1495, 7}, {1488, 7}, {1481, 7}, {1474, 7},
|
||||||
{1467, 7}, {1460, 7}, {1453, 7}, {1446, 6}, {1440, 7}, {1433, 7}, {1426, 6}, {1420, 6},
|
{1467, 7}, {1460, 7}, {1453, 7}, {1446, 6}, {1440, 7}, {1433, 7}, {1426, 6}, {1420, 6},
|
||||||
{1414, 7}, {1407, 6}, {1401, 6}, {1395, 7}, {1388, 6}, {1382, 6}, {1376, 6}, {1370, 6},
|
{1414, 7}, {1407, 6}, {1401, 6}, {1395, 7}, {1388, 6}, {1382, 6}, {1376, 6}, {1370, 6},
|
||||||
{1364, 6}, {1358, 6}, {1352, 6}, {1346, 5}, {1341, 6}, {1335, 6}, {1329, 5}, {1324, 6},
|
{1364, 6}, {1358, 6}, {1352, 6}, {1346, 5}, {1341, 6}, {1335, 6}, {1329, 5}, {1324, 6},
|
||||||
{1318, 5}, {1313, 6}, {1307, 5}, {1302, 6}, {1296, 5}, {1291, 5}, {1286, 6}, {1280, 5},
|
{1318, 5}, {1313, 6}, {1307, 5}, {1302, 6}, {1296, 5}, {1291, 5}, {1286, 6}, {1280, 5},
|
||||||
{1275, 5}, {1270, 5}, {1265, 5}, {1260, 5}, {1255, 5}, {1250, 5}, {1245, 5}, {1240, 5},
|
{1275, 5}, {1270, 5}, {1265, 5}, {1260, 5}, {1255, 5}, {1250, 5}, {1245, 5}, {1240, 5},
|
||||||
{1235, 5}, {1230, 5}, {1225, 5}, {1220, 5}, {1215, 4}, {1211, 5}, {1206, 5}, {1201, 5},
|
{1235, 5}, {1230, 5}, {1225, 5}, {1220, 5}, {1215, 4}, {1211, 5}, {1206, 5}, {1201, 5},
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -21,25 +21,25 @@ extern "C" {
|
||||||
|
|
||||||
static inline void spi_init()
|
static inline void spi_init()
|
||||||
{
|
{
|
||||||
DDRB &= ~((1 << DD_SCK) | (1 << DD_MOSI) | (1 << DD_MISO));
|
DDRB &= ~((1 << DD_SCK) | (1 << DD_MOSI) | (1 << DD_MISO));
|
||||||
DDRB |= (1 << DD_SS) | (1 << DD_SCK) | (1 << DD_MOSI);
|
DDRB |= (1 << DD_SS) | (1 << DD_SCK) | (1 << DD_MOSI);
|
||||||
PORTB &= ~((1 << DD_SCK) | (1 << DD_MOSI) | (1 << DD_MISO));
|
PORTB &= ~((1 << DD_SCK) | (1 << DD_MOSI) | (1 << DD_MISO));
|
||||||
PORTB |= (1 << DD_SS);
|
PORTB |= (1 << DD_SS);
|
||||||
SPCR = SPI_SPCR(0, 0, 0, 1, 0); //SPE=1, MSTR=1 (0x50)
|
SPCR = SPI_SPCR(0, 0, 0, 1, 0); //SPE=1, MSTR=1 (0x50)
|
||||||
SPSR = 0x00;
|
SPSR = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void spi_setup(uint8_t spcr, uint8_t spsr)
|
static inline void spi_setup(uint8_t spcr, uint8_t spsr)
|
||||||
{
|
{
|
||||||
SPCR = spcr;
|
SPCR = spcr;
|
||||||
SPSR = spsr;
|
SPSR = spsr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t spi_txrx(uint8_t tx)
|
static inline uint8_t spi_txrx(uint8_t tx)
|
||||||
{
|
{
|
||||||
SPDR = tx;
|
SPDR = tx;
|
||||||
while (!(SPSR & (1 << SPIF)));
|
while (!(SPSR & (1 << SPIF)));
|
||||||
return SPDR;
|
return SPDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@
|
||||||
|
|
||||||
// These can't be used after statements in c89.
|
// These can't be used after statements in c89.
|
||||||
#ifdef __COUNTER__
|
#ifdef __COUNTER__
|
||||||
#define static_assert(e,m) \
|
#define static_assert(e,m) \
|
||||||
;enum { ASSERT_CONCAT(STATIC_ASSERT_, __COUNTER__) = 1/(int)(!!(e)) }
|
;enum { ASSERT_CONCAT(STATIC_ASSERT_, __COUNTER__) = 1/(int)(!!(e)) }
|
||||||
#else
|
#else
|
||||||
//This can't be used twice on the same line so ensure if using in headers
|
//This can't be used twice on the same line so ensure if using in headers
|
||||||
//that the headers are not included twice (by wrapping in #ifndef...#endif)
|
//that the headers are not included twice (by wrapping in #ifndef...#endif)
|
||||||
//Note it doesn't cause an issue when used on same line of separate modules
|
//Note it doesn't cause an issue when used on same line of separate modules
|
||||||
//compiled with gcc -combine -fwhole-program.
|
//compiled with gcc -combine -fwhole-program.
|
||||||
#define static_assert(e,m) \
|
#define static_assert(e,m) \
|
||||||
;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) }
|
;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) }
|
||||||
#endif //__COUNTER__
|
#endif //__COUNTER__
|
||||||
|
|
||||||
|
|
|
||||||
2149
Firmware/stepper.cpp
2149
Firmware/stepper.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -38,9 +38,9 @@ void st_init();
|
||||||
void isr();
|
void isr();
|
||||||
|
|
||||||
#ifdef LIN_ADVANCE
|
#ifdef LIN_ADVANCE
|
||||||
void advance_isr();
|
void advance_isr();
|
||||||
void advance_isr_scheduler();
|
void advance_isr_scheduler();
|
||||||
void clear_current_adv_vars(); //Used to reset the built up pretension and remaining esteps on filament change.
|
void clear_current_adv_vars(); //Used to reset the built up pretension and remaining esteps on filament change.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Block until all buffered steps are executed
|
// Block until all buffered steps are executed
|
||||||
|
|
@ -64,12 +64,12 @@ float st_get_position_mm(uint8_t axis);
|
||||||
// to avoid a stepper timer overflow.
|
// to avoid a stepper timer overflow.
|
||||||
FORCE_INLINE void st_reset_timer()
|
FORCE_INLINE void st_reset_timer()
|
||||||
{
|
{
|
||||||
// Clear a possible pending interrupt on OCR1A overflow.
|
// Clear a possible pending interrupt on OCR1A overflow.
|
||||||
TIFR1 |= 1 << OCF1A;
|
TIFR1 |= 1 << OCF1A;
|
||||||
// Reset the counter.
|
// Reset the counter.
|
||||||
TCNT1 = 0;
|
TCNT1 = 0;
|
||||||
// Wake up after 1ms from now.
|
// Wake up after 1ms from now.
|
||||||
OCR1A = 2000;
|
OCR1A = 2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkHitEndstops(); //call from somewhere to create an serial error message with the locations the endstops where hit, in case they were triggered
|
void checkHitEndstops(); //call from somewhere to create an serial error message with the locations the endstops where hit, in case they were triggered
|
||||||
|
|
@ -104,7 +104,7 @@ void microstep_init();
|
||||||
void microstep_readings();
|
void microstep_readings();
|
||||||
|
|
||||||
#ifdef BABYSTEPPING
|
#ifdef BABYSTEPPING
|
||||||
void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention
|
void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
242
Firmware/swi2c.c
242
Firmware/swi2c.c
|
|
@ -16,136 +16,148 @@
|
||||||
|
|
||||||
void __delay(void)
|
void __delay(void)
|
||||||
{
|
{
|
||||||
_delay_us(1.5);
|
_delay_us(1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swi2c_init(void)
|
void swi2c_init(void)
|
||||||
{
|
{
|
||||||
PIN_OUT(SWI2C_SDA);
|
PIN_OUT(SWI2C_SDA);
|
||||||
PIN_OUT(SWI2C_SCL);
|
PIN_OUT(SWI2C_SCL);
|
||||||
PIN_SET(SWI2C_SDA);
|
PIN_SET(SWI2C_SDA);
|
||||||
PIN_SET(SWI2C_SCL);
|
PIN_SET(SWI2C_SCL);
|
||||||
uint8_t i; for (i = 0; i < 100; i++)
|
uint8_t i;
|
||||||
__delay();
|
for (i = 0; i < 100; i++)
|
||||||
|
__delay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swi2c_start(void)
|
void swi2c_start(void)
|
||||||
{
|
{
|
||||||
PIN_CLR(SWI2C_SDA);
|
PIN_CLR(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_CLR(SWI2C_SCL);
|
PIN_CLR(SWI2C_SCL);
|
||||||
__delay();
|
__delay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swi2c_stop(void)
|
void swi2c_stop(void)
|
||||||
{
|
{
|
||||||
PIN_SET(SWI2C_SCL);
|
PIN_SET(SWI2C_SCL);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_SET(SWI2C_SDA);
|
PIN_SET(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void swi2c_ack(void)
|
void swi2c_ack(void)
|
||||||
{
|
{
|
||||||
PIN_CLR(SWI2C_SDA);
|
PIN_CLR(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_SET(SWI2C_SCL);
|
PIN_SET(SWI2C_SCL);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_CLR(SWI2C_SCL);
|
PIN_CLR(SWI2C_SCL);
|
||||||
__delay();
|
__delay();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t swi2c_wait_ack()
|
uint8_t swi2c_wait_ack()
|
||||||
{
|
{
|
||||||
PIN_INP(SWI2C_SDA);
|
PIN_INP(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
// PIN_SET(SWI2C_SDA);
|
// PIN_SET(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_SET(SWI2C_SCL);
|
PIN_SET(SWI2C_SCL);
|
||||||
// __delay();
|
// __delay();
|
||||||
uint8_t ack = 0;
|
uint8_t ack = 0;
|
||||||
uint16_t ackto = SWI2C_TMO;
|
uint16_t ackto = SWI2C_TMO;
|
||||||
while (!(ack = (PIN_GET(SWI2C_SDA)?0:1)) && ackto--) __delay();
|
while (!(ack = (PIN_GET(SWI2C_SDA)?0:1)) && ackto--) __delay();
|
||||||
PIN_CLR(SWI2C_SCL);
|
PIN_CLR(SWI2C_SCL);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_OUT(SWI2C_SDA);
|
PIN_OUT(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_CLR(SWI2C_SDA);
|
PIN_CLR(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
return ack;
|
return ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t swi2c_read(void)
|
uint8_t swi2c_read(void)
|
||||||
{
|
{
|
||||||
PIN_SET(SWI2C_SDA);
|
PIN_SET(SWI2C_SDA);
|
||||||
__delay();
|
__delay();
|
||||||
PIN_INP(SWI2C_SDA);
|
PIN_INP(SWI2C_SDA);
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
int8_t bit; for (bit = 7; bit >= 0; bit--)
|
int8_t bit;
|
||||||
{
|
for (bit = 7; bit >= 0; bit--)
|
||||||
PIN_SET(SWI2C_SCL);
|
{
|
||||||
__delay();
|
PIN_SET(SWI2C_SCL);
|
||||||
data |= (PIN_GET(SWI2C_SDA)?1:0) << bit;
|
__delay();
|
||||||
PIN_CLR(SWI2C_SCL);
|
data |= (PIN_GET(SWI2C_SDA)?1:0) << bit;
|
||||||
__delay();
|
PIN_CLR(SWI2C_SCL);
|
||||||
}
|
__delay();
|
||||||
PIN_OUT(SWI2C_SDA);
|
}
|
||||||
return data;
|
PIN_OUT(SWI2C_SDA);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swi2c_write(uint8_t data)
|
void swi2c_write(uint8_t data)
|
||||||
{
|
{
|
||||||
int8_t bit; for (bit = 7; bit >= 0; bit--)
|
int8_t bit;
|
||||||
{
|
for (bit = 7; bit >= 0; bit--)
|
||||||
if (data & (1 << bit)) PIN_SET(SWI2C_SDA);
|
{
|
||||||
else PIN_CLR(SWI2C_SDA);
|
if (data & (1 << bit)) PIN_SET(SWI2C_SDA);
|
||||||
__delay();
|
else PIN_CLR(SWI2C_SDA);
|
||||||
PIN_SET(SWI2C_SCL);
|
__delay();
|
||||||
__delay();
|
PIN_SET(SWI2C_SCL);
|
||||||
PIN_CLR(SWI2C_SCL);
|
__delay();
|
||||||
__delay();
|
PIN_CLR(SWI2C_SCL);
|
||||||
}
|
__delay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t swi2c_check(uint8_t dev_addr)
|
uint8_t swi2c_check(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
swi2c_start();
|
swi2c_start();
|
||||||
swi2c_write((dev_addr & SWI2C_DMSK) << SWI2C_ASHF);
|
swi2c_write((dev_addr & SWI2C_DMSK) << SWI2C_ASHF);
|
||||||
if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
|
if (!swi2c_wait_ack()) {
|
||||||
swi2c_stop();
|
swi2c_stop();
|
||||||
return 1;
|
return 0;
|
||||||
|
}
|
||||||
|
swi2c_stop();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SWI2C_A8 //8bit address
|
#ifdef SWI2C_A8 //8bit address
|
||||||
|
|
||||||
uint8_t swi2c_readByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte)
|
uint8_t swi2c_readByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte)
|
||||||
{
|
{
|
||||||
swi2c_start();
|
swi2c_start();
|
||||||
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
||||||
if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
|
if (!swi2c_wait_ack()) {
|
||||||
swi2c_write(addr & 0xff);
|
swi2c_stop();
|
||||||
if (!swi2c_wait_ack()) return 0;
|
return 0;
|
||||||
swi2c_stop();
|
}
|
||||||
swi2c_start();
|
swi2c_write(addr & 0xff);
|
||||||
swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
if (!swi2c_wait_ack()) return 0;
|
||||||
if (!swi2c_wait_ack()) return 0;
|
swi2c_stop();
|
||||||
uint8_t byte = swi2c_read();
|
swi2c_start();
|
||||||
swi2c_stop();
|
swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
||||||
if (pbyte) *pbyte = byte;
|
if (!swi2c_wait_ack()) return 0;
|
||||||
return 1;
|
uint8_t byte = swi2c_read();
|
||||||
|
swi2c_stop();
|
||||||
|
if (pbyte) *pbyte = byte;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte)
|
uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte)
|
||||||
{
|
{
|
||||||
swi2c_start();
|
swi2c_start();
|
||||||
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
||||||
if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
|
if (!swi2c_wait_ack()) {
|
||||||
swi2c_write(addr & 0xff);
|
swi2c_stop();
|
||||||
if (!swi2c_wait_ack()) return 0;
|
return 0;
|
||||||
swi2c_write(*pbyte);
|
}
|
||||||
if (!swi2c_wait_ack()) return 0;
|
swi2c_write(addr & 0xff);
|
||||||
swi2c_stop();
|
if (!swi2c_wait_ack()) return 0;
|
||||||
return 1;
|
swi2c_write(*pbyte);
|
||||||
|
if (!swi2c_wait_ack()) return 0;
|
||||||
|
swi2c_stop();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //SWI2C_A8
|
#endif //SWI2C_A8
|
||||||
|
|
@ -154,36 +166,42 @@ uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte)
|
||||||
|
|
||||||
uint8_t swi2c_readByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte)
|
uint8_t swi2c_readByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte)
|
||||||
{
|
{
|
||||||
swi2c_start();
|
swi2c_start();
|
||||||
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
||||||
if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
|
if (!swi2c_wait_ack()) {
|
||||||
swi2c_write(addr >> 8);
|
swi2c_stop();
|
||||||
if (!swi2c_wait_ack()) return 0;
|
return 0;
|
||||||
swi2c_write(addr & 0xff);
|
}
|
||||||
if (!swi2c_wait_ack()) return 0;
|
swi2c_write(addr >> 8);
|
||||||
swi2c_stop();
|
if (!swi2c_wait_ack()) return 0;
|
||||||
swi2c_start();
|
swi2c_write(addr & 0xff);
|
||||||
swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
if (!swi2c_wait_ack()) return 0;
|
||||||
if (!swi2c_wait_ack()) return 0;
|
swi2c_stop();
|
||||||
uint8_t byte = swi2c_read();
|
swi2c_start();
|
||||||
swi2c_stop();
|
swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
||||||
if (pbyte) *pbyte = byte;
|
if (!swi2c_wait_ack()) return 0;
|
||||||
return 1;
|
uint8_t byte = swi2c_read();
|
||||||
|
swi2c_stop();
|
||||||
|
if (pbyte) *pbyte = byte;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t swi2c_writeByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte)
|
uint8_t swi2c_writeByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte)
|
||||||
{
|
{
|
||||||
swi2c_start();
|
swi2c_start();
|
||||||
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
|
||||||
if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
|
if (!swi2c_wait_ack()) {
|
||||||
swi2c_write(addr >> 8);
|
swi2c_stop();
|
||||||
if (!swi2c_wait_ack()) return 0;
|
return 0;
|
||||||
swi2c_write(addr & 0xff);
|
}
|
||||||
if (!swi2c_wait_ack()) return 0;
|
swi2c_write(addr >> 8);
|
||||||
swi2c_write(*pbyte);
|
if (!swi2c_wait_ack()) return 0;
|
||||||
if (!swi2c_wait_ack()) return 0;
|
swi2c_write(addr & 0xff);
|
||||||
swi2c_stop();
|
if (!swi2c_wait_ack()) return 0;
|
||||||
return 1;
|
swi2c_write(*pbyte);
|
||||||
|
if (!swi2c_wait_ack()) return 0;
|
||||||
|
swi2c_stop();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //SWI2C_A16
|
#endif //SWI2C_A16
|
||||||
|
|
|
||||||
|
|
@ -27,67 +27,70 @@ unsigned char swspi_cfg = 0;
|
||||||
|
|
||||||
void swspi_init(unsigned char miso, unsigned char mosi, unsigned char sck, unsigned char cfg)
|
void swspi_init(unsigned char miso, unsigned char mosi, unsigned char sck, unsigned char cfg)
|
||||||
{
|
{
|
||||||
swspi_miso = miso;
|
swspi_miso = miso;
|
||||||
swspi_mosi = mosi;
|
swspi_mosi = mosi;
|
||||||
swspi_sck = sck;
|
swspi_sck = sck;
|
||||||
swspi_cfg = cfg;
|
swspi_cfg = cfg;
|
||||||
GPIO_INP(swspi_miso);
|
GPIO_INP(swspi_miso);
|
||||||
GPIO_OUT(swspi_mosi);
|
GPIO_OUT(swspi_mosi);
|
||||||
GPIO_OUT(swspi_sck);
|
GPIO_OUT(swspi_sck);
|
||||||
GPIO_CLR(swspi_mosi);
|
GPIO_CLR(swspi_mosi);
|
||||||
SWSPI_SCK_DN;
|
SWSPI_SCK_DN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swspi_tx(unsigned char tx)
|
void swspi_tx(unsigned char tx)
|
||||||
{
|
{
|
||||||
int delay = 1 << (swspi_cfg & SWSPI_DEL));
|
int delay = 1 << (swspi_cfg & SWSPI_DEL));
|
||||||
if (swspi_miso == swspi_mosi) GPIO_OUT(swspi_mosi);
|
if (swspi_miso == swspi_mosi) GPIO_OUT(swspi_mosi);
|
||||||
unsigned char i = 0; for (; i < 8; i++)
|
unsigned char i = 0;
|
||||||
{
|
for (; i < 8; i++)
|
||||||
if (tx & 0x80) GPIO_SET(swspi_mosi);
|
{
|
||||||
else GPIO_CLR(swspi_mosi);
|
if (tx & 0x80) GPIO_SET(swspi_mosi);
|
||||||
DELAY(delay);
|
else GPIO_CLR(swspi_mosi);
|
||||||
SWSPI_SCK_UP;
|
DELAY(delay);
|
||||||
DELAY(delay);
|
SWSPI_SCK_UP;
|
||||||
SWSPI_SCK_DN;
|
DELAY(delay);
|
||||||
tx <<= 1;
|
SWSPI_SCK_DN;
|
||||||
}
|
tx <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char swspi_rx()
|
unsigned char swspi_rx()
|
||||||
{
|
{
|
||||||
int delay = 1 << (swspi_cfg & SWSPI_DEL));
|
int delay = 1 << (swspi_cfg & SWSPI_DEL));
|
||||||
if (swspi_miso == swspi_mosi) GPIO_OUT(swspi_mosi);
|
if (swspi_miso == swspi_mosi) GPIO_OUT(swspi_mosi);
|
||||||
unsigned char rx = 0;
|
unsigned char rx = 0;
|
||||||
unsigned char i = 0; for (; i < 8; i++)
|
unsigned char i = 0;
|
||||||
{
|
for (; i < 8; i++)
|
||||||
rx <<= 1;
|
{
|
||||||
DELAY(delay);
|
rx <<= 1;
|
||||||
SWSPI_SCK_UP;
|
DELAY(delay);
|
||||||
DELAY(delay);
|
SWSPI_SCK_UP;
|
||||||
rx |= GPIO_GET(swspi_miso)?1:0;
|
DELAY(delay);
|
||||||
SWSPI_SCK_DN;
|
rx |= GPIO_GET(swspi_miso)?1:0;
|
||||||
}
|
SWSPI_SCK_DN;
|
||||||
return rx;
|
}
|
||||||
|
return rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char swspi_txrx(unsigned char tx)
|
unsigned char swspi_txrx(unsigned char tx)
|
||||||
{
|
{
|
||||||
int delay = 1 << (swspi_cfg & SWSPI_DEL));
|
int delay = 1 << (swspi_cfg & SWSPI_DEL));
|
||||||
unsigned char rx = 0;
|
unsigned char rx = 0;
|
||||||
unsigned char i = 0; for (; i < 8; i++)
|
unsigned char i = 0;
|
||||||
{
|
for (; i < 8; i++)
|
||||||
rx <<= 1;
|
{
|
||||||
if (tx & 0x80) GPIO_SET(swspi_mosi);
|
rx <<= 1;
|
||||||
else GPIO_CLR(swspi_mosi);
|
if (tx & 0x80) GPIO_SET(swspi_mosi);
|
||||||
DELAY(delay);
|
else GPIO_CLR(swspi_mosi);
|
||||||
SWSPI_SCK_UP;
|
DELAY(delay);
|
||||||
DELAY(delay);
|
SWSPI_SCK_UP;
|
||||||
rx |= GPIO_GET(swspi_miso)?1:0;
|
DELAY(delay);
|
||||||
SWSPI_SCK_DN;
|
rx |= GPIO_GET(swspi_miso)?1:0;
|
||||||
tx <<= 1;
|
SWSPI_SCK_DN;
|
||||||
}
|
tx <<= 1;
|
||||||
return rx;
|
}
|
||||||
|
return rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //__SWSPI
|
#endif //__SWSPI
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -24,7 +24,7 @@
|
||||||
#include "Marlin.h"
|
#include "Marlin.h"
|
||||||
#include "planner.h"
|
#include "planner.h"
|
||||||
#ifdef PID_ADD_EXTRUSION_RATE
|
#ifdef PID_ADD_EXTRUSION_RATE
|
||||||
#include "stepper.h"
|
#include "stepper.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ENABLE_TEMPERATURE_INTERRUPT() TIMSK0 |= (1<<OCIE0B)
|
#define ENABLE_TEMPERATURE_INTERRUPT() TIMSK0 |= (1<<OCIE0B)
|
||||||
|
|
@ -39,8 +39,8 @@ void manage_heater(); //it is critical that this is called periodically.
|
||||||
extern int target_temperature[EXTRUDERS];
|
extern int target_temperature[EXTRUDERS];
|
||||||
extern float current_temperature[EXTRUDERS];
|
extern float current_temperature[EXTRUDERS];
|
||||||
#ifdef SHOW_TEMP_ADC_VALUES
|
#ifdef SHOW_TEMP_ADC_VALUES
|
||||||
extern int current_temperature_raw[EXTRUDERS];
|
extern int current_temperature_raw[EXTRUDERS];
|
||||||
extern int current_temperature_bed_raw;
|
extern int current_temperature_bed_raw;
|
||||||
#endif
|
#endif
|
||||||
extern int target_temperature_bed;
|
extern int target_temperature_bed;
|
||||||
extern float current_temperature_bed;
|
extern float current_temperature_bed;
|
||||||
|
|
@ -64,27 +64,27 @@ extern int current_voltage_raw_bed;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
|
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
|
||||||
extern float redundant_temperature;
|
extern float redundant_temperature;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
|
#if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1
|
||||||
extern unsigned char soft_pwm_bed;
|
extern unsigned char soft_pwm_bed;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
extern int pid_cycle, pid_number_of_cycles;
|
extern int pid_cycle, pid_number_of_cycles;
|
||||||
extern float Kc,_Kp,_Ki,_Kd;
|
extern float Kc,_Kp,_Ki,_Kd;
|
||||||
extern bool pid_tuning_finished;
|
extern bool pid_tuning_finished;
|
||||||
float scalePID_i(float i);
|
float scalePID_i(float i);
|
||||||
float scalePID_d(float d);
|
float scalePID_d(float d);
|
||||||
float unscalePID_i(float i);
|
float unscalePID_i(float i);
|
||||||
float unscalePID_d(float d);
|
float unscalePID_d(float d);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef BABYSTEPPING
|
#ifdef BABYSTEPPING
|
||||||
extern volatile int babystepsTodo[3];
|
extern volatile int babystepsTodo[3];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void babystepsTodoZadd(int n)
|
inline void babystepsTodoZadd(int n)
|
||||||
|
|
@ -110,33 +110,33 @@ inline void babystepsTodoZsubtract(int n)
|
||||||
//deg=degreeCelsius
|
//deg=degreeCelsius
|
||||||
|
|
||||||
FORCE_INLINE float degHotend(uint8_t extruder) {
|
FORCE_INLINE float degHotend(uint8_t extruder) {
|
||||||
return current_temperature[extruder];
|
return current_temperature[extruder];
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SHOW_TEMP_ADC_VALUES
|
#ifdef SHOW_TEMP_ADC_VALUES
|
||||||
FORCE_INLINE float rawHotendTemp(uint8_t extruder) {
|
FORCE_INLINE float rawHotendTemp(uint8_t extruder) {
|
||||||
return current_temperature_raw[extruder];
|
return current_temperature_raw[extruder];
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE float rawBedTemp() {
|
FORCE_INLINE float rawBedTemp() {
|
||||||
return current_temperature_bed_raw;
|
return current_temperature_bed_raw;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE float degBed() {
|
FORCE_INLINE float degBed() {
|
||||||
return current_temperature_bed;
|
return current_temperature_bed;
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE float degTargetHotend(uint8_t extruder) {
|
FORCE_INLINE float degTargetHotend(uint8_t extruder) {
|
||||||
return target_temperature[extruder];
|
return target_temperature[extruder];
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE float degTargetBed() {
|
FORCE_INLINE float degTargetBed() {
|
||||||
return target_temperature_bed;
|
return target_temperature_bed;
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
|
FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
|
||||||
target_temperature[extruder] = celsius;
|
target_temperature[extruder] = celsius;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void setTargetHotendSafe(const float &celsius, uint8_t extruder)
|
static inline void setTargetHotendSafe(const float &celsius, uint8_t extruder)
|
||||||
|
|
@ -146,27 +146,27 @@ static inline void setTargetHotendSafe(const float &celsius, uint8_t extruder)
|
||||||
|
|
||||||
static inline void setAllTargetHotends(const float &celsius)
|
static inline void setAllTargetHotends(const float &celsius)
|
||||||
{
|
{
|
||||||
for(int i=0;i<EXTRUDERS;i++) setTargetHotend(celsius,i);
|
for(int i=0; i<EXTRUDERS; i++) setTargetHotend(celsius,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE void setTargetBed(const float &celsius) {
|
FORCE_INLINE void setTargetBed(const float &celsius) {
|
||||||
target_temperature_bed = celsius;
|
target_temperature_bed = celsius;
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE bool isHeatingHotend(uint8_t extruder){
|
FORCE_INLINE bool isHeatingHotend(uint8_t extruder) {
|
||||||
return target_temperature[extruder] > current_temperature[extruder];
|
return target_temperature[extruder] > current_temperature[extruder];
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE bool isHeatingBed() {
|
FORCE_INLINE bool isHeatingBed() {
|
||||||
return target_temperature_bed > current_temperature_bed;
|
return target_temperature_bed > current_temperature_bed;
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {
|
FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {
|
||||||
return target_temperature[extruder] < current_temperature[extruder];
|
return target_temperature[extruder] < current_temperature[extruder];
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCE_INLINE bool isCoolingBed() {
|
FORCE_INLINE bool isCoolingBed() {
|
||||||
return target_temperature_bed < current_temperature_bed;
|
return target_temperature_bed < current_temperature_bed;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define degHotend0() degHotend(0)
|
#define degHotend0() degHotend(0)
|
||||||
|
|
@ -202,15 +202,15 @@ void setWatch();
|
||||||
void updatePID();
|
void updatePID();
|
||||||
|
|
||||||
|
|
||||||
FORCE_INLINE void autotempShutdown(){
|
FORCE_INLINE void autotempShutdown() {
|
||||||
#ifdef AUTOTEMP
|
#ifdef AUTOTEMP
|
||||||
if(autotemp_enabled)
|
if(autotemp_enabled)
|
||||||
{
|
{
|
||||||
autotemp_enabled=false;
|
autotemp_enabled=false;
|
||||||
if(degTargetHotend(active_extruder)>autotemp_min)
|
if(degTargetHotend(active_extruder)>autotemp_min)
|
||||||
setTargetHotend(0,active_extruder);
|
setTargetHotend(0,active_extruder);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PID_autotune(float temp, int extruder, int ncycles);
|
void PID_autotune(float temp, int extruder, int ncycles);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
1296
Firmware/tmc2130.cpp
1296
Firmware/tmc2130.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -40,11 +40,11 @@ extern uint8_t tmc2130_wave_fac[4];
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t toff:4;
|
uint8_t toff:4;
|
||||||
uint8_t hstr:3;
|
uint8_t hstr:3;
|
||||||
uint8_t hend:4;
|
uint8_t hend:4;
|
||||||
uint8_t tbl:2;
|
uint8_t tbl:2;
|
||||||
uint8_t res:3;
|
uint8_t res:3;
|
||||||
} tmc2130_chopper_config_t;
|
} tmc2130_chopper_config_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,67 +18,67 @@ FILE _uart2io = {0};
|
||||||
|
|
||||||
int uart2_putchar(char c, FILE *stream __attribute__((unused)))
|
int uart2_putchar(char c, FILE *stream __attribute__((unused)))
|
||||||
{
|
{
|
||||||
while (!uart2_txready);
|
while (!uart2_txready);
|
||||||
UDR2 = c; // transmit byte
|
UDR2 = c; // transmit byte
|
||||||
// while (!uart2_txcomplete); // wait until byte sent
|
// while (!uart2_txcomplete); // wait until byte sent
|
||||||
// UCSR2A |= (1 << TXC2); // delete TXCflag
|
// UCSR2A |= (1 << TXC2); // delete TXCflag
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uart2_getchar(FILE *stream __attribute__((unused)))
|
int uart2_getchar(FILE *stream __attribute__((unused)))
|
||||||
{
|
{
|
||||||
if (rbuf_empty(uart2_ibuf)) return -1;
|
if (rbuf_empty(uart2_ibuf)) return -1;
|
||||||
return rbuf_get(uart2_ibuf);
|
return rbuf_get(uart2_ibuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
//uart init (io + FILE stream)
|
//uart init (io + FILE stream)
|
||||||
void uart2_init(void)
|
void uart2_init(void)
|
||||||
{
|
{
|
||||||
DDRH &= ~0x01;
|
DDRH &= ~0x01;
|
||||||
PORTH |= 0x01;
|
PORTH |= 0x01;
|
||||||
rbuf_ini(uart2_ibuf, sizeof(uart2_ibuf) - 4);
|
rbuf_ini(uart2_ibuf, sizeof(uart2_ibuf) - 4);
|
||||||
UCSR2A |= (1 << U2X2); // baudrate multiplier
|
UCSR2A |= (1 << U2X2); // baudrate multiplier
|
||||||
UBRR2L = UART_BAUD_SELECT(UART2_BAUD, F_CPU); // select baudrate
|
UBRR2L = UART_BAUD_SELECT(UART2_BAUD, F_CPU); // select baudrate
|
||||||
UCSR2B = (1 << RXEN2) | (1 << TXEN2); // enable receiver and transmitter
|
UCSR2B = (1 << RXEN2) | (1 << TXEN2); // enable receiver and transmitter
|
||||||
UCSR2B |= (1 << RXCIE2); // enable rx interrupt
|
UCSR2B |= (1 << RXCIE2); // enable rx interrupt
|
||||||
fdev_setup_stream(uart2io, uart2_putchar, uart2_getchar, _FDEV_SETUP_WRITE | _FDEV_SETUP_READ); //setup uart2 i/o stream
|
fdev_setup_stream(uart2io, uart2_putchar, uart2_getchar, _FDEV_SETUP_WRITE | _FDEV_SETUP_READ); //setup uart2 i/o stream
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns 1 if chars in input buffer match to str
|
//returns 1 if chars in input buffer match to str
|
||||||
//returns -1 if chars does not match and 0 for empty buffer
|
//returns -1 if chars does not match and 0 for empty buffer
|
||||||
int8_t uart2_rx_str_P(const char* str)
|
int8_t uart2_rx_str_P(const char* str)
|
||||||
{
|
{
|
||||||
uint8_t r = rbuf_r(uart2_ibuf); //get read index
|
uint8_t r = rbuf_r(uart2_ibuf); //get read index
|
||||||
uint8_t w = rbuf_w(uart2_ibuf); //get write index
|
uint8_t w = rbuf_w(uart2_ibuf); //get write index
|
||||||
// printf_P(PSTR("uart2_rx_str_P r=%d w=%d\n"), r, w);
|
// printf_P(PSTR("uart2_rx_str_P r=%d w=%d\n"), r, w);
|
||||||
uint8_t e = rbuf_l(uart2_ibuf) - 1; //get end index
|
uint8_t e = rbuf_l(uart2_ibuf) - 1; //get end index
|
||||||
uint8_t len = strlen_P(str); //get string length
|
uint8_t len = strlen_P(str); //get string length
|
||||||
str += len; //last char will be compared first
|
str += len; //last char will be compared first
|
||||||
// printf_P(PSTR(" len=%d\n"), len);
|
// printf_P(PSTR(" len=%d\n"), len);
|
||||||
while (len--) //loop over all chars
|
while (len--) //loop over all chars
|
||||||
{
|
{
|
||||||
if (w == r) return 0; //empty buffer - return 0
|
if (w == r) return 0; //empty buffer - return 0
|
||||||
if ((--w) == 255) w = e; //decrement index
|
if ((--w) == 255) w = e; //decrement index
|
||||||
char c0 = pgm_read_byte(--str); //read char from str
|
char c0 = pgm_read_byte(--str); //read char from str
|
||||||
char c1 = uart2_ibuf[4 + w]; //read char from input buffer
|
char c1 = uart2_ibuf[4 + w]; //read char from input buffer
|
||||||
// printf_P(PSTR(" uart2_rx_str_P w=%d l=%d c0=%02x c1=%02x\n"), w, len, c0, c1);
|
// printf_P(PSTR(" uart2_rx_str_P w=%d l=%d c0=%02x c1=%02x\n"), w, len, c0, c1);
|
||||||
if (c0 == c1) continue; //if match, continue with next char
|
if (c0 == c1) continue; //if match, continue with next char
|
||||||
if ((c0 == '\r') && (c1 == '\n')) //match cr as lf
|
if ((c0 == '\r') && (c1 == '\n')) //match cr as lf
|
||||||
continue;
|
continue;
|
||||||
if ((c0 == '\n') && (c1 == '\r')) //match lf as cr
|
if ((c0 == '\n') && (c1 == '\r')) //match lf as cr
|
||||||
continue;
|
continue;
|
||||||
return -1; //no match - return -1
|
return -1; //no match - return -1
|
||||||
}
|
}
|
||||||
return 1; //all characters match - return 1
|
return 1; //all characters match - return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
ISR(USART2_RX_vect)
|
ISR(USART2_RX_vect)
|
||||||
{
|
{
|
||||||
//printf_P(PSTR("USART2_RX_vect \n") );
|
//printf_P(PSTR("USART2_RX_vect \n") );
|
||||||
if (rbuf_put(uart2_ibuf, UDR2) < 0) // put received byte to buffer
|
if (rbuf_put(uart2_ibuf, UDR2) < 0) // put received byte to buffer
|
||||||
{ //rx buffer full
|
{ //rx buffer full
|
||||||
//uart2_rx_clr(); //for sure, clear input buffer
|
//uart2_rx_clr(); //for sure, clear input buffer
|
||||||
printf_P(PSTR("USART2 rx Full!!!\n"));
|
printf_P(PSTR("USART2 rx Full!!!\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -65,7 +65,7 @@ extern bool lcd_calibrate_z_end_stop_manual(bool only_z);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Show the result of the calibration process on the LCD screen.
|
// Show the result of the calibration process on the LCD screen.
|
||||||
extern void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask);
|
extern void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask);
|
||||||
|
|
||||||
extern void lcd_diag_show_end_stops();
|
extern void lcd_diag_show_end_stops();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,37 @@
|
||||||
// unification for AVR and RPI
|
// unification for AVR and RPI
|
||||||
|
|
||||||
#ifdef __AVR
|
#ifdef __AVR
|
||||||
//#include "Arduino.h"
|
//#include "Arduino.h"
|
||||||
#include "Marlin.h"
|
#include "Marlin.h"
|
||||||
#define GPIO_INP(gpio) pinMode(gpio, INPUT)
|
#define GPIO_INP(gpio) pinMode(gpio, INPUT)
|
||||||
#define GPIO_OUT(gpio) pinMode(gpio, OUTPUT)
|
#define GPIO_OUT(gpio) pinMode(gpio, OUTPUT)
|
||||||
#define GPIO_SET(gpio) digitalWrite(gpio, HIGH)
|
#define GPIO_SET(gpio) digitalWrite(gpio, HIGH)
|
||||||
#define GPIO_CLR(gpio) digitalWrite(gpio, LOW)
|
#define GPIO_CLR(gpio) digitalWrite(gpio, LOW)
|
||||||
#define GPIO_GET(gpio) (digitalRead(gpio) != LOW)
|
#define GPIO_GET(gpio) (digitalRead(gpio) != LOW)
|
||||||
#define DELAY(delay) delayMicroseconds(delay)
|
#define DELAY(delay) delayMicroseconds(delay)
|
||||||
#define PRINT MYSERIAL.print
|
#define PRINT MYSERIAL.print
|
||||||
#endif //RC522_AVR
|
#endif //RC522_AVR
|
||||||
|
|
||||||
#ifdef __RPI
|
#ifdef __RPI
|
||||||
#include <bcm2835.h>
|
#include <bcm2835.h>
|
||||||
#define GPIO_INP(gpio) bcm2835_gpio_fsel(gpio, BCM2835_GPIO_FSEL_INPT)
|
#define GPIO_INP(gpio) bcm2835_gpio_fsel(gpio, BCM2835_GPIO_FSEL_INPT)
|
||||||
#define GPIO_OUT(gpio) bcm2835_gpio_fsel(gpio, BCM2835_GPIO_FSEL_OUTP)
|
#define GPIO_OUT(gpio) bcm2835_gpio_fsel(gpio, BCM2835_GPIO_FSEL_OUTP)
|
||||||
#define GPIO_SET(gpio) bcm2835_gpio_write(gpio, HIGH)
|
#define GPIO_SET(gpio) bcm2835_gpio_write(gpio, HIGH)
|
||||||
#define GPIO_CLR(gpio) bcm2835_gpio_write(gpio, LOW)
|
#define GPIO_CLR(gpio) bcm2835_gpio_write(gpio, LOW)
|
||||||
#define GPIO_GET(gpio) (bcm2835_gpio_lev(gpio) != LOW)
|
#define GPIO_GET(gpio) (bcm2835_gpio_lev(gpio) != LOW)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#define DELAY(delay) usleep(delay)
|
#define DELAY(delay) usleep(delay)
|
||||||
#define PRINT(p) print(p)
|
#define PRINT(p) print(p)
|
||||||
#define DEC 10
|
#define DEC 10
|
||||||
#define HEX 16
|
#define HEX 16
|
||||||
void print(const char* pc) { printf("%s", pc); }
|
void print(const char* pc) {
|
||||||
void print(int v) { printf("%d", v); }
|
printf("%s", pc);
|
||||||
void print(float v) { printf("%f", v); }
|
}
|
||||||
|
void print(int v) {
|
||||||
|
printf("%d", v);
|
||||||
|
}
|
||||||
|
void print(float v) {
|
||||||
|
printf("%f", v);
|
||||||
|
}
|
||||||
#endif //RC522_RPI
|
#endif //RC522_RPI
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,22 +117,22 @@ inline bool parse_version(const char *str, uint16_t version[4])
|
||||||
inline bool strncmp_PP(const char *p1, const char *p2, uint8_t n)
|
inline bool strncmp_PP(const char *p1, const char *p2, uint8_t n)
|
||||||
{
|
{
|
||||||
for (; n > 0; -- n, ++ p1, ++ p2) {
|
for (; n > 0; -- n, ++ p1, ++ p2) {
|
||||||
if (pgm_read_byte(p1) >= 65 && pgm_read_byte(p1) <= 92) //p1 is upper case (p2 is always lowercase)
|
if (pgm_read_byte(p1) >= 65 && pgm_read_byte(p1) <= 92) //p1 is upper case (p2 is always lowercase)
|
||||||
{
|
{
|
||||||
if ((pgm_read_byte(p1)+32) < pgm_read_byte(p2))
|
if ((pgm_read_byte(p1)+32) < pgm_read_byte(p2))
|
||||||
return -1;
|
return -1;
|
||||||
if ((pgm_read_byte(p1)+32) > pgm_read_byte(p2))
|
if ((pgm_read_byte(p1)+32) > pgm_read_byte(p2))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (pgm_read_byte(p1) == 0) {
|
else if (pgm_read_byte(p1) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else { //p1 is lowercase
|
else { //p1 is lowercase
|
||||||
if (pgm_read_byte(p1) < pgm_read_byte(p2))
|
if (pgm_read_byte(p1) < pgm_read_byte(p2))
|
||||||
return -1;
|
return -1;
|
||||||
if (pgm_read_byte(p1) > pgm_read_byte(p2))
|
if (pgm_read_byte(p1) > pgm_read_byte(p2))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +165,8 @@ inline bool parse_version_P(const char *str, uint16_t version[4])
|
||||||
uint8_t n = minor - major - 1;
|
uint8_t n = minor - major - 1;
|
||||||
if (n > 4)
|
if (n > 4)
|
||||||
return false;
|
return false;
|
||||||
memcpy_P(buf, major, n); buf[n] = 0;
|
memcpy_P(buf, major, n);
|
||||||
|
buf[n] = 0;
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
version[0] = strtol(buf, &endptr, 10);
|
version[0] = strtol(buf, &endptr, 10);
|
||||||
if (*endptr != 0)
|
if (*endptr != 0)
|
||||||
|
|
@ -173,7 +174,8 @@ inline bool parse_version_P(const char *str, uint16_t version[4])
|
||||||
n = rev - minor - 1;
|
n = rev - minor - 1;
|
||||||
if (n > 4)
|
if (n > 4)
|
||||||
return false;
|
return false;
|
||||||
memcpy_P(buf, minor, n); buf[n] = 0;
|
memcpy_P(buf, minor, n);
|
||||||
|
buf[n] = 0;
|
||||||
version[1] = strtol(buf, &endptr, 10);
|
version[1] = strtol(buf, &endptr, 10);
|
||||||
if (*endptr != 0)
|
if (*endptr != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -242,30 +244,30 @@ inline int8_t is_provided_version_newer(const char *version_string)
|
||||||
|
|
||||||
bool force_selftest_if_fw_version()
|
bool force_selftest_if_fw_version()
|
||||||
{
|
{
|
||||||
//if fw version used before flashing new firmware (fw version currently stored in eeprom) is lower then 3.1.2-RC2, function returns true to force selftest
|
//if fw version used before flashing new firmware (fw version currently stored in eeprom) is lower then 3.1.2-RC2, function returns true to force selftest
|
||||||
|
|
||||||
uint16_t ver_eeprom[4];
|
uint16_t ver_eeprom[4];
|
||||||
uint16_t ver_with_calibration[4] = {3, 1, 2, 4}; //hardcoded 3.1.2-RC2 version
|
uint16_t ver_with_calibration[4] = {3, 1, 2, 4}; //hardcoded 3.1.2-RC2 version
|
||||||
bool force_selftest = false;
|
bool force_selftest = false;
|
||||||
|
|
||||||
ver_eeprom[0] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MAJOR);
|
ver_eeprom[0] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MAJOR);
|
||||||
ver_eeprom[1] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MINOR);
|
ver_eeprom[1] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MINOR);
|
||||||
ver_eeprom[2] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_REVISION);
|
ver_eeprom[2] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_REVISION);
|
||||||
ver_eeprom[3] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_FLAVOR);
|
ver_eeprom[3] = eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_FLAVOR);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 4; ++i) {
|
for (uint8_t i = 0; i < 4; ++i) {
|
||||||
if (ver_with_calibration[i] > ver_eeprom[i]) {
|
if (ver_with_calibration[i] > ver_eeprom[i]) {
|
||||||
force_selftest = true;
|
force_selftest = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (ver_with_calibration[i] < ver_eeprom[i])
|
else if (ver_with_calibration[i] < ver_eeprom[i])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//force selftest also in case that version used before flashing new firmware was 3.2.0-RC1
|
//force selftest also in case that version used before flashing new firmware was 3.2.0-RC1
|
||||||
if ((ver_eeprom[0] == 3) && (ver_eeprom[1] == 2) && (ver_eeprom[2] == 0) && (ver_eeprom[3] == 3)) force_selftest = true;
|
if ((ver_eeprom[0] == 3) && (ver_eeprom[1] == 2) && (ver_eeprom[2] == 0) && (ver_eeprom[3] == 3)) force_selftest = true;
|
||||||
|
|
||||||
return force_selftest;
|
return force_selftest;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool show_upgrade_dialog_if_version_newer(const char *version_string)
|
bool show_upgrade_dialog_if_version_newer(const char *version_string)
|
||||||
|
|
@ -295,13 +297,13 @@ bool show_upgrade_dialog_if_version_newer(const char *version_string)
|
||||||
for (const char *c = version_string; ! is_whitespace_or_nl_or_eol(*c); ++ c)
|
for (const char *c = version_string; ! is_whitespace_or_nl_or_eol(*c); ++ c)
|
||||||
lcd_putc(*c);
|
lcd_putc(*c);
|
||||||
lcd_puts_at_P(0, 3, _i("Please upgrade."));////MSG_NEW_FIRMWARE_PLEASE_UPGRADE c=20 r=0
|
lcd_puts_at_P(0, 3, _i("Please upgrade."));////MSG_NEW_FIRMWARE_PLEASE_UPGRADE c=20 r=0
|
||||||
if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
|
if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
|
||||||
tone(BEEPER, 1000);
|
tone(BEEPER, 1000);
|
||||||
delay_keep_alive(50);
|
delay_keep_alive(50);
|
||||||
noTone(BEEPER);
|
noTone(BEEPER);
|
||||||
delay_keep_alive(500);
|
delay_keep_alive(500);
|
||||||
if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
|
if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
|
||||||
tone(BEEPER, 1000);
|
tone(BEEPER, 1000);
|
||||||
delay_keep_alive(50);
|
delay_keep_alive(50);
|
||||||
noTone(BEEPER);
|
noTone(BEEPER);
|
||||||
lcd_wait_for_click();
|
lcd_wait_for_click();
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ extern void update_current_firmware_version_to_eeprom();
|
||||||
|
|
||||||
|
|
||||||
inline int8_t eeprom_read_int8(unsigned char* addr) {
|
inline int8_t eeprom_read_int8(unsigned char* addr) {
|
||||||
uint8_t v = eeprom_read_byte(addr);
|
uint8_t v = eeprom_read_byte(addr);
|
||||||
return *reinterpret_cast<int8_t*>(&v);
|
return *reinterpret_cast<int8_t*>(&v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void eeprom_update_int8(unsigned char* addr, int8_t v) {
|
inline void eeprom_update_int8(unsigned char* addr, int8_t v) {
|
||||||
eeprom_update_byte(addr, *reinterpret_cast<uint8_t*>(&v));
|
eeprom_update_byte(addr, *reinterpret_cast<uint8_t*>(&v));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* UTIL_H */
|
#endif /* UTIL_H */
|
||||||
|
|
|
||||||
|
|
@ -28,93 +28,105 @@ vector_3::vector_3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) { }
|
||||||
|
|
||||||
vector_3 vector_3::cross(vector_3 left, vector_3 right)
|
vector_3 vector_3::cross(vector_3 left, vector_3 right)
|
||||||
{
|
{
|
||||||
return vector_3(left.y * right.z - left.z * right.y,
|
return vector_3(left.y * right.z - left.z * right.y,
|
||||||
left.z * right.x - left.x * right.z,
|
left.z * right.x - left.x * right.z,
|
||||||
left.x * right.y - left.y * right.x);
|
left.x * right.y - left.y * right.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_3 vector_3::operator+(vector_3 v)
|
vector_3 vector_3::operator+(vector_3 v)
|
||||||
{
|
{
|
||||||
return vector_3((x + v.x), (y + v.y), (z + v.z));
|
return vector_3((x + v.x), (y + v.y), (z + v.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_3 vector_3::operator-(vector_3 v)
|
vector_3 vector_3::operator-(vector_3 v)
|
||||||
{
|
{
|
||||||
return vector_3((x - v.x), (y - v.y), (z - v.z));
|
return vector_3((x - v.x), (y - v.y), (z - v.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_3 vector_3::get_normal()
|
vector_3 vector_3::get_normal()
|
||||||
{
|
{
|
||||||
vector_3 normalized = vector_3(x, y, z);
|
vector_3 normalized = vector_3(x, y, z);
|
||||||
normalized.normalize();
|
normalized.normalize();
|
||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
float vector_3::get_length()
|
float vector_3::get_length()
|
||||||
{
|
{
|
||||||
float length = sqrt((x * x) + (y * y) + (z * z));
|
float length = sqrt((x * x) + (y * y) + (z * z));
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vector_3::normalize()
|
void vector_3::normalize()
|
||||||
{
|
{
|
||||||
float length = get_length();
|
float length = get_length();
|
||||||
x /= length;
|
x /= length;
|
||||||
y /= length;
|
y /= length;
|
||||||
z /= length;
|
z /= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vector_3::apply_rotation(matrix_3x3 matrix)
|
void vector_3::apply_rotation(matrix_3x3 matrix)
|
||||||
{
|
{
|
||||||
float resultX = x * matrix.matrix[3*0+0] + y * matrix.matrix[3*1+0] + z * matrix.matrix[3*2+0];
|
float resultX = x * matrix.matrix[3*0+0] + y * matrix.matrix[3*1+0] + z * matrix.matrix[3*2+0];
|
||||||
float resultY = x * matrix.matrix[3*0+1] + y * matrix.matrix[3*1+1] + z * matrix.matrix[3*2+1];
|
float resultY = x * matrix.matrix[3*0+1] + y * matrix.matrix[3*1+1] + z * matrix.matrix[3*2+1];
|
||||||
float resultZ = x * matrix.matrix[3*0+2] + y * matrix.matrix[3*1+2] + z * matrix.matrix[3*2+2];
|
float resultZ = x * matrix.matrix[3*0+2] + y * matrix.matrix[3*1+2] + z * matrix.matrix[3*2+2];
|
||||||
|
|
||||||
x = resultX;
|
x = resultX;
|
||||||
y = resultY;
|
y = resultY;
|
||||||
z = resultZ;
|
z = resultZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vector_3::debug(char* title)
|
void vector_3::debug(char* title)
|
||||||
{
|
{
|
||||||
SERIAL_PROTOCOL(title);
|
SERIAL_PROTOCOL(title);
|
||||||
SERIAL_PROTOCOLPGM(" x: ");
|
SERIAL_PROTOCOLPGM(" x: ");
|
||||||
SERIAL_PROTOCOL(x);
|
SERIAL_PROTOCOL(x);
|
||||||
SERIAL_PROTOCOLPGM(" y: ");
|
SERIAL_PROTOCOLPGM(" y: ");
|
||||||
SERIAL_PROTOCOL(y);
|
SERIAL_PROTOCOL(y);
|
||||||
SERIAL_PROTOCOLPGM(" z: ");
|
SERIAL_PROTOCOLPGM(" z: ");
|
||||||
SERIAL_PROTOCOL(z);
|
SERIAL_PROTOCOL(z);
|
||||||
SERIAL_PROTOCOLPGM("\n");
|
SERIAL_PROTOCOLPGM("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_rotation_xyz(matrix_3x3 matrix, float &x, float& y, float& z)
|
void apply_rotation_xyz(matrix_3x3 matrix, float &x, float& y, float& z)
|
||||||
{
|
{
|
||||||
vector_3 vector = vector_3(x, y, z);
|
vector_3 vector = vector_3(x, y, z);
|
||||||
vector.apply_rotation(matrix);
|
vector.apply_rotation(matrix);
|
||||||
x = vector.x;
|
x = vector.x;
|
||||||
y = vector.y;
|
y = vector.y;
|
||||||
z = vector.z;
|
z = vector.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix_3x3 matrix_3x3::create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2)
|
matrix_3x3 matrix_3x3::create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2)
|
||||||
{
|
{
|
||||||
//row_0.debug("row_0");
|
//row_0.debug("row_0");
|
||||||
//row_1.debug("row_1");
|
//row_1.debug("row_1");
|
||||||
//row_2.debug("row_2");
|
//row_2.debug("row_2");
|
||||||
matrix_3x3 new_matrix;
|
matrix_3x3 new_matrix;
|
||||||
new_matrix.matrix[0] = row_0.x; new_matrix.matrix[1] = row_0.y; new_matrix.matrix[2] = row_0.z;
|
new_matrix.matrix[0] = row_0.x;
|
||||||
new_matrix.matrix[3] = row_1.x; new_matrix.matrix[4] = row_1.y; new_matrix.matrix[5] = row_1.z;
|
new_matrix.matrix[1] = row_0.y;
|
||||||
new_matrix.matrix[6] = row_2.x; new_matrix.matrix[7] = row_2.y; new_matrix.matrix[8] = row_2.z;
|
new_matrix.matrix[2] = row_0.z;
|
||||||
//new_matrix.debug("new_matrix");
|
new_matrix.matrix[3] = row_1.x;
|
||||||
|
new_matrix.matrix[4] = row_1.y;
|
||||||
|
new_matrix.matrix[5] = row_1.z;
|
||||||
|
new_matrix.matrix[6] = row_2.x;
|
||||||
|
new_matrix.matrix[7] = row_2.y;
|
||||||
|
new_matrix.matrix[8] = row_2.z;
|
||||||
|
//new_matrix.debug("new_matrix");
|
||||||
|
|
||||||
return new_matrix;
|
return new_matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void matrix_3x3::set_to_identity()
|
void matrix_3x3::set_to_identity()
|
||||||
{
|
{
|
||||||
matrix[0] = 1; matrix[1] = 0; matrix[2] = 0;
|
matrix[0] = 1;
|
||||||
matrix[3] = 0; matrix[4] = 1; matrix[5] = 0;
|
matrix[1] = 0;
|
||||||
matrix[6] = 0; matrix[7] = 0; matrix[8] = 1;
|
matrix[2] = 0;
|
||||||
|
matrix[3] = 0;
|
||||||
|
matrix[4] = 1;
|
||||||
|
matrix[5] = 0;
|
||||||
|
matrix[6] = 0;
|
||||||
|
matrix[7] = 0;
|
||||||
|
matrix[8] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix_3x3 matrix_3x3::create_look_at(vector_3 target)
|
matrix_3x3 matrix_3x3::create_look_at(vector_3 target)
|
||||||
|
|
@ -123,44 +135,50 @@ matrix_3x3 matrix_3x3::create_look_at(vector_3 target)
|
||||||
vector_3 x_row = vector_3(1, 0, -target.x/target.z).get_normal();
|
vector_3 x_row = vector_3(1, 0, -target.x/target.z).get_normal();
|
||||||
vector_3 y_row = vector_3::cross(z_row, x_row).get_normal();
|
vector_3 y_row = vector_3::cross(z_row, x_row).get_normal();
|
||||||
|
|
||||||
// x_row.debug("x_row");
|
// x_row.debug("x_row");
|
||||||
// y_row.debug("y_row");
|
// y_row.debug("y_row");
|
||||||
// z_row.debug("z_row");
|
// z_row.debug("z_row");
|
||||||
|
|
||||||
|
|
||||||
// create the matrix already correctly transposed
|
// create the matrix already correctly transposed
|
||||||
matrix_3x3 rot = matrix_3x3::create_from_rows(x_row, y_row, z_row);
|
matrix_3x3 rot = matrix_3x3::create_from_rows(x_row, y_row, z_row);
|
||||||
|
|
||||||
// rot.debug("rot");
|
// rot.debug("rot");
|
||||||
return rot;
|
return rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
matrix_3x3 matrix_3x3::transpose(matrix_3x3 original)
|
matrix_3x3 matrix_3x3::transpose(matrix_3x3 original)
|
||||||
{
|
{
|
||||||
matrix_3x3 new_matrix;
|
matrix_3x3 new_matrix;
|
||||||
new_matrix.matrix[0] = original.matrix[0]; new_matrix.matrix[1] = original.matrix[3]; new_matrix.matrix[2] = original.matrix[6];
|
new_matrix.matrix[0] = original.matrix[0];
|
||||||
new_matrix.matrix[3] = original.matrix[1]; new_matrix.matrix[4] = original.matrix[4]; new_matrix.matrix[5] = original.matrix[7];
|
new_matrix.matrix[1] = original.matrix[3];
|
||||||
new_matrix.matrix[6] = original.matrix[2]; new_matrix.matrix[7] = original.matrix[5]; new_matrix.matrix[8] = original.matrix[8];
|
new_matrix.matrix[2] = original.matrix[6];
|
||||||
return new_matrix;
|
new_matrix.matrix[3] = original.matrix[1];
|
||||||
|
new_matrix.matrix[4] = original.matrix[4];
|
||||||
|
new_matrix.matrix[5] = original.matrix[7];
|
||||||
|
new_matrix.matrix[6] = original.matrix[2];
|
||||||
|
new_matrix.matrix[7] = original.matrix[5];
|
||||||
|
new_matrix.matrix[8] = original.matrix[8];
|
||||||
|
return new_matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void matrix_3x3::debug(char* title)
|
void matrix_3x3::debug(char* title)
|
||||||
{
|
{
|
||||||
SERIAL_PROTOCOL(title);
|
SERIAL_PROTOCOL(title);
|
||||||
SERIAL_PROTOCOL("\n");
|
SERIAL_PROTOCOL("\n");
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(int i=0; i<3; i++)
|
for(int i=0; i<3; i++)
|
||||||
{
|
{
|
||||||
for(int j=0; j<3; j++)
|
for(int j=0; j<3; j++)
|
||||||
{
|
{
|
||||||
SERIAL_PROTOCOL(matrix[count]);
|
SERIAL_PROTOCOL(matrix[count]);
|
||||||
SERIAL_PROTOCOLPGM(" ");
|
SERIAL_PROTOCOLPGM(" ");
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SERIAL_PROTOCOLPGM("\n");
|
SERIAL_PROTOCOLPGM("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #ifdef ENABLE_AUTO_BED_LEVELING
|
#endif // #ifdef ENABLE_AUTO_BED_LEVELING
|
||||||
|
|
|
||||||
|
|
@ -24,35 +24,35 @@ class matrix_3x3;
|
||||||
|
|
||||||
struct vector_3
|
struct vector_3
|
||||||
{
|
{
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
|
|
||||||
vector_3();
|
vector_3();
|
||||||
vector_3(float x, float y, float z);
|
vector_3(float x, float y, float z);
|
||||||
|
|
||||||
static vector_3 cross(vector_3 a, vector_3 b);
|
static vector_3 cross(vector_3 a, vector_3 b);
|
||||||
|
|
||||||
vector_3 operator+(vector_3 v);
|
vector_3 operator+(vector_3 v);
|
||||||
vector_3 operator-(vector_3 v);
|
vector_3 operator-(vector_3 v);
|
||||||
void normalize();
|
void normalize();
|
||||||
float get_length();
|
float get_length();
|
||||||
vector_3 get_normal();
|
vector_3 get_normal();
|
||||||
|
|
||||||
void debug(char* title);
|
void debug(char* title);
|
||||||
|
|
||||||
void apply_rotation(matrix_3x3 matrix);
|
void apply_rotation(matrix_3x3 matrix);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct matrix_3x3
|
struct matrix_3x3
|
||||||
{
|
{
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
|
|
||||||
static matrix_3x3 create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2);
|
static matrix_3x3 create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2);
|
||||||
static matrix_3x3 create_look_at(vector_3 target);
|
static matrix_3x3 create_look_at(vector_3 target);
|
||||||
static matrix_3x3 transpose(matrix_3x3 original);
|
static matrix_3x3 transpose(matrix_3x3 original);
|
||||||
|
|
||||||
void set_to_identity();
|
void set_to_identity();
|
||||||
|
|
||||||
void debug(char* title);
|
void debug(char* title);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,140 +45,140 @@ int w25x20cl_mfrid_devid(void);
|
||||||
|
|
||||||
int8_t w25x20cl_init(void)
|
int8_t w25x20cl_init(void)
|
||||||
{
|
{
|
||||||
PIN_OUT(W25X20CL_PIN_CS);
|
PIN_OUT(W25X20CL_PIN_CS);
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
W25X20CL_SPI_ENTER();
|
W25X20CL_SPI_ENTER();
|
||||||
if (!w25x20cl_mfrid_devid()) return 0;
|
if (!w25x20cl_mfrid_devid()) return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_enable_wr(void)
|
void w25x20cl_enable_wr(void)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_ENABLE_WR); // send command 0x06
|
_SPI_TX(_CMD_ENABLE_WR); // send command 0x06
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_disable_wr(void)
|
void w25x20cl_disable_wr(void)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_DISABLE_WR); // send command 0x04
|
_SPI_TX(_CMD_DISABLE_WR); // send command 0x04
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t w25x20cl_rd_status_reg(void)
|
uint8_t w25x20cl_rd_status_reg(void)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90
|
_SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90
|
||||||
uint8_t val = _SPI_RX(); // receive value
|
uint8_t val = _SPI_RX(); // receive value
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_wr_status_reg(uint8_t val)
|
void w25x20cl_wr_status_reg(uint8_t val)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90
|
_SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90
|
||||||
_SPI_TX(val); // send value
|
_SPI_TX(val); // send value
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt)
|
void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_RD_DATA); // send command 0x03
|
_SPI_TX(_CMD_RD_DATA); // send command 0x03
|
||||||
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
||||||
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
||||||
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
||||||
while (cnt--) // receive data
|
while (cnt--) // receive data
|
||||||
*(data++) = _SPI_RX();
|
*(data++) = _SPI_RX();
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt)
|
void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
|
_SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
|
||||||
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
||||||
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
||||||
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
||||||
while (cnt--) // send data
|
while (cnt--) // send data
|
||||||
_SPI_TX(*(data++));
|
_SPI_TX(*(data++));
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
|
void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
|
_SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
|
||||||
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
||||||
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
||||||
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
||||||
while (cnt--) // send data
|
while (cnt--) // send data
|
||||||
_SPI_TX(pgm_read_byte(data++));
|
_SPI_TX(pgm_read_byte(data++));
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_erase(uint8_t cmd, uint32_t addr)
|
void w25x20cl_erase(uint8_t cmd, uint32_t addr)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(cmd); // send command 0x20
|
_SPI_TX(cmd); // send command 0x20
|
||||||
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
|
||||||
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
|
||||||
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_sector_erase(uint32_t addr)
|
void w25x20cl_sector_erase(uint32_t addr)
|
||||||
{
|
{
|
||||||
return w25x20cl_erase(_CMD_SECTOR_ERASE, addr);
|
return w25x20cl_erase(_CMD_SECTOR_ERASE, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_block32_erase(uint32_t addr)
|
void w25x20cl_block32_erase(uint32_t addr)
|
||||||
{
|
{
|
||||||
return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr);
|
return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_block64_erase(uint32_t addr)
|
void w25x20cl_block64_erase(uint32_t addr)
|
||||||
{
|
{
|
||||||
return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr);
|
return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_chip_erase(void)
|
void w25x20cl_chip_erase(void)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7
|
_SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void w25x20cl_rd_uid(uint8_t* uid)
|
void w25x20cl_rd_uid(uint8_t* uid)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_RD_UID); // send command 0x4b
|
_SPI_TX(_CMD_RD_UID); // send command 0x4b
|
||||||
uint8_t cnt = 4; // 4 dummy bytes
|
uint8_t cnt = 4; // 4 dummy bytes
|
||||||
while (cnt--) // receive dummy bytes
|
while (cnt--) // receive dummy bytes
|
||||||
_SPI_RX();
|
_SPI_RX();
|
||||||
cnt = 8; // 8 bytes UID
|
cnt = 8; // 8 bytes UID
|
||||||
while (cnt--) // receive UID
|
while (cnt--) // receive UID
|
||||||
uid[7 - cnt] = _SPI_RX();
|
uid[7 - cnt] = _SPI_RX();
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
}
|
}
|
||||||
|
|
||||||
int w25x20cl_mfrid_devid(void)
|
int w25x20cl_mfrid_devid(void)
|
||||||
{
|
{
|
||||||
_CS_LOW();
|
_CS_LOW();
|
||||||
_SPI_TX(_CMD_MFRID_DEVID); // send command 0x90
|
_SPI_TX(_CMD_MFRID_DEVID); // send command 0x90
|
||||||
uint8_t cnt = 3; // 3 address bytes
|
uint8_t cnt = 3; // 3 address bytes
|
||||||
while (cnt--) // send address bytes
|
while (cnt--) // send address bytes
|
||||||
_SPI_TX(0x00);
|
_SPI_TX(0x00);
|
||||||
uint8_t w25x20cl_mfrid = _SPI_RX(); // receive mfrid
|
uint8_t w25x20cl_mfrid = _SPI_RX(); // receive mfrid
|
||||||
uint8_t w25x20cl_devid = _SPI_RX(); // receive devid
|
uint8_t w25x20cl_devid = _SPI_RX(); // receive devid
|
||||||
_CS_HIGH();
|
_CS_HIGH();
|
||||||
return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));
|
return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25x20cl_wait_busy(void)
|
void w25x20cl_wait_busy(void)
|
||||||
{
|
{
|
||||||
while (w25x20cl_rd_status_reg() & W25X20CL_STATUS_BUSY) ;
|
while (w25x20cl_rd_status_reg() & W25X20CL_STATUS_BUSY) ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1118
Firmware/xyzcal.cpp
1118
Firmware/xyzcal.cpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue