Felipe Neves
/
ftf_mbed_lab5
ftf connects queue lab
Embed:
(wiki syntax)
Show/hide line numbers
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 }
Generated on Fri Jul 15 2022 13:58:21 by 1.7.2