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:
4:8d6883cdc3c8
Parent:
3:c7f97bebf2f7
Child:
5:cb4d45f41e17

File content as of revision 4:8d6883cdc3c8:

#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);
        _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();
    _t = new Timer();
    _t->start();

    _click_interval_us = 300*1000;
    _debounce_ignore_us = 100*1000;
    _longpress_us = 1000*1000;
    
    _debounce_ignore = false;
    _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

    // --- 長押し検出用タイマーを停止
    _longpress_timeout->detach();
    _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 )
{
#if 0
    if( _pressed == false) {
        DBG_PRINT("isr_released: illigal release, ignore.");
        fflush(stdout);
        return;
    } else {
        _pressed = false;  
    }
#endif
    
    // 長押し検出用タイマーを停止    
    _longpress_timeout->detach();
    
    // --- チャタリング(debounce)チェック ------------------------------------------------
    if(_debounce_ignore == true) {
        DBG_PRINT("isr_released: bounce. ");
        fflush(stdout);
        
        return;
    } else if(_longpressed == true) { // 長押しチェック 
        DBG_PRINT("isr_released: _longpressed. ");
        fflush(stdout);

        _longpressed = false;

        return;
    } else {
        DBG_PRINT("isr_released called:\r\n");
        fflush(stdout);
    }    
    
    // クリック認定
    _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 )
{
    DBG_PRINT("--- debounce T.O.\r\n");
    _debounce_ignore = false;
}

void MultiClick::click_timeout( void )
{
    DBG_PRINT("===== multiclick T.O.\r\n\r\n");

    // クリックイベントを通知
    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;    
}

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; }

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; }