Fork of original library to fix mbed 5 deprecation warnings

Dependencies:   LPC1114_WakeInterruptIn

Dependents:   low-power-sleep

Fork of WakeUp by Erik -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WakeUp_LPC11XX.cpp Source File

WakeUp_LPC11XX.cpp

00001 /**
00002 See homepage of this lib for LPC11xx special treatment
00003 **/
00004 
00005 #ifdef TARGET_LPC11XX_11CXX
00006 
00007 #include "WakeUp.h"
00008 #include "WakeInterruptIn.h"
00009 #include "pinmap.h"
00010 #include "toolchain.h"
00011 
00012 //Pin used, allowed pins = P0_1 (dp24, default), P0_8 (dp1) and P0_9 (dp2)
00013 //By defining WakeUpPin in for example your main.cpp this can be overridden
00014 WEAK PinName WakeUpPin = dp24;
00015 extern PinName WakeUpPin;
00016 
00017 WakeInterruptIn IRQ_in(WakeUpPin);
00018 PwmOut pulse_out(WakeUpPin);
00019 
00020 Callback<void()> WakeUp::cbk;
00021 float WakeUp::cycles_per_ms = 20.0;
00022 
00023 static uint32_t old_clk_sel = ~0;
00024 static uint32_t SYSAHBCLKCTRL;
00025 static uint32_t TCR, PR, MR3;
00026 static LPC_TMR_TypeDef *WakeUpTimer;
00027 static uint32_t SYSAHBCLKCTRL_Sleep;
00028 static uint8_t WakeUpTimer_Match;
00029 
00030 static inline void restore(void);
00031 
00032 
00033 void WakeUp::set_ms(uint32_t ms)
00034 {
00035     if (old_clk_sel == ~0) {                                //Only during first run
00036         old_clk_sel = LPC_SYSCON->MAINCLKSEL;
00037         SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
00038         
00039         switch(WakeUpPin) {
00040             case dp24:
00041                 WakeUpTimer = LPC_TMR32B0;
00042                 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<9);
00043                 WakeUpTimer_Match = 2;
00044                 break;
00045             case dp1:
00046                 WakeUpTimer = LPC_TMR16B0;
00047                 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
00048                 WakeUpTimer_Match = 0;
00049                 break;
00050             case dp2:
00051                 WakeUpTimer = LPC_TMR16B0;
00052                 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
00053                 WakeUpTimer_Match = 1;
00054                 break;
00055             default:
00056                 error("Invalid WakeUp pin, choose dp1, dp2 or dp24");
00057         }            
00058     }
00059         
00060     if (ms != 0) {        
00061         if (LPC_SYSCON->SYSAHBCLKCTRL != SYSAHBCLKCTRL_Sleep)    //Always when it is different from sleep settings
00062             SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
00063 
00064         LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
00065         LPC_SYSCON->PDSLEEPCFG = 0x000018B7 | (LPC_SYSCON->PDRUNCFG & (PDRUNCFG_WDTOSC_PD | PDRUNCFG_BOD_PD)); 
00066         
00067         //Set oscillator for 20kHz
00068         LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
00069         
00070         //Store old PWM
00071         TCR = WakeUpTimer->TCR;
00072         PR = WakeUpTimer->PR;
00073         MR3 = WakeUpTimer->MR3;
00074         
00075         //Setup PWM
00076         WakeUpTimer->TCR = TMR16B0TCR_CRST;
00077         uint32_t ticks = (float)ms * cycles_per_ms;
00078         
00079         //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)
00080         WakeUpTimer->PR = ticks >> 16;
00081         WakeUpTimer->MR[WakeUpTimer_Match] = ticks / ((ticks >> 16) + 1);
00082         WakeUpTimer->MR3 = 0xFFFF;
00083                 
00084         IRQ_in.rise(irq_handler);
00085         
00086         //Disable most peripherals
00087         LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL_Sleep;
00088         
00089         //Switch clock to WD OSC
00090         LPC_SYSCON->MAINCLKSEL = 0x2;
00091         LPC_SYSCON->MAINCLKUEN = 0;
00092         LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
00093         
00094         //Enable PWM:
00095         WakeUpTimer->TCR = TMR16B0TCR_CEN;
00096     } else {
00097         //Else restore normal settings
00098         restore();
00099     }
00100     
00101 }
00102 
00103 void WakeUp::irq_handler(void)
00104 {    
00105     restore();    
00106     if (cbk) {
00107         cbk.call();
00108     }
00109 }
00110 
00111 void WakeUp::calibrate(void)
00112 {
00113     //Save current pin function
00114     __IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + (dp24 & 0xFF));
00115     uint32_t old_pinfun = *reg;
00116     
00117     //Set oscillator for 20kHz
00118     LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
00119     LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
00120     
00121     //Direct WDT to the CLKOUT pin (dp24), sample it back
00122     DigitalIn din(dp24);
00123     Timer timer;
00124     
00125     LPC_SYSCON->CLKOUTDIV = 1;
00126     LPC_SYSCON->CLKOUTCLKSEL = 0x2;
00127     LPC_SYSCON->CLKOUTUEN = 0;
00128     LPC_SYSCON->CLKOUTUEN = CLKOUTUEN_ENA;
00129     pin_function(dp24, 1);
00130     
00131     int count = 0;
00132     timer.start();
00133     while (timer.read_ms() < 100) {
00134         while (din.read() == 0);
00135         while (din.read() == 1);
00136         count++;
00137     }
00138     cycles_per_ms = (float)count / 100.0f;
00139     
00140     //Set old pin function back, disable CLKOUT
00141     *reg = old_pinfun;
00142     LPC_SYSCON->CLKOUTDIV = 0;
00143 }
00144 
00145 static inline void restore(void) {
00146         
00147     WakeUpTimer->MR[WakeUpTimer_Match] = 0xFFFFFFFF;
00148 
00149     if (old_clk_sel == 3)                           //Was running on PLL
00150         while(LPC_SYSCON->SYSPLLSTAT != SYSPLLSTAT_LOCK);
00151     
00152     if (old_clk_sel < 4) {  //If valid setting
00153         LPC_SYSCON->MAINCLKSEL = old_clk_sel;
00154         LPC_SYSCON->MAINCLKUEN = 0;
00155         LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
00156     }
00157     
00158     IRQ_in.rise(NULL);
00159     
00160     LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL; 
00161     
00162     WakeUpTimer->MR3 = MR3;
00163     WakeUpTimer->PR = PR;
00164     WakeUpTimer->TCR = TCR;
00165 }
00166 
00167 #endif