Code: Toggle on Tap

Recently there have been a lot of questions about how to make something toggle when a button is tapped (i.e. the button is pressed and it previously wasn’t). The something being toggled is most likely going to be the state of a relay for pneumatics, but it can also be a variable or PWM output.

Below is a function that we use to abstract the functionality of toggling on the tap of a button.

The intended audience is

  • Programmers that are new to the concept of state toggling
  • Programmers that have many instances of state toggling

Feel free to use/modify this code in any way desired.

/***************************
* FUNCTION NAME: toggle_on_tap
* PURPOSE:       Toggle a parameter when a button is tapped
* ARGUMENTS:   unsigned char cur_button - The current button state
*              unsigned char prev_button - The button state for the previous loop
*              unsigned char prev_state - The parameter state for the previous loop
*              unsigned char state1 - A state that the parameter can have
*              unsigned char state2 - The other state that the parameter can have
* RETURNS:     unsigned char new_state - The new state of the parameter
******************************/
unsigned char toggle_on_tap( unsigned char cur_button, 
                             unsigned char prev_button, 
                             unsigned char prev_state,
                             unsigned char state1,
                             unsigned char state2)
{ 
    unsigned char new_state = prev_state;
    if ((cur_button == 1) && (prev_button == 0))
    {
       if (prev_state == state1)
       {
          new_state = state2;
       }
       else
       {
          new_state = state1;
       }
    }
//  printf("Cur %d PrevB %d  PrevS %d  NewS %d\r",cur_button,prev_button,prev_state,new_state);
    return new_state;
}

Here’s an example of how it could be used.

  • P1 trigger cycles relay 1 between STATE_A and STATE_B
  • P1 top cycles relay 2 between STATE_C and STATE_D

#define STATE_A 1
#define STATE_B 0
#define STATE_C 0
#define STATE_D 1

...

static unsigned char p1_sw_trig_prev = 0;
static unsigned char p1_sw_top_prev = 0;

static unsigned char relay1_state_prev = STATE_A;
static unsigned char relay2_state_prev = STATE_C;

unsigned char new_state;

// Get the new state based on the current button state
// and the previous button and relay states
new_state = toggle_on_tap(p1_sw_trig, 
                          p1_sw_trig_prev,
                          relay1_state_prev,
                          STATE_A,
                          STATE_B);
// Set the output to the new state
relay1_fwd = new_state;

// This may or may not be needed based on the application
// relay1_rev = relay1_state_prev;

//Store the current trigger state as the previous triggger state
p1_sw_trig_prev = p1_sw_trig;

//Store the new relay state as the previous relay state
relay1_state_prev = new_state;

// Get the new state based on the current button state
// and the previous button and relay states
new_state = toggle_on_tap(p1_sw_top, 
                          p1_sw_top_prev,
                          relay2_state_prev,
                          STATE_C,
                          STATE_D);

// Set the output to the new state
relay2_fwd = new_state;

// This may or may not be needed based on the application
// relay2_rev = relay1_state_prev;

//Store the current trigger state as the previous triggger state
p1_sw_top_prev = p1_sw_top;

//Store the new relay state as the previous relay state
relay2_state_prev = new_state;