update button logic

This commit is contained in:
fsender
2025-04-08 01:24:09 +08:00
parent f1a61272a9
commit 742e3ca1bc
3 changed files with 98 additions and 53 deletions

View File

@@ -40,51 +40,63 @@
#include "readguy.h" //包含readguy_driver 基础驱动库
ReadguyDriver guy;//新建一个readguy对象, 用于显示驱动.
int c=1;
void setup(){
Serial.begin(115200); //初始化串口
guy.init(); //初始化readguy_driver 基础驱动库. 尽管初始化过程会刷屏, 但此示例不会用到屏幕.
//if(guy.width()<guy.height()) guy.setRotation(1); //横向
if(guy.width()<200) guy.setRotation(1); //对于小屏幕, 设置横向
c = guy.getButtonsCount(); //此函数用于返回设备有多少个按键.
Serial.println(F("[readguy] Button demo")); //显示文本 默认是不支持中文显示的.
guy.println("Button demo"); //显示文本 默认是不支持中文显示的.
guy.println(F("Button demo."));
guy.println(F("Press the buttons in any way!"));
guy.println(F("Information will show"));
guy.println(F("on the EPD display."));
guy.println();
guy.print(F("Your device supports "));
guy.printf_P(PSTR("%d button%c.\r\n"),c,c==1?' ':'s'); //显示文本
guy.display();//刷新墨水屏.
guy.setButtonSpecial(true);//对于三按键系统,打开此模式将会允许双击进行特殊操作(如切换键盘)
//guy.setButtonSpecial(true); //对于拨轮, 无法做到按住按钮1按下按钮2
}
void loop(){
int val = guy.getBtn(); //此函数用于获取按键状态 没有按键按下时 返回0.
auto val = guy.getBtn(); //此函数用于获取按键状态 没有按键按下时 返回0.
if(val>0){
int c = guy.getButtonsCount(); //此函数用于返回设备有多少个按键. [最近更新的函数]
if(val!=guyBNone){
guy.fillRect(0,guy.height()-10, guy.width(),10,1);
guy.setCursor(2,guy.height()-10);
switch (val){
case 1: //下一个 手势
if(c==1) guy.println("key single clicked!");
else if(c==2) guy.println("Left key clicked!");
else if(c==3) guy.println("Right key clicked!");
case guyBNext: //下一个 手势
if(c==1) guy.println(F("key single clicked!"));
else if(c==2) guy.println(F("Left key clicked!"));
else if(c==3) guy.println(F("Right key clicked!"));
break;
case 2: //上一个 手势
if(c==1) guy.println("key long pressed!");
else if(c==2) guy.println("Left key long pressed!");
else if(c==3) guy.println("Left key clicked!");
case guyBPrev: //上一个 手势
if(c==1) guy.println(F("key long pressed!"));
else if(c==2) guy.println(F("Left key long pressed!"));
else if(c==3) guy.println(F("Left key clicked!"));
break;
case 3: //特殊 手势
if(c==1) guy.println("key clicked and pressed!");
else if(c==2) guy.println("Right clicked at left pressing!");
else if(c==3) guy.println("Centre key double clicked!");
case guyBSpecial: //特殊 手势
if(c==1) guy.println(F("key clicked and pressed!"));
else if(c==2) guy.println(F("Right clicked at left pressing!"));
else if(c==3) guy.println(F("Centre key double clicked!"));
break;
case 4: //确定 手势
if(c==1) guy.println("key double clicked!");
else if(c==2) guy.println("Right key clicked!");
else if(c==3) guy.println("Centre key clicked!");
case guyBOK: //确定 手势
if(c==1) guy.println(F("key double clicked!"));
else if(c==2) guy.println(F("Right key clicked!"));
else if(c==3) guy.println(F("Centre key clicked!"));
break;
case 8: //返回 手势
if(c==1) guy.println("key triple clicked!");
else if(c==2) guy.println("Right key long pressed!");
else if(c==3) guy.println("Centre key long pressed!");
case guyBCancel: //返回 手势
if(c==1) guy.println(F("key triple clicked!"));
else if(c==2) guy.println(F("Right key long pressed!"));
else if(c==3) guy.println(F("Centre key long pressed!"));
break;
default: //未知手势
guy.println(F("Unknown gesture!"));
break;
}
guy.display();
guy.scroll(0,-8);
}
delay(10);
}/* END OF FILE. ReadGuy project.

View File

@@ -509,11 +509,13 @@ void ReadguyDriver::setButtonDriver(){
btn_rd[1].setLongRepeatMode(0); //双按键 确定按键 设置为不允许连按
}
else if(READGUY_buttons==3){
btn_rd[0].long_press_ms = 20; //只有长按, 按一下也是长按,
//btn_rd[0].long_press_ms = 20; //只有长按, 按一下也是长按, 2025/4/7更新: 优化识别逻辑, 这样不会变慢了
btn_rd[0].double_press_ms = 20; //不识别双击三击,
btn_rd[0].setLongRepeatMode(1); //并且开启连按
//2024/2/25更新:需要支持连按适配拨轮
btn_rd[1].enScanDT(1); //识别双击或三击(默认) 2025/3/12更新:默认开启识别, 但按下确定键的响应会稍微变慢
//2025/3/12更新:默认开启识别, 但按下确定键的响应会稍微变慢
//2025/4/7更新: 优化识别逻辑, 这样不会变慢了
btn_rd[1].enScanDT(0); //识别双击或三击(默认)
btn_rd[1].setLongRepeatMode(0); //三按键 确定按键 设置为不允许连按
btn_rd[2].long_press_ms = 20; //只有长按, 按一下也是长按, 并且开启连按
btn_rd[2].double_press_ms = 20; //不识别双击三击,
@@ -908,28 +910,32 @@ void ReadguyDriver::nvs_write(){
uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
static unsigned long last=0;
static unsigned long last2=0;
uint8_t res1,res2,res3,res4=0;
switch(READGUY_buttons){
case 1:
uint8_t res1,res2,res3=0,res4=0;
if(READGUY_buttons == 1){
res1=btn_rd[0].read();
if(res1 == 1) res4 |= 1; //点按
else if(res1 == 2) res4 |= 4; //双击-确定
else if(res1 == 3) res4 |= 8; //三击-返回
else if(res1 == 4) res4 |= 2; //长按-向上翻页
else if(res1 == 5) res4 |= 3; //单击后长按-新增操作(可以连按)
break;
case 2:
else if(res1 == 5) res4 |= 16; //单击后长按-新增操作(可以连按)
}
else{ // case 2: //3
res1=btn_rd[0].read(); //选项上下键 两个按钮引脚都读取
res2=btn_rd[1].read(); //确定/返回键
if(READGUY_buttons>=3) res3=btn_rd[2].read(); //确定/返回键
//#if 1
{
bool newval=btn_rd[0].isPressedRaw();
if(newval && last2) last2=0;
else if(!(newval || last2)) last2=millis(); //捕获按钮松开的行为
if(res1 && (millis()-last>=btn_rd[1].long_press_ms) && (!btn_rd[1].isPressedRaw())){
//Serial.printf("[%9d] res 1 state: %d %d\n",millis(),longpresstest,pressedRawtest);
res4 = (res1 == 1)?1:2; //左键点按-向下翻页
bool newval=btn_rd[0].isPressedRaw();
if(newval && last2>1) last2=0;
else if(!(newval || last2>1)) last2=millis(); //捕获按钮松开的行为
//if(newval && btn_rd[1].isPressedRaw()) last2 = 1;
if((res1||res3) && (millis()-last>=btn_rd[1].long_press_ms) && (!btn_rd[1].isPressedRaw())){
//Serial.printf("[%9d] res 1 state: %d %d\n",millis(),longpresstest,pressedRawtest);
if(READGUY_buttons>=3) {
if(res1) res4 |= 2; //点按
else if(res3) res4 |= 1; //点按
}
else res4 = (res1 == 1)?1:2; //左键点按-向下翻页
if(last2 == 1) res4 = 0;//本次触发过3事件
}
//#endif
/*
@@ -939,7 +945,7 @@ uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
last=nowm;
}
if(res2) {
if(btn_rd[0].isPressedRaw()) res4 |= 3; //避免GCC警告(我常年喜欢-Werror=all
if(btn_rd[0].isPressedRaw()) res4 |= 16; //避免GCC警告(我常年喜欢-Werror=all
else if(res2 == 1 && nowm>last) res4 |= 4; //右键点按-确定
else if(res2 == 4 && nowm>last) res4 |= 8; //右键长按-返回
last=nowm;
@@ -948,14 +954,17 @@ uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
if(res2) {
unsigned long ts=millis();
//Serial.printf("[%9lu] now last2: %lu, threshold %lu\n",ts,last2,ts-last2);
if(btn_rd[0].isPressedRaw() || ts-last2<=20) { //2024.2.25新增: 20毫秒的去抖时间 防误判
res4 |= 3; //避免GCC警告(我常年喜欢-Werror=all
if(newval || ts-last2<=20) { //2024.2.25新增: 20毫秒的去抖时间 防误判
res4 |= 16; //避免GCC警告(我常年喜欢-Werror=all
last2 = 1;
}
else if(res2 == 1) res4 |= 4; //右键点按-确定
else if(res2 == 2) res4 |= 16; //新增: 双击进入操作5
else if(res2 == 4) res4 |= 8; //右键长按-返回
last=ts;
}
if(res4==5 || res4==6) res4=3;
if(res4==5 || res4==6) res4=16;
#if 0
break;
case 3:
res1=btn_rd[0].read();
@@ -966,11 +975,22 @@ uint8_t ReadguyDriver::getBtn_impl(){ //按钮不可用, 返回0.
res4 |= ((btn_rd[0].isPressedRaw()<<1)|1);
last=millis();
}
//if(res3 && ((millis()-last)<btn_rd[0].long_repeat_ms)) res4 |=3;
if(res2 == 1) res4 |= 4;
else if(res2 == 4) res4 |= 8;
else if(res2 == 2) res4 |= 3; //新增: 双击进入操作5
//if((res2||res3) && ((millis()-last)<btn_rd[0].long_repeat_ms)) res4 |=3;
if(res2) {
unsigned long ts=millis();
//Serial.printf("[%9lu] now last2: %lu, threshold %lu\n",ts,last2,ts-last2);
if(btn_rd[0].isPressedRaw() || ts-last2<=20) { //2024.2.25新增: 20毫秒的去抖时间 防误判
res4 |= 16; //避免GCC警告(我常年喜欢-Werror=all
}
else if(res2 == 1) res4 |= 4; //右键点按-确定
else if(res2 == 4) res4 |= 8; //右键长按-返回
last=ts;
}
//if(res2 == 1) res4 |= 4;
//else if(res2 == 4) res4 |= 8;
//else if((res2 == 2) || ) res4 |= 16; //新增: 双击进入操作5
break;
#endif
}
return res4;
}

View File

@@ -202,6 +202,19 @@
#define RG_IL_CONEXP inline
#endif
enum ReadguyButtonGesture: uint8_t{
guyBNone =0,
guyBNext =1,
guyBRight =1,
guyBPrev =2,
guyBLeft =2,
guyBSelect =4,
guyBOK =4,
guyBCancel =8,
guyBBack =8,
guyBSpecial =16
};
class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
public:
#ifdef READGUY_ESP_ENABLE_WIFI
@@ -338,7 +351,7 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
bool SDinside(bool check=true) { return check?setSDcardDriver():READGUY_sd_ok; };
void SDdeinit() { READGUY_sd_ok = 0; }; //当SD卡被检测到拔出或不可用时, 调用此函数标记
/// @brief 检查按钮. 当配置未完成时,按钮不可用, 返回0.
uint8_t getBtn() { return (READGUY_cali==127)?getBtn_impl():0; }
ReadguyButtonGesture getBtn() { return (READGUY_cali==127)?(ReadguyButtonGesture)getBtn_impl():guyBNone; }
/// @brief [此函数已弃用 非常不建议使用] 根据按钮ID来检查按钮. 注意这里如果按下返回0, 没按下或者按钮无效返回1
//uint8_t getBtn(int btnID){return btnID<getButtonsCount()?(!(btn_rd[btnID].isPressedRaw())):1;}
/// @brief 该函数用于设置按键是否允许扫描连按
@@ -494,10 +507,10 @@ class ReadguyDriver: public LGFX_Sprite{ // readguy 基础类
#else
epd_spi->beginTransaction(SPISettings(ESP32_DISP_FREQUENCY, MSBFIRST, SPI_MODE0));
#endif
spibz ++;
spibz +=1;
}
static void in_release(){//SPI结束传输屏幕数据
spibz --;
spibz -=1;
#if (defined(READGUY_ALLOW_DC_AS_BUTTON))
if(!(spibz&0x3f))
#else