Kenji Arai / TYBLE16_simple_data_logger

Dependencies:   mbed-os_TYBLE16 BME280_SPI RX8025NB nRF51_Vdd MB85RSxx_SPI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dt_logger.cpp Source File

dt_logger.cpp

00001 /*
00002  * Mbed Application program / TYBLE-16 Data logger
00003  *
00004  * Copyright (c) 2019 Kenji Arai / JH1PJL
00005  *  http://www.page.sannet.ne.jp/kenjia/index.html
00006  *  https://os.mbed.com/users/kenjiArai/
00007  *      Created:    December  14th, 2019
00008  *      Revised:    December  19th, 2019
00009  */
00010 
00011 //  Include --------------------------------------------------------------------
00012 #include "mbed.h"
00013 #include "dt_logger.h"
00014 
00015 //  Object ---------------------------------------------------------------------
00016 extern Serial pc;
00017 
00018 //  Definition -----------------------------------------------------------------
00019 #define BAUD(x)                 pc.baud(x)
00020 #define GETC(x)                 pc.getc(x)
00021 #define PUTC(x)                 pc.putc(x)
00022 #define PRINTF(...)             pc.printf(__VA_ARGS__)
00023 #define READABLE(x)             pc.readable(x)
00024 
00025 // FRAM
00026 #define FRAM_TOP                0x0
00027 
00028 //  RAM ------------------------------------------------------------------------
00029 char linebuf[64];
00030 int buf_size = sizeof(linebuf);
00031 
00032 //  for FRAM control
00033 int16_t read_pointer;
00034 
00035 typedef struct {
00036     uint16_t    head;
00037     uint16_t    tail;
00038 } ring_t;
00039 
00040 union _inf{
00041     uint8_t buf_pointer[PTR_SIZE];
00042     ring_t log_inf;
00043 }inf;
00044 
00045 typedef struct {
00046     uint32_t    time;   // 4byte
00047     uint16_t    vcc;    // 2
00048     uint16_t    baro;   // 2
00049     int16_t     temp;   // 2
00050     uint16_t    humi;   // 2
00051     uint32_t    dmy;    // 4
00052 }one_log;       // 16 bytes total
00053 
00054 union _one{
00055     uint8_t bf[PKT_SIZE];
00056     one_log lg;
00057 }one;
00058 
00059 extern time_t log_sec;
00060 extern float vcc_voltage;
00061 extern float barometer;
00062 extern float temperature;
00063 extern float humidity;
00064 
00065 //  ROM / Constant data --------------------------------------------------------
00066 const char *const mon_msg =
00067                      "Monitor for TYBLE16 Data logger, created on " __DATE__"";
00068 //                            $,2019/12/21,12:43:16,3.29,1004.5,+29.3,45.8,*
00069 const char *const log_head = "$,YYYY/MM/DD,HH:MM:SS,Vcc ,Press , Temp,Humi,*";
00070 const char *const msg_emty = "Data empty";
00071 const char *const msg_end  = "\r\nreach to end";
00072 
00073 //  Function prototypes --------------------------------------------------------
00074 extern time_t w_check_rtc_time(RX8025 &ex_rtc);
00075 
00076 static void data_logger(MB85RSxx_SPI &fram, char *ptr);
00077 static void msg_hlp (void);
00078 static void time_enter_mode(RX8025 &ex_rtc, char *ptr);
00079 static void chk_and_set_time(RX8025 &ex_rtc, char *ptr);
00080 static int xatoi (char **str, unsigned long *res);
00081 static void get_line(char *buff, int len);
00082 static void put_rn(void);
00083 static void put_r(void);
00084 static void put_lin(void);
00085 static void put_spc(uint8_t n);
00086 
00087 //------------------------------------------------------------------------------
00088 //  Control Program
00089 //------------------------------------------------------------------------------
00090 // ---------- Program starts here! ---------------------------------------------
00091 void mon(RX8025 &ex_rtc, MB85RSxx_SPI &fram)
00092 {
00093     char *ptr;
00094     
00095     if (READABLE()){ char c = GETC();}  // dummy read
00096     put_rn();
00097     PRINTF("%s [Help:'?' key]", mon_msg);
00098     put_rn();
00099     for (;;) {
00100         put_r();
00101         PUTC('>');
00102         ptr = linebuf;
00103         get_line(ptr, sizeof(linebuf));
00104         switch (*ptr++) {
00105     //--------------------------------------------------------------------------
00106     //  check and set RTC
00107     //--------------------------------------------------------------------------
00108         case 't' :
00109             put_r(); 
00110             time_enter_mode(ex_rtc, ptr);               
00111             break;
00112     //--------------------------------------------------------------------------
00113     //  check FRAM status
00114     //--------------------------------------------------------------------------
00115         case 'd' :
00116             put_r(); 
00117             data_logger(fram, ptr);               
00118             break;
00119     //--------------------------------------------------------------------------
00120     //  help
00121     //--------------------------------------------------------------------------
00122         case '?' :
00123             put_r(); 
00124             msg_hlp();                 
00125             break;
00126     //--------------------------------------------------------------------------
00127     //  Go back to main()
00128     //--------------------------------------------------------------------------
00129         case 'q' :        // Quit
00130             PRINTF("\rReturn to main\r\n");
00131             PRINTF("cannot control anymore from here\r\n");
00132             return;
00133         }
00134     }
00135 }
00136 //------------------------------------------------------------------------------
00137 // Data Logging / Save into FRAM
00138 //------------------------------------------------------------------------------
00139 /*
00140     head = H, tail =T
00141     state1: H=1(RING_TOP),T=1(RING_TOP) -> just after Clear command
00142     state2: H=1,T=n     -> n = 2 to RING_TAIL-1 (not filled yet)    
00143     state3: H=1,T=RING_TAIL -> need to check!!!! (just filled)
00144     state4: H=2,T=1(RING_TOP) -> start ringed state
00145     state5: H=n,T=n-1   -> n = 2 to RING_TAIL-1 (ringed)
00146     state6: H=RING_TAIL,T=RING_TAIL-1 -> need to check!!!!!
00147     state7: H=1(RING_TOP),T=RING_TAIL -> need to check!!!!!
00148     state8: same as "state5"    
00149         -> Need to check state3,6,7
00150 */
00151 //  Make one data packet data structure
00152 void dtlog_data_pack(void)
00153 {
00154     one.lg.time = log_sec - DATE_COUNT_START;
00155     one.lg.vcc  = (uint16_t)(vcc_voltage * 100);
00156     one.lg.baro = (uint16_t)(barometer   * 10);
00157     one.lg.temp = (int16_t) (temperature * 10);
00158     one.lg.humi = (uint16_t)(humidity    * 10);
00159     one.lg.dmy  = 0xffff;
00160 }
00161 
00162 //  Print one packet as normalized data
00163 void print_one_block_data(void)
00164 {
00165     struct tm *t;
00166     time_t seconds;
00167     uint16_t dt0;
00168     int16_t dt1;
00169 
00170     put_rn();
00171     //--- Header
00172     PUTC('$');
00173     //--- Time
00174     seconds = one.lg.time + DATE_COUNT_START;
00175     t = localtime(&seconds);
00176     PRINTF(",%04d/%02d/%02d,%02d:%02d:%02d,",
00177             t->tm_year + 1900, t->tm_mon + 1,
00178             t->tm_mday, t->tm_hour,
00179             t->tm_min, t->tm_sec
00180     );
00181     //--- Vcc
00182     dt0 = one.lg.vcc;
00183     PRINTF("%01d.%02d,", dt0/100, dt0%100);
00184     //--- Pressure/Barometer
00185     dt0 = one.lg.baro;
00186     PRINTF("%04d.%01d,", dt0/10, dt0%10 );
00187     //--- Temperature
00188     dt1 = one.lg.temp;
00189     PRINTF("%+03d.%01d,", dt1/10, abs(dt1)%10 );
00190     //--- Humidity     
00191     dt0 = one.lg.humi;
00192     PRINTF("%02d.%01d,", dt0/10, dt0%10 );
00193     //---- Tail
00194     PUTC('*');
00195 }
00196 
00197 // Read buffer pointer
00198 static void dtlog_pointer_read(MB85RSxx_SPI &fram)
00199 {
00200     uint8_t i;
00201     uint8_t *addr;
00202 
00203     // Read FRAM and save to buf_pointer[]
00204     addr = (uint8_t *)FRAM_TOP;
00205     fram.read((int)addr, inf.buf_pointer, PTR_SIZE);
00206     PRINTF("Head=%d,Tail=%d\r\n", inf.log_inf.head, inf.log_inf.tail);
00207 }
00208 
00209 //  Write one packet
00210 void dtlog_one_write(MB85RSxx_SPI &fram)
00211 {
00212     uint8_t *addr;
00213 
00214     // Read FRAM buffer pointer to RAM
00215     addr = (uint8_t *)FRAM_TOP;
00216     fram.read((int)addr, inf.buf_pointer, PTR_SIZE);
00217     PRINTF("Befre:Head=%d,Tail=%d -> ", inf.log_inf.head, inf.log_inf.tail);
00218     // Write data_pack[] into  FRAM
00219     addr = (uint8_t *)(FRAM_TOP + (inf.log_inf.tail * PTR_SIZE));
00220     fram.write_enable();
00221     fram.write((int)addr, one.bf, PTR_SIZE);
00222     fram.write_disable();
00223     // Increment buffer pointer in RAM
00224     if (inf.log_inf.head == RING_TOP){      // check state1,2,3
00225         if (inf.log_inf.tail == RING_TAIL){     // check state3
00226             inf.log_inf.tail = RING_TOP;        // set state4
00227             inf.log_inf.head = 2;               // missing one oldest data
00228         } else {
00229             inf.log_inf.tail++;                 // set state2
00230         }
00231     } else {    // check state 4,5,6,7
00232         if (inf.log_inf.head == RING_TAIL){ // check state6
00233             inf.log_inf.head = RING_TOP;        // set state7
00234             inf.log_inf.tail = RING_TAIL;
00235         } else if (inf.log_inf.tail == inf.log_inf.head - 1){ // check state4,5
00236             ++inf.log_inf.tail;     // continue state5
00237             ++inf.log_inf.head;
00238         }
00239     }
00240     // Write buffer pointer into FRAM
00241     addr = (uint8_t *)FRAM_TOP;
00242     fram.write_enable();
00243     fram.write((int)addr, inf.buf_pointer, PTR_SIZE);
00244     fram.write_disable();
00245     PRINTF("After:Head=%d,Tail=%d\r\n", inf.log_inf.head, inf.log_inf.tail);
00246 }
00247 
00248 // Read some block from buffer
00249 void dtlog_block_read(MB85RSxx_SPI &fram, int16_t *pt, uint16_t n)
00250 {
00251     uint8_t *addr;
00252     uint16_t num;
00253 
00254     dtlog_pointer_read(fram);
00255     if (inf.log_inf.tail == inf.log_inf.head){ // Check pointer
00256         PRINTF("%s", msg_emty);
00257         put_rn();
00258         return;
00259     }
00260     PRINTF("Head:%d,Tail:%d, Start pointer:%d, Number of data:%d\r\n",
00261             inf.log_inf.head, inf.log_inf.tail, *pt, n);
00262     PRINTF("%s", log_head);
00263     for (num = 0; num < n; num++){
00264         // Read FRAM and save to data_pack[]
00265         addr = (uint8_t *)(FRAM_TOP + (*pt * PTR_SIZE));
00266         fram.read((int)addr, one.bf, PTR_SIZE);
00267         print_one_block_data();
00268         if (READABLE()){    GETC(); break;}
00269         if (inf.log_inf.head == RING_TOP){  // check state 1,2,3
00270             *pt += 1;
00271             if (*pt >= inf.log_inf.tail){ // check state 2,3
00272                 PRINTF("%s", msg_end);
00273                 break;
00274             }
00275         } else {    // state 4,5,6,7
00276             if (inf.log_inf.head == RING_TAIL){ // check state 6
00277                 if (inf.log_inf.tail == RING_TAIL -1){ // check state 6
00278                     if (*pt == RING_TAIL){ // same as  :pt += 1
00279                         *pt = RING_TOP;
00280                     } else { // next read
00281                         *pt += 1;
00282                         if (*pt >= inf.log_inf.tail){
00283                             PRINTF("%s", msg_end);
00284                             break;
00285                         }
00286                     }
00287                 }
00288             } else if (inf.log_inf.tail == inf.log_inf.head - 1){// check state5
00289                 *pt += 1;
00290                 if (*pt > RING_TAIL){ // same as  :pt += 1
00291                     *pt = RING_TOP;
00292                 } else if (*pt == inf.log_inf.tail){ // reach to end
00293                     PRINTF("%s", msg_end);
00294                     break;
00295                 }
00296             }
00297         }
00298     }
00299     put_rn();
00300 }
00301 
00302 //  Clear all buffer
00303 void dtlog_clear_all_buff(MB85RSxx_SPI &fram)
00304 {
00305     uint8_t *addr;
00306 
00307     // Set initial data 
00308     inf.log_inf.head = inf.log_inf.tail = RING_TOP;  
00309     // Write buffer pointer
00310     addr = (uint8_t *)FRAM_TOP;
00311     fram.write_enable();
00312     fram.write((int)addr, inf.buf_pointer, PTR_SIZE);
00313     fram.write_disable();
00314 }
00315 
00316 // FRAM buffer occupation
00317 uint16_t dtlog_buf_occupation(MB85RSxx_SPI &fram)
00318 {
00319     uint16_t dt = 0;
00320     uint8_t *addr;
00321 
00322     // Read FRAM buffer pointer to RAM
00323     addr = (uint8_t *)FRAM_TOP;
00324     fram.read((int)addr, inf.buf_pointer, PTR_SIZE);
00325     // check buffer pointer
00326     if (inf.log_inf.head == inf.log_inf.tail){
00327         PRINTF("%s", msg_emty);
00328         put_rn();
00329         return 0;
00330     }
00331     if (inf.log_inf.head == RING_TOP){  // check state1,2,3
00332         dt = inf.log_inf.tail - inf.log_inf.head;
00333     } else {    // state 4,5,6,7
00334         if (inf.log_inf.head == RING_TAIL){ // check state6
00335             if (inf.log_inf.tail == RING_TAIL - 1){ // check state6
00336                 dt = inf.log_inf.tail - RING_TOP + 1;
00337             }
00338         } else if (inf.log_inf.tail == inf.log_inf.head - 1){ // check state4,5
00339             dt = RING_TAIL;
00340         } else {    // error
00341             dt = 0;
00342         }
00343     }
00344     return dt;
00345 }
00346 
00347 //  Read block number
00348 void dtlog_num_of_block(MB85RSxx_SPI &fram)
00349 {
00350     uint16_t dt;
00351 
00352     dt = dtlog_buf_occupation(fram);
00353     if (dt == 0){
00354         PRINTF("%s", msg_emty);
00355     } else {
00356         PRINTF("Number of data = %d", dt);    
00357         put_rn();
00358         dt = (uint16_t)(((uint32_t)dt * 1000 )/ (BLK_NO - 2));
00359         PRINTF("FRAM Occupation = %d.%01d%%", dt / 10, dt % 10);
00360     }
00361     put_rn();
00362 }
00363 
00364 //------------------------------------------------------------------------------
00365 //  Monitor
00366 //------------------------------------------------------------------------------
00367 //  Help Massage
00368 void msg_hlp (void)
00369 {
00370     PRINTF("%s", mon_msg);                  put_rn();
00371     PRINTF("d - Data logger");              put_rn();
00372     PRINTF("t - Check and set RTC");        put_rn();
00373     PRINTF("q - Return to main");           put_rn();
00374 }
00375 
00376 //  Data Logger / Check status and Output data
00377 static void data_logger(MB85RSxx_SPI &fram, char *ptr)
00378 {
00379     char c;
00380     unsigned long dt;
00381     uint16_t n;
00382     const char *const Msg  = "Data Logger Mode, ?[Help]";
00383 
00384     PRINTF("%s", Msg);
00385     put_rn();
00386     // Get FRAM resource
00387     dtlog_pointer_read(fram);
00388     dt = inf.log_inf.head;
00389     while (1){
00390         // Get FRAM resource
00391         dtlog_pointer_read(fram);
00392         PRINTF("DL>");
00393         ptr = linebuf;
00394         get_line(ptr, buf_size);
00395         switch (*ptr++) {
00396             case 'a' :
00397                 put_r();
00398                 read_pointer = inf.log_inf.head;
00399                 n = dtlog_buf_occupation(fram);
00400                 dtlog_block_read(fram, &read_pointer, n);
00401                 break;
00402             case 'c' :  // Clear data
00403                 put_r();
00404                 PRINTF("Delete all data?");
00405                 put_rn();
00406                 PRINTF("Enter y/n (n-cancel)");
00407                 put_rn();
00408                 c = GETC();
00409                 PUTC(c);
00410                 put_rn();
00411                 if (c == 'y'){
00412                     PRINTF("Cleared all logging data");
00413                     dtlog_clear_all_buff(fram);
00414                 } else {
00415                     PRINTF("Canceled");
00416                 }
00417                 put_rn();
00418                 break;
00419             case 'd' :  // d <pointer> [<count>] - Dump buffer
00420                 put_r();
00421                 if (xatoi(&ptr, &dt)){  read_pointer = (uint16_t)dt;
00422                 } else {                read_pointer = inf.log_inf.head; }  
00423                 if (xatoi(&ptr, &dt)){  n = (uint8_t)dt;                
00424                 } else {                n = BLK_SIZE; }
00425                 if (read_pointer == 0){ read_pointer = 1;}
00426                 dtlog_block_read(fram, &read_pointer, n);
00427                 break;
00428             case 0x0d : // CR
00429                 put_r();
00430                 dtlog_block_read(fram, &read_pointer, BLK_SIZE);
00431                 break;
00432             case 'b' :  // Back
00433                 put_r();
00434                 read_pointer -= (BLK_SIZE * 2);
00435                 if (read_pointer <= 0){ read_pointer = 1;}
00436                 dtlog_block_read(fram, &read_pointer, n);
00437                 break;
00438             case 'n' :
00439             case 's' :  // Status
00440                 put_r();
00441                 dtlog_num_of_block(fram);
00442                 break;
00443             case 'q' :  // exit
00444                 linebuf[0] = 0;
00445                 return;
00446             case '?' :
00447                 put_r();
00448                 PRINTF("d - <pointer> [<count>] Dump one block data"); put_rn();
00449                 PRINTF("a - Dump all log data");        put_rn();
00450                 PRINTF("c - Clear log data");           put_rn();
00451                 PRINTF("s - Logger status");            put_rn();
00452                 PRINTF("q - Exit DL mode");             put_rn();  
00453                 break;
00454             default:
00455                 PUTC('?');
00456                 put_rn();
00457                 break;
00458         }
00459     }
00460 }
00461 
00462 void time_enter_mode(RX8025 &ex_rtc, char *pointer)
00463 {
00464     char *ptr;
00465     char linebuf[64];
00466     time_t seconds;
00467 
00468     pc.printf("Set time into RTC\r\n");
00469     pc.printf(" e.g. ->19 12 19 10 11 12 -> December 19th,'19, 10:11:12\r\n");
00470     seconds = w_check_rtc_time(ex_rtc);
00471     strftime(linebuf, 50, "Current time: %Y/%m/%d,%H:%M:%S\r\n",
00472              localtime(&seconds));
00473     pc.printf("%s", linebuf);
00474     pc.printf(" If time is fine, just hit enter\r\n");
00475     pc.puts("->");
00476     if (pointer == 0) {
00477         ptr = linebuf;
00478     } else {
00479         ptr = pointer;
00480     }
00481     get_line(ptr, sizeof(linebuf));
00482     pc.printf("\r");
00483     chk_and_set_time(ex_rtc, ptr);
00484 }
00485 
00486 void chk_and_set_time(RX8025 &ex_rtc, char *ptr)
00487 {
00488     unsigned long p1;
00489     struct tm t;
00490     time_t seconds;
00491 
00492     if (xatoi(&ptr, &p1)) {
00493         t.tm_year       = (uint8_t)p1 + 100;
00494         pc.printf("Year:%d ", (int)p1);
00495         xatoi( &ptr, &p1 );
00496         t.tm_mon        = (uint8_t)p1 - 1;
00497         pc.printf("Month:%d ", (int)p1);
00498         xatoi( &ptr, &p1 );
00499         t.tm_mday       = (uint8_t)p1;
00500         pc.printf("Day:%d ", (int)p1);
00501         xatoi( &ptr, &p1 );
00502         t.tm_hour       = (uint8_t)p1;
00503         pc.printf("Hour:%d ", (int)p1);
00504         xatoi( &ptr, &p1 );
00505         t.tm_min        = (uint8_t)p1;
00506         pc.printf("Min:%d ", (int)p1);
00507         xatoi( &ptr, &p1 );
00508         t.tm_sec        = (uint8_t)p1;
00509         pc.printf("Sec: %d \r\n", (int)p1);
00510     } else {
00511         return;
00512     }
00513     seconds = mktime(&t);
00514     set_time(seconds);
00515     struct tm *time_ajd = localtime(&seconds);
00516     ex_rtc.set_time_rtc(time_ajd);
00517     pc.printf(
00518         "Date: %04d/%02d/%02d, %02d:%02d:%02d\r\n",
00519         t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec
00520     );
00521 }
00522 
00523 //  Get key input data
00524 void get_line (char *buff, int len)
00525 {
00526     char c;
00527     int idx = 0;
00528 
00529     for (;;) {
00530         c = pc.getc();
00531         if (c == '\r') {
00532             buff[idx++] = c;
00533             break;
00534         }
00535         if ((c == '\b') && idx) {
00536             idx--;
00537             pc.putc(c);
00538             pc.putc(' ');
00539             pc.putc(c);
00540         }
00541         if (((uint8_t)c >= ' ') && (idx < len - 1)) {
00542             buff[idx++] = c;
00543             pc.putc(c);
00544         }
00545     }
00546     buff[idx] = 0;
00547     pc.putc('\n');
00548 }
00549 
00550 //  Change string -> integer
00551 int xatoi (char **str, unsigned long *res)
00552 {
00553     unsigned long val;
00554     unsigned char c, radix, s = 0;
00555 
00556     while ((c = **str) == ' ') {
00557         (*str)++;
00558     }
00559     if (c == '-') {
00560         s = 1;
00561         c = *(++(*str));
00562     }
00563     if (c == '0') {
00564         c = *(++(*str));
00565         if (c <= ' ') {
00566             *res = 0;
00567             return 1;
00568         }
00569         if (c == 'x') {
00570             radix = 16;
00571             c = *(++(*str));
00572         } else {
00573             if (c == 'b') {
00574                 radix = 2;
00575                 c = *(++(*str));
00576             } else {
00577                 if ((c >= '0')&&(c <= '9')) {
00578                     radix = 8;
00579                 } else {
00580                     return 0;
00581                 }
00582             }
00583         }
00584     } else {
00585         if ((c < '1')||(c > '9')) {
00586             return 0;
00587         }
00588         radix = 10;
00589     }
00590     val = 0;
00591     while (c > ' ') {
00592         if (c >= 'a') {
00593             c -= 0x20;
00594         }
00595         c -= '0';
00596         if (c >= 17) {
00597             c -= 7;
00598             if (c <= 9) {
00599                 return 0;
00600             }
00601         }
00602         if (c >= radix) {
00603             return 0;
00604         }
00605         val = val * radix + c;
00606         c = *(++(*str));
00607     }
00608     if (s) {
00609         val = -val;
00610     }
00611     *res = val;
00612     return 1;
00613 }
00614 
00615 //  Put \r\n
00616 void put_rn(void){  PUTC('\r');     PUTC('\n');}
00617 
00618 //  Put \r
00619 void put_r(void){   PUTC('\r');}
00620 
00621 // Put ", "
00622 void put_lin(void){ PRINTF(", ");}
00623 
00624 // Put space n
00625 void put_spc(uint8_t n){ for(;n > 0; n--){ PUTC(' '); }}