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

Committer:
madelectroneng
Date:
Tue Dec 26 21:30:09 2017 +0000
Revision:
2:0c49a8f32f6e
Inital setup

Who changed what in which revision?

UserRevisionLine numberNew contents of line
madelectroneng 2:0c49a8f32f6e 1 /**
madelectroneng 2:0c49a8f32f6e 2 See homepage of this lib for LPC11xx special treatment
madelectroneng 2:0c49a8f32f6e 3 **/
madelectroneng 2:0c49a8f32f6e 4
madelectroneng 2:0c49a8f32f6e 5 #ifdef TARGET_LPC11XX_11CXX
madelectroneng 2:0c49a8f32f6e 6
madelectroneng 2:0c49a8f32f6e 7 #include "WakeUp.h"
madelectroneng 2:0c49a8f32f6e 8 #include "WakeInterruptIn.h"
madelectroneng 2:0c49a8f32f6e 9 #include "pinmap.h"
madelectroneng 2:0c49a8f32f6e 10 #include "toolchain.h"
madelectroneng 2:0c49a8f32f6e 11
madelectroneng 2:0c49a8f32f6e 12 //Pin used, allowed pins = P0_1 (dp24, default), P0_8 (dp1) and P0_9 (dp2)
madelectroneng 2:0c49a8f32f6e 13 //By defining WakeUpPin in for example your main.cpp this can be overridden
madelectroneng 2:0c49a8f32f6e 14 WEAK PinName WakeUpPin = dp24;
madelectroneng 2:0c49a8f32f6e 15 extern PinName WakeUpPin;
madelectroneng 2:0c49a8f32f6e 16
madelectroneng 2:0c49a8f32f6e 17 WakeInterruptIn IRQ_in(WakeUpPin);
madelectroneng 2:0c49a8f32f6e 18 PwmOut pulse_out(WakeUpPin);
madelectroneng 2:0c49a8f32f6e 19
madelectroneng 2:0c49a8f32f6e 20 Callback<void()> WakeUp::callback;
madelectroneng 2:0c49a8f32f6e 21 float WakeUp::cycles_per_ms = 20.0;
madelectroneng 2:0c49a8f32f6e 22
madelectroneng 2:0c49a8f32f6e 23 static uint32_t old_clk_sel = ~0;
madelectroneng 2:0c49a8f32f6e 24 static uint32_t SYSAHBCLKCTRL;
madelectroneng 2:0c49a8f32f6e 25 static uint32_t TCR, PR, MR3;
madelectroneng 2:0c49a8f32f6e 26 static LPC_TMR_TypeDef *WakeUpTimer;
madelectroneng 2:0c49a8f32f6e 27 static uint32_t SYSAHBCLKCTRL_Sleep;
madelectroneng 2:0c49a8f32f6e 28 static uint8_t WakeUpTimer_Match;
madelectroneng 2:0c49a8f32f6e 29
madelectroneng 2:0c49a8f32f6e 30 static inline void restore(void);
madelectroneng 2:0c49a8f32f6e 31
madelectroneng 2:0c49a8f32f6e 32
madelectroneng 2:0c49a8f32f6e 33 void WakeUp::set_ms(uint32_t ms)
madelectroneng 2:0c49a8f32f6e 34 {
madelectroneng 2:0c49a8f32f6e 35 if (old_clk_sel == ~0) { //Only during first run
madelectroneng 2:0c49a8f32f6e 36 old_clk_sel = LPC_SYSCON->MAINCLKSEL;
madelectroneng 2:0c49a8f32f6e 37 SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
madelectroneng 2:0c49a8f32f6e 38
madelectroneng 2:0c49a8f32f6e 39 switch(WakeUpPin) {
madelectroneng 2:0c49a8f32f6e 40 case dp24:
madelectroneng 2:0c49a8f32f6e 41 WakeUpTimer = LPC_TMR32B0;
madelectroneng 2:0c49a8f32f6e 42 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<9);
madelectroneng 2:0c49a8f32f6e 43 WakeUpTimer_Match = 2;
madelectroneng 2:0c49a8f32f6e 44 break;
madelectroneng 2:0c49a8f32f6e 45 case dp1:
madelectroneng 2:0c49a8f32f6e 46 WakeUpTimer = LPC_TMR16B0;
madelectroneng 2:0c49a8f32f6e 47 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
madelectroneng 2:0c49a8f32f6e 48 WakeUpTimer_Match = 0;
madelectroneng 2:0c49a8f32f6e 49 break;
madelectroneng 2:0c49a8f32f6e 50 case dp2:
madelectroneng 2:0c49a8f32f6e 51 WakeUpTimer = LPC_TMR16B0;
madelectroneng 2:0c49a8f32f6e 52 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
madelectroneng 2:0c49a8f32f6e 53 WakeUpTimer_Match = 1;
madelectroneng 2:0c49a8f32f6e 54 break;
madelectroneng 2:0c49a8f32f6e 55 default:
madelectroneng 2:0c49a8f32f6e 56 error("Invalid WakeUp pin, choose dp1, dp2 or dp24");
madelectroneng 2:0c49a8f32f6e 57 }
madelectroneng 2:0c49a8f32f6e 58 }
madelectroneng 2:0c49a8f32f6e 59
madelectroneng 2:0c49a8f32f6e 60 if (ms != 0) {
madelectroneng 2:0c49a8f32f6e 61 if (LPC_SYSCON->SYSAHBCLKCTRL != SYSAHBCLKCTRL_Sleep) //Always when it is different from sleep settings
madelectroneng 2:0c49a8f32f6e 62 SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
madelectroneng 2:0c49a8f32f6e 63
madelectroneng 2:0c49a8f32f6e 64 LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
madelectroneng 2:0c49a8f32f6e 65 LPC_SYSCON->PDSLEEPCFG = 0x000018B7 | (LPC_SYSCON->PDRUNCFG & (PDRUNCFG_WDTOSC_PD | PDRUNCFG_BOD_PD));
madelectroneng 2:0c49a8f32f6e 66
madelectroneng 2:0c49a8f32f6e 67 //Set oscillator for 20kHz
madelectroneng 2:0c49a8f32f6e 68 LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
madelectroneng 2:0c49a8f32f6e 69
madelectroneng 2:0c49a8f32f6e 70 //Store old PWM
madelectroneng 2:0c49a8f32f6e 71 TCR = WakeUpTimer->TCR;
madelectroneng 2:0c49a8f32f6e 72 PR = WakeUpTimer->PR;
madelectroneng 2:0c49a8f32f6e 73 MR3 = WakeUpTimer->MR3;
madelectroneng 2:0c49a8f32f6e 74
madelectroneng 2:0c49a8f32f6e 75 //Setup PWM
madelectroneng 2:0c49a8f32f6e 76 WakeUpTimer->TCR = TMR16B0TCR_CRST;
madelectroneng 2:0c49a8f32f6e 77 uint32_t ticks = (float)ms * cycles_per_ms;
madelectroneng 2:0c49a8f32f6e 78
madelectroneng 2:0c49a8f32f6e 79 //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)
madelectroneng 2:0c49a8f32f6e 80 WakeUpTimer->PR = ticks >> 16;
madelectroneng 2:0c49a8f32f6e 81 WakeUpTimer->MR[WakeUpTimer_Match] = ticks / ((ticks >> 16) + 1);
madelectroneng 2:0c49a8f32f6e 82 WakeUpTimer->MR3 = 0xFFFF;
madelectroneng 2:0c49a8f32f6e 83
madelectroneng 2:0c49a8f32f6e 84 IRQ_in.rise(irq_handler);
madelectroneng 2:0c49a8f32f6e 85
madelectroneng 2:0c49a8f32f6e 86 //Disable most peripherals
madelectroneng 2:0c49a8f32f6e 87 LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL_Sleep;
madelectroneng 2:0c49a8f32f6e 88
madelectroneng 2:0c49a8f32f6e 89 //Switch clock to WD OSC
madelectroneng 2:0c49a8f32f6e 90 LPC_SYSCON->MAINCLKSEL = 0x2;
madelectroneng 2:0c49a8f32f6e 91 LPC_SYSCON->MAINCLKUEN = 0;
madelectroneng 2:0c49a8f32f6e 92 LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
madelectroneng 2:0c49a8f32f6e 93
madelectroneng 2:0c49a8f32f6e 94 //Enable PWM:
madelectroneng 2:0c49a8f32f6e 95 WakeUpTimer->TCR = TMR16B0TCR_CEN;
madelectroneng 2:0c49a8f32f6e 96 } else {
madelectroneng 2:0c49a8f32f6e 97 //Else restore normal settings
madelectroneng 2:0c49a8f32f6e 98 restore();
madelectroneng 2:0c49a8f32f6e 99 }
madelectroneng 2:0c49a8f32f6e 100
madelectroneng 2:0c49a8f32f6e 101 }
madelectroneng 2:0c49a8f32f6e 102
madelectroneng 2:0c49a8f32f6e 103 void WakeUp::irq_handler(void)
madelectroneng 2:0c49a8f32f6e 104 {
madelectroneng 2:0c49a8f32f6e 105 restore();
madelectroneng 2:0c49a8f32f6e 106 callback.call();
madelectroneng 2:0c49a8f32f6e 107 }
madelectroneng 2:0c49a8f32f6e 108
madelectroneng 2:0c49a8f32f6e 109 void WakeUp::calibrate(void)
madelectroneng 2:0c49a8f32f6e 110 {
madelectroneng 2:0c49a8f32f6e 111 //Save current pin function
madelectroneng 2:0c49a8f32f6e 112 __IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + (dp24 & 0xFF));
madelectroneng 2:0c49a8f32f6e 113 uint32_t old_pinfun = *reg;
madelectroneng 2:0c49a8f32f6e 114
madelectroneng 2:0c49a8f32f6e 115 //Set oscillator for 20kHz
madelectroneng 2:0c49a8f32f6e 116 LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
madelectroneng 2:0c49a8f32f6e 117 LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
madelectroneng 2:0c49a8f32f6e 118
madelectroneng 2:0c49a8f32f6e 119 //Direct WDT to the CLKOUT pin (dp24), sample it back
madelectroneng 2:0c49a8f32f6e 120 DigitalIn din(dp24);
madelectroneng 2:0c49a8f32f6e 121 Timer timer;
madelectroneng 2:0c49a8f32f6e 122
madelectroneng 2:0c49a8f32f6e 123 LPC_SYSCON->CLKOUTDIV = 1;
madelectroneng 2:0c49a8f32f6e 124 LPC_SYSCON->CLKOUTCLKSEL = 0x2;
madelectroneng 2:0c49a8f32f6e 125 LPC_SYSCON->CLKOUTUEN = 0;
madelectroneng 2:0c49a8f32f6e 126 LPC_SYSCON->CLKOUTUEN = CLKOUTUEN_ENA;
madelectroneng 2:0c49a8f32f6e 127 pin_function(dp24, 1);
madelectroneng 2:0c49a8f32f6e 128
madelectroneng 2:0c49a8f32f6e 129 int count = 0;
madelectroneng 2:0c49a8f32f6e 130 timer.start();
madelectroneng 2:0c49a8f32f6e 131 while (timer.read_ms() < 100) {
madelectroneng 2:0c49a8f32f6e 132 while (din.read() == 0);
madelectroneng 2:0c49a8f32f6e 133 while (din.read() == 1);
madelectroneng 2:0c49a8f32f6e 134 count++;
madelectroneng 2:0c49a8f32f6e 135 }
madelectroneng 2:0c49a8f32f6e 136 cycles_per_ms = (float)count / 100.0f;
madelectroneng 2:0c49a8f32f6e 137
madelectroneng 2:0c49a8f32f6e 138 //Set old pin function back, disable CLKOUT
madelectroneng 2:0c49a8f32f6e 139 *reg = old_pinfun;
madelectroneng 2:0c49a8f32f6e 140 LPC_SYSCON->CLKOUTDIV = 0;
madelectroneng 2:0c49a8f32f6e 141 }
madelectroneng 2:0c49a8f32f6e 142
madelectroneng 2:0c49a8f32f6e 143 static inline void restore(void) {
madelectroneng 2:0c49a8f32f6e 144
madelectroneng 2:0c49a8f32f6e 145 WakeUpTimer->MR[WakeUpTimer_Match] = 0xFFFFFFFF;
madelectroneng 2:0c49a8f32f6e 146
madelectroneng 2:0c49a8f32f6e 147 if (old_clk_sel == 3) //Was running on PLL
madelectroneng 2:0c49a8f32f6e 148 while(LPC_SYSCON->SYSPLLSTAT != SYSPLLSTAT_LOCK);
madelectroneng 2:0c49a8f32f6e 149
madelectroneng 2:0c49a8f32f6e 150 if (old_clk_sel < 4) { //If valid setting
madelectroneng 2:0c49a8f32f6e 151 LPC_SYSCON->MAINCLKSEL = old_clk_sel;
madelectroneng 2:0c49a8f32f6e 152 LPC_SYSCON->MAINCLKUEN = 0;
madelectroneng 2:0c49a8f32f6e 153 LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
madelectroneng 2:0c49a8f32f6e 154 }
madelectroneng 2:0c49a8f32f6e 155
madelectroneng 2:0c49a8f32f6e 156 IRQ_in.rise(NULL);
madelectroneng 2:0c49a8f32f6e 157
madelectroneng 2:0c49a8f32f6e 158 LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL;
madelectroneng 2:0c49a8f32f6e 159
madelectroneng 2:0c49a8f32f6e 160 WakeUpTimer->MR3 = MR3;
madelectroneng 2:0c49a8f32f6e 161 WakeUpTimer->PR = PR;
madelectroneng 2:0c49a8f32f6e 162 WakeUpTimer->TCR = TCR;
madelectroneng 2:0c49a8f32f6e 163 }
madelectroneng 2:0c49a8f32f6e 164
madelectroneng 2:0c49a8f32f6e 165 #endif