An example project for the Heltec Turtle LoRa board (STM32L4 and SX1276 chips). The projects is only supported for the Nucleo-L432KC board platform in the mbed online and offline compiler environment. Visit www.radioshuttle.de (choose Turtle board) for instructions. Note that most source files and libraries are open source, however some files especially the RadioShuttle core protocol is copyrighted work. Check header for details.

Dependencies:   mbed BufferedSerial SX1276GenericLib OLED_SSD1306 HELIOS_Si7021 NVProperty RadioShuttle-STM32L4 USBDeviceHT

Committer:
Helmut Tschemernjak
Date:
Mon Jan 21 11:56:10 2019 +0100
Revision:
5:c6a960febe80
Parent:
1:56fdc660a26a
Child:
14:d9340be18c3d
Moved PendingInterrupts into utils
InitSerial should always set the RTC when needed.
Fix RX to GND to avoid floating pins

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Helmut64 0:3b6c2ce051a6 1 /*
Helmut Tschemernjak 1:56fdc660a26a 2 * Copyright (c) 2019 Helmut Tschemernjak
Helmut64 0:3b6c2ce051a6 3 * 30826 Garbsen (Hannover) Germany
Helmut64 0:3b6c2ce051a6 4 */
Helmut Tschemernjak 1:56fdc660a26a 5 #include "main.h"
Helmut Tschemernjak 5:c6a960febe80 6
Helmut Tschemernjak 5:c6a960febe80 7 volatile uint32_t PendingInterrupts; // global interrupt mask of received interrupts
Helmut Tschemernjak 5:c6a960febe80 8
Helmut64 0:3b6c2ce051a6 9 time_t cvt_date(char const *date, char const *time);
Helmut64 0:3b6c2ce051a6 10
Helmut64 0:3b6c2ce051a6 11 BufferedSerial *ser;
Helmut64 0:3b6c2ce051a6 12 #ifdef FEATURE_USBSERIAL
Helmut64 0:3b6c2ce051a6 13 USBSerialBuffered *usb;
Helmut64 0:3b6c2ce051a6 14 #endif
Helmut64 0:3b6c2ce051a6 15 bool _useDprintf;
Helmut64 0:3b6c2ce051a6 16
Helmut64 0:3b6c2ce051a6 17 void InitSerial(int timeout, DigitalOut *led)
Helmut64 0:3b6c2ce051a6 18 {
Helmut64 0:3b6c2ce051a6 19 _useDprintf = true;
Helmut64 0:3b6c2ce051a6 20 bool uartActive;
Helmut64 0:3b6c2ce051a6 21 {
Helmut64 0:3b6c2ce051a6 22 {
Helmut64 0:3b6c2ce051a6 23 // need to turn rx low to avoid floating signal
Helmut64 0:3b6c2ce051a6 24 DigitalOut rx(USBRX);
Helmut64 0:3b6c2ce051a6 25 rx = 0;
Helmut64 0:3b6c2ce051a6 26 }
Helmut64 0:3b6c2ce051a6 27 DigitalIn uartRX(USBRX);
Helmut64 0:3b6c2ce051a6 28 uartActive = uartRX.read();
Helmut64 0:3b6c2ce051a6 29 }
Helmut64 0:3b6c2ce051a6 30 #ifdef FEATURE_USBSERIAL
Helmut64 0:3b6c2ce051a6 31 if (!uartActive) {
Helmut64 0:3b6c2ce051a6 32 usb = new USBSerialBuffered();
Helmut64 0:3b6c2ce051a6 33 Timer t;
Helmut64 0:3b6c2ce051a6 34 t.start();
Helmut64 0:3b6c2ce051a6 35 while(!usb->connected()) {
Helmut64 0:3b6c2ce051a6 36 if (led)
Helmut64 0:3b6c2ce051a6 37 *led = !*led;
Helmut64 0:3b6c2ce051a6 38 wait_ms(100);
Helmut64 0:3b6c2ce051a6 39 if (timeout) {
Helmut Tschemernjak 5:c6a960febe80 40 if (t.read_ms() >= timeout) {
Helmut Tschemernjak 5:c6a960febe80 41 delete usb;
Helmut Tschemernjak 5:c6a960febe80 42 usb = NULL;
Helmut Tschemernjak 5:c6a960febe80 43 DigitalOut rx(USBRX);
Helmut Tschemernjak 5:c6a960febe80 44 rx = 0; // need to turn tx low to avoid floating signal
Helmut Tschemernjak 5:c6a960febe80 45 goto done;
Helmut Tschemernjak 5:c6a960febe80 46 }
Helmut64 0:3b6c2ce051a6 47 }
Helmut64 0:3b6c2ce051a6 48 }
Helmut Tschemernjak 5:c6a960febe80 49 goto done;
Helmut64 0:3b6c2ce051a6 50 } else {
Helmut64 0:3b6c2ce051a6 51 #else
Helmut64 0:3b6c2ce051a6 52 {
Helmut64 0:3b6c2ce051a6 53 #endif
Helmut64 0:3b6c2ce051a6 54 ser = new BufferedSerial(USBTX, USBRX);
Helmut64 0:3b6c2ce051a6 55 ser->baud(230400);
Helmut64 0:3b6c2ce051a6 56 ser->format(8);
Helmut64 0:3b6c2ce051a6 57 }
Helmut Tschemernjak 5:c6a960febe80 58 done:
Helmut64 0:3b6c2ce051a6 59 time_t t = cvt_date(__DATE__, __TIME__);
Helmut64 0:3b6c2ce051a6 60 if (t > time(NULL)) {
Helmut64 0:3b6c2ce051a6 61 set_time(t);
Helmut64 0:3b6c2ce051a6 62 }
Helmut64 0:3b6c2ce051a6 63 }
Helmut64 0:3b6c2ce051a6 64
Helmut64 0:3b6c2ce051a6 65 void printTimeStamp()
Helmut64 0:3b6c2ce051a6 66 {
Helmut64 0:3b6c2ce051a6 67 static LowPowerTimer *timer;
Helmut64 0:3b6c2ce051a6 68 if (!timer) {
Helmut64 0:3b6c2ce051a6 69 timer = new LowPowerTimer();
Helmut64 0:3b6c2ce051a6 70 timer->start();
Helmut64 0:3b6c2ce051a6 71 }
Helmut64 0:3b6c2ce051a6 72 time_t seconds = time(NULL);
Helmut64 0:3b6c2ce051a6 73 struct tm *tm = localtime(&seconds);
Helmut64 0:3b6c2ce051a6 74 int usecs = timer->read_us();
Helmut64 0:3b6c2ce051a6 75 if (usecs < 0) {
Helmut64 0:3b6c2ce051a6 76 usecs = 0;
Helmut64 0:3b6c2ce051a6 77 timer->stop();
Helmut64 0:3b6c2ce051a6 78 timer->reset();
Helmut64 0:3b6c2ce051a6 79 timer->start();
Helmut64 0:3b6c2ce051a6 80 }
Helmut64 0:3b6c2ce051a6 81 int msecs = usecs % 1000000;
Helmut64 0:3b6c2ce051a6 82
Helmut64 0:3b6c2ce051a6 83 rprintf("%02d:%02d:%02d.%06d ", tm->tm_hour, tm->tm_min, tm->tm_sec, msecs);
Helmut64 0:3b6c2ce051a6 84 }
Helmut64 0:3b6c2ce051a6 85
Helmut64 0:3b6c2ce051a6 86 void dprintf(const char *format, ...)
Helmut64 0:3b6c2ce051a6 87 {
Helmut64 0:3b6c2ce051a6 88 std::va_list arg;
Helmut64 0:3b6c2ce051a6 89
Helmut64 0:3b6c2ce051a6 90 va_start(arg, format);
Helmut64 0:3b6c2ce051a6 91 VAprintf(true, true, _useDprintf, format, arg);
Helmut64 0:3b6c2ce051a6 92 va_end(arg);
Helmut64 0:3b6c2ce051a6 93 }
Helmut64 0:3b6c2ce051a6 94
Helmut64 0:3b6c2ce051a6 95 void rprintf(const char *format, ...)
Helmut64 0:3b6c2ce051a6 96 {
Helmut64 0:3b6c2ce051a6 97 std::va_list arg;
Helmut64 0:3b6c2ce051a6 98
Helmut64 0:3b6c2ce051a6 99 va_start(arg, format);
Helmut64 0:3b6c2ce051a6 100 VAprintf(false, false, _useDprintf, format, arg);
Helmut64 0:3b6c2ce051a6 101 va_end(arg);
Helmut64 0:3b6c2ce051a6 102 }
Helmut64 0:3b6c2ce051a6 103
Helmut64 0:3b6c2ce051a6 104 void VAprintf(bool timstamp, bool newline, bool printEnabled, const char *format, va_list arg)
Helmut64 0:3b6c2ce051a6 105 {
Helmut64 0:3b6c2ce051a6 106 if (!printEnabled)
Helmut64 0:3b6c2ce051a6 107 return;
Helmut64 0:3b6c2ce051a6 108
Helmut64 0:3b6c2ce051a6 109 if (timstamp)
Helmut64 0:3b6c2ce051a6 110 printTimeStamp();
Helmut64 0:3b6c2ce051a6 111 #ifdef FEATURE_USBSERIAL
Helmut64 0:3b6c2ce051a6 112 if (usb) {
Helmut64 0:3b6c2ce051a6 113 usb->vprintf_irqsafe(format, arg);
Helmut64 0:3b6c2ce051a6 114 if (newline)
Helmut64 0:3b6c2ce051a6 115 usb->printf_irqsafe("\r\n");
Helmut64 0:3b6c2ce051a6 116 #else
Helmut64 0:3b6c2ce051a6 117 if (0) {
Helmut64 0:3b6c2ce051a6 118 #endif
Helmut64 0:3b6c2ce051a6 119 } else if (ser) {
Helmut64 0:3b6c2ce051a6 120 // serial jas
Helmut64 0:3b6c2ce051a6 121 int r = 0;
Helmut64 0:3b6c2ce051a6 122 r = vsnprintf(NULL, 0, format, arg);
Helmut64 0:3b6c2ce051a6 123 if (r < 82) {
Helmut64 0:3b6c2ce051a6 124 char buffer[82+1];
Helmut64 0:3b6c2ce051a6 125
Helmut64 0:3b6c2ce051a6 126 vsnprintf(buffer, sizeof(buffer), format, arg);
Helmut64 0:3b6c2ce051a6 127 r = ser->write(buffer, r);
Helmut64 0:3b6c2ce051a6 128 } else {
Helmut64 0:3b6c2ce051a6 129 char *buffer = new char[r+1];
Helmut64 0:3b6c2ce051a6 130 if (buffer) {
Helmut64 0:3b6c2ce051a6 131 vsnprintf(buffer, r+1, format, arg);
Helmut64 0:3b6c2ce051a6 132 r = ser->write(buffer, r);
Helmut64 0:3b6c2ce051a6 133 delete[] buffer;
Helmut64 0:3b6c2ce051a6 134 } else {
Helmut64 0:3b6c2ce051a6 135 error("%s %d cannot alloc memory (%d bytes)!\r\n", __FILE__, __LINE__, r+1);
Helmut64 0:3b6c2ce051a6 136 r = 0;
Helmut64 0:3b6c2ce051a6 137 }
Helmut64 0:3b6c2ce051a6 138 }
Helmut64 0:3b6c2ce051a6 139 if (newline)
Helmut64 0:3b6c2ce051a6 140 ser->write("\r\n", 2);
Helmut64 0:3b6c2ce051a6 141 }
Helmut64 0:3b6c2ce051a6 142 }
Helmut64 0:3b6c2ce051a6 143
Helmut64 0:3b6c2ce051a6 144
Helmut64 0:3b6c2ce051a6 145 void dump(const char *title, const void *data, int len, bool dwords)
Helmut64 0:3b6c2ce051a6 146 {
Helmut64 0:3b6c2ce051a6 147 dprintf("dump(\"%s\", 0x%x, %d bytes)", title, data, len);
Helmut64 0:3b6c2ce051a6 148
Helmut64 0:3b6c2ce051a6 149 int i, j, cnt;
Helmut64 0:3b6c2ce051a6 150 unsigned char *u;
Helmut64 0:3b6c2ce051a6 151 const int width = 16;
Helmut64 0:3b6c2ce051a6 152 const int seppos = 7;
Helmut64 0:3b6c2ce051a6 153
Helmut64 0:3b6c2ce051a6 154 cnt = 0;
Helmut64 0:3b6c2ce051a6 155 u = (unsigned char *)data;
Helmut64 0:3b6c2ce051a6 156 while (len > 0) {
Helmut64 0:3b6c2ce051a6 157 rprintf("%08x: ", (unsigned int)data + cnt);
Helmut64 0:3b6c2ce051a6 158 if (dwords) {
Helmut64 0:3b6c2ce051a6 159 unsigned int *ip = ( unsigned int *)u;
Helmut64 0:3b6c2ce051a6 160 rprintf(" 0x%08x\r\n", *ip);
Helmut64 0:3b6c2ce051a6 161 u+= 4;
Helmut64 0:3b6c2ce051a6 162 len -= 4;
Helmut64 0:3b6c2ce051a6 163 cnt += 4;
Helmut64 0:3b6c2ce051a6 164 continue;
Helmut64 0:3b6c2ce051a6 165 }
Helmut64 0:3b6c2ce051a6 166 cnt += width;
Helmut64 0:3b6c2ce051a6 167 j = len < width ? len : width;
Helmut64 0:3b6c2ce051a6 168 for (i = 0; i < j; i++) {
Helmut64 0:3b6c2ce051a6 169 rprintf("%2.2x ", *(u + i));
Helmut64 0:3b6c2ce051a6 170 if (i == seppos)
Helmut64 0:3b6c2ce051a6 171 rprintf(" ");
Helmut64 0:3b6c2ce051a6 172 }
Helmut64 0:3b6c2ce051a6 173 rprintf(" ");
Helmut64 0:3b6c2ce051a6 174 if (j < width) {
Helmut64 0:3b6c2ce051a6 175 i = width - j;
Helmut64 0:3b6c2ce051a6 176 if (i > seppos + 1)
Helmut64 0:3b6c2ce051a6 177 rprintf(" ");
Helmut64 0:3b6c2ce051a6 178 while (i--) {
Helmut64 0:3b6c2ce051a6 179 rprintf("%s", " ");
Helmut64 0:3b6c2ce051a6 180 }
Helmut64 0:3b6c2ce051a6 181 }
Helmut64 0:3b6c2ce051a6 182 for (i = 0; i < j; i++) {
Helmut64 0:3b6c2ce051a6 183 int c = *(u + i);
Helmut64 0:3b6c2ce051a6 184 if (c >= ' ' && c <= '~')
Helmut64 0:3b6c2ce051a6 185 rprintf("%c", c);
Helmut64 0:3b6c2ce051a6 186 else
Helmut64 0:3b6c2ce051a6 187 rprintf(".");
Helmut64 0:3b6c2ce051a6 188 if (i == seppos)
Helmut64 0:3b6c2ce051a6 189 rprintf(" ");
Helmut64 0:3b6c2ce051a6 190 }
Helmut64 0:3b6c2ce051a6 191 len -= width;
Helmut64 0:3b6c2ce051a6 192 u += width;
Helmut64 0:3b6c2ce051a6 193 rprintf("\r\n");
Helmut64 0:3b6c2ce051a6 194 }
Helmut64 0:3b6c2ce051a6 195 rprintf("--\r\n");
Helmut64 0:3b6c2ce051a6 196 }
Helmut64 0:3b6c2ce051a6 197
Helmut64 0:3b6c2ce051a6 198 /*
Helmut64 0:3b6c2ce051a6 199 * Convert compile time to system time
Helmut64 0:3b6c2ce051a6 200 */
Helmut64 0:3b6c2ce051a6 201 time_t
Helmut64 0:3b6c2ce051a6 202 cvt_date(char const *date, char const *time)
Helmut64 0:3b6c2ce051a6 203 {
Helmut64 0:3b6c2ce051a6 204 char s_month[5];
Helmut64 0:3b6c2ce051a6 205 int year;
Helmut64 0:3b6c2ce051a6 206 struct tm t;
Helmut64 0:3b6c2ce051a6 207 static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
Helmut64 0:3b6c2ce051a6 208 sscanf(date, "%s %d %d", s_month, &t.tm_mday, &year);
Helmut64 0:3b6c2ce051a6 209 sscanf(time, "%2d %*c %2d %*c %2d", &t.tm_hour, &t.tm_min, &t.tm_sec);
Helmut64 0:3b6c2ce051a6 210 // Find where is s_month in month_names. Deduce month value.
Helmut64 0:3b6c2ce051a6 211 t.tm_mon = (strstr(month_names, s_month) - month_names) / 3;
Helmut64 0:3b6c2ce051a6 212 t.tm_year = year - 1900;
Helmut64 0:3b6c2ce051a6 213 return (int)mktime(&t);
Helmut64 0:3b6c2ce051a6 214 }
Helmut Tschemernjak 1:56fdc660a26a 215
Helmut Tschemernjak 1:56fdc660a26a 216
Helmut Tschemernjak 1:56fdc660a26a 217
Helmut Tschemernjak 1:56fdc660a26a 218 void InterrruptMSG(enum InterrruptDevice irqid) {
Helmut Tschemernjak 1:56fdc660a26a 219 help_atomic_or_relaxed(&PendingInterrupts, irqid);
Helmut Tschemernjak 1:56fdc660a26a 220 }
Helmut Tschemernjak 1:56fdc660a26a 221
Helmut Tschemernjak 1:56fdc660a26a 222
Helmut Tschemernjak 1:56fdc660a26a 223 uint32_t readclrPendingInterrupts() {
Helmut Tschemernjak 1:56fdc660a26a 224 return help_atomic_readclr_relaxed(&PendingInterrupts);
Helmut Tschemernjak 1:56fdc660a26a 225 }
Helmut Tschemernjak 1:56fdc660a26a 226
Helmut Tschemernjak 1:56fdc660a26a 227 uint32_t readPendingInterrupts() {
Helmut Tschemernjak 1:56fdc660a26a 228 return help_atomic_load_relaxed(&PendingInterrupts);
Helmut Tschemernjak 1:56fdc660a26a 229 }
Helmut Tschemernjak 1:56fdc660a26a 230
Helmut Tschemernjak 1:56fdc660a26a 231 const char *
Helmut Tschemernjak 1:56fdc660a26a 232 BatterySource(void)
Helmut Tschemernjak 1:56fdc660a26a 233 {
Helmut Tschemernjak 1:56fdc660a26a 234 const char *pwrSource = "Battery";
Helmut Tschemernjak 1:56fdc660a26a 235 #ifdef BATPOWER_EN
Helmut Tschemernjak 1:56fdc660a26a 236 {
Helmut Tschemernjak 1:56fdc660a26a 237 DigitalIn pwr(BATPOWER_EN);
Helmut Tschemernjak 1:56fdc660a26a 238 if (pwr == BATPOWER_EXT)
Helmut Tschemernjak 1:56fdc660a26a 239 pwrSource = "USB";
Helmut Tschemernjak 1:56fdc660a26a 240 }
Helmut Tschemernjak 1:56fdc660a26a 241 #endif
Helmut Tschemernjak 1:56fdc660a26a 242 return pwrSource;
Helmut Tschemernjak 1:56fdc660a26a 243 }
Helmut Tschemernjak 1:56fdc660a26a 244