|
3 | 3 | #include "ArduinoLowPower.h"
|
4 | 4 | #include "WInterrupts.h"
|
5 | 5 |
|
| 6 | +static void configGCLK6() |
| 7 | +{ |
| 8 | + // enable EIC clock |
| 9 | + GCLK->CLKCTRL.bit.CLKEN = 0; //disable GCLK module |
| 10 | + while (GCLK->STATUS.bit.SYNCBUSY); |
| 11 | + |
| 12 | + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK6 | GCLK_CLKCTRL_ID( GCM_EIC )) ; //EIC clock switched on GCLK6 |
| 13 | + while (GCLK->STATUS.bit.SYNCBUSY); |
| 14 | + |
| 15 | + GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(6)); //source for GCLK6 is OSCULP32K |
| 16 | + while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); |
| 17 | + |
| 18 | + GCLK->GENCTRL.bit.RUNSTDBY = 1; //GCLK6 run standby |
| 19 | + while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); |
| 20 | + |
| 21 | + /* Errata: Make sure that the Flash does not power all the way down |
| 22 | + * when in sleep mode. */ |
| 23 | + |
| 24 | + NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; |
| 25 | +} |
| 26 | + |
6 | 27 | void ArduinoLowPowerClass::idle() {
|
7 | 28 | SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
8 | 29 | PM->SLEEP.reg = 2;
|
@@ -80,26 +101,117 @@ void ArduinoLowPowerClass::attachInterruptWakeup(uint32_t pin, voidFuncPtr callb
|
80 | 101 | //pinMode(pin, INPUT_PULLUP);
|
81 | 102 | attachInterrupt(pin, callback, mode);
|
82 | 103 |
|
83 |
| - // enable EIC clock |
84 |
| - GCLK->CLKCTRL.bit.CLKEN = 0; //disable GCLK module |
85 |
| - while (GCLK->STATUS.bit.SYNCBUSY); |
| 104 | + configGCLK6(); |
86 | 105 |
|
87 |
| - GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK6 | GCLK_CLKCTRL_ID( GCM_EIC )) ; //EIC clock switched on GCLK6 |
88 |
| - while (GCLK->STATUS.bit.SYNCBUSY); |
| 106 | + // Enable wakeup capability on pin in case being used during sleep |
| 107 | + EIC->WAKEUP.reg |= (1 << in); |
| 108 | +} |
89 | 109 |
|
90 |
| - GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(6)); //source for GCLK6 is OSCULP32K |
91 |
| - while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); |
| 110 | +void ArduinoLowPowerClass::attachAdcInterrupt(uint32_t pin, voidFuncPtr callback, adc_interrupt mode, uint16_t lo, uint16_t hi) |
| 111 | +{ |
| 112 | + uint8_t winmode = 0; |
92 | 113 |
|
93 |
| - GCLK->GENCTRL.bit.RUNSTDBY = 1; //GCLK6 run standby |
94 |
| - while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); |
| 114 | + switch (mode) { |
| 115 | + case ADC_INT_BETWEEN: winmode = ADC_WINCTRL_WINMODE_MODE3; break; |
| 116 | + case ADC_INT_OUTSIDE: winmode = ADC_WINCTRL_WINMODE_MODE4; break; |
| 117 | + case ADC_INT_ABOVE_MIN: winmode = ADC_WINCTRL_WINMODE_MODE1; break; |
| 118 | + case ADC_INT_BELOW_MAX: winmode = ADC_WINCTRL_WINMODE_MODE2; break; |
| 119 | + default: return; |
| 120 | + } |
95 | 121 |
|
96 |
| - // Enable wakeup capability on pin in case being used during sleep |
97 |
| - EIC->WAKEUP.reg |= (1 << in); |
| 122 | + adc_cb = callback; |
98 | 123 |
|
99 |
| - /* Errata: Make sure that the Flash does not power all the way down |
100 |
| - * when in sleep mode. */ |
| 124 | + configGCLK6(); |
101 | 125 |
|
102 |
| - NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; |
| 126 | + // Configure ADC to use GCLK6 (OSCULP32K) |
| 127 | + while (GCLK->STATUS.bit.SYNCBUSY) {} |
| 128 | + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_ADC |
| 129 | + | GCLK_CLKCTRL_GEN_GCLK6 |
| 130 | + | GCLK_CLKCTRL_CLKEN; |
| 131 | + while (GCLK->STATUS.bit.SYNCBUSY) {} |
| 132 | + |
| 133 | + // Set ADC prescaler as low as possible |
| 134 | + ADC->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV4; |
| 135 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 136 | + |
| 137 | + // Configure window mode |
| 138 | + ADC->WINLT.reg = lo; |
| 139 | + ADC->WINUT.reg = hi; |
| 140 | + ADC->WINCTRL.reg = winmode; |
| 141 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 142 | + |
| 143 | + // Enable window interrupt |
| 144 | + ADC->INTENSET.bit.WINMON = 1; |
| 145 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 146 | + |
| 147 | + // Enable ADC in standby mode |
| 148 | + ADC->CTRLA.bit.RUNSTDBY = 1; |
| 149 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 150 | + |
| 151 | + // Enable continuous conversions |
| 152 | + ADC->CTRLB.bit.FREERUN = 1; |
| 153 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 154 | + |
| 155 | + // Configure input mux |
| 156 | + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; |
| 157 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 158 | + |
| 159 | + // Enable the ADC |
| 160 | + ADC->CTRLA.bit.ENABLE = 1; |
| 161 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 162 | + |
| 163 | + // Start continuous conversions |
| 164 | + ADC->SWTRIG.bit.START = 1; |
| 165 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 166 | + |
| 167 | + // Enable the ADC interrupt |
| 168 | + NVIC_EnableIRQ(ADC_IRQn); |
| 169 | +} |
| 170 | + |
| 171 | +void ArduinoLowPowerClass::detachAdcInterrupt() |
| 172 | +{ |
| 173 | + // Disable the ADC interrupt |
| 174 | + NVIC_DisableIRQ(ADC_IRQn); |
| 175 | + |
| 176 | + // Disable the ADC |
| 177 | + ADC->CTRLA.bit.ENABLE = 0; |
| 178 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 179 | + |
| 180 | + // Disable continuous conversions |
| 181 | + ADC->CTRLB.bit.FREERUN = 0; |
| 182 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 183 | + |
| 184 | + // Disable ADC in standby mode |
| 185 | + ADC->CTRLA.bit.RUNSTDBY = 1; |
| 186 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 187 | + |
| 188 | + // Disable window interrupt |
| 189 | + ADC->INTENCLR.bit.WINMON = 1; |
| 190 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 191 | + |
| 192 | + // Disable window mode |
| 193 | + ADC->WINCTRL.reg = ADC_WINCTRL_WINMODE_DISABLE; |
| 194 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 195 | + |
| 196 | + // Restore ADC prescaler |
| 197 | + ADC->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV512_Val; |
| 198 | + while (ADC->STATUS.bit.SYNCBUSY) {} |
| 199 | + |
| 200 | + // Restore ADC clock |
| 201 | + while (GCLK->STATUS.bit.SYNCBUSY) {} |
| 202 | + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_ADC |
| 203 | + | GCLK_CLKCTRL_GEN_GCLK0 |
| 204 | + | GCLK_CLKCTRL_CLKEN; |
| 205 | + while (GCLK->STATUS.bit.SYNCBUSY) {} |
| 206 | + |
| 207 | + adc_cb = nullptr; |
| 208 | +} |
| 209 | + |
| 210 | +void ADC_Handler() |
| 211 | +{ |
| 212 | + // Clear the interrupt flag |
| 213 | + ADC->INTFLAG.bit.WINMON = 1; |
| 214 | + LowPower.adc_cb(); |
103 | 215 | }
|
104 | 216 |
|
105 | 217 | ArduinoLowPowerClass LowPower;
|
|
0 commit comments