Barometer program : Data Logger function includes Barometer & temperature (BMP180), Humidity & temp. (RHT03), Sunshine (Cds), RTC(M41T62) data. : Logging data saves into EEPROM (AT24C1024) using ring buffer function.

Dependencies:   AT24C1024 RHT03 TextLCD BMP180 M41T62

Fork of mbed_blinky by Mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mon.cpp Source File

mon.cpp

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