Helmut Tschemernjak / SX1276GenericLib

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

Files at this revision

API Documentation at this revision

Comitter:
Helmut Tschemernjak
Date:
Sat Nov 18 13:54:15 2017 +0100
Parent:
96:9da7e00c9d0f
Child:
98:1e741f2b3eda
Commit message:
Change timeout functions to use a generic TIMER_REF instead of a D21 TCC pointer
Added support for ESP32 SPI, Serial
Added suport for ESP32 64-bit timer

Changed in this revision

Arduino-mbed-APIs/arduino-d21.cpp Show annotated file Show diff for this revision Revisions of this file
Arduino-mbed-APIs/arduino-esp32.cpp Show annotated file Show diff for this revision Revisions of this file
Arduino-mbed-APIs/arduino-mbed.cpp Show annotated file Show diff for this revision Revisions of this file
Arduino-mbed-APIs/arduino-mbed.h Show annotated file Show diff for this revision Revisions of this file
sx1276/library.properties Show annotated file Show diff for this revision Revisions of this file
--- a/Arduino-mbed-APIs/arduino-d21.cpp	Tue Nov 14 14:52:01 2017 +0100
+++ b/Arduino-mbed-APIs/arduino-d21.cpp	Sat Nov 18 13:54:15 2017 +0100
@@ -262,13 +262,11 @@
     return count;
 }
 
-
-Tcc *getTimeout_tcc(void)
+TIMER_REF *getTimeoutTimer(void)
 {
     return TCC_data[USE_TCC_TIMEOUT].tcc_ptr;
 }
 
-
 void stopTimer(Tcc *t)
 {
     t->CTRLA.reg &= ~TCC_CTRLA_ENABLE;   // Disable TC
@@ -424,6 +422,6 @@
     __WFI(); // wait for interrupt
 }
 
-#endif // D21 TCC Timer, sleep, etc-
+#endif // D21 TCC Timer, sleep, etc.
 
 #endif // ARDUINO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Arduino-mbed-APIs/arduino-esp32.cpp	Sat Nov 18 13:54:15 2017 +0100
@@ -0,0 +1,230 @@
+/*
+ * The file is Licensed under the Apache License, Version 2.0
+ * (c) 2017 Helmut Tschemernjak
+ * 30826 Garbsen (Hannover) Germany
+ */
+
+#ifdef ARDUINO
+
+using namespace std;
+
+#include "arduino-mbed.h"
+#include "arduino-util.h"
+
+
+
+#if defined(ARDUINO_ARCH_ESP32)
+/*
+ * ARDUINO_ARCH_ESP32 ESP32 development board
+ * Heltec ESP32 boards
+ */
+
+int
+CPUID(uint8_t *buf, int maxSize, uint32_t xorval)
+{
+ 	uint64_t chipid = ESP.getEfuseMac();//The chip ID is essentially its MAC address(length: 6 bytes).
+    
+    
+    if (maxSize >= sizeof(chipid)) {
+        memset(buf, 0, maxSize);
+        chipid = chipid ^ xorval;
+        memcpy(&chipid, buf, sizeof(chipid));
+        return sizeof(chipid) ;
+    }
+    return 0;
+}
+
+/*
+ * see esp32-hal-timer.h is automatically included from:
+ * Arduino15/packages/arduino/hardware/espressif/esp32/cores/esp32
+ */
+static void initTimer(int timerID);
+void IRAM_ATTR onTimer(void);
+/*
+ * The Atmel ESP32 has three 64-bit timer.
+ */
+struct TIMER_config {
+    int timerID;
+    hw_timer_t *timer;
+    uint8_t nbits;
+} Timer_data[] {
+    { 0, NULL, 32 },
+    { 1, NULL, 32 },
+    { 2, NULL, 32 },
+    { -1, NULL, 0 }
+};
+
+/*
+ * We preferably use ESP32 timers because it supports 64-bit counters
+ */
+#define USE_TIMER_TIMEOUT	0 // 0, 1, 2 (see ESP32 docs)
+#define USE_TIMER_TICKER	1 // 0, 1, 2 (see ESP32 docs)
+#define MAX_TIMERS			3
+
+/*
+ * Calculation of ticks see timerBegin divider
+ */
+#define NS_PER_CLOCK_CPU	1000 // ns secs per clock
+#define NS_PER_CLOCK_RTC	1000 // ns secs per clock
+#define TIMER_INFINITE		0x7fffffffffffffff // max esp alarm timeout
+#define NS_PER_CLOCK	NS_PER_CLOCK_RTC
+
+
+const char *GetTimerName(int timerID)
+{
+    switch(timerID) {
+        case USE_TIMER_TIMEOUT:
+            return "TIMEOUT";
+            break;
+        case USE_TIMER_TICKER:
+            return "TICKER";
+            break;
+        default:
+            return "Uknown";
+    }
+}
+
+/* ----------------- TICKER TIMER CODE ----------------------*/
+
+/*
+ * The global ns_counter contains the time in ns from the last time
+ * the counter has been wrapped. It cannot be used directly because the
+ * current counter has to be added fore using it. Use instead
+ * ns_getTicker(), us_ ns_getTicker(), ms_getTicker()
+ */
+
+static volatile bool initTickerDone = false;
+
+uint64_t ns_getTicker(void)
+{
+    int timerID = Timer_data[USE_TIMER_TICKER].timerID;
+    
+    if (!initTickerDone) {
+        initTimer(timerID);
+        initTickerDone = true;
+        dprintf("ESP32 Revision: %d (%d MHz)\r\n", ESP.getChipRevision(), ESP.getCpuFreqMHz());
+    }
+    
+    hw_timer_t *timer = Timer_data[USE_TIMER_TICKER].timer;
+    uint64_t ns = timerRead(timer);
+    uint16_t div = timerGetDivider(timer);
+    ns *= div;	// get to the real clocks
+    ns /= 8; 	// 80 MHz , divide by 8 to keep more NS
+    ns *= 100; 	// us to ns equals 1000, however we divided only by 8 remaing are 1000
+    
+    return ns;
+}
+
+
+/* ----------------- SUPPORT CODE FOR TCC TIMERS----------------------*/
+
+static volatile bool initTimerDone = false;
+
+static void initTimer(int timerID)
+{
+    //dprintf("initTimer: %s", GetTimerName(timerID));
+    struct TIMER_config *cp = &Timer_data[timerID];
+    if (timerID > MAX_TIMERS-1)
+        return;
+    
+    cp->timer = timerBegin(timerID, 80, true);
+    timerWrite(cp->timer, 0);
+	if (timerID == USE_TIMER_TICKER)
+    	timerStart(cp->timer);
+    else {
+    	timerAttachInterrupt(cp->timer, &onTimer, true);
+        timerAlarmWrite(cp->timer, TIMER_INFINITE, true);
+        timerAlarmEnable(cp->timer);
+        timerStart(cp->timer);
+    }
+	/*
+     * somehow the timer needs some time to initalize before being used.
+     * otherwise it will not issue any alarms
+     * This affects only ESP32 rev 0
+	 */
+     delay(20);
+}
+
+
+TIMER_REF *getTimeoutTimer(void)
+{
+    struct TIMER_config *cp = &Timer_data[USE_TIMER_TIMEOUT];
+    
+    return &cp->timerID;
+}
+
+
+void stopTimer(int *timerIDPtr)
+{
+    struct TIMER_config *cp = &Timer_data[*timerIDPtr];
+    if (*timerIDPtr > MAX_TIMERS-1)
+        return;
+
+    if (cp->timer)
+	    timerAlarmWrite(cp->timer, TIMER_INFINITE, true);
+}
+
+
+/* ----------------- TIMEOUT TIMER CODE ----------------------*/
+
+void startTimer(int *timerIDPtr, uint64_t delay_ns)
+{
+    if (!initTimerDone) {
+        initTimer(*timerIDPtr);	// initial setup with stopped timer
+        initTimerDone = true;
+    }
+
+    struct TIMER_config *cp = &Timer_data[*timerIDPtr];
+    if (*timerIDPtr > MAX_TIMERS-1)
+        return;
+    uint64_t usecs = delay_ns/1000;
+    if (delay_ns == 1) // immediate timeout
+        usecs = 1;
+    timerAlarmWrite(cp->timer, usecs, true);
+    // dprintf("startTimer: %s in %d us", GetTimerName(*timerIDPtr), usecs);
+}
+
+/*
+ * The onTimer is only called for every Timeout expired timer
+ */
+void IRAM_ATTR onTimer(void) {
+    //dprintf("onTimer int called");
+    uint64_t nsecs = ns_getTicker();
+
+    for (int i = 0; i < MAX_TIMEOUTS-1; i++) {
+        struct TimeoutVector *tvp = &TimeOuts[i];
+        if (tvp->timer && nsecs >= tvp->timer->_timeout) {
+            Timeout *saveTimer = tvp->timer;
+            tvp->timer = NULL;
+            Timeout::_irq_handler(saveTimer);
+        }
+    }
+    /*
+     * we need to restart the timer for remaining interrupts
+     * Another reason is that we stopped this counter, in case there are
+     * remaining counts, we need to re-schedule the counter.
+     */
+    Timeout::restart();
+}
+
+
+/* ----------------- ESP32 sleep() and deepsleep() code ----------------------*/
+
+void sleep(void)
+{
+    asm("waiti 0");
+}
+
+/*
+ * TODO
+ * The ESP32 deepsleep can be enhanced to bring the ESP into low power mode.
+ */
+
+void deepsleep(void)
+{
+    asm("waiti 0");
+}
+
+#endif // ESp32  Timer, sleep, etc.
+
+#endif // ARDUINO
--- a/Arduino-mbed-APIs/arduino-mbed.cpp	Tue Nov 14 14:52:01 2017 +0100
+++ b/Arduino-mbed-APIs/arduino-mbed.cpp	Sat Nov 18 13:54:15 2017 +0100
@@ -22,6 +22,7 @@
 
 void InitSerial(Stream *serial, int timeout_ms, DigitalOut *led, bool waitForSerial) {
     ser = serial;
+#ifdef ARDUINO_SAMD_ZERO
     SerialUSB_active = true;
     if (!timeout_ms)
         return;
@@ -59,6 +60,11 @@
             }
         }
     }
+#elif ARDUINO_ARCH_ESP32
+	SerialUSB_active = false;
+#else
+#eror "unkown MCU"
+#endif
 }
 
 static void pinInt00(void);
@@ -356,7 +362,7 @@
 void
 Timeout::restart()
 {
-    Tcc *t = getTimeout_tcc();
+    TIMER_REF *t = getTimeoutTimer();
     uint64_t timeout = ~0;
     
     /*
--- a/Arduino-mbed-APIs/arduino-mbed.h	Tue Nov 14 14:52:01 2017 +0100
+++ b/Arduino-mbed-APIs/arduino-mbed.h	Sat Nov 18 13:54:15 2017 +0100
@@ -27,21 +27,27 @@
  #define MYdigitalPinToInterrupt(x)	(x)
 #endif
 
+#ifdef ARDUINO_ARCH_ESP32
+typedef int	TIMER_REF;
+#elif ARDUINO_SAMD_ZERO
+typedef Tcc TIMER_REF;
+#else
+#error "unkown platform"
+#endif
+
 class DigitalOut;
 void InitSerial(Stream *serial, int timeout_ms, DigitalOut *led, bool waitForSerial);
 extern Stream *ser;
 extern bool SerialUSB_active;
 
 /*
- * Arduino_d21.cpp
+ * Arduino_d21.cpp Arduino_ESP32.cpp
  */
-extern void startTimer(Tcc *t, uint64_t delay_ns);
-extern void stopTimer(Tcc *t);
+extern void startTimer(TIMER_REF *t, uint64_t delay_ns);
+extern void stopTimer(TIMER_REF *t);
+extern TIMER_REF *getTimeoutTimer(void);
 extern uint64_t ns_getTicker(void);
-extern Tcc *getTimeout_tcc(void);
 extern int CPUID(uint8_t *buf, int maxSize, uint32_t xorval);
-
-
 extern void sleep(void);
 extern void deepsleep(void);
 
@@ -148,6 +154,10 @@
         _mosi = mosi;
         _miso = miso;
         _sclk = sclk;
+#ifdef ARDUINO_ARCH_ESP32 // TODO
+        if (1)
+	        _spi = &SPI;
+#elif defined (ARDUINO_SAMD_ZERO)
         if (mosi == PIN_SPI_MOSI && miso == PIN_SPI_MISO && sclk == PIN_SPI_SCK)
             _spi = &SPI;
 #if SPI_INTERFACES_COUNT > 1
@@ -158,6 +168,7 @@
         else if (mosi == PIN_SPI2_MOSI && miso == PIN_SPI2_MISO && sclk == PIN_SPI2_SCK)
             _spi = &SPI2;
 #endif
+#endif
         else {
             _spi = NULL;
             return;
--- a/sx1276/library.properties	Tue Nov 14 14:52:01 2017 +0100
+++ b/sx1276/library.properties	Sat Nov 18 13:54:15 2017 +0100
@@ -6,4 +6,4 @@
 paragraph=
 category=Communication
 url=http://www.radioshuttle.de
-architectures=samd
+architectures=samd,esp32