/******************************************************************************
*  LPC11U24 ReinvokeISP demoprogram for MicroCore64 board (by Paul Seerden)
*
*******************************************************************************/

#include <LPC11Uxx.h>                          // LPC11Uxx definitions

#define   LPCXpresso           0               // select KEIL or LPCXpresso

#define   IAP_LOCATION         (0x1fff1ff1)
#define   IAP_REINVOKE_ISP     (57)

typedef void (*IAP)(unsigned long *, unsigned long *);

const IAP iap_entry = (IAP)IAP_LOCATION;

#if !LPCXpresso
__asm void __set_msp(uint32_t sp)
{
    MOV sp,r0
    BX lr
}
#endif

void SysTick_Handler(void)
{
  static uint8_t cnt = 0;

    if (++cnt > 20)                            // 20 * 10 msec = 200 msec
    {
        cnt = 0;
        LPC_GPIO->NOT[1] = 1 << 26;            // toggle LED1
    }
}

int main(void)
{
  unsigned long cmd[5];
  unsigned long res[4];

    SysTick_Config(SystemCoreClock/100);       // generate IRQ each 10 ms
    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 6);     // enable clock for GPIO
    LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 16);    // enable clock for IOCON

    LPC_GPIO->DIR[1] |= (1 << 26);             // configure P1.26 (LED1) as output

    while (1)                                  // loop forever
    {
        if (!(LPC_GPIO->PIN[0] & (1<<16)))     // P0.16 low ?
        {                                      // yes then reinvoke ISP
            cmd[0] = IAP_REINVOKE_ISP;
#if LPCXpresso
            __SET_MSP(0x10001800 - 32);        // for LPCXpresso: set stack pointer to RAM top - 32 bytes
#else
            __set_msp(0x10001800 - 32);        // for KEIL: set stack pointer to RAM top - 32 bytes
#endif
            iap_entry(cmd, res);               // enter ISP
        }
    }
}
