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 Helmut Tschemernjak

Committer:
Helmut Tschemernjak
Date:
Wed Nov 22 12:14:00 2017 +0100
Revision:
105:6e6d141c3da8
Parent:
101:50377edb21c6
Moved ESP32 helper functions into arduino-esp32.cpp
Allow to change MAX_TIMEOUTS without need to change
custom d21 and ESP32 assembler files

Who changed what in which revision?

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