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
Device/WakeUp_LPC11XX.cpp@2:0c49a8f32f6e, 2017-12-26 (annotated)
- Committer:
- madelectroneng
- Date:
- Tue Dec 26 21:30:09 2017 +0000
- Revision:
- 2:0c49a8f32f6e
Inital setup
Who changed what in which revision?
User | Revision | Line number | New 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 |