1st working program

Dependencies:   mbed-os_TYBLE16 BME280_SPI RX8025NB nRF51_Vdd MB85RSxx_SPI

see /users/kenjiArai/notebook/tyble16-module-as-mbed-os-5-board-mbedlization/

Revision:
6:a3238e93f694
Child:
7:cedbf234a089
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dt_logger.cpp	Wed Dec 18 09:24:58 2019 +0000
@@ -0,0 +1,625 @@
+/*
+ * Mbed Application program / TYBLE-16 Data logger
+ *
+ * Copyright (c) 2019 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  https://os.mbed.com/users/kenjiArai/
+ *      Created:    December  14th, 2019
+ *      Revised:    December  17th, 2019
+ */
+
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "dt_logger.h"
+
+//  Object ---------------------------------------------------------------------
+extern Serial pc;
+
+//  Definition -----------------------------------------------------------------
+#define BAUD(x)         		pc.baud(x)
+#define GETC(x)         		pc.getc(x)
+#define PUTC(x)					pc.putc(x)
+#define PRINTF(...)     		pc.printf(__VA_ARGS__)
+#define READABLE(x)     		pc.readable(x)
+
+// FRAM
+#define FRAM_TOP					0x0
+
+//  RAM ------------------------------------------------------------------------
+char linebuf[64];
+int buf_size = sizeof(linebuf);
+
+// 	for FRAM control
+int16_t read_pointer;
+
+typedef struct {
+    uint16_t    head;
+    uint16_t    tail;
+} ring_t;
+
+union _inf{
+	uint8_t buf_pointer[PTR_SIZE];
+	ring_t log_inf;
+}inf;
+
+typedef struct {
+	uint32_t	time;	// 4byte
+	uint16_t	vcc;	// 2
+	uint16_t	baro;	// 2
+	int16_t		temp;	// 2
+	uint16_t	humi;	// 2
+	uint32_t	dmy;	// 4
+}one_log;		// 16 bytes total
+
+union _one{
+	uint8_t bf[PKT_SIZE];
+	one_log lg;
+}one;
+
+extern time_t log_sec;
+extern float vcc_voltage;
+extern float barometer;
+extern float temperature;
+extern float humidity;
+
+//  ROM / Constant data --------------------------------------------------------
+const char *const mon_msg =
+					 "Monitor for TYBLE16 Data logger, created on " __DATE__"";
+//                            $,2019/12/21,12:43:16,3.29,1004.5,+29.3,45.8,*
+const char *const log_head = "$,YYYY/MM/DD,HH:MM:SS,Vcc ,Press , Temp,Humi,*";
+const char *const msg_emty = "Data empty";
+const char *const msg_end  = "\r\nreach to end";
+
+//  Function prototypes --------------------------------------------------------
+extern time_t w_check_rtc_time(RX8025 &ex_rtc);
+
+static void data_logger(MB85RSxx_SPI &fram, char *ptr);
+static void msg_hlp (void);
+static void time_enter_mode(RX8025 &ex_rtc, char *ptr);
+static void chk_and_set_time(RX8025 &ex_rtc, char *ptr);
+static int xatoi (char **str, unsigned long *res);
+static void get_line(char *buff, int len);
+static void put_rn(void);
+static void put_r(void);
+static void put_lin(void);
+static void put_spc(uint8_t n);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+// ---------- Program starts here! ---------------------------------------------
+int mon(RX8025 &ex_rtc, MB85RSxx_SPI &fram)
+{
+	char *ptr;
+	
+	if (READABLE()){ char c = GETC();}	// dummy read
+    put_rn();
+    PRINTF("%s [Help:'?' key]", mon_msg);
+    put_rn();
+    for (;;) {
+        put_r();
+        PUTC('>');
+        ptr = linebuf;
+        get_line(ptr, sizeof(linebuf));
+        switch (*ptr++) {
+    //--------------------------------------------------------------------------
+    //  check and set RTC
+    //--------------------------------------------------------------------------
+        case 't' :
+        	put_r(); 
+            time_enter_mode(ex_rtc, ptr);               
+            break;
+    //--------------------------------------------------------------------------
+    //  check FRAM status
+    //--------------------------------------------------------------------------
+        case 'd' :
+        	put_r(); 
+            data_logger(fram, ptr);               
+            break;
+    //--------------------------------------------------------------------------
+    //  help
+    //--------------------------------------------------------------------------
+        case '?' :
+        	put_r(); 
+            msg_hlp();                 
+            break;
+    //--------------------------------------------------------------------------
+    //  Go back to main()
+    //--------------------------------------------------------------------------
+        case 'q' :        // Quit
+            PRINTF("\rReturn to main\r\n");
+            PRINTF("cannot control anymore from here\r\n");
+            return 0;
+        }
+    }
+}
+//------------------------------------------------------------------------------
+// Data Logging / Save into FRAM
+//------------------------------------------------------------------------------
+/*
+    head = H, tail =T
+	state1:	H=1(RING_TOP),T=1(RING_TOP)	-> just after Clear command
+	state2:	H=1,T=n		-> n = 2 to RING_TAIL-1 (not filled yet)	
+	state3:	H=1,T=RING_TAIL	-> need to check!!!! (just filled)
+	state4:	H=2,T=1(RING_TOP) -> start ringed state
+	state5:	H=n,T=n-1	-> n = 2 to RING_TAIL-1 (ringed)
+	state6:	H=RING_TAIL,T=RING_TAIL-1 -> need to check!!!!!
+	state7:	H=1(RING_TOP),T=RING_TAIL -> need to check!!!!!
+	state8:	same as "state5"	
+		-> Need to check state3,6,7
+*/
+//  Make one data packet data structure
+void dtlog_data_pack(void)
+{
+    one.lg.time = log_sec - DATE_COUNT_START;
+    one.lg.vcc  = (uint16_t)(vcc_voltage * 100);
+    one.lg.baro = (uint16_t)(barometer   * 10);
+    one.lg.temp = (int16_t) (temperature * 10);
+    one.lg.humi = (uint16_t)(humidity    * 10);
+	one.lg.dmy	= 0xffff;
+}
+
+//  Print one packet as normalized data
+void print_one_block_data(void)
+{
+	struct tm *t;
+	time_t seconds;
+	uint16_t dt0;
+	int16_t dt1;
+
+    put_rn();
+    //--- Header
+    PUTC('$');
+    //--- Time
+    seconds = one.lg.time + DATE_COUNT_START;
+    t = localtime(&seconds);
+	PRINTF(",%04d/%02d/%02d,%02d:%02d:%02d,",
+			t->tm_year + 1900, t->tm_mon + 1,
+			t->tm_mday, t->tm_hour,
+			t->tm_min, t->tm_sec
+	);
+	//--- Vcc
+	dt0 = one.lg.vcc;
+	PRINTF("%01d.%02d,", dt0/100, dt0%100);
+	//--- Pressure/Barometer
+	dt0 = one.lg.baro;
+	PRINTF("%04d.%01d,", dt0/10, dt0%10 );
+	//--- Temperature
+	dt1 = one.lg.temp;
+	PRINTF("%+03d.%01d,", dt1/10, abs(dt1)%10 );
+	//--- Humidity	   
+	dt0 = one.lg.humi;
+	PRINTF("%02d.%01d,", dt0/10, dt0%10 );
+	//---- Tail
+    PUTC('*');
+}
+
+// Read buffer pointer
+static void dtlog_pointer_read(MB85RSxx_SPI &fram)
+{
+	uint8_t i;
+	uint8_t *addr;
+
+    // Read FRAM and save to buf_pointer[]
+	addr = (uint8_t *)FRAM_TOP;
+	fram.read((int)addr, inf.buf_pointer, PTR_SIZE);
+	PRINTF("Head=%d,Tail=%d\r\n", inf.log_inf.head, inf.log_inf.tail);
+}
+
+//  Write one packet
+void dtlog_one_write(MB85RSxx_SPI &fram)
+{
+	uint8_t *addr;
+
+    // Read FRAM buffer pointer to RAM
+	addr = (uint8_t *)FRAM_TOP;
+	fram.read((int)addr, inf.buf_pointer, PTR_SIZE);
+ 	PRINTF("Befre:Head=%d,Tail=%d -> ", inf.log_inf.head, inf.log_inf.tail);
+    // Write data_pack[] into  FRAM
+	addr = (uint8_t *)(FRAM_TOP + (inf.log_inf.tail * PTR_SIZE));
+    fram.write_enable();
+	fram.write((int)addr, one.bf, PTR_SIZE);
+	fram.write_disable();
+    // Increment buffer pointer in RAM
+    if (inf.log_inf.head == RING_TOP){		// check state1,2,3
+    	if (inf.log_inf.tail == RING_TAIL){		// check state3
+			inf.log_inf.tail = RING_TOP;		// set state4
+			inf.log_inf.head = 2;				// missing one oldest data
+		} else {
+			inf.log_inf.tail++;					// set state2
+		}
+    } else {	// check state 4,5,6,7
+    	if (inf.log_inf.head == RING_TAIL){	// check state6
+    		inf.log_inf.head = RING_TOP; 		// set state7
+    		inf.log_inf.tail = RING_TAIL;
+    	} else if (inf.log_inf.tail == inf.log_inf.head - 1){ // check state4,5
+			++inf.log_inf.tail;		// continue state5
+			++inf.log_inf.head;
+		}
+    }
+    // Write buffer pointer into FRAM
+	addr = (uint8_t *)FRAM_TOP;
+    fram.write_enable();
+	fram.write((int)addr, inf.buf_pointer, PTR_SIZE);
+	fram.write_disable();
+	PRINTF("After:Head=%d,Tail=%d\r\n", inf.log_inf.head, inf.log_inf.tail);
+}
+
+// Read some block from buffer
+void dtlog_block_read(MB85RSxx_SPI &fram, int16_t *pt, uint16_t n)
+{
+	uint8_t *addr;
+	uint16_t num;
+
+    dtlog_pointer_read(fram);
+    if (inf.log_inf.tail == inf.log_inf.head){ // Check pointer
+        PRINTF("%s", msg_emty);
+        put_rn();
+        return;
+    }
+	PRINTF("Head:%d,Tail:%d, Start pointer:%d, Number of data:%d\r\n",
+			inf.log_inf.head, inf.log_inf.tail, *pt, n);
+    PRINTF("%s", log_head);
+    for (num = 0; num < n; num++){
+        // Read FRAM and save to data_pack[]
+		addr = (uint8_t *)(FRAM_TOP + (*pt * PTR_SIZE));
+		fram.read((int)addr, one.bf, PTR_SIZE);
+        print_one_block_data();
+        if (READABLE()){	GETC(); break;}
+	    if (inf.log_inf.head == RING_TOP){	// check state 1,2,3
+	        *pt += 1;
+	        if (*pt >= inf.log_inf.tail){ // check state 2,3
+	        	PRINTF("%s", msg_end);
+            	break;
+            }
+	    } else {	// state 4,5,6,7
+	    	if (inf.log_inf.head == RING_TAIL){ // check state 6
+	    		if (inf.log_inf.tail == RING_TAIL -1){ // check state 6
+	    			if (*pt == RING_TAIL){ // same as  :pt += 1
+	    				*pt = RING_TOP;
+	    			} else { // next read
+				    	*pt += 1;
+				        if (*pt >= inf.log_inf.tail){
+				        	PRINTF("%s", msg_end);
+			            	break;
+		            	}
+		            }
+	    		}
+	    	} else if (inf.log_inf.tail == inf.log_inf.head - 1){// check state5
+		    	*pt += 1;
+		    	if (*pt > RING_TAIL){ // same as  :pt += 1
+		    		*pt = RING_TOP;
+		    	} else if (*pt == inf.log_inf.tail){ // reach to end
+		        	PRINTF("%s", msg_end);
+	            	break;
+            	}
+			}
+	    }
+    }
+    put_rn();
+}
+
+//  Clear all buffer
+void dtlog_clear_all_buff(MB85RSxx_SPI &fram)
+{
+	uint8_t *addr;
+
+    // Set initial data 
+	inf.log_inf.head = inf.log_inf.tail = RING_TOP;  
+    // Write buffer pointer
+	addr = (uint8_t *)FRAM_TOP;
+    fram.write_enable();
+	fram.write((int)addr, inf.buf_pointer, PTR_SIZE);
+	fram.write_disable();
+}
+
+// FRAM buffer occupation
+uint16_t dtlog_buf_occupation(MB85RSxx_SPI &fram)
+{
+	uint16_t dt = 0;
+	uint8_t *addr;
+
+    // Read FRAM buffer pointer to RAM
+	addr = (uint8_t *)FRAM_TOP;
+	fram.read((int)addr, inf.buf_pointer, PTR_SIZE);
+    // check buffer pointer
+    if (inf.log_inf.head == inf.log_inf.tail){
+        PRINTF("%s", msg_emty);
+        put_rn();
+        return 0;
+    }
+    if (inf.log_inf.head == RING_TOP){	// check state1,2,3
+    	dt = inf.log_inf.tail - inf.log_inf.head;
+    } else {	// state 4,5,6,7
+    	if (inf.log_inf.head == RING_TAIL){	// check state6
+    		if (inf.log_inf.tail == RING_TAIL - 1){	// check state6
+			    dt = inf.log_inf.tail - RING_TOP + 1;
+    		}
+    	} else if (inf.log_inf.tail == inf.log_inf.head - 1){ // check state4,5
+			dt = RING_TAIL;
+		} else {	// error
+		    dt = 0;
+		}
+    }
+    return dt;
+}
+
+//  Read block number
+void dtlog_num_of_block(MB85RSxx_SPI &fram)
+{
+	uint16_t dt;
+
+	dt = dtlog_buf_occupation(fram);
+	if (dt == 0){
+		PRINTF("%s", msg_emty);
+    } else {
+	    PRINTF("Number of data = %d", dt);    
+	    put_rn();
+	    dt = (uint16_t)(((uint32_t)dt * 1000 )/ (BLK_NO - 2));
+	    PRINTF("FRAM Occupation = %d.%01d%%", dt / 10, dt % 10);
+    }
+    put_rn();
+}
+
+//------------------------------------------------------------------------------
+//	Monitor
+//------------------------------------------------------------------------------
+//  Help Massage
+void msg_hlp (void)
+{
+    PRINTF("%s", mon_msg);					put_rn();
+    PRINTF("d - Data logger");				put_rn();
+    PRINTF("t - Check and set RTC");		put_rn();
+    PRINTF("q - Return to main");			put_rn();
+}
+
+//	Data Logger / Check status and Output data
+static void data_logger(MB85RSxx_SPI &fram, char *ptr)
+{
+	char c;
+	unsigned long dt;
+	uint16_t n;
+	const char *const Msg  = "Data Logger Mode, ?[Help]";
+
+	PRINTF("%s", Msg);
+	put_rn();
+	// Get FRAM resource
+	dtlog_pointer_read(fram);
+	dt = inf.log_inf.head;
+	while (1){
+		// Get FRAM resource
+		dtlog_pointer_read(fram);
+		PRINTF("DL>");
+        ptr = linebuf;
+        get_line(ptr, buf_size);
+		switch (*ptr++) {
+			case 'a' :
+				put_r();
+				read_pointer = inf.log_inf.head;
+				n = dtlog_buf_occupation(fram);
+				dtlog_block_read(fram, &read_pointer, n);
+				break;
+			case 'c' :	// Clear data
+				put_r();
+				PRINTF("Delete all data?");
+				put_rn();
+				PRINTF("Enter y/n (n-cancel)");
+				put_rn();
+				c = GETC();
+				PUTC(c);
+				put_rn();
+				if (c == 'y'){
+					PRINTF("Cleared all logging data");
+					dtlog_clear_all_buff(fram);
+				} else {
+					PRINTF("Canceled");
+				}
+				put_rn();
+				break;
+			case 'd' :	// d <pointer> [<count>] - Dump buffer
+				put_r();
+				if (xatoi(&ptr, &dt)){	read_pointer = (uint16_t)dt;
+				} else {				read_pointer = inf.log_inf.head; }	
+				if (xatoi(&ptr, &dt)){	n = (uint8_t)dt;				
+				} else {				n = BLK_SIZE; }
+				if (read_pointer == 0){ read_pointer = 1;}
+				dtlog_block_read(fram, &read_pointer, n);
+				break;
+			case 0x0d :	// CR
+				put_r();
+				dtlog_block_read(fram, &read_pointer, BLK_SIZE);
+				break;
+			case 'b' :	// Back
+				put_r();
+				read_pointer -= (BLK_SIZE * 2);
+				if (read_pointer <= 0){ read_pointer = 1;}
+				dtlog_block_read(fram, &read_pointer, n);
+				break;
+			case 'n' :
+			case 's' :	// Status
+				put_r();
+				dtlog_num_of_block(fram);
+				break;
+			case 'q' :	// exit
+				linebuf[0] = 0;
+				return;
+			case '?' :
+				put_r();
+			    PRINTF("d - <pointer> [<count>] Dump one block data"); put_rn();
+			    PRINTF("a - Dump all log data");		put_rn();
+			    PRINTF("c - Clear log data");			put_rn();
+			    PRINTF("s - Logger status");			put_rn();
+			    PRINTF("q - Exit DL mode");				put_rn();  
+				break;
+			default:
+				PUTC('?');
+				put_rn();
+				break;
+		}
+	}
+}
+
+void time_enter_mode(RX8025 &ex_rtc, char *pointer)
+{
+    char *ptr;
+    char linebuf[64];
+    time_t seconds;
+
+    pc.printf("Set time into RTC\r\n");
+    pc.printf(" e.g. ->19 12 16 10 11 12 -> December 16th,'19, 10:11:12\r\n");
+    seconds = w_check_rtc_time(ex_rtc);
+    strftime(linebuf, 50, "Current time: %Y/%m/%d,%H:%M:%S\r\n",
+             localtime(&seconds));
+    pc.printf("%s", linebuf);
+    pc.printf(" If time is fine, just hit enter\r\n");
+    pc.puts("->");
+    if (pointer == 0) {
+        ptr = linebuf;
+    } else {
+        ptr = pointer;
+    }
+    get_line(ptr, sizeof(linebuf));
+    pc.printf("\r");
+    chk_and_set_time(ex_rtc, ptr);
+}
+
+void chk_and_set_time(RX8025 &ex_rtc, char *ptr)
+{
+    unsigned long p1;
+    struct tm t;
+    time_t seconds;
+
+    if (xatoi(&ptr, &p1)) {
+        t.tm_year       = (uint8_t)p1 + 100;
+        pc.printf("Year:%d ", (int)p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mon        = (uint8_t)p1 - 1;
+        pc.printf("Month:%d ", (int)p1);
+        xatoi( &ptr, &p1 );
+        t.tm_mday       = (uint8_t)p1;
+        pc.printf("Day:%d ", (int)p1);
+        xatoi( &ptr, &p1 );
+        t.tm_hour       = (uint8_t)p1;
+        pc.printf("Hour:%d ", (int)p1);
+        xatoi( &ptr, &p1 );
+        t.tm_min        = (uint8_t)p1;
+        pc.printf("Min:%d ", (int)p1);
+        xatoi( &ptr, &p1 );
+        t.tm_sec        = (uint8_t)p1;
+        pc.printf("Sec: %d \r\n", (int)p1);
+    } else {
+        return;
+    }
+    seconds = mktime(&t);
+    set_time(seconds);
+    struct tm *time_ajd = localtime(&seconds);
+    ex_rtc.set_time_rtc(time_ajd);
+    pc.printf(
+        "Date: %04d/%02d/%02d, %02d:%02d:%02d\r\n",
+        t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec
+    );
+}
+
+//  Get key input data
+void get_line (char *buff, int len)
+{
+    char c;
+    int idx = 0;
+
+    for (;;) {
+        c = pc.getc();
+        if (c == '\r') {
+            buff[idx++] = c;
+            break;
+        }
+        if ((c == '\b') && idx) {
+            idx--;
+            pc.putc(c);
+            pc.putc(' ');
+            pc.putc(c);
+        }
+        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
+            buff[idx++] = c;
+            pc.putc(c);
+        }
+    }
+    buff[idx] = 0;
+    pc.putc('\n');
+}
+
+//  Change string -> integer
+int xatoi (char **str, unsigned long *res)
+{
+    unsigned long val;
+    unsigned char c, radix, s = 0;
+
+    while ((c = **str) == ' ') {
+        (*str)++;
+    }
+    if (c == '-') {
+        s = 1;
+        c = *(++(*str));
+    }
+    if (c == '0') {
+        c = *(++(*str));
+        if (c <= ' ') {
+            *res = 0;
+            return 1;
+        }
+        if (c == 'x') {
+            radix = 16;
+            c = *(++(*str));
+        } else {
+            if (c == 'b') {
+                radix = 2;
+                c = *(++(*str));
+            } else {
+                if ((c >= '0')&&(c <= '9')) {
+                    radix = 8;
+                } else {
+                    return 0;
+                }
+            }
+        }
+    } else {
+        if ((c < '1')||(c > '9')) {
+            return 0;
+        }
+        radix = 10;
+    }
+    val = 0;
+    while (c > ' ') {
+        if (c >= 'a') {
+            c -= 0x20;
+        }
+        c -= '0';
+        if (c >= 17) {
+            c -= 7;
+            if (c <= 9) {
+                return 0;
+            }
+        }
+        if (c >= radix) {
+            return 0;
+        }
+        val = val * radix + c;
+        c = *(++(*str));
+    }
+    if (s) {
+        val = -val;
+    }
+    *res = val;
+    return 1;
+}
+
+//  Put \r\n
+void put_rn(void){	PUTC('\r');		PUTC('\n');}
+
+//  Put \r
+void put_r(void){	PUTC('\r');}
+
+// Put ", "
+void put_lin(void){	PRINTF(", ");}
+
+// Put space n
+void put_spc(uint8_t n){ for(;n > 0; n--){ PUTC(' '); }}