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

Revision:
37:77fa81e4ad79
Parent:
33:617765dcce6c
Child:
38:1f3792d6f9ec
--- a/utils.cpp	Wed Feb 13 14:08:15 2019 +0100
+++ b/utils.cpp	Wed Feb 13 14:10:17 2019 +0100
@@ -3,11 +3,17 @@
  * 30826 Garbsen (Hannover) Germany
  */
 #include "main.h"
+#include "GenericPingPong.h"
+#ifdef TOOLCHAIN_GCC
+#include <malloc.h>
+#endif
 
 volatile uint32_t PendingInterrupts;	// global interrupt mask of received interrupts
 
 time_t cvt_date(char const *date, char const *time);
 
+static float GetBrownOutVolt(void);
+
 BufferedSerial *ser;
 #ifdef FEATURE_USBSERIAL
 USBSerialBuffered *usb;
@@ -55,6 +61,36 @@
     }
 }
 
+void RunStartup(void)
+{
+	rprintf("\r\n");
+    int mbedversion = 9999;
+#ifdef MBED_LIBRARY_VERSION // not available in mbed head compiles
+    mbedversion = MBED_LIBRARY_VERSION;
+#endif
+    dprintf("Turtle: %d.%d (%s %s mbed: v%d)", MAJOR_VERSION, MINOR_VERSION, __DATE__, __TIME__, mbedversion);
+
+    dprintf("SysClock: %u Hz.", (unsigned int)SystemCoreClock);
+#ifdef __ARMCC_VERSION
+    dprintf("ARM Compiler Version: 0x%x", __ARMCC_VERSION);
+#elif __GNUC__
+    dprintf("GCC Compiler Version: %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+#endif
+	
+	const char *errstr;
+	if (__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET)
+		errstr = "RESET OCCURRED";
+	else
+	 	errstr = "initalized";
+	
+    dprintf("Brown Out Reset %s (%1.1f V)", errstr, GetBrownOutVolt());
+    dprintf("Voltage: %.2f (%s powered)", BatteryVoltage(), BatterySource());
+
+	dprintf("InitDefaults Done");
+	MemoryAvailable(true);
+	
+    __HAL_RCC_CLEAR_RESET_FLAGS();
+}
 void printTimeStamp()
 {
     static LowPowerTimer *timer;
@@ -323,9 +359,142 @@
 }
 
 
+float
+GetBrownOutVolt(void)
+{
+	float borVolt;
+		unsigned int *FlashOptionRegister = (unsigned int *)0x1FFF7800;
+		
+		int val = *FlashOptionRegister >> 8 & 0x7; // masking out the BOR bits 9-11
+		switch(val) {
+			case 0:
+				return borVolt = 1.7;
+			case 1:
+				return borVolt =  2.0;
+			case 2:
+				return borVolt =  2.2;
+			case 3:
+				return borVolt = 2.5;
+			case 4:
+				return borVolt = 2.8;
+			default:
+				return borVolt = 999;
+		}
+}
+
 void MCUReset(void)
 {
     #define AIRCR_VECTKEY_MASK    0x05FA0000
     SCB->AIRCR = AIRCR_VECTKEY_MASK | 0x04; // NVIC_GenerateSystemReset();
 }
 
+size_t
+MemoryAvailable(bool print)
+{
+    size_t counter;
+#ifdef TOOLCHAIN_GCC
+    struct mallinfo mi = mallinfo();
+    extern char end[];
+    extern char _estack[];
+    counter = (_estack - end) - mi.uordblks;
+    if (print)
+        dprintf("MemoryAvailable: %d kB (%d bytes)", counter/1024, counter);
+    return counter;
+#else
+    struct elem *head, *current, *nextone;
+    current = head = (struct elem*) malloc(sizeof(struct elem));
+    if (head == NULL)
+        return 0;      /*No memory available.*/
+    counter = 0;
+   // __disable_irq();
+    do {
+        counter++;
+        current->next = (struct elem*) malloc(sizeof(struct elem));
+        current = current->next;
+    } while (current != NULL);
+    /* Now counter holds the number of type elem
+       structures we were able to allocate. We
+       must free them all before returning. */
+    current = head;
+    do {
+        nextone = current->next;
+        free(current);
+        current = nextone;
+    } while (nextone != NULL);
+   // __enable_irq();
+
+    if (print)
+        dprintf("MemoryAvailable: %d kB (%d bytes)", (counter*FREEMEM_CELL)/1024, counter*FREEMEM_CELL);
+    return counter*FREEMEM_CELL;
+#endif
+}
+
+
+static const char *cmds = \
+	"\r\nThe following commands are available:\r\n\r\n" \
+	" p -- Property Editor\r\n" \
+	" t -- LoRa PingPong Test\r\n" \
+	" d -- Hexdump of memory address [offset count]\r\n"
+	" r -- Reset\r\n" \
+	" c -- Continue with RadioShuttle\r\n" \
+	"\r\n" \
+	"waiting 10 secs ...\r\n" \
+	"\r\n";
+
+void RunCommands(int timeout_ms) {
+	bool cmdLoop = true;
+	while(cmdLoop) {
+		char buf[32];
+
+		rprintf(cmds);
+		rprintf("Turtle$ ");
+		if (ConsoleReadline(buf, sizeof(buf), true, timeout_ms) == NULL) {
+			cmdLoop = false;
+			break;
+		}
+		switch(buf[0]) {
+			case 'p':
+			case 'P':
+#ifdef FEATURE_NVPROPERTYEDITOR
+				NVPropertyEditor();
+#endif
+			break;
+			case 't':
+			case 'T':
+#ifdef FEATURE_LORA_PING_PONG
+    			SX1276PingPong();	// basic LoRa raw ping/pong without RadioShuttle
+#endif
+				break;
+			case 'r':
+			case 'R':
+				MCUReset();
+				break;
+			case 'd':
+			case 'D':
+				{
+					char *addr = strchr(buf, ' ');
+					if (addr) {
+						*addr++ = 0;
+						char *length = strchr(addr, ' ');
+						if (length) {
+							*length++ = 0;
+						}
+						unsigned long address = strtoll(addr, NULL, 0);
+						unsigned long cnt = 32;
+						if (length)
+							cnt = strtoll(length, NULL, 0);
+						dump("Hexdump", (void *)address, cnt);
+					}
+				}
+				break;
+			case 'c':
+			case 'C':
+				cmdLoop = false;
+				break;
+			default:
+				break;
+		}
+	}
+	rprintf("\r\n");
+
+}