Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: sx1276/arduino-mbed.cpp
- Revision:
- 66:fbb2da34bd9a
- Parent:
- 65:b2d98328fcba
- Child:
- 67:d3afd803f40d
diff -r b2d98328fcba -r fbb2da34bd9a sx1276/arduino-mbed.cpp
--- a/sx1276/arduino-mbed.cpp Tue Jul 11 13:32:34 2017 +0200
+++ b/sx1276/arduino-mbed.cpp Wed Jul 12 15:11:30 2017 +0200
@@ -219,71 +219,166 @@
* see tcc.h included from
* Arduino15/packages/arduino/tools/CMSIS-Atmel/1.1.0/CMSIS/
* Device/ATMEL/samd21/include/component/tcc.h
+ * See also tcc.c (ASF/mbed, e.g. Tcc_get_count_value)
+ * TODO connect the clock source to OSCULP32K.
*/
-static const struct TCC_CONFIG {
+static void initTimer(Tcc *t);
+static uint32_t getTimerCount(Tcc *t);
+
+
+static const struct TCC_config {
Tcc *tcc_ptr;
IRQn_Type tcc_irq;
uint8_t nbits;
-} TCC_CONFIG[] {
+} TCC_data[] {
{ TCC0, TCC0_IRQn, 24 },
{ TCC1, TCC1_IRQn, 24 },
{ TCC2, TCC2_IRQn, 16 },
+ { NULL, (IRQn_Type)NULL, 0 }
};
-#define USE_TCC 0 // TCC0, TTC1, TTC2 are working using the Arduino D21
+#define USE_TCC_TIMEOUT 0 // TCC0, TTC1, TTC2 are working using the Arduino D21
+#define USE_TCC_TICKER 1
+
+#define NS_PER_CLOCK 21333 // ns secs per clock
+
+/* ----------------- TICKER TIMER CODE ----------------------*/
+long long ticker_ns = 0;
+static bool initTickerDone = false;
+
+/*long long*/ uint32_t us_getTicker(void)
+{
+ Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr;
+ if (!initTickerDone) {
+ initTimer(t);
+ initTickerDone = true;
+
+ int bits = TCC_data[USE_TCC_TIMEOUT].nbits;
+ int maxCounts = (uint32_t)(1<<bits)-1;
+ t->CC[0].bit.CC = 0xfff; // maxCounts;
+
+ t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC
+ while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+
+ }
+ long long tmp_ns = ticker_ns;
+ tmp_ns += (NS_PER_CLOCK * getTimerCount(t));
+ uint32_t t32 = (long long)tmp_ns / (long long)1000 / (long long)1000;
+ return t32;
+}
+#if USE_TCC_TICKER == 0
+void TCC0_Handler()
+#elif USE_TCC_TICKER == 1
+void TCC1_Handler()
+#elif USE_TCC_TICKER == 2
+void TCC2_Handler()
+#endif
+{
+ Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr;
+ /*
+ * Overflow means the max timer exeeded
+ */
+ if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt
+ Serial.print("Ticker_OVF\r\n");
+ t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag
+
+ int bits = TCC_data[USE_TCC_TICKER].nbits;
+ int maxCounts = (uint32_t)(1<<bits);
+
+ ticker_ns += (NS_PER_CLOCK * maxCounts);
+ }
+ if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt
+ Serial.print("MC0\r\n");
+ t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag
+ }
+ Serial.println("TICKER_INTR");
+#if 1
+ t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
+ while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+ t->CTRLA.reg |= TCC_CTRLA_ENABLE; // Disable TC
+ while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+#endif
+}
+
+/* ----------------- TIMEOUT TIMER CODE ----------------------*/
static bool initTimerDone = false;
-static void initTimer() {
- Tcc *TC = TCC_CONFIG[USE_TCC].tcc_ptr;
+static void initTimer(Tcc *t) {
- // Enable clock for TC, see gclk.h
- if (TC == TCC0 || TC == TCC1) {
+ // Enable clock for TCC, see gclk.h
+ if (t == TCC0 || t == TCC1) {
REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC0_TCC1);
- } else if (TC == TCC2) {
+ } else if (t == TCC2) {
REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3_Val);
}
while (GCLK->STATUS.bit.SYNCBUSY == 1); // wait for sync
- TC->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
- while (TC->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+ t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TCC
+ while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
- TC->CTRLA.reg |= (TCC_CTRLA_PRESCALER_DIV1024 | TCC_CTRLA_RUNSTDBY); // Set perscaler
+ t->CTRLA.reg |= (TCC_CTRLA_PRESCALER_DIV1024 | TCC_CTRLA_RUNSTDBY); // Set perscaler
- TC->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ; // Set wave form configuration
- while (TC->SYNCBUSY.bit.WAVE == 1); // wait for sync
+ t->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ; // Set wave form configuration
+ while (t->SYNCBUSY.bit.WAVE == 1); // wait for sync
- TC->PER.bit.PER = 0xFFFFFF; // set counter top to max 24 bit
- while (TC->SYNCBUSY.bit.PER == 1); // wait for sync
+ t->PER.bit.PER = 0xFFFFFF; // set counter top to max 24 bit
+ while (t->SYNCBUSY.bit.PER == 1); // wait for sync
// the compare counter TC->CC[0].reg will be set in the startTimer
// after the timeout calculation is known.
// Interrupts
- TC->INTENSET.reg = 0; // disable all interrupts
- TC->INTENSET.bit.OVF = 1; // enable overfollow
- TC->INTENSET.bit.MC0 = 1; // enable compare match to CC0
+ t->INTENSET.reg = 0; // disable all interrupts
+ t->INTENSET.bit.OVF = 1; // enable overfollow
+ t->INTENSET.bit.MC0 = 1; // enable compare match to CC0
- NVIC_EnableIRQ( TCC_CONFIG[USE_TCC].tcc_irq); // Enable InterruptVector
+ const struct TCC_config *cp = &TCC_data[0];
+ while (cp->tcc_ptr) {
+ if (cp->tcc_ptr == t) {
+ NVIC_EnableIRQ(cp->tcc_irq); // Enable InterruptVector
+ break;
+ }
+ cp++;
+ }
initTimerDone = true;
}
-static void stopTimer(void)
-{
- Tcc *TC = TCC_CONFIG[USE_TCC].tcc_ptr;
+static uint32_t getTimerCount(Tcc *t) {
+
+ uint32_t last_cmd;
+ /* Wait last command done */
+ do {
+ while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */
+
+ last_cmd = t->CTRLBSET.reg & TCC_CTRLBSET_CMD_Msk;
+ if (TCC_CTRLBSET_CMD_NONE == last_cmd) {
+ /* Issue read command and break */
+ t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val;
+ break;
+ } else if (TCC_CTRLBSET_CMD_READSYNC == last_cmd) {
+ /* Command have been issued */
+ break;
+ }
+ } while (1);
- TC->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
- while (TC->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+ while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */
+
+ return t->COUNT.reg;
}
-static void startTimer(uint32_t delay_us)
+static void stopTimer(Tcc *t)
{
- Tcc *TC = TCC_CONFIG[USE_TCC].tcc_ptr;
+ t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
+ while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+}
+
+static void startTimer(Tcc *t, uint32_t delay_us)
+{
+ if (!initTimerDone)
+ initTimer(t); // initial setup with stopped timer
- if (!initTimerDone)
- initTimer(); // initial setup with stopped timer
-
- stopTimer(); // avoid timer interrupts while calculating
+ stopTimer(t); // avoid timer interrupts while calculating
/*
* every 21333 ns equals one tick (1/(48000000/1024))
@@ -294,18 +389,18 @@
nclocks = nclocks / 21333;
int nCounts = nclocks;
- int bits = TCC_CONFIG[USE_TCC].nbits;
+ int bits = TCC_data[USE_TCC_TIMEOUT].nbits;
int maxCounts = (uint32_t)(1<<bits)-1;
if (nCounts > maxCounts) // if count exceeds timer capacity
nCounts = maxCounts; // set the largest posible count.
- if (nCounts == 0)
+ if (nCounts <= 0)
nCounts = 1;
- TC->CC[0].bit.CC = nCounts;
- while (TC->SYNCBUSY.bit.CC0 == 1); // wait for sync
+ t->CC[0].bit.CC = nCounts;
+ while (t->SYNCBUSY.bit.CC0 == 1); // wait for sync
- TC->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC
- while (TC->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+ t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC
+ while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
#if 1
Serial.print(millis(), DEC);
Serial.print(" startTimer: nCounts=");
@@ -315,16 +410,16 @@
-#if USE_TCC == 0
+#if USE_TCC_TIMEOUT == 0
void TCC0_Handler()
-#elif USE_TCC == 1
+#elif USE_TCC_TIMEOUT == 1
void TCC1_Handler()
-#elif USE_TCC == 2
+#elif USE_TCC_TIMEOUT == 2
void TCC2_Handler()
#endif
{
static uint32_t last_usecs = 0;
- Tcc *TC = TCC_CONFIG[USE_TCC].tcc_ptr;
+ Tcc *t = TCC_data[USE_TCC_TIMEOUT].tcc_ptr;
uint32_t usecs = micros();
uint32_t u_offset = 0;
@@ -336,23 +431,26 @@
u_offset = 1000;
}
last_usecs = usecs;
+
+ // Serial.print(getTimerCount(t), DEC);
+ // Serial.println(" TimerCount");
/*
* Overflow means the max timer exeeded, we need restart the timer
* Interrupts and
*/
- if (TC->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt
- Serial.print("OVF\r\n");
- TC->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag
+ if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt
+ Serial.print("Timer_OVF\r\n");
+ t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag
}
- if (TC->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt
+ if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt
//Serial.print("MC0\r\n");
- TC->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag
+ t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag
}
- TC->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
- while (TC->SYNCBUSY.bit.ENABLE == 1); // wait for sync
+ t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC
+ while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync
for (int i = 0; i < MAX_TIMEOUTS-1; i++) {
struct TimeoutVector *tvp = &TimeOuts[i];
@@ -425,17 +523,18 @@
interrupts();
if (timeout == (uint32_t)~0) {
- stopTimer();
+ stopTimer(TCC_data[USE_TCC_TIMEOUT].tcc_ptr);
return;
}
if (!usecs)
usecs = micros();
+ Tcc *t = TCC_data[USE_TCC_TIMEOUT].tcc_ptr;
if (timeout > usecs) {
- startTimer(timeout - usecs);
+ startTimer(t, timeout - usecs);
return;
} else {
- startTimer(1); // just one usec to trigger interrrupt
+ startTimer(t, 1); // just one usec to trigger interrrupt
}
}
#endif // ARDUINO