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

Committer:
Helmut Tschemernjak
Date:
Sun Nov 19 17:51:27 2017 +0100
Revision:
101:50377edb21c6
Parent:
97:3d5d489206aa
Child:
103:59930a715bf8
Added a feature to preset the ns_ticker start value

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Helmut Tschemernjak 97:3d5d489206aa 1 /*
Helmut Tschemernjak 97:3d5d489206aa 2 * The file is Licensed under the Apache License, Version 2.0
Helmut Tschemernjak 97:3d5d489206aa 3 * (c) 2017 Helmut Tschemernjak
Helmut Tschemernjak 97:3d5d489206aa 4 * 30826 Garbsen (Hannover) Germany
Helmut Tschemernjak 97:3d5d489206aa 5 */
Helmut Tschemernjak 97:3d5d489206aa 6
Helmut Tschemernjak 97:3d5d489206aa 7 #ifdef ARDUINO
Helmut Tschemernjak 97:3d5d489206aa 8
Helmut Tschemernjak 97:3d5d489206aa 9 using namespace std;
Helmut Tschemernjak 97:3d5d489206aa 10
Helmut Tschemernjak 97:3d5d489206aa 11 #include "arduino-mbed.h"
Helmut Tschemernjak 97:3d5d489206aa 12 #include "arduino-util.h"
Helmut Tschemernjak 101:50377edb21c6 13 #include <time.h>
Helmut Tschemernjak 97:3d5d489206aa 14
Helmut Tschemernjak 97:3d5d489206aa 15
Helmut Tschemernjak 97:3d5d489206aa 16 #if defined(ARDUINO_ARCH_ESP32)
Helmut Tschemernjak 97:3d5d489206aa 17 /*
Helmut Tschemernjak 97:3d5d489206aa 18 * ARDUINO_ARCH_ESP32 ESP32 development board
Helmut Tschemernjak 97:3d5d489206aa 19 * Heltec ESP32 boards
Helmut Tschemernjak 97:3d5d489206aa 20 */
Helmut Tschemernjak 97:3d5d489206aa 21
Helmut Tschemernjak 97:3d5d489206aa 22 int
Helmut Tschemernjak 97:3d5d489206aa 23 CPUID(uint8_t *buf, int maxSize, uint32_t xorval)
Helmut Tschemernjak 97:3d5d489206aa 24 {
Helmut Tschemernjak 97:3d5d489206aa 25 uint64_t chipid = ESP.getEfuseMac();//The chip ID is essentially its MAC address(length: 6 bytes).
Helmut Tschemernjak 97:3d5d489206aa 26
Helmut Tschemernjak 97:3d5d489206aa 27
Helmut Tschemernjak 97:3d5d489206aa 28 if (maxSize >= sizeof(chipid)) {
Helmut Tschemernjak 97:3d5d489206aa 29 memset(buf, 0, maxSize);
Helmut Tschemernjak 97:3d5d489206aa 30 chipid = chipid ^ xorval;
Helmut Tschemernjak 97:3d5d489206aa 31 memcpy(&chipid, buf, sizeof(chipid));
Helmut Tschemernjak 97:3d5d489206aa 32 return sizeof(chipid) ;
Helmut Tschemernjak 97:3d5d489206aa 33 }
Helmut Tschemernjak 97:3d5d489206aa 34 return 0;
Helmut Tschemernjak 97:3d5d489206aa 35 }
Helmut Tschemernjak 97:3d5d489206aa 36
Helmut Tschemernjak 97:3d5d489206aa 37 /*
Helmut Tschemernjak 97:3d5d489206aa 38 * see esp32-hal-timer.h is automatically included from:
Helmut Tschemernjak 97:3d5d489206aa 39 * Arduino15/packages/arduino/hardware/espressif/esp32/cores/esp32
Helmut Tschemernjak 97:3d5d489206aa 40 */
Helmut Tschemernjak 97:3d5d489206aa 41 static void initTimer(int timerID);
Helmut Tschemernjak 97:3d5d489206aa 42 void IRAM_ATTR onTimer(void);
Helmut Tschemernjak 97:3d5d489206aa 43 /*
Helmut Tschemernjak 97:3d5d489206aa 44 * The Atmel ESP32 has three 64-bit timer.
Helmut Tschemernjak 97:3d5d489206aa 45 */
Helmut Tschemernjak 97:3d5d489206aa 46 struct TIMER_config {
Helmut Tschemernjak 97:3d5d489206aa 47 int timerID;
Helmut Tschemernjak 97:3d5d489206aa 48 hw_timer_t *timer;
Helmut Tschemernjak 97:3d5d489206aa 49 uint8_t nbits;
Helmut Tschemernjak 97:3d5d489206aa 50 } Timer_data[] {
Helmut Tschemernjak 97:3d5d489206aa 51 { 0, NULL, 32 },
Helmut Tschemernjak 97:3d5d489206aa 52 { 1, NULL, 32 },
Helmut Tschemernjak 97:3d5d489206aa 53 { 2, NULL, 32 },
Helmut Tschemernjak 97:3d5d489206aa 54 { -1, NULL, 0 }
Helmut Tschemernjak 97:3d5d489206aa 55 };
Helmut Tschemernjak 97:3d5d489206aa 56
Helmut Tschemernjak 97:3d5d489206aa 57 /*
Helmut Tschemernjak 97:3d5d489206aa 58 * We preferably use ESP32 timers because it supports 64-bit counters
Helmut Tschemernjak 97:3d5d489206aa 59 */
Helmut Tschemernjak 97:3d5d489206aa 60 #define USE_TIMER_TIMEOUT 0 // 0, 1, 2 (see ESP32 docs)
Helmut Tschemernjak 97:3d5d489206aa 61 #define USE_TIMER_TICKER 1 // 0, 1, 2 (see ESP32 docs)
Helmut Tschemernjak 97:3d5d489206aa 62 #define MAX_TIMERS 3
Helmut Tschemernjak 101:50377edb21c6 63 #define TIMER_DIVIDER 80
Helmut Tschemernjak 101:50377edb21c6 64 #define TIMER_CLOCK 80
Helmut Tschemernjak 97:3d5d489206aa 65
Helmut Tschemernjak 97:3d5d489206aa 66 /*
Helmut Tschemernjak 97:3d5d489206aa 67 * Calculation of ticks see timerBegin divider
Helmut Tschemernjak 97:3d5d489206aa 68 */
Helmut Tschemernjak 97:3d5d489206aa 69 #define NS_PER_CLOCK_CPU 1000 // ns secs per clock
Helmut Tschemernjak 97:3d5d489206aa 70 #define NS_PER_CLOCK_RTC 1000 // ns secs per clock
Helmut Tschemernjak 97:3d5d489206aa 71 #define TIMER_INFINITE 0x7fffffffffffffff // max esp alarm timeout
Helmut Tschemernjak 97:3d5d489206aa 72 #define NS_PER_CLOCK NS_PER_CLOCK_RTC
Helmut Tschemernjak 97:3d5d489206aa 73
Helmut Tschemernjak 97:3d5d489206aa 74
Helmut Tschemernjak 97:3d5d489206aa 75 const char *GetTimerName(int timerID)
Helmut Tschemernjak 97:3d5d489206aa 76 {
Helmut Tschemernjak 97:3d5d489206aa 77 switch(timerID) {
Helmut Tschemernjak 97:3d5d489206aa 78 case USE_TIMER_TIMEOUT:
Helmut Tschemernjak 97:3d5d489206aa 79 return "TIMEOUT";
Helmut Tschemernjak 97:3d5d489206aa 80 break;
Helmut Tschemernjak 97:3d5d489206aa 81 case USE_TIMER_TICKER:
Helmut Tschemernjak 97:3d5d489206aa 82 return "TICKER";
Helmut Tschemernjak 97:3d5d489206aa 83 break;
Helmut Tschemernjak 97:3d5d489206aa 84 default:
Helmut Tschemernjak 97:3d5d489206aa 85 return "Uknown";
Helmut Tschemernjak 97:3d5d489206aa 86 }
Helmut Tschemernjak 97:3d5d489206aa 87 }
Helmut Tschemernjak 97:3d5d489206aa 88
Helmut Tschemernjak 97:3d5d489206aa 89 /* ----------------- TICKER TIMER CODE ----------------------*/
Helmut Tschemernjak 97:3d5d489206aa 90
Helmut Tschemernjak 97:3d5d489206aa 91 /*
Helmut Tschemernjak 97:3d5d489206aa 92 * The global ns_counter contains the time in ns from the last time
Helmut Tschemernjak 97:3d5d489206aa 93 * the counter has been wrapped. It cannot be used directly because the
Helmut Tschemernjak 97:3d5d489206aa 94 * current counter has to be added fore using it. Use instead
Helmut Tschemernjak 97:3d5d489206aa 95 * ns_getTicker(), us_ ns_getTicker(), ms_getTicker()
Helmut Tschemernjak 97:3d5d489206aa 96 */
Helmut Tschemernjak 97:3d5d489206aa 97
Helmut Tschemernjak 97:3d5d489206aa 98 static volatile bool initTickerDone = false;
Helmut Tschemernjak 97:3d5d489206aa 99
Helmut Tschemernjak 97:3d5d489206aa 100 uint64_t ns_getTicker(void)
Helmut Tschemernjak 97:3d5d489206aa 101 {
Helmut Tschemernjak 97:3d5d489206aa 102 int timerID = Timer_data[USE_TIMER_TICKER].timerID;
Helmut Tschemernjak 97:3d5d489206aa 103
Helmut Tschemernjak 97:3d5d489206aa 104 if (!initTickerDone) {
Helmut Tschemernjak 97:3d5d489206aa 105 initTimer(timerID);
Helmut Tschemernjak 97:3d5d489206aa 106 initTickerDone = true;
Helmut Tschemernjak 97:3d5d489206aa 107 }
Helmut Tschemernjak 97:3d5d489206aa 108
Helmut Tschemernjak 97:3d5d489206aa 109 hw_timer_t *timer = Timer_data[USE_TIMER_TICKER].timer;
Helmut Tschemernjak 97:3d5d489206aa 110 uint64_t ns = timerRead(timer);
Helmut Tschemernjak 97:3d5d489206aa 111 uint16_t div = timerGetDivider(timer);
Helmut Tschemernjak 97:3d5d489206aa 112 ns *= div; // get to the real clocks
Helmut Tschemernjak 101:50377edb21c6 113 ns *= 1000; // convert micros to NS.
Helmut Tschemernjak 101:50377edb21c6 114 ns /= TIMER_CLOCK; // 80 MHz clock, convert to micro seconds
Helmut Tschemernjak 97:3d5d489206aa 115
Helmut Tschemernjak 97:3d5d489206aa 116 return ns;
Helmut Tschemernjak 97:3d5d489206aa 117 }
Helmut Tschemernjak 97:3d5d489206aa 118
Helmut Tschemernjak 97:3d5d489206aa 119
Helmut Tschemernjak 97:3d5d489206aa 120 /* ----------------- SUPPORT CODE FOR TCC TIMERS----------------------*/
Helmut Tschemernjak 97:3d5d489206aa 121
Helmut Tschemernjak 97:3d5d489206aa 122 static volatile bool initTimerDone = false;
Helmut Tschemernjak 97:3d5d489206aa 123
Helmut Tschemernjak 97:3d5d489206aa 124 static void initTimer(int timerID)
Helmut Tschemernjak 97:3d5d489206aa 125 {
Helmut Tschemernjak 97:3d5d489206aa 126 //dprintf("initTimer: %s", GetTimerName(timerID));
Helmut Tschemernjak 97:3d5d489206aa 127 struct TIMER_config *cp = &Timer_data[timerID];
Helmut Tschemernjak 97:3d5d489206aa 128 if (timerID > MAX_TIMERS-1)
Helmut Tschemernjak 97:3d5d489206aa 129 return;
Helmut Tschemernjak 97:3d5d489206aa 130
Helmut Tschemernjak 101:50377edb21c6 131 cp->timer = timerBegin(timerID, TIMER_DIVIDER, true);
Helmut Tschemernjak 97:3d5d489206aa 132 timerWrite(cp->timer, 0);
Helmut Tschemernjak 101:50377edb21c6 133 if (timerID == USE_TIMER_TICKER) {
Helmut Tschemernjak 101:50377edb21c6 134 time_t t = time(NULL);
Helmut Tschemernjak 101:50377edb21c6 135 if (t > 0) {
Helmut Tschemernjak 101:50377edb21c6 136 struct tm mytm;
Helmut Tschemernjak 101:50377edb21c6 137 uint64_t tstart;
Helmut Tschemernjak 101:50377edb21c6 138
Helmut Tschemernjak 101:50377edb21c6 139 localtime_r(&t, &mytm);
Helmut Tschemernjak 101:50377edb21c6 140 tstart = mytm.tm_sec + (mytm.tm_min * 60) + (mytm.tm_hour * 3600);
Helmut Tschemernjak 101:50377edb21c6 141 tstart *= 1000000;
Helmut Tschemernjak 101:50377edb21c6 142 tstart *= TIMER_CLOCK;
Helmut Tschemernjak 101:50377edb21c6 143 tstart /= TIMER_DIVIDER;
Helmut Tschemernjak 101:50377edb21c6 144 timerWrite(cp->timer, tstart);
Helmut Tschemernjak 101:50377edb21c6 145 }
Helmut Tschemernjak 97:3d5d489206aa 146 timerStart(cp->timer);
Helmut Tschemernjak 101:50377edb21c6 147 } else {
Helmut Tschemernjak 97:3d5d489206aa 148 timerAttachInterrupt(cp->timer, &onTimer, true);
Helmut Tschemernjak 97:3d5d489206aa 149 timerAlarmWrite(cp->timer, TIMER_INFINITE, true);
Helmut Tschemernjak 97:3d5d489206aa 150 timerAlarmEnable(cp->timer);
Helmut Tschemernjak 97:3d5d489206aa 151 timerStart(cp->timer);
Helmut Tschemernjak 97:3d5d489206aa 152 }
Helmut Tschemernjak 97:3d5d489206aa 153 /*
Helmut Tschemernjak 97:3d5d489206aa 154 * somehow the timer needs some time to initalize before being used.
Helmut Tschemernjak 97:3d5d489206aa 155 * otherwise it will not issue any alarms
Helmut Tschemernjak 97:3d5d489206aa 156 * This affects only ESP32 rev 0
Helmut Tschemernjak 97:3d5d489206aa 157 */
Helmut Tschemernjak 101:50377edb21c6 158 if (ESP.getChipRevision() == 0)
Helmut Tschemernjak 101:50377edb21c6 159 delay(20);
Helmut Tschemernjak 97:3d5d489206aa 160 }
Helmut Tschemernjak 97:3d5d489206aa 161
Helmut Tschemernjak 97:3d5d489206aa 162
Helmut Tschemernjak 97:3d5d489206aa 163 TIMER_REF *getTimeoutTimer(void)
Helmut Tschemernjak 97:3d5d489206aa 164 {
Helmut Tschemernjak 97:3d5d489206aa 165 struct TIMER_config *cp = &Timer_data[USE_TIMER_TIMEOUT];
Helmut Tschemernjak 97:3d5d489206aa 166
Helmut Tschemernjak 97:3d5d489206aa 167 return &cp->timerID;
Helmut Tschemernjak 97:3d5d489206aa 168 }
Helmut Tschemernjak 97:3d5d489206aa 169
Helmut Tschemernjak 97:3d5d489206aa 170
Helmut Tschemernjak 97:3d5d489206aa 171 void stopTimer(int *timerIDPtr)
Helmut Tschemernjak 97:3d5d489206aa 172 {
Helmut Tschemernjak 97:3d5d489206aa 173 struct TIMER_config *cp = &Timer_data[*timerIDPtr];
Helmut Tschemernjak 97:3d5d489206aa 174 if (*timerIDPtr > MAX_TIMERS-1)
Helmut Tschemernjak 97:3d5d489206aa 175 return;
Helmut Tschemernjak 97:3d5d489206aa 176
Helmut Tschemernjak 97:3d5d489206aa 177 if (cp->timer)
Helmut Tschemernjak 97:3d5d489206aa 178 timerAlarmWrite(cp->timer, TIMER_INFINITE, true);
Helmut Tschemernjak 97:3d5d489206aa 179 }
Helmut Tschemernjak 97:3d5d489206aa 180
Helmut Tschemernjak 97:3d5d489206aa 181
Helmut Tschemernjak 97:3d5d489206aa 182 /* ----------------- TIMEOUT TIMER CODE ----------------------*/
Helmut Tschemernjak 97:3d5d489206aa 183
Helmut Tschemernjak 97:3d5d489206aa 184 void startTimer(int *timerIDPtr, uint64_t delay_ns)
Helmut Tschemernjak 97:3d5d489206aa 185 {
Helmut Tschemernjak 97:3d5d489206aa 186 if (!initTimerDone) {
Helmut Tschemernjak 97:3d5d489206aa 187 initTimer(*timerIDPtr); // initial setup with stopped timer
Helmut Tschemernjak 97:3d5d489206aa 188 initTimerDone = true;
Helmut Tschemernjak 97:3d5d489206aa 189 }
Helmut Tschemernjak 97:3d5d489206aa 190
Helmut Tschemernjak 97:3d5d489206aa 191 struct TIMER_config *cp = &Timer_data[*timerIDPtr];
Helmut Tschemernjak 97:3d5d489206aa 192 if (*timerIDPtr > MAX_TIMERS-1)
Helmut Tschemernjak 97:3d5d489206aa 193 return;
Helmut Tschemernjak 97:3d5d489206aa 194 uint64_t usecs = delay_ns/1000;
Helmut Tschemernjak 97:3d5d489206aa 195 if (delay_ns == 1) // immediate timeout
Helmut Tschemernjak 97:3d5d489206aa 196 usecs = 1;
Helmut Tschemernjak 97:3d5d489206aa 197 timerAlarmWrite(cp->timer, usecs, true);
Helmut Tschemernjak 97:3d5d489206aa 198 // dprintf("startTimer: %s in %d us", GetTimerName(*timerIDPtr), usecs);
Helmut Tschemernjak 97:3d5d489206aa 199 }
Helmut Tschemernjak 97:3d5d489206aa 200
Helmut Tschemernjak 97:3d5d489206aa 201 /*
Helmut Tschemernjak 97:3d5d489206aa 202 * The onTimer is only called for every Timeout expired timer
Helmut Tschemernjak 97:3d5d489206aa 203 */
Helmut Tschemernjak 97:3d5d489206aa 204 void IRAM_ATTR onTimer(void) {
Helmut Tschemernjak 97:3d5d489206aa 205 //dprintf("onTimer int called");
Helmut Tschemernjak 97:3d5d489206aa 206 uint64_t nsecs = ns_getTicker();
Helmut Tschemernjak 97:3d5d489206aa 207
Helmut Tschemernjak 97:3d5d489206aa 208 for (int i = 0; i < MAX_TIMEOUTS-1; i++) {
Helmut Tschemernjak 97:3d5d489206aa 209 struct TimeoutVector *tvp = &TimeOuts[i];
Helmut Tschemernjak 97:3d5d489206aa 210 if (tvp->timer && nsecs >= tvp->timer->_timeout) {
Helmut Tschemernjak 97:3d5d489206aa 211 Timeout *saveTimer = tvp->timer;
Helmut Tschemernjak 97:3d5d489206aa 212 tvp->timer = NULL;
Helmut Tschemernjak 97:3d5d489206aa 213 Timeout::_irq_handler(saveTimer);
Helmut Tschemernjak 97:3d5d489206aa 214 }
Helmut Tschemernjak 97:3d5d489206aa 215 }
Helmut Tschemernjak 97:3d5d489206aa 216 /*
Helmut Tschemernjak 97:3d5d489206aa 217 * we need to restart the timer for remaining interrupts
Helmut Tschemernjak 97:3d5d489206aa 218 * Another reason is that we stopped this counter, in case there are
Helmut Tschemernjak 97:3d5d489206aa 219 * remaining counts, we need to re-schedule the counter.
Helmut Tschemernjak 97:3d5d489206aa 220 */
Helmut Tschemernjak 97:3d5d489206aa 221 Timeout::restart();
Helmut Tschemernjak 97:3d5d489206aa 222 }
Helmut Tschemernjak 97:3d5d489206aa 223
Helmut Tschemernjak 97:3d5d489206aa 224
Helmut Tschemernjak 97:3d5d489206aa 225 /* ----------------- ESP32 sleep() and deepsleep() code ----------------------*/
Helmut Tschemernjak 97:3d5d489206aa 226
Helmut Tschemernjak 97:3d5d489206aa 227 void sleep(void)
Helmut Tschemernjak 97:3d5d489206aa 228 {
Helmut Tschemernjak 97:3d5d489206aa 229 asm("waiti 0");
Helmut Tschemernjak 97:3d5d489206aa 230 }
Helmut Tschemernjak 97:3d5d489206aa 231
Helmut Tschemernjak 97:3d5d489206aa 232 /*
Helmut Tschemernjak 97:3d5d489206aa 233 * TODO
Helmut Tschemernjak 97:3d5d489206aa 234 * The ESP32 deepsleep can be enhanced to bring the ESP into low power mode.
Helmut Tschemernjak 97:3d5d489206aa 235 */
Helmut Tschemernjak 97:3d5d489206aa 236
Helmut Tschemernjak 97:3d5d489206aa 237 void deepsleep(void)
Helmut Tschemernjak 97:3d5d489206aa 238 {
Helmut Tschemernjak 101:50377edb21c6 239 // Light Sleep
Helmut Tschemernjak 97:3d5d489206aa 240 asm("waiti 0");
Helmut Tschemernjak 97:3d5d489206aa 241 }
Helmut Tschemernjak 97:3d5d489206aa 242
Helmut Tschemernjak 97:3d5d489206aa 243 #endif // ESp32 Timer, sleep, etc.
Helmut Tschemernjak 97:3d5d489206aa 244
Helmut Tschemernjak 97:3d5d489206aa 245 #endif // ARDUINO