You can use multiple clicks event with one button. This library supports follow events, Single click, Double click, over 3 times click, Long press.

Dependents:   multiclick_test

Revision:
5:cb4d45f41e17
Parent:
4:8d6883cdc3c8
Child:
6:7f1142cc196a
--- a/MultiClick.cpp	Wed Jun 15 05:17:19 2016 +0000
+++ b/MultiClick.cpp	Wed Jun 15 08:55:09 2016 +0000
@@ -10,155 +10,113 @@
     if(_mode == PullUp) {
          DBG_PRINT("isr fall.\r\n");
         _iin->fall(this, &MultiClick::isr_pressed);
-        _iin->rise(this, &MultiClick::isr_released);
     } else {
          DBG_PRINT("isr rise.\r\n");
-        _iin->fall(this, &MultiClick::isr_released);
         _iin->rise(this, &MultiClick::isr_pressed);
     }
     
-    _timeout = new Timeout();
-    _debounce_timeout = new Timeout();
-    _longpress_timeout = new Timeout();
+    _click_detect_timeout = new Timeout();
+    _press_check = new Ticker();
     _t = new Timer();
     _t->start();
 
+    _press_check_interval_us = 25*1000;
+    _shortpress_num = 1;
+    _longpress_num = 20;
     _click_interval_us = 300*1000;
-    _debounce_ignore_us = 100*1000;
-    _longpress_us = 1000*1000;
     
-    _debounce_ignore = false;
+    _pressed_count = 0;
     _longpressed = false;
 }
 
 void MultiClick::isr_pressed( void )
 {
-#if 0
-    // チャタリングチェック1
-    if(_pressed == true) {
-        DBG_PRINT("isr_pressed: illigal press, ignore.");
-        fflush(stdout);
-        return;
-    } else {
-        _pressed = true;  
-    }
-#endif
+    DBG_PRINT("isr_pressed called:\r\n");
+    fflush(stdout);
 
-    // --- 長押し検出用タイマーを停止
-    _longpress_timeout->detach();
+    if(_pressed_count > 0) { // 「プレス中のプレス」
+        DBG_PRINT("_");
+        press_check_func();
+    } else { // 通常時
+
+    // プレス判定処理開始
+    _pressed_count = 0;
+    _press_check->detach();
+    _press_check->attach_us(this, &MultiClick::press_check_func, _press_check_interval_us );
+    
     _longpressed = false;
-    
-    // --- チャタリング(debounce)チェック2 ------------------------------------------------                
-    if(_debounce_ignore == true) {
-        DBG_PRINT("isr_pressed: bounce. ");
-        fflush(stdout);
-    } else {
-        DBG_PRINT("isr_pressed called:\r\n");
-        fflush(stdout);
-        
-        // 長押し検出用タイマー開始
-        _longpress_timeout->attach_us(this, &MultiClick::longpress_timeout, _longpress_us );
+
     }
-
 }
 
-void MultiClick::isr_released( void )
+void MultiClick::press_check_func( void )
 {
-#if 0
-    if( _pressed == false) {
-        DBG_PRINT("isr_released: illigal release, ignore.");
-        fflush(stdout);
-        return;
-    } else {
-        _pressed = false;  
-    }
-#endif
+    int curr_state;
+    curr_state = _iin->read();
     
-    // 長押し検出用タイマーを停止    
-    _longpress_timeout->detach();
-    
-    // --- チャタリング(debounce)チェック ------------------------------------------------
-    if(_debounce_ignore == true) {
-        DBG_PRINT("isr_released: bounce. ");
-        fflush(stdout);
+    if(curr_state == 0) { // 押されている場合
+        DBG_PRINT(".");
+        _pressed_count++;
+        // 長押しチェック
+        if(_pressed_count > _longpress_num) {
+            if(_longpressed != true) {
+                if(_c_callback_longpressed != 0) {
+                    (*_c_callback_longpressed)();
+                }
+                _longpressed = true;
+            }
+        }
+    } else { // 押されていない場合
+        DBG_PRINT("# _pressed_count=%d\r\n", _pressed_count);
         
-        return;
-    } else if(_longpressed == true) { // 長押しチェック 
-        DBG_PRINT("isr_released: _longpressed. ");
-        fflush(stdout);
+        if(_pressed_count >= _shortpress_num) {
+            _click_times++;
+        }
+        DBG_PRINT("# _click_times=%d\r\n", _click_times);
+        
+        _press_check->detach();    //  プレスチェックを停止
 
-        _longpressed = false;
-
-        return;
-    } else {
-        DBG_PRINT("isr_released called:\r\n");
-        fflush(stdout);
-    }    
+        _click_detect_timeout->detach(); // マルチクリック検出用タイマーを設定
+        _click_detect_timeout->attach_us(this, &MultiClick::click_detect_timeout, _click_interval_us );
+        
+    }
     
-    // クリック認定
-    _click_times++;
-    
-    // チャタリングチェック期間を開始する設定(初回、押し下げ後一定時間は、押し下げを無視)
-    _debounce_ignore = true;
-    _debounce_timeout->detach();
-    _debounce_timeout->attach_us(this, &MultiClick::debounce_timeout, _debounce_ignore_us );
-
-    // マルチクリック検出用タイマーを設定
-    _timeout->detach();
-    _timeout->attach_us(this, &MultiClick::click_timeout, _click_interval_us );
-
-
 }
 
-void MultiClick::debounce_timeout( void )
+void MultiClick::click_detect_timeout( void )
 {
-    DBG_PRINT("--- debounce T.O.\r\n");
-    _debounce_ignore = false;
-}
-
-void MultiClick::click_timeout( void )
-{
-    DBG_PRINT("===== multiclick T.O.\r\n\r\n");
+    DBG_PRINT("-> click_detect T.O.\r\n");
 
-    // クリックイベントを通知
-    switch( _click_times ) {
-    case 0:
-        DBG_PRINT("error!");
-        break;
+    if(_longpressed) { // 長押し時は何もしない
+        DBG_PRINT("-> skip n click C.B. \r\n");
+    } else { // クリックイベントを通知
+        switch( _click_times ) {
+        case 0:
+            DBG_PRINT("error!");
+            break;
+        
+        case 1:
+            if(_c_callback_clicked != 0) {
+                (*_c_callback_clicked)();
+            }
+            break;
     
-    case 1:
-        if(_c_callback_clicked != 0) {
-            (*_c_callback_clicked)();
-        }
-        break;
-
-    case 2:
-        if(_c_callback_doubleclicked != 0) {
-            (*_c_callback_doubleclicked)();
-        }
-        break;
-    default:
-        if(_c_callback_n_clicked != 0) {
-            (*_c_callback_n_clicked)(_click_times);
+        case 2:
+            if(_c_callback_doubleclicked != 0) {
+                (*_c_callback_doubleclicked)();
+            }
+            break;
+        default:
+            if(_c_callback_n_clicked != 0) {
+                (*_c_callback_n_clicked)(_click_times);
+            }
         }
     }
-
-    _click_times = 0;    
+    
+    _click_times = 0;
+    _pressed_count = 0;
 }
 
-void MultiClick::longpress_timeout( void )
-{
-    DBG_PRINT("===== longpress T.O.\r\n\r\n");
-
-    if(_c_callback_longpressed != 0) {
-        (*_c_callback_longpressed)();
-    }
-
-    _click_times = 0;
-    _longpressed = true;    
-}
-
-
 void MultiClick::attach_clicked(void (*function)(void) = 0) { _c_callback_clicked = function; }
 
 void MultiClick::attach_doubleclicked(void (*function)(void) = 0) { _c_callback_doubleclicked = function; }