This is code is part of a Technion course project in advanced IoT, implementing a device to receive and present sensors data from a Formula racing car built by students at Technion - Israel Institute of Technology.

Dependencies:   mbed Buffer

Fork of DISCO-L072CZ-LRWAN1_LoRa_PingPong by ST

This is code is part of a Technion course project in advanced IoT, implementing a device to receive sensors data from another L072CZ-LRWAN1 installed on a Formula racing car (built by students at Technion - Israel Institute of Technology), and sends it to a GUI presenting the data (GUI project: github.com/ward-mattar/TechnionFormulaGUI).

How to install

  • Create an account on Mbed: https://os.mbed.com/account/signup/
  • Import project into Compiler
  • In the Program Workspace select "Formula_Nucleo_Receiver"
  • Select a Platform like so:
  1. Click button at top-left
  2. Add Board
  3. Search "NUCLEO F103RB" and then "Add to your Mbed Compiler"
  • Finally click "Compile", if the build was successful, the binary would download automatically
  • To install it on device simply plug it in to a PC, open device drive and drag then drop binary file in it
Committer:
wardm
Date:
Sat May 19 15:42:38 2018 +0000
Revision:
12:046346a16ff4
V1.0.0

Who changed what in which revision?

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