ftf mbed os semaphores 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 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 }