#include <msp430.h> 

// IR transmitter test

#include "driverlib.h"

//******************************************************************************
//
//          PINOUTS
//
//******************************************************************************
// PIN 1.0 = onboard red LED for MSP430FR2433 dev board - Set to basic output
// PIN 2.6 = IR LED. Pin set to output in IR transmit mode IREN
// PIN 2.7 = onboard switch for MSP430FR2433 dev board. Set to trigger on high to low

//******************************************************************************
//
//          Function Prototypes
//
//******************************************************************************
void Init_Clock(void);
void Init_GPIO(void);
void Start_38k_Timer(void);
void Start_Envelope_Timer(void);
void BlinkLED ();

//******************************************************************************
//
//          Global Variables
//
//******************************************************************************
volatile uint32_t buttonDebounce;

/************ Lighting Related Global Variables ************/
// Blank for now


/************ IR TX Related Global Variables ************/
//unsigned char   IR_code = 0;
//unsigned char   IR_flag = 0;
unsigned char   IR_stop = 0;
unsigned char   byte_cnt = 0;
unsigned int    bit_sel = 0;
unsigned char   *send_addr;
unsigned char   send_data[4]={0x55, 0xaa, 0x00, 0xff}; // default values. every other byte is inverse

/************ Timer Related Global Variables ************/
uint32_t MclockValue = 0;           //Variable to store current MClock value
uint32_t SMclockValue = 0;          //Variable to store current SMClock value
uint32_t AclockValue = 0;           //Variable to store current AClock value

/************ Clock Frequencies ************/
//Target frequency for MCLK in kHz
#define CS_MCLK_DESIRED_FREQUENCY_IN_KHZ 8000

//MCLK/FLLRef Ratio
// Set this to MCLK value divided by 32000. This sets a countdown timer to allow the FLL to settle into the desired MCLK value
#define CS_MCLK_FLLREF_RATIO 250

void main (void)
{
    //Stop watchdog timer
    WDT_A_hold(WDT_A_BASE);

    // Initialize everything
    Init_GPIO();                                //Initialize GPIO
    Init_Clock();                               //Initialize Clock

    //Verify if the Clock settings are as expected
    MclockValue = CS_getMCLK();
    SMclockValue = CS_getSMCLK();
    AclockValue = CS_getACLK();

    IR_stop = 0;   //enable IR emitter

    while(1)
        {

            // clear the flag and counter
            //IR_flag  = 0;
            byte_cnt = 0;
            bit_sel = 0;

            if(IR_stop == 0)
            {
                // disable Port1 & Port2 interrupt during IR emitting
                P1IE = 0;
                P2IE = 0;

                // Start generating a 38khz signal
                Start_38k_Timer();
                Start_Envelope_Timer();
                // Stop and sit here just putting out a constant 38khz signal
                while(1);

            }
            __bis_SR_register(LPM3_bits + GIE);     //enter LPM3 with global interrupts enabled

            IR_stop = 0;                            // enable IR code emitting
        }

    //Enter LPM3 w/interrupt
    //__bis_SR_register(LPM3_bits + GIE);

    //For debugger
    __no_operation();
}

//******************************************************************************
//
//          Functions
//
//******************************************************************************

//Initialize Clock
void Init_Clock(void)
{
    // This function uses driverlib to set the clock values for the board
    // See driverlib documentation for more information about these functions

    // Set DCO FLL reference = REFO
    CS_initClockSignal(CS_FLLREF,CS_REFOCLK_SELECT,CS_CLOCK_DIVIDER_1);

    // Set Ratio and Desired MCLK Frequency and initialize DCO
    CS_initFLLSettle(CS_MCLK_DESIRED_FREQUENCY_IN_KHZ,CS_MCLK_FLLREF_RATIO);

    // Set ACLK = REFO
    CS_initClockSignal(CS_ACLK,CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

                                            // DCOCLK = MCLK and SMCLK source
    CSCTL5 |= DIVM_0 | DIVS_1;              // MCLK = DCOCLK = 8MHZ,
                                            // SMCLK = MCLK/2 = 4MHz
}

//Initialize GPIO
void Init_GPIO(void)
{
    //************  IR CONFIGURATION  ************//
    // Configure IR output pin
    // Set P 2.6 to output the signal from IR module
//    GPIO_setAsPeripheralModuleFunctionOutputPin(
//      GPIO_PORT_P2,
//      GPIO_PIN6,
//      GPIO_PRIMARY_MODULE_FUNCTION
//      );

    GPIO_setAsPeripheralModuleFunctionOutputPin(
      GPIO_PORT_P1,
      GPIO_PIN4,
      GPIO_PRIMARY_MODULE_FUNCTION
      );

    // DEBUG - Set P 1.2 to output the signal from Timer_A0
    // See slau445g page 328 for instruction on how to set manually
//    GPIO_setAsPeripheralModuleFunctionOutputPin(
//      GPIO_PORT_P1,
//      GPIO_PIN2,
//      GPIO_SECONDARY_MODULE_FUNCTION
//      );
//
//    // DEBUG - Set P 1.4 to output the signal from Timer_A1
//    GPIO_setAsPeripheralModuleFunctionOutputPin(
//      GPIO_PORT_P1,
//      GPIO_PIN4,
//      GPIO_SECONDARY_MODULE_FUNCTION
//      );

    // Currently set for FSK modulation with output set to high
    // Configure IR modulation - see slau445g page 78
    // BIT 4 = IRDATA
    // BIT 3 = IRDSSEL  - IR Data Source Select 0 = hardware | 1 = IRDATA bit
    // BIT 2 = IRMSEL   - IR Mode Select    0 = ASK | 1 = FSK
    // BIT 1 = IRPSEL   - Polarity (don't touch)
    // BIT 0 = IREN     - IR Enable 0 = off | 1 = on
    SYSCFG1 = IRDSSEL + IREN;       // Datasource = IRDATA bit, ASK mode

    PMM_unlockLPM5();
}

void Start_38k_Timer(void){
    // This setup configures and starts a constant 38khz signal using timer_A0
    // Timer configuration step order from slau445g page 363

    // Step 1 - Clear everything    slau445g page 377
    TA0CTL = TACLR;

    // Step 2 - Initialize Timer_A0 Capture/Compare Register    slau445g page 381
    // 38kHz 1/4 duty-cycle carrier waveform length setting     slaa644b page 10
    // Configured based on 4 MHz clock!!
    TA0CCR0 = 104;          // (4000 / 38 = 105) (timer counts from 0)
    TA0CCR2 = 25;           // (105 / 4 = 26) (1/4 duty cycle for power conservation)

    // Step 3 - Configure Timer_A0 Capture/Compare Control Register     slau445g page 379
    TA0CCTL2 = OUTMOD_7;                // output mode: reset/set

    // Step 4 - Configure Timer_A0 Control Register     slau445g page 377
    // timer operation mode settings
    // TACLR    = Timer A counter clear
    // TASSEL_2 = Timer A clock source select: 2 - SMCLK
    // MC_1     = Timer A mode control: 1 - Up to CCR0
    TA0CTL = TASSEL_2 + MC_1;
}

void Start_Envelope_Timer(void){
    // This setup configures an envelope timing signal using timer_A0
    // Timer configuration step order from slau445g page 363

    // Currently configured to output a constant high signal

    // Step 1 - Clear everything    slau445g page 377
    TA1CTL = TACLR;

    // Step 2 - Initialize Timer_A1 Capture/Compare Register    slau445g page 381
    // 9 ms
    // Configured based on 4 MHz clock!!
    TA1CCR0 = 8000 - 1;          // (4000000 x 0.001 = 4000 + TA1CCR2 = 8000) (1ms low)
    TA1CCR2 = 4000 - 1;          // (4000000 x 0.001 = 4000) (1ms high)

    // Step 3 - Configure Timer_A1 Capture/Compare Control Register     slau445g page 379
    TA1CCTL2 = OUTMOD_7;                // output mode: reset/set

    // Step 4 - Configure Timer_A1 Control Register     slau445g page 377
    // timer operation mode settings
    // TACLR    = Timer A counter clear
    // TASSEL_2 = Timer A clock source select: 2 - SMCLK
    // MC_1     = Timer A mode control: 1 - Up to CCR0
    TA1CTL = TASSEL_2 + MC_1;
}
