/**
 * @file main.c
 * @brief Demo Button Toggle Timer
 *
 * In this example one LED is toggled every time one button is pressed.
 * Button press is detected using periodic timer interrupt.
 *
 * @date 2019
 * @author Strahinja Jankovic (jankovics@etf.bg.ac.rs)
 * @author Marija Bezulj (meja@etf.ba.ac.rs)
 *
 * @version [2.0 - 04/2021] Hardware change
 * @version [1.0 - 03/2019] Initial version
 */
#include <msp430.h> 
#include <stdint.h>

/**
 * @brief Use Ganssle debouncing or simple debouncing
 * 0 - simple
 * 1 - Ganssle
 */
#define USE_GANSSLE     1

/**
 * @brief Timer period
 *
 * Timer is clocked by ACLK (32768Hz)
 * It takes 32768 cycles to count to 1s.
 * If we need a period of X ms, then number of cycles
 * that is written to the CCR0 register is
 * 32768/1000 * X
 */
#if (USE_GANSSLE == 0)
#define TIMER_PERIOD        (1048)  /* ~32ms (31.26ms)  */
#else
#define TIMER_PERIOD        (65)    /* ~2ms  (1.98ms)   */
#endif


/**
 * @brief Main function
 * main.c
 * Main function only initializes ports and enables global interrupts
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	// LED1 init
	P2OUT &= ~BIT4;             // set P2.4 to '0'
	P2DIR |= BIT4;              // configure P2.4 as out
	// S2 (switch 2) init
	P1REN |= BIT5;              // enable pull up/down
	P1OUT |= BIT5;              // set pull up
	P1DIR &= ~BIT5;             // configure P1.5 as in
	// Timer A init
	// Up mode, TA0CCR0 = TIMER_PERIOD
	TA0CCTL0 |= CCIE;           // enable c/c interrupt
	TA0CCR0 = TIMER_PERIOD;     // set timer period for compare mode
	TA0CTL = TASSEL__ACLK | MC__UP;

	__enable_interrupt();

	while(1)
	{

	}
}


/**
 * @brief TIMERA0 Interrupt service routine
 *
 * ISR debounces P1.5 and toggles LED if falling edge is detected.
 */
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TACC0ISR (void)
{
#if (USE_GANSSLE == 0)
    static uint8_t P1IN_old = 0;
        if (((P1IN & BIT5) == 0) & ((P1IN_old & BIT5) != 0))
        {
            // button is pressed
            P2OUT ^= BIT4;
        }
        P1IN_old = P1IN;            // save the last P1IN value
    // flag is automatically cleared
#else
    static uint16_t state = 0;       // current debounce status
        state = (state << 1) | 0xe000 | ((P1IN & BIT5) ? 1 : 0);
        if (state == 0xf000)
        {
            P2OUT ^= BIT4;
        }
#endif /* USE_GANSSLE */
}
