#include "msp.h"
/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

//#define BSL_PARAM 0xFC48DFFF // I2C slave address = 0x48, Interface selection = UART
#define BSL_PARAM 0xFC48FFFF // I2C slave address = 0x48, Interface selection = AUTO
#define BSL_API_TABLE_ADDR 0x00202000 // Address of BSL API table
#define BSL_ENTRY_FUNCTION (*((uint32_t *)BSL_API_TABLE_ADDR))

volatile unsigned long timer=0;
volatile char status=0;
#define STATUS_RUHE     0b00000000
#define STATUS_BSL      0b00000100


/**
 * ISR
 */
// Timer32_0 ISR
void Timer32_0_INT (void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
    //Testweise rote LED toggeln
    MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1,GPIO_PIN0);
    timer++;
}

void PORT1_IRQHandler(void)
{
    MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2,GPIO_PIN0);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
    status=STATUS_BSL;
}

void port_init (void)
{
    //MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PJ, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P3, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P4, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P5, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, (PIN_ALL8 & ~GPIO_PIN7));
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P7, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P8, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P9, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P10, PIN_ALL8);
    /* Configure I/O to minimize power consumption before going to sleep */
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P3, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P5, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P7, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P8, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P9, PIN_ALL8);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P10, PIN_ALL8);
    //MAP_GPIO_setAsOutputPin(GPIO_PORT_PJ, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3);
    PJDIR = 0xff; PJOUT = 0; PJSEL0 = 0x30; PJSEL1 = 0;

    //Configuring LFXTOUT and LFXTIN for XTAL operation
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_PJ, GPIO_PIN0 | GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);

    //Interrupt für RX-Pin aktivieren
    MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
    MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P1, GPIO_PIN1, GPIO_HIGH_TO_LOW_TRANSITION);
    MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);
    MAP_Interrupt_enableInterrupt(INT_PORT1);
}

/*
 * Timer 32 Init-Routine
 *
 */
void timer32_init(void)
{
    //Timer32 Initialisieren
    MAP_Timer32_initModule(TIMER32_0_BASE,TIMER32_PRESCALER_16,TIMER32_32BIT,TIMER32_PERIODIC_MODE);
    //ReloadValue auf 93750 setzen um den Timer jede 0,5 Sekunden einen Int erzeugen zu lassen
    //ReloadValue auf 187500 setzen um den Timer jede 1 Sekunden einen Int erzeugen zu lassen
    MAP_Timer32_setCountInBackground(TIMER32_0_BASE,93750);
    MAP_Timer32_setCount(TIMER32_0_BASE,93750);
    //Interrupt aktivieren
    MAP_Timer32_registerInterrupt(TIMER32_0_INTERRUPT,Timer32_0_INT);
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
    MAP_Timer32_enableInterrupt(TIMER32_0_BASE);
    //Timer starten
    MAP_Timer32_startTimer(TIMER32_0_BASE,false);
}



/**
 * main.c
 */
void main(void)
{
    MAP_WDT_A_holdTimer();

    port_init();

    /* Starting LFXT */
    //Externer Quarz für RTC 32,768kHz
    MAP_CS_setExternalClockSourceFrequency(32768,0);
    MAP_CS_startLFXT(CS_LFXT_DRIVE3);
    MAP_CS_initClockSignal(CS_BCLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
    //Externen Quarz für ACLK
    MAP_CS_initClockSignal(CS_ACLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
    //Interne Clocksource für Uart und alles weitere (3MHz)
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);

    timer32_init();

    MAP_Interrupt_enableMaster();

    while (1)
    {
        __no_operation();
        if((status && STATUS_BSL) > 0)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2,GPIO_PIN1);
            status=STATUS_RUHE;
            MAP_Interrupt_disableMaster();

            //Eiskalt alle Int-Anforderungen löschen
            NVIC->ICER[0] = 0xFFFF;
            NVIC->ICPR[0] = 0xFFFF;
            NVIC->ICER[1] = 0xFFFF;
            NVIC->ICPR[1] = 0xFFFF;
            NVIC->IABR[0] = 0xFFFF;
            NVIC->IABR[1] = 0xFFFF;

            //BSL aufrufen und hoffentlich neue Firmware erhalten
            ((void (*)())BSL_ENTRY_FUNCTION)((uint32_t)BSL_PARAM); // Call the BSL with given BSL parameters

        }
    }
}
