Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: LPC1114_WakeInterruptIn
Fork of WakeUp by
Device/WakeUp_LPC11XX.cpp
- Committer:
- Sissors
- Date:
- 2014-07-30
- Revision:
- 13:fd24cec76d5a
- Parent:
- 12:779d866b8a2d
- Child:
- 14:6bf547e1e62d
File content as of revision 13:fd24cec76d5a:
/**
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);
FunctionPointer 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)
{
//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;
}
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
