/* --COPYRIGHT--,BSD
 * Copyright (c) 2014, 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
 *
 * Out of Box Demo for the MSP-EXP430FR4133
 * Main loop, initialization, and interrupt service routines
 *
 * September 2014
 * E. Chen
 *
 * wM-Bus code added
 * M. Stefanov
 *
 ******************************************************************************/

#include "main.h"
#include <wdt_a.h>
#include "hal_LCD.h"
#include "3outof6.h"
#include "TempSensorMode.h"
#include <msp_wm430fr4_rtc.h>

#include "cs.h"


// Backup Memory variables to track states through LPM3.5
volatile unsigned char * S1buttonDebounce = &BAKMEM2_L;       // S1 button debounce flag
volatile unsigned char * S2buttonDebounce = &BAKMEM2_H;       // S2 button debounce flag
volatile unsigned char * batSensorRunning = &BAKMEM3_L;       // Stopwatch running flag
volatile unsigned char * tempSensorRunning = &BAKMEM3_H;      // Temp Sensor running flag
volatile unsigned char * mode = &BAKMEM7_L;                   // mode flag
volatile unsigned char * wmbusRunning = &BAKMEM7_H;      	  // WMBUS RF running flag
volatile unsigned int * rf_device = &BAKMEM8;                   // RF device Type: CC1120, CC1200, ...
volatile unsigned char * chip_ver = &BAKMEM9_L;      	  // RF Chip version 2.1 or 2.3, ...


volatile unsigned char * Seconds = &BAKMEM10_L;               // Store seconds in the backup RAM module
volatile unsigned char * Minutes = &BAKMEM10_H;               // Store minutes in the backup RAM module
volatile unsigned char * Hours = &BAKMEM11_L;                 // Store hours in the backup RAM module
volatile unsigned char * Days = &BAKMEM11_H;                 // Store hours in the backup RAM module
volatile unsigned char * Months = &BAKMEM12_L;               // Store seconds in the backup RAM module
volatile unsigned char * Years = &BAKMEM12_H;               // Store minutes in the backup RAM module

volatile unsigned char *txrxSet = &BAKMEM13_L;               // TX or RX operation flag
volatile unsigned char *freqBand = &BAKMEM13_H;               // TX or RX operation flag
volatile uint16_t *txPackets = &BAKMEM14;               // TX packets
volatile uint16_t *rxPackets = &BAKMEM15;               // RX packets

extern unsigned int degC, degF;

volatile unsigned int holdCount = 0;
bool bADC_done_flag = false; //for Battery measurement
// For ADC
uint32_t ui32Bat_Vol;

uint8_t const ui8Month_Table[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

extern tWMRTC tRTCData;
extern void RTC_Config();
// Fram record address
#define FRAM_RECORD_ADDRESS 0xFF00	 // Refresh every 1 second
#define FRAM_RECORD_CHECK 0xFF40	 // First record check address
#define FRAM_RECORD_BASE 0xFA00	     // Monthly record in stand-alone address

extern void ADC10_Config();

#ifdef Comm_Sub1GHz

#include <msp_wm430fr4_cc1120.h>
#include <mbus_packet.h>
#include "chip_detect.h"

uint32_t ui32Sum = 0;	                 // Total
/*
void FRAMWrite_Long(uint32_t *pFRAM_write_ptr, uint32_t ui32data)
{
	SYSCFG0 &= ~PFWP;
	*pFRAM_write_ptr = ui32data;
	SYSCFG0 |= PFWP;
}

void FRAMWrite_Char(uint8_t *pFRAM_write_ptr, uint8_t ui8data)
{
	SYSCFG0 &= ~PFWP;
	*pFRAM_write_ptr = ui8data;
	SYSCFG0 |= PFWP;
}
*/
//extern uint8_t WMbus_mode;
void ManualCalibration();
void wmbusInit();
bool bCC1120_Send_Flag = false;
extern void RegisterConfig(void);
//----------------------------------------------------------------------------------
//  Constants
//----------------------------------------------------------------------------------

//#define PKTLEN       20 // 1 < PKTLEN < 126 , 20 Bytes for Payload

/*******************************************************************************
*               Packet Examples from EN13757-4:2012
*   Packet S2:  0F 44 AE 0C 78 56 34 12 01 07 44 47 78 0B 13 43 65 87 1E 6D     (20 Bytes) S- and T-Modes with Format A
*   Packet C2:  14 44 AE 0C 78 56 34 12 01 07 8C 20 27 78 0B 13 43 65 87 7A C5  (21 Bytes) all other Modes with Format B
*/

uint8_t wMBusPacketC[]= {0x14,PACKET_C_FIELD, 0xAE, 0x0C, PACKET_CI_FIELD, 0x56, 0x34, 0x12, MAN_ID, MAN_VER, 0x8C, 0x20, 0x27, PACKET_CI_FIELD, 0x0B, 0x13, 0x43, 0x65, 0x87, 0x00, 0x00/*0x7A, 0xC5*/}; //C2-Mode

extern uint8_t TXpacket[];
extern uint8_t TXbytes[];
extern uint8_t TXdataLength;
extern uint16_t  packetLength, TmodeByteLength;

uint8_t ui8packetTxSemaphore=0;
volatile uint8_t ui8packetRxSemaphore=0;

uint16_t ui16wmbusACC_Counter=0; //8-bit field with increasing Number for AES-128, check EN13757-4 or OMSv3/v4 spec

static radioChipType_t pRadioChipType;

#endif

// TimerA0 UpMode Configuration Parameter
Timer_A_initUpModeParam initUpParam_A0 =
{
		TIMER_A_CLOCKSOURCE_SMCLK,              // SMCLK Clock Source
		TIMER_A_CLOCKSOURCE_DIVIDER_1,          // SMCLK/1 = 2MHz
		30000,                                  // 15ms debounce period
		TIMER_A_TAIE_INTERRUPT_DISABLE,         // Disable Timer interrupt
		TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE ,    // Enable CCR0 interrupt
		TIMER_A_DO_CLEAR,                       // Clear value
		true                                    // Start Timer
};

/*
 * main.c
 */
int main(void) {
    // Stop Watchdog timer
    WDT_A_hold(__MSP430_BASEADDRESS_WDT_A__);     // Stop WDT

    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    //FRCTL0 = FRCTLPW | NWAITS_1;

    //FR4133 MCLK runs at 8MHz

    // Check if a wakeup from LPMx.5
    if (SYSRSTIV == SYSRSTIV_LPM5WU)
    {
        Init_GPIO();  //LOCKLPM5 Bit is cleared inside this f()

        __enable_interrupt();
    }
    else   {
        // Start-up Initializations
        Init_GPIO();
        Init_Clock();

        P4SEL0 |= BIT1 | BIT2;                // set XT1 pin as second function

        do
        {
          CSCTL7 &= ~(XT1OFFG | DCOFFG);      // Clear XT1 and DCO fault flag
          SFRIFG1 &= ~OFIFG;
        } while (SFRIFG1 & OFIFG);            // Test oscillator fault flag

        CSCTL3 |= SELREF__XT1CLK;             // Set XT1CLK as FLL reference source
        CSCTL1 &= ~(DCORSEL_7);               // Clear DCO frequency select bits first
        CSCTL1 |= DCORSEL_3;                  // Set DCO = 8MHz
        CSCTL2 = FLLD_0 + 243;                // DCODIV = 8MHz

        do
        {
          __delay_cycles(7 * 31 * 8);                 // Requires 7 reference clock delay before
                                                      // polling FLLUNLOCK bits @8 MHz, ~1736 cycles
        } while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));  // Poll until FLL is locked

        CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK;     // Set ACLK = XT1CLK = 32768Hz
                                                      // DCOCLK = MCLK and SMCLK source
        CSCTL5 |= DIVM_0 | DIVS_1;                    // MCLK = DCOCLK = 8MHZ,
                                                      // SMCLK = MCLK/2 = 4MHz

        Init_RTC();
        RTC_Config();
        Init_LCD();
		clearLCD();

		*mode = WMbus_mode; 	//Set Default wM-Bus Mode (any of 868/433 or 169Mhz band)
		if (*mode>0 && *mode<4)
			*freqBand = 86;
		else if (*mode>0 && *mode==4)
			*freqBand = 43;
		else if (*mode!= 8 && *mode >4)
			*freqBand = 16;

        ADC10_Config();

        GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN2);  //Pins for Buttons
        GPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN6);

        *S1buttonDebounce = *S2buttonDebounce = *batSensorRunning = *tempSensorRunning = *txrxSet = * wmbusRunning = * txPackets = *rxPackets = 0;

        __enable_interrupt();

        displayScrollText("FR4133 WMBUS KIT");

        wmbusInit();    // initialize wMBus mode
        __delay_cycles(4000000);
       	while (*txrxSet == 0) {
           showString("RX  TX");
       	}

       	RegisterConfig();  //initialize CC1xxx device with Settings as selected per WMbus_mode in mbus_packet.h

       	TrxSpiCmdStrobe(CC112X_SPWD); //CC1120 in Sleep mode
    }


    // Check if the first record or not
    if((*((uint32_t *)FRAM_RECORD_CHECK)) == 0xAA) {
    		ui32Sum = *((uint32_t *)FRAM_RECORD_ADDRESS); // Load the last data
    }
    else    {
    	ui32Sum = 0;
    	FRAMWrite_Long((uint32_t *)FRAM_RECORD_CHECK,0xAA);
    }


    while(1)
    {
        LCD_E_selectDisplayMemory(LCD_E_BASE, LCD_E_DISPLAYSOURCE_MEMORY);

#ifdef Comm_Sub1GHz

        while (*wmbusRunning == 0) {
            showString("S1  TX");
        }

		if (bCC1120_Send_Flag && *wmbusRunning == 1 && *txrxSet == 1) 		{ //TX operation
						// update wMbus packet counter
			ui16wmbusACC_Counter++;

    	// Calculate total number of bytes in the wireless MBUS packet
    	//Update packet and UPDATE CRC16!!!
		if (WMbus_mode == WMBUS_SMODE || WMbus_mode == WMBUS_TMODE ) {

		//Update packet and UPDATE CRC16!!!
		TXpacket[15] = (unsigned char) ((ui16wmbusACC_Counter&0x00FF0000)>>16);
		TXpacket[16] = (unsigned char) ((ui16wmbusACC_Counter&0x0000FF00)>>8);
		TXpacket[17] = (unsigned char) (ui16wmbusACC_Counter&0x000000FF);
		}

		if (*mode == WMBUS_SMODE) {
		    encodeTXPacket(TXbytes, TXpacket, TXdataLength);
			packetLength = packetSize (TXpacket[0]); //works for S-mode packet with Manchester in HW
			cc112xSpiWriteTxFifo(TXbytes, packetLength);
		}

		else if (*mode == WMBUS_TMODE) {
			TXpacket[13] = DIF_FIELD; //0x0B; need overwrite due to TXpacket->TXbytes->TXpacket handling
			TXpacket[14] = VIF_FIELD; //0x13;
			encodeTXPacket(TXbytes, TXpacket, TXdataLength);

			//calculate T-mode TXpacket length
			packetLength = packetSize (TXbytes[0]); //works for S-mode packet with Manchester in HW
			encodeTXBytesTmode(TXpacket, TXbytes, packetLength);
			TmodeByteLength = byteSize(2, 1, packetLength);
			cc112xSpiWriteTxFifo(TXpacket, TmodeByteLength);
		}

	    else if (*mode == WMBUS_CMODE || *mode == WMBUS_C2MODE || *mode == WMBUS_NabefMODE || WMbus_mode == WMBUS_NcdMODE || WMbus_mode == WMBUS_NgMODE ||
					    		 	 WMbus_mode == WMBUS_FMODE ) {
			wMBusPacketC[16] = (unsigned char) ((ui16wmbusACC_Counter&0x00FF0000)>>16);
			wMBusPacketC[17] = (unsigned char) ((ui16wmbusACC_Counter&0x0000FF00)>>8);
			wMBusPacketC[18] = (unsigned char) (ui16wmbusACC_Counter&0x000000FF);

			packetLength = packetSize (wMBusPacketC[0]);
			encodeTXPacket(TXbytes, wMBusPacketC, packetLength);

			// write wM-Bus packet to tx fifo
			cc112xSpiWriteTxFifo(TXbytes, packetLength);
		}

	   // strobe TX to send packet
	   TrxSpiCmdStrobe(CC112X_STX);

	   // wait for interrupt that packet has been sent.
	   // (Assumes the GPIO connected to the radioRxTxISR function is set
		// to GPIOx_CFG = 0x06)
	   while (!ui8packetTxSemaphore);
	   // clear semaphore flag
	   ui8packetTxSemaphore = 0;
	   (*txPackets)++;

	   showString("TX    ");
	   // TX symbol ON
	   LCDMEM[pos6+1] |= 0x04;
	   // ANT symbol ON
	   LCDMEM[pos3+1] |= 0x04;

	    // Handles displaying up to 9999 packets
	    if (*txPackets >= 1000)
	    showChar( ((*txPackets / 1000) % 10 + '0'), pos3);
	   // LCDMEMW[position/2] = digit[c-48][0] | (digit[c-48][1] << 8);
	    if (*txPackets >= 100)
	        showChar((*txPackets/100) %10 + '0',pos4);
	    if (*txPackets >= 10)
	        showChar((*txPackets/10)%10 + '0',pos5);
	    if (*txPackets >= 1)
	        showChar((*txPackets/1)%10 + '0',pos6);

		bCC1120_Send_Flag = false;

		TrxSpiCmdStrobe(CC112X_SPWD);
//		SPI_Standby();
		}

		else if(*wmbusRunning == 1 && *txrxSet == 2) 		{ //TX operation

			TrxSpiCmdStrobe(CC112X_SIDLE);
			TrxSpiCmdStrobe(CC112X_SFRX);

			if (*rxPackets == 0) {
				showString("RX    ");
				// ANT symbol ON
				LCDMEM[pos3+1] |= 0x04;
				// RX symbol ON
				LCDMEM[pos6+1] |= 0x01;
			}

			TrxSpiCmdStrobe(CC112X_SIDLE);
			TrxSpiCmdStrobe(CC112X_SRX);

				// wait for interrupt that packet has been sent.
		    	// (Assumes the GPIO connected to the radioRxTxISR function is set
		    	// to GPIOx_CFG = 0x06)
		    while (!ui8packetRxSemaphore);
		    // clear semaphore flag
		    //read out packet
		    CC1120_RX_PROCESS(); //reads out RX FIFO into TXbytes
		    ui8packetRxSemaphore = 0;

			// Check if wM-Bus CRC ok
		    if (*mode == WMBUS_CMODE || *mode == WMBUS_C2MODE || *mode == WMBUS_NabefMODE || WMbus_mode == WMBUS_NcdMODE || WMbus_mode == WMBUS_NgMODE ||
		    					    		 	 WMbus_mode == WMBUS_FMODE ) {

		    	packetLength = TXbytes[0];
			    //decode it and if CRC16 OK then count up RX packets
		    	if (decodeTXPacket( TXpacket, TXbytes, packetLength+1) == 0 && packetLength > 9) //at least 1. Block
		    		  (*rxPackets)++;
		    }
		    else if (*mode == WMBUS_SMODE) {
		    	packetLength = packetSize (TXbytes[0]); //works for S-mode packet with Manchester in HW

		    	if (decodeRXBytesSmode( TXpacket, TXbytes, packetLength) == 0 && packetLength > 9) //at least 1. Block
		    		 (*rxPackets)++;
			}

		    else if (*mode == WMBUS_TMODE) {
		    	//decode 3-of-6 Bytes
		    	if ( decode3outof6(TXbytes, TXpacket, 0) == 0)
		    		packetLength = packetSize (TXpacket[0]);
		    	if (decodeRXBytesTmode(TXbytes, TXpacket, packetLength) == 0 && packetLength > 9) //at least 1. Block
		    	 		 (*rxPackets)++;
		    }

		    // Handles displaying up to 9999 packets
		   	if (*rxPackets >= 1000)
		   	    showChar( ((*rxPackets / 1000) % 10 + '0'), pos3);
		   	   // LCDMEMW[position/2] = digit[c-48][0] | (digit[c-48][1] << 8);
		    if (*rxPackets >= 100)
		   	        showChar((*rxPackets/100) %10 + '0',pos4);
		    if (*rxPackets >= 10)
		   	       showChar((*rxPackets/10)%10 + '0',pos5);
		    if (*rxPackets >= 1)
		   	        showChar((*rxPackets/1)%10 + '0',pos6);

			TrxSpiCmdStrobe(CC112X_SRX);
		}


#endif

       // }
        __bis_SR_register(LPM3_bits | GIE);         // enter LPM3
        __no_operation();
    }
}

/*
 * GPIO Initialization
 */
void Init_GPIO()
{
    // Set all GPIO pins to output low to prevent floating input and reduce power consumption
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P7, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setOutputLowOnPin(GPIO_PORT_P8, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);

    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P7, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
    GPIO_setAsOutputPin(GPIO_PORT_P8, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);

    GPIO_setAsInputPin(GPIO_PORT_P1, GPIO_PIN1 |GPIO_PIN5 |GPIO_PIN7);

    // Configure button S1 (P1.2) interrupt
    GPIO_selectInterruptEdge(GPIO_PORT_P1, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN2);
    GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN2);
    GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN2);

    // Configure button S2 (P2.6) interrupt
    GPIO_selectInterruptEdge(GPIO_PORT_P2, GPIO_PIN6, GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P2, GPIO_PIN6);
    GPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN6);
    GPIO_enableInterrupt(GPIO_PORT_P2, GPIO_PIN6);

    //configure GPIO0 from CC112x (P1.7) interrupt
    GPIO_selectInterruptEdge(GPIO_PORT_P1, GPIO_PIN7, GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN7);
    GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN7);
    GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN7);

    // Configure GPIO3 (P1.5) interrupt
    GPIO_selectInterruptEdge(GPIO_PORT_P1, GPIO_PIN5, GPIO_LOW_TO_HIGH_TRANSITION);
    GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_P1, GPIO_PIN5);
    GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN5);
    GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN5);

    // Set P4.1 and P4.2 as Secondary Module Function Input, LFXT.
    GPIO_setAsPeripheralModuleFunctionInputPin(
           GPIO_PORT_P4,
           GPIO_PIN1 + GPIO_PIN2,
           GPIO_PRIMARY_MODULE_FUNCTION
           );

    // Disable the GPIO power-on default high-impedance mode
    // to activate previously configured port settings
    PMM_unlockLPM5();
}

/*
 * Clock System Initialization
 */
void Init_Clock()
{
    // Intializes the XT1 crystal oscillator
   //CS_turnOnXT1(CS_XT1_DRIVE_1);
    //CS_XT1Start(CS_XT1_DRIVE_1);

    CS_turnOnXT1LF(CS_XT1_DRIVE_1);
}

/*
 * Real Time Clock counter Initialization
 */
void Init_RTC()
{
    RTC_setModulo(RTC_BASE, 32768);
    RTC_enableInterrupt(RTC_BASE, RTC_OVERFLOW_INTERRUPT);
}

/*
 * SPI Init to RF and  RF chip detect
 */
void wmbusInit()
{
    // Set SPI to master 3-pin config
	SPI_Config();
	trxDetectChipType(&pRadioChipType);
	rf_device = (unsigned int*) pRadioChipType.deviceName;
	chip_ver = (unsigned char*) pRadioChipType.ver;

	if (rf_device == (unsigned int*) 0x1120 && chip_ver == (unsigned char*) 0x21) {
		ManualCalibration();
	   showString("CC1120");
	}
	else if (pRadioChipType.deviceName == 0x1200) {
		showString("CC1200");
	}
}


/*
 * PORT1 Interrupt Service Routine
 * Handles S1 button press interrupt
 */
#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
    P1OUT |= BIT0;    // Turn LED1 On
    switch(__even_in_range(P1IV, P1IV_P1IFG7))
    {
        case P1IV_NONE : break;
        case P1IV_P1IFG0 : break;
        case P1IV_P1IFG1 : break;
        case P1IV_P1IFG2 :
            if ((*S1buttonDebounce) == 0)
            {
                *S1buttonDebounce = 1;                        // First high to low transition
                holdCount = 0;
                if (*txrxSet == 0) {
                    *txrxSet = 2; //RX operation selected
                    *wmbusRunning = 1;
                    clearLCD(); //print S_mode on LCD
                    showString("RX    ");
                }

                // Start debounce timer
                Timer_A_initUpMode(TIMER_A0_BASE, &initUpParam_A0);
                break;
            }
        case P1IV_P1IFG3 : break;
        case P1IV_P1IFG4 : break;
        case P1IV_P1IFG5 :
#ifdef Comm_Sub1GHz

		// set packet semaphore Pin 1.5 is GPIO3, use as RX Sync word Interrupt Flag?
    //    if ( *txrxSet == 2 /* RX operation selected */ &&  *wmbusRunning ==1)
  //        ui8packetRxSemaphore = 1;
		// clear isr flag
#endif
        	break;
        case P1IV_P1IFG6 : break;

        case P1IV_P1IFG7 : //Pin 1.7 is GPIO0, use as Interrupt Flag
#ifdef Comm_Sub1GHz
		// set packet semaphore
        if ( *txrxSet == 1 /*TX operation selected */ &&  *wmbusRunning ==1)
		  ui8packetTxSemaphore = 1;
        else if ( *txrxSet == 2 /* RX operation selected */ &&  *wmbusRunning ==1)
          ui8packetRxSemaphore = 1;
		// clear isr flag
#endif
        	break;
    }
    P1OUT &= ~BIT0;    // Turn LED1 On
}

/*
 * PORT2 Interrupt Service Routine
 * Handles S2 button press interrupt
 */
#pragma vector = PORT2_VECTOR
__interrupt void PORT2_ISR(void)
{
    P4OUT |= BIT0;    // Turn LED2 On
    switch(__even_in_range(P2IV, P2IV_P2IFG7))
    {
        case P2IV_NONE : break;
        case P2IV_P2IFG0 : break;
        case P2IV_P2IFG1 : break;
        case P2IV_P2IFG2 : break;
        case P2IV_P2IFG3 : break;
        case P2IV_P2IFG4 : break;
        case P2IV_P2IFG5 : break;
        case P2IV_P2IFG6 :
            if ((*S2buttonDebounce) == 0)  {
                *S2buttonDebounce = 1;                        // First high to low transition
                holdCount = 0;

                if (*txrxSet == 0) {
                	*txrxSet = 1; //TX
                	*wmbusRunning = 1;
                	clearLCD(); //print S_mode on LCD
                	displayScrollText("TX");
                	break;
                }
            //    else if
              //
               // 	break;
              //  }

                switch (*mode)
                {
                    case WMBUS_SMODE:
                    	clearLCD(); //print S_mode on LCD
                        displayScrollText("S-MODE 868.3 MHZ");
                            // Toggle between LCD Normal/Blink memory
                   // LCDMEMCTL ^= LCDDISP;

                        break;
                    case WMBUS_TMODE:
                    	clearLCD(); //print S_mode on LCD
                    	displayScrollText("T-MODE 868.95 MHZ");
                        break;

                    case WMBUS_CMODE:
                    	clearLCD(); //print S_mode on LCD
                    	displayScrollText("C-MODE 868.95 MHZ");
                    break;

                    case WMBUS_C2MODE:
                    	clearLCD(); //print S_mode on LCD
                    	displayScrollText("C2-MODE 869.525 MHZ");
                    break;

                    case WMBUS_FMODE:
                                        	clearLCD(); //print S_mode on LCD
                                            displayScrollText("F-MODE 433 MHZ");
                                                // Toggle between LCD Normal/Blink memory
                                       // LCDMEMCTL ^= LCDDISP;

                                            break;
                    case WMBUS_NabefMODE:
                                        	clearLCD(); //print S_mode on LCD
                                        	displayScrollText("N-AB 169 MHZ");
                    break;
                                        case WMBUS_NcdMODE:
                                        	clearLCD(); //print S_mode on LCD
                                        	displayScrollText("N-CD 169 MHZ");
                                        break;
                                        case WMBUS_NgMODE:
                                        	clearLCD(); //print S_mode on LCD
                                        	displayScrollText("N-G 169 MHZ");
                                        break;
                }

                // Start debounce timer
                Timer_A_initUpMode(TIMER_A0_BASE, &initUpParam_A0);
            }


        case P2IV_P2IFG7 : break;
    }
    P4OUT &= ~BIT0;    // Turn LED2 OFF
}

/*
 * Timer A0 Interrupt Service Routine
 * Used as button debounce timer
 */
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR (void)
{
    // Both button S1 & S2 held down
    if (!(P1IN & BIT2) && !(P2IN & BIT6))
    {
        holdCount++;
        if (holdCount == 40)
        {
            // Stop Timer A0
            Timer_A_stop(TIMER_A0_BASE);

            // Change mode
            clearLCD();
            wmbusRunning=0;

            __bic_SR_register_on_exit(LPM3_bits);                // exit LPM3
        }
    }

    // Button S1 released
    if (P1IN & BIT2)
    {
        *S1buttonDebounce = 0;                                   // Clear button debounce
        P1OUT &= ~BIT0;
    }

    // Button S2 released
    if (P2IN & BIT6)
    {
        *S2buttonDebounce = 0;                                   // Clear button debounce
        P4OUT &= ~BIT0;
    }

    // Both button S1 & S2 released
    if ((P1IN & BIT2) && (P2IN & BIT6))
    {
        // Stop timer A0
    	Timer_A_stop(TIMER_A0_BASE);
        __bic_SR_register_on_exit(LPM3_bits);            // exit LPM3
    }
}

/*
 * RTC Interrupt Service Routine wakes every 1sec
 */
#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
	{
		uint8_t ui8Days = 31;
		uint8_t *pAddress;              // For monthly data storage

		tRTCData.ui8Second++;			//Inc RTC tick
        * Seconds = tRTCData.ui8Second;

#ifdef Comm_Sub1GHz
		if (tRTCData.ui8Second & 0x4 == 0x4 ) //every 15sec a TX % 15 == 0
				bCC1120_Send_Flag = true;  // TX the wM-Bus packet flag
#endif

		if(tRTCData.ui8Second == 30) {
			//add Flag for Temp. measurement (reuse TempSensor code)
			PMMCTL2 |= INTREFEN;                // 1.5V voltage reference generate
			ADCCTL0 = ADCSHT_8 + ADCON;         // 256 ADCCLK cycles
			*tempSensorRunning = 1;				//Temperature Sensor inside ADC active, ADCIFG Flag
			* batSensorRunning = 0; 			//Voltage Reference Sensor inside ADC active, ADCIFG Flag
		}


		if(tRTCData.ui8Second == 59)
		{
			PMMCTL2 |= INTREFEN;                // 1.5V voltage reference generate
			ADCCTL0 = ADCSHT_8 + ADCON;         // 256 ADCCLK cycles
			//add Flag for Battery voltage measurement
			*batSensorRunning = 1;
		}


		if (tRTCData.ui8Second >= 60)      { // 60s
			ADCCTL0 |= ADCENC + ADCSC;  // Battery voltage detect each 1 minute
			tRTCData.ui8Second = 0;
			tRTCData.ui8Minute++;  // count up Minutes
			* Minutes = tRTCData.ui8Minute; //Add to backup Memory
			if (tRTCData.ui8Minute >= 60)
			{
				tRTCData.ui8Minute = 0;
				tRTCData.ui8Hour++;
				* Hours = tRTCData.ui8Hour; //Add to backup Memory
			}

			if (tRTCData.ui8Hour >= 24)
			{
				tRTCData.ui8Hour = 0;
				tRTCData.ui8Day++;
				* Days = tRTCData.ui8Day; //Add to backup Memory
				if (tRTCData.ui8Month == 2)
				{
					if (tRTCData.ui8Year % 4 == 0)
					{
						ui8Days = 29;
					}
					else
					{
						ui8Days = 28;
					}
				}
				else
				{
					ui8Days = ui8Month_Table[tRTCData.ui8Month - 1];
				}
			}

			if (tRTCData.ui8Day > ui8Days)	//Month is over
			{
				// Monthly record
				pAddress = (uint8_t *)(FRAM_RECORD_BASE + (tRTCData.ui8Year - 13)*120 + (tRTCData.ui8Month - 1)*10);
				FRAMWrite_Char(pAddress++,tRTCData.ui8Year);
				FRAMWrite_Char(pAddress++,tRTCData.ui8Month);
				FRAMWrite_Char(pAddress++,tRTCData.ui8Day-1);
				FRAMWrite_Char(pAddress++,tRTCData.ui8Hour);
				FRAMWrite_Char(pAddress++,tRTCData.ui8Minute);
				FRAMWrite_Char(pAddress++,tRTCData.ui8Second);
				FRAMWrite_Long((uint32_t *)(pAddress++),ui32Sum);

				tRTCData.ui8Day = 1;
				tRTCData.ui8Month++;
				* Months = tRTCData.ui8Month; //Add to backup Memory
			}

			if (tRTCData.ui8Month > 12)
			{
				tRTCData.ui8Month = 1;
				tRTCData.ui8Year++;
				* Years = tRTCData.ui8Year; //Add to backup Memory
			}
		}
		__low_power_mode_off_on_exit();
	}
	break;
	default: break;
	}
}

/*
 * ADC Interrupt Service Routine
 * Wake up from LPM3 when ADC conversion completes
 */
#define CALADC_15V_30C  *((unsigned int *)0x1A1A)               // Temperature Sensor Calibration-30 C
                                                                // See device datasheet for TLV table memory mapping
#define CALADC_15V_85C  *((unsigned int *)0x1A1C)               // Temperature Sensor Calibration-85 C

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC_VECTOR
__interrupt void ADC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
    {
        case ADCIV_NONE:
            break;
        case ADCIV_ADCOVIFG:
            break;
        case ADCIV_ADCTOVIFG:
            break;
        case ADCIV_ADCHIIFG:
            break;
        case ADCIV_ADCLOIFG:
            break;
        case ADCIV_ADCINIFG:
            break;
        case ADCIV_ADCIFG:

        	if (*batSensorRunning) {
				ui32Bat_Vol = (uint32_t)150 * 1023 / (ADCMEM0&0x3FF); //100; reading ADCMEM0 resets the Conversion done IFG
				bADC_done_flag = true;
				PMMCTL2 &= ~INTREFEN;   // For low power
				ADCCTL0 &= ~ADCON;
				*batSensorRunning = false;
				//*tempSensorRunning = true;
				if(ui32Bat_Vol < 280)   	{
				// if Battery low then raise Low Power Flag Status Bit in the next and all subsequent wM-Bus Frames .....
				// TX with Bit set for Low-power Error
				}
        	}
        	else if (*tempSensorRunning)		{		//Temperature Sensor inside ADC active, ADCIFG Flag
        		//Temp measurement
        		//*batSensorRunning = true;
        		*tempSensorRunning = false;

        		// Calculate Temperature in degree C and F
        		signed short temp = (ADCMEM0 - CALADC_15V_30C);
        	//	*degC = ((long)temp * 10 * (85-30) * 10)/((CALADC_15V_85C-CALADC_15V_30C)*10) + 300;
        	//	*degF = (*degC) * 9 / 5 + 320;

        	}
            break;
        default:
            break;
    }
}
