Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reprapworld Keypad: Prevent key-mashing issues? #3957

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 74 additions & 27 deletions Marlin/ultralcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include "printcounter.h"
#endif

char conv[9]; // for converted numbers

int preheatHotendTemp1, preheatBedTemp1, preheatFanSpeed1,
preheatHotendTemp2, preheatBedTemp2, preheatFanSpeed2;

Expand Down Expand Up @@ -321,9 +323,6 @@ uint8_t lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW; // Set when the LCD needs to
UNUSED(_skipStatic)

#if ENABLED(ENCODER_RATE_MULTIPLIER)

//#define ENCODER_RATE_MULTIPLIER_DEBUG // If defined, output the encoder steps per second value

/**
* MENU_MULTIPLIER_ITEM generates drawing and handling code for a multiplier menu item
*/
Expand All @@ -333,8 +332,7 @@ uint8_t lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW; // Set when the LCD needs to
lastEncoderMovementMillis = 0; \
_MENU_ITEM_PART_2(type, ## args); \
} while(0)

#endif //ENCODER_RATE_MULTIPLIER
#endif // ENCODER_RATE_MULTIPLIER

#define MENU_ITEM_DUMMY() do { _thisItemNr++; } while(0)
#define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, PSTR(label), ## args)
Expand Down Expand Up @@ -2311,21 +2309,57 @@ void kill_screen(const char* lcd_msg) {
*
*/
#if ENABLED(REPRAPWORLD_KEYPAD)

#define KEY_REPEAT_DELAY 250
#define KEY_REPEAT_SLOW 100
#define KEY_REPEAT_FAST 10
#define KEY_REPEAT_FACTOR 0.95
#define KEY_MOVE_FIRST 1
#define KEY_MOVE_OTHER 0.1

static void _reprapworld_keypad_move(AxisEnum axis, int dir) {
move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP;
encoderPosition = dir;
switch (axis) {
case X_AXIS: lcd_move_x(); break;
case Y_AXIS: lcd_move_y(); break;
case Z_AXIS: lcd_move_z();
static bool no_reentry = false;
if (no_reentry) return;
millis_t next_move_ms = millis(), repeat_ms = KEY_REPEAT_DELAY;
move_menu_scale = KEY_MOVE_FIRST; // first move is larger
no_reentry = true;
SERIAL_ECHOLNPGM("Enter Keypad Loop");
while (REPRAPWORLD_KEYPAD_PRESSED) {
millis_t now = millis();
if (ELAPSED(now, next_move_ms)) {

encoderPosition = dir; // move by -1 or 1
switch (axis) { // on a single axis
case X_AXIS: lcd_move_x(); break;
case Y_AXIS: lcd_move_y(); break;
case Z_AXIS: lcd_move_z();
}

manual_move_start_time = now; // move now
manage_manual_move();

SERIAL_ECHOPAIR("Keypad Loop, delay ", repeat_ms);
SERIAL_EOL;

next_move_ms = now + repeat_ms; // next move after current interval
if (repeat_ms == KEY_REPEAT_DELAY) { // at the initial interval?
move_menu_scale = KEY_MOVE_OTHER; // move in smaller increments
repeat_ms = KEY_REPEAT_SLOW; // 10 times per second to start
}
else if (repeat_ms > KEY_REPEAT_FAST) // above speed threshold?
repeat_ms *= KEY_REPEAT_FACTOR; // keep shortening the interval
}
idle();
}
SERIAL_ECHOLNPGM("Exit Keypad Loop");
no_reentry = false;
}
static void reprapworld_keypad_move_z_up() { _reprapworld_keypad_move(Z_AXIS, 1); }
static void reprapworld_keypad_move_z_down() { _reprapworld_keypad_move(Z_AXIS, -1); }
static void reprapworld_keypad_move_x_left() { _reprapworld_keypad_move(X_AXIS, -1); }
static void reprapworld_keypad_move_x_right() { _reprapworld_keypad_move(X_AXIS, 1); }
static void reprapworld_keypad_move_y_up() { _reprapworld_keypad_move(Y_AXIS, -1); }
static void reprapworld_keypad_move_y_down() { _reprapworld_keypad_move(Y_AXIS, 1); }
static void reprapworld_keypad_move_y_fwd() { _reprapworld_keypad_move(Y_AXIS, -1); }
static void reprapworld_keypad_move_y_back() { _reprapworld_keypad_move(Y_AXIS, 1); }
static void reprapworld_keypad_move_home() { enqueue_and_echo_commands_P(PSTR("G28")); } // move all axes home and wait
static void reprapworld_keypad_move_menu() { lcd_goto_screen(lcd_move_menu); }
#endif // REPRAPWORLD_KEYPAD
Expand Down Expand Up @@ -2589,11 +2623,17 @@ void lcd_update() {
static uint8_t keypad_debounce = 0;

if (!REPRAPWORLD_KEYPAD_PRESSED) {
if (keypad_debounce > 0) keypad_debounce--;
if (keypad_debounce > 0) {
SERIAL_ECHOPAIR("Keypad Debouncing ", keypad_debounce);
SERIAL_EOL;
keypad_debounce--;
}
}
else if (!keypad_debounce) {
keypad_debounce = 2;

SERIAL_ECHOLNPGM("Keypad Initial Press");

if (REPRAPWORLD_KEYPAD_MOVE_MENU) reprapworld_keypad_move_menu();

#if DISABLED(DELTA) && Z_HOME_DIR == -1
Expand All @@ -2607,8 +2647,8 @@ void lcd_update() {
if (REPRAPWORLD_KEYPAD_MOVE_Z_DOWN) reprapworld_keypad_move_z_down();
if (REPRAPWORLD_KEYPAD_MOVE_X_LEFT) reprapworld_keypad_move_x_left();
if (REPRAPWORLD_KEYPAD_MOVE_X_RIGHT) reprapworld_keypad_move_x_right();
if (REPRAPWORLD_KEYPAD_MOVE_Y_DOWN) reprapworld_keypad_move_y_down();
if (REPRAPWORLD_KEYPAD_MOVE_Y_UP) reprapworld_keypad_move_y_up();
if (REPRAPWORLD_KEYPAD_MOVE_Y_FWD) reprapworld_keypad_move_y_fwd();
if (REPRAPWORLD_KEYPAD_MOVE_Y_BACK) reprapworld_keypad_move_y_back();
}
else {
if (REPRAPWORLD_KEYPAD_MOVE_HOME) reprapworld_keypad_move_home();
Expand All @@ -2633,15 +2673,6 @@ void lcd_update() {

if (encoderStepRate >= ENCODER_100X_STEPS_PER_SEC) encoderMultiplier = 100;
else if (encoderStepRate >= ENCODER_10X_STEPS_PER_SEC) encoderMultiplier = 10;

#if ENABLED(ENCODER_RATE_MULTIPLIER_DEBUG)
SERIAL_ECHO_START;
SERIAL_ECHOPAIR("Enc Step Rate: ", encoderStepRate);
SERIAL_ECHOPAIR(" Multiplier: ", encoderMultiplier);
SERIAL_ECHOPAIR(" ENCODER_10X_STEPS_PER_SEC: ", ENCODER_10X_STEPS_PER_SEC);
SERIAL_ECHOPAIR(" ENCODER_100X_STEPS_PER_SEC: ", ENCODER_100X_STEPS_PER_SEC);
SERIAL_EOL;
#endif //ENCODER_RATE_MULTIPLIER_DEBUG
}

lastEncoderMovementMillis = ms;
Expand Down Expand Up @@ -2822,6 +2853,18 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
DST = ~new_##DST; //invert it, because a pressed switch produces a logical 0


// Make a hex string for debugging
char *to_hex(unsigned long value, uint8_t digits=4) {
const char *hex_digits = "0123456789ABCDEF";
digits = constrain(digits, 2, 8);
conv[digits] = '\0';
while (digits--) {
conv[digits] = hex_digits[value & 0xF];
value >>= 4;
}
return conv;
}

/**
* Read encoder buttons from the hardware registers
* Warning: This function is called from interrupt context!
Expand Down Expand Up @@ -2881,6 +2924,12 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
#endif
#if ENABLED(REPRAPWORLD_KEYPAD)
GET_BUTTON_STATES(buttons_reprapworld_keypad);
static uint8_t old_buttons_reprapworld_keypad = 0;
if (old_buttons_reprapworld_keypad != buttons_reprapworld_keypad) {
old_buttons_reprapworld_keypad = buttons_reprapworld_keypad;
SERIAL_ECHOPAIR("Keypad Bits: 0x", to_hex(buttons_reprapworld_keypad, 2));
SERIAL_EOL;
}
#endif
#else
GET_BUTTON_STATES(buttons);
Expand Down Expand Up @@ -2935,8 +2984,6 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
#define DIGIT(n) ('0' + (n))
#define DIGIMOD(n) DIGIT((n) % 10)

char conv[8];

// Convert float to rj string with 123 or -12 format
char *ftostr3(const float& x) { return itostr3((int)x); }

Expand Down
42 changes: 22 additions & 20 deletions Marlin/ultralcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,33 +106,35 @@
#define BLEN_REPRAPWORLD_KEYPAD_UP 6
#define BLEN_REPRAPWORLD_KEYPAD_LEFT 7

#define EN_REPRAPWORLD_KEYPAD_F3 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F3))
#define EN_REPRAPWORLD_KEYPAD_F2 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F2))
#define EN_REPRAPWORLD_KEYPAD_F1 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F1))
#define EN_REPRAPWORLD_KEYPAD_DOWN (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_DOWN))
#define EN_REPRAPWORLD_KEYPAD_RIGHT (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_RIGHT))
#define EN_REPRAPWORLD_KEYPAD_MIDDLE (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_MIDDLE))
#define EN_REPRAPWORLD_KEYPAD_UP (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_UP))
#define EN_REPRAPWORLD_KEYPAD_LEFT (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_LEFT))

#define REPRAPWORLD_KEYPAD_MOVE_Z_DOWN (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_F3)
#define REPRAPWORLD_KEYPAD_MOVE_Z_UP (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_F2)
#define REPRAPWORLD_KEYPAD_MOVE_MENU (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_F1)
#define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_DOWN)
#define REPRAPWORLD_KEYPAD_MOVE_X_RIGHT (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_RIGHT)
#define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_MIDDLE)
#define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_UP)
#define REPRAPWORLD_KEYPAD_MOVE_X_LEFT (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_LEFT)

#define REPRAPWORLD_KEYPAD_PRESSED (buttons_reprapworld_keypad & ( \
#define _KEYPAD_BIT(I) (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_## I))
#define EN_REPRAPWORLD_KEYPAD_F3 (_KEYPAD_BIT(F3))
#define EN_REPRAPWORLD_KEYPAD_F2 (_KEYPAD_BIT(F2))
#define EN_REPRAPWORLD_KEYPAD_F1 (_KEYPAD_BIT(F1))
#define EN_REPRAPWORLD_KEYPAD_LEFT (_KEYPAD_BIT(LEFT))
#define EN_REPRAPWORLD_KEYPAD_RIGHT (_KEYPAD_BIT(RIGHT))
#define EN_REPRAPWORLD_KEYPAD_UP (_KEYPAD_BIT(UP))
#define EN_REPRAPWORLD_KEYPAD_DOWN (_KEYPAD_BIT(DOWN))
#define EN_REPRAPWORLD_KEYPAD_MIDDLE (_KEYPAD_BIT(MIDDLE))

#define _KEYPAD_TEST(B) (buttons_reprapworld_keypad & (B))
#define REPRAPWORLD_KEYPAD_MOVE_Z_DOWN (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_F3))
#define REPRAPWORLD_KEYPAD_MOVE_Z_UP (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_F2))
#define REPRAPWORLD_KEYPAD_MOVE_MENU (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_F1))
#define REPRAPWORLD_KEYPAD_MOVE_X_LEFT (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_LEFT))
#define REPRAPWORLD_KEYPAD_MOVE_X_RIGHT (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_RIGHT))
#define REPRAPWORLD_KEYPAD_MOVE_Y_FWD (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_UP))
#define REPRAPWORLD_KEYPAD_MOVE_Y_BACK (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_DOWN))
#define REPRAPWORLD_KEYPAD_MOVE_HOME (_KEYPAD_TEST(EN_REPRAPWORLD_KEYPAD_MIDDLE))

#define REPRAPWORLD_KEYPAD_PRESSED _KEYPAD_TEST( \
EN_REPRAPWORLD_KEYPAD_F3 | \
EN_REPRAPWORLD_KEYPAD_F2 | \
EN_REPRAPWORLD_KEYPAD_F1 | \
EN_REPRAPWORLD_KEYPAD_DOWN | \
EN_REPRAPWORLD_KEYPAD_RIGHT | \
EN_REPRAPWORLD_KEYPAD_MIDDLE | \
EN_REPRAPWORLD_KEYPAD_UP | \
EN_REPRAPWORLD_KEYPAD_LEFT) \
EN_REPRAPWORLD_KEYPAD_LEFT \
)

#endif // REPRAPWORLD_KEYPAD
Expand Down