#include <msp430fr2433.h>
#include <stdint.h>

//leave uncommented for calibration, comment out to compare without calibration
#define VLO_CAL

#define CLK_FREQ 32768                      // High accuracy clock frequency
#define RTC_CAL 80                          // VLO calibration cycles setting
#define TIMING 1                            // Wake up every 1 second

uint16_t rtc_cnt;                           // Variable for RTC setting
uint16_t counts;                            // Counts of VLO calibration
uint16_t cap_cnt1,cap_cnt2;                 // Timer capture values

void init_CS(void);                         // Setup clock
void cal_VLO(void);                         // VLO calibration
void init_GPIO(void);                       // Initialize GPIO


void main(void)
{
    WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer
    init_CS();                              // Call init routine
    init_GPIO();

    #ifdef VLO_CAL
    cal_VLO();                              // calibrate VLO
    rtc_cnt = RTC_CAL * TIMING * CLK_FREQ / counts;
    RTCMOD = rtc_cnt -1;                     // setup RTC for 1 second interrupt
    RTCCTL = RTCSS__VLOCLK | RTCSR | RTCPS__10 | RTCIE; // Source = VLO, divided by 10
    #else
    RTCMOD = 1000 -1;                     // setup RTC for 1 second interrupt
    RTCCTL = RTCSS__VLOCLK | RTCSR | RTCPS__10 | RTCIE; // Source = VLO, divided by 10
    #endif

    while(1)
    {
        P1OUT ^= BIT0;                      // For test only, test timing accuracy. Measure this output on scope.
        __bis_SR_register(LPM4_bits+ GIE);  // Enter LPM4
    }
}


void init_CS(void)
{
    __bis_SR_register(SCG0);                // disable FLL
    CSCTL3 |= SELREF__REFOCLK;              // Set REFO as FLL reference source
    CSCTL0 = 0;                             // clear DCO and MOD registers
    CSCTL1 &= ~(DCORSEL_7);                 // Clear DCO frequency select bits first
    CSCTL1 |= DCORSEL_0;                    // Set DCO = 1MHz
    CSCTL2 = FLLD_0 + 30;                   // DCODIV = 1MHz
    __delay_cycles(3);
    __bic_SR_register(SCG0);                // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
    CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
                                            // default DCODIV as MCLK and SMCLK source
}

void init_GPIO(void)
{
    // Port output low
    P1OUT = 0x00;
    P1DIR |= 0xFF;
    P2OUT = 0x00;
    P2DIR |= 0xFF;
    P3OUT = 0x00;
    P3DIR |= 0xFF;

    PM5CTL0 &= ~LOCKLPM5;                   // Disable the GPIO power-on default high-impedance mode
                                            // to activate previously configured port settings
}


void cal_VLO(void)
{
    cap_cnt1 = 0;                           // First capture counter
    cap_cnt2 = 0;                           // Second capture counter

    RTCMOD = RTC_CAL -1;                    // Ouput RTC pulse every RTC_CAL VLO clock cycles
//    RTCCTL = RTCSS__VLOCLK | RTCSR | RTCPS__1024;

    RTCCTL = RTCSS__VLOCLK | RTCSR | RTCPS__10;//Changed the VLO divider setting


     TA0CCTL1 |= CM_1 | CCIS_1 | CAP | CCIE; // Timer0_A1 Setup
                                             /// Capture rising edge,
                                             // Capture on RTC output  CCIS_1
                                             //  CCIE Enable interrupt
                                             // Enable capture mode,


    TA0CTL |= TASSEL__ACLK | MC_2 | TACLR;  // Use ACLK as clock source, clear TACLR
                                            // Start timer in continuous mode

    __bis_SR_register(LPM3_bits | GIE);     //wake on first count
    __no_operation();
    __bis_SR_register(LPM3_bits);           // wake again to get second count

    counts = cap_cnt2 - cap_cnt1;

    TA0CTL = 0;                             // Stop timer
    TA0CCTL0 = 0;
    RTCCTL = 0;                             // Stop RTC
}



#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A3_VECTOR))) TIMER0_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch(__even_in_range(TA0IV,TA0IV_TAIFG))
    {
        case TA0IV_NONE:
            break;                                  // No interrupt
        case TA0IV_TACCR1:

            if(cap_cnt1 ==0)
                {
                cap_cnt1 = TA0CCR1; // First capture counter

                }
            else
            {


                cap_cnt2 = TA0CCR1; // Second capture counter


            }
            //
            TA0CCTL1 &= ~CCIFG;        // Clear timer IFG

            __bic_SR_register_on_exit(LPM3_bits);   // Exit LPM3


            break;                                  // CCR1 not used
        case TA0IV_TACCR2:

            break;                                  // CCR2 not used
        case TA0IV_TAIFG:
            break;                                  // overflow
        default:
            break;
    }
}

// RTC interrupt service routine
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
{
    switch(__even_in_range(RTCIV,RTCIV_RTCIF))
    {
    case  RTCIV_NONE:   break;              // No interrupt
    case  RTCIV_RTCIF:                      // RTC Overflow
        __bic_SR_register_on_exit(LPM4_bits);// Exit LPM4
        break;
    default: break;
    }
}
