/**
 * @file main.c
 * @brief Demo Timer PWM LED
 *
 * In this example a button is used to change LED PWM duty ratio.
 *
 * @date 2019
 * @author Strahinja Jankovic (jankovics@etf.bg.ac.rs)
 * @author Marija Bezulj (meja@etf.bg.ac.rs)
 *
 * @version [2.0 - 04/2021] Hardware change
 * @version [1.1 - 03/2019] Code refactor
 * @version [1.0 - 03/2017] Initial version
 */
#include <msp430.h> 

/**
 * @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
 */
#define TIMER_PERIOD        (1048)  /* ~32ms (31.26ms)  */

/**
 * @brief PWM period
 */
#define PWM_PERIOD      15

/** Initial pulse width */
#define PWM_INITIAL_PW  1

/**
 * main.c
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer

	// init LD2 as input since the drive will be from pwm
	P2DIR &= ~BIT5;

	// init button S2
    // S2 (switch 2) init
    P1REN |= BIT5;              // enable pull up/down
    P1OUT |= BIT5;              // set pull up
    P1DIR &= ~BIT5;             // configure P1.5 as in
    P1IES |= BIT5;              // interrupt on falling edge
    P1IFG &= ~BIT5;             // clear flag
    P1IE  |= BIT5;              // enable interrupt

    // use timer B0 for debouncing
    TBCCR0 = TIMER_PERIOD;
    TBCCTL0 = CCIE;             // enable interrupt for CCR0
    TBCTL = TBSSEL__ACLK;       // set TB clock source


    // init timerA0 with out on LD2 through TA0 CCR2
    TA0CCR0 = PWM_PERIOD;       // init pwm period
    // timer is in compare mode with active OUT signal
    TA0CCR2 = PWM_INITIAL_PW;   // initial state is no pulse
    TA0CCTL2 = OUTMOD_7;        // outmode is Reset/Set
                                // CCR2 value defines the pulse width
	// init P1.3 pin as alternate function pin
    P1SEL |= BIT3;              // alternate function
    P1DIR |= BIT3;              // P1.3 is TA0.2 pin
    // activate timer
    TA0CTL = TASSEL__ACLK | MC__UP;

    __enable_interrupt();

    while(1);
}

/**
 * @brief Button P1.5 ISR
 * Button debounce.
 */
void __attribute__ ((interrupt(PORT1_VECTOR))) P1ISR (void)
{
    if ((P1IFG & BIT5) != 0)
    {
        TBCTL |= MC__UP;        // start timer B
        P1IFG &= ~BIT5;         // clear flag
    }
}

/**
 * @brief TimerB CCR0 ISR
 * Check if the button is still pressed after debounce period.
 * Increment PWM pulse width
 */
void __attribute__ ((interrupt(TIMER0_B0_VECTOR))) TBCCR0ISR (void)
{
    if ((P1IN & BIT5) == 0)     // button is pressed
    {
        TBCTL &= ~MC__UP;       // stop debounce timer
        TBCTL |= TBCLR;         // clear debounce timer
        TA0CCR2 = (TA0CCR2 + 1) & 0x0f; // increase PWM pulse width
    }
}
