From 21dcfb23f45b11bdb41c316d75d9bed1fd406cfa Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Thu, 31 Oct 2019 15:31:08 +0100 Subject: [PATCH 01/58] Follow RepRap Wiki G-codes documentation M120 is Enable endstops M121 is disable endstops I guess this was just a typo issue. --- Firmware/Marlin_main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index a2cbece56..593194c60 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -6366,16 +6366,16 @@ Sigma_Exit: lcd_setstatus(strchr_pointer + 5); break;*/ - //! ### M120 - Disable endstops + //! ### M120 - Ensable endstops // ---------------------------------------- case 120: - enable_endstops(false) ; + enable_endstops(true) ; break; - //! ### M121 - Enable endstops + //! ### M121 - Disable endstops // ---------------------------------------- case 121: - enable_endstops(true) ; + enable_endstops(false) ; break; //! ### M119 - Get endstop states From 6017600714a751a46b879964d186ea97115c5277 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 16 Jun 2019 21:05:13 +0200 Subject: [PATCH 02/58] Reintroduce the ability to disable TMC interpolation per-axis --- Firmware/tmc2130.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Firmware/tmc2130.cpp b/Firmware/tmc2130.cpp index 108d00b1d..b87272e2d 100755 --- a/Firmware/tmc2130.cpp +++ b/Firmware/tmc2130.cpp @@ -437,6 +437,9 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_ uint8_t tbl = tmc2130_chopper_config[axis].tbl; //blanking time, original value = 2 if (axis == E_AXIS) { +#if defined(TMC2130_INTPOL_E) && (TMC2130_INTPOL_E == 0) + intpol = 0; +#endif #ifdef TMC2130_CNSTOFF_E // fd = 0 (slow decay only) hstrt = 0; //fd0..2 @@ -447,6 +450,16 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_ // toff = TMC2130_TOFF_E; // toff = 3-5 // rndtf = 1; } +#if defined(TMC2130_INTPOL_XY) && (TMC2130_INTPOL_XY == 0) + else if (axis == X_AXIS || axis == Y_AXIS) { + intpol = 0; + } +#endif +#if defined(TMC2130_INTPOL_Z) && (TMC2130_INTPOL_Z == 0) + else if (axis == Z_AXIS) { + intpol = 0; + } +#endif // DBG(_n("tmc2130_setup_chopper(axis=%hhd, mres=%hhd, curh=%hhd, curr=%hhd\n"), axis, mres, current_h, current_r); // DBG(_n(" toff=%hhd, hstr=%hhd, hend=%hhd, tbl=%hhd\n"), toff, hstrt, hend, tbl); if (current_r <= 31) From 6ceca9bf85f93479e677194635e873bbfa831bbb Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 18 Feb 2020 11:52:36 +0100 Subject: [PATCH 03/58] Implement double-edge stepping Introduce new wrapper macros to tick the stepper pins. Default to the original raising-edge stepping mode. When using the TMC double-edge stepping mode (aka half-wave or square-wave mode) the _LO macros become no-ops. --- Firmware/stepper.cpp | 128 +++++++++++++++++++++++++++++-------------- Firmware/tmc2130.cpp | 16 +++++- 2 files changed, 100 insertions(+), 44 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index de250ec97..8f2a4f125 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -48,6 +48,50 @@ int fsensor_counter; //counter for e-steps uint16_t SP_min = 0x21FF; #endif //DEBUG_STACK_MONITOR + +/* + * Stepping macros + */ +#define _STEP_PIN_X_AXIS X_STEP_PIN +#define _STEP_PIN_Y_AXIS Y_STEP_PIN +#define _STEP_PIN_Z_AXIS Z_STEP_PIN +#define _STEP_PIN_E_AXIS E0_STEP_PIN + +#ifdef DEBUG_XSTEP_DUP_PIN +#define _STEP_PIN_X_DUP_AXIS DEBUG_XSTEP_DUP_PIN +#endif +#ifdef DEBUG_YSTEP_DUP_PIN +#define _STEP_PIN_Y_DUP_AXIS DEBUG_YSTEP_DUP_PIN +#endif +#ifdef Y_DUAL_STEPPER_DRIVERS +#error Y_DUAL_STEPPER_DRIVERS not fully implemented +#define _STEP_PIN_Y2_AXIS Y2_STEP_PIN +#endif +#ifdef Z_DUAL_STEPPER_DRIVERS +#error Z_DUAL_STEPPER_DRIVERS not fully implemented +#define _STEP_PIN_Z2_AXIS Z2_STEP_PIN +#endif + +#ifdef TMC2130_DEDGE_STEPPING +#define STEP_NC_HI(axis) TOGGLE(_STEP_PIN_##axis) +#define STEP_NC_LO(axis) //NOP +#else + +#define _STEP_HI_X_AXIS !INVERT_X_STEP_PIN +#define _STEP_LO_X_AXIS INVERT_X_STEP_PIN +#define _STEP_HI_Y_AXIS !INVERT_Y_STEP_PIN +#define _STEP_LO_Y_AXIS INVERT_Y_STEP_PIN +#define _STEP_HI_Z_AXIS !INVERT_Z_STEP_PIN +#define _STEP_LO_Z_AXIS INVERT_Z_STEP_PIN +#define _STEP_HI_E_AXIS !INVERT_E_STEP_PIN +#define _STEP_LO_E_AXIS INVERT_E_STEP_PIN + +#define STEP_NC_HI(axis) WRITE_NC(_STEP_PIN_##axis, _STEP_HI_##axis) +#define STEP_NC_LO(axis) WRITE_NC(_STEP_PIN_##axis, _STEP_LO_##axis) + +#endif //TMC2130_DEDGE_STEPPING + + //=========================================================================== //=============================public variables ============================ //=========================================================================== @@ -300,9 +344,9 @@ FORCE_INLINE void stepper_next_block() _delay_us(100); for (uint8_t i = 0; i < st_backlash_x; i++) { - WRITE_NC(X_STEP_PIN, !INVERT_X_STEP_PIN); + STEP_NC_HI(X_AXIS); _delay_us(100); - WRITE_NC(X_STEP_PIN, INVERT_X_STEP_PIN); + STEP_NC_LO(X_AXIS); _delay_us(900); } } @@ -323,9 +367,9 @@ FORCE_INLINE void stepper_next_block() _delay_us(100); for (uint8_t i = 0; i < st_backlash_y; i++) { - WRITE_NC(Y_STEP_PIN, !INVERT_Y_STEP_PIN); + STEP_NC_HI(Y_AXIS); _delay_us(100); - WRITE_NC(Y_STEP_PIN, INVERT_Y_STEP_PIN); + STEP_NC_LO(Y_AXIS); _delay_us(900); } } @@ -607,44 +651,44 @@ FORCE_INLINE void stepper_tick_lowres() // Step in X axis counter_x.lo += current_block->steps_x.lo; if (counter_x.lo > 0) { - WRITE_NC(X_STEP_PIN, !INVERT_X_STEP_PIN); + STEP_NC_HI(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - WRITE_NC(DEBUG_XSTEP_DUP_PIN,!INVERT_X_STEP_PIN); + STEP_NC_HI(X_DUP_AXIS); #endif //DEBUG_XSTEP_DUP_PIN counter_x.lo -= current_block->step_event_count.lo; count_position[X_AXIS]+=count_direction[X_AXIS]; - WRITE_NC(X_STEP_PIN, INVERT_X_STEP_PIN); + STEP_NC_LO(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - WRITE_NC(DEBUG_XSTEP_DUP_PIN,INVERT_X_STEP_PIN); + STEP_NC_LO(X_DUP_AXIS); #endif //DEBUG_XSTEP_DUP_PIN } // Step in Y axis counter_y.lo += current_block->steps_y.lo; if (counter_y.lo > 0) { - WRITE_NC(Y_STEP_PIN, !INVERT_Y_STEP_PIN); + STEP_NC_HI(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - WRITE_NC(DEBUG_YSTEP_DUP_PIN,!INVERT_Y_STEP_PIN); + STEP_NC_HI(Y_DUP_AXIS); #endif //DEBUG_YSTEP_DUP_PIN counter_y.lo -= current_block->step_event_count.lo; count_position[Y_AXIS]+=count_direction[Y_AXIS]; - WRITE_NC(Y_STEP_PIN, INVERT_Y_STEP_PIN); + STEP_NC_LO(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - WRITE_NC(DEBUG_YSTEP_DUP_PIN,INVERT_Y_STEP_PIN); + STEP_NC_LO(Y_DUP_AXIS); #endif //DEBUG_YSTEP_DUP_PIN } // Step in Z axis counter_z.lo += current_block->steps_z.lo; if (counter_z.lo > 0) { - WRITE_NC(Z_STEP_PIN, !INVERT_Z_STEP_PIN); + STEP_NC_HI(Z_AXIS); counter_z.lo -= current_block->step_event_count.lo; count_position[Z_AXIS]+=count_direction[Z_AXIS]; - WRITE_NC(Z_STEP_PIN, INVERT_Z_STEP_PIN); + STEP_NC_LO(Z_AXIS); } // Step in E axis counter_e.lo += current_block->steps_e.lo; if (counter_e.lo > 0) { #ifndef LIN_ADVANCE - WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); + STEP_NC_HI(E_AXIS); #endif /* LIN_ADVANCE */ counter_e.lo -= current_block->step_event_count.lo; count_position[E_AXIS] += count_direction[E_AXIS]; @@ -654,7 +698,7 @@ FORCE_INLINE void stepper_tick_lowres() #ifdef FILAMENT_SENSOR fsensor_counter += count_direction[E_AXIS]; #endif //FILAMENT_SENSOR - WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); + STEP_NC_LO(E_AXIS); #endif } if(++ step_events_completed.lo >= current_block->step_event_count.lo) @@ -669,44 +713,44 @@ FORCE_INLINE void stepper_tick_highres() // Step in X axis counter_x.wide += current_block->steps_x.wide; if (counter_x.wide > 0) { - WRITE_NC(X_STEP_PIN, !INVERT_X_STEP_PIN); + STEP_NC_HI(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - WRITE_NC(DEBUG_XSTEP_DUP_PIN,!INVERT_X_STEP_PIN); + STEP_NC_HI(X_DUP_AXIS); #endif //DEBUG_XSTEP_DUP_PIN counter_x.wide -= current_block->step_event_count.wide; count_position[X_AXIS]+=count_direction[X_AXIS]; - WRITE_NC(X_STEP_PIN, INVERT_X_STEP_PIN); + STEP_NC_LO(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - WRITE_NC(DEBUG_XSTEP_DUP_PIN,INVERT_X_STEP_PIN); + STEP_NC_LO(X_DUP_AXIS); #endif //DEBUG_XSTEP_DUP_PIN } // Step in Y axis counter_y.wide += current_block->steps_y.wide; if (counter_y.wide > 0) { - WRITE_NC(Y_STEP_PIN, !INVERT_Y_STEP_PIN); + STEP_NC_HI(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - WRITE_NC(DEBUG_YSTEP_DUP_PIN,!INVERT_Y_STEP_PIN); + STEP_NC_HI(Y_DUP_AXIS); #endif //DEBUG_YSTEP_DUP_PIN counter_y.wide -= current_block->step_event_count.wide; count_position[Y_AXIS]+=count_direction[Y_AXIS]; - WRITE_NC(Y_STEP_PIN, INVERT_Y_STEP_PIN); + STEP_NC_LO(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - WRITE_NC(DEBUG_YSTEP_DUP_PIN,INVERT_Y_STEP_PIN); + STEP_NC_LO(Y_DUP_AXIS); #endif //DEBUG_YSTEP_DUP_PIN } // Step in Z axis counter_z.wide += current_block->steps_z.wide; if (counter_z.wide > 0) { - WRITE_NC(Z_STEP_PIN, !INVERT_Z_STEP_PIN); + STEP_NC_HI(Z_AXIS); counter_z.wide -= current_block->step_event_count.wide; count_position[Z_AXIS]+=count_direction[Z_AXIS]; - WRITE_NC(Z_STEP_PIN, INVERT_Z_STEP_PIN); + STEP_NC_LO(Z_AXIS); } // Step in E axis counter_e.wide += current_block->steps_e.wide; if (counter_e.wide > 0) { #ifndef LIN_ADVANCE - WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); + STEP_NC_HI(E_AXIS); #endif /* LIN_ADVANCE */ counter_e.wide -= current_block->step_event_count.wide; count_position[E_AXIS]+=count_direction[E_AXIS]; @@ -716,7 +760,7 @@ FORCE_INLINE void stepper_tick_highres() #ifdef FILAMENT_SENSOR fsensor_counter += count_direction[E_AXIS]; #endif //FILAMENT_SENSOR - WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); + STEP_NC_LO(E_AXIS); #endif } if(++ step_events_completed.wide >= current_block->step_event_count.wide) @@ -997,9 +1041,9 @@ FORCE_INLINE void advance_isr_scheduler() { bool rev = (e_steps < 0); do { - WRITE_NC(E0_STEP_PIN, !INVERT_E_STEP_PIN); + STEP_NC_HI(E_AXIS); e_steps += (rev? 1: -1); - WRITE_NC(E0_STEP_PIN, INVERT_E_STEP_PIN); + STEP_NC_LO(E_AXIS); #if defined(FILAMENT_SENSOR) && defined(PAT9125) fsensor_counter += (rev? -1: 1); #endif @@ -1385,14 +1429,14 @@ void babystep(const uint8_t axis,const bool direction) WRITE(X_DIR_PIN,(INVERT_X_DIR)^direction); //perform step - WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); + STEP_NC_HI(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - WRITE(DEBUG_XSTEP_DUP_PIN,!INVERT_X_STEP_PIN); + STEP_NC_HI(X_DUP_AXIS); #endif //DEBUG_XSTEP_DUP_PIN delayMicroseconds(1); - WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); + STEP_NC_LO(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - WRITE(DEBUG_XSTEP_DUP_PIN,INVERT_X_STEP_PIN); + STEP_NC_LO(X_DUP_AXIS); #endif //DEBUG_XSTEP_DUP_PIN //get old pin state back. @@ -1408,14 +1452,14 @@ void babystep(const uint8_t axis,const bool direction) WRITE(Y_DIR_PIN,(INVERT_Y_DIR)^direction); //perform step - WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); + STEP_NC_HI(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - WRITE(DEBUG_YSTEP_DUP_PIN,!INVERT_Y_STEP_PIN); + STEP_NC_HI(Y_DUP_AXIS); #endif //DEBUG_YSTEP_DUP_PIN delayMicroseconds(1); - WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); + STEP_NC_LO(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - WRITE(DEBUG_YSTEP_DUP_PIN,INVERT_Y_STEP_PIN); + STEP_NC_LO(Y_DUP_AXIS); #endif //DEBUG_YSTEP_DUP_PIN //get old pin state back. @@ -1434,14 +1478,14 @@ void babystep(const uint8_t axis,const bool direction) WRITE(Z2_DIR_PIN,(INVERT_Z_DIR)^direction^BABYSTEP_INVERT_Z); #endif //perform step - WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); + STEP_NC_HI(Z_AXIS); #ifdef Z_DUAL_STEPPER_DRIVERS - WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN); + STEP_NC_HI(Z2_AXIS); #endif delayMicroseconds(1); - WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); + STEP_NC_LO(Z_AXIS); #ifdef Z_DUAL_STEPPER_DRIVERS - WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN); + STEP_NC_LO(Z2_AXIS); #endif //get old pin state back. diff --git a/Firmware/tmc2130.cpp b/Firmware/tmc2130.cpp index b87272e2d..20c23704f 100755 --- a/Firmware/tmc2130.cpp +++ b/Firmware/tmc2130.cpp @@ -428,6 +428,11 @@ void tmc2130_check_overtemp() void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_t current_r) { uint8_t intpol = (mres != 0); // intpol to 256 only if microsteps aren't 256 +#ifdef TMC2130_DEDGE_STEPPING + uint8_t dedge = 1; +#else + uint8_t dedge = 0; +#endif uint8_t toff = tmc2130_chopper_config[axis].toff; // toff = 3 (fchop = 27.778kHz) uint8_t hstrt = tmc2130_chopper_config[axis].hstr; //initial 4, modified to 5 uint8_t hend = tmc2130_chopper_config[axis].hend; //original value = 1 @@ -464,12 +469,12 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_ // DBG(_n(" toff=%hhd, hstr=%hhd, hend=%hhd, tbl=%hhd\n"), toff, hstrt, hend, tbl); if (current_r <= 31) { - tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 1, 0, 0, 0, mres, intpol, 0, 0); + tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 1, 0, 0, 0, mres, intpol, dedge, 0); tmc2130_wr(axis, TMC2130_REG_IHOLD_IRUN, 0x000f0000 | ((current_r & 0x1f) << 8) | (current_h & 0x1f)); } else { - tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 0, 0, 0, 0, mres, intpol, 0, 0); + tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 0, 0, 0, 0, mres, intpol, dedge, 0); tmc2130_wr(axis, TMC2130_REG_IHOLD_IRUN, 0x000f0000 | (((current_r >> 1) & 0x1f) << 8) | ((current_h >> 1) & 0x1f)); } } @@ -706,10 +711,17 @@ static uint8_t tmc2130_rx(uint8_t axis, uint8_t addr, uint32_t* rval) #define _SET_DIR_Z(dir) { WRITE(Z_DIR_PIN, dir?INVERT_Z_DIR:!INVERT_Z_DIR); asm("nop"); } #define _SET_DIR_E(dir) { WRITE(E0_DIR_PIN, dir?INVERT_E0_DIR:!INVERT_E0_DIR); asm("nop"); } +#ifdef TMC2130_DEDGE_STEPPING +#define _DO_STEP_X { TOGGLE(X_STEP_PIN); asm("nop"); } +#define _DO_STEP_Y { TOGGLE(Y_STEP_PIN); asm("nop"); } +#define _DO_STEP_Z { TOGGLE(Z_STEP_PIN); asm("nop"); } +#define _DO_STEP_E { TOGGLE(E0_STEP_PIN); asm("nop"); } +#else #define _DO_STEP_X { WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); asm("nop"); WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); asm("nop"); } #define _DO_STEP_Y { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); asm("nop"); WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); asm("nop"); } #define _DO_STEP_Z { WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); asm("nop"); WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); asm("nop"); } #define _DO_STEP_E { WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); asm("nop"); WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); asm("nop"); } +#endif uint16_t tmc2130_get_res(uint8_t axis) From 1181beffb1c47828a1d40303348b53f2c06345e7 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 17 Jun 2019 21:10:18 +0200 Subject: [PATCH 04/58] Enable DEDGE stepping on supported variants --- Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 1 + Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index b135d8d13..e1eb2ef1f 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -269,6 +269,7 @@ // #define TMC2130_UNLOAD_CURRENT_R 12 // lower current for M600 to protect filament sensor - Unused #define TMC2130_STEALTH_Z +#define TMC2130_DEDGE_STEPPING //#define TMC2130_SERVICE_CODES_M910_M918 diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index e618c54ef..d4c52281c 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -271,6 +271,7 @@ // #define TMC2130_UNLOAD_CURRENT_R 12 // lower current for M600 to protect filament sensor - Unused #define TMC2130_STEALTH_Z +#define TMC2130_DEDGE_STEPPING //#define TMC2130_SERVICE_CODES_M910_M918 From e6b182aa9fc3a8f812a8580a0c25152418f3c2bc Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 18 Jun 2019 17:11:01 +0200 Subject: [PATCH 05/58] Implement proper step/delay pauses in tmc2130 functions Add constants for the various required delays in tmc2130.h, which will come in handy for stepper.cpp as well. Move the delays in the _set functions and remove the pauses from the various calling points and macros. Note that the hard-coded pause wouldn't cut it for the stepper ISR, but it's fine for other use cases. --- Firmware/tmc2130.cpp | 39 ++++++++++++++++++++------------------- Firmware/tmc2130.h | 4 ++++ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Firmware/tmc2130.cpp b/Firmware/tmc2130.cpp index 20c23704f..15646b925 100755 --- a/Firmware/tmc2130.cpp +++ b/Firmware/tmc2130.cpp @@ -696,31 +696,31 @@ static uint8_t tmc2130_rx(uint8_t axis, uint8_t addr, uint32_t* rval) #define _GET_PWR_Z (READ(Z_ENABLE_PIN) == Z_ENABLE_ON) #define _GET_PWR_E (READ(E0_ENABLE_PIN) == E_ENABLE_ON) -#define _SET_PWR_X(ena) { WRITE(X_ENABLE_PIN, ena?X_ENABLE_ON:!X_ENABLE_ON); asm("nop"); } -#define _SET_PWR_Y(ena) { WRITE(Y_ENABLE_PIN, ena?Y_ENABLE_ON:!Y_ENABLE_ON); asm("nop"); } -#define _SET_PWR_Z(ena) { WRITE(Z_ENABLE_PIN, ena?Z_ENABLE_ON:!Z_ENABLE_ON); asm("nop"); } -#define _SET_PWR_E(ena) { WRITE(E0_ENABLE_PIN, ena?E_ENABLE_ON:!E_ENABLE_ON); asm("nop"); } +#define _SET_PWR_X(ena) WRITE(X_ENABLE_PIN, ena?X_ENABLE_ON:!X_ENABLE_ON) +#define _SET_PWR_Y(ena) WRITE(Y_ENABLE_PIN, ena?Y_ENABLE_ON:!Y_ENABLE_ON) +#define _SET_PWR_Z(ena) WRITE(Z_ENABLE_PIN, ena?Z_ENABLE_ON:!Z_ENABLE_ON) +#define _SET_PWR_E(ena) WRITE(E0_ENABLE_PIN, ena?E_ENABLE_ON:!E_ENABLE_ON) #define _GET_DIR_X (READ(X_DIR_PIN) == INVERT_X_DIR) #define _GET_DIR_Y (READ(Y_DIR_PIN) == INVERT_Y_DIR) #define _GET_DIR_Z (READ(Z_DIR_PIN) == INVERT_Z_DIR) #define _GET_DIR_E (READ(E0_DIR_PIN) == INVERT_E0_DIR) -#define _SET_DIR_X(dir) { WRITE(X_DIR_PIN, dir?INVERT_X_DIR:!INVERT_X_DIR); asm("nop"); } -#define _SET_DIR_Y(dir) { WRITE(Y_DIR_PIN, dir?INVERT_Y_DIR:!INVERT_Y_DIR); asm("nop"); } -#define _SET_DIR_Z(dir) { WRITE(Z_DIR_PIN, dir?INVERT_Z_DIR:!INVERT_Z_DIR); asm("nop"); } -#define _SET_DIR_E(dir) { WRITE(E0_DIR_PIN, dir?INVERT_E0_DIR:!INVERT_E0_DIR); asm("nop"); } +#define _SET_DIR_X(dir) WRITE(X_DIR_PIN, dir?INVERT_X_DIR:!INVERT_X_DIR) +#define _SET_DIR_Y(dir) WRITE(Y_DIR_PIN, dir?INVERT_Y_DIR:!INVERT_Y_DIR) +#define _SET_DIR_Z(dir) WRITE(Z_DIR_PIN, dir?INVERT_Z_DIR:!INVERT_Z_DIR) +#define _SET_DIR_E(dir) WRITE(E0_DIR_PIN, dir?INVERT_E0_DIR:!INVERT_E0_DIR) #ifdef TMC2130_DEDGE_STEPPING -#define _DO_STEP_X { TOGGLE(X_STEP_PIN); asm("nop"); } -#define _DO_STEP_Y { TOGGLE(Y_STEP_PIN); asm("nop"); } -#define _DO_STEP_Z { TOGGLE(Z_STEP_PIN); asm("nop"); } -#define _DO_STEP_E { TOGGLE(E0_STEP_PIN); asm("nop"); } +#define _DO_STEP_X TOGGLE(X_STEP_PIN) +#define _DO_STEP_Y TOGGLE(Y_STEP_PIN) +#define _DO_STEP_Z TOGGLE(Z_STEP_PIN) +#define _DO_STEP_E TOGGLE(E0_STEP_PIN) #else -#define _DO_STEP_X { WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); asm("nop"); WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); asm("nop"); } -#define _DO_STEP_Y { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); asm("nop"); WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); asm("nop"); } -#define _DO_STEP_Z { WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); asm("nop"); WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); asm("nop"); } -#define _DO_STEP_E { WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); asm("nop"); WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); asm("nop"); } +#define _DO_STEP_X { WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); } +#define _DO_STEP_Y { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); } +#define _DO_STEP_Z { WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); } +#define _DO_STEP_E { WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); } #endif @@ -762,6 +762,7 @@ void tmc2130_set_pwr(uint8_t axis, uint8_t pwr) case Z_AXIS: _SET_PWR_Z(pwr); break; case E_AXIS: _SET_PWR_E(pwr); break; } + delayMicroseconds(TMC2130_SET_PWR_DELAY); } uint8_t tmc2130_get_inv(uint8_t axis) @@ -798,6 +799,7 @@ void tmc2130_set_dir(uint8_t axis, uint8_t dir) case Z_AXIS: _SET_DIR_Z(dir); break; case E_AXIS: _SET_DIR_E(dir); break; } + delayMicroseconds(TMC2130_SET_DIR_DELAY); } void tmc2130_do_step(uint8_t axis) @@ -813,8 +815,8 @@ void tmc2130_do_step(uint8_t axis) void tmc2130_do_steps(uint8_t axis, uint16_t steps, uint8_t dir, uint16_t delay_us) { - tmc2130_set_dir(axis, dir); - delayMicroseconds(100); + if (tmc2130_get_dir(axis) != dir) + tmc2130_set_dir(axis, dir); while (steps--) { tmc2130_do_step(axis); @@ -845,7 +847,6 @@ void tmc2130_goto_step(uint8_t axis, uint8_t step, uint8_t dir, uint16_t delay_u cnt = steps; } tmc2130_set_dir(axis, dir); - delayMicroseconds(100); mscnt = tmc2130_rd_MSCNT(axis); while ((cnt--) && ((mscnt >> shift) != step)) { diff --git a/Firmware/tmc2130.h b/Firmware/tmc2130.h index ed4c0d7c0..4b5b764ce 100644 --- a/Firmware/tmc2130.h +++ b/Firmware/tmc2130.h @@ -29,6 +29,10 @@ extern uint8_t tmc2130_sg_homing_axes_mask; #define TMC2130_WAVE_FAC1000_MAX 200 #define TMC2130_WAVE_FAC1000_STP 1 +#define TMC2130_MINIMUM_PULSE 0 // minimum pulse width in uS +#define TMC2130_SET_DIR_DELAY 20 // minimum delay after setting direction in uS +#define TMC2130_SET_PWR_DELAY 0 // minimum delay after changing pwr mode in uS + extern uint8_t tmc2130_home_enabled; extern uint8_t tmc2130_home_origin[2]; extern uint8_t tmc2130_home_bsteps[2]; From 6ea198a866efcc6ecc55d2c7c29a4535ee9bee14 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 14 Jul 2019 17:39:06 +0200 Subject: [PATCH 06/58] Fix DEDGE in sm4.c (fixes xyz calibration) --- Firmware/sm4.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Firmware/sm4.c b/Firmware/sm4.c index 34cf8a3c9..b68e02762 100644 --- a/Firmware/sm4.c +++ b/Firmware/sm4.c @@ -129,11 +129,15 @@ void sm4_set_dir_bits(uint8_t dir_bits) 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)) +#ifdef TMC2130_DEDGE_STEPPING + PORTC ^= (axes_mask & 0x0f); //set step signals by mask +#else register uint8_t portC = PORTC & 0xf0; PORTC = portC | (axes_mask & 0x0f); //set step signals by mask asm("nop"); PORTC = portC; //set step signals to zero asm("nop"); +#endif #endif //((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3) || (MOTHERBOARD == BOARD_EINSY_1_0a)) } From 78bbfc62379719a127cd5edcc48b3eb21aa2594f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 14 Jul 2019 18:53:37 +0200 Subject: [PATCH 07/58] Fix delay calculations inside babystep() - Avoid all delays when using DEDGE stepping - Correctly account for direction change delays --- Firmware/stepper.cpp | 179 +++++++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 74 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 8f2a4f125..b3cc5a577 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -72,6 +72,14 @@ uint16_t SP_min = 0x21FF; #define _STEP_PIN_Z2_AXIS Z2_STEP_PIN #endif +#ifdef TMC2130 +#define STEPPER_MINIMUM_PULSE TMC2130_MINIMUM_PULSE +#define STEPPER_SET_DIR_DELAY TMC2130_SET_DIR_DELAY +#else +#define STEPPER_MINIMUM_PULSE 2 +#define STEPPER_SET_DIR_DELAY 100 +#endif + #ifdef TMC2130_DEDGE_STEPPING #define STEP_NC_HI(axis) TOGGLE(_STEP_PIN_##axis) #define STEP_NC_LO(axis) //NOP @@ -1416,89 +1424,112 @@ void quickStop() #ifdef BABYSTEPPING void babystep(const uint8_t axis,const bool direction) { - //MUST ONLY BE CALLED BY A ISR, it depends on that no other ISR interrupts this - //store initial pin states - switch(axis) - { - case X_AXIS: - { - enable_x(); - uint8_t old_x_dir_pin= READ(X_DIR_PIN); //if dualzstepper, both point to same direction. - - //setup new step - WRITE(X_DIR_PIN,(INVERT_X_DIR)^direction); - - //perform step - STEP_NC_HI(X_AXIS); + // MUST ONLY BE CALLED BY A ISR as stepper pins are manipulated directly. + // note: when switching direction no delay is inserted at the end when the + // original is restored. We assume enough time passes as the function + // returns and the stepper is manipulated again (to avoid dead times) + switch(axis) + { + case X_AXIS: + { + enable_x(); + uint8_t old_x_dir_pin = READ(X_DIR_PIN); //if dualzstepper, both point to same direction. + uint8_t new_x_dir_pin = (INVERT_X_DIR)^direction; + + //setup new step + if (new_x_dir_pin != old_x_dir_pin) { + WRITE_NC(X_DIR_PIN, new_x_dir_pin); + delayMicroseconds(STEPPER_SET_DIR_DELAY); + } + + //perform step + STEP_NC_HI(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - STEP_NC_HI(X_DUP_AXIS); -#endif //DEBUG_XSTEP_DUP_PIN - delayMicroseconds(1); - STEP_NC_LO(X_AXIS); + STEP_NC_HI(X_DUP_AXIS); +#endif +#ifndef TMC2130_DEDGE_STEPPING + delayMicroseconds(STEPPER_MINIMUM_PULSE); + STEP_NC_LO(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN - STEP_NC_LO(X_DUP_AXIS); -#endif //DEBUG_XSTEP_DUP_PIN + STEP_NC_LO(X_DUP_AXIS); +#endif +#endif - //get old pin state back. - WRITE(X_DIR_PIN,old_x_dir_pin); - } - break; - case Y_AXIS: - { - enable_y(); - uint8_t old_y_dir_pin= READ(Y_DIR_PIN); //if dualzstepper, both point to same direction. - - //setup new step - WRITE(Y_DIR_PIN,(INVERT_Y_DIR)^direction); - - //perform step - STEP_NC_HI(Y_AXIS); + //get old pin state back. + WRITE_NC(X_DIR_PIN, old_x_dir_pin); + } + break; + + case Y_AXIS: + { + enable_y(); + uint8_t old_y_dir_pin = READ(Y_DIR_PIN); //if dualzstepper, both point to same direction. + uint8_t new_y_dir_pin = (INVERT_Y_DIR)^direction; + + //setup new step + if (new_y_dir_pin != old_y_dir_pin) { + WRITE_NC(Y_DIR_PIN, new_y_dir_pin); + delayMicroseconds(STEPPER_SET_DIR_DELAY); + } + + //perform step + STEP_NC_HI(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - STEP_NC_HI(Y_DUP_AXIS); -#endif //DEBUG_YSTEP_DUP_PIN - delayMicroseconds(1); - STEP_NC_LO(Y_AXIS); + STEP_NC_HI(Y_DUP_AXIS); +#endif +#ifndef TMC2130_DEDGE_STEPPING + delayMicroseconds(STEPPER_MINIMUM_PULSE); + STEP_NC_LO(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN - STEP_NC_LO(Y_DUP_AXIS); -#endif //DEBUG_YSTEP_DUP_PIN + STEP_NC_LO(Y_DUP_AXIS); +#endif +#endif - //get old pin state back. - WRITE(Y_DIR_PIN,old_y_dir_pin); + //get old pin state back. + WRITE_NC(Y_DIR_PIN, old_y_dir_pin); + } + break; - } - break; - - case Z_AXIS: - { - enable_z(); - uint8_t old_z_dir_pin= READ(Z_DIR_PIN); //if dualzstepper, both point to same direction. - //setup new step - WRITE(Z_DIR_PIN,(INVERT_Z_DIR)^direction^BABYSTEP_INVERT_Z); - #ifdef Z_DUAL_STEPPER_DRIVERS - WRITE(Z2_DIR_PIN,(INVERT_Z_DIR)^direction^BABYSTEP_INVERT_Z); - #endif - //perform step - STEP_NC_HI(Z_AXIS); - #ifdef Z_DUAL_STEPPER_DRIVERS - STEP_NC_HI(Z2_AXIS); - #endif - delayMicroseconds(1); - STEP_NC_LO(Z_AXIS); - #ifdef Z_DUAL_STEPPER_DRIVERS - STEP_NC_LO(Z2_AXIS); - #endif + case Z_AXIS: + { + enable_z(); + uint8_t old_z_dir_pin = READ(Z_DIR_PIN); //if dualzstepper, both point to same direction. + uint8_t new_z_dir_pin = (INVERT_Z_DIR)^direction^BABYSTEP_INVERT_Z; - //get old pin state back. - WRITE(Z_DIR_PIN,old_z_dir_pin); - #ifdef Z_DUAL_STEPPER_DRIVERS - WRITE(Z2_DIR_PIN,old_z_dir_pin); - #endif + //setup new step + if (new_z_dir_pin != old_z_dir_pin) { + WRITE_NC(Z_DIR_PIN, new_z_dir_pin); +#ifdef Z_DUAL_STEPPER_DRIVERS + WRITE_NC(Z2_DIR_PIN, new_z_dir_pin); +#endif + delayMicroseconds(STEPPER_SET_DIR_DELAY); + } - } - break; - - default: break; - } + //perform step + STEP_NC_HI(Z_AXIS); +#ifdef Z_DUAL_STEPPER_DRIVERS + STEP_NC_HI(Z2_AXIS); +#endif +#ifndef TMC2130_DEDGE_STEPPING + delayMicroseconds(STEPPER_MINIMUM_PULSE); + STEP_NC_LO(Z_AXIS); +#ifdef Z_DUAL_STEPPER_DRIVERS + STEP_NC_LO(Z2_AXIS); +#endif +#endif + + //get old pin state back. + if (new_z_dir_pin != old_z_dir_pin) { + WRITE_NC(Z_DIR_PIN, old_z_dir_pin); +#ifdef Z_DUAL_STEPPER_DRIVERS + WRITE_NC(Z2_DIR_PIN, old_z_dir_pin); +#endif + } + } + break; + + default: break; + } } #endif //BABYSTEPPING From 502bc8c72ddcb92828a4016546439674b2a74d5d Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 20 Aug 2020 12:33:52 +0200 Subject: [PATCH 08/58] Isolate more pat9125 code Remove probing from Marlin_main and move it into pat9125_probe so that it can support the various variants. --- Firmware/Marlin_main.cpp | 15 ++++----------- Firmware/config.h | 4 +++- Firmware/pat9125.c | 39 +++++++++++++++++++++++++++++---------- Firmware/pat9125.h | 1 + 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 2a261db2a..e3be3dfbd 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -88,18 +88,13 @@ #include "la10compat.h" #endif -#ifdef SWSPI -#include "swspi.h" -#endif //SWSPI - #include "spi.h" -#ifdef SWI2C -#include "swi2c.h" -#endif //SWI2C - #ifdef FILAMENT_SENSOR #include "fsensor.h" +#ifdef IR_SENSOR +#include "pat9125.h" // for pat9125_probe +#endif #endif //FILAMENT_SENSOR #ifdef TMC2130 @@ -864,9 +859,7 @@ static void check_if_fw_is_on_right_printer(){ #ifdef FILAMENT_SENSOR if((PRINTER_TYPE == PRINTER_MK3) || (PRINTER_TYPE == PRINTER_MK3S)){ #ifdef IR_SENSOR - swi2c_init(); - const uint8_t pat9125_detected = swi2c_readByte_A8(PAT9125_I2C_ADDR,0x00,NULL); - if (pat9125_detected){ + if (pat9125_probe()){ lcd_show_fullscreen_message_and_wait_P(_i("MK3S firmware detected on MK3 printer"));}////c=20 r=3 #endif //IR_SENSOR diff --git a/Firmware/config.h b/Firmware/config.h index 1a0a97008..b7705584a 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -23,7 +23,6 @@ #define ADC_CALLBACK adc_ready //callback function () //SWI2C configuration -#define SWI2C //#define SWI2C_SDA 20 //SDA on P3 //#define SWI2C_SCL 21 //SCL on P3 #define SWI2C_A8 @@ -31,7 +30,10 @@ #define SWI2C_TMO 2048 //2048 cycles timeout //PAT9125 configuration +//#define PAT9125_SWSPI #define PAT9125_SWI2C +//#define PAT9125_I2C + #define PAT9125_I2C_ADDR 0x75 //ID=LO //#define PAT9125_I2C_ADDR 0x79 //ID=HI //#define PAT9125_I2C_ADDR 0x73 //ID=NC diff --git a/Firmware/pat9125.c b/Firmware/pat9125.c index de4693d29..10b06b3ea 100644 --- a/Firmware/pat9125.c +++ b/Firmware/pat9125.c @@ -26,12 +26,15 @@ #define PAT9125_BANK_SELECTION 0x7f -#ifdef PAT9125_SWSPI +#if defined(PAT9125_SWSPI) #include "swspi.h" -#endif //PAT9125_SWSPI -#ifdef PAT9125_SWI2C +#elif defined(PAT9125_SWI2C) #include "swi2c.h" -#endif //PAT9125_SWI2C +#elif defined(PAT9125_I2C) +#error not implemented +#else +#error unknown PAT9125 communication method +#endif uint8_t pat9125_PID1 = 0; @@ -103,14 +106,30 @@ extern FILE _uartout; #define uartout (&_uartout) +uint8_t pat9125_probe() +{ +#if defined(PAT9125_SWSPI) + swspi_init(); + //#error not implemented +#elif defined(PAT9125_SWI2C) + swi2c_init(); + return swi2c_readByte_A8(PAT9125_I2C_ADDR,0x00,NULL); +#elif defined(PAT9125_I2C) + twi_init(); + #ifdef IR_SENSOR + // NOTE: this is called from the MK3S variant, so it should be kept minimal + #error not implemented + #else + return pat9125_rd_reg(PAT9125_PID1) != 0; + #endif +#endif +} + uint8_t pat9125_init(void) { -#ifdef PAT9125_SWSPI - swspi_init(); -#endif //PAT9125_SWSPI -#ifdef PAT9125_SWI2C - swi2c_init(); -#endif //PAT9125_SWI2C + if (!pat9125_probe()) + return 0; + // Verify that the sensor responds with its correct product ID. pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1); pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2); diff --git a/Firmware/pat9125.h b/Firmware/pat9125.h index 12f7fe949..1fb2539f4 100755 --- a/Firmware/pat9125.h +++ b/Firmware/pat9125.h @@ -18,6 +18,7 @@ extern int16_t pat9125_y; extern uint8_t pat9125_b; extern uint8_t pat9125_s; +extern uint8_t pat9125_probe(void); // Return non-zero if PAT9125 can be trivially detected extern uint8_t pat9125_init(void); extern uint8_t pat9125_update(void); // update all sensor data extern uint8_t pat9125_update_y(void); // update _y only From 240dc1132ee90fe3680e787dcde665306cc3bcf2 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 20 Aug 2020 12:36:01 +0200 Subject: [PATCH 09/58] Include initial implementation based on Arduino's twi --- Firmware/config.h | 4 +- Firmware/pat9125.c | 47 ++-- Firmware/twi.c | 561 +++++++++++++++++++++++++++++++++++++++++++++ Firmware/twi.h | 55 +++++ 4 files changed, 646 insertions(+), 21 deletions(-) create mode 100644 Firmware/twi.c create mode 100644 Firmware/twi.h diff --git a/Firmware/config.h b/Firmware/config.h index b7705584a..b107d0ec5 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -31,8 +31,8 @@ //PAT9125 configuration //#define PAT9125_SWSPI -#define PAT9125_SWI2C -//#define PAT9125_I2C +//#define PAT9125_SWI2C +#define PAT9125_I2C #define PAT9125_I2C_ADDR 0x75 //ID=LO //#define PAT9125_I2C_ADDR 0x79 //ID=HI diff --git a/Firmware/pat9125.c b/Firmware/pat9125.c index 10b06b3ea..bf2c0d958 100644 --- a/Firmware/pat9125.c +++ b/Firmware/pat9125.c @@ -31,7 +31,7 @@ #elif defined(PAT9125_SWI2C) #include "swi2c.h" #elif defined(PAT9125_I2C) -#error not implemented +#include "twi.h" #else #error unknown PAT9125 communication method #endif @@ -253,39 +253,48 @@ uint8_t pat9125_update_bs(void) uint8_t pat9125_rd_reg(uint8_t addr) { uint8_t data = 0; -#ifdef PAT9125_SWSPI +#if defined(PAT9125_SWSPI) swspi_start(); swspi_tx(addr & 0x7f); data = swspi_rx(); swspi_stop(); -#endif //PAT9125_SWSPI -#ifdef PAT9125_SWI2C +#elif defined(PAT9125_SWI2C) if (!swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error - { - pat9125_PID1 = 0xff; - pat9125_PID2 = 0xff; - return 0; - } -#endif //PAT9125_SWI2C + goto error; +#elif defined(PAT9125_I2C) + if (twi_writeTo(PAT9125_I2C_ADDR,&addr,1,1,0) != 0 || + twi_readFrom(PAT9125_I2C_ADDR,&data,1,1) != 1) + goto error; +#endif return data; + + error: + pat9125_PID1 = 0xff; + pat9125_PID2 = 0xff; + return 0; } void pat9125_wr_reg(uint8_t addr, uint8_t data) { -#ifdef PAT9125_SWSPI +#if defined(PAT9125_SWSPI) swspi_start(); swspi_tx(addr | 0x80); swspi_tx(data); swspi_stop(); -#endif //PAT9125_SWSPI -#ifdef PAT9125_SWI2C +#elif defined(PAT9125_SWI2C) if (!swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error - { - pat9125_PID1 = 0xff; - pat9125_PID2 = 0xff; - return; - } -#endif //PAT9125_SWI2C + goto error; +#elif defined(PAT9125_I2C) + if (twi_writeTo(PAT9125_I2C_ADDR,&addr,1,1,0) != 0 || + twi_writeTo(PAT9125_I2C_ADDR,&data,1,1,1) != 0) + goto error; +#endif + return; + + error: + pat9125_PID1 = 0xff; + pat9125_PID2 = 0xff; + return; } uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data) diff --git a/Firmware/twi.c b/Firmware/twi.c new file mode 100644 index 000000000..171af7303 --- /dev/null +++ b/Firmware/twi.c @@ -0,0 +1,561 @@ +/* + twi.c - TWI/I2C library for Wiring & Arduino + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +#include +#include +#include +#include +#include +#include +#include "Arduino.h" // for digitalWrite + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif + +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#include "pins_arduino.h" +#include "twi.h" + +static volatile uint8_t twi_state; +static volatile uint8_t twi_slarw; +static volatile uint8_t twi_sendStop; // should the transaction end with a stop +static volatile uint8_t twi_inRepStart; // in the middle of a repeated start + +static void (*twi_onSlaveTransmit)(void); +static void (*twi_onSlaveReceive)(uint8_t*, int); + +static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_masterBufferIndex; +static volatile uint8_t twi_masterBufferLength; + +static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_txBufferIndex; +static volatile uint8_t twi_txBufferLength; + +static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_rxBufferIndex; + +static volatile uint8_t twi_error; + +/* + * Function twi_init + * Desc readys twi pins and sets twi bitrate + * Input none + * Output none + */ +void twi_init(void) +{ + // initialize state + twi_state = TWI_READY; + twi_sendStop = true; // default value + twi_inRepStart = false; + + // activate internal pullups for twi. + digitalWrite(SDA, 1); + digitalWrite(SCL, 1); + + // initialize twi prescaler and bit rate + cbi(TWSR, TWPS0); + cbi(TWSR, TWPS1); + TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ + + // enable twi module, acks, and twi interrupt + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); +} + +/* + * Function twi_disable + * Desc disables twi pins + * Input none + * Output none + */ +void twi_disable(void) +{ + // disable twi module, acks, and twi interrupt + TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA)); + + // deactivate internal pullups for twi. + digitalWrite(SDA, 0); + digitalWrite(SCL, 0); +} + +/* + * Function twi_slaveInit + * Desc sets slave address and enables interrupt + * Input none + * Output none + */ +void twi_setAddress(uint8_t address) +{ + // set twi slave address (skip over TWGCE bit) + TWAR = address << 1; +} + +/* + * Function twi_setClock + * Desc sets twi bit rate + * Input Clock Frequency + * Output none + */ +void twi_setFrequency(uint32_t frequency) +{ + TWBR = ((F_CPU / frequency) - 16) / 2; + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ +} + +/* + * Function twi_readFrom + * Desc attempts to become twi bus master and read a + * series of bytes from a device on the bus + * Input address: 7bit i2c device address + * data: pointer to byte array + * length: number of bytes to read into array + * sendStop: Boolean indicating whether to send a stop at the end + * Output number of bytes read + */ +uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) +{ + uint8_t i; + + // ensure data will fit into buffer + if(TWI_BUFFER_LENGTH < length){ + return 0; + } + + // wait until twi is ready, become master receiver + while(TWI_READY != twi_state){ + continue; + } + twi_state = TWI_MRX; + twi_sendStop = sendStop; + // reset error state (0xFF.. no error occured) + twi_error = 0xFF; + + // initialize buffer iteration vars + twi_masterBufferIndex = 0; + twi_masterBufferLength = length-1; // This is not intuitive, read on... + // On receive, the previously configured ACK/NACK setting is transmitted in + // response to the received byte before the interrupt is signalled. + // Therefor we must actually set NACK when the _next_ to last byte is + // received, causing that NACK to be sent in response to receiving the last + // expected byte of data. + + // build sla+w, slave device address + w bit + twi_slarw = TW_READ; + twi_slarw |= address << 1; + + if (true == twi_inRepStart) { + // if we're in the repeated start state, then we've already sent the start, + // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. + // We need to remove ourselves from the repeated start state before we enable interrupts, + // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning + // up. Also, don't enable the START interrupt. There may be one pending from the + // repeated start that we sent ourselves, and that would really confuse things. + twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR + do { + TWDR = twi_slarw; + } while(TWCR & _BV(TWWC)); + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START + } + else + // send start condition + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + + // wait for read operation to complete + while(TWI_MRX == twi_state){ + continue; + } + + if (twi_masterBufferIndex < length) + length = twi_masterBufferIndex; + + // copy twi buffer to data + for(i = 0; i < length; ++i){ + data[i] = twi_masterBuffer[i]; + } + + return length; +} + +/* + * Function twi_writeTo + * Desc attempts to become twi bus master and write a + * series of bytes to a device on the bus + * Input address: 7bit i2c device address + * data: pointer to byte array + * length: number of bytes in array + * wait: boolean indicating to wait for write or not + * sendStop: boolean indicating whether or not to send a stop at the end + * Output 0 .. success + * 1 .. length to long for buffer + * 2 .. address send, NACK received + * 3 .. data send, NACK received + * 4 .. other twi error (lost bus arbitration, bus error, ..) + */ +uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) +{ + uint8_t i; + + // ensure data will fit into buffer + if(TWI_BUFFER_LENGTH < length){ + return 1; + } + + // wait until twi is ready, become master transmitter + while(TWI_READY != twi_state){ + continue; + } + twi_state = TWI_MTX; + twi_sendStop = sendStop; + // reset error state (0xFF.. no error occured) + twi_error = 0xFF; + + // initialize buffer iteration vars + twi_masterBufferIndex = 0; + twi_masterBufferLength = length; + + // copy data to twi buffer + for(i = 0; i < length; ++i){ + twi_masterBuffer[i] = data[i]; + } + + // build sla+w, slave device address + w bit + twi_slarw = TW_WRITE; + twi_slarw |= address << 1; + + // if we're in a repeated start, then we've already sent the START + // in the ISR. Don't do it again. + // + if (true == twi_inRepStart) { + // if we're in the repeated start state, then we've already sent the start, + // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. + // We need to remove ourselves from the repeated start state before we enable interrupts, + // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning + // up. Also, don't enable the START interrupt. There may be one pending from the + // repeated start that we sent outselves, and that would really confuse things. + twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR + do { + TWDR = twi_slarw; + } while(TWCR & _BV(TWWC)); + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START + } + else + // send start condition + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs + + // wait for write operation to complete + while(wait && (TWI_MTX == twi_state)){ + continue; + } + + if (twi_error == 0xFF) + return 0; // success + else if (twi_error == TW_MT_SLA_NACK) + return 2; // error: address send, nack received + else if (twi_error == TW_MT_DATA_NACK) + return 3; // error: data send, nack received + else + return 4; // other twi error +} + +/* + * Function twi_transmit + * Desc fills slave tx buffer with data + * must be called in slave tx event callback + * Input data: pointer to byte array + * length: number of bytes in array + * Output 1 length too long for buffer + * 2 not slave transmitter + * 0 ok + */ +uint8_t twi_transmit(const uint8_t* data, uint8_t length) +{ + uint8_t i; + + // ensure data will fit into buffer + if(TWI_BUFFER_LENGTH < (twi_txBufferLength+length)){ + return 1; + } + + // ensure we are currently a slave transmitter + if(TWI_STX != twi_state){ + return 2; + } + + // set length and copy data into tx buffer + for(i = 0; i < length; ++i){ + twi_txBuffer[twi_txBufferLength+i] = data[i]; + } + twi_txBufferLength += length; + + return 0; +} + +/* + * Function twi_attachSlaveRxEvent + * Desc sets function called before a slave read operation + * Input function: callback function to use + * Output none + */ +void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) +{ + twi_onSlaveReceive = function; +} + +/* + * Function twi_attachSlaveTxEvent + * Desc sets function called before a slave write operation + * Input function: callback function to use + * Output none + */ +void twi_attachSlaveTxEvent( void (*function)(void) ) +{ + twi_onSlaveTransmit = function; +} + +/* + * Function twi_reply + * Desc sends byte or readys receive line + * Input ack: byte indicating to ack or to nack + * Output none + */ +void twi_reply(uint8_t ack) +{ + // transmit master read ready signal, with or without ack + if(ack){ + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); + }else{ + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + } +} + +/* + * Function twi_stop + * Desc relinquishes bus master status + * Input none + * Output none + */ +void twi_stop(void) +{ + // send stop condition + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + + // wait for stop condition to be exectued on bus + // TWINT is not set after a stop condition! + while(TWCR & _BV(TWSTO)){ + continue; + } + + // update twi state + twi_state = TWI_READY; +} + +/* + * Function twi_releaseBus + * Desc releases bus control + * Input none + * Output none + */ +void twi_releaseBus(void) +{ + // release bus + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + + // update twi state + twi_state = TWI_READY; +} + +ISR(TWI_vect) +{ + switch(TW_STATUS){ + // All Master + case TW_START: // sent start condition + case TW_REP_START: // sent repeated start condition + // copy device address and r/w bit to output register and ack + TWDR = twi_slarw; + twi_reply(1); + break; + + // Master Transmitter + case TW_MT_SLA_ACK: // slave receiver acked address + case TW_MT_DATA_ACK: // slave receiver acked data + // if there is data to send, send it, otherwise stop + if(twi_masterBufferIndex < twi_masterBufferLength){ + // copy data to output register and ack + TWDR = twi_masterBuffer[twi_masterBufferIndex++]; + twi_reply(1); + }else{ + if (twi_sendStop) + twi_stop(); + else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } + } + break; + case TW_MT_SLA_NACK: // address sent, nack received + twi_error = TW_MT_SLA_NACK; + twi_stop(); + break; + case TW_MT_DATA_NACK: // data sent, nack received + twi_error = TW_MT_DATA_NACK; + twi_stop(); + break; + case TW_MT_ARB_LOST: // lost bus arbitration + twi_error = TW_MT_ARB_LOST; + twi_releaseBus(); + break; + + // Master Receiver + case TW_MR_DATA_ACK: // data received, ack sent + // put byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + case TW_MR_SLA_ACK: // address sent, ack received + // ack if more bytes are expected, otherwise nack + if(twi_masterBufferIndex < twi_masterBufferLength){ + twi_reply(1); + }else{ + twi_reply(0); + } + break; + case TW_MR_DATA_NACK: // data received, nack sent + // put final byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + if (twi_sendStop) + twi_stop(); + else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } + break; + case TW_MR_SLA_NACK: // address sent, nack received + twi_stop(); + break; + // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case + + // Slave Receiver + case TW_SR_SLA_ACK: // addressed, returned ack + case TW_SR_GCALL_ACK: // addressed generally, returned ack + case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack + case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack + // enter slave receiver mode + twi_state = TWI_SRX; + // indicate that rx buffer can be overwritten and ack + twi_rxBufferIndex = 0; + twi_reply(1); + break; + case TW_SR_DATA_ACK: // data received, returned ack + case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack + // if there is still room in the rx buffer + if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ + // put byte in buffer and ack + twi_rxBuffer[twi_rxBufferIndex++] = TWDR; + twi_reply(1); + }else{ + // otherwise nack + twi_reply(0); + } + break; + case TW_SR_STOP: // stop or repeated start condition received + // ack future responses and leave slave receiver state + twi_releaseBus(); + // put a null char after data if there's room + if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ + twi_rxBuffer[twi_rxBufferIndex] = '\0'; + } + // callback to user defined callback + twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); + // since we submit rx buffer to "wire" library, we can reset it + twi_rxBufferIndex = 0; + break; + case TW_SR_DATA_NACK: // data received, returned nack + case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack + // nack back at master + twi_reply(0); + break; + + // Slave Transmitter + case TW_ST_SLA_ACK: // addressed, returned ack + case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack + // enter slave transmitter mode + twi_state = TWI_STX; + // ready the tx buffer index for iteration + twi_txBufferIndex = 0; + // set tx buffer length to be zero, to verify if user changes it + twi_txBufferLength = 0; + // request for txBuffer to be filled and length to be set + // note: user must call twi_transmit(bytes, length) to do this + twi_onSlaveTransmit(); + // if they didn't change buffer & length, initialize it + if(0 == twi_txBufferLength){ + twi_txBufferLength = 1; + twi_txBuffer[0] = 0x00; + } + // transmit first byte from buffer, fall + case TW_ST_DATA_ACK: // byte sent, ack returned + // copy data to output register + TWDR = twi_txBuffer[twi_txBufferIndex++]; + // if there is more to send, ack, otherwise nack + if(twi_txBufferIndex < twi_txBufferLength){ + twi_reply(1); + }else{ + twi_reply(0); + } + break; + case TW_ST_DATA_NACK: // received nack, we are done + case TW_ST_LAST_DATA: // received ack, but we are done already! + // ack future responses + twi_reply(1); + // leave slave receiver state + twi_state = TWI_READY; + break; + + // All + case TW_NO_INFO: // no state information + break; + case TW_BUS_ERROR: // bus error, illegal stop/start + twi_error = TW_BUS_ERROR; + twi_stop(); + break; + } +} + diff --git a/Firmware/twi.h b/Firmware/twi.h new file mode 100644 index 000000000..cb48708c4 --- /dev/null +++ b/Firmware/twi.h @@ -0,0 +1,55 @@ +/* + twi.h - TWI/I2C library for Wiring & Arduino + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef twi_h +#define twi_h + + #include + + //#define ATMEGA8 + + #ifndef TWI_FREQ + #define TWI_FREQ 400000L + #endif + + #ifndef TWI_BUFFER_LENGTH + #define TWI_BUFFER_LENGTH 32 + #endif + + #define TWI_READY 0 + #define TWI_MRX 1 + #define TWI_MTX 2 + #define TWI_SRX 3 + #define TWI_STX 4 + + void twi_init(void); + void twi_disable(void); + void twi_setAddress(uint8_t); + void twi_setFrequency(uint32_t); + uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); + uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); + uint8_t twi_transmit(const uint8_t*, uint8_t); + void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); + void twi_attachSlaveTxEvent( void (*)(void) ); + void twi_reply(uint8_t); + void twi_stop(void); + void twi_releaseBus(void); + +#endif + From 7f425120f09dc33b7bd1b75af4d42cdad5ad1441 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 20 Aug 2020 15:29:57 +0200 Subject: [PATCH 10/58] Strip down the TWI code - Only implement a single syncronous read/write function to read a byte, since that's all we need currently - Implement a compact IR_SENSOR probe for PAT9125 - Saves 242 bytes compared to PAT9125_SWI2C --- Firmware/pat9125.c | 13 +- Firmware/twi.c | 518 +++------------------------------------------ Firmware/twi.h | 64 +++--- 3 files changed, 63 insertions(+), 532 deletions(-) diff --git a/Firmware/pat9125.c b/Firmware/pat9125.c index bf2c0d958..ab6342aaa 100644 --- a/Firmware/pat9125.c +++ b/Firmware/pat9125.c @@ -118,9 +118,10 @@ uint8_t pat9125_probe() twi_init(); #ifdef IR_SENSOR // NOTE: this is called from the MK3S variant, so it should be kept minimal - #error not implemented + uint8_t addr = PAT9125_PID1; + return (twi_rw8(PAT9125_I2C_ADDR,TW_READ,&addr) == 0); #else - return pat9125_rd_reg(PAT9125_PID1) != 0; + return (pat9125_rd_reg(PAT9125_PID1) != 0); #endif #endif } @@ -262,8 +263,8 @@ uint8_t pat9125_rd_reg(uint8_t addr) if (!swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error goto error; #elif defined(PAT9125_I2C) - if (twi_writeTo(PAT9125_I2C_ADDR,&addr,1,1,0) != 0 || - twi_readFrom(PAT9125_I2C_ADDR,&data,1,1) != 1) + if (twi_rw8(PAT9125_I2C_ADDR,TW_WRITE,&addr) || + twi_rw8(PAT9125_I2C_ADDR,TW_READ,&data)) goto error; #endif return data; @@ -285,8 +286,8 @@ void pat9125_wr_reg(uint8_t addr, uint8_t data) if (!swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error goto error; #elif defined(PAT9125_I2C) - if (twi_writeTo(PAT9125_I2C_ADDR,&addr,1,1,0) != 0 || - twi_writeTo(PAT9125_I2C_ADDR,&data,1,1,1) != 0) + if (twi_rw8(PAT9125_I2C_ADDR,TW_WRITE,&addr) || + twi_rw8(PAT9125_I2C_ADDR,TW_READ,&data)) goto error; #endif return; diff --git a/Firmware/twi.c b/Firmware/twi.c index 171af7303..161db52ac 100644 --- a/Firmware/twi.c +++ b/Firmware/twi.c @@ -1,5 +1,5 @@ /* - twi.c - TWI/I2C library for Wiring & Arduino + twi.c - Stripped-down TWI/I2C library Copyright (c) 2006 Nicholas Zambetti. All right reserved. This library is free software; you can redistribute it and/or @@ -20,11 +20,6 @@ */ #include -#include -#include -#include -#include -#include #include "Arduino.h" // for digitalWrite #ifndef cbi @@ -35,43 +30,11 @@ #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif -#include "pins_arduino.h" #include "twi.h" -static volatile uint8_t twi_state; -static volatile uint8_t twi_slarw; -static volatile uint8_t twi_sendStop; // should the transaction end with a stop -static volatile uint8_t twi_inRepStart; // in the middle of a repeated start -static void (*twi_onSlaveTransmit)(void); -static void (*twi_onSlaveReceive)(uint8_t*, int); - -static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_masterBufferIndex; -static volatile uint8_t twi_masterBufferLength; - -static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_txBufferIndex; -static volatile uint8_t twi_txBufferLength; - -static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_rxBufferIndex; - -static volatile uint8_t twi_error; - -/* - * Function twi_init - * Desc readys twi pins and sets twi bitrate - * Input none - * Output none - */ void twi_init(void) { - // initialize state - twi_state = TWI_READY; - twi_sendStop = true; // default value - twi_inRepStart = false; - // activate internal pullups for twi. digitalWrite(SDA, 1); digitalWrite(SCL, 1); @@ -85,477 +48,46 @@ void twi_init(void) SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) note: TWBR should be 10 or higher for master mode It is 72 for a 16mhz Wiring board with 100kHz TWI */ - - // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); } -/* - * Function twi_disable - * Desc disables twi pins - * Input none - * Output none - */ void twi_disable(void) { - // disable twi module, acks, and twi interrupt - TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA)); - // deactivate internal pullups for twi. digitalWrite(SDA, 0); digitalWrite(SCL, 0); } -/* - * Function twi_slaveInit - * Desc sets slave address and enables interrupt - * Input none - * Output none - */ -void twi_setAddress(uint8_t address) +uint8_t twi_waitfor(uint8_t status) { - // set twi slave address (skip over TWGCE bit) - TWAR = address << 1; + while(!(TWCR & _BV(TWINT))); + return (TW_STATUS != status); } -/* - * Function twi_setClock - * Desc sets twi bit rate - * Input Clock Frequency - * Output none - */ -void twi_setFrequency(uint32_t frequency) +uint8_t twi_rw8(uint8_t address, uint8_t mode, uint8_t* data) { - TWBR = ((F_CPU / frequency) - 16) / 2; - - /* twi bit rate formula from atmega128 manual pg 204 - SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) - note: TWBR should be 10 or higher for master mode - It is 72 for a 16mhz Wiring board with 100kHz TWI */ -} + // send start condition + TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA); + if(twi_waitfor(TW_START)) + return 1; -/* - * Function twi_readFrom - * Desc attempts to become twi bus master and read a - * series of bytes from a device on the bus - * Input address: 7bit i2c device address - * data: pointer to byte array - * length: number of bytes to read into array - * sendStop: Boolean indicating whether to send a stop at the end - * Output number of bytes read - */ -uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) -{ - uint8_t i; + // send address + TWDR = mode; + TWDR |= (address << 1); + TWCR = _BV(TWEN) | _BV(TWINT); + if(twi_waitfor(mode == TW_READ? TW_MR_SLA_ACK: TW_MT_SLA_ACK)) + return 2; - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 0; - } + // send or receive data + if(mode == TW_WRITE) + TWDR = *data; + TWCR = _BV(TWEN) | _BV(TWINT); + if(twi_waitfor(mode == TW_READ? TW_MR_DATA_NACK: TW_MT_DATA_ACK)) + return 3; + if(mode == TW_READ) + *data = TWDR; - // wait until twi is ready, become master receiver - while(TWI_READY != twi_state){ - continue; - } - twi_state = TWI_MRX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; + // send stop + TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTO); - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length-1; // This is not intuitive, read on... - // On receive, the previously configured ACK/NACK setting is transmitted in - // response to the received byte before the interrupt is signalled. - // Therefor we must actually set NACK when the _next_ to last byte is - // received, causing that NACK to be sent in response to receiving the last - // expected byte of data. - - // build sla+w, slave device address + w bit - twi_slarw = TW_READ; - twi_slarw |= address << 1; - - if (true == twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. - // We need to remove ourselves from the repeated start state before we enable interrupts, - // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning - // up. Also, don't enable the START interrupt. There may be one pending from the - // repeated start that we sent ourselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - do { - TWDR = twi_slarw; - } while(TWCR & _BV(TWWC)); - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else - // send start condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); - - // wait for read operation to complete - while(TWI_MRX == twi_state){ - continue; - } - - if (twi_masterBufferIndex < length) - length = twi_masterBufferIndex; - - // copy twi buffer to data - for(i = 0; i < length; ++i){ - data[i] = twi_masterBuffer[i]; - } - - return length; -} - -/* - * Function twi_writeTo - * Desc attempts to become twi bus master and write a - * series of bytes to a device on the bus - * Input address: 7bit i2c device address - * data: pointer to byte array - * length: number of bytes in array - * wait: boolean indicating to wait for write or not - * sendStop: boolean indicating whether or not to send a stop at the end - * Output 0 .. success - * 1 .. length to long for buffer - * 2 .. address send, NACK received - * 3 .. data send, NACK received - * 4 .. other twi error (lost bus arbitration, bus error, ..) - */ -uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 1; - } - - // wait until twi is ready, become master transmitter - while(TWI_READY != twi_state){ - continue; - } - twi_state = TWI_MTX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; - - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length; - - // copy data to twi buffer - for(i = 0; i < length; ++i){ - twi_masterBuffer[i] = data[i]; - } - - // build sla+w, slave device address + w bit - twi_slarw = TW_WRITE; - twi_slarw |= address << 1; - - // if we're in a repeated start, then we've already sent the START - // in the ISR. Don't do it again. - // - if (true == twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. - // We need to remove ourselves from the repeated start state before we enable interrupts, - // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning - // up. Also, don't enable the START interrupt. There may be one pending from the - // repeated start that we sent outselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - do { - TWDR = twi_slarw; - } while(TWCR & _BV(TWWC)); - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else - // send start condition - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs - - // wait for write operation to complete - while(wait && (TWI_MTX == twi_state)){ - continue; - } - - if (twi_error == 0xFF) - return 0; // success - else if (twi_error == TW_MT_SLA_NACK) - return 2; // error: address send, nack received - else if (twi_error == TW_MT_DATA_NACK) - return 3; // error: data send, nack received - else - return 4; // other twi error -} - -/* - * Function twi_transmit - * Desc fills slave tx buffer with data - * must be called in slave tx event callback - * Input data: pointer to byte array - * length: number of bytes in array - * Output 1 length too long for buffer - * 2 not slave transmitter - * 0 ok - */ -uint8_t twi_transmit(const uint8_t* data, uint8_t length) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < (twi_txBufferLength+length)){ - return 1; - } - - // ensure we are currently a slave transmitter - if(TWI_STX != twi_state){ - return 2; - } - - // set length and copy data into tx buffer - for(i = 0; i < length; ++i){ - twi_txBuffer[twi_txBufferLength+i] = data[i]; - } - twi_txBufferLength += length; - return 0; } - -/* - * Function twi_attachSlaveRxEvent - * Desc sets function called before a slave read operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) -{ - twi_onSlaveReceive = function; -} - -/* - * Function twi_attachSlaveTxEvent - * Desc sets function called before a slave write operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveTxEvent( void (*function)(void) ) -{ - twi_onSlaveTransmit = function; -} - -/* - * Function twi_reply - * Desc sends byte or readys receive line - * Input ack: byte indicating to ack or to nack - * Output none - */ -void twi_reply(uint8_t ack) -{ - // transmit master read ready signal, with or without ack - if(ack){ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); - }else{ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); - } -} - -/* - * Function twi_stop - * Desc relinquishes bus master status - * Input none - * Output none - */ -void twi_stop(void) -{ - // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); - - // wait for stop condition to be exectued on bus - // TWINT is not set after a stop condition! - while(TWCR & _BV(TWSTO)){ - continue; - } - - // update twi state - twi_state = TWI_READY; -} - -/* - * Function twi_releaseBus - * Desc releases bus control - * Input none - * Output none - */ -void twi_releaseBus(void) -{ - // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); - - // update twi state - twi_state = TWI_READY; -} - -ISR(TWI_vect) -{ - switch(TW_STATUS){ - // All Master - case TW_START: // sent start condition - case TW_REP_START: // sent repeated start condition - // copy device address and r/w bit to output register and ack - TWDR = twi_slarw; - twi_reply(1); - break; - - // Master Transmitter - case TW_MT_SLA_ACK: // slave receiver acked address - case TW_MT_DATA_ACK: // slave receiver acked data - // if there is data to send, send it, otherwise stop - if(twi_masterBufferIndex < twi_masterBufferLength){ - // copy data to output register and ack - TWDR = twi_masterBuffer[twi_masterBufferIndex++]; - twi_reply(1); - }else{ - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } - } - break; - case TW_MT_SLA_NACK: // address sent, nack received - twi_error = TW_MT_SLA_NACK; - twi_stop(); - break; - case TW_MT_DATA_NACK: // data sent, nack received - twi_error = TW_MT_DATA_NACK; - twi_stop(); - break; - case TW_MT_ARB_LOST: // lost bus arbitration - twi_error = TW_MT_ARB_LOST; - twi_releaseBus(); - break; - - // Master Receiver - case TW_MR_DATA_ACK: // data received, ack sent - // put byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - case TW_MR_SLA_ACK: // address sent, ack received - // ack if more bytes are expected, otherwise nack - if(twi_masterBufferIndex < twi_masterBufferLength){ - twi_reply(1); - }else{ - twi_reply(0); - } - break; - case TW_MR_DATA_NACK: // data received, nack sent - // put final byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } - break; - case TW_MR_SLA_NACK: // address sent, nack received - twi_stop(); - break; - // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case - - // Slave Receiver - case TW_SR_SLA_ACK: // addressed, returned ack - case TW_SR_GCALL_ACK: // addressed generally, returned ack - case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack - case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack - // enter slave receiver mode - twi_state = TWI_SRX; - // indicate that rx buffer can be overwritten and ack - twi_rxBufferIndex = 0; - twi_reply(1); - break; - case TW_SR_DATA_ACK: // data received, returned ack - case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack - // if there is still room in the rx buffer - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ - // put byte in buffer and ack - twi_rxBuffer[twi_rxBufferIndex++] = TWDR; - twi_reply(1); - }else{ - // otherwise nack - twi_reply(0); - } - break; - case TW_SR_STOP: // stop or repeated start condition received - // ack future responses and leave slave receiver state - twi_releaseBus(); - // put a null char after data if there's room - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ - twi_rxBuffer[twi_rxBufferIndex] = '\0'; - } - // callback to user defined callback - twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); - // since we submit rx buffer to "wire" library, we can reset it - twi_rxBufferIndex = 0; - break; - case TW_SR_DATA_NACK: // data received, returned nack - case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack - // nack back at master - twi_reply(0); - break; - - // Slave Transmitter - case TW_ST_SLA_ACK: // addressed, returned ack - case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack - // enter slave transmitter mode - twi_state = TWI_STX; - // ready the tx buffer index for iteration - twi_txBufferIndex = 0; - // set tx buffer length to be zero, to verify if user changes it - twi_txBufferLength = 0; - // request for txBuffer to be filled and length to be set - // note: user must call twi_transmit(bytes, length) to do this - twi_onSlaveTransmit(); - // if they didn't change buffer & length, initialize it - if(0 == twi_txBufferLength){ - twi_txBufferLength = 1; - twi_txBuffer[0] = 0x00; - } - // transmit first byte from buffer, fall - case TW_ST_DATA_ACK: // byte sent, ack returned - // copy data to output register - TWDR = twi_txBuffer[twi_txBufferIndex++]; - // if there is more to send, ack, otherwise nack - if(twi_txBufferIndex < twi_txBufferLength){ - twi_reply(1); - }else{ - twi_reply(0); - } - break; - case TW_ST_DATA_NACK: // received nack, we are done - case TW_ST_LAST_DATA: // received ack, but we are done already! - // ack future responses - twi_reply(1); - // leave slave receiver state - twi_state = TWI_READY; - break; - - // All - case TW_NO_INFO: // no state information - break; - case TW_BUS_ERROR: // bus error, illegal stop/start - twi_error = TW_BUS_ERROR; - twi_stop(); - break; - } -} - diff --git a/Firmware/twi.h b/Firmware/twi.h index cb48708c4..abcb8e975 100644 --- a/Firmware/twi.h +++ b/Firmware/twi.h @@ -1,5 +1,5 @@ /* - twi.h - TWI/I2C library for Wiring & Arduino + twi.h - Stripped-down TWI/I2C library Copyright (c) 2006 Nicholas Zambetti. All right reserved. This library is free software; you can redistribute it and/or @@ -17,39 +17,37 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef twi_h -#define twi_h +#pragma once - #include - - //#define ATMEGA8 - - #ifndef TWI_FREQ - #define TWI_FREQ 400000L - #endif - - #ifndef TWI_BUFFER_LENGTH - #define TWI_BUFFER_LENGTH 32 - #endif - - #define TWI_READY 0 - #define TWI_MRX 1 - #define TWI_MTX 2 - #define TWI_SRX 3 - #define TWI_STX 4 - - void twi_init(void); - void twi_disable(void); - void twi_setAddress(uint8_t); - void twi_setFrequency(uint32_t); - uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); - uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); - uint8_t twi_transmit(const uint8_t*, uint8_t); - void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); - void twi_attachSlaveTxEvent( void (*)(void) ); - void twi_reply(uint8_t); - void twi_stop(void); - void twi_releaseBus(void); +#include +#include +#ifndef TWI_FREQ +#define TWI_FREQ 400000L #endif +/* + * Function twi_init + * Desc readys twi pins and sets twi bitrate + * Input none + * Output none + */ +void twi_init(void); + +/* + * Function twi_disable + * Desc disables twi pins + * Input none + * Output none + */ +void twi_disable(void); + +/* + * Function twi_rw8 + * Desc read/write a single byte from a device + * Input address: 7bit i2c device address + * mode: TW_READ or TW_WRITE + * data: pointer to byte + * Output 0 on success + */ +uint8_t twi_rw8(uint8_t address, uint8_t mode, uint8_t* data); From 30e7b777e03054417f23d161b9a30df3b96e89ee Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Thu, 20 Aug 2020 22:13:13 +0200 Subject: [PATCH 11/58] Error-out with PAT9125_SWSPI (not fully implemented) .. and likely will never was/be. --- Firmware/pat9125.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/pat9125.c b/Firmware/pat9125.c index ab6342aaa..f47d676bb 100644 --- a/Firmware/pat9125.c +++ b/Firmware/pat9125.c @@ -110,7 +110,7 @@ uint8_t pat9125_probe() { #if defined(PAT9125_SWSPI) swspi_init(); - //#error not implemented + #error not implemented #elif defined(PAT9125_SWI2C) swi2c_init(); return swi2c_readByte_A8(PAT9125_I2C_ADDR,0x00,NULL); From d8a88379385504241747aca0877076049992e3dc Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 25 Aug 2020 11:31:35 +0200 Subject: [PATCH 12/58] Document the 3 possible modes --- Firmware/config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/config.h b/Firmware/config.h index b107d0ec5..c64bd441e 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -30,9 +30,9 @@ #define SWI2C_TMO 2048 //2048 cycles timeout //PAT9125 configuration -//#define PAT9125_SWSPI -//#define PAT9125_SWI2C -#define PAT9125_I2C +//#define PAT9125_SWSPI // software SPI mode (incomplete) +//#define PAT9125_SWI2C // software I2C mode +#define PAT9125_I2C // hardware I2C mode #define PAT9125_I2C_ADDR 0x75 //ID=LO //#define PAT9125_I2C_ADDR 0x79 //ID=HI From e37cdab38fd0a8df2bcad4eca3e410e7b9de148f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 25 Aug 2020 11:58:48 +0200 Subject: [PATCH 13/58] PAT9125_I2C: accept either NACK or ACK in receive Both would be technically correct. --- Firmware/twi.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Firmware/twi.c b/Firmware/twi.c index 161db52ac..11c708aa7 100644 --- a/Firmware/twi.c +++ b/Firmware/twi.c @@ -57,34 +57,52 @@ void twi_disable(void) digitalWrite(SCL, 0); } -uint8_t twi_waitfor(uint8_t status) +static void twi_wait() { while(!(TWCR & _BV(TWINT))); - return (TW_STATUS != status); } uint8_t twi_rw8(uint8_t address, uint8_t mode, uint8_t* data) { // send start condition TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA); - if(twi_waitfor(TW_START)) + twi_wait(); + if(TW_STATUS != TW_START) return 1; // send address TWDR = mode; TWDR |= (address << 1); TWCR = _BV(TWEN) | _BV(TWINT); - if(twi_waitfor(mode == TW_READ? TW_MR_SLA_ACK: TW_MT_SLA_ACK)) - return 2; + twi_wait(); - // send or receive data if(mode == TW_WRITE) + { + if(TW_STATUS != TW_MT_SLA_ACK) + return 2; + + // send data TWDR = *data; - TWCR = _BV(TWEN) | _BV(TWINT); - if(twi_waitfor(mode == TW_READ? TW_MR_DATA_NACK: TW_MT_DATA_ACK)) - return 3; - if(mode == TW_READ) + TWCR = _BV(TWEN) | _BV(TWINT); + twi_wait(); + if(TW_STATUS != TW_MT_DATA_ACK) + return 3; + } + else + { + if(TW_STATUS != TW_MR_SLA_ACK) + return 2; + + // receive data + TWCR = _BV(TWEN) | _BV(TWINT); + twi_wait(); + + // accept ACK or NACK (since only 1 byte is read) + if(!(TW_STATUS & TW_MR_DATA_ACK)) + return 3; + *data = TWDR; + } // send stop TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTO); From 6d476d71447e707df2ee5b3c367a650235357f9b Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 27 Sep 2020 14:29:07 +0200 Subject: [PATCH 14/58] Still use SWI2C on RAMBo10a boards The wiring for the PAT9125 on RAMBo10a boards is not directly connected to the SCL pin and requires the sw mode. Detect this requirement by checking the definition for the SWI2C_SCL pin in the board definition. Remove SWI2C_SCL/SDA from the other boards to use the HW mode. --- Firmware/config.h | 5 ++++- Firmware/pins_Einsy_1_0.h | 6 ------ Firmware/pins_Rambo_1_3.h | 3 --- Firmware/swi2c.c | 3 +++ 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Firmware/config.h b/Firmware/config.h index c64bd441e..922a53989 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -31,8 +31,11 @@ //PAT9125 configuration //#define PAT9125_SWSPI // software SPI mode (incomplete) -//#define PAT9125_SWI2C // software I2C mode +#ifdef SWI2C_SCL +#define PAT9125_SWI2C // software I2C mode +#else #define PAT9125_I2C // hardware I2C mode +#endif #define PAT9125_I2C_ADDR 0x75 //ID=LO //#define PAT9125_I2C_ADDR 0x79 //ID=HI diff --git a/Firmware/pins_Einsy_1_0.h b/Firmware/pins_Einsy_1_0.h index 14b562337..21578ebd0 100755 --- a/Firmware/pins_Einsy_1_0.h +++ b/Firmware/pins_Einsy_1_0.h @@ -18,12 +18,6 @@ #define W25X20CL // external 256kB flash #define BOOTAPP // bootloader support - -#define SWI2C_SDA 20 //SDA on P3 -#define SWI2C_SCL 21 //SCL on P3 - - - #define X_TMC2130_CS 41 #define X_TMC2130_DIAG 64 // !!! changed from 40 (EINY03) #define X_STEP_PIN 37 diff --git a/Firmware/pins_Rambo_1_3.h b/Firmware/pins_Rambo_1_3.h index 538fb4f35..522ad28f8 100644 --- a/Firmware/pins_Rambo_1_3.h +++ b/Firmware/pins_Rambo_1_3.h @@ -11,9 +11,6 @@ #define PINDA_THERMISTOR -#define SWI2C_SDA 20 //SDA on P3 -#define SWI2C_SCL 21 //SCL on P3 - #ifdef MICROMETER_LOGGING #define D_DATACLOCK 24 //Y_MAX (green) #define D_DATA 30 //X_MAX (blue) diff --git a/Firmware/swi2c.c b/Firmware/swi2c.c index 49fbc5efc..62a28e1a9 100644 --- a/Firmware/swi2c.c +++ b/Firmware/swi2c.c @@ -7,6 +7,7 @@ #include "pins.h" #include "io_atmega2560.h" +#ifdef SWI2C_SCL #define SWI2C_RMSK 0x01 //read mask (bit0 = 1) #define SWI2C_WMSK 0x00 //write mask (bit0 = 0) @@ -187,3 +188,5 @@ uint8_t swi2c_writeByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyt } #endif //SWI2C_A16 + +#endif //SWI2C_SCL From 384f40956c4292c33ec087e90f9dfa6da5383800 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 27 Sep 2020 16:42:20 +0200 Subject: [PATCH 15/58] Remove obsolete cbi/sbi --- Firmware/twi.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Firmware/twi.c b/Firmware/twi.c index 11c708aa7..f8c077abb 100644 --- a/Firmware/twi.c +++ b/Firmware/twi.c @@ -22,14 +22,6 @@ #include #include "Arduino.h" // for digitalWrite -#ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#endif - -#ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) -#endif - #include "twi.h" @@ -40,8 +32,7 @@ void twi_init(void) digitalWrite(SCL, 1); // initialize twi prescaler and bit rate - cbi(TWSR, TWPS0); - cbi(TWSR, TWPS1); + TWSR &= ~(_BV(TWPS0) | _BV(TWPS1)); TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; /* twi bit rate formula from atmega128 manual pg 204 From c2e8d229a751df2451fd49915c55b4d3ba3f52c7 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 28 Sep 2020 20:21:07 +0200 Subject: [PATCH 16/58] Be more compliant in the I2C protocol - Enter a repeated-start for reading data - Write in the same session --- Firmware/pat9125.c | 6 +-- Firmware/twi.c | 110 +++++++++++++++++++++++++++++---------------- Firmware/twi.h | 20 ++++++--- 3 files changed, 89 insertions(+), 47 deletions(-) diff --git a/Firmware/pat9125.c b/Firmware/pat9125.c index f47d676bb..c6ffecf3c 100644 --- a/Firmware/pat9125.c +++ b/Firmware/pat9125.c @@ -263,8 +263,7 @@ uint8_t pat9125_rd_reg(uint8_t addr) if (!swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error goto error; #elif defined(PAT9125_I2C) - if (twi_rw8(PAT9125_I2C_ADDR,TW_WRITE,&addr) || - twi_rw8(PAT9125_I2C_ADDR,TW_READ,&data)) + if (twi_r8(PAT9125_I2C_ADDR,addr,&data)) goto error; #endif return data; @@ -286,8 +285,7 @@ void pat9125_wr_reg(uint8_t addr, uint8_t data) if (!swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error goto error; #elif defined(PAT9125_I2C) - if (twi_rw8(PAT9125_I2C_ADDR,TW_WRITE,&addr) || - twi_rw8(PAT9125_I2C_ADDR,TW_READ,&data)) + if (twi_w8(PAT9125_I2C_ADDR,addr,data)) goto error; #endif return; diff --git a/Firmware/twi.c b/Firmware/twi.c index f8c077abb..6dd1645c0 100644 --- a/Firmware/twi.c +++ b/Firmware/twi.c @@ -48,55 +48,89 @@ void twi_disable(void) digitalWrite(SCL, 0); } -static void twi_wait() + +static void twi_stop() { - while(!(TWCR & _BV(TWINT))); + TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTO); } -uint8_t twi_rw8(uint8_t address, uint8_t mode, uint8_t* data) + +static uint8_t twi_wait(uint8_t status) +{ + while(!(TWCR & _BV(TWINT))); + if(TW_STATUS != status) + { + twi_stop(); + return 1; + } + return 0; +} + + +static uint8_t twi_start(uint8_t address, uint8_t reg) { // send start condition TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA); - twi_wait(); - if(TW_STATUS != TW_START) + if(twi_wait(TW_START)) return 1; // send address - TWDR = mode; - TWDR |= (address << 1); + TWDR = TW_WRITE | (address << 1); TWCR = _BV(TWEN) | _BV(TWINT); - twi_wait(); + if(twi_wait(TW_MT_SLA_ACK)) + return 2; - if(mode == TW_WRITE) - { - if(TW_STATUS != TW_MT_SLA_ACK) - return 2; - - // send data - TWDR = *data; - TWCR = _BV(TWEN) | _BV(TWINT); - twi_wait(); - if(TW_STATUS != TW_MT_DATA_ACK) - return 3; - } - else - { - if(TW_STATUS != TW_MR_SLA_ACK) - return 2; - - // receive data - TWCR = _BV(TWEN) | _BV(TWINT); - twi_wait(); - - // accept ACK or NACK (since only 1 byte is read) - if(!(TW_STATUS & TW_MR_DATA_ACK)) - return 3; - - *data = TWDR; - } - - // send stop - TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTO); + // send register + TWDR = reg; + TWCR = _BV(TWEN) | _BV(TWINT); + if(twi_wait(TW_MT_DATA_ACK)) + return 3; return 0; } + + +uint8_t twi_r8(uint8_t address, uint8_t reg, uint8_t* data) +{ + if(twi_start(address, reg)) + return 1; + + // repeat start + TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA); + if(twi_wait(TW_REP_START)) + return 2; + + // start receiving + TWDR = TW_READ | (address << 1); + TWCR = _BV(TWEN) | _BV(TWINT); + if(twi_wait(TW_MR_SLA_ACK)) + return 3; + + // receive data + TWCR = _BV(TWEN) | _BV(TWINT); + if(twi_wait(TW_MR_DATA_NACK)) + return 4; + + *data = TWDR; + + // send stop + twi_stop(); + return 0; +} + + +uint8_t twi_w8(uint8_t address, uint8_t reg, uint8_t data) +{ + if(twi_start(address, reg)) + return 1; + + // send data + TWDR = data; + TWCR = _BV(TWEN) | _BV(TWINT); + if(twi_wait(TW_MT_DATA_ACK)) + return 2; + + // send stop + twi_stop(); + return 0; +} diff --git a/Firmware/twi.h b/Firmware/twi.h index abcb8e975..bdb617fcb 100644 --- a/Firmware/twi.h +++ b/Firmware/twi.h @@ -43,11 +43,21 @@ void twi_init(void); void twi_disable(void); /* - * Function twi_rw8 - * Desc read/write a single byte from a device + * Function twi_r8 + * Desc read a single byte from a device * Input address: 7bit i2c device address - * mode: TW_READ or TW_WRITE - * data: pointer to byte + * reg: register address + * data: pointer to byte for result * Output 0 on success */ -uint8_t twi_rw8(uint8_t address, uint8_t mode, uint8_t* data); +uint8_t twi_r8(uint8_t address, uint8_t reg, uint8_t* data); + +/* + * Function twi_w8 + * Desc write a single byte from a device + * Input address: 7bit i2c device address + * reg: register address + * data: byte to write + * Output 0 on success + */ +uint8_t twi_w8(uint8_t address, uint8_t reg, uint8_t data); From df824414eface1c89175eb23e41ca06210bda334 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 28 Sep 2020 21:02:06 +0200 Subject: [PATCH 17/58] Fix probing in IR_SENSOR --- Firmware/pat9125.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/pat9125.c b/Firmware/pat9125.c index c6ffecf3c..58308a9a7 100644 --- a/Firmware/pat9125.c +++ b/Firmware/pat9125.c @@ -118,8 +118,8 @@ uint8_t pat9125_probe() twi_init(); #ifdef IR_SENSOR // NOTE: this is called from the MK3S variant, so it should be kept minimal - uint8_t addr = PAT9125_PID1; - return (twi_rw8(PAT9125_I2C_ADDR,TW_READ,&addr) == 0); + uint8_t data; + return (twi_r8(PAT9125_I2C_ADDR,PAT9125_PID1,&data) == 0); #else return (pat9125_rd_reg(PAT9125_PID1) != 0); #endif From 8a27b6abdb556307070c6f5bf2f76711d0436286 Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Thu, 7 Jan 2021 11:45:40 +0100 Subject: [PATCH 18/58] Move Z up before xy home running xyz calibration to prevent scratches on bed and sheet --- Firmware/Marlin_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index c6f9e4b74..a4123ded8 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -2974,6 +2974,8 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level) //set_destination_to_current(); int l_feedmultiply = setup_for_endstop_move(); lcd_display_message_fullscreen_P(_T(MSG_AUTO_HOME)); + raise_z_above(MESH_HOME_Z_SEARCH); + st_synchronize(); home_xy(); enable_endstops(false); From dea3f23a69f700032b97f765a77d03b71a2d1e27 Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Thu, 14 Jan 2021 11:52:22 +0200 Subject: [PATCH 19/58] PRUSA SN in eeprom --- Firmware/Marlin_main.cpp | 38 ++++++++++++++++++++++++++++++-------- Firmware/eeprom.h | 4 +++- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 3be465912..86b14402c 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -407,6 +407,7 @@ static void gcode_M105(uint8_t extruder); static void temp_compensation_start(); static void temp_compensation_apply(); +static bool get_PRUSA_SN(char* SN); uint16_t gcode_in_progress = 0; uint16_t mcode_in_progress = 0; @@ -1075,6 +1076,21 @@ void setup() if(!(eeprom_read_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED))) eeprom_update_byte((unsigned char *)EEPROM_FAN_CHECK_ENABLED,true); } + + + if (eeprom_read_byte((uint8_t*)EEPROM_PRUSA_SN + 19)) //saved EEPROM SN is not valid. Try to retrieve it. + { + char SN[20]; + if (get_PRUSA_SN(SN)) + { + eeprom_update_block(SN, (uint8_t*)EEPROM_PRUSA_SN, 20); + puts_P(PSTR("SN updated")); + } + else + puts_P(PSTR("SN update failed")); + } + + #ifndef W25X20CL SERIAL_PROTOCOLLNPGM("start"); #else @@ -3386,25 +3402,26 @@ void gcode_M701() * * Typical format of S/N is:CZPX0917X003XC13518 * - * Command operates only in farm mode, if not in farm mode, "Not in farm mode." is written to MYSERIAL. - * * Send command ;S to serial port 0 to retrieve serial number stored in 32U2 processor, - * reply is transmitted to serial port 1 character by character. + * reply is transmitted to the selected serial port. * Operation takes typically 23 ms. If the retransmit is not finished until 100 ms, * it is interrupted, so less, or no characters are retransmitted, only newline character is send * in any case. + * The command will fail if the 32U2 processor is unpowered via USB since it is isolated from the rest of the electronics. + * In that case the value that is stored in the EEPROM should be used instead. + * + * @return 1 on success */ -static void gcode_PRUSA_SN() +static bool get_PRUSA_SN(char* SN) { uint8_t selectedSerialPort_bak = selectedSerialPort; - char SN[20]; selectedSerialPort = 0; SERIAL_ECHOLNRPGM(PSTR(";S")); uint8_t numbersRead = 0; ShortTimer timeout; timeout.start(); - while (numbersRead < (sizeof(SN) - 1)) { + while (numbersRead < 19) { if (MSerial.available() > 0) { SN[numbersRead] = MSerial.read(); numbersRead++; @@ -3413,7 +3430,7 @@ static void gcode_PRUSA_SN() } SN[numbersRead] = 0; selectedSerialPort = selectedSerialPort_bak; - SERIAL_ECHOLN(SN); + return (numbersRead == 19); } //! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors //! at the TACH_1 pin, which causes bad detection of print fan speed. @@ -3950,7 +3967,12 @@ void process_commands() card.openFile(strchr_pointer+4,false); } else if (code_seen("SN")) { // PRUSA SN - gcode_PRUSA_SN(); + char SN[20]; + eeprom_read_block(SN, (uint8_t*)EEPROM_PRUSA_SN, 20); + if (SN[19]) + puts_P(PSTR("SN invalid")); + else + puts(SN); } else if(code_seen("Fir")){ // PRUSA Fir diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 731db1da1..f54bb8ed7 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -316,6 +316,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0D29 3369 | uint8 | EEPROM_PINDA_TEMP_COMPENSATION | ffh 255 | ffh 255 | PINDA temp compensation unknown state | LCD menu | D3 Ax0d29 C1 | ^ | ^ | ^ | 00h 0 | ^ | PINDA has no temp compensation PINDA v1/2 | ^ | ^ | ^ | ^ | ^ | 01h 1 | ^ | PINDA has temp compensation aka SuperPINDA | ^ | ^ +| 0x0D15 3349 | char[20] | EEPROM_PRUSA_SN | SN[19] == 0 | ffffffffffffffff... | PRUSA Serial number string | PRUSA SN | D3 Ax0d15 C20 | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code @@ -521,8 +522,9 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_ALTFAN_OVERRIDE (EEPROM_UVLO_LA_K-1) //uint8 #define EEPROM_EXPERIMENTAL_VISIBILITY (EEPROM_ALTFAN_OVERRIDE-1) //uint8 #define EEPROM_PINDA_TEMP_COMPENSATION (EEPROM_EXPERIMENTAL_VISIBILITY-1) //uint8 +#define EEPROM_PRUSA_SN (EEPROM_PINDA_TEMP_COMPENSATION-20) //char[20] //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_PINDA_TEMP_COMPENSATION +#define EEPROM_LAST_ITEM EEPROM_PRUSA_SN // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! From 20c3f4cb7709692824d7751e150d9df0606b75b3 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Thu, 14 Jan 2021 12:53:12 +0200 Subject: [PATCH 20/58] Update comments --- Firmware/Marlin_main.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 86b14402c..d43e05e58 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1077,8 +1077,9 @@ void setup() eeprom_update_byte((unsigned char *)EEPROM_FAN_CHECK_ENABLED,true); } - - if (eeprom_read_byte((uint8_t*)EEPROM_PRUSA_SN + 19)) //saved EEPROM SN is not valid. Try to retrieve it. + //saved EEPROM SN is not valid. Try to retrieve it. + //SN is valid only if it is NULL terminated. Any other character means either uninitialized or corrupted + if (eeprom_read_byte((uint8_t*)EEPROM_PRUSA_SN + 19)) { char SN[20]; if (get_PRUSA_SN(SN)) @@ -3403,14 +3404,14 @@ void gcode_M701() * Typical format of S/N is:CZPX0917X003XC13518 * * Send command ;S to serial port 0 to retrieve serial number stored in 32U2 processor, - * reply is transmitted to the selected serial port. + * reply is stored in *SN. * Operation takes typically 23 ms. If the retransmit is not finished until 100 ms, - * it is interrupted, so less, or no characters are retransmitted, only newline character is send - * in any case. + * it is interrupted, so less, or no characters are retransmitted, the function returns false * The command will fail if the 32U2 processor is unpowered via USB since it is isolated from the rest of the electronics. * In that case the value that is stored in the EEPROM should be used instead. * * @return 1 on success + * @return 0 on general failure */ static bool get_PRUSA_SN(char* SN) { From 4fed728e083306aa4cddc950a9a1624bf7c61faf Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 26 Jan 2021 15:59:21 +0100 Subject: [PATCH 21/58] Elide delayMicroseconds for TMC2130 in non-DEDGE mode Introduce new macros TMC2130_MINIMUM_DELAY/STEPPER_MINIMUM_DELAY for blocking pauses. If MINIMUM_PULSE has defined to be zero, avoid the delay call entirely. --- Firmware/stepper.cpp | 8 +++++--- Firmware/tmc2130.cpp | 8 ++++---- Firmware/tmc2130.h | 6 ++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index b3cc5a577..e06e0602f 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -75,9 +75,11 @@ uint16_t SP_min = 0x21FF; #ifdef TMC2130 #define STEPPER_MINIMUM_PULSE TMC2130_MINIMUM_PULSE #define STEPPER_SET_DIR_DELAY TMC2130_SET_DIR_DELAY +#define STEPPER_MINIMUM_DELAY TMC2130_MINIMUM_DELAY #else #define STEPPER_MINIMUM_PULSE 2 #define STEPPER_SET_DIR_DELAY 100 +#define STEPPER_MINIMUM_DELAY delayMicroseconds(STEPPER_MINIMUM_PULSE) #endif #ifdef TMC2130_DEDGE_STEPPING @@ -1448,7 +1450,7 @@ void babystep(const uint8_t axis,const bool direction) STEP_NC_HI(X_DUP_AXIS); #endif #ifndef TMC2130_DEDGE_STEPPING - delayMicroseconds(STEPPER_MINIMUM_PULSE); + STEPPER_MINIMUM_DELAY; STEP_NC_LO(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN STEP_NC_LO(X_DUP_AXIS); @@ -1478,7 +1480,7 @@ void babystep(const uint8_t axis,const bool direction) STEP_NC_HI(Y_DUP_AXIS); #endif #ifndef TMC2130_DEDGE_STEPPING - delayMicroseconds(STEPPER_MINIMUM_PULSE); + STEPPER_MINIMUM_DELAY; STEP_NC_LO(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN STEP_NC_LO(Y_DUP_AXIS); @@ -1511,7 +1513,7 @@ void babystep(const uint8_t axis,const bool direction) STEP_NC_HI(Z2_AXIS); #endif #ifndef TMC2130_DEDGE_STEPPING - delayMicroseconds(STEPPER_MINIMUM_PULSE); + STEPPER_MINIMUM_DELAY; STEP_NC_LO(Z_AXIS); #ifdef Z_DUAL_STEPPER_DRIVERS STEP_NC_LO(Z2_AXIS); diff --git a/Firmware/tmc2130.cpp b/Firmware/tmc2130.cpp index 15646b925..41f7b7c12 100755 --- a/Firmware/tmc2130.cpp +++ b/Firmware/tmc2130.cpp @@ -717,10 +717,10 @@ static uint8_t tmc2130_rx(uint8_t axis, uint8_t addr, uint32_t* rval) #define _DO_STEP_Z TOGGLE(Z_STEP_PIN) #define _DO_STEP_E TOGGLE(E0_STEP_PIN) #else -#define _DO_STEP_X { WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); } -#define _DO_STEP_Y { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); } -#define _DO_STEP_Z { WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); } -#define _DO_STEP_E { WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); delayMicroseconds(TMC2130_MINIMUM_PULSE); WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); } +#define _DO_STEP_X { WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); TMC2130_MINIMUM_DELAY; WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); } +#define _DO_STEP_Y { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); TMC2130_MINIMUM_DELAY; WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); } +#define _DO_STEP_Z { WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); TMC2130_MINIMUM_DELAY; WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); } +#define _DO_STEP_E { WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); TMC2130_MINIMUM_DELAY; WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN); } #endif diff --git a/Firmware/tmc2130.h b/Firmware/tmc2130.h index 4b5b764ce..36ba55522 100644 --- a/Firmware/tmc2130.h +++ b/Firmware/tmc2130.h @@ -33,6 +33,12 @@ extern uint8_t tmc2130_sg_homing_axes_mask; #define TMC2130_SET_DIR_DELAY 20 // minimum delay after setting direction in uS #define TMC2130_SET_PWR_DELAY 0 // minimum delay after changing pwr mode in uS +#if TMC2130_MINIMUM_PULSE == 0 +#define TMC2130_MINIMUM_DELAY //NOP +#else +#define TMC2130_MINIMUM_DELAY delayMicroseconds(TMC2130_MINIMUM_PULSE) +#endif + extern uint8_t tmc2130_home_enabled; extern uint8_t tmc2130_home_origin[2]; extern uint8_t tmc2130_home_bsteps[2]; From 2a6989ecd559f70ceb08aa471e0399c52747ddc8 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 26 Jan 2021 16:09:23 +0100 Subject: [PATCH 22/58] Remove TMC2130 special-cases With the new STEPPER_MINIMUM_DELAY being automatically removed for TMC2130 we no longer need to add specialized #ifdefs for DEDGE in babystep. --- Firmware/stepper.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index e06e0602f..e74d7154e 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -1449,12 +1449,10 @@ void babystep(const uint8_t axis,const bool direction) #ifdef DEBUG_XSTEP_DUP_PIN STEP_NC_HI(X_DUP_AXIS); #endif -#ifndef TMC2130_DEDGE_STEPPING STEPPER_MINIMUM_DELAY; STEP_NC_LO(X_AXIS); #ifdef DEBUG_XSTEP_DUP_PIN STEP_NC_LO(X_DUP_AXIS); -#endif #endif //get old pin state back. @@ -1479,12 +1477,10 @@ void babystep(const uint8_t axis,const bool direction) #ifdef DEBUG_YSTEP_DUP_PIN STEP_NC_HI(Y_DUP_AXIS); #endif -#ifndef TMC2130_DEDGE_STEPPING STEPPER_MINIMUM_DELAY; STEP_NC_LO(Y_AXIS); #ifdef DEBUG_YSTEP_DUP_PIN STEP_NC_LO(Y_DUP_AXIS); -#endif #endif //get old pin state back. @@ -1512,12 +1508,10 @@ void babystep(const uint8_t axis,const bool direction) #ifdef Z_DUAL_STEPPER_DRIVERS STEP_NC_HI(Z2_AXIS); #endif -#ifndef TMC2130_DEDGE_STEPPING STEPPER_MINIMUM_DELAY; STEP_NC_LO(Z_AXIS); #ifdef Z_DUAL_STEPPER_DRIVERS STEP_NC_LO(Z2_AXIS); -#endif #endif //get old pin state back. From b17cdcd4d7ebd9e53a4180cf9e6768845d1b1eef Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 26 Jan 2021 16:12:59 +0100 Subject: [PATCH 23/58] Ensure MINIMUM_PULSE is always 0 in DEDGE mode This ensures delays are always properly elided without having to check for DEDGE all over the place. --- Firmware/stepper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index e74d7154e..8684713b4 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -83,6 +83,7 @@ uint16_t SP_min = 0x21FF; #endif #ifdef TMC2130_DEDGE_STEPPING +static_assert(TMC2130_MINIMUM_PULSE == 0, "DEDGE requires/implies TMC2130_MINIMUM_PULSE == 0"); #define STEP_NC_HI(axis) TOGGLE(_STEP_PIN_##axis) #define STEP_NC_LO(axis) //NOP #else From d3734b02cc1fbb8ba9a446d9ac5ef83b91756178 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 26 Jan 2021 16:18:23 +0100 Subject: [PATCH 24/58] Also fix delay instances inside unused BACKLASH_[XY] --- Firmware/stepper.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index 8684713b4..d47dd2dc0 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -352,13 +352,13 @@ FORCE_INLINE void stepper_next_block() WRITE_NC(X_DIR_PIN, INVERT_X_DIR); else WRITE_NC(X_DIR_PIN, !INVERT_X_DIR); - _delay_us(100); + delayMicroseconds(STEPPER_SET_DIR_DELAY); for (uint8_t i = 0; i < st_backlash_x; i++) { STEP_NC_HI(X_AXIS); - _delay_us(100); + STEPPER_MINIMUM_DELAY; STEP_NC_LO(X_AXIS); - _delay_us(900); + _delay_us(900); // hard-coded jerk! *bad* } } last_dir_bits &= ~1; @@ -375,13 +375,13 @@ FORCE_INLINE void stepper_next_block() WRITE_NC(Y_DIR_PIN, INVERT_Y_DIR); else WRITE_NC(Y_DIR_PIN, !INVERT_Y_DIR); - _delay_us(100); + delayMicroseconds(STEPPER_SET_DIR_DELAY); for (uint8_t i = 0; i < st_backlash_y; i++) { STEP_NC_HI(Y_AXIS); - _delay_us(100); + STEPPER_MINIMUM_DELAY; STEP_NC_LO(Y_AXIS); - _delay_us(900); + _delay_us(900); // hard-coded jerk! *bad* } } last_dir_bits &= ~2; From a9625747db85f22cb583d4fdc4c4f0dc2706e687 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Tue, 26 Jan 2021 19:37:14 +0100 Subject: [PATCH 25/58] Reinstate the nop instruction as delay in non-DEDGE When TMC2130_MINIMUM_PULSE is 0 a minimum delay is implied. In this case, use a single "nop" instruction. --- Firmware/stepper.cpp | 3 ++- Firmware/tmc2130.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Firmware/stepper.cpp b/Firmware/stepper.cpp index d47dd2dc0..fc8d9f44d 100644 --- a/Firmware/stepper.cpp +++ b/Firmware/stepper.cpp @@ -83,7 +83,8 @@ uint16_t SP_min = 0x21FF; #endif #ifdef TMC2130_DEDGE_STEPPING -static_assert(TMC2130_MINIMUM_PULSE == 0, "DEDGE requires/implies TMC2130_MINIMUM_PULSE == 0"); +static_assert(TMC2130_MINIMUM_DELAY 1, // this will fail to compile when non-empty + "DEDGE implies/requires an empty TMC2130_MINIMUM_DELAY"); #define STEP_NC_HI(axis) TOGGLE(_STEP_PIN_##axis) #define STEP_NC_LO(axis) //NOP #else diff --git a/Firmware/tmc2130.h b/Firmware/tmc2130.h index 36ba55522..485bf41cc 100644 --- a/Firmware/tmc2130.h +++ b/Firmware/tmc2130.h @@ -33,8 +33,10 @@ extern uint8_t tmc2130_sg_homing_axes_mask; #define TMC2130_SET_DIR_DELAY 20 // minimum delay after setting direction in uS #define TMC2130_SET_PWR_DELAY 0 // minimum delay after changing pwr mode in uS -#if TMC2130_MINIMUM_PULSE == 0 +#ifdef TMC2130_DEDGE_STEPPING #define TMC2130_MINIMUM_DELAY //NOP +#elif TMC2130_MINIMUM_PULSE == 0 +#define TMC2130_MINIMUM_DELAY asm("nop") #else #define TMC2130_MINIMUM_DELAY delayMicroseconds(TMC2130_MINIMUM_PULSE) #endif From fba83bd3091414bda8d0e1b220ab4f229610e436 Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Wed, 27 Jan 2021 12:43:41 +0100 Subject: [PATCH 26/58] Add new flags -c -p -n --- PF-build.sh | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/PF-build.sh b/PF-build.sh index b75395782..5b0979e2a 100755 --- a/PF-build.sh +++ b/PF-build.sh @@ -56,7 +56,7 @@ # Some may argue that this is only used by a script, BUT as soon someone accidentally or on purpose starts Arduino IDE # it will use the default Arduino IDE folders and so can corrupt the build environment. # -# Version: 1.0.6-Build_33 +# Version: 1.0.6-Build_36 # Change log: # 12 Jan 2019, 3d-gussner, Fixed "compiler.c.elf.flags=-w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections" in 'platform.txt' # 16 Jan 2019, 3d-gussner, Build_2, Added development check to modify 'Configuration.h' to prevent unwanted LCD messages that Firmware is unknown @@ -135,6 +135,7 @@ # Update exit numbers 1-13 for prepare build env 21-29 for prepare compiling 30-36 compiling # 08 Jan 2021, 3d-gussner, Comment out 'sudo' auto installation # Add '-?' '-h' help option +# 27 Jan 2021, 3d-gussner, Add `-c`, `-p` and `-n` options #### Start check if OSTYPE is supported OS_FOUND=$( command -v uname) @@ -451,7 +452,7 @@ if type git > /dev/null; then git_available="1" fi -while getopts v:l:d:b:o:?h flag +while getopts v:l:d:b:o:c:p:n:?h flag do case "${flag}" in v) variant_flag=${OPTARG};; @@ -459,6 +460,9 @@ while getopts v:l:d:b:o:?h flag d) devel_flag=${OPTARG};; b) build_flag=${OPTARG};; o) output_flag=${OPTARG};; + c) clean_flag=${OPTARG};; + p) prusa_flag=${OPTARG};; + n) new_build_flag=${OPTARG};; ?) help_flag=1;; h) help_flag=1;; esac @@ -469,6 +473,9 @@ while getopts v:l:d:b:o:?h flag #echo "build_flag: $build_flag"; #echo "output_flag: $output_flag"; #echo "help_flag: $help_flag" +#echo "clean_flag: $clean_flag" +#echo "prusa_flag: $prusa_flag" +#echo "new_build_flag: $new_build_flag" # # '?' 'h' argument usage and help @@ -482,19 +489,23 @@ echo "$(tput setaf 2)-l$(tput sgr0) Languages '$(tput setaf 2)ALL$(tput sgr0)' f echo "$(tput setaf 2)-d$(tput sgr0) Devel build '$(tput setaf 2)GOLD$(tput sgr0)', '$(tput setaf 2)RC$(tput sgr0)', '$(tput setaf 2)BETA$(tput sgr0)', '$(tput setaf 2)ALPHA$(tput sgr0)', '$(tput setaf 2)DEBUG$(tput sgr0)', '$(tput setaf 2)DEVEL$(tput sgr0)' and '$(tput setaf 2)UNKNOWN$(tput sgr0)'" echo "$(tput setaf 2)-b$(tput sgr0) Build/commit number '$(tput setaf 2)Auto$(tput sgr0)' needs git or a number" echo "$(tput setaf 2)-o$(tput sgr0) Output '$(tput setaf 2)1$(tput sgr0)' force or '$(tput setaf 2)0$(tput sgr0)' block output and delays" +echo "$(tput setaf 2)-c$(tput sgr0) Do not clean up lang build'$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes" +echo "$(tput setaf 2)-p$(tput sgr0) Keep Configuration_prusa.h '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes" +echo "$(tput setaf 2)-n$(tput sgr0) New fresh build '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes" echo "$(tput setaf 2)-?$(tput sgr0) Help" echo "$(tput setaf 2)-h$(tput sgr0) Help" echo echo "Brief USAGE:" -echo " $(tput setaf 2)./PF-build.sh$(tput sgr0) [-v] [-l] [-d] [-b] [-o]" +echo " $(tput setaf 2)./PF-build.sh$(tput sgr0) [-v] [-l] [-d] [-b] [-o] [-c] [-p] [-n]" echo echo "Example:" echo " $(tput setaf 2)./PF-build.sh -v All -l ALL -d GOLD$(tput sgr0)" echo " Will build all variants as multi language and final GOLD version" echo -echo " $(tput setaf 2) ./PF-build.sh -v 1_75mm_MK3S-EINSy10a-E3Dv6full.h -b Auto -l ALL -d GOLD -o 1$(tput sgr0)" +echo " $(tput setaf 2) ./PF-build.sh -v 1_75mm_MK3S-EINSy10a-E3Dv6full.h -b Auto -l ALL -d GOLD -o 1 -c 1 -p 1 -n 1$(tput sgr0)" echo " Will build MK3S multi language final GOLD firmware " -echo " with current commit count number and output extra information" +echo " with current commit count number and output extra information," +echo " not delete lang build temporary files, keep Configuration_prusa.h and build with new fresh build folder." echo exit @@ -807,6 +818,12 @@ do if [ $OUTPUT == "1" ] ; then sleep 2 fi + + #New fresh PF-Firmware-build + if [ "$new_build_flag" == "1" ]; then + rm -r -f $BUILD_PATH/* || exit 36 + fi + #$BUILD_ENV_PATH/arduino-builder -dump-prefs -debug-level 10 -compile -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=$BOARD_PACKAGE_NAME:avr:$BOARD -build-path=$BUILD_PATH -warnings=all $SCRIPT_PATH/Firmware/Firmware.ino || exit 14 $BUILD_ENV_PATH/arduino-builder -compile -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=$BOARD_PACKAGE_NAME:avr:$BOARD -build-path=$BUILD_PATH -warnings=all $SCRIPT_PATH/Firmware/Firmware.ino || exit 30 echo "$(tput sgr 0)" @@ -874,17 +891,21 @@ do fi fi # Cleanup after build - echo "$(tput setaf 3)" - ./fw-clean.sh || exit 34 - ./lang-clean.sh || exit 35 - echo "$(tput sgr 0)" + if [[ -z "$clean_flag" || "$clean_flag" == "0" ]]; then + echo "$(tput setaf 3)" + ./fw-clean.sh || exit 34 + ./lang-clean.sh || exit 35 + echo "$(tput sgr 0)" + fi else echo "$(tput setaf 2)Copying English only firmware to PF-build-hex folder$(tput sgr 0)" cp -f $BUILD_PATH/Firmware.ino.hex $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-EN_ONLY.hex || exit 34 fi # Cleanup Firmware - rm $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 36 + if [[ -z "$prusa_flag" || "$prusa_flag" == "0" ]]; then + rm $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 36 + fi if find $SCRIPT_PATH/lang/ -name '*RAMBo10a*.txt' -printf 1 -quit | grep -q 1 then rm $SCRIPT_PATH/lang/*RAMBo10a*.txt @@ -901,6 +922,12 @@ do then rm $SCRIPT_PATH/lang/not_used.txt fi + + #New fresh PF-Firmware-build + if [ "$new_build_flag" == "1" ]; then + rm -r -f $BUILD_PATH/* || exit 36 + fi + # Restore files to previous state sed -i -- "s/^#define FW_DEV_VERSION FW_VERSION_$DEV_STATUS/#define FW_DEV_VERSION FW_VERSION_UNKNOWN/g" $SCRIPT_PATH/Firmware/Configuration.h sed -i -- 's/^#define FW_REPOSITORY "Prusa3d"/#define FW_REPOSITORY "Unknown"/g' $SCRIPT_PATH/Firmware/Configuration.h From e9d5c447322e899b0e7cfdc71146e4911e7a0b5a Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 29 Jan 2021 00:13:49 +0100 Subject: [PATCH 27/58] Also toggle pins efficiently in sm4.c Use the same technique used in fastio to toggle pins efficiently in sm4 when DEDGE is used. --- Firmware/sm4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/sm4.c b/Firmware/sm4.c index b68e02762..c2f128243 100644 --- a/Firmware/sm4.c +++ b/Firmware/sm4.c @@ -130,7 +130,7 @@ 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)) #ifdef TMC2130_DEDGE_STEPPING - PORTC ^= (axes_mask & 0x0f); //set step signals by mask + PINC = (axes_mask & 0x0f); // toggle step signals by mask #else register uint8_t portC = PORTC & 0xf0; PORTC = portC | (axes_mask & 0x0f); //set step signals by mask From 30262b0a6eeecade45186a5d708f0c94d4cff20f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 29 Jan 2021 17:30:04 +0100 Subject: [PATCH 28/58] Remove redundant definitions of CRITICAL_SECTION_* Move CRITICAL_SECTION_START/END into fastio.h, where it's needed. --- Firmware/Marlin.h | 5 ----- Firmware/fastio.h | 7 +++++++ Firmware/tone04.c | 9 --------- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 697f2f72c..f81abd8f7 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -287,11 +287,6 @@ FORCE_INLINE unsigned long millis_nc() { void setPwmFrequency(uint8_t pin, int val); #endif -#ifndef CRITICAL_SECTION_START - #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); - #define CRITICAL_SECTION_END SREG = _sreg; -#endif //CRITICAL_SECTION_START - extern bool fans_check_enabled; extern float homing_feedrate[]; extern uint8_t axis_relative_modes; diff --git a/Firmware/fastio.h b/Firmware/fastio.h index e4f25ed8b..c4fee1019 100644 --- a/Firmware/fastio.h +++ b/Firmware/fastio.h @@ -17,6 +17,13 @@ #define MASK(PIN) (1 << PIN) #endif +#ifndef CRITICAL_SECTION_START + #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); + #define CRITICAL_SECTION_END SREG = _sreg; + #include +#endif //CRITICAL_SECTION_START + + /* magic I/O routines now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0); diff --git a/Firmware/tone04.c b/Firmware/tone04.c index 41f904a91..5c36a5370 100644 --- a/Firmware/tone04.c +++ b/Firmware/tone04.c @@ -7,16 +7,7 @@ #ifdef SYSTEM_TIMER_2 -#include -#include #include "pins.h" - -#ifndef CRITICAL_SECTION_START - #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); - #define CRITICAL_SECTION_END SREG = _sreg; -#endif //CRITICAL_SECTION_START - - #include "fastio.h" void timer4_init(void) From 1fa7b8cd8d0f04b0332dd242283c57caf600d103 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 29 Jan 2021 17:48:59 +0100 Subject: [PATCH 29/58] Move SDA/SCL pins into pins.h for fastio compatibility fastio relies on macros for pin definitions, so we cannot use the const declaration in Sd2PinMap or the arduino's definition. Declare SDA/SCL_PIN into pins.h based on the current MCU, which is identical in all our variants. Remove the conflicting/unused declaration in Sd2PinMap. --- Firmware/Sd2PinMap.h | 6 +----- Firmware/pins.h | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Firmware/Sd2PinMap.h b/Firmware/Sd2PinMap.h index 8a608731e..da50958f0 100644 --- a/Firmware/Sd2PinMap.h +++ b/Firmware/Sd2PinMap.h @@ -37,10 +37,6 @@ struct pin_map_t { || defined(__AVR_ATmega2560__) // Mega -// Two Wire (aka I2C) ports -uint8_t const SDA_PIN = 20; // D1 -uint8_t const SCL_PIN = 21; // D0 - #undef MOSI_PIN #undef MISO_PIN // SPI port @@ -365,4 +361,4 @@ static inline __attribute__((always_inline)) #endif // Sd2PinMap_h -#endif \ No newline at end of file +#endif diff --git a/Firmware/pins.h b/Firmware/pins.h index 5d3b4f832..1c20a001a 100644 --- a/Firmware/pins.h +++ b/Firmware/pins.h @@ -25,6 +25,11 @@ #error Unknown MOTHERBOARD value in configuration.h #endif +#if !defined(SDA_PIN) && (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) +#define SDA_PIN 20 +#define SCL_PIN 21 +#endif + //List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! #define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN, #if EXTRUDERS > 1 From 2d71a071f0d4f63c4dbc2bfa56294c497c5988da Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 29 Jan 2021 17:51:38 +0100 Subject: [PATCH 30/58] Switch twi.c to fastio --- Firmware/twi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Firmware/twi.c b/Firmware/twi.c index 6dd1645c0..e8c9a378e 100644 --- a/Firmware/twi.c +++ b/Firmware/twi.c @@ -19,17 +19,18 @@ Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts */ -#include -#include "Arduino.h" // for digitalWrite +#include +#include "config.h" +#include "fastio.h" #include "twi.h" void twi_init(void) { // activate internal pullups for twi. - digitalWrite(SDA, 1); - digitalWrite(SCL, 1); + WRITE(SDA_PIN, 1); + WRITE(SCL_PIN, 1); // initialize twi prescaler and bit rate TWSR &= ~(_BV(TWPS0) | _BV(TWPS1)); @@ -44,8 +45,8 @@ void twi_init(void) void twi_disable(void) { // deactivate internal pullups for twi. - digitalWrite(SDA, 0); - digitalWrite(SCL, 0); + WRITE(SDA_PIN, 0); + WRITE(SCL_PIN, 0); } From b8b75186fe96a695521402edc1dd015dfc684ffa Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 29 Jan 2021 18:30:16 +0100 Subject: [PATCH 31/58] Remove the extra copy of CRITICAL_SECTION from fastio --- Firmware/fastio.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Firmware/fastio.h b/Firmware/fastio.h index 94a029a62..855c000e2 100644 --- a/Firmware/fastio.h +++ b/Firmware/fastio.h @@ -9,12 +9,6 @@ #include #include "macros.h" -#ifndef CRITICAL_SECTION_START - #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); - #define CRITICAL_SECTION_END SREG = _sreg; - #include -#endif //CRITICAL_SECTION_START - /* magic I/O routines From 6b6205d2f6a0ddf5045886ba89aa53ce55ab635f Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Sun, 31 Jan 2021 15:06:20 +0200 Subject: [PATCH 32/58] M27 refactoring and M27 L initial implementation --- Firmware/Marlin_main.cpp | 2 +- Firmware/cardreader.cpp | 55 ++++++++++++++++++++++------------------ Firmware/cardreader.h | 2 +- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 4739dc4a8..a16718486 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -5818,7 +5818,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) ### M27 - Get SD status M27: Report SD print status */ case 27: - card.getStatus(); + card.getStatus(code_seen('L')); break; /*! diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index e228c5236..2140a09af 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -502,31 +502,38 @@ uint32_t CardReader::getFileSize() return filesize; } -void CardReader::getStatus() +void CardReader::getStatus(bool arg_L) { - if(sdprinting) - { - if (isPrintPaused) { - SERIAL_PROTOCOLLNPGM("SD print paused"); - } - else if (saved_printing) { - SERIAL_PROTOCOLLNPGM("Print saved"); - } - else { - SERIAL_PROTOCOLLN(LONGEST_FILENAME); - SERIAL_PROTOCOLRPGM(_N("SD printing byte "));////MSG_SD_PRINTING_BYTE - SERIAL_PROTOCOL(sdpos); - SERIAL_PROTOCOL('/'); - SERIAL_PROTOCOLLN(filesize); - uint16_t time = ( _millis() - starttime ) / 60000U; - SERIAL_PROTOCOL(itostr2(time/60)); - SERIAL_PROTOCOL(':'); - SERIAL_PROTOCOLLN(itostr2(time%60)); - } - } - else { - SERIAL_PROTOCOLLNPGM("Not SD printing"); - } + if (isPrintPaused) + { + if (saved_printing && (saved_printing_type == PRINTING_TYPE_SD)) + SERIAL_PROTOCOLLNPGM("SD print paused"); + else + SERIAL_PROTOCOLLNPGM("Print saved"); + } + else if (sdprinting) + { + if (arg_L) + { + SERIAL_PROTOCOL('/'); + for (uint8_t i = 0; i < getWorkDirDepth(); i++) + printf_P(PSTR("%s/"), dir_names[i]); + puts(filename); + } + else + SERIAL_PROTOCOLLN(LONGEST_FILENAME); + + SERIAL_PROTOCOLRPGM(_N("SD printing byte "));////MSG_SD_PRINTING_BYTE + SERIAL_PROTOCOL(sdpos); + SERIAL_PROTOCOL('/'); + SERIAL_PROTOCOLLN(filesize); + uint16_t time = ( _millis() - starttime ) / 60000U; + SERIAL_PROTOCOL(itostr2(time/60)); + SERIAL_PROTOCOL(':'); + SERIAL_PROTOCOLLN(itostr2(time%60)); + } + else + SERIAL_PROTOCOLLNPGM("Not SD printing"); } void CardReader::write_command(char *buf) { diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index 25e97882e..40098d3c0 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -26,7 +26,7 @@ public: void release(); void startFileprint(); uint32_t getFileSize(); - void getStatus(); + void getStatus(bool arg_L); void printingHasFinished(); void getfilename(uint16_t nr, const char* const match=NULL); From 698499f00df6bc7797cdf8bca212661cfd79f8da Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Sun, 31 Jan 2021 17:18:32 +0200 Subject: [PATCH 33/58] split timer0 and timer2 initialization. Move timer2 init early --- Firmware/Marlin_main.cpp | 2 ++ Firmware/temperature.cpp | 5 ++++- Firmware/timer02.c | 20 ++++++++++++-------- Firmware/timer02.h | 3 +++ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index d43e05e58..68ecb1c19 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -1013,6 +1013,8 @@ static void w25x20cl_err_msg() // are initialized by the main() routine provided by the Arduino framework. void setup() { + timer2_init(); // enables functional millis + mmu_init(); ultralcd_init(); diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 3b38c25cc..a1281b649 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -1124,7 +1124,10 @@ void tp_init() adc_init(); - timer0_init(); + timer0_init(); //enables the heatbed timer. + + // timer2 already enabled earlier in the code + // now enable the COMPB temperature interrupt OCR2B = 128; TIMSK2 |= (1< #include +#include "macros.h" void timer0_init(void) { - //save sreg - uint8_t _sreg = SREG; - //disable interrupts for sure - cli(); + CRITICAL_SECTION_START; TCNT0 = 0; // Fast PWM duty (0-255). @@ -25,7 +23,14 @@ void timer0_init(void) TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0B1) | (1 << COM0B0); TCCR0B = (1 << CS01); // CLK/8 prescaling TIMSK0 |= (1 << TOIE0); // enable timer overflow interrupt - + + CRITICAL_SECTION_END; +} + +void timer2_init(void) +{ + CRITICAL_SECTION_START; + // Everything, that used to be on timer0 was moved to timer2 (delay, beeping, millis etc.) //setup timer2 TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00 @@ -36,9 +41,8 @@ void timer0_init(void) TIMSK2 &= ~(1< Date: Sun, 31 Jan 2021 16:56:58 +0200 Subject: [PATCH 34/58] Patch broken string PROGMEM transition with setTargetedHotend() error --- Firmware/Marlin_main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 4739dc4a8..1feb69446 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -10026,16 +10026,16 @@ bool setTargetedHotend(int code, uint8_t &extruder) SERIAL_ECHORPGM(_n("M104 Invalid extruder "));////MSG_M104_INVALID_EXTRUDER break; case 105: - SERIAL_ECHO(_n("M105 Invalid extruder "));////MSG_M105_INVALID_EXTRUDER + SERIAL_ECHORPGM(_n("M105 Invalid extruder "));////MSG_M105_INVALID_EXTRUDER break; case 109: - SERIAL_ECHO(_n("M109 Invalid extruder "));////MSG_M109_INVALID_EXTRUDER + SERIAL_ECHORPGM(_n("M109 Invalid extruder "));////MSG_M109_INVALID_EXTRUDER break; case 218: - SERIAL_ECHO(_n("M218 Invalid extruder "));////MSG_M218_INVALID_EXTRUDER + SERIAL_ECHORPGM(_n("M218 Invalid extruder "));////MSG_M218_INVALID_EXTRUDER break; case 221: - SERIAL_ECHO(_n("M221 Invalid extruder "));////MSG_M221_INVALID_EXTRUDER + SERIAL_ECHORPGM(_n("M221 Invalid extruder "));////MSG_M221_INVALID_EXTRUDER break; } SERIAL_PROTOCOLLN((int)extruder); From ec4c1be0582a3ba3a5109a3328c953d8a1847d67 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Fri, 29 Jan 2021 16:34:09 +0100 Subject: [PATCH 35/58] Silence bUpdateEEPROM unused warning in MK3 variant --- Firmware/fsensor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/fsensor.cpp b/Firmware/fsensor.cpp index 7c225bf2a..4eac7bd08 100755 --- a/Firmware/fsensor.cpp +++ b/Firmware/fsensor.cpp @@ -233,6 +233,8 @@ void fsensor_init(void) bool fsensor_enable(bool bUpdateEEPROM) { #ifdef PAT9125 + (void)bUpdateEEPROM; // silence unused warning in this variant + if (mmu_enabled == false) { //filament sensor is pat9125, enable only if it is working uint8_t pat9125 = pat9125_init(); printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125); From b6d56bc0f401928e80811c866ec303e198d7eb65 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 1 Feb 2021 14:54:37 +0200 Subject: [PATCH 36/58] Change M27 argument from L to P as that makes more sense (path vs LFN)) --- Firmware/Marlin_main.cpp | 2 +- Firmware/cardreader.cpp | 4 ++-- Firmware/cardreader.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index a16718486..62ec6f678 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -5818,7 +5818,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) ### M27 - Get SD status M27: Report SD print status */ case 27: - card.getStatus(code_seen('L')); + card.getStatus(code_seen('P')); break; /*! diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index 2140a09af..a96268972 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -502,7 +502,7 @@ uint32_t CardReader::getFileSize() return filesize; } -void CardReader::getStatus(bool arg_L) +void CardReader::getStatus(bool arg_P) { if (isPrintPaused) { @@ -513,7 +513,7 @@ void CardReader::getStatus(bool arg_L) } else if (sdprinting) { - if (arg_L) + if (arg_P) { SERIAL_PROTOCOL('/'); for (uint8_t i = 0; i < getWorkDirDepth(); i++) diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index 40098d3c0..524454002 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -26,7 +26,7 @@ public: void release(); void startFileprint(); uint32_t getFileSize(); - void getStatus(bool arg_L); + void getStatus(bool arg_P); void printingHasFinished(); void getfilename(uint16_t nr, const char* const match=NULL); From 7e09df6a340972cc9738699ee2a88977d3439534 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Mon, 1 Feb 2021 14:54:44 +0200 Subject: [PATCH 37/58] Add documentation --- Firmware/Marlin_main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 62ec6f678..652466d73 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -5816,6 +5816,12 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) /*! ### M27 - Get SD status M27: Report SD print status + #### Usage + + M27 [ P ] + + #### Parameters + - `P` - Show full SFN path instead of LFN only. */ case 27: card.getStatus(code_seen('P')); From 2f4119a6d723fc1e0e7b148aed73101cb89c5369 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 2 Feb 2021 13:21:16 +0200 Subject: [PATCH 38/58] M552 - Printer IP address --- Firmware/Marlin.h | 2 ++ Firmware/Marlin_main.cpp | 19 +++++++++++++++++++ Firmware/ultralcd.cpp | 31 +++++++++++++++++++------------ Firmware/util.cpp | 7 +++++++ Firmware/util.h | 3 +++ 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 307b8c91b..17fce2713 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -501,4 +501,6 @@ void raise_z_above(float target, bool plan=true); extern "C" void softReset(); +extern uint32_t IP_address; + #endif diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 9deb51055..61e5a33ce 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -321,6 +321,8 @@ uint16_t print_time_remaining_normal = PRINT_TIME_REMAINING_INIT; //estimated re uint8_t print_percent_done_silent = PRINT_PERCENT_DONE_INIT; uint16_t print_time_remaining_silent = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes +uint32_t IP_address = 0; + //=========================================================================== //=============================Private Variables============================= //=========================================================================== @@ -8003,6 +8005,23 @@ Sigma_Exit: break; } #endif // CUSTOM_M_CODE_SET_Z_PROBE_OFFSET + case 552: + { + if (code_seen('P')) + { + uint8_t valCnt = 0; + IP_address = 0; + do + { + *strchr_pointer = '*'; + ((uint8_t*)&IP_address)[valCnt] = code_value_short(); + valCnt++; + } while ((valCnt < 4) && code_seen('.')); + + if (valCnt != 4) + IP_address = 0; + } + } break; #ifdef FILAMENTCHANGEENABLE diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index d7976d277..0f6bc1fa3 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2057,8 +2057,8 @@ static void lcd_support_menu() { // 22bytes total int8_t status; // 1byte bool is_flash_air; // 1byte - uint8_t ip[4]; // 4bytes - char ip_str[3*4+3+1]; // 16bytes + uint32_t ip; // 4bytes + char ip_str[IP4_STR_SIZE]; // 16bytes } _menu_data_t; static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data"); _menu_data_t* _md = (_menu_data_t*)&(menu_data[0]); @@ -2069,17 +2069,10 @@ static void lcd_support_menu() _md->status = 1; _md->is_flash_air = card.ToshibaFlashAir_isEnabled(); if (_md->is_flash_air) { - card.ToshibaFlashAir_GetIP(_md->ip); // ip[4] filled with 0 if it failed - // Prepare IP string from ip[4] - sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"), - _md->ip[0], _md->ip[1], - _md->ip[2], _md->ip[3]); + card.ToshibaFlashAir_GetIP((uint8_t*)(&_md->ip)); // ip == 0 if it failed } - } else if (_md->is_flash_air && - _md->ip[0] == 0 && _md->ip[1] == 0 && - _md->ip[2] == 0 && _md->ip[3] == 0 && - ++ _md->status == 16) - { + } else if (_md->is_flash_air && _md->ip == 0 && ++ _md->status == 16) + { // Waiting for the FlashAir card to get an IP address from a router. Force an update. _md->status = 0; } @@ -2143,6 +2136,20 @@ static void lcd_support_menu() MENU_ITEM_BACK_P(PSTR(" ")); if (((menu_item - 1) == menu_line) && lcd_draw_update) { lcd_set_cursor(2, menu_row); + ip4_to_str(_md->ip_str, (uint8_t*)(&_md->ip)); + lcd_printf_P(PSTR("%s"), _md->ip_str); + } + } + + // Show the printer IP address, if it is available. + if (IP_address) { + + MENU_ITEM_BACK_P(STR_SEPARATOR); + MENU_ITEM_BACK_P(PSTR("Printer IP Addr:")); //c=18 r=1 + MENU_ITEM_BACK_P(PSTR(" ")); + if (((menu_item - 1) == menu_line) && lcd_draw_update) { + lcd_set_cursor(2, menu_row); + ip4_to_str(_md->ip_str, (uint8_t*)(&IP_address)); lcd_printf_P(PSTR("%s"), _md->ip_str); } } diff --git a/Firmware/util.cpp b/Firmware/util.cpp index e335793a0..a25efd359 100644 --- a/Firmware/util.cpp +++ b/Firmware/util.cpp @@ -4,6 +4,7 @@ #include "sound.h" #include "language.h" #include "util.h" +#include // Allocate the version string in the program memory. Otherwise the string lands either on the stack or in the global RAM. const char FW_VERSION_STR[] PROGMEM = FW_VERSION; @@ -604,3 +605,9 @@ else { sPrinterName=_sPrinterName; } } + + +void ip4_to_str(char* dest, uint8_t* IP) +{ + sprintf_P(dest, PSTR("%u.%u.%u.%u"), IP[0], IP[1], IP[2], IP[3]); +} diff --git a/Firmware/util.h b/Firmware/util.h index f25749de0..6d34aa081 100644 --- a/Firmware/util.h +++ b/Firmware/util.h @@ -110,4 +110,7 @@ void gcode_level_check(uint16_t nGcodeLevel); void fSetMmuMode(bool bMMu); +#define IP4_STR_SIZE 16 +extern void ip4_to_str(char* dest, uint8_t* IP); + #endif /* UTIL_H */ From 647cde0caeb3365e66d65cf1d558168c2ae2dc29 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 2 Feb 2021 13:38:20 +0200 Subject: [PATCH 39/58] Add documentation --- Firmware/Marlin_main.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 61e5a33ce..777a05ff4 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -3734,6 +3734,7 @@ extern uint8_t st_backlash_y; //!@n M503 - print the current settings (from memory not from EEPROM) //!@n M509 - force language selection on next restart //!@n M540 - Use S[0|1] to enable or disable the stop SD card print on endstop hit (requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) +//!@n M552 - Set IP address //!@n M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal] //!@n M605 - Set dual x-carriage movement mode: S [ X R ] //!@n M860 - Wait for PINDA thermistor to reach target temperature. @@ -8005,6 +8006,19 @@ Sigma_Exit: break; } #endif // CUSTOM_M_CODE_SET_Z_PROBE_OFFSET + + /*! + ### M552 - Set IP address M552: Set IP address, enable/disable network interface" + Sets the printer IP address that is shown in the support menu. Designed to be used with the help of host software. + If P is not specified nothing happens. + If the structure of the IP address is invalid, 0.0.0.0 is assumed and nothing is shown on the screen in the Support menu. + #### Usage + + M552 [ P ] + + #### Parameters + - `P` - The IP address in xxx.xxx.xxx.xxx format. Eg: P192.168.1.14 + */ case 552: { if (code_seen('P')) From 5c9d202871c0bdb63323b77d5ed88827588d9533 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 2 Feb 2021 19:08:19 +0200 Subject: [PATCH 40/58] Change MAX_DIR_DEPTH from 10 to 6 You can't run M23 with so many directories as the length of the command will exceed the maximum allowed by cmdqueue --- Firmware/cardreader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index 524454002..9bf9bd0a6 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -3,7 +3,7 @@ #ifdef SDSUPPORT -#define MAX_DIR_DEPTH 10 +#define MAX_DIR_DEPTH 6 #include "SdFile.h" enum LsAction {LS_SerialPrint,LS_SerialPrint_LFN,LS_Count,LS_GetFilename}; From f6ae3790770d39d3df71911c5112485edc04582b Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 2 Feb 2021 19:08:44 +0200 Subject: [PATCH 41/58] Fix dir_names array definition. Prevents overrun --- Firmware/Marlin.h | 2 +- Firmware/Marlin_main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 17fce2713..aa057bc5b 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -352,7 +352,7 @@ extern bool mesh_bed_run_from_menu; extern bool sortAlpha; -extern char dir_names[3][9]; +extern char dir_names[MAX_DIR_DEPTH][9]; extern int8_t lcd_change_fil_state; // save/restore printing diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 777a05ff4..4e0511c19 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -228,7 +228,7 @@ bool fan_state[2]; int fan_edge_counter[2]; int fan_speed[2]; -char dir_names[3][9]; +char dir_names[MAX_DIR_DEPTH][9]; bool sortAlpha = false; From 896f4e1dd1b55bc14e77cd63996aab87267a4464 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 2 Feb 2021 19:14:05 +0200 Subject: [PATCH 42/58] Fix compile error --- Firmware/Marlin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index aa057bc5b..1ed5e0bd3 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -352,7 +352,7 @@ extern bool mesh_bed_run_from_menu; extern bool sortAlpha; -extern char dir_names[MAX_DIR_DEPTH][9]; +extern char dir_names[][9]; extern int8_t lcd_change_fil_state; // save/restore printing From 1c76152e62e9aa6fd3dafbc8eecb800cab6003f6 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 20 Sep 2020 18:15:27 +0200 Subject: [PATCH 43/58] Implement separate travel acceleration (M204 T) Allow to separate extrusion and travel acceleration settings using M204, as Marlin 1.1.x and 2.x does using M204 T. This allows to reduce the number of instructions required during printing, since resetting the acceleration for travel moves is no longer required and can be done a single time during the print. Provision for this parameter was pre-existing, but not implemented. M204 has two forms: the lagacy format (Marlin <1.1): M204 S[print-acc] T[retract-acc] and the newer format: M204 P[print-acc] R[retract-acc] T[travel-acc] The distinction in the MK3 FW is done based on the presence of the P parameter. If P is seen, the new format is adoped. In the new format however, M204 T was ignored until this change. To keep backward compatibility, M204 S[acc] will set both print and travel acceleration, which is identical in behavior to recent versions of Marlin. --- Firmware/ConfigurationStore.cpp | 3 ++- Firmware/ConfigurationStore.h | 1 + Firmware/Marlin_main.cpp | 11 +++-------- Firmware/planner.cpp | 3 ++- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Firmware/ConfigurationStore.cpp b/Firmware/ConfigurationStore.cpp index 0bd13a3a1..009a90248 100644 --- a/Firmware/ConfigurationStore.cpp +++ b/Firmware/ConfigurationStore.cpp @@ -184,7 +184,7 @@ static_assert (false, "zprobe_zoffset was not initialized in printers in field t "0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf"); #endif -static_assert (sizeof(M500_conf) == 192, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, " +static_assert (sizeof(M500_conf) == 196, "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." "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."); @@ -232,6 +232,7 @@ static const M500_conf default_conf PROGMEM = #else // TMC2130 {16,16,16,16}, #endif + DEFAULT_TRAVEL_ACCELERATION, }; //! @brief Read M500 configuration diff --git a/Firmware/ConfigurationStore.h b/Firmware/ConfigurationStore.h index b9dca3685..3e3caf725 100644 --- a/Firmware/ConfigurationStore.h +++ b/Firmware/ConfigurationStore.h @@ -38,6 +38,7 @@ typedef struct float max_feedrate_silent[4]; //!< max speeds for silent mode unsigned long max_acceleration_units_per_sq_second_silent[4]; unsigned char axis_ustep_resolution[4]; + float travel_acceleration; //!< travel acceleration mm/s^2 } M500_conf; extern M500_conf cs; diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 4e0511c19..f25b5aebf 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -7258,7 +7258,7 @@ Sigma_Exit: // Legacy acceleration format. This format is used by the legacy Marlin, MK2 or MK3 firmware, // and it is also generated by Slic3r to control acceleration per extrusion type // (there is a separate acceleration settings in Slicer for perimeter, first layer etc). - cs.acceleration = code_value(); + cs.acceleration = cs.travel_acceleration = code_value(); // Interpret the T value as retract acceleration in the old Marlin format. if(code_seen('T')) cs.retract_acceleration = code_value(); @@ -7268,13 +7268,8 @@ Sigma_Exit: cs.acceleration = code_value(); if(code_seen('R')) cs.retract_acceleration = code_value(); - if(code_seen('T')) { - // Interpret the T value as the travel acceleration in the new Marlin format. - /*! - @todo Prusa3D firmware currently does not support travel acceleration value independent from the extruding acceleration value. - */ - // travel_acceleration = code_value(); - } + if(code_seen('T')) + cs.travel_acceleration = code_value(); } } break; diff --git a/Firmware/planner.cpp b/Firmware/planner.cpp index 2615ef66e..ba3791ae8 100644 --- a/Firmware/planner.cpp +++ b/Firmware/planner.cpp @@ -1082,7 +1082,8 @@ Having the real displacement of the head, we can calculate the total movement le } else { - block->acceleration_st = ceil(cs.acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 + float acceleration = (block->steps_e.wide == 0? cs.travel_acceleration: cs.acceleration); + block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2 #ifdef LIN_ADVANCE /** From 5589954b77dd35042ed743f8aa8d94c2d717d44f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 20 Sep 2020 19:03:05 +0200 Subject: [PATCH 44/58] Add DEFAULT_TRAVEL_ACCELERATION in all variants Use the same value as DEFAULT_ACCELERATION for compatibility. --- Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h | 3 ++- Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h | 3 ++- Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h | 5 +++-- Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h | 5 +++-- Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h | 5 +++-- Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h | 5 +++-- Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h | 5 +++-- Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h | 5 +++-- 8 files changed, 22 insertions(+), 14 deletions(-) diff --git a/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h index a74b69482..4c20082e9 100644 --- a/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h @@ -90,8 +90,9 @@ AXIS SETTINGS #define DEFAULT_MAX_ACCELERATION {9000,9000,500,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for Skeinforge 40+, for older versions raise them a lot. #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for retracts +#define DEFAULT_TRAVEL_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for travels #define MANUAL_FEEDRATE {3000, 3000, 1000, 100} // set the speeds for manual moves (mm/min) diff --git a/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h index 72ac605fd..35313a412 100644 --- a/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h @@ -90,8 +90,9 @@ AXIS SETTINGS #define DEFAULT_MAX_ACCELERATION {9000,9000,500,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for Skeinforge 40+, for older versions raise them a lot. #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for printing moves #define DEFAULT_RETRACT_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for retracts +#define DEFAULT_TRAVEL_ACCELERATION 1500 // X, Y, Z and E max acceleration in mm/s^2 for travels #define MANUAL_FEEDRATE {3000, 3000, 1000, 100} // set the speeds for manual moves (mm/min) diff --git a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h index ba40e0468..acd7883dd 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h @@ -94,8 +94,9 @@ #define DEFAULT_MAX_ACCELERATION {1000, 1000, 200, 5000} // (mm/sec^2) max acceleration (M201) #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204S) -#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204T) +#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204P) +#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204R) +#define DEFAULT_TRAVEL_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for travels (M204T) #define MANUAL_FEEDRATE {2700, 2700, 1000, 100} // set the speeds for manual moves (mm/min) diff --git a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h index 33bb47170..ddf7e77a0 100644 --- a/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h @@ -95,8 +95,9 @@ #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204S) -#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204T) +#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204P) +#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204R) +#define DEFAULT_TRAVEL_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for travels (M204T) #define MANUAL_FEEDRATE {2700, 2700, 1000, 100} // set the speeds for manual moves (mm/min) diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h index 19b2c76fd..e7b114d96 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h @@ -94,8 +94,9 @@ #define DEFAULT_MAX_ACCELERATION {1000, 1000, 200, 5000} // (mm/sec^2) max acceleration (M201) #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204S) -#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204T) +#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204P) +#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204R) +#define DEFAULT_TRAVEL_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for travels (M204T) #define MANUAL_FEEDRATE {2700, 2700, 1000, 100} // set the speeds for manual moves (mm/min) diff --git a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h index cc02867dd..cde812498 100644 --- a/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h @@ -95,8 +95,9 @@ #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204S) -#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204T) +#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204P) +#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204R) +#define DEFAULT_TRAVEL_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for travels (M204T) #define MANUAL_FEEDRATE {2700, 2700, 1000, 100} // set the speeds for manual moves (mm/min) diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index 65f7ae997..2c62f2fdd 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -99,8 +99,9 @@ #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204S) -#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204T) +#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204P) +#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204R) +#define DEFAULT_TRAVEL_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for travels (M204T) #define MANUAL_FEEDRATE {2700, 2700, 1000, 100} // set the speeds for manual moves (mm/min) diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index c7ab7508e..d74d75d54 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -101,8 +101,9 @@ #define DEFAULT_MAX_ACCELERATION_SILENT {960, 960, 200, 5000} // (mm/sec^2) max acceleration (M201), silent mode -#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204S) -#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204T) +#define DEFAULT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204P) +#define DEFAULT_RETRACT_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204R) +#define DEFAULT_TRAVEL_ACCELERATION 1250 // X, Y, Z and E max acceleration in mm/s^2 for travels (M204T) #define MANUAL_FEEDRATE {2700, 2700, 1000, 100} // set the speeds for manual moves (mm/min) From 45811f82aa04b58dadd93990298fef36747ea82d Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 20 Sep 2020 19:04:08 +0200 Subject: [PATCH 45/58] Initialize default travel_acceleration from EEPROM When reading uninitialized memory, preset the travel acceleration to be the same as the default acceleration. --- Firmware/ConfigurationStore.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Firmware/ConfigurationStore.cpp b/Firmware/ConfigurationStore.cpp index 009a90248..c8548564a 100644 --- a/Firmware/ConfigurationStore.cpp +++ b/Firmware/ConfigurationStore.cpp @@ -235,6 +235,18 @@ static const M500_conf default_conf PROGMEM = DEFAULT_TRAVEL_ACCELERATION, }; + +static bool is_uninitialized(void* addr, uint8_t len) +{ + while(len--) + { + if(reinterpret_cast(addr)[len] != 0xff) + return false; + } + return true; +} + + //! @brief Read M500 configuration //! @retval true Succeeded. Stored settings retrieved or default settings retrieved in case EEPROM has been erased. //! @retval false Failed. Default settings has been retrieved, because of older version or corrupted data. @@ -294,6 +306,9 @@ bool Config_RetrieveSettings() tmc2130_set_res(E_AXIS, cs.axis_ustep_resolution[E_AXIS]); #endif //TMC2130 + if(is_uninitialized(&cs.travel_acceleration, sizeof(cs.travel_acceleration))) + cs.travel_acceleration = cs.acceleration; + reset_acceleration_rates(); // Call updatePID (similar to when we have processed M301) From 76911f67dbd69c22558beb84f45b85f643515372 Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 20 Sep 2020 19:05:19 +0200 Subject: [PATCH 46/58] Take advantage of the new is_uninitialized function Save some space and perform some cleanup --- Firmware/ConfigurationStore.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Firmware/ConfigurationStore.cpp b/Firmware/ConfigurationStore.cpp index c8548564a..dc8126acd 100644 --- a/Firmware/ConfigurationStore.cpp +++ b/Firmware/ConfigurationStore.cpp @@ -270,13 +270,9 @@ bool Config_RetrieveSettings() for (uint8_t i = 0; i < (sizeof(cs.max_feedrate_silent)/sizeof(cs.max_feedrate_silent[0])); ++i) { const uint32_t erased = 0xffffffff; - bool initialized = false; - - for(uint8_t j = 0; j < sizeof(float); ++j) - { - if(0xff != reinterpret_cast(&(cs.max_feedrate_silent[i]))[j]) initialized = true; + if (is_uninitialized(&(cs.max_feedrate_silent[i]), sizeof(float))) { + memcpy_P(&cs.max_feedrate_silent[i],&default_conf.max_feedrate_silent[i], sizeof(cs.max_feedrate_silent[i])); } - if (!initialized) memcpy_P(&cs.max_feedrate_silent[i],&default_conf.max_feedrate_silent[i], sizeof(cs.max_feedrate_silent[i])); if (erased == cs.max_acceleration_units_per_sq_second_silent[i]) { memcpy_P(&cs.max_acceleration_units_per_sq_second_silent[i],&default_conf.max_acceleration_units_per_sq_second_silent[i],sizeof(cs.max_acceleration_units_per_sq_second_silent[i])); } From f7542aa0644b8ea6d9928e8dbe64e527e686599f Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Sun, 20 Sep 2020 19:06:15 +0200 Subject: [PATCH 47/58] Report travel acceleration in M503 Use the new M204 format consistently also in M503's output --- Firmware/ConfigurationStore.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/ConfigurationStore.cpp b/Firmware/ConfigurationStore.cpp index dc8126acd..adccb3999 100644 --- a/Firmware/ConfigurationStore.cpp +++ b/Firmware/ConfigurationStore.cpp @@ -96,7 +96,7 @@ void Config_PrintSettings(uint8_t level) "%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 - 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: P=print, R=retract, T=travel\n%S M204 P%.2f R%.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" "%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n" ), @@ -106,7 +106,7 @@ void Config_PrintSettings(uint8_t level) 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_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, cs.travel_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.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS] #else //TMC2130 @@ -114,14 +114,14 @@ void Config_PrintSettings(uint8_t level) "%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 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: P=print, R=retract, T=travel\n%S M204 P%.2f R%.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" "%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, 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, cs.acceleration, cs.retract_acceleration, + echomagic, echomagic, cs.acceleration, cs.retract_acceleration, cs.travel_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.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS] #endif //TMC2130 From 186ce0f4b32dda9d5a2fa8e0e2649cc130d2cfca Mon Sep 17 00:00:00 2001 From: Yuri D'Elia Date: Mon, 1 Feb 2021 00:02:49 +0100 Subject: [PATCH 48/58] Handle acceleration settings in UVLO/power panic Acceleration settings need to be saved in UVLO, since these are often changed/set during a print. This is especially important for travel and retract acceleration, which is usually set once per-print. Saving and restoring is not 100% correct. We save the current front-end value, which might ahead of the backend when UVLO is triggered. Print acceleration, likely the most significant, should be saved in the block buffer to be accurate. Acceleration needs to be restored after the UVLO Z repositioning is performed, using an M204 command. This is correct, however we don't save the _temporary_ max acceleration limits set via M201, which could be higher than the saved limits (via M500). This could result in lower clamped values compared to the original print. Maximum acceleration/jerk/feedrate limits should _all_ be saved in UVLO in the future. --- Firmware/Marlin_main.cpp | 11 +++++++++++ Firmware/eeprom.h | 11 +++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index f25b5aebf..780a0bca3 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -10963,6 +10963,10 @@ void uvlo_() #endif eeprom_update_word((uint16_t*)(EEPROM_EXTRUDEMULTIPLY), (uint16_t)extrudemultiply); + eeprom_update_float((float*)(EEPROM_UVLO_ACCELL), cs.acceleration); + eeprom_update_float((float*)(EEPROM_UVLO_RETRACT_ACCELL), cs.retract_acceleration); + eeprom_update_float((float*)(EEPROM_UVLO_TRAVEL_ACCELL), cs.travel_acceleration); + // Store the saved target eeprom_update_float((float*)(EEPROM_UVLO_SAVED_TARGET+0*4), saved_target[X_AXIS]); eeprom_update_float((float*)(EEPROM_UVLO_SAVED_TARGET+1*4), saved_target[Y_AXIS]); @@ -11307,6 +11311,13 @@ void restore_print_from_eeprom(bool mbl_was_active) { sprintf_P(cmd, PSTR("G1 Z%f"), eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION_Z))); enquecommand(cmd); + // Restore acceleration settings + float acceleration = eeprom_read_float((float*)(EEPROM_UVLO_ACCELL)); + float retract_acceleration = eeprom_read_float((float*)(EEPROM_UVLO_RETRACT_ACCELL)); + float travel_acceleration = eeprom_read_float((float*)(EEPROM_UVLO_TRAVEL_ACCELL)); + sprintf_P(cmd, PSTR("M204 P%f R%f T%f"), acceleration, retract_acceleration, travel_acceleration); + enquecommand(cmd); + // Unretract. sprintf_P(cmd, PSTR("G1 E%0.3f F2700"), default_retraction); enquecommand(cmd); diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 03af214f2..f9f93b7d8 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -319,8 +319,10 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | ^ | ^ | ^ | 00h 0 | ^ | PINDA has no temp compensation PINDA v1/2 | ^ | ^ | ^ | ^ | ^ | 01h 1 | ^ | PINDA has temp compensation aka SuperPINDA | ^ | ^ | 0x0D15 3349 | char[20] | EEPROM_PRUSA_SN | SN[19] == 0 | ffffffffffffffff... | PRUSA Serial number string | PRUSA SN | D3 Ax0d15 C20 +| 0x0D11 3345 | float | EEPROM_UVLO_ACCELL | ??? | ff ff ff ffh | Power panic saved normal acceleration | ??? | D3 Ax0d11 C4 +| 0x0D0D 3341 | float | EEPROM_UVLO_RETRACT_ACCELL | ??? | ff ff ff ffh | Power panic saved retract acceleration | ??? | D3 Ax0d0d C4 +| 0x0D09 3337 | float | EEPROM_UVLO_TRAVEL_ACCELL | ??? | ff ff ff ffh | Power panic saved travel acceleration | ??? | D3 Ax0d09 C4 - | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 0x0012 18 | uint16 | EEPROM_FIRMWARE_VERSION_END | ??? | ff ffh 65535 | ??? | ??? | D3 Ax0012 C2 @@ -525,8 +527,13 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_EXPERIMENTAL_VISIBILITY (EEPROM_ALTFAN_OVERRIDE-1) //uint8 #define EEPROM_PINDA_TEMP_COMPENSATION (EEPROM_EXPERIMENTAL_VISIBILITY-1) //uint8 #define EEPROM_PRUSA_SN (EEPROM_PINDA_TEMP_COMPENSATION-20) //char[20] + +#define EEPROM_UVLO_ACCELL (EEPROM_PRUSA_SN-4) // float +#define EEPROM_UVLO_RETRACT_ACCELL (EEPROM_UVLO_ACCELL-4) // float +#define EEPROM_UVLO_TRAVEL_ACCELL (EEPROM_UVLO_RETRACT_ACCELL-4) // float + //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_PRUSA_SN +#define EEPROM_LAST_ITEM EEPROM_UVLO_TRAVEL_ACCELL // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! From f343e6432ac33c7417d35d3f2faadcb9f94ae515 Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Sun, 31 Jan 2021 16:42:01 +0200 Subject: [PATCH 49/58] Fix diveSubfolder string termination --- Firmware/cardreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index a96268972..4b55e8161 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -340,9 +340,9 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir) { const size_t maxLen = 12; char subdirname[maxLen+1]; - subdirname[maxLen] = 0; const size_t len = ((static_cast(dirname_end-dirname_start))>maxLen) ? maxLen : (dirname_end-dirname_start); strncpy(subdirname, dirname_start, len); + subdirname[len] = 0; SERIAL_ECHOLN(subdirname); if (!dir.open(curDir, subdirname, O_READ)) { From 52f7a71dce177cf7dc484988a6701f08e689d9e2 Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Sat, 6 Feb 2021 14:59:11 +0200 Subject: [PATCH 50/58] More fixes that were extracted from #2405 --- Firmware/Marlin.h | 4 -- Firmware/Marlin_main.cpp | 8 +--- Firmware/cardreader.cpp | 81 +++++++++++++++++++++------------------- Firmware/cardreader.h | 10 +++-- Firmware/messages.c | 1 + Firmware/messages.h | 1 + Firmware/ultralcd.cpp | 12 ++---- 7 files changed, 57 insertions(+), 60 deletions(-) diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 1ed5e0bd3..cbe03c0f6 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -350,10 +350,6 @@ extern unsigned long t_fan_rising_edge; extern bool mesh_bed_leveling_flag; extern bool mesh_bed_run_from_menu; -extern bool sortAlpha; - -extern char dir_names[][9]; - extern int8_t lcd_change_fil_state; // save/restore printing extern bool saved_printing; diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 6db1d2770..e5daeee07 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -228,10 +228,6 @@ bool fan_state[2]; int fan_edge_counter[2]; int fan_speed[2]; -char dir_names[MAX_DIR_DEPTH][9]; - -bool sortAlpha = false; - float extruder_multiplier[EXTRUDERS] = {1.0 #if EXTRUDERS > 1 @@ -11281,8 +11277,8 @@ void restore_print_from_eeprom(bool mbl_was_active) { } dir_name[8] = '\0'; MYSERIAL.println(dir_name); - strcpy(dir_names[i], dir_name); - card.chdir(dir_name); + // strcpy(dir_names[i], dir_name); + card.chdir(dir_name, false); } for (int i = 0; i < 8; i++) { diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index 4b55e8161..418dbb940 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -32,6 +32,7 @@ CardReader::CardReader() workDirDepth = 0; file_subcall_ctr=0; memset(workDirParents, 0, sizeof(workDirParents)); + presort_flag = false; autostart_stilltocheck=true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software. lastnr=0; @@ -69,12 +70,15 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters +*/ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) { + static uint8_t recursionCnt = 0; dir_t p; uint8_t cnt = 0; // Read the next entry from a directory while (parent.readDir(p, longFilename) > 0) { - // If the entry is a directory and the action is LS_SerialPrint - if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { + if (recursionCnt >= MAX_DIR_DEPTH) + return; + else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint + recursionCnt++; // Get the short name for the item, which we know is a folder char lfilename[FILENAME_LENGTH]; createFilename(lfilename, p); @@ -108,6 +112,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m if (lsAction == LS_SerialPrint_LFN) puts_P(PSTR("DIR_EXIT")); + recursionCnt--; } else { uint8_t pn0 = p.name[0]; @@ -241,18 +246,18 @@ void CardReader::initsd() } -void CardReader::setroot() +void CardReader::setroot(bool doPresort) { - /*if(!workDir.openRoot(&volume)) - { - SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL); - }*/ workDir=root; + workDirDepth = 0; curDir=&workDir; - #ifdef SDCARD_SORT_ALPHA - presort(); - #endif +#ifdef SDCARD_SORT_ALPHA + if (doPresort) + presort(); + else + presort_flag = true; +#endif } void CardReader::release() { @@ -317,19 +322,17 @@ void CardReader::getAbsFilename(char *t) * @param[in,out] fileName * expects file name including path * in case of absolute path, file name without path is returned - * @param[in,out] dir SdFile object to operate with, - * in case of absolute path, curDir is modified to point to dir, - * so it is not possible to create on stack inside this function, - * as curDir would point to destroyed object. */ -void CardReader::diveSubfolder (const char *fileName, SdFile& dir) +bool CardReader::diveSubfolder (const char *&fileName) { curDir=&root; - if (!fileName) return; + if (!fileName) + return 1; const char *dirname_start, *dirname_end; if (fileName[0] == '/') // absolute path { + setroot(false); dirname_start = fileName + 1; while (*dirname_start) { @@ -344,19 +347,10 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir) strncpy(subdirname, dirname_start, len); subdirname[len] = 0; SERIAL_ECHOLN(subdirname); - if (!dir.open(curDir, subdirname, O_READ)) - { - SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL); - SERIAL_PROTOCOL(subdirname); - SERIAL_PROTOCOLLN('.'); - return; - } - else - { - //SERIAL_ECHOLN("dive ok"); - } + if (!chdir(subdirname, false)) + return 0; - curDir = &dir; + curDir = &workDir; dirname_start = dirname_end + 1; } else // the reminder after all /fsa/fdsa/ is the filename @@ -373,6 +367,7 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir) { curDir = &workDir; } + return 1; } void CardReader::openFile(const char* name,bool read, bool replace_current/*=true*/) @@ -423,9 +418,9 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru } sdprinting = false; - SdFile myDir; const char *fname=name; - diveSubfolder(fname,myDir); + if (!diveSubfolder(fname)) + return; if(read) { @@ -438,10 +433,9 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru SERIAL_PROTOCOLLN(filesize); sdpos = 0; - SERIAL_PROTOCOLLNRPGM(_N("File selected"));////MSG_SD_FILE_SELECTED + SERIAL_PROTOCOLLNRPGM(MSG_FILE_SELECTED); + lcd_setstatuspgm(MSG_FILE_SELECTED); getfilename(0, fname); - lcd_setstatus(longFilename[0] ? longFilename : fname); - lcd_setstatuspgm(PSTR("SD-PRINTING")); } else { @@ -475,9 +469,9 @@ void CardReader::removeFile(const char* name) file.close(); sdprinting = false; - SdFile myDir; const char *fname=name; - diveSubfolder(fname,myDir); + if (!diveSubfolder(fname)) + return; if (file.remove(curDir, fname)) { @@ -670,7 +664,7 @@ uint16_t CardReader::getnrfilenames() return nrFiles; } -void CardReader::chdir(const char * relpath) +bool CardReader::chdir(const char * relpath, bool doPresort) { SdFile newfile; SdFile *parent=&root; @@ -678,23 +672,32 @@ void CardReader::chdir(const char * relpath) if(workDir.isOpen()) parent=&workDir; - if(!newfile.open(*parent,relpath, O_READ)) + if(!newfile.open(*parent,relpath, O_READ) || ((workDirDepth + 1) >= MAX_DIR_DEPTH)) { SERIAL_ECHO_START; SERIAL_ECHORPGM(_n("Cannot enter subdir: "));////MSG_SD_CANT_ENTER_SUBDIR SERIAL_ECHOLN(relpath); + return 0; } else { + strcpy(dir_names[workDirDepth], relpath); + puts(relpath); + if (workDirDepth < MAX_DIR_DEPTH) { for (int d = ++workDirDepth; d--;) workDirParents[d+1] = workDirParents[d]; workDirParents[0]=*parent; } workDir=newfile; - #ifdef SDCARD_SORT_ALPHA + +#ifdef SDCARD_SORT_ALPHA + if (doPresort) presort(); - #endif + else + presort_flag = true; +#endif + return 1; } } diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index 9bf9bd0a6..819e8bf27 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -39,9 +39,9 @@ public: void ls(bool printLFN); - void chdir(const char * relpath); + bool chdir(const char * relpath, bool doPresort); void updir(); - void setroot(); + void setroot(bool doPresort); #ifdef SDCARD_SORT_ALPHA void presort(); @@ -82,6 +82,10 @@ public: char longFilename[LONG_FILENAME_LENGTH]; bool filenameIsDir; int lastnr; //last number of the autostart; +#ifdef SDCARD_SORT_ALPHA + bool presort_flag; + char dir_names[MAX_DIR_DEPTH][9]; +#endif // SDCARD_SORT_ALPHA private: SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH]; uint16_t workDirDepth; @@ -155,7 +159,7 @@ private: int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. char* diveDirName; - void diveSubfolder (const char *fileName, SdFile& dir); + bool diveSubfolder (const char *&fileName); void lsDive(const char *prepend, SdFile parent, const char * const match=NULL); #ifdef SDCARD_SORT_ALPHA void flush_presort(); diff --git a/Firmware/messages.c b/Firmware/messages.c index 0b1d58e04..39f0cf336 100644 --- a/Firmware/messages.c +++ b/Firmware/messages.c @@ -197,3 +197,4 @@ const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20 const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13 const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20 const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed"; +const char MSG_FILE_SELECTED[] PROGMEM_N1 = "File selected"; ////c=20 diff --git a/Firmware/messages.h b/Firmware/messages.h index 0a05c58f5..a5b672fa2 100644 --- a/Firmware/messages.h +++ b/Firmware/messages.h @@ -197,6 +197,7 @@ extern const char MSG_M112_KILL[]; extern const char MSG_ADVANCE_K[]; extern const char MSG_POWERPANIC_DETECTED[]; extern const char MSG_LCD_STATUS_CHANGED[]; +extern const char MSG_FILE_SELECTED[]; #if defined(__cplusplus) } diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 0f6bc1fa3..2d92596f0 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -4317,7 +4317,7 @@ static void lcd_sort_type_set() { default: sdSort = SD_SORT_TIME; } eeprom_update_byte((unsigned char *)EEPROM_SD_SORT, sdSort); - presort_flag = true; + card.presort_flag = true; } #endif //SDCARD_SORT_ALPHA @@ -8548,7 +8548,7 @@ static void menu_action_sdfile(const char* filename) for (uint_least8_t i = 0; i < depth; i++) { for (uint_least8_t j = 0; j < 8; j++) { - eeprom_write_byte((uint8_t*)EEPROM_DIRS + j + 8 * i, dir_names[i][j]); + eeprom_write_byte((uint8_t*)EEPROM_DIRS + j + 8 * i, card.dir_names[i][j]); } } @@ -8566,12 +8566,8 @@ static void menu_action_sdfile(const char* filename) void menu_action_sddirectory(const char* filename) { - uint8_t depth = (uint8_t)card.getWorkDirDepth(); - - strcpy(dir_names[depth], filename); - MYSERIAL.println(dir_names[depth]); - card.chdir(filename); - lcd_encoder = 0; + card.chdir(filename, true); + lcd_encoder = 0; } /** LCD API **/ From 77a5082b5664c7ccfe05ed08af16c89ad7c7b448 Mon Sep 17 00:00:00 2001 From: Voinea Dragos Date: Sat, 6 Feb 2021 17:25:17 +0200 Subject: [PATCH 51/58] Fix presort_flag duplicate declaration --- Firmware/ultralcd.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 2d92596f0..a736f8c2b 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -75,11 +75,6 @@ int8_t FSensorStateMenu = 1; bool bMenuFSDetect=false; #endif //IR_SENSOR_ANALOG - -#ifdef SDCARD_SORT_ALPHA -bool presort_flag = false; -#endif - LcdCommands lcd_commands_type = LcdCommands::Idle; static uint8_t lcd_commands_step = 0; @@ -7183,8 +7178,8 @@ void lcd_sdcard_menu() { uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT); - if (presort_flag == true) { - presort_flag = false; + if (card.presort_flag == true) { + card.presort_flag = false; card.presort(); } if (lcd_draw_update == 0 && LCD_CLICKED == 0) From f5cde38a7c000eeacfc7dc08f46e820359ee8777 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sat, 6 Feb 2021 21:06:37 +0200 Subject: [PATCH 52/58] Remove duplicit debug line --- Firmware/cardreader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index 418dbb940..8273e3d04 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -346,7 +346,6 @@ bool CardReader::diveSubfolder (const char *&fileName) const size_t len = ((static_cast(dirname_end-dirname_start))>maxLen) ? maxLen : (dirname_end-dirname_start); strncpy(subdirname, dirname_start, len); subdirname[len] = 0; - SERIAL_ECHOLN(subdirname); if (!chdir(subdirname, false)) return 0; From c739aa900303fddd86c62bc951f26ef18178a0a8 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Sun, 7 Feb 2021 21:51:44 +0200 Subject: [PATCH 53/58] M23 full path support. --- Firmware/cardreader.cpp | 22 ++++++++++++++++------ Firmware/cardreader.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index 8273e3d04..c414e2823 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -309,6 +309,18 @@ void CardReader::getAbsFilename(char *t) else t[0]=0; } + +void CardReader::printAbsFilenameFast() +{ + SERIAL_PROTOCOL('/'); + for (uint8_t i = 0; i < getWorkDirDepth(); i++) + { + SERIAL_PROTOCOL(dir_names[i]); + SERIAL_PROTOCOL('/'); + } + SERIAL_PROTOCOL(LONGEST_FILENAME); +} + /** * @brief Dive into subfolder * @@ -425,16 +437,16 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru { if (file.open(curDir, fname, O_READ)) { + getfilename(0, fname); filesize = file.fileSize(); SERIAL_PROTOCOLRPGM(_N("File opened: "));////MSG_SD_FILE_OPENED - SERIAL_PROTOCOL(fname); + printAbsFilenameFast(); SERIAL_PROTOCOLRPGM(_n(" Size: "));////MSG_SD_SIZE SERIAL_PROTOCOLLN(filesize); sdpos = 0; SERIAL_PROTOCOLLNRPGM(MSG_FILE_SELECTED); lcd_setstatuspgm(MSG_FILE_SELECTED); - getfilename(0, fname); } else { @@ -508,10 +520,8 @@ void CardReader::getStatus(bool arg_P) { if (arg_P) { - SERIAL_PROTOCOL('/'); - for (uint8_t i = 0; i < getWorkDirDepth(); i++) - printf_P(PSTR("%s/"), dir_names[i]); - puts(filename); + printAbsFilenameFast(); + SERIAL_PROTOCOLLN(); } else SERIAL_PROTOCOLLN(LONGEST_FILENAME); diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index 819e8bf27..0e94bd3c9 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -34,6 +34,7 @@ public: uint16_t getnrfilenames(); void getAbsFilename(char *t); + void printAbsFilenameFast(); void getDirName(char* name, uint8_t level); uint16_t getWorkDirDepth(); From fb39e7296b126c67a34937576389429d0ffc9de2 Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Mon, 8 Feb 2021 10:58:41 +0100 Subject: [PATCH 54/58] Uniform message `Press the knob` --- Firmware/Marlin_main.cpp | 2 +- lang/lang_en.txt | 2 +- lang/lang_en_cz.txt | 2 +- lang/lang_en_de.txt | 2 +- lang/lang_en_es.txt | 2 +- lang/lang_en_fr.txt | 2 +- lang/lang_en_it.txt | 2 +- lang/lang_en_pl.txt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 6db1d2770..bc90849eb 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -11786,7 +11786,7 @@ void M600_wait_for_user(float HotendTempBckp) { delay_keep_alive(4); if (_millis() > waiting_start_time + (unsigned long)M600_TIMEOUT * 1000) { - lcd_display_message_fullscreen_P(_i("Press knob to preheat nozzle and continue."));////MSG_PRESS_TO_PREHEAT c=20 r=4 + lcd_display_message_fullscreen_P(_i("Press the knob to preheat nozzle and continue."));////MSG_PRESS_TO_PREHEAT c=20 r=4 wait_for_user_state = 1; setAllTargetHotends(0); st_synchronize(); diff --git a/lang/lang_en.txt b/lang/lang_en.txt index bcb0a4444..41879c5a0 100644 --- a/lang/lang_en.txt +++ b/lang/lang_en.txt @@ -620,7 +620,7 @@ "Please upgrade." #MSG_PRESS_TO_PREHEAT c=20 r=4 -"Press knob to preheat nozzle and continue." +"Press the knob to preheat nozzle and continue." #MSG_FS_PAUSE c=5 "Pause" diff --git a/lang/lang_en_cz.txt b/lang/lang_en_cz.txt index 0b3d7b14f..4c7efc5e8 100644 --- a/lang/lang_en_cz.txt +++ b/lang/lang_en_cz.txt @@ -827,7 +827,7 @@ "Prosim aktualizujte." #MSG_PRESS_TO_PREHEAT c=20 r=4 -"Press knob to preheat nozzle and continue." +"Press the knob to preheat nozzle and continue." "Pro nahrati trysky a pokracovani stisknete tlacitko." #MSG_FS_PAUSE c=5 diff --git a/lang/lang_en_de.txt b/lang/lang_en_de.txt index 0a436a9ee..f38699318 100644 --- a/lang/lang_en_de.txt +++ b/lang/lang_en_de.txt @@ -827,7 +827,7 @@ "Bitte aktualisieren." #MSG_PRESS_TO_PREHEAT c=20 r=4 -"Press knob to preheat nozzle and continue." +"Press the knob to preheat nozzle and continue." "Bitte druecken Sie den Knopf um die Duese vorzuheizen und fortzufahren." #MSG_FS_PAUSE c=5 diff --git a/lang/lang_en_es.txt b/lang/lang_en_es.txt index 2e29fa20a..f8b39e17d 100644 --- a/lang/lang_en_es.txt +++ b/lang/lang_en_es.txt @@ -827,7 +827,7 @@ "Actualize por favor" #MSG_PRESS_TO_PREHEAT c=20 r=4 -"Press knob to preheat nozzle and continue." +"Press the knob to preheat nozzle and continue." "Pulsa el dial para precalentar la boquilla y continue." #MSG_FS_PAUSE c=5 diff --git a/lang/lang_en_fr.txt b/lang/lang_en_fr.txt index cc0cbb95b..f64f800df 100644 --- a/lang/lang_en_fr.txt +++ b/lang/lang_en_fr.txt @@ -827,7 +827,7 @@ "Mettez a jour le FW." #MSG_PRESS_TO_PREHEAT c=20 r=4 -"Press knob to preheat nozzle and continue." +"Press the knob to preheat nozzle and continue." "Appuyez sur le bouton pour prechauffer la buse et continuer." #MSG_FS_PAUSE c=5 diff --git a/lang/lang_en_it.txt b/lang/lang_en_it.txt index 8cd939082..e33833364 100644 --- a/lang/lang_en_it.txt +++ b/lang/lang_en_it.txt @@ -827,7 +827,7 @@ "Prego aggiornare." #MSG_PRESS_TO_PREHEAT c=20 r=4 -"Press knob to preheat nozzle and continue." +"Press the knob to preheat nozzle and continue." "Premete la manopola per preriscaldare l'ugello e continuare." #MSG_FS_PAUSE c=5 diff --git a/lang/lang_en_pl.txt b/lang/lang_en_pl.txt index 38d1421f7..b796c11ac 100644 --- a/lang/lang_en_pl.txt +++ b/lang/lang_en_pl.txt @@ -827,7 +827,7 @@ "Prosze zaktualizowac." #MSG_PRESS_TO_PREHEAT c=20 r=4 -"Press knob to preheat nozzle and continue." +"Press the knob to preheat nozzle and continue." "Wcisnij pokretlo aby rozgrzac dysze i kontynuowac." #MSG_FS_PAUSE c=5 From 214695105c181796bc5c958aee9fafb65c53ff3f Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Mon, 8 Feb 2021 11:33:46 +0100 Subject: [PATCH 55/58] Fix issue #2958 --- Firmware/ultralcd.cpp | 8 ++++---- lang/lang_en.txt | 6 +++--- lang/lang_en_cz.txt | 6 +++--- lang/lang_en_de.txt | 6 +++--- lang/lang_en_es.txt | 6 +++--- lang/lang_en_fr.txt | 6 +++--- lang/lang_en_it.txt | 6 +++--- lang/lang_en_pl.txt | 6 +++--- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 0f6bc1fa3..0e654384e 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2235,18 +2235,18 @@ uint8_t nLevel; lcd_set_cursor(0,0); lcdui_print_temp(LCD_STR_THERMOMETER[0],(int)degHotend(0),(int)degTargetHotend(0)); -lcd_puts_at_P(0,2, _i("Press the knob")); ////MSG_ c=20 r=1 -lcd_set_cursor(0,3); +lcd_puts_at_P(0,1, _i("Press the knob")); ////MSG_ c=20 +lcd_set_cursor(0,2); switch(eFilamentAction) { case FilamentAction::Load: case FilamentAction::AutoLoad: case FilamentAction::MmuLoad: - lcd_puts_P(_i("to load filament")); ////MSG_ c=20 r=1 + lcd_puts_P(_i("to load filament")); ////MSG_ c=20 r=2 break; case FilamentAction::UnLoad: case FilamentAction::MmuUnLoad: - lcd_puts_P(_i("to unload filament")); ////MSG_ c=20 r=1 + lcd_puts_P(_i("to unload filament")); ////MSG_ c=20 r=2 break; case FilamentAction::MmuEject: case FilamentAction::MmuCut: diff --git a/lang/lang_en.txt b/lang/lang_en.txt index 41879c5a0..875aa370e 100644 --- a/lang/lang_en.txt +++ b/lang/lang_en.txt @@ -644,7 +644,7 @@ "Print from SD" # -"Press the knob" +"Press the knob" c=20 r=2 #MSG_PRINT_PAUSED c=20 r=1 "Print paused" @@ -875,10 +875,10 @@ "Total failures" # -"to load filament" +"to load filament" c=20 r=2 # -"to unload filament" +"to unload filament" c=20 r=2 #MSG_UNLOAD_FILAMENT c=17 "Unload filament" diff --git a/lang/lang_en_cz.txt b/lang/lang_en_cz.txt index 4c7efc5e8..3c8f0f06a 100644 --- a/lang/lang_en_cz.txt +++ b/lang/lang_en_cz.txt @@ -859,7 +859,7 @@ "Tisk z SD" # -"Press the knob" +"Press the knob" c=20 r=2 "Stisknete hl. tlacitko" #MSG_PRINT_PAUSED c=20 r=1 @@ -1167,11 +1167,11 @@ "Celkem selhani" # -"to load filament" +"to load filament" c=20 r=2 "k zavedeni filamentu" # -"to unload filament" +"to unload filament" c=20 r=2 "k vyjmuti filamentu" #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_de.txt b/lang/lang_en_de.txt index f38699318..649994d93 100644 --- a/lang/lang_en_de.txt +++ b/lang/lang_en_de.txt @@ -859,7 +859,7 @@ "Drucken von SD" # -"Press the knob" +"Press the knob" c=20 r=2 "Knopf druecken zum" #MSG_PRINT_PAUSED c=20 r=1 @@ -1167,11 +1167,11 @@ "Gesamte Fehler" # -"to load filament" +"to load filament" c=20 r=2 "Filament laden" # -"to unload filament" +"to unload filament" c=20 r=2 "Filament entladen" #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_es.txt b/lang/lang_en_es.txt index f8b39e17d..359130207 100644 --- a/lang/lang_en_es.txt +++ b/lang/lang_en_es.txt @@ -859,7 +859,7 @@ "Menu tarjeta SD" # -"Press the knob" +"Press the knob" c=20 r=2 "Pulsa el dial" #MSG_PRINT_PAUSED c=20 r=1 @@ -1167,11 +1167,11 @@ "Fallos totales" # -"to load filament" +"to load filament" c=20 r=2 "para cargar el filamento" # -"to unload filament" +"to unload filament" c=20 r=2 "para descargar el filamento" #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_fr.txt b/lang/lang_en_fr.txt index f64f800df..54dc7a7cc 100644 --- a/lang/lang_en_fr.txt +++ b/lang/lang_en_fr.txt @@ -859,7 +859,7 @@ "Impr. depuis la SD" # -"Press the knob" +"Press the knob" c=20 r=2 "App. sur sur bouton" #MSG_PRINT_PAUSED c=20 r=1 @@ -1167,11 +1167,11 @@ "Total des echecs" # -"to load filament" +"to load filament" c=20 r=2 "pour charger le fil." # -"to unload filament" +"to unload filament" c=20 r=2 "pour decharger fil." #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_it.txt b/lang/lang_en_it.txt index e33833364..d5846cba7 100644 --- a/lang/lang_en_it.txt +++ b/lang/lang_en_it.txt @@ -859,7 +859,7 @@ "Stampa da SD" # -"Press the knob" +"Press the knob" c=20 r=2 "Premere la manopola" #MSG_PRINT_PAUSED c=20 r=1 @@ -1167,11 +1167,11 @@ "Totale fallimenti" # -"to load filament" +"to load filament" c=20 r=2 "per caricare il filamento" # -"to unload filament" +"to unload filament" c=20 r=2 "per scaricare il filamento" #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_pl.txt b/lang/lang_en_pl.txt index b796c11ac..eb4103eee 100644 --- a/lang/lang_en_pl.txt +++ b/lang/lang_en_pl.txt @@ -859,7 +859,7 @@ "Druk z karty SD" # -"Press the knob" +"Press the knob" c=20 r=2 "Wcisnij pokretlo" #MSG_PRINT_PAUSED c=20 r=1 @@ -1167,11 +1167,11 @@ "Suma bledow" # -"to load filament" +"to load filament" c=20 r=2 "aby zaladow. fil." # -"to unload filament" +"to unload filament" c=20 r=2 "aby rozlad. filament" #MSG_UNLOAD_FILAMENT c=17 From aecbd7ab49ec5fb0f7ca84b6bd40fd3f6823145f Mon Sep 17 00:00:00 2001 From: 3d-gussner <3d.gussner@gmail.com> Date: Mon, 8 Feb 2021 12:17:41 +0100 Subject: [PATCH 56/58] Fix `c=aa` location in lang files Fix too long translations in Spanish and Italian --- Firmware/ultralcd.cpp | 4 ++-- lang/lang_en.txt | 12 ++++++------ lang/lang_en_cz.txt | 12 ++++++------ lang/lang_en_de.txt | 12 ++++++------ lang/lang_en_es.txt | 16 ++++++++-------- lang/lang_en_fr.txt | 12 ++++++------ lang/lang_en_it.txt | 16 ++++++++-------- lang/lang_en_pl.txt | 12 ++++++------ 8 files changed, 48 insertions(+), 48 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 0e654384e..10fa2da38 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2242,11 +2242,11 @@ switch(eFilamentAction) case FilamentAction::Load: case FilamentAction::AutoLoad: case FilamentAction::MmuLoad: - lcd_puts_P(_i("to load filament")); ////MSG_ c=20 r=2 + lcd_puts_P(_i("to load filament")); ////MSG_ c=20 break; case FilamentAction::UnLoad: case FilamentAction::MmuUnLoad: - lcd_puts_P(_i("to unload filament")); ////MSG_ c=20 r=2 + lcd_puts_P(_i("to unload filament")); ////MSG_ c=20 break; case FilamentAction::MmuEject: case FilamentAction::MmuCut: diff --git a/lang/lang_en.txt b/lang/lang_en.txt index 875aa370e..8c0e6eb9d 100644 --- a/lang/lang_en.txt +++ b/lang/lang_en.txt @@ -643,8 +643,8 @@ #MSG_CARD_MENU "Print from SD" -# -"Press the knob" c=20 r=2 +# c=20 +"Press the knob" #MSG_PRINT_PAUSED c=20 r=1 "Print paused" @@ -874,11 +874,11 @@ #MSG_TOTAL_FAILURES c=20 "Total failures" -# -"to load filament" c=20 r=2 +# c=20 +"to load filament" -# -"to unload filament" c=20 r=2 +# c=20 +"to unload filament" #MSG_UNLOAD_FILAMENT c=17 "Unload filament" diff --git a/lang/lang_en_cz.txt b/lang/lang_en_cz.txt index 3c8f0f06a..2c0bc664b 100644 --- a/lang/lang_en_cz.txt +++ b/lang/lang_en_cz.txt @@ -858,8 +858,8 @@ "Print from SD" "Tisk z SD" -# -"Press the knob" c=20 r=2 +# c=20 +"Press the knob" "Stisknete hl. tlacitko" #MSG_PRINT_PAUSED c=20 r=1 @@ -1166,12 +1166,12 @@ "Total failures" "Celkem selhani" -# -"to load filament" c=20 r=2 +# c=20 +"to load filament" "k zavedeni filamentu" -# -"to unload filament" c=20 r=2 +# c=20 +"to unload filament" "k vyjmuti filamentu" #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_de.txt b/lang/lang_en_de.txt index 649994d93..e6fd5bccc 100644 --- a/lang/lang_en_de.txt +++ b/lang/lang_en_de.txt @@ -858,8 +858,8 @@ "Print from SD" "Drucken von SD" -# -"Press the knob" c=20 r=2 +# c=20 +"Press the knob" "Knopf druecken zum" #MSG_PRINT_PAUSED c=20 r=1 @@ -1166,12 +1166,12 @@ "Total failures" "Gesamte Fehler" -# -"to load filament" c=20 r=2 +# c=20 +"to load filament" "Filament laden" -# -"to unload filament" c=20 r=2 +# c=20 +"to unload filament" "Filament entladen" #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_es.txt b/lang/lang_en_es.txt index 359130207..4e622ebb9 100644 --- a/lang/lang_en_es.txt +++ b/lang/lang_en_es.txt @@ -858,8 +858,8 @@ "Print from SD" "Menu tarjeta SD" -# -"Press the knob" c=20 r=2 +# c=20 +"Press the knob" "Pulsa el dial" #MSG_PRINT_PAUSED c=20 r=1 @@ -1166,13 +1166,13 @@ "Total failures" "Fallos totales" -# -"to load filament" c=20 r=2 -"para cargar el filamento" +# c=20 +"to load filament" +"para cargar el fil." -# -"to unload filament" c=20 r=2 -"para descargar el filamento" +# c=20 +"to unload filament" +"para descargar fil." #MSG_UNLOAD_FILAMENT c=17 "Unload filament" diff --git a/lang/lang_en_fr.txt b/lang/lang_en_fr.txt index 54dc7a7cc..edf2bb8b4 100644 --- a/lang/lang_en_fr.txt +++ b/lang/lang_en_fr.txt @@ -858,8 +858,8 @@ "Print from SD" "Impr. depuis la SD" -# -"Press the knob" c=20 r=2 +# c=20 +"Press the knob" "App. sur sur bouton" #MSG_PRINT_PAUSED c=20 r=1 @@ -1166,12 +1166,12 @@ "Total failures" "Total des echecs" -# -"to load filament" c=20 r=2 +# c=20 +"to load filament" "pour charger le fil." -# -"to unload filament" c=20 r=2 +# c=20 +"to unload filament" "pour decharger fil." #MSG_UNLOAD_FILAMENT c=17 diff --git a/lang/lang_en_it.txt b/lang/lang_en_it.txt index d5846cba7..043d1141b 100644 --- a/lang/lang_en_it.txt +++ b/lang/lang_en_it.txt @@ -858,8 +858,8 @@ "Print from SD" "Stampa da SD" -# -"Press the knob" c=20 r=2 +# c=20 +"Press the knob" "Premere la manopola" #MSG_PRINT_PAUSED c=20 r=1 @@ -1166,13 +1166,13 @@ "Total failures" "Totale fallimenti" -# -"to load filament" c=20 r=2 -"per caricare il filamento" +# c=20 +"to load filament" +"per caricare il fil." -# -"to unload filament" c=20 r=2 -"per scaricare il filamento" +# c=20 +"to unload filament" +"per scaricare fil." #MSG_UNLOAD_FILAMENT c=17 "Unload filament" diff --git a/lang/lang_en_pl.txt b/lang/lang_en_pl.txt index eb4103eee..4e6be18e0 100644 --- a/lang/lang_en_pl.txt +++ b/lang/lang_en_pl.txt @@ -858,8 +858,8 @@ "Print from SD" "Druk z karty SD" -# -"Press the knob" c=20 r=2 +# c=20 +"Press the knob" "Wcisnij pokretlo" #MSG_PRINT_PAUSED c=20 r=1 @@ -1166,12 +1166,12 @@ "Total failures" "Suma bledow" -# -"to load filament" c=20 r=2 +# c=20 +"to load filament" "aby zaladow. fil." -# -"to unload filament" c=20 r=2 +# c=20 +"to unload filament" "aby rozlad. filament" #MSG_UNLOAD_FILAMENT c=17 From 5f49d65546a08d633ea452816718983f0a5a6acc Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Mon, 8 Feb 2021 09:49:11 +0100 Subject: [PATCH 57/58] Farmers' request - allow file sorting menu item --- Firmware/ultralcd.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index 0f6bc1fa3..d3686509a 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -5291,16 +5291,13 @@ do\ else\ MENU_ITEM_TOGGLE_P(_T(MSG_SD_CARD), _T(MSG_NORMAL), lcd_toshiba_flash_air_compatibility_toggle);\ \ - if (!farm_mode)\ + uint8_t sdSort;\ + EEPROM_read(EEPROM_SD_SORT, (uint8_t*)&sdSort, sizeof(sdSort));\ + switch (sdSort)\ {\ - uint8_t sdSort;\ - EEPROM_read(EEPROM_SD_SORT, (uint8_t*)&sdSort, sizeof(sdSort));\ - switch (sdSort)\ - {\ - case SD_SORT_TIME: MENU_ITEM_TOGGLE_P(_T(MSG_SORT), _T(MSG_SORT_TIME), lcd_sort_type_set); break;\ - case SD_SORT_ALPHA: MENU_ITEM_TOGGLE_P(_T(MSG_SORT), _T(MSG_SORT_ALPHA), lcd_sort_type_set); break;\ - default: MENU_ITEM_TOGGLE_P(_T(MSG_SORT), _T(MSG_NONE), lcd_sort_type_set);\ - }\ + case SD_SORT_TIME: MENU_ITEM_TOGGLE_P(_T(MSG_SORT), _T(MSG_SORT_TIME), lcd_sort_type_set); break;\ + case SD_SORT_ALPHA: MENU_ITEM_TOGGLE_P(_T(MSG_SORT), _T(MSG_SORT_ALPHA), lcd_sort_type_set); break;\ + default: MENU_ITEM_TOGGLE_P(_T(MSG_SORT), _T(MSG_NONE), lcd_sort_type_set);\ }\ }\ while (0) From 4fcbf95db65e33d4fa7ee561a510c8f79f2bdfd1 Mon Sep 17 00:00:00 2001 From: Alex Voinea Date: Tue, 9 Feb 2021 15:00:46 +0200 Subject: [PATCH 58/58] apply RAII principle on the lsDive recursion limiter --- Firmware/cardreader.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index c414e2823..3ca88f63c 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -71,14 +71,22 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) { static uint8_t recursionCnt = 0; + // RAII incrementer for the recursionCnt + class _incrementer + { + public: + _incrementer() {recursionCnt++;} + ~_incrementer() {recursionCnt--;} + } recursionCntIncrementer; + dir_t p; uint8_t cnt = 0; // Read the next entry from a directory while (parent.readDir(p, longFilename) > 0) { - if (recursionCnt >= MAX_DIR_DEPTH) + if (recursionCnt > MAX_DIR_DEPTH) return; else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint - recursionCnt++; + // Get the short name for the item, which we know is a folder char lfilename[FILENAME_LENGTH]; createFilename(lfilename, p); @@ -112,7 +120,6 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m if (lsAction == LS_SerialPrint_LFN) puts_P(PSTR("DIR_EXIT")); - recursionCnt--; } else { uint8_t pn0 = p.name[0];