This is the code used on my video series "Hybrid Supercapacitor Car Battery" for my own hardware monitoring system. THe videos can be found on madelectronengineering.com

Dependencies:   BurstSPI Fonts INA219 mbed LPC1114_WakeInterruptIn

Fork of SharpMemoryLCD by Paul Staron

Revision:
2:0c49a8f32f6e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Device/WakeUp_LPC11XX.cpp	Tue Dec 26 21:30:09 2017 +0000
@@ -0,0 +1,165 @@
+/**
+See homepage of this lib for LPC11xx special treatment
+**/
+
+#ifdef TARGET_LPC11XX_11CXX
+
+#include "WakeUp.h"
+#include "WakeInterruptIn.h"
+#include "pinmap.h"
+#include "toolchain.h"
+
+//Pin used, allowed pins = P0_1 (dp24, default), P0_8 (dp1) and P0_9 (dp2)
+//By defining WakeUpPin in for example your main.cpp this can be overridden
+WEAK PinName WakeUpPin = dp24;
+extern PinName WakeUpPin;
+
+WakeInterruptIn IRQ_in(WakeUpPin);
+PwmOut pulse_out(WakeUpPin);
+
+Callback<void()> WakeUp::callback;
+float WakeUp::cycles_per_ms = 20.0;
+
+static uint32_t old_clk_sel = ~0;
+static uint32_t SYSAHBCLKCTRL;
+static uint32_t TCR, PR, MR3;
+static LPC_TMR_TypeDef *WakeUpTimer;
+static uint32_t SYSAHBCLKCTRL_Sleep;
+static uint8_t WakeUpTimer_Match;
+
+static inline void restore(void);
+
+
+void WakeUp::set_ms(uint32_t ms)
+{
+    if (old_clk_sel == ~0) {                                //Only during first run
+        old_clk_sel = LPC_SYSCON->MAINCLKSEL;
+        SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
+        
+        switch(WakeUpPin) {
+            case dp24:
+                WakeUpTimer = LPC_TMR32B0;
+                SYSAHBCLKCTRL_Sleep = 0x15 | (1<<9);
+                WakeUpTimer_Match = 2;
+                break;
+            case dp1:
+                WakeUpTimer = LPC_TMR16B0;
+                SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
+                WakeUpTimer_Match = 0;
+                break;
+            case dp2:
+                WakeUpTimer = LPC_TMR16B0;
+                SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
+                WakeUpTimer_Match = 1;
+                break;
+            default:
+                error("Invalid WakeUp pin, choose dp1, dp2 or dp24");
+        }            
+    }
+        
+    if (ms != 0) {        
+        if (LPC_SYSCON->SYSAHBCLKCTRL != SYSAHBCLKCTRL_Sleep)    //Always when it is different from sleep settings
+            SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
+
+        LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
+        LPC_SYSCON->PDSLEEPCFG = 0x000018B7 | (LPC_SYSCON->PDRUNCFG & (PDRUNCFG_WDTOSC_PD | PDRUNCFG_BOD_PD)); 
+        
+        //Set oscillator for 20kHz
+        LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
+        
+        //Store old PWM
+        TCR = WakeUpTimer->TCR;
+        PR = WakeUpTimer->PR;
+        MR3 = WakeUpTimer->MR3;
+        
+        //Setup PWM
+        WakeUpTimer->TCR = TMR16B0TCR_CRST;
+        uint32_t ticks = (float)ms * cycles_per_ms;
+        
+        //whatever timer it is, we treat it as 16-bit (with PR that is 32-bit still, do the math, it is enough for this)
+        WakeUpTimer->PR = ticks >> 16;
+        WakeUpTimer->MR[WakeUpTimer_Match] = ticks / ((ticks >> 16) + 1);
+        WakeUpTimer->MR3 = 0xFFFF;
+                
+        IRQ_in.rise(irq_handler);
+        
+        //Disable most peripherals
+        LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL_Sleep;
+        
+        //Switch clock to WD OSC
+        LPC_SYSCON->MAINCLKSEL = 0x2;
+        LPC_SYSCON->MAINCLKUEN = 0;
+        LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
+        
+        //Enable PWM:
+        WakeUpTimer->TCR = TMR16B0TCR_CEN;
+    } else {
+        //Else restore normal settings
+        restore();
+    }
+    
+}
+
+void WakeUp::irq_handler(void)
+{    
+    restore();    
+    callback.call();
+}
+
+void WakeUp::calibrate(void)
+{
+    //Save current pin function
+    __IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + (dp24 & 0xFF));
+    uint32_t old_pinfun = *reg;
+    
+    //Set oscillator for 20kHz
+    LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
+    LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
+    
+    //Direct WDT to the CLKOUT pin (dp24), sample it back
+    DigitalIn din(dp24);
+    Timer timer;
+    
+    LPC_SYSCON->CLKOUTDIV = 1;
+    LPC_SYSCON->CLKOUTCLKSEL = 0x2;
+    LPC_SYSCON->CLKOUTUEN = 0;
+    LPC_SYSCON->CLKOUTUEN = CLKOUTUEN_ENA;
+    pin_function(dp24, 1);
+    
+    int count = 0;
+    timer.start();
+    while (timer.read_ms() < 100) {
+        while (din.read() == 0);
+        while (din.read() == 1);
+        count++;
+    }
+    cycles_per_ms = (float)count / 100.0f;
+    
+    //Set old pin function back, disable CLKOUT
+    *reg = old_pinfun;
+    LPC_SYSCON->CLKOUTDIV = 0;
+}
+
+static inline void restore(void) {
+        
+    WakeUpTimer->MR[WakeUpTimer_Match] = 0xFFFFFFFF;
+
+    if (old_clk_sel == 3)                           //Was running on PLL
+        while(LPC_SYSCON->SYSPLLSTAT != SYSPLLSTAT_LOCK);
+    
+    if (old_clk_sel < 4) {  //If valid setting
+        LPC_SYSCON->MAINCLKSEL = old_clk_sel;
+        LPC_SYSCON->MAINCLKUEN = 0;
+        LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
+    }
+    
+    IRQ_in.rise(NULL);
+    
+    LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL; 
+    
+    WakeUpTimer->MR3 = MR3;
+    WakeUpTimer->PR = PR;
+    WakeUpTimer->TCR = TCR;
+}
+
+#endif