Double click detection

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
SuCh_2227511
Level 3
Level 3
First like received First like given

I like to implement the double click function with a timer. But it seems not working. And I am not sure it is the good way to implement the function. Please advise.

DoubleClick.png

#define BUTTON_CLICKTIME_MS_MAX             (3000u) //3 sec

#define DOUBLE_CLICKTIME_MS_MAX             (500u) //0.5 sec

CY_ISR(CCChangeIsrHandler)

{

    if (!clickCount) // ==0u

    {

        Timer_Start();

        clickCount = 1u;

    }

    else //!=0u

    {

        clickTime = Timer_ReadCapture();

        Timer_Stop();

        clickCount = 2u;

    }

    Wakeup_SW_ClearInterrupt();

    Wakeup_Interrupt_ClearPending();

}

int main(void)

{

Wakeup_Interrupt_StartEx(CCChangeIsrHandler);

while (1) {

        /* DOUBLE CLICK */

        if (clickCount == 2u && clickTime < DOUBLE_CLICKTIME_MS_MAX)

        {

            changeCC();

        }

       /* LONG PRESS */

        while(Wakeup_SW_Read() == 0)

        {

            CyDelay(1u);

            btnHoldTime++;

        }

    

        /* Enter STOP mode when the button is pressed longer than 3 sec */

        if(btnHoldTime >= BUTTON_CLICKTIME_MS_MAX)

        {

            applicationPower = HIBERNATE;

        }

    }

}

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I tried this with CY8CKIT-044.

When started LED turns to GREEN.

If SW2 is pushed LED turns to YELLOW.

If you keep pushing SW2 for 3 seconds, PSoC enters to DeepSleep (LED off)

and with a push of SW2 again will make it wake up.

Or the LED color returns to the previous color (= current_color).

In each double click LED changes color to GREEN -> CYAN -> MAZENTA -> GREEN ...

I used systick to detect double click and a Timer for 3 seconds push.

Needless to say, there must be many more method(s) to do this,

but I hope at least this one is working (as I expected.)

schematic

000-schematic.JPG

pins

001-pins.JPG

main.c

==================

#include "project.h"

#define LED_WHITE   7

#define LED_YELLOW  6

#define LED_MAZENTA 5

#define LED_RED     4

#define LED_CYAN    3

#define LED_GREEN   2

#define LED_BLUE    1

#define LED_BLACK   0

volatile int hibernate_flag    = 0 ;

volatile int switch_flag       = 0 ;

volatile uint32_t tick_count   = 0 ;

volatile int double_click_flag = 0 ;

uint8_t current_color          = LED_BLACK ;

void set_led(uint8_t color)

{

    if (color & 0x01) { LED_B_Write(0) ; } else { LED_B_Write(1) ; }

    if (color & 0x02) { LED_G_Write(0) ; } else { LED_G_Write(1) ; }

    if (color & 0x04) { LED_R_Write(0) ; } else { LED_R_Write(1) ; }

}

CY_ISR(tick_isr)

{

    tick_count++ ;

}

CY_ISR(sw2_pushed_isr)

{

    push_int_ClearPending() ;

    SW2_ClearInterrupt() ;

  

    Timer_WriteCounter(0) ;

    Timer_Enable() ;

    switch_flag = 1 ;

    set_led(LED_YELLOW) ;

}

CY_ISR(sw2_released_isr)

{

    release_int_ClearPending() ;

  

    Timer_Stop() ;

    if (tick_count < 1000) {

        double_click_flag = 1 ;

    }

    tick_count = 0 ;

    set_led(current_color) ;

}

CY_ISR(hibernate_isr)

{

    Timer_ClearInterrupt(Timer_INTR_MASK_TC) ;

    Timer_Stop() ;

    Timer_WriteCounter(0) ;

    hibernate_flag = 1 ;

}

void do_double_click(void)

{

    switch(current_color) {

    case LED_GREEN: current_color = LED_CYAN ; break ;

    case LED_CYAN: current_color = LED_MAZENTA ; break ;

    default: current_color = LED_GREEN ; break ;

    }

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

  

    Timer_Init() ;

  

    Timer_ClearInterrupt(Timer_INTR_MASK_TC) ;

    Timer_Int_StartEx(hibernate_isr) ;

  

    CySysTickStart() ;

    CySysTickSetCallback(0, tick_isr) ;  

  

    push_int_ClearPending() ;

    push_int_StartEx(sw2_pushed_isr) ;

  

    release_int_ClearPending() ;

    release_int_StartEx(sw2_released_isr) ;

  

    current_color = LED_GREEN ;

    set_led(current_color) ;

}

void prepare_to_sleep(void)

{

    CySysTickDisableInterrupt() ;

    release_int_Disable() ;

}

void recover_from_sleep(void)

{

    CySysTickEnableInterrupt() ;

    release_int_ClearPending() ;

    release_int_Enable() ;

}

int main(void)

{

    init_hardware() ;

 

    for(;;)

    {

        if (double_click_flag) {

            double_click_flag = 0 ;

            do_double_click() ;

        }

        if (hibernate_flag) {

            hibernate_flag = 0 ;

            set_led(LED_BLACK) ; /* turn LED off */

            prepare_to_sleep() ;

            CySysPmDeepSleep() ;

            recover_from_sleep() ;

            set_led(current_color) ;

        }

    }

}

==================

moto

View solution in original post

0 Likes
2 Replies
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I tried this with CY8CKIT-044.

When started LED turns to GREEN.

If SW2 is pushed LED turns to YELLOW.

If you keep pushing SW2 for 3 seconds, PSoC enters to DeepSleep (LED off)

and with a push of SW2 again will make it wake up.

Or the LED color returns to the previous color (= current_color).

In each double click LED changes color to GREEN -> CYAN -> MAZENTA -> GREEN ...

I used systick to detect double click and a Timer for 3 seconds push.

Needless to say, there must be many more method(s) to do this,

but I hope at least this one is working (as I expected.)

schematic

000-schematic.JPG

pins

001-pins.JPG

main.c

==================

#include "project.h"

#define LED_WHITE   7

#define LED_YELLOW  6

#define LED_MAZENTA 5

#define LED_RED     4

#define LED_CYAN    3

#define LED_GREEN   2

#define LED_BLUE    1

#define LED_BLACK   0

volatile int hibernate_flag    = 0 ;

volatile int switch_flag       = 0 ;

volatile uint32_t tick_count   = 0 ;

volatile int double_click_flag = 0 ;

uint8_t current_color          = LED_BLACK ;

void set_led(uint8_t color)

{

    if (color & 0x01) { LED_B_Write(0) ; } else { LED_B_Write(1) ; }

    if (color & 0x02) { LED_G_Write(0) ; } else { LED_G_Write(1) ; }

    if (color & 0x04) { LED_R_Write(0) ; } else { LED_R_Write(1) ; }

}

CY_ISR(tick_isr)

{

    tick_count++ ;

}

CY_ISR(sw2_pushed_isr)

{

    push_int_ClearPending() ;

    SW2_ClearInterrupt() ;

  

    Timer_WriteCounter(0) ;

    Timer_Enable() ;

    switch_flag = 1 ;

    set_led(LED_YELLOW) ;

}

CY_ISR(sw2_released_isr)

{

    release_int_ClearPending() ;

  

    Timer_Stop() ;

    if (tick_count < 1000) {

        double_click_flag = 1 ;

    }

    tick_count = 0 ;

    set_led(current_color) ;

}

CY_ISR(hibernate_isr)

{

    Timer_ClearInterrupt(Timer_INTR_MASK_TC) ;

    Timer_Stop() ;

    Timer_WriteCounter(0) ;

    hibernate_flag = 1 ;

}

void do_double_click(void)

{

    switch(current_color) {

    case LED_GREEN: current_color = LED_CYAN ; break ;

    case LED_CYAN: current_color = LED_MAZENTA ; break ;

    default: current_color = LED_GREEN ; break ;

    }

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

  

    Timer_Init() ;

  

    Timer_ClearInterrupt(Timer_INTR_MASK_TC) ;

    Timer_Int_StartEx(hibernate_isr) ;

  

    CySysTickStart() ;

    CySysTickSetCallback(0, tick_isr) ;  

  

    push_int_ClearPending() ;

    push_int_StartEx(sw2_pushed_isr) ;

  

    release_int_ClearPending() ;

    release_int_StartEx(sw2_released_isr) ;

  

    current_color = LED_GREEN ;

    set_led(current_color) ;

}

void prepare_to_sleep(void)

{

    CySysTickDisableInterrupt() ;

    release_int_Disable() ;

}

void recover_from_sleep(void)

{

    CySysTickEnableInterrupt() ;

    release_int_ClearPending() ;

    release_int_Enable() ;

}

int main(void)

{

    init_hardware() ;

 

    for(;;)

    {

        if (double_click_flag) {

            double_click_flag = 0 ;

            do_double_click() ;

        }

        if (hibernate_flag) {

            hibernate_flag = 0 ;

            set_led(LED_BLACK) ; /* turn LED off */

            prepare_to_sleep() ;

            CySysPmDeepSleep() ;

            recover_from_sleep() ;

            set_led(current_color) ;

        }

    }

}

==================

moto

0 Likes

Thank you so much for giving me such a good tip to use Systick and the two interrupts in a pin, which I never imagined.

My project is based on CYBLE-022001-00, which is PRoC with BLE. Your way works good as it is but not with my application.

When I apply your way my device does not sleep at all. My application is supposed to sleep with stop mode after x amount of time of inactivity.

It seems the interrupt of systick wakes it up all the time.  I changed the systick to PWM timer with changing a few code, which works well. Thanks again!