Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed-os_TYBLE16 BME280_SPI RX8025NB nRF51_Vdd MB85RSxx_SPI
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(' '); }}
Generated on Mon Jul 18 2022 00:15:15 by
1.7.2