Felipe Neves
/
ftf_mbed_lab4
ftf mbed os semaphores lab
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /** 00002 * @brief NXP FTF LAB3 - Mbed OS Semaphore lab 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 /* defines the axis for acc */ 00019 #define ACC_NOOF_AXIS 3 00020 00021 /* defines the time of acquisition in ms */ 00022 #define ACC_SAMPLE_RATE 200 00023 00024 /* acc event flags */ 00025 #define ACC_EVENT 0x00000001 00026 00027 /* bmi160 slave address */ 00028 #define BMI160_ADDR ((0x68)<<1) 00029 00030 /* bmi160 g conversion factor */ 00031 #define ACC_2G_SCALE_FACTOR (0.0000610f) 00032 00033 00034 00035 /** Instance a on board GLCD object */ 00036 ST7567 glcd(D11, D13, D12, D9, D10); 00037 00038 00039 /* allocate statically stacks for the shell task */ 00040 unsigned char shell_stk[4096]; 00041 Thread shell_thread(osPriorityRealtime, 4096, &shell_stk[0]); 00042 00043 /* thread for accelerometer and LCD */ 00044 unsigned char acc_stack[1024]; 00045 unsigned char lcd_stack[1024]; 00046 unsigned char align_stack[2048]; 00047 Thread acc_thread(osPriorityHigh, 1024 ,&acc_stack[0]); 00048 Thread lcd_thread(osPriorityNormal, 1024, &lcd_stack[0]); 00049 Thread align_thread(osPriorityRealtime, 2048, &align_stack[0]); 00050 00051 /* semaphore to sync acc reading to lcd printing */ 00052 Semaphore acc_sema; 00053 Semaphore align_event_sema; 00054 00055 /* buffer to store acc samples */ 00056 int16_t acc_sample_buffer[ACC_NOOF_AXIS] = {0x0, 0x0, 0x0}; 00057 uint8_t acc_status = 0; 00058 00059 00060 /** Instance a UART class to communicate with pc */ 00061 Serial pc_serial(USBTX,USBRX); 00062 00063 00064 /** 00065 * @brief accelerometer processing task 00066 */ 00067 static void acc_task(void) { 00068 I2C *imu_comm = new I2C(P2_3, P2_4); 00069 char i2c_reg_buffer[2] = {0}; 00070 00071 /* setup the frequency */ 00072 imu_comm->frequency(20000); 00073 00074 /* issue a sw reset */ 00075 i2c_reg_buffer[0] = 0x7E; 00076 i2c_reg_buffer[1] = 0xB6; 00077 imu_comm->write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); 00078 00079 /* wait property time for device reset */ 00080 Thread::wait(200); 00081 00082 /* enable the accelerometer */ 00083 i2c_reg_buffer[0] = 0x7E; 00084 i2c_reg_buffer[1] = 0x11; 00085 imu_comm->write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); 00086 00087 /* sets the output data rate to 100 Hz */ 00088 i2c_reg_buffer[0] = 0x40; 00089 i2c_reg_buffer[1] = 0x28; 00090 imu_comm->write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); 00091 00092 for(;;) { 00093 int err = 0; 00094 00095 /* reads status register */ 00096 i2c_reg_buffer[0] = 0x1B; 00097 err = imu_comm->write(BMI160_ADDR, i2c_reg_buffer, 1, true); 00098 err = imu_comm->read(BMI160_ADDR, (char *)&acc_status, sizeof(acc_status), false); 00099 00100 /* reads the acc register */ 00101 i2c_reg_buffer[0] = 0x12; 00102 err = imu_comm->write(BMI160_ADDR, i2c_reg_buffer, 1, true); 00103 err = imu_comm->read(BMI160_ADDR, (char *)&acc_sample_buffer, sizeof(acc_sample_buffer), false); 00104 /* notify a new reading */ 00105 acc_sema.release(); 00106 /* notify a align event */ 00107 align_event_sema.release(); 00108 Thread::wait(ACC_SAMPLE_RATE); 00109 } 00110 } 00111 00112 00113 static void align_event_task(void) 00114 { 00115 DigitalOut led1(LED1); 00116 DigitalOut led2(LED2); 00117 DigitalOut led3(LED3); 00118 00119 float x,y,z; 00120 00121 for(;;) { 00122 align_event_sema.wait(); 00123 00124 /* new reading, check for event */ 00125 x = (float)acc_sample_buffer[0] * ACC_2G_SCALE_FACTOR; 00126 y = (float)acc_sample_buffer[1] * ACC_2G_SCALE_FACTOR; 00127 z = (float)acc_sample_buffer[2] * ACC_2G_SCALE_FACTOR; 00128 00129 /* light led of correspondign axis alignment */ 00130 if(x > 0.90f || x < -0.90) { 00131 led1 = 0; 00132 } else { 00133 led1 = 1; 00134 } 00135 if(y > 0.90f || y < -0.90) { 00136 led2 = 0; 00137 00138 }else { 00139 led2 = 1; 00140 00141 } 00142 if(z > 0.90f || z < -0.90) { 00143 led3 = 0; 00144 00145 }else { 00146 led3 = 1; 00147 } 00148 00149 } 00150 00151 } 00152 00153 00154 /** 00155 * @brief lcd update task 00156 */ 00157 static void lcd_task(void) { 00158 const char banner[] = {"FTF IMU demo\0"}; 00159 float x, y,z ; 00160 00161 00162 glcd.set_contrast(0x35); 00163 glcd.cls(); 00164 00165 for(;;) { 00166 /* wait for accelerometer event */ 00167 acc_sema.wait(); 00168 00169 /* format the readings */ 00170 x = (float)acc_sample_buffer[0] * ACC_2G_SCALE_FACTOR; 00171 y = (float)acc_sample_buffer[1] * ACC_2G_SCALE_FACTOR; 00172 z = (float)acc_sample_buffer[2] * ACC_2G_SCALE_FACTOR; 00173 00174 00175 glcd.locate((LCD_WIDTH - (sizeof(banner) * FONT_WIDTH))/2,1); 00176 glcd.printf(banner); 00177 00178 00179 /* new samples arrived, format and prints on lcd */ 00180 glcd.locate(0, FONT_HEIGHT * 2); 00181 glcd.printf("x axis: %f",x); 00182 00183 glcd.locate(0, FONT_HEIGHT * 3); 00184 glcd.printf("y axis: %f",y); 00185 00186 glcd.locate(0, FONT_HEIGHT * 4); 00187 glcd.printf("z axis: %f",z); 00188 00189 glcd.locate(0, FONT_HEIGHT * 5); 00190 glcd.printf("acc status: 0x%x",acc_status); 00191 00192 } 00193 } 00194 00195 00196 00197 /** 00198 * @brief thread_command interpreter 00199 */ 00200 void shell_execute_command(int argc, char **argv){ 00201 00202 00203 } 00204 00205 00206 /** 00207 * @brief show help menu 00208 */ 00209 static void print_usage(void) { 00210 pc_serial.printf("## use with the syntax below: \n\r"); 00211 pc_serial.printf("## command <arg1> <arg2> ... <arg16> \n\r"); 00212 pc_serial.printf("## Available commands: \n\r"); 00213 } 00214 00215 00216 /** 00217 * @brief parse the command received via comport 00218 */ 00219 static void shell_parser (char *cmd, int size) { 00220 int cmd_ptr = 0; 00221 int arg_ptr = 0; 00222 int cmd_size = 0; 00223 char command_buffer[256]; 00224 00225 int argc = 0; 00226 char *argv[16]; 00227 00228 /* copy to the root command */ 00229 memset(&command_buffer, 0, sizeof(command_buffer)); 00230 00231 /* find the root command terminator (space) */ 00232 while(cmd_ptr < size) { 00233 if(cmd[cmd_ptr] == ' ') break; 00234 cmd_ptr++; 00235 } 00236 cmd_size = size - cmd_ptr; 00237 00238 00239 /* extract command arguments */ 00240 strncpy(&command_buffer[0], &cmd[cmd_ptr + 1], (size - cmd_ptr)); 00241 00242 /* terminates the root command */ 00243 cmd[cmd_ptr] = 0; 00244 arg_ptr = 0; 00245 00246 //pc_serial.printf("## command: %s \n\r", cmd); 00247 //pc_serial.printf("## arguments: %s \n\r", command_buffer); 00248 00249 00250 /* extract the further arguments */ 00251 while(arg_ptr < (cmd_size)) { 00252 00253 argc++; 00254 *(argv + (argc- 1)) = &command_buffer[arg_ptr]; 00255 00256 /* find terminator */ 00257 while(command_buffer[arg_ptr] != ' ') { 00258 arg_ptr++; 00259 } 00260 00261 /* adds to argument list */ 00262 command_buffer[arg_ptr] = 0; 00263 arg_ptr++; 00264 // pc_serial.printf("## argument no: %d : %s \n\r", argc, argv[argc-1]); 00265 } 00266 00267 00268 00269 /* finds and execute the command table */ 00270 } 00271 00272 00273 00274 00275 /** 00276 * @brief shell commands processing thread 00277 */ 00278 static void shell_task(void) 00279 { 00280 char serial_buffer[1024] = {0}; 00281 int read_ptr = 0; 00282 const char msg[] = {"Welcome to NXP FTF !\0"}; 00283 00284 /* setup the serial as 115200 bps */ 00285 pc_serial.baud(115200); 00286 00287 /* setup our on-board glcd */ 00288 glcd.set_contrast(0x35); 00289 glcd.cls(); 00290 00291 /* Center the LCD cursor based on message size*/ 00292 glcd.locate(LCD_WIDTH - (sizeof(msg) * FONT_WIDTH), 00293 (LCD_HEIGHT - FONT_HEIGHT) / 2); 00294 00295 00296 /* prints a welcome message */ 00297 glcd.printf(msg); 00298 00299 glcd.cls(); 00300 Thread::wait(1000); 00301 00302 00303 pc_serial.printf("******************************************************************\n\r"); 00304 pc_serial.printf("*** Welcome to NXP FTF Simple Shell application ****\n\r"); 00305 pc_serial.printf("*** Type some commands or just Enter key to see the available ****\n\r"); 00306 pc_serial.printf("******************************************************************\n\r"); 00307 pc_serial.printf(">>"); 00308 00309 for(;;Thread::wait(50)) { 00310 /* check if we have character available */ 00311 if(pc_serial.readable()) { 00312 bool new_cmd = false; 00313 00314 /* get the incoming character */ 00315 char c = pc_serial.getc(); 00316 00317 if( (c == '\n') || (c == '\r')) { 00318 /* handle enter key */ 00319 new_cmd = true; 00320 pc_serial.printf("\n\r"); 00321 00322 }else if( (c == 0x7F) || (c == 0x08)){ 00323 /* handle backspace and del keys */ 00324 pc_serial.printf("\033[1D"); 00325 pc_serial.putc(' '); 00326 pc_serial.printf("\033[1D"); 00327 00328 read_ptr--; 00329 if(read_ptr < -1) read_ptr = 1023; 00330 serial_buffer[read_ptr] = ' '; 00331 00332 00333 } else { 00334 /* loopback the pressed key */ 00335 pc_serial.putc(c); 00336 00337 /* store the incoming character on command circular buffer */ 00338 serial_buffer[read_ptr] = c; 00339 read_ptr = (read_ptr + 1) % 1024; 00340 } 00341 00342 00343 00344 if(new_cmd != false) { 00345 /* command arrived, has other characters? */ 00346 if(read_ptr != 0) { 00347 shell_parser(&serial_buffer[0], read_ptr); 00348 } else { 00349 print_usage(); 00350 } 00351 /* reset the buffer command */ 00352 memset(&serial_buffer, 0, sizeof(serial_buffer)); 00353 read_ptr = 0; 00354 pc_serial.printf(">>"); 00355 } 00356 00357 } 00358 } 00359 } 00360 00361 /** 00362 * @brief main application loop 00363 */ 00364 int main(void) 00365 { 00366 00367 glcd.cls(); 00368 00369 /* starts the shell task and applications task*/ 00370 shell_thread.start(shell_task); 00371 acc_thread.start(acc_task); 00372 lcd_thread.start(lcd_task); 00373 align_thread.start(align_event_task); 00374 00375 return 0; 00376 }
Generated on Sat Jul 16 2022 20:37:13 by 1.7.2