LoRa node acquiring analog input and sending to LoRa Server - Working ok
Dependents: DISCO-L072CZ-LRWAN1_LoRa_node EIoT_LoRa_node_1 EIoT_LoRa_node_2 EIoT_LoRa_node_3
Fork of SX1276GenericLib by
Arduino-mbed-APIs/arduino-d21.cpp@85:93832cc77534, 2017-08-12 (annotated)
- Committer:
- Helmut Tschemernjak
- Date:
- Sat Aug 12 19:16:08 2017 +0200
- Revision:
- 85:93832cc77534
- Parent:
- 84:3428e25c7157
- Child:
- 86:49d19df5bbce
The deepsleep does not need to disable the SysTick, it is off
already in suspend mode. It looks like out D21 MCU does not
need to keep the flash on during sleep, we got a newer chip
revision.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Helmut Tschemernjak | 77:7f227a4dffe6 | 1 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 2 | * The file is Licensed under the Apache License, Version 2.0 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 3 | * (c) 2017 Helmut Tschemernjak |
Helmut Tschemernjak | 77:7f227a4dffe6 | 4 | * 30826 Garbsen (Hannover) Germany |
Helmut Tschemernjak | 77:7f227a4dffe6 | 5 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 6 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 7 | #ifdef ARDUINO |
Helmut Tschemernjak | 77:7f227a4dffe6 | 8 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 9 | using namespace std; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 10 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 11 | #include "arduino-mbed.h" |
Helmut Tschemernjak | 77:7f227a4dffe6 | 12 | #include "arduino-util.h" |
Helmut Tschemernjak | 77:7f227a4dffe6 | 13 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 14 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 15 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 16 | #if defined(__SAMD21G18A__) || defined(__SAMD21J18A__) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 17 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 18 | * __SAMD21J18A__ is the SamD21 Explained Board |
Helmut Tschemernjak | 77:7f227a4dffe6 | 19 | * __SAMD21G18A__ is Genuino Zero-Board (compatible with the LoRa board) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 20 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 21 | |
Helmut Tschemernjak | 78:9d2cc07d9525 | 22 | int |
Helmut Tschemernjak | 78:9d2cc07d9525 | 23 | CPUID(uint8_t *buf, int maxSize, uint32_t xorval) |
Helmut Tschemernjak | 78:9d2cc07d9525 | 24 | { |
Helmut Tschemernjak | 78:9d2cc07d9525 | 25 | int f1 = 0x55d5f559; // D21 128-bit UUID, first 32 bit. |
Helmut Tschemernjak | 78:9d2cc07d9525 | 26 | int f2 = 0x55d5f515; // D21 128-bit UUID, next 96 bit. |
Helmut Tschemernjak | 78:9d2cc07d9525 | 27 | |
Helmut Tschemernjak | 78:9d2cc07d9525 | 28 | if (maxSize >= 16 ) { |
Helmut Tschemernjak | 78:9d2cc07d9525 | 29 | int cnt = 0; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 30 | int fa = f1 ^ xorval; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 31 | uint32_t *first = (uint32_t *)fa; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 32 | uint8_t *dst = (uint8_t *)first; |
Helmut Tschemernjak | 84:3428e25c7157 | 33 | for (int i = 0; i < (int)sizeof(uint32_t); i++) |
Helmut Tschemernjak | 78:9d2cc07d9525 | 34 | *buf++ = *dst++; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 35 | cnt += 4; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 36 | int fb = f2 ^ xorval; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 37 | uint32_t *next = (uint32_t *)fb; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 38 | dst = (uint8_t *)next; |
Helmut Tschemernjak | 84:3428e25c7157 | 39 | for (int i = 0; i < (int)sizeof(uint32_t)*3; i++) |
Helmut Tschemernjak | 78:9d2cc07d9525 | 40 | *buf++ = *dst++; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 41 | cnt += 12; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 42 | return cnt; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 43 | } |
Helmut Tschemernjak | 78:9d2cc07d9525 | 44 | |
Helmut Tschemernjak | 78:9d2cc07d9525 | 45 | return 0; |
Helmut Tschemernjak | 78:9d2cc07d9525 | 46 | } |
Helmut Tschemernjak | 78:9d2cc07d9525 | 47 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 48 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 49 | * see tcc.h is automatically included from: |
Helmut Tschemernjak | 77:7f227a4dffe6 | 50 | * Arduino15/packages/arduino/tools/CMSIS-Atmel/1.1.0/CMSIS/ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 51 | * Device/ATMEL/samd21/include/component/tcc.h |
Helmut Tschemernjak | 77:7f227a4dffe6 | 52 | * See also tcc.c (ASF/mbed, e.g. Tcc_get_count_value) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 53 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 54 | static void initTimer(Tcc *t); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 55 | static uint32_t getTimerCount(Tcc *t); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 56 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 57 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 58 | * The Atmel D21 has three TCC timer, other models have more. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 59 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 60 | const struct TCC_config { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 61 | Tcc *tcc_ptr; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 62 | IRQn_Type tcc_irq; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 63 | uint8_t nbits; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 64 | } TCC_data[] { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 65 | { TCC0, TCC0_IRQn, 24 }, |
Helmut Tschemernjak | 77:7f227a4dffe6 | 66 | { TCC1, TCC1_IRQn, 24 }, |
Helmut Tschemernjak | 77:7f227a4dffe6 | 67 | { TCC2, TCC2_IRQn, 16 }, |
Helmut Tschemernjak | 77:7f227a4dffe6 | 68 | { NULL, (IRQn_Type)NULL, 0 } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 69 | }; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 70 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 71 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 72 | * We preferably use the TCC timers because it supports 24-bit counters |
Helmut Tschemernjak | 77:7f227a4dffe6 | 73 | * versus TC Timer which supports only 8 or 16 bit counters only. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 74 | * TCC0/1/2 timer work on the D21 using Arduino Zero. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 75 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 76 | #define USE_TCC_TIMEOUT 0 // 0=TCC0, 1=TTC1, 2=TTC2 (see TCC_data) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 77 | #define USE_TCC_TICKER 1 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 78 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 79 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 80 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 81 | * every 21333 ns equals one tick (1/(48000000/1024)) // prescaler 1024, 48 MHz |
Helmut Tschemernjak | 77:7f227a4dffe6 | 82 | * every 61035 ns equals one tick (1/(32768/2)) // prescaler 2, 32 kHz |
Helmut Tschemernjak | 77:7f227a4dffe6 | 83 | * COUNT*DIVIDER*SECS until interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 84 | * CPU 48 MHz = (65536*1024)/1.398636s |
Helmut Tschemernjak | 77:7f227a4dffe6 | 85 | * RTC 32 kHz = (65536*2)/4.0s |
Helmut Tschemernjak | 77:7f227a4dffe6 | 86 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 87 | #define NS_PER_CLOCK_CPU 21333 // ns secs per clock |
Helmut Tschemernjak | 77:7f227a4dffe6 | 88 | #define NS_PER_CLOCK_RTC 61035 // ns secs per clock |
Helmut Tschemernjak | 77:7f227a4dffe6 | 89 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 90 | #define NS_PER_CLOCK NS_PER_CLOCK_RTC |
Helmut Tschemernjak | 77:7f227a4dffe6 | 91 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 92 | /* ----------------- TICKER TIMER CODE ----------------------*/ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 93 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 94 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 95 | * The global ns_counter contains the time in ns from the last time |
Helmut Tschemernjak | 77:7f227a4dffe6 | 96 | * the counter has been wrapped. It cannot be used directly because the |
Helmut Tschemernjak | 77:7f227a4dffe6 | 97 | * current counter has to be added fore using it. Use instead |
Helmut Tschemernjak | 77:7f227a4dffe6 | 98 | * ns_getTicker(), us_ ns_getTicker(), ms_getTicker() |
Helmut Tschemernjak | 77:7f227a4dffe6 | 99 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 100 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 101 | uint64_t ticker_ns; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 102 | static bool initTickerDone = false; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 103 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 104 | uint64_t ns_getTicker(void) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 105 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 106 | Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 107 | if (!initTickerDone) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 108 | initTimer(t); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 109 | initTickerDone = true; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 110 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 111 | // set counter top to max 16 bit for testing |
Helmut Tschemernjak | 77:7f227a4dffe6 | 112 | // t->PER.bit.PER = 0xffff; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 113 | // while (t->SYNCBUSY.bit.PER == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 114 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 115 | t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC |
Helmut Tschemernjak | 77:7f227a4dffe6 | 116 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 117 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 118 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 119 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 120 | * if we are called from the interrupt level, the counter contains |
Helmut Tschemernjak | 77:7f227a4dffe6 | 121 | * somehow wrong data, therfore we needs to read it twice. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 122 | * Another option was to add a little wait (loop 500x) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 123 | * in the TCC_TIMEOUT interrupt handler. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 124 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 125 | if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) // check if we are in the interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 126 | getTimerCount(t); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 127 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 128 | uint64_t counter_us = (uint64_t)NS_PER_CLOCK * (uint64_t)getTimerCount(t); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 129 | uint64_t ns = ticker_ns + counter_us; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 130 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 131 | return ns; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 132 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 133 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 134 | #if USE_TCC_TICKER == 0 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 135 | void TCC0_Handler() |
Helmut Tschemernjak | 77:7f227a4dffe6 | 136 | #elif USE_TCC_TICKER == 1 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 137 | void TCC1_Handler() |
Helmut Tschemernjak | 77:7f227a4dffe6 | 138 | #elif USE_TCC_TICKER == 2 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 139 | void TCC2_Handler() |
Helmut Tschemernjak | 77:7f227a4dffe6 | 140 | #endif |
Helmut Tschemernjak | 77:7f227a4dffe6 | 141 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 142 | Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 143 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 144 | * Overflow means the timer top exeeded |
Helmut Tschemernjak | 77:7f227a4dffe6 | 145 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 146 | if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 147 | t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag |
Helmut Tschemernjak | 77:7f227a4dffe6 | 148 | // ser->println("T_OVF"); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 149 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 150 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 151 | * reading the count once is needed, otherwise |
Helmut Tschemernjak | 77:7f227a4dffe6 | 152 | * it will not wrap correct. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 153 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 154 | getTimerCount(t); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 155 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 156 | int bits = TCC_data[USE_TCC_TICKER].nbits; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 157 | int maxCounts = (uint32_t)(1<<bits); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 158 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 159 | ticker_ns += (uint64_t)NS_PER_CLOCK * (uint64_t)maxCounts; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 160 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 161 | if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 162 | t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag |
Helmut Tschemernjak | 77:7f227a4dffe6 | 163 | // ser->println("T_MC0"); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 164 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 165 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 166 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 167 | /* ----------------- SUPPORT CODE FOR TCC TIMERS----------------------*/ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 168 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 169 | static bool initTimerDone = false; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 170 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 171 | static void initTimer(Tcc *t) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 172 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 173 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 174 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 175 | * enable clock for TCC, see gclk.h |
Helmut Tschemernjak | 77:7f227a4dffe6 | 176 | * GCLK_CLKCTRL_GEN_GCLK0 for 48 Mhz CPU |
Helmut Tschemernjak | 77:7f227a4dffe6 | 177 | * GCLK_CLKCTRL_GEN_GCLK1 for 32k extern crystal XOSC32K (ifdef CRYSTALLESS) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 178 | * GCLK_CLKCTRL_GEN_GCLK1 for 32k internal OSC32K |
Helmut Tschemernjak | 77:7f227a4dffe6 | 179 | * see Arduino: arduino/hardware/samd/1.6.15/cores/arduino/startup.c |
Helmut Tschemernjak | 77:7f227a4dffe6 | 180 | * Use TCC_CTRLA_PRESCALER_DIV1024 for for 48 Mhz clock |
Helmut Tschemernjak | 77:7f227a4dffe6 | 181 | * Use TCC_CTRLA_PRESCALER_DIV2 for 32k clock |
Helmut Tschemernjak | 77:7f227a4dffe6 | 182 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 183 | if (t == TCC0 || t == TCC1) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 184 | REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC0_TCC1); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 185 | } else if (t == TCC2) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 186 | REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC2_TC3_Val); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 187 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 188 | while (GCLK->STATUS.bit.SYNCBUSY == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 189 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 190 | t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TCC |
Helmut Tschemernjak | 77:7f227a4dffe6 | 191 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 192 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 193 | t->CTRLA.reg |= (TCC_CTRLA_PRESCALER_DIV2 | TCC_CTRLA_RUNSTDBY); // Set perscaler |
Helmut Tschemernjak | 77:7f227a4dffe6 | 194 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 195 | t->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ; // Set wave form configuration |
Helmut Tschemernjak | 77:7f227a4dffe6 | 196 | while (t->SYNCBUSY.bit.WAVE == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 197 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 198 | t->PER.bit.PER = 0xffffff; // set counter top to max 24 bit |
Helmut Tschemernjak | 77:7f227a4dffe6 | 199 | while (t->SYNCBUSY.bit.PER == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 200 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 201 | // the compare counter TC->CC[0].reg will be set in the startTimer |
Helmut Tschemernjak | 77:7f227a4dffe6 | 202 | // after the timeout calculation is known. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 203 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 204 | // Interrupts |
Helmut Tschemernjak | 77:7f227a4dffe6 | 205 | t->INTENSET.reg = 0; // disable all interrupts |
Helmut Tschemernjak | 77:7f227a4dffe6 | 206 | t->INTENSET.bit.OVF = 1; // enable overfollow |
Helmut Tschemernjak | 77:7f227a4dffe6 | 207 | t->INTENSET.bit.MC0 = 1; // enable compare match to CC0 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 208 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 209 | const struct TCC_config *cp = &TCC_data[0]; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 210 | while (cp->tcc_ptr) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 211 | if (cp->tcc_ptr == t) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 212 | NVIC_EnableIRQ(cp->tcc_irq); // Enable InterruptVector |
Helmut Tschemernjak | 77:7f227a4dffe6 | 213 | break; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 214 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 215 | cp++; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 216 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 217 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 218 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 219 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 220 | #if 0 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 221 | // Atmel ASF Code |
Helmut Tschemernjak | 77:7f227a4dffe6 | 222 | static uint32_t getTimerCount(Tcc *t) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 223 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 224 | uint32_t last_cmd; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 225 | /* Wait last command done */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 226 | do { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 227 | while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 228 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 229 | last_cmd = t->CTRLBSET.reg & TCC_CTRLBSET_CMD_Msk; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 230 | if (TCC_CTRLBSET_CMD_NONE == last_cmd) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 231 | /* Issue read command and break */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 232 | t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 233 | break; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 234 | } else if (TCC_CTRLBSET_CMD_READSYNC == last_cmd) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 235 | /* Command have been issued */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 236 | break; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 237 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 238 | } while (1); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 239 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 240 | while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 241 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 242 | return t->COUNT.reg; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 243 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 244 | #endif |
Helmut Tschemernjak | 77:7f227a4dffe6 | 245 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 246 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 247 | static uint32_t getTimerCount(Tcc *t) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 248 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 249 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 250 | noInterrupts(); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 251 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 252 | while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 253 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 254 | t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val; /* Issue read command and break */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 255 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 256 | while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 257 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 258 | uint32_t count = t->COUNT.reg; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 259 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 260 | interrupts(); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 261 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 262 | return count; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 263 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 264 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 265 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 266 | Tcc *getTimeout_tcc(void) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 267 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 268 | return TCC_data[USE_TCC_TIMEOUT].tcc_ptr; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 269 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 270 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 271 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 272 | void stopTimer(Tcc *t) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 273 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 274 | t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC |
Helmut Tschemernjak | 77:7f227a4dffe6 | 275 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 276 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 277 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 278 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 279 | /* ----------------- TIMEOUT TIMER CODE ----------------------*/ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 280 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 281 | void startTimer(Tcc *t, uint64_t delay_ns) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 282 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 283 | if (!initTimerDone) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 284 | initTimer(t); // initial setup with stopped timer |
Helmut Tschemernjak | 77:7f227a4dffe6 | 285 | initTimerDone = true; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 286 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 287 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 288 | stopTimer(t); // avoid timer interrupts while calculating |
Helmut Tschemernjak | 77:7f227a4dffe6 | 289 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 290 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 291 | * every 21333 ns equals one tick (1/(48000000/1024)) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 292 | * COUNT*DIVIDER*SECS until interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 293 | * 48 Mhz = (65536*1024)/1.398636s |
Helmut Tschemernjak | 77:7f227a4dffe6 | 294 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 295 | uint64_t nclocks = (uint64_t)delay_ns; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 296 | nclocks /= (uint64_t)NS_PER_CLOCK; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 297 | int nCounts = nclocks; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 298 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 299 | int bits = TCC_data[USE_TCC_TIMEOUT].nbits; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 300 | int maxCounts = (uint32_t)(1<<bits)-1; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 301 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 302 | if (nCounts > maxCounts) // if count exceeds timer capacity |
Helmut Tschemernjak | 77:7f227a4dffe6 | 303 | nCounts = maxCounts; // set the largest posible count. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 304 | if (nCounts <= 0) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 305 | nCounts = 1; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 306 | t->CC[0].bit.CC = nCounts; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 307 | while (t->SYNCBUSY.bit.CC0 == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 308 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 309 | t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC |
Helmut Tschemernjak | 77:7f227a4dffe6 | 310 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 311 | #if 0 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 312 | ser->print(ms_getTicker(), DEC); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 313 | ser->print(" startTimer: nCounts="); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 314 | ser->println(nCounts, DEC); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 315 | #endif |
Helmut Tschemernjak | 77:7f227a4dffe6 | 316 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 317 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 318 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 319 | #if USE_TCC_TIMEOUT == 0 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 320 | void TCC0_Handler() |
Helmut Tschemernjak | 77:7f227a4dffe6 | 321 | #elif USE_TCC_TIMEOUT == 1 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 322 | void TCC1_Handler() |
Helmut Tschemernjak | 77:7f227a4dffe6 | 323 | #elif USE_TCC_TIMEOUT == 2 |
Helmut Tschemernjak | 77:7f227a4dffe6 | 324 | void TCC2_Handler() |
Helmut Tschemernjak | 77:7f227a4dffe6 | 325 | #endif |
Helmut Tschemernjak | 77:7f227a4dffe6 | 326 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 327 | Tcc *t = TCC_data[USE_TCC_TIMEOUT].tcc_ptr; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 328 | uint64_t nsecs = ns_getTicker(); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 329 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 330 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 331 | * Overflow means the max timer exeeded, we need restart the timer |
Helmut Tschemernjak | 77:7f227a4dffe6 | 332 | * Interrupts and |
Helmut Tschemernjak | 77:7f227a4dffe6 | 333 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 334 | if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 335 | t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag |
Helmut Tschemernjak | 77:7f227a4dffe6 | 336 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 337 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 338 | if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 339 | //ser->print("MC0\r\n"); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 340 | t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag |
Helmut Tschemernjak | 77:7f227a4dffe6 | 341 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 342 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 343 | t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC |
Helmut Tschemernjak | 77:7f227a4dffe6 | 344 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 77:7f227a4dffe6 | 345 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 346 | for (int i = 0; i < MAX_TIMEOUTS-1; i++) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 347 | struct TimeoutVector *tvp = &TimeOuts[i]; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 348 | if (tvp->timer && nsecs >= tvp->timer->_timeout) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 349 | Timeout *saveTimer = tvp->timer; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 350 | tvp->timer = NULL; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 351 | Timeout::_irq_handler(saveTimer); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 352 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 353 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 354 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 355 | * we need to restart the timer for remaining interrupts |
Helmut Tschemernjak | 77:7f227a4dffe6 | 356 | * Another reason is that we stopped this counter, in case there are |
Helmut Tschemernjak | 77:7f227a4dffe6 | 357 | * remaining counts, we need to re-schedule the counter. |
Helmut Tschemernjak | 77:7f227a4dffe6 | 358 | */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 359 | Timeout::restart(); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 360 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 361 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 362 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 363 | /* ----------------- D21 sleep() and deepsleep() code ----------------------*/ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 364 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 365 | void sleep(void) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 366 | { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 367 | /* |
Helmut Tschemernjak | 77:7f227a4dffe6 | 368 | * If we use the native USB port our Serial is SerialUSB |
Helmut Tschemernjak | 77:7f227a4dffe6 | 369 | * and if the SerialUSB and connected we should |
Helmut Tschemernjak | 77:7f227a4dffe6 | 370 | * not enter into sleep mode because this kills the Arduino USB emulation |
Helmut Tschemernjak | 77:7f227a4dffe6 | 371 | */ |
Helmut Tschemernjak | 84:3428e25c7157 | 372 | SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disbale SysTick |
Helmut Tschemernjak | 84:3428e25c7157 | 373 | uint32_t saved_ms = ms_getTicker(); |
Helmut Tschemernjak | 84:3428e25c7157 | 374 | |
Helmut Tschemernjak | 84:3428e25c7157 | 375 | if (SerialUSB_active) { |
Helmut Tschemernjak | 84:3428e25c7157 | 376 | __DSB(); // ensures the completion of memory accesses |
Helmut Tschemernjak | 84:3428e25c7157 | 377 | __WFI(); // wait for interrupt |
Helmut Tschemernjak | 84:3428e25c7157 | 378 | } else { |
Helmut Tschemernjak | 84:3428e25c7157 | 379 | #if 0 // (SAMD20 || SAMD21) |
Helmut Tschemernjak | 84:3428e25c7157 | 380 | /* Errata: Make sure that the Flash does not power all the way down |
Helmut Tschemernjak | 84:3428e25c7157 | 381 | * when in sleep mode. */ |
Helmut Tschemernjak | 84:3428e25c7157 | 382 | NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 383 | #endif |
Helmut Tschemernjak | 84:3428e25c7157 | 384 | |
Helmut Tschemernjak | 84:3428e25c7157 | 385 | SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // clear deep sleep |
Helmut Tschemernjak | 84:3428e25c7157 | 386 | PM->SLEEP.reg = 2; // SYSTEM_SLEEPMODE_IDLE_2 IDLE 2 sleep mode. |
Helmut Tschemernjak | 84:3428e25c7157 | 387 | |
Helmut Tschemernjak | 84:3428e25c7157 | 388 | __DSB(); // ensures the completion of memory accesses |
Helmut Tschemernjak | 84:3428e25c7157 | 389 | __WFI(); // wait for interrupt |
Helmut Tschemernjak | 84:3428e25c7157 | 390 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 391 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 392 | int count = ms_getTicker() - saved_ms; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 393 | if (count > 0) { // update the Arduino Systicks |
Helmut Tschemernjak | 77:7f227a4dffe6 | 394 | for (int i = 0; i < count; i++) { |
Helmut Tschemernjak | 77:7f227a4dffe6 | 395 | SysTick_Handler(); |
Helmut Tschemernjak | 77:7f227a4dffe6 | 396 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 397 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 398 | SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // enable SysTick |
Helmut Tschemernjak | 77:7f227a4dffe6 | 399 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 400 | |
Helmut Tschemernjak | 85:93832cc77534 | 401 | /* |
Helmut Tschemernjak | 85:93832cc77534 | 402 | * TODO |
Helmut Tschemernjak | 85:93832cc77534 | 403 | * Check if we need to disable the USB GCLK->CLKCTRL.reg (see USBCore.cpp) |
Helmut Tschemernjak | 85:93832cc77534 | 404 | * Check what else we need to disable? |
Helmut Tschemernjak | 85:93832cc77534 | 405 | */ |
Helmut Tschemernjak | 85:93832cc77534 | 406 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 407 | void deepsleep(void) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 408 | { |
Helmut Tschemernjak | 85:93832cc77534 | 409 | #if 0 // (SAMD20 || SAMD21) |
Helmut Tschemernjak | 77:7f227a4dffe6 | 410 | /* Errata: Make sure that the Flash does not power all the way down |
Helmut Tschemernjak | 77:7f227a4dffe6 | 411 | * when in sleep mode. */ |
Helmut Tschemernjak | 77:7f227a4dffe6 | 412 | NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; |
Helmut Tschemernjak | 77:7f227a4dffe6 | 413 | #endif |
Helmut Tschemernjak | 77:7f227a4dffe6 | 414 | |
Helmut Tschemernjak | 85:93832cc77534 | 415 | // SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disbale SysTick |
Helmut Tschemernjak | 77:7f227a4dffe6 | 416 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 417 | SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // standby mode |
Helmut Tschemernjak | 77:7f227a4dffe6 | 418 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 419 | __DSB(); // ensures the completion of memory accesses |
Helmut Tschemernjak | 77:7f227a4dffe6 | 420 | __WFI(); // wait for interrupt |
Helmut Tschemernjak | 77:7f227a4dffe6 | 421 | |
Helmut Tschemernjak | 85:93832cc77534 | 422 | // SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // enable SysTick |
Helmut Tschemernjak | 77:7f227a4dffe6 | 423 | } |
Helmut Tschemernjak | 77:7f227a4dffe6 | 424 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 425 | #endif // D21 TCC Timer, sleep, etc- |
Helmut Tschemernjak | 77:7f227a4dffe6 | 426 | |
Helmut Tschemernjak | 77:7f227a4dffe6 | 427 | #endif // ARDUINO |