SX1276GenericLib to support sx1276 bassed LoRa modules, including HopeRF RFM95, Murata CMWX1ZZABZ and Semtech SX1276MB1MAS/SX1276MB1LAS modules

Dependents:   DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_USB_Rx ... more

Fork of SX1276Lib by Semtech

Committer:
Helmut Tschemernjak
Date:
Fri Aug 11 15:11:08 2017 +0200
Revision:
84:3428e25c7157
Parent:
78:9d2cc07d9525
Child:
85:93832cc77534
Modified InitSerial() to check if the USB Serial is active,
turn off USB if no SerialUSB is being in use to save power

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 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 77:7f227a4dffe6 378 // USB->CTRLA.bit.ENABLE = 0;
Helmut Tschemernjak 77:7f227a4dffe6 379 // USB->HOST.CTRLA.reg = 0;
Helmut Tschemernjak 77:7f227a4dffe6 380 // USB->HOST.CTRLA.bit.ENABLE &= USB_CTRLA_ENABLE;
Helmut Tschemernjak 84:3428e25c7157 381 } else {
Helmut Tschemernjak 84:3428e25c7157 382 #if 0 // (SAMD20 || SAMD21)
Helmut Tschemernjak 84:3428e25c7157 383 /* Errata: Make sure that the Flash does not power all the way down
Helmut Tschemernjak 84:3428e25c7157 384 * when in sleep mode. */
Helmut Tschemernjak 84:3428e25c7157 385 NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;
Helmut Tschemernjak 77:7f227a4dffe6 386 #endif
Helmut Tschemernjak 84:3428e25c7157 387
Helmut Tschemernjak 84:3428e25c7157 388 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // clear deep sleep
Helmut Tschemernjak 84:3428e25c7157 389 PM->SLEEP.reg = 2; // SYSTEM_SLEEPMODE_IDLE_2 IDLE 2 sleep mode.
Helmut Tschemernjak 84:3428e25c7157 390
Helmut Tschemernjak 84:3428e25c7157 391 __DSB(); // ensures the completion of memory accesses
Helmut Tschemernjak 84:3428e25c7157 392 __WFI(); // wait for interrupt
Helmut Tschemernjak 84:3428e25c7157 393 }
Helmut Tschemernjak 77:7f227a4dffe6 394
Helmut Tschemernjak 77:7f227a4dffe6 395 int count = ms_getTicker() - saved_ms;
Helmut Tschemernjak 77:7f227a4dffe6 396 if (count > 0) { // update the Arduino Systicks
Helmut Tschemernjak 77:7f227a4dffe6 397 for (int i = 0; i < count; i++) {
Helmut Tschemernjak 77:7f227a4dffe6 398 SysTick_Handler();
Helmut Tschemernjak 77:7f227a4dffe6 399 }
Helmut Tschemernjak 77:7f227a4dffe6 400 }
Helmut Tschemernjak 77:7f227a4dffe6 401 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // enable SysTick
Helmut Tschemernjak 77:7f227a4dffe6 402 }
Helmut Tschemernjak 77:7f227a4dffe6 403
Helmut Tschemernjak 77:7f227a4dffe6 404 void deepsleep(void)
Helmut Tschemernjak 77:7f227a4dffe6 405 {
Helmut Tschemernjak 77:7f227a4dffe6 406 #if 1 // (SAMD20 || SAMD21)
Helmut Tschemernjak 77:7f227a4dffe6 407 /* Errata: Make sure that the Flash does not power all the way down
Helmut Tschemernjak 77:7f227a4dffe6 408 * when in sleep mode. */
Helmut Tschemernjak 77:7f227a4dffe6 409 NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;
Helmut Tschemernjak 77:7f227a4dffe6 410 #endif
Helmut Tschemernjak 77:7f227a4dffe6 411
Helmut Tschemernjak 77:7f227a4dffe6 412 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disbale SysTick
Helmut Tschemernjak 77:7f227a4dffe6 413
Helmut Tschemernjak 77:7f227a4dffe6 414 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // standby mode
Helmut Tschemernjak 77:7f227a4dffe6 415
Helmut Tschemernjak 77:7f227a4dffe6 416 __DSB(); // ensures the completion of memory accesses
Helmut Tschemernjak 77:7f227a4dffe6 417 __WFI(); // wait for interrupt
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 77:7f227a4dffe6 422 #endif // D21 TCC Timer, sleep, etc-
Helmut Tschemernjak 77:7f227a4dffe6 423
Helmut Tschemernjak 77:7f227a4dffe6 424 #endif // ARDUINO