ftf connects queue lab

Dependencies:   ST7567

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /**
00002  *  @brief NXP FTF LAB3 - Mbed OS Queue message to control tasks
00003  */
00004 
00005 
00006 #include "mbed.h"
00007 #include "ST7567.h"
00008 #include "rtos.h"
00009 
00010 /* LCD screen dimensions */
00011 #define LCD_HEIGHT          64
00012 #define LCD_WIDTH           128
00013 
00014 /* LCD font dimensions */
00015 #define FONT_HEIGHT         10
00016 #define FONT_WIDTH          5
00017 
00018 
00019 /** led task command descriptor */
00020 typedef struct  {
00021     int led_nbr;
00022     bool on_off;
00023     bool make_color;
00024     uint8_t color;
00025 
00026 }led_cmd_desc_t;
00027 
00028 
00029 /** glcd command descriptor */
00030 typedef struct  {
00031     char message[64];
00032     int x;
00033     int y;
00034 }glcd_cmd_desc_t;
00035 
00036 
00037 
00038 /** Instance a on board GLCD object */
00039  ST7567 glcd(D11, D13, D12, D9, D10); 
00040  
00041  /* allocate statically stacks for the three threads */
00042 unsigned char led_stk[1024];
00043 unsigned char disp_stk[1024];
00044 unsigned char shell_stk[8192];
00045 
00046 /* creates three tread objects with different priorities */
00047 Thread led_thread(osPriorityRealtime, 1024, &led_stk[0]);
00048 Thread disp_thread(osPriorityRealtime, 1024, &disp_stk[0]);
00049 Thread shell_thread(osPriorityNormal, 8192, &shell_stk[0]);
00050 
00051 /* create two queues, one for led commands other to lcd commands */
00052 Mail<led_cmd_desc_t, 16> led_q;
00053 Mail<glcd_cmd_desc_t, 16> disp_q;
00054 
00055 
00056  /** Instance a UART class to communicate with pc */
00057 Serial pc_serial(USBTX,USBRX);
00058 
00059 
00060 /**
00061  * @brief application demo task 
00062  */
00063 void led_task(void) {
00064     osEvent evt;
00065     DigitalOut leds[3] = {LED1, LED2, LED3};
00066     led_cmd_desc_t *cmd;
00067 
00068     
00069     leds[0] = leds[1] = leds[2] = 1;
00070     
00071     for(;;) {
00072  
00073         /* wait for a new command */
00074         evt = led_q.get(osWaitForever);
00075         if(evt.status != osEventMail) continue;                
00076         cmd = (led_cmd_desc_t *)evt.value.p;
00077         if(cmd == NULL) continue;
00078         
00079         
00080         
00081         if(cmd->make_color != true) {
00082                         
00083             /* is a led on_off command */
00084             if(cmd->on_off == true) {
00085                 
00086                 if(cmd->led_nbr == 0) {
00087                     /* handle all leds */
00088                     leds[0] = leds[1] = leds[2] = 0;    
00089                 } else { 
00090                     /* handle specific led */
00091                     leds[cmd->led_nbr - 1] = 0;
00092                 }                   
00093             } else {
00094                 if(cmd->led_nbr == 0) {
00095                     /* handle all leds */
00096                     leds[0] = leds[1] = leds[2] = 1;    
00097                 } else { 
00098                     /* handle specific led */
00099                     leds[cmd->led_nbr - 1] = 1;
00100                 }                                   
00101             }
00102             
00103             /* free memory for next message */
00104             led_q.free(cmd);
00105  
00106         } else {
00107             /* is a make color command */
00108             int r, b, g;
00109 
00110             
00111             /* extract color bitfields */
00112             r = (cmd->color & 0x04 )>> 2;
00113             b = cmd->color & 0x01;
00114             g = (cmd->color & 0x02) >> 1;            
00115             
00116             leds[0] = ~(r) & 0x1;
00117             leds[1] = ~(b) & 0x1;
00118             leds[2] = ~(g) & 0x1;
00119             
00120             /* free memory for next message */
00121             led_q.free(cmd);
00122 
00123         }
00124         
00125     }
00126 }
00127 
00128 /**
00129  * @brief application demo task 
00130  */
00131 void disp_task(void) {
00132     osEvent evt;
00133     glcd_cmd_desc_t *gl;
00134  
00135     for(;;) {
00136         /* wait for a new command */
00137         evt = disp_q.get(osWaitForever);
00138         /* check if not corrupted */
00139         if(evt.status != osEventMail) continue;                
00140         gl = (glcd_cmd_desc_t *)evt.value.p;
00141         if(gl == NULL) continue;
00142         
00143         /* check consistency */
00144         //pc_serial.printf("## %3d \n\r", gl->x);
00145         //pc_serial.printf("## %2d \n\r", gl->y);
00146         //pc_serial.printf("## %s \n\r", gl->message);
00147 
00148         
00149         
00150         glcd.cls();
00151         /* set the glcd cursor */
00152         glcd.locate(gl->x * FONT_WIDTH,  gl->y * FONT_HEIGHT);        
00153         /* and prints the message */
00154         glcd.printf("%s", gl->message);
00155         
00156         disp_q.free(gl);
00157     }
00158 }
00159 
00160 
00161 
00162 
00163 /**
00164  * @brief thread_command interpreter
00165  */
00166 void shell_led_command(int argc, char **argv){
00167     led_cmd_desc_t *led_cmd = led_q.alloc();
00168 
00169     if(led_cmd == NULL) {
00170         pc_serial.printf("leds: FATAL! Not enough memory! \n\r");
00171         return;
00172     }
00173     if(argc < 1) {
00174         pc_serial.printf("## leds: too few arguments! \n\r");
00175         led_q.free(led_cmd);
00176         return;    
00177     }
00178     
00179     /* if has only one argument, the command can be  a color */
00180     if(argc == 1) {
00181         /* extract and limit the color value */
00182         sscanf(argv[0],"%d", &led_cmd->color);
00183         led_cmd->color &= 0x07;
00184         led_cmd->on_off = false;
00185         led_cmd->make_color = true;
00186     } else if(( argc > 1) && (argc <= 2)) {
00187         /* selects the led */
00188         if(strcmp("LED1", argv[0]) == 0) {
00189             led_cmd->led_nbr = 1;
00190         }else if(strcmp("LED2",argv[0]) == 0) {
00191             led_cmd->led_nbr = 2;            
00192         }else if(strcmp("LED3",argv[0]) == 0) {
00193             led_cmd->led_nbr = 3;
00194         }else if(strcmp("all",argv[0]) == 0) {
00195             led_cmd->led_nbr = 0;
00196         }else {
00197             pc_serial.printf("## leds: invalid led! \n\r");
00198             led_q.free(led_cmd);
00199             return;
00200         }
00201         
00202         
00203         /* take the action */
00204         if(strcmp("on", argv[1])== 0) {
00205             led_cmd->make_color = false;
00206             led_cmd->on_off = true;
00207         }else if (strcmp("off", argv[1])==0){
00208             led_cmd->make_color = false;
00209             led_cmd->on_off = false;
00210         } else {
00211             pc_serial.printf("## leds: invalid option! \n\r");
00212             led_q.free(led_cmd);
00213             return;
00214         }
00215     } else {
00216         pc_serial.printf("## leds: too many arguments! \n\r");
00217         led_q.free(led_cmd);
00218         return;
00219     }
00220     
00221     /* send the command descriptor to be executed in thread */
00222     led_q.put(led_cmd); 
00223     pc_serial.printf("## leds: running! \n\r");
00224 
00225 
00226 }
00227 
00228 /**
00229  * @brief parses the glcd commands 
00230  */
00231 static void shell_disp_command(int argc, char **argv){
00232     glcd_cmd_desc_t *gl = disp_q.alloc();
00233 
00234     memset(&gl->message,0, 64);
00235     
00236     int position_x = 0;
00237     int position_y = 0;    
00238     
00239     if(argc < 3) {
00240         pc_serial.printf("display: Too few arguments, exiting \n\r");
00241         disp_q.free(gl);
00242     } else {
00243         sscanf(argv[0], "%3d", &gl->x);
00244         sscanf(argv[1], "%2d", &gl->y);
00245 
00246         /* check position range */
00247         if(position_x > 127 || position_x < 0) {
00248             pc_serial.printf("## display: Invalid arguments, exiting");    
00249             disp_q.free(gl);            
00250             return;
00251         }
00252 
00253         if(position_y > 63 || position_y < 0) {
00254             pc_serial.printf("## display: Invalid arguments, exiting");    
00255             disp_q.free(gl);
00256             return;
00257         }
00258 
00259         /* rebuild the string */
00260         for(int i = 0; i < (argc - 2); i++) {
00261             strcat(&gl->message[0], argv[2 + i]);
00262             strcat(&gl->message[0],(const char *)" ");
00263         }
00264 
00265         
00266         /* check consistency */
00267         //pc_serial.printf("## %3d \n\r", gl->x);
00268         //pc_serial.printf("## %2d \n\r", gl->y);
00269         //pc_serial.printf("## %s \n\r", gl->message);
00270         
00271         /* sends the text command to lcd task */
00272         disp_q.put(gl);
00273     }
00274 }
00275 
00276 /**
00277  * @brief show help menu 
00278  */
00279 static void print_usage(void) {
00280     pc_serial.printf("## use with the syntax below:         \n\r");
00281     pc_serial.printf("## command <arg1> <arg2> ... <arg16>  \n\r");
00282     pc_serial.printf("## Available commands:                \n\r");
00283     pc_serial.printf ("## leds [LED1/2/3] [color1 -- 8] [on/off] : controls on board leds in multithread mode \n\r");
00284     pc_serial.printf ("## leds LED1 on                    : for example turns on led 1\n\r");
00285     pc_serial.printf ("## leds 5                          : for example show purple color \n\r"); 
00286     pc_serial.printf ("##\n\r");
00287     pc_serial.printf ("## disp <x>  <y> <message>         : prints a message on lcd \n\r"); 
00288     pc_serial.printf ("## disp 0 3 Hello world!           : prints hello world at 0 colunm and 3 row \n\r");      
00289 }
00290 
00291  
00292 /**
00293  * @brief parse the command received via comport
00294  */
00295 static void shell_parser (char *cmd, int size) {
00296     int cmd_ptr = 0;
00297     int arg_ptr = 0;
00298     int cmd_size = 0;
00299     char command_buffer[256];
00300     
00301     int argc = 0;
00302     char *argv[16];    
00303     
00304     /* copy to the root command */
00305     memset(&command_buffer, 0, sizeof(command_buffer)); 
00306     
00307     /* find the root command terminator (space) */
00308     while(cmd_ptr < size) {
00309         if(cmd[cmd_ptr] == ' ') break;
00310         cmd_ptr++;
00311     }
00312     cmd_size = size - cmd_ptr;
00313     
00314     
00315     /* extract command arguments */
00316     strncpy(&command_buffer[0], &cmd[cmd_ptr + 1], (size - cmd_ptr));    
00317     
00318     /* terminates the root command */
00319     cmd[cmd_ptr] = 0;
00320     arg_ptr = 0;
00321     
00322     //pc_serial.printf("## command: %s \n\r", cmd);
00323     //pc_serial.printf("## arguments: %s \n\r", command_buffer);
00324 
00325   
00326     /* extract the further arguments */
00327     while(arg_ptr < (cmd_size)) {
00328  
00329         argc++;
00330         *(argv + (argc- 1)) = &command_buffer[arg_ptr];
00331  
00332         /* find terminator */
00333         while(command_buffer[arg_ptr] != ' ') {
00334             arg_ptr++;
00335         }
00336         
00337         /* adds to argument list */
00338         command_buffer[arg_ptr] = 0;
00339         arg_ptr++;       
00340        // pc_serial.printf("## argument no: %d : %s \n\r", argc, argv[argc-1]);
00341     }
00342 
00343 
00344 
00345     /* finds and execute the command table */
00346     if(strcmp("leds", cmd) == 0) { 
00347         shell_led_command(argc, argv);
00348     } else if(strcmp("disp", cmd) == 0){
00349         shell_disp_command(argc, argv);
00350     } else {
00351         print_usage();
00352     }    
00353 
00354 }
00355 
00356 
00357 
00358 
00359 /**
00360  * @brief shell commands processing thread 
00361  */
00362 static void shell_task(void)
00363 {
00364     char serial_buffer[1024] = {0};
00365     int read_ptr = 0;
00366     const char msg[] = {"Welcome to NXP FTF !\0"};
00367  
00368     /* setup the serial as 115200 bps */
00369     pc_serial.baud(115200);
00370 
00371 /* setup our on-board glcd */
00372     glcd.set_contrast(0x35);
00373     glcd.cls();
00374 
00375    /* Center the LCD cursor based on message size*/
00376     glcd.locate(LCD_WIDTH - (sizeof(msg) * FONT_WIDTH), 
00377                     (LCD_HEIGHT - FONT_HEIGHT) / 2);
00378 
00379     
00380     /* prints a welcome message */
00381     glcd.printf(msg);
00382     
00383     glcd.cls();
00384     Thread::wait(1000);
00385     
00386   
00387     pc_serial.printf("******************************************************************\n\r");    
00388     pc_serial.printf("***         Welcome to NXP FTF Simple Shell application      ****\n\r");
00389     pc_serial.printf("*** Type some commands or just Enter key to see the available ****\n\r");
00390     pc_serial.printf("******************************************************************\n\r");            
00391     pc_serial.printf(">>");
00392     
00393     for(;;Thread::wait(50)) {        
00394         /* check if we have character available */
00395         if(pc_serial.readable()) {
00396             bool new_cmd = false;
00397             
00398             /* get the incoming character */
00399             char c = pc_serial.getc();
00400                        
00401             if( (c == '\n') || (c == '\r')) {
00402                 /* handle enter key */
00403                 new_cmd = true;
00404                 pc_serial.printf("\n\r");
00405                 
00406             }else if( (c == 0x7F) || (c == 0x08)){
00407                 /* handle backspace and del keys */
00408                 pc_serial.printf("\033[1D");
00409                 pc_serial.putc(' ');
00410                 pc_serial.printf("\033[1D");
00411                 
00412                 read_ptr--;
00413                 if(read_ptr < -1) read_ptr = 1023;
00414                 serial_buffer[read_ptr] = ' ';
00415 
00416                 
00417             } else {
00418                 /* loopback the pressed key */
00419                 pc_serial.putc(c);
00420                 
00421                 /* store the incoming character on command circular buffer */
00422                 serial_buffer[read_ptr] = c;
00423                 read_ptr = (read_ptr + 1) % 1024;
00424             }
00425             
00426             
00427             
00428             if(new_cmd != false) {
00429                 /* command arrived, has other characters? */
00430                 if(read_ptr != 0) {
00431                     shell_parser(&serial_buffer[0], read_ptr);
00432                 } else {
00433                     print_usage();
00434                 }
00435                 /* reset the buffer command */
00436                 memset(&serial_buffer, 0, sizeof(serial_buffer));
00437                 read_ptr = 0;
00438                 pc_serial.printf(">>");
00439             } 
00440 
00441         }        
00442     }
00443 }
00444 
00445 
00446 /**
00447  * @brief main application loop
00448  */
00449 int main(void) 
00450 {   
00451 
00452     glcd.cls();
00453 
00454     /* starts the shell task and applications task*/
00455     shell_thread.start(shell_task);   
00456     led_thread.start(led_task);
00457     disp_thread.start(disp_task);
00458     return 0;
00459 }