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

MultiClick.cpp

Committer:
ohtsuka
Date:
2016-06-15
Revision:
5:cb4d45f41e17
Parent:
4:8d6883cdc3c8
Child:
6:7f1142cc196a

File content as of revision 5:cb4d45f41e17:

#include "MultiClick.h"

MultiClick::MultiClick(PinName p, PinMode m)
{
    _iin = new InterruptIn(p);
    _mode = m;
    
    _iin->mode(_mode);

    if(_mode == PullUp) {
         DBG_PRINT("isr fall.\r\n");
        _iin->fall(this, &MultiClick::isr_pressed);
    } else {
         DBG_PRINT("isr rise.\r\n");
        _iin->rise(this, &MultiClick::isr_pressed);
    }
    
    _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;
    
    _pressed_count = 0;
    _longpressed = false;
}

void MultiClick::isr_pressed( void )
{
    DBG_PRINT("isr_pressed called:\r\n");
    fflush(stdout);

    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;

    }
}

void MultiClick::press_check_func( void )
{
    int curr_state;
    curr_state = _iin->read();
    
    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);
        
        if(_pressed_count >= _shortpress_num) {
            _click_times++;
        }
        DBG_PRINT("# _click_times=%d\r\n", _click_times);
        
        _press_check->detach();    //  プレスチェックを停止

        _click_detect_timeout->detach(); // マルチクリック検出用タイマーを設定
        _click_detect_timeout->attach_us(this, &MultiClick::click_detect_timeout, _click_interval_us );
        
    }
    
}

void MultiClick::click_detect_timeout( void )
{
    DBG_PRINT("-> click_detect T.O.\r\n");

    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 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;
    _pressed_count = 0;
}

void MultiClick::attach_clicked(void (*function)(void) = 0) { _c_callback_clicked = function; }

void MultiClick::attach_doubleclicked(void (*function)(void) = 0) { _c_callback_doubleclicked = function; }

void MultiClick::attach_n_clicked(void (*function)(int) = 0) { _c_callback_n_clicked = function; }

void MultiClick::attach_longpressed(void (*function)(void) = 0) { _c_callback_longpressed = function; }