/* --COPYRIGHT--,BSD
 * Copyright (c) 2012, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
 
/*******************************************************************************
 *
 *  main.c - Main User Experience Project for TMP006 Booster Pack
 *
 *  Texas Instruments Inc.
 *  Built with CCS Version 5.2.0 and IAR Embedded Workbench Version: 5.10
 *
 ******************************************************************************/

/*
 * This demo leverages hardware or software UART. By default, it is configured 
 * for Hardware UART. If Timer UART is required, change the setting in uart.h
 * and recompile and redownload the code. The UART is used to transmit data 
 * back to the host PC. It also has communication protocols between the host
 * PC. The following is the protocol list.
 *
 * Received header packets from msp430
 * 0x80 Temperature,tDie,VObj - Data streaming header
 * 0x81 Temperature,tDie,VObj - Data logging header
 * 0xFA <Mode> <ConversionRate> - Current configuration
 *     Mode - 0x00 - Data Streaming
 *            0x01 - Data logging
 *     ConversionRate - 0xE4 - Changes conversion time to every 4 seconds
 *                      0xE3 - Changes conversion time to every 2 seconds
 *                      0xE2 - Changes conversion time to every 1 seconds
 *                      0xE1 - Changes conversion time to every 0.5 seconds
 *                      0xE0 - Changes conversion time to every 0.25 seconds
 * 0xFB <Response> - Data logging response
 *     Response - 'E' - Erased successfully
 *              - 'D' - Dumped all data
 *
 * Allowable transmit header packets from host
 * 'D' - Dump data logged data to PC. This command will respond back with 0xFB <Response> 0x0A 0x0D
 *       when successful.
 * 'E' - Erase data logged data. This command will respond back with 0xFB <Response> 0x0A 0x0D when
 *       successful.
 * 0xBB - Set to data streaming mode. This command has no response.
 * 0xAA - Set to data logging mode. This command has no response.
 * 0xE4 - Changes conversion time to every 4 seconds. This command has no response.
 * 0xE3 - Changes conversion time to every 2 seconds. This command has no response.
 * 0xE2 - Changes conversion time to every 1 seconds. This command has no response.
 * 0xE1 - Changes conversion time to every 0.5 seconds. This command has no response.
 * 0xE0 - Changes conversion time to every 0.25 seconds. This command has no response.
 * 0xFA - Ping MSP430 for current configuration. Response would be 0xFA <Mode> <ConversionRate> 0x0A 0x0D
 *
 */

#include <msp430.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "uart.h"
#include "tmp006.h"

#define DRDY_BIT    BIT1
#define DRDY_PxIN   P2IN
#define DRDY_PxDIR  P2DIR

/* GREEN LED Configuration */
#define GREEN_PxOUT  P2OUT
#define GREEN_BIT    BIT4
#define GREEN_PxDIR  P2DIR
#define GREEN_CLEAR  GREEN_PxOUT &= ~(GREEN_BIT)
#define GREEN_SET    GREEN_PxOUT |= (GREEN_BIT)
/* RED Configuration */
#define RED_PxOUT  P2OUT
#define RED_BIT    BIT3
#define RED_PxDIR  P2DIR
#define RED_CLEAR  RED_PxOUT &= ~(RED_BIT)
#define RED_SET    RED_PxOUT |= (RED_BIT)

/* Temperature defines */
#define     TIMER_PWM_PERIOD      2000
#define     TIMER_PWM_OFFSET      20

#define     TEMP_SAME             0
#define     TEMP_HOT              1
#define     TEMP_COLD             2

/* Can switch between data stream or data logging mode
 * 0 - data streaming
 * 1 - data logging
 */
unsigned char mode = 0;

/* Store a boolean check if the mode has changed */
unsigned char stateChanged = 0;

/* Size of data logger array
 * NOTE: This HAS to be aligned every 512 bytes segment to prevent unwanted main application
 * code being erased.
 */
#define     DATALOGSIZE         2048

/* Set a temperature threshold to turn the LED on or off when there is a temperature difference
 * in Fahrenheit
 */
#define     TEMP_THRESHOLD      4

/* Hard coded address to prevent custom linker file. If DATALOGSIZE is adjusted, this value must
 * also change.
 * NOTE: This HAS to be aligned every 512 bytes segment to prevent unwanted main application
 * code being erased.
 */
#ifdef __IAR_SYSTEMS_ICC__
__no_init int data_log_tDie[DATALOGSIZE] @ 0xC000;
__no_init int data_log_vObj[DATALOGSIZE] @ 0xD000;
#else
#pragma DATA_SECTION(data_log_tDie, ".datalog");
int data_log_tDie[DATALOGSIZE];
#pragma DATA_SECTION(data_log_vObj, ".datalog");
int data_log_vObj[DATALOGSIZE];
#endif

/* Data logger pointer in the array */
unsigned int flashPtr;

/* Calibrated temperature value */
long double tempCalibrated = 0;

/* Temperature polarity */
unsigned char tempPolarity = TEMP_SAME;

/* Store the current conversionRateSetting */
unsigned char conversionRateSetting = 0xE2;

/* Prototype Headers */
void sendTemp(long double temperature);
void dataStreaming(void);
void dataLogging(void);
void initializeDataLogging(void);
void eraseDataLog(void);
void dataLogger(int Tdie, int Vobj);
void receivedDataCommand(unsigned char receiveData);
unsigned int scanLastPoint(void);
void sendRawData(int tDie, int vObj);
void configureTimerPwm(void);
void configureTimerWakeUp(void);
void sendCurrentState(void);

void main(void)
{
    /* Stop WDT */
    WDTCTL = WDTPW + WDTHOLD;

    /* ACLK = VLO */
    BCSCTL3 |= LFXT1S_2;

    /* Use 1 MHz calibration constant */
    if (CALBC1_1MHZ != 0xFF) {
        /* Follow recommended flow. First, clear all DCOx and MODx bits. Then
         * apply new RSELx values. Finally, apply new DCOx and MODx bit values.
         */
        DCOCTL = 0x00;
        /* Set DCO to 1MHz */
        BCSCTL1 = CALBC1_1MHZ;
        DCOCTL = CALDCO_1MHZ;
    }

    /* Configure GREEN and RED LED */
    GREEN_CLEAR;
    GREEN_PxDIR |= GREEN_BIT;
    RED_CLEAR;
    RED_PxDIR |= RED_BIT;

    /* Configure P1.0 to indicate if it's in data logging mode or data streaming mode
     * Data logging mode - LED OFF
     * Data streaming mode - LED ON
     * Start in data streaming mode
     */
    P1OUT |= BIT0;
    P1DIR |= BIT0;

    /* Configure P1.3 switch */
    P1DIR &= ~BIT3;
    P1OUT |= BIT3;
    P1REN |= BIT3;
    P1IES |= BIT3;
    P1IFG &= ~BIT3;
    P1IE |= BIT3;

    /* Initialzie UART */
    uartInit();

    /* Initialize data logging variables */
    initializeDataLogging();

    /* Configure TMP006 with DRDY pin enabled
     * Configured to sample every 1 second
     */
    tmp006_init(1, TMP006_CR_1);

    /* Configure P2.1 for /DRDY pin */
    P2DIR &= ~BIT1;

    /* Read device ID if TMP006 is connected */
    if (tmp006_read(TMP006_P_DEVICE_ID) != 0x0067)
    {
        /* if device is not connected, stay in LPM4 */
        __bis_SR_register(LPM4_bits);
    }

    /* Read manufacturer ID */
    if (tmp006_read(TMP006_P_MAN_ID) != 0x5449)
    {
        /* if device is not connected, stay in LPM4 */
        __bis_SR_register(LPM4_bits);
    }

    if (mode)
    {
        /* Data logging mode */
        configureTimerWakeUp();
    }
    else
    {
        /* Data streaming mode */
        configureTimerPwm();
    }

    /* Enter LPM and wake up periodically based on timer1 */
    __bis_SR_register(GIE);

    while (1)
    {
        if (stateChanged) {
            /* Inform host that mode has been switched */
            sendCurrentState();

            /* Clear the state change to detect again in the future */
            stateChanged = 0;
        }

        if (mode) {
            /* Enter LPM and wake up periodically every 5 seconds */
            __bis_SR_register(LPM0_bits + GIE);

            dataLogging();
        }
        else {
            dataStreaming();
        }
    }
}

/*!
 *
 * Function that streams data back to the PC via UART. It also sets the Red
 * LED if temperature is greater than 90F. Set the Green LED if temperature
 * is less than 40F. Else clear LEDs.
 *
 * @param None
 *
 * @return None
 *
 */
void dataStreaming(void)
{
    /* calculated temperature value returned by getTemp */
    struct TempReading currTemp;

    /* Calculated temperature difference */
    long tempDifference;

    /* Poll if DRDY is ready */
    while(DRDY_PxIN & DRDY_BIT);

    /* Get current temperature from TMP006
     * Function returns a structure containing temperature in degree C
     * with raw values
     */
    currTemp = tmp006_getTemp();

    /* Convert degree C to degree F */
    currTemp.temp = (currTemp.temp * (1.8)) + 32.0;

    /* Initialize calibrated temperature with the initial value */
    if (tempCalibrated == 0)
    {
        tempCalibrated = currTemp.temp;
    }

    tempDifference = (long) (currTemp.temp - tempCalibrated);
    if (tempDifference < -TEMP_THRESHOLD)
    {
        tempDifference = -tempDifference;
        tempPolarity = TEMP_COLD;
        RED_PxOUT &= ~RED_BIT;
    }
    else if (tempDifference > TEMP_THRESHOLD)
    {
        tempPolarity = TEMP_HOT;
        GREEN_PxOUT &= ~GREEN_BIT;
    }
    else
    {
        tempPolarity = TEMP_SAME;
        TA1CCTL0 &= ~CCIE;
        TA1CCTL1 &= ~CCIE;
        GREEN_PxOUT &= ~(RED_BIT + GREEN_BIT);
    }

    if (tempPolarity != TEMP_SAME)
    {
        tempDifference <<= 3;
        tempDifference += TIMER_PWM_OFFSET;
        TA1CCR1 = ( (tempDifference) < (TIMER_PWM_PERIOD-1) ? (tempDifference) : (TIMER_PWM_PERIOD-1) );
        TA1CCTL0 |= CCIE;
        TA1CCTL1 |= CCIE;
    }

    /* Transmit data streaming header packet */
    uartTxByte(0x80);

    /* Transmit calculated temperature to the PC */
    sendTemp(currTemp.temp);

    /* Send comma separator */
    uartTxByte(',');

    sendRawData(currTemp.tDie, currTemp.vObj);

    /* Send new line */
    uartTxByte(0x0A);
    uartTxByte(0x0D);
}

/*!
 *
 * Function that initializes the flash module and scans where data logging was
 * last stopped
 *
 * @param None
 *
 * @return None
 *
 */
void initializeDataLogging(void)
{
    /* Scan for last stopping point in Flash */
    flashPtr = scanLastPoint();

    /* Initialize Flash */
    /* MCLK/3 for Flash Timing Generator */
    FCTL2 = FWKEY + FSSEL0 + FN1;
}

/*!
 *
 * Function to start data logging in Flash
 *
 * @param None
 *
 * @return None
 *
 */
void dataLogging(void)
{
    int vObj = 0;
    int tDie = 0;

    /* Poll if DRDY is ready */
    while(DRDY_PxIN & DRDY_BIT);

    vObj = tmp006_read(TMP006_P_VOBJ);
    tDie = tmp006_read(TMP006_P_TABT);

    /* Log temperature here */
    dataLogger(tDie, vObj);
}

/*!
 *
 * Function that packets and sends data through UART
 *
 * @param None
 *
 * @return None
 *
 */
void sendTemp(long double temperature)
{
    unsigned char i;
    short int isNeg = temperature < 0;      /* Create a boolean to track the sign */
    short int magnitude = 0;                /* Create a counter for the magnitude */
    int tempInt = abs((int)(temperature*10)); /* Clip uneeded decimal points */
    char arrayTemp[8] = {0};

    /* If the temperature is negative */
    if(isNeg)
    {
        uartTxByte('-');
    }

    while(tempInt != 0 && magnitude < 5)
    {
        arrayTemp[4-magnitude] = (0x30 + (tempInt%10));
        /* Increment the magnitude */
        magnitude++;
        if ((4 - magnitude) == 3)
        {
            arrayTemp[4 - magnitude] = '.';
            magnitude++;
        }
        /* Remove 1 order of magnitude */
        tempInt = tempInt/10;
    }

    if (magnitude == 4)
    {
        /* Zero pad the front since it is less than 100F */
        arrayTemp[0] = 0x30;
    }
    else if (magnitude == 3)
    {
        arrayTemp[0] = 0x30;
        arrayTemp[1] = 0x30;
    }
    else if (magnitude == 2)
    {
        arrayTemp[0] = 0x30;
        arrayTemp[1] = 0x30;
        arrayTemp[2] = 0x30;
    }

    /* Pad Degree F */
    arrayTemp[5] = ' ';
    arrayTemp[6] = 'F';

    for (i = 0; i < sizeof(arrayTemp); i++)
    {
        if (arrayTemp[i] == 0x00)
        {
            break;
        }
        uartTxByte(arrayTemp[i]);
    }
}

void sendRawData(int tDie, int vObj)
{
    unsigned char j;
    char arrayTemp_tDie[8] = {0};
    char arrayTemp_vObj[8] = {0};

    sprintf(arrayTemp_tDie, "%d", tDie);
    sprintf(arrayTemp_vObj, "%d", vObj);

    for (j = 0; j < sizeof(arrayTemp_tDie); j++)
    {
        if (arrayTemp_tDie[j] == 0x00)
        {
            break;
        }
        uartTxByte(arrayTemp_tDie[j]);
    }

    /* Add artificial space */
    uartTxByte(',');

    for (j = 0; j < sizeof(arrayTemp_vObj); j++)
    {
        if (arrayTemp_vObj[j] == 0x00)
        {
            break;
        }
        uartTxByte(arrayTemp_vObj[j]);
    }
}

/*!
 *
 * Function that erases data log from flash
 *
 * @param None
 *
 * @return None
 *
 */
void eraseDataLog(void)
{
    unsigned int i;

    /* Set Erase bit */
    FCTL1 = FWKEY + ERASE;

    /* Clear Lock bit */
    FCTL3 = FWKEY;

    for (i = 0; i < DATALOGSIZE; i=i+512)
    {
        data_log_tDie[i] = 0;
        /* Set Erase bit */
        FCTL1 = FWKEY + ERASE;
        data_log_vObj[i] = 0;
        /* Set Erase bit */
        FCTL1 = FWKEY + ERASE;
    }

    /* Clear WRT bit */
    FCTL1 = FWKEY;

    /* Set LOCK bit */
    FCTL3 = FWKEY + LOCK;

    /* Reset data log pointer */
    flashPtr = 0;
}

/*!
 *
 * Function that writes Tdie and Vobj to Flash
 *
 * @param Tdie die temperature
 * @param Vobj object voltage
 *
 * @return None
 *
 */
void dataLogger(int Tdie, int Vobj)
{
    /* Set WRT bit for write operation */
    FCTL1 = FWKEY + WRT;
    /* Clear Lock bit */
    FCTL3 = FWKEY;

    data_log_tDie[flashPtr] = Tdie;
    data_log_vObj[flashPtr++] = Vobj;

    /* Clear WRT bit */
    FCTL1 = FWKEY;
    /* Set LOCK bit */
    FCTL3 = FWKEY + LOCK;

    if (flashPtr == DATALOGSIZE)
    {
        flashPtr = 0;
    }
}

/*!
 *
 * Function that parses the received command for decoding and perform the
 * necessary functions:
 * 'D' - Dumps the raw data back to the PC
 * 'E' - Erases the data logged in Flash
 * 0xE4 - Changes conversion time to every 4 seconds
 * 0xE3 - Changes conversion time to every 2 seconds
 * 0xE2 - Changes conversion time to every 1 seconds
 * 0xE1 - Changes conversion time to every 0.5 seconds
 * 0xE0 - Changes conversion time to every 0.25 seconds
 * 0xBB - configures it in data streaming mode
 * 0xAA - configures it in data logging mode
 *
 * @param None
 *
 * @return None
 *
 */
void receivedDataCommand(unsigned char receiveData)
{
    long double * tDie;
    long double * vObj;
    long double dieTemp;
    long double voltObj;

    long double temp;

    if (receiveData == 'D')
    {
        unsigned int i = 0;

        /* Start dumping data out now */
        for (i = 0; i < DATALOGSIZE; i++)
        {
            if ((data_log_tDie[i] == 0xFFFF) && (data_log_vObj[i] == 0xFFFF))
            {
                break;
            }

            dieTemp = (long double) (data_log_tDie[i] >> 2);
            dieTemp = dieTemp * .03125 + 273.15;
            tDie = &dieTemp;
            voltObj = ((long double) data_log_vObj[i] * .00000015625);
            vObj = &voltObj;

            /* Calculate temperature */
            temp = tmp006_calculateTemp(tDie, vObj);

            /* Convert degree C to degree F */
            temp = temp*(1.8) + 32.0;

            /* Transmit data logging header packet */
            uartTxByte(0x81);

            /* Send temperature value to PC */
            sendTemp(temp);

            /* Send a comma separation */
            uartTxByte(',');

            /* Send raw data */
            sendRawData(data_log_tDie[i], data_log_vObj[i]);

            /* Send new line */
            uartTxByte(0x0A);
            uartTxByte(0x0D);
        }

        /* Send data logging header packet response */
        uartTxByte(0xFB);

        /* Send that data dump is successful */
        uartTxByte(receiveData);

        /* Send new line */
        uartTxByte(0x0A);
        uartTxByte(0x0D);
    }
    else if (receiveData == 'E')
    {
        /* Clear Data log */
        eraseDataLog();

        /* Send data logging header packet response */
        uartTxByte(0xFB);

        /* Send that erase is successful */
        uartTxByte(receiveData);

        /* Send new line */
        uartTxByte(0x0A);
        uartTxByte(0x0D);
    }
    else if ((receiveData & 0xF0) == 0xE0)
    {
        /* Configure sampling interval */

        /* Store the new conversion rate setting */
        conversionRateSetting = receiveData;

        /* Use the lower nibble to configure time interval */
        unsigned int converstionTime = receiveData & 0x0F;

        /* Shift left by 9 bits */
        converstionTime = converstionTime << 9;

        /* Re-configure TMP006 with DRDY pin enabled with a new conversion time */
        tmp006_init(1, converstionTime);
    }
    else if (receiveData == 0xBB)
    {
        /* Configure it to data streaming mode */
        mode = 0;

        /* Set P1.0 LED ON for data streaming mode */
        P1OUT |= BIT0;

        /* Configure Timer for PWM signals */
        configureTimerPwm();
    }
    else if (receiveData == 0xAA)
    {
        /* Configure it to data logging mode */
        mode = 1;

        /* Set P1.0 LED OFF for data streaming mode */
        P1OUT &= ~BIT0;

        /* Configure Timer for wake up */
        configureTimerWakeUp();
    }
    else if (receiveData == 0xFA)
    {
        /* Current configuration settings */
        sendCurrentState();
    }
}

/*!
 *
 * Send the current settings
 *
 */
void sendCurrentState(void)
{
    /* Current configuration settings */
    /* Send header packet back */
    uartTxByte(0xFA);

    /* Send mode */
    uartTxByte(mode);

    /* Send conversion rate */
    uartTxByte(conversionRateSetting);

    /* Send new line */
    uartTxByte(0x0A);
    uartTxByte(0x0D);
}

/*!
 *
 * Function that scans the last point in Flash when data log was last written
 *
 * @param None
 *
 * @return None
 *
 */
unsigned int scanLastPoint(void)
{
    unsigned int i;
    for (i = 0; i < DATALOGSIZE; i++)
    {
        if (data_log_tDie[i] == 0xFFFF)
        {
            return i;
        }
    }

    /* Else start from the beginning */
    return 0;
}

/*!
 *
 * Configure Timer1 for PWM mode in data streaming mode.
 *
 * @param None
 *
 * @return None
 *
 */
void configureTimerPwm(void)
{
    TA1CCR0 = TIMER_PWM_PERIOD;             //
    TA1CTL = TASSEL_2 | MC_1 | TACLR;       // TACLK = SMCLK, Up mode.
    TA1CCTL0 &= ~CCIFG;
    TA1CCTL1 &= ~CCIFG;
    TA1CCTL0 = CCIE;
    TA1CCTL1 = CCIE | OUTMOD_3;             // TACCTL1 Capture Compare
    TA1CCR1 = 1;
}

/*!
 *
 * Configure Timer1 for periodic wake-up only for data logging mode.
 *
 * @param None
 *
 * @return None
 *
 */
void configureTimerWakeUp(void)
{
    TA1CCTL1 &= ~CCIE;
    TA1CCTL0 = CCIE;
    TA1CCTL0 &= ~CCIFG;
    TA1CCTL1 &= ~CCIFG;
    TA1CCR0 = 50000;
    TA1CTL = TASSEL_1 | MC_1 | TACLR;               /* ACLK = VLO, up mode */
}

/*!
 *
 * Timer_A1 interrupt service routine. This interrupt handler handles PWM of LEDs
 * in Data streaming mode or generic timer mode in data logging mode
 *
 */
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer_A (void)
{
    if (mode)
    {
        /* Data logging mode */
        __bic_SR_register_on_exit(LPM3_bits);
    }
    else
    {
        /* Data streaming mode
         * in PWM mode. Switch LEDs on */
        if (tempPolarity == TEMP_HOT)
            RED_PxOUT |= RED_BIT;
        if (tempPolarity == TEMP_COLD)
            GREEN_PxOUT |= GREEN_BIT;
    }
    TA1CCTL0 &= ~CCIFG;
}

/*!
 *
 * Timer_A1 interrupt service routine. This interrupt handler handles PWM of LEDs
 * in Data streaming mode.
 *
 */
#pragma vector=TIMER1_A1_VECTOR
__interrupt void ta1_isr(void)
{
    TA1CCTL1 &= ~CCIFG;
    GREEN_PxOUT &= ~(GREEN_BIT + RED_BIT);
}

/*!
 *
 * Monitor P1.3 switch press
 *
 */
#pragma vector=PORT1_VECTOR
__interrupt void port1_isr(void)
{
    /* Toggle P1.0 LED to show if it is in data streaming mode or data logging mode
     * LED ON - DATA LOGGING mode
     * LED OFF - DATA STREAMING mode
     */
    P1OUT ^= BIT0;

    /* Toggle mode between data logging and data streaming */
    mode ^= 0x01;

    stateChanged = 1;

    /* Debounce switch */
    __delay_cycles(400000);

    /* Clear all interrupt flags */
    P1IFG = 0;

    if (mode)
    {
        /* Just switched over to data logging mode */
        configureTimerWakeUp();
    }
    else
    {
        /* Just switched over to data streaming mode */
        configureTimerPwm();

        /* Exit just in case it was in LPM during mode switch */
        __bic_SR_register_on_exit(LPM3_bits);
    }
}
