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:
Sun Feb 03 13:02:44 2019 +0100
Revision:
16:c12c85fdfa60
Parent:
14:d9340be18c3d
Child:
22:9cca40fcb25e
Added line editor backspace support

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
Helmut Tschemernjak 14:d9340be18c3d 144 char *ConsoleReadline(char *buf, int buflen, bool echo)
Helmut Tschemernjak 14:d9340be18c3d 145 {
Helmut Tschemernjak 14:d9340be18c3d 146 int count = 0;
Helmut Tschemernjak 14:d9340be18c3d 147 memset(buf, 0, buflen);
Helmut Tschemernjak 14:d9340be18c3d 148
Helmut Tschemernjak 14:d9340be18c3d 149 if (usb ) {
Helmut Tschemernjak 14:d9340be18c3d 150 usb->flush();
Helmut Tschemernjak 14:d9340be18c3d 151 while(usb->readable())
Helmut Tschemernjak 14:d9340be18c3d 152 usb->getc(); // flush old chars
Helmut Tschemernjak 14:d9340be18c3d 153
Helmut Tschemernjak 14:d9340be18c3d 154 while(true) {
Helmut Tschemernjak 14:d9340be18c3d 155 if (usb->readable()) {
Helmut Tschemernjak 14:d9340be18c3d 156 int c = usb->getc();
Helmut Tschemernjak 14:d9340be18c3d 157 if (c == 0 || c == -1 || c == '\r' || c == '\n' || c == 3 || c == 4)
Helmut Tschemernjak 14:d9340be18c3d 158 break;
Helmut Tschemernjak 16:c12c85fdfa60 159 if (c == '\b' || c == 0x7f) { // backspace
Helmut Tschemernjak 16:c12c85fdfa60 160 if (count < 1)
Helmut Tschemernjak 16:c12c85fdfa60 161 continue;
Helmut Tschemernjak 16:c12c85fdfa60 162 buf[--count] = 0;
Helmut Tschemernjak 16:c12c85fdfa60 163 if (echo)
Helmut Tschemernjak 16:c12c85fdfa60 164 rprintf("\b \b");
Helmut Tschemernjak 16:c12c85fdfa60 165 usb->flush();
Helmut Tschemernjak 16:c12c85fdfa60 166 continue;
Helmut Tschemernjak 16:c12c85fdfa60 167 }
Helmut Tschemernjak 14:d9340be18c3d 168 if (echo) {
Helmut Tschemernjak 14:d9340be18c3d 169 rprintf("%c", c);
Helmut Tschemernjak 14:d9340be18c3d 170 usb->flush();
Helmut Tschemernjak 14:d9340be18c3d 171 }
Helmut Tschemernjak 14:d9340be18c3d 172
Helmut Tschemernjak 14:d9340be18c3d 173 buf[count] = c;
Helmut Tschemernjak 14:d9340be18c3d 174 if (count++ >= buflen-2)
Helmut Tschemernjak 14:d9340be18c3d 175 break;
Helmut Tschemernjak 14:d9340be18c3d 176 // dprintf("Got char: '%c'(%d)", c, c);
Helmut Tschemernjak 14:d9340be18c3d 177 }
Helmut Tschemernjak 14:d9340be18c3d 178 }
Helmut Tschemernjak 14:d9340be18c3d 179 }
Helmut Tschemernjak 14:d9340be18c3d 180 if (ser) {
Helmut Tschemernjak 14:d9340be18c3d 181 while(ser->readable())
Helmut Tschemernjak 14:d9340be18c3d 182 ser->getc(); // flush old chars
Helmut Tschemernjak 14:d9340be18c3d 183
Helmut Tschemernjak 14:d9340be18c3d 184 while(true) {
Helmut Tschemernjak 14:d9340be18c3d 185 if (ser->readable()) {
Helmut Tschemernjak 14:d9340be18c3d 186 int c = ser->getc();
Helmut Tschemernjak 14:d9340be18c3d 187 if (c == 0 || c == -1 || c == '\r' || c == '\n' || c == 3 || c == 4)
Helmut Tschemernjak 14:d9340be18c3d 188 break;
Helmut Tschemernjak 16:c12c85fdfa60 189 if (c == '\b' || c == 0x7f) { // backspace
Helmut Tschemernjak 16:c12c85fdfa60 190 if (count < 1)
Helmut Tschemernjak 16:c12c85fdfa60 191 continue;
Helmut Tschemernjak 16:c12c85fdfa60 192 buf[--count] = 0;
Helmut Tschemernjak 16:c12c85fdfa60 193 if (echo)
Helmut Tschemernjak 16:c12c85fdfa60 194 rprintf("\b \b");
Helmut Tschemernjak 16:c12c85fdfa60 195 continue;
Helmut Tschemernjak 16:c12c85fdfa60 196 }
Helmut Tschemernjak 14:d9340be18c3d 197 if (echo)
Helmut Tschemernjak 14:d9340be18c3d 198 rprintf("%c", c);
Helmut Tschemernjak 14:d9340be18c3d 199 buf[count] = c;
Helmut Tschemernjak 14:d9340be18c3d 200 if (count++ >= buflen-2)
Helmut Tschemernjak 14:d9340be18c3d 201 break;
Helmut Tschemernjak 14:d9340be18c3d 202 // dprintf("Got char: '%c'(%d)", c, c);
Helmut Tschemernjak 14:d9340be18c3d 203 }
Helmut Tschemernjak 14:d9340be18c3d 204 }
Helmut Tschemernjak 14:d9340be18c3d 205 }
Helmut Tschemernjak 14:d9340be18c3d 206 if (echo)
Helmut Tschemernjak 14:d9340be18c3d 207 rprintf("\r\n");
Helmut Tschemernjak 14:d9340be18c3d 208 if (count)
Helmut Tschemernjak 14:d9340be18c3d 209 return buf;
Helmut Tschemernjak 14:d9340be18c3d 210 return NULL;
Helmut Tschemernjak 14:d9340be18c3d 211 }
Helmut Tschemernjak 14:d9340be18c3d 212
Helmut64 0:3b6c2ce051a6 213
Helmut64 0:3b6c2ce051a6 214 void dump(const char *title, const void *data, int len, bool dwords)
Helmut64 0:3b6c2ce051a6 215 {
Helmut Tschemernjak 14:d9340be18c3d 216 dprintf("dump(\"%s\", 0x%x, %d bytes)", title, (unsigned int)data, len);
Helmut64 0:3b6c2ce051a6 217
Helmut64 0:3b6c2ce051a6 218 int i, j, cnt;
Helmut64 0:3b6c2ce051a6 219 unsigned char *u;
Helmut64 0:3b6c2ce051a6 220 const int width = 16;
Helmut64 0:3b6c2ce051a6 221 const int seppos = 7;
Helmut64 0:3b6c2ce051a6 222
Helmut64 0:3b6c2ce051a6 223 cnt = 0;
Helmut64 0:3b6c2ce051a6 224 u = (unsigned char *)data;
Helmut64 0:3b6c2ce051a6 225 while (len > 0) {
Helmut64 0:3b6c2ce051a6 226 rprintf("%08x: ", (unsigned int)data + cnt);
Helmut64 0:3b6c2ce051a6 227 if (dwords) {
Helmut64 0:3b6c2ce051a6 228 unsigned int *ip = ( unsigned int *)u;
Helmut64 0:3b6c2ce051a6 229 rprintf(" 0x%08x\r\n", *ip);
Helmut64 0:3b6c2ce051a6 230 u+= 4;
Helmut64 0:3b6c2ce051a6 231 len -= 4;
Helmut64 0:3b6c2ce051a6 232 cnt += 4;
Helmut64 0:3b6c2ce051a6 233 continue;
Helmut64 0:3b6c2ce051a6 234 }
Helmut64 0:3b6c2ce051a6 235 cnt += width;
Helmut64 0:3b6c2ce051a6 236 j = len < width ? len : width;
Helmut64 0:3b6c2ce051a6 237 for (i = 0; i < j; i++) {
Helmut64 0:3b6c2ce051a6 238 rprintf("%2.2x ", *(u + i));
Helmut64 0:3b6c2ce051a6 239 if (i == seppos)
Helmut64 0:3b6c2ce051a6 240 rprintf(" ");
Helmut64 0:3b6c2ce051a6 241 }
Helmut64 0:3b6c2ce051a6 242 rprintf(" ");
Helmut64 0:3b6c2ce051a6 243 if (j < width) {
Helmut64 0:3b6c2ce051a6 244 i = width - j;
Helmut64 0:3b6c2ce051a6 245 if (i > seppos + 1)
Helmut64 0:3b6c2ce051a6 246 rprintf(" ");
Helmut64 0:3b6c2ce051a6 247 while (i--) {
Helmut64 0:3b6c2ce051a6 248 rprintf("%s", " ");
Helmut64 0:3b6c2ce051a6 249 }
Helmut64 0:3b6c2ce051a6 250 }
Helmut64 0:3b6c2ce051a6 251 for (i = 0; i < j; i++) {
Helmut64 0:3b6c2ce051a6 252 int c = *(u + i);
Helmut64 0:3b6c2ce051a6 253 if (c >= ' ' && c <= '~')
Helmut64 0:3b6c2ce051a6 254 rprintf("%c", c);
Helmut64 0:3b6c2ce051a6 255 else
Helmut64 0:3b6c2ce051a6 256 rprintf(".");
Helmut64 0:3b6c2ce051a6 257 if (i == seppos)
Helmut64 0:3b6c2ce051a6 258 rprintf(" ");
Helmut64 0:3b6c2ce051a6 259 }
Helmut64 0:3b6c2ce051a6 260 len -= width;
Helmut64 0:3b6c2ce051a6 261 u += width;
Helmut64 0:3b6c2ce051a6 262 rprintf("\r\n");
Helmut64 0:3b6c2ce051a6 263 }
Helmut64 0:3b6c2ce051a6 264 rprintf("--\r\n");
Helmut64 0:3b6c2ce051a6 265 }
Helmut64 0:3b6c2ce051a6 266
Helmut64 0:3b6c2ce051a6 267 /*
Helmut64 0:3b6c2ce051a6 268 * Convert compile time to system time
Helmut64 0:3b6c2ce051a6 269 */
Helmut64 0:3b6c2ce051a6 270 time_t
Helmut64 0:3b6c2ce051a6 271 cvt_date(char const *date, char const *time)
Helmut64 0:3b6c2ce051a6 272 {
Helmut64 0:3b6c2ce051a6 273 char s_month[5];
Helmut64 0:3b6c2ce051a6 274 int year;
Helmut64 0:3b6c2ce051a6 275 struct tm t;
Helmut64 0:3b6c2ce051a6 276 static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
Helmut64 0:3b6c2ce051a6 277 sscanf(date, "%s %d %d", s_month, &t.tm_mday, &year);
Helmut64 0:3b6c2ce051a6 278 sscanf(time, "%2d %*c %2d %*c %2d", &t.tm_hour, &t.tm_min, &t.tm_sec);
Helmut64 0:3b6c2ce051a6 279 // Find where is s_month in month_names. Deduce month value.
Helmut64 0:3b6c2ce051a6 280 t.tm_mon = (strstr(month_names, s_month) - month_names) / 3;
Helmut64 0:3b6c2ce051a6 281 t.tm_year = year - 1900;
Helmut64 0:3b6c2ce051a6 282 return (int)mktime(&t);
Helmut64 0:3b6c2ce051a6 283 }
Helmut Tschemernjak 1:56fdc660a26a 284
Helmut Tschemernjak 1:56fdc660a26a 285
Helmut Tschemernjak 1:56fdc660a26a 286
Helmut Tschemernjak 1:56fdc660a26a 287 void InterrruptMSG(enum InterrruptDevice irqid) {
Helmut Tschemernjak 1:56fdc660a26a 288 help_atomic_or_relaxed(&PendingInterrupts, irqid);
Helmut Tschemernjak 1:56fdc660a26a 289 }
Helmut Tschemernjak 1:56fdc660a26a 290
Helmut Tschemernjak 1:56fdc660a26a 291
Helmut Tschemernjak 1:56fdc660a26a 292 uint32_t readclrPendingInterrupts() {
Helmut Tschemernjak 1:56fdc660a26a 293 return help_atomic_readclr_relaxed(&PendingInterrupts);
Helmut Tschemernjak 1:56fdc660a26a 294 }
Helmut Tschemernjak 1:56fdc660a26a 295
Helmut Tschemernjak 1:56fdc660a26a 296 uint32_t readPendingInterrupts() {
Helmut Tschemernjak 1:56fdc660a26a 297 return help_atomic_load_relaxed(&PendingInterrupts);
Helmut Tschemernjak 1:56fdc660a26a 298 }
Helmut Tschemernjak 1:56fdc660a26a 299
Helmut Tschemernjak 1:56fdc660a26a 300 const char *
Helmut Tschemernjak 1:56fdc660a26a 301 BatterySource(void)
Helmut Tschemernjak 1:56fdc660a26a 302 {
Helmut Tschemernjak 1:56fdc660a26a 303 const char *pwrSource = "Battery";
Helmut Tschemernjak 1:56fdc660a26a 304 #ifdef BATPOWER_EN
Helmut Tschemernjak 1:56fdc660a26a 305 {
Helmut Tschemernjak 1:56fdc660a26a 306 DigitalIn pwr(BATPOWER_EN);
Helmut Tschemernjak 1:56fdc660a26a 307 if (pwr == BATPOWER_EXT)
Helmut Tschemernjak 1:56fdc660a26a 308 pwrSource = "USB";
Helmut Tschemernjak 1:56fdc660a26a 309 }
Helmut Tschemernjak 1:56fdc660a26a 310 #endif
Helmut Tschemernjak 1:56fdc660a26a 311 return pwrSource;
Helmut Tschemernjak 1:56fdc660a26a 312 }
Helmut Tschemernjak 1:56fdc660a26a 313