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

New encoder logic with debouncing #26723

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5be8b4e
New encoder logic with debouncing
dbuezas Jan 23, 2024
6d6b163
Increase debouncing time to 3ms and fix unused variable warning
dbuezas Jan 26, 2024
c88345d
Add encoder reset mechanism to avoid off-by-one-step bug in Ender 3
dbuezas Jan 30, 2024
92c4c7d
Encoder reset timeout depends on steps per pulses. Reset may advance …
dbuezas Feb 2, 2024
2100d45
Advance encoder after a while if it has crossed the half a step thres…
dbuezas Feb 4, 2024
c9e0792
Revert "Advance encoder after a while if it has crossed the half a st…
dbuezas Feb 4, 2024
32fd50d
Revert "Encoder reset timeout depends on steps per pulses. Reset may …
dbuezas Feb 4, 2024
fc1d80b
Make RESET_ENCODER_AFTER_MS depend on ENCODER_PULSES_PER_STEP
dbuezas Feb 4, 2024
eaa43b3
Merge remote-tracking branch 'OriginalRepo/bugfix-2.1.x' into dbuezas…
dbuezas Feb 5, 2024
4073275
Compute abs_diff after step reset
dbuezas Feb 5, 2024
df74c62
Fix no screen wakeup if encoder has 1 pulse per step
dbuezas Feb 5, 2024
160c46d
misc. cleanup
thinkyhead Feb 7, 2024
f5b39d2
Test ignoring 2 steps jump.
dbuezas Feb 7, 2024
e18704b
Merge branch 'bugfix-2.1.x' into pr/26723
thinkyhead Feb 8, 2024
408aeba
merge followup
thinkyhead Feb 8, 2024
3d36ddc
Add missed step detection, remove BLOCK_CLICK_AFTER_MOVEMENT_MS and R…
dbuezas Feb 8, 2024
0a6ec33
Merge branch 'bugfix-2.1.x' into pr/26723
thinkyhead Feb 9, 2024
adff939
prettify
thinkyhead Feb 9, 2024
5a015dc
Adjust encoder multiplier
thinkyhead Feb 9, 2024
e67b68e
Move epps fallback
thinkyhead Feb 9, 2024
fa68359
some E3V2 encoder
thinkyhead Feb 9, 2024
b928eec
more E3V2
thinkyhead Feb 9, 2024
b6bd7e3
more more
thinkyhead Feb 9, 2024
a78a4b1
const
thinkyhead Feb 9, 2024
55853b2
Merge branch 'bugfix-2.1.x' into pr/26723
thinkyhead Feb 10, 2024
7657a28
index encoder bits
thinkyhead Feb 10, 2024
f625a8f
en_A, B
thinkyhead Feb 10, 2024
96f31fe
struct
thinkyhead Feb 10, 2024
04c8a86
lvgl encoder
thinkyhead Feb 10, 2024
71a9459
encoder style
thinkyhead Feb 10, 2024
3e4cbed
simplify lv
thinkyhead Feb 10, 2024
8a5c1be
clarify
thinkyhead Feb 10, 2024
bd0a74e
share 'get_encoder_delta'
thinkyhead Feb 11, 2024
3ff61dc
no pause EN1/2
thinkyhead Feb 11, 2024
e329cb6
use buttons.h
thinkyhead Feb 11, 2024
1ed1e91
const
thinkyhead Feb 11, 2024
98ba982
Merge remote-tracking branch 'upstream/bugfix-2.1.x' into pr/26723
thinkyhead Feb 27, 2024
fb6b08e
Use ui.get_encoder_delta in lv_update_encoder
thinkyhead Feb 28, 2024
ffb1c82
Clarify HAS_MARLINUI_ENCODER
thinkyhead Feb 28, 2024
0467ea4
unify button init
thinkyhead Feb 28, 2024
00b8733
combine ab debounce
thinkyhead Mar 10, 2024
49a49ac
Split up A-B debounce
thinkyhead Apr 14, 2024
5f84257
Merge branch 'bugfix-2.1.x' into pr/26723
thinkyhead Apr 14, 2024
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
29 changes: 19 additions & 10 deletions Marlin/src/inc/Conditionals_LCD.h
Original file line number Diff line number Diff line change
Expand Up @@ -893,10 +893,11 @@
#endif
#endif

// FSMC/SPI TFT Panels (LVGL)
// FSMC/SPI TFT Panels (LVGL) with encoder click wheel
#if ENABLED(TFT_LVGL_UI)
#define HAS_TFT_LVGL_UI 1
#define SERIAL_RUNTIME_HOOK 1
#define STD_ENCODER_PULSES_PER_STEP 4
#endif

// FSMC/SPI TFT Panels
Expand Down Expand Up @@ -976,6 +977,17 @@
#define DETECT_I2C_LCD_DEVICE 1
#endif

/**
* Ender-3 V2 DWIN with Encoder
*/
#if ANY(DWIN_CREALITY_LCD, DWIN_LCD_PROUI)
#define HAS_DWIN_E3V2_BASIC 1
#endif
#if ANY(HAS_DWIN_E3V2_BASIC, DWIN_CREALITY_LCD_JYERSUI)
#define HAS_DWIN_E3V2 1
#define STD_ENCODER_PULSES_PER_STEP 4
#endif

// Encoder behavior
#ifndef STD_ENCODER_PULSES_PER_STEP
#if ENABLED(TOUCH_SCREEN)
Expand All @@ -997,10 +1009,12 @@
#define ENCODER_FEEDRATE_DEADZONE 6
#endif

// Shift register panels
// ---------------------
// 2 wire Non-latching LCD SR from:
// https://github.com/fmalpartida/New-LiquidCrystal/wiki/schematics#user-content-ShiftRegister_connection
/**
* Shift register panels
* ---------------------
* 2 wire Non-latching LCD SR from:
* https://github.com/fmalpartida/New-LiquidCrystal/wiki/schematics#user-content-ShiftRegister_connection
*/
#if ENABLED(FF_INTERFACEBOARD)
#define SR_LCD_3W_NL // Non latching 3 wire shift register
#define IS_ULTIPANEL 1
Expand Down Expand Up @@ -1040,11 +1054,6 @@
#define EXTENSIBLE_UI
#endif

// Aliases for LCD features
#if ANY(DWIN_CREALITY_LCD, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI)
#define HAS_DWIN_E3V2 1
#endif

// E3V2 extras
#if HAS_DWIN_E3V2 || IS_DWIN_MARLINUI
#define SERIAL_CATCHALL 0
Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/lcd/buttons.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
#include "../inc/MarlinConfig.h"

#if ((!HAS_ADC_BUTTONS && IS_NEWPANEL) || BUTTONS_EXIST(EN1, EN2)) && !IS_TFTGLCD_PANEL
#define HAS_ENCODER_WHEEL 1
#define HAS_MARLINUI_ENCODER 1
#endif
#if (HAS_ENCODER_WHEEL || ANY_BUTTON(ENC, BACK, UP, DOWN, LEFT, RIGHT)) && DISABLED(TOUCH_UI_FTDI_EVE)
#if (HAS_MARLINUI_ENCODER || ANY_BUTTON(ENC, BACK, UP, DOWN, LEFT, RIGHT)) && DISABLED(TOUCH_UI_FTDI_EVE)
#define HAS_DIGITAL_BUTTONS 1
#endif
#if !HAS_ADC_BUTTONS && (IS_RRW_KEYPAD || (HAS_WIRED_LCD && !IS_NEWPANEL))
Expand Down
96 changes: 24 additions & 72 deletions Marlin/src/lcd/e3v2/common/encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,43 +42,19 @@

#include <stdlib.h>

#ifndef ENCODER_PULSES_PER_STEP
#define ENCODER_PULSES_PER_STEP 4
#endif

EncoderRate encoderRate;

// TODO: Replace with ui.quick_feedback
void Encoder_tick() {
TERN_(HAS_BEEPER, if (ui.sound_on) buzzer.click(10));
}

// Encoder initialization
void encoderConfiguration() {
#if BUTTON_EXISTS(EN1)
SET_INPUT_PULLUP(BTN_EN1);
#endif
#if BUTTON_EXISTS(EN2)
SET_INPUT_PULLUP(BTN_EN2);
#endif
#if BUTTON_EXISTS(ENC)
SET_INPUT_PULLUP(BTN_ENC);
#endif
#if HAS_BEEPER
SET_OUTPUT(BEEPER_PIN); // TODO: Use buzzer.h which already inits this
#endif
}

// Analyze encoder value and return state
EncoderState encoderReceiveAnalyze() {
const millis_t now = millis();
static uint8_t lastEncoderBits;
uint8_t newbutton = 0;
static signed char temp_diff = 0;
static int8_t temp_diff = 0; // Cleared on each full step, as configured

EncoderState temp_diffState = ENCODER_DIFF_NO;
if (BUTTON_PRESSED(EN1)) newbutton |= EN_A;
if (BUTTON_PRESSED(EN2)) newbutton |= EN_B;
if (BUTTON_PRESSED(ENC)) {
static millis_t next_click_update_ms;
if (ELAPSED(now, next_click_update_ms)) {
Expand All @@ -98,71 +74,47 @@ EncoderState encoderReceiveAnalyze() {
}
else return ENCODER_DIFF_NO;
}
if (newbutton != lastEncoderBits) {
switch (newbutton) {
case 0:
if (lastEncoderBits == 1) temp_diff++;
else if (lastEncoderBits == 2) temp_diff--;
break;
case 2:
if (lastEncoderBits == 0) temp_diff++;
else if (lastEncoderBits == 3) temp_diff--;
break;
case 3:
if (lastEncoderBits == 2) temp_diff++;
else if (lastEncoderBits == 1) temp_diff--;
break;
case 1:
if (lastEncoderBits == 3) temp_diff++;
else if (lastEncoderBits == 0) temp_diff--;
break;
}
lastEncoderBits = newbutton;
}

if (ABS(temp_diff) >= ENCODER_PULSES_PER_STEP) {
if (temp_diff > 0) temp_diffState = TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CCW, ENCODER_DIFF_CW);
else temp_diffState = TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CW, ENCODER_DIFF_CCW);
temp_diff += ui.get_encoder_delta();

const int8_t abs_diff = ABS(temp_diff);
if (abs_diff >= ENCODER_PULSES_PER_STEP) {
temp_diffState = temp_diff > 0
? TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CCW, ENCODER_DIFF_CW)
: TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CW, ENCODER_DIFF_CCW);

int32_t encoder_multiplier = 1;

#if ENABLED(ENCODER_RATE_MULTIPLIER)

millis_t ms = millis();
int32_t encoder_multiplier = 1;
const millis_t ms = millis();

// if must encoder rati multiplier
// Encoder rate multiplier
if (encoderRate.enabled) {
const float abs_diff = ABS(temp_diff),
encoderMovementSteps = abs_diff / (ENCODER_PULSES_PER_STEP);
if (encoderRate.lastEncoderTime) {
// Note that the rate is always calculated between two passes through the
// loop and that the abs of the temp_diff value is tracked.
const float encoderStepRate = encoderMovementSteps / float(ms - encoderRate.lastEncoderTime) * 1000;
if (ENCODER_100X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_100X_STEPS_PER_SEC)
encoder_multiplier = 100;
else if (ENCODER_10X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_10X_STEPS_PER_SEC)
encoder_multiplier = 10;
else if (ENCODER_5X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_5X_STEPS_PER_SEC)
encoder_multiplier = 5;
}
// Note that the rate is always calculated between two passes through the
// loop and that the abs of the temp_diff value is tracked.
const float encoderStepRate = ((float(abs_diff) / float(ENCODER_PULSES_PER_STEP)) * 1000.0f) / float(ms - encoderRate.lastEncoderTime);
encoderRate.lastEncoderTime = ms;
if (ENCODER_100X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_100X_STEPS_PER_SEC)
encoder_multiplier = 100;
else if (ENCODER_10X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_10X_STEPS_PER_SEC)
encoder_multiplier = 10;
else if (ENCODER_5X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_5X_STEPS_PER_SEC)
encoder_multiplier = 5;
}

#else

constexpr int32_t encoder_multiplier = 1;

#endif

// encoderRate.encoderMoveValue += (temp_diff * encoder_multiplier) / (ENCODER_PULSES_PER_STEP);
encoderRate.encoderMoveValue = (temp_diff * encoder_multiplier) / (ENCODER_PULSES_PER_STEP);
if (encoderRate.encoderMoveValue < 0) encoderRate.encoderMoveValue = -encoderRate.encoderMoveValue;
encoderRate.encoderMoveValue = abs_diff * encoder_multiplier / (ENCODER_PULSES_PER_STEP);

temp_diff = 0;
}

if (temp_diffState != ENCODER_DIFF_NO) {
TERN_(HAS_BACKLIGHT_TIMEOUT, ui.refresh_backlight_timeout());
if (!ui.backlight) ui.refresh_brightness();
}

return temp_diffState;
}

Expand Down
3 changes: 0 additions & 3 deletions Marlin/src/lcd/e3v2/common/encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ typedef enum {

#define ENCODER_WAIT_MS TERN(DWIN_LCD_PROUI, 10, 20)

// Encoder initialization
void encoderConfiguration();

// Analyze encoder value and return state
EncoderState encoderReceiveAnalyze();

Expand Down
1 change: 0 additions & 1 deletion Marlin/src/lcd/e3v2/creality/dwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4078,7 +4078,6 @@ void hmiInit() {
}

void dwinInitScreen() {
encoderConfiguration();
hmiInit();
hmiSetLanguageCache();
hmiStartFrame(true);
Expand Down
1 change: 0 additions & 1 deletion Marlin/src/lcd/e3v2/jyersui/dwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5143,7 +5143,6 @@ void MarlinUI::init_lcd() {
if (dwinHandshake()) SERIAL_ECHOLNPGM("ok."); else SERIAL_ECHOLNPGM("error.");
dwinFrameSetDir(1); // Orientation 90°
dwinUpdateLCD(); // Show bootscreen (first image)
encoderConfiguration();
for (uint16_t t = 0; t <= 100; t += 2) {
dwinIconShow(ICON, ICON_Bar, 15, 260);
dwinDrawRectangle(1, COLOR_BG_BLACK, 15 + t * 242 / 100, 260, 257, 280);
Expand Down
1 change: 0 additions & 1 deletion Marlin/src/lcd/e3v2/proui/dwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1909,7 +1909,6 @@ void MarlinUI::init_lcd() {
const bool hs = dwinHandshake(); UNUSED(hs);
dwinFrameSetDir(1);
dwinJPGCacheTo1(Language_English);
encoderConfiguration();
}

void dwinInitScreen() {
Expand Down
113 changes: 30 additions & 83 deletions Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ void tft_lvgl_init() {

tft_style_init();
filament_pin_setup();
lv_encoder_pin_init();

#if ENABLED(MKS_WIFI_MODULE)
mks_esp_wifi_init();
Expand Down Expand Up @@ -331,12 +330,12 @@ bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data) {
}

int16_t enc_diff = 0;
lv_indev_state_t state = LV_INDEV_STATE_REL;
lv_indev_state_t indev_enc_state = LV_INDEV_STATE_REL; // ENC button is pressed or released

bool my_mousewheel_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) {
(void) indev_drv; // Unused
UNUSED(indev_drv);

data->state = state;
data->state = indev_enc_state;
data->enc_diff = enc_diff;
enc_diff = 0;

Expand Down Expand Up @@ -446,101 +445,49 @@ lv_fs_res_t sd_tell_cb(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) {
return LV_FS_RES_OK;
}

void lv_encoder_pin_init() {
#if BUTTON_EXISTS(EN1)
SET_INPUT_PULLUP(BTN_EN1);
void lv_update_encoder() {

#if ANY_BUTTON(EN1, EN2)
constexpr uint8_t epps = ENCODER_PULSES_PER_STEP; // We can fill in
static uint8_t pulse_count;
pulse_count += ui.get_encoder_delta();
const int8_t fullSteps = pulse_count / epps;
pulse_count -= fullSteps * epps;
enc_diff += fullSteps;
#endif
#if BUTTON_EXISTS(EN2)
SET_INPUT_PULLUP(BTN_EN2);

#if ANY_BUTTON(ENC, BACK, UP, DOWN, LEFT, RIGHT)
static millis_t last_encoder_ms;
const millis_t now = millis(), diffTime = getTickDiff(now, last_encoder_ms);
if (diffTime <= 50) return;
#endif

#if BUTTON_EXISTS(ENC)
SET_INPUT_PULLUP(BTN_ENC);
static uint8_t old_button_enc = LV_INDEV_STATE_REL;
const uint8_t enc_c = BUTTON_PRESSED(ENC) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
if (enc_c != old_button_enc) {
indev_enc_state = enc_c ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
old_button_enc = enc_c;
}
#endif

#if BUTTON_EXISTS(BACK)
SET_INPUT_PULLUP(BTN_BACK);
if (BUTTON_PRESSED(BACK)) {}
#endif

#if BUTTON_EXISTS(UP)
SET_INPUT(BTN_UP);
if (BUTTON_PRESSED(UP)) {}
#endif
#if BUTTON_EXISTS(DOWN)
SET_INPUT(BTN_DOWN);
if (BUTTON_PRESSED(DOWN)) {}
#endif
#if BUTTON_EXISTS(LEFT)
SET_INPUT(BTN_LEFT);
if (BUTTON_PRESSED(LEFT)) {}
#endif
#if BUTTON_EXISTS(RIGHT)
SET_INPUT(BTN_RIGHT);
if (BUTTON_PRESSED(RIGHT)) {}
#endif
}

#if 1 // HAS_ENCODER_ACTION

void lv_update_encoder() {
static uint32_t encoder_time1;
uint32_t tmpTime, diffTime = 0;
tmpTime = millis();
diffTime = getTickDiff(tmpTime, encoder_time1);
if (diffTime > 50) {

#if HAS_ENCODER_WHEEL

#if ANY_BUTTON(EN1, EN2, ENC, BACK)

uint8_t newbutton = 0;
if (BUTTON_PRESSED(EN1)) newbutton |= EN_A;
if (BUTTON_PRESSED(EN2)) newbutton |= EN_B;
if (BUTTON_PRESSED(ENC)) newbutton |= EN_C;
if (BUTTON_PRESSED(BACK)) newbutton |= EN_D;

#else

constexpr uint8_t newbutton = 0;

#endif

static uint8_t buttons = 0;
buttons = newbutton;
static uint8_t lastEncoderBits;

#define encrot0 0
#define encrot1 1
#define encrot2 2

uint8_t enc = 0;
if (buttons & EN_A) enc |= B01;
if (buttons & EN_B) enc |= B10;
if (enc != lastEncoderBits) {
switch (enc) {
case encrot1:
if (lastEncoderBits == encrot0) {
enc_diff--;
encoder_time1 = tmpTime;
}
break;
case encrot2:
if (lastEncoderBits == encrot0) {
enc_diff++;
encoder_time1 = tmpTime;
}
break;
}
lastEncoderBits = enc;
}
static uint8_t last_button_state = LV_INDEV_STATE_REL;
const uint8_t enc_c = (buttons & EN_C) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
if (enc_c != last_button_state) {
state = enc_c ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
last_button_state = enc_c;
}

#endif // HAS_ENCODER_WHEEL

} // encoder_time1
}

#endif // HAS_ENCODER_ACTION
}

#ifdef __PLAT_NATIVE_SIM__
#include <lv_misc/lv_log.h>
Expand Down
Loading
Loading