Felipe Neves
/
ftf_mbed_lab4
ftf mbed os semaphores lab
main.cpp
- Committer:
- uLipe
- Date:
- 2016-11-06
- Revision:
- 0:30211b394890
File content as of revision 0:30211b394890:
/** * @brief NXP FTF LAB3 - Mbed OS Semaphore lab */ #include "mbed.h" #include "ST7567.h" #include "rtos.h" /* LCD screen dimensions */ #define LCD_HEIGHT 64 #define LCD_WIDTH 128 /* LCD font dimensions */ #define FONT_HEIGHT 10 #define FONT_WIDTH 5 /* defines the axis for acc */ #define ACC_NOOF_AXIS 3 /* defines the time of acquisition in ms */ #define ACC_SAMPLE_RATE 200 /* acc event flags */ #define ACC_EVENT 0x00000001 /* bmi160 slave address */ #define BMI160_ADDR ((0x68)<<1) /* bmi160 g conversion factor */ #define ACC_2G_SCALE_FACTOR (0.0000610f) /** Instance a on board GLCD object */ ST7567 glcd(D11, D13, D12, D9, D10); /* allocate statically stacks for the shell task */ unsigned char shell_stk[4096]; Thread shell_thread(osPriorityRealtime, 4096, &shell_stk[0]); /* thread for accelerometer and LCD */ unsigned char acc_stack[1024]; unsigned char lcd_stack[1024]; unsigned char align_stack[2048]; Thread acc_thread(osPriorityHigh, 1024 ,&acc_stack[0]); Thread lcd_thread(osPriorityNormal, 1024, &lcd_stack[0]); Thread align_thread(osPriorityRealtime, 2048, &align_stack[0]); /* semaphore to sync acc reading to lcd printing */ Semaphore acc_sema; Semaphore align_event_sema; /* buffer to store acc samples */ int16_t acc_sample_buffer[ACC_NOOF_AXIS] = {0x0, 0x0, 0x0}; uint8_t acc_status = 0; /** Instance a UART class to communicate with pc */ Serial pc_serial(USBTX,USBRX); /** * @brief accelerometer processing task */ static void acc_task(void) { I2C *imu_comm = new I2C(P2_3, P2_4); char i2c_reg_buffer[2] = {0}; /* setup the frequency */ imu_comm->frequency(20000); /* issue a sw reset */ i2c_reg_buffer[0] = 0x7E; i2c_reg_buffer[1] = 0xB6; imu_comm->write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); /* wait property time for device reset */ Thread::wait(200); /* enable the accelerometer */ i2c_reg_buffer[0] = 0x7E; i2c_reg_buffer[1] = 0x11; imu_comm->write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); /* sets the output data rate to 100 Hz */ i2c_reg_buffer[0] = 0x40; i2c_reg_buffer[1] = 0x28; imu_comm->write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); for(;;) { int err = 0; /* reads status register */ i2c_reg_buffer[0] = 0x1B; err = imu_comm->write(BMI160_ADDR, i2c_reg_buffer, 1, true); err = imu_comm->read(BMI160_ADDR, (char *)&acc_status, sizeof(acc_status), false); /* reads the acc register */ i2c_reg_buffer[0] = 0x12; err = imu_comm->write(BMI160_ADDR, i2c_reg_buffer, 1, true); err = imu_comm->read(BMI160_ADDR, (char *)&acc_sample_buffer, sizeof(acc_sample_buffer), false); /* notify a new reading */ acc_sema.release(); /* notify a align event */ align_event_sema.release(); Thread::wait(ACC_SAMPLE_RATE); } } static void align_event_task(void) { DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); float x,y,z; for(;;) { align_event_sema.wait(); /* new reading, check for event */ x = (float)acc_sample_buffer[0] * ACC_2G_SCALE_FACTOR; y = (float)acc_sample_buffer[1] * ACC_2G_SCALE_FACTOR; z = (float)acc_sample_buffer[2] * ACC_2G_SCALE_FACTOR; /* light led of correspondign axis alignment */ if(x > 0.90f || x < -0.90) { led1 = 0; } else { led1 = 1; } if(y > 0.90f || y < -0.90) { led2 = 0; }else { led2 = 1; } if(z > 0.90f || z < -0.90) { led3 = 0; }else { led3 = 1; } } } /** * @brief lcd update task */ static void lcd_task(void) { const char banner[] = {"FTF IMU demo\0"}; float x, y,z ; glcd.set_contrast(0x35); glcd.cls(); for(;;) { /* wait for accelerometer event */ acc_sema.wait(); /* format the readings */ x = (float)acc_sample_buffer[0] * ACC_2G_SCALE_FACTOR; y = (float)acc_sample_buffer[1] * ACC_2G_SCALE_FACTOR; z = (float)acc_sample_buffer[2] * ACC_2G_SCALE_FACTOR; glcd.locate((LCD_WIDTH - (sizeof(banner) * FONT_WIDTH))/2,1); glcd.printf(banner); /* new samples arrived, format and prints on lcd */ glcd.locate(0, FONT_HEIGHT * 2); glcd.printf("x axis: %f",x); glcd.locate(0, FONT_HEIGHT * 3); glcd.printf("y axis: %f",y); glcd.locate(0, FONT_HEIGHT * 4); glcd.printf("z axis: %f",z); glcd.locate(0, FONT_HEIGHT * 5); glcd.printf("acc status: 0x%x",acc_status); } } /** * @brief thread_command interpreter */ void shell_execute_command(int argc, char **argv){ } /** * @brief show help menu */ static void print_usage(void) { pc_serial.printf("## use with the syntax below: \n\r"); pc_serial.printf("## command <arg1> <arg2> ... <arg16> \n\r"); pc_serial.printf("## Available commands: \n\r"); } /** * @brief parse the command received via comport */ static void shell_parser (char *cmd, int size) { int cmd_ptr = 0; int arg_ptr = 0; int cmd_size = 0; char command_buffer[256]; int argc = 0; char *argv[16]; /* copy to the root command */ memset(&command_buffer, 0, sizeof(command_buffer)); /* find the root command terminator (space) */ while(cmd_ptr < size) { if(cmd[cmd_ptr] == ' ') break; cmd_ptr++; } cmd_size = size - cmd_ptr; /* extract command arguments */ strncpy(&command_buffer[0], &cmd[cmd_ptr + 1], (size - cmd_ptr)); /* terminates the root command */ cmd[cmd_ptr] = 0; arg_ptr = 0; //pc_serial.printf("## command: %s \n\r", cmd); //pc_serial.printf("## arguments: %s \n\r", command_buffer); /* extract the further arguments */ while(arg_ptr < (cmd_size)) { argc++; *(argv + (argc- 1)) = &command_buffer[arg_ptr]; /* find terminator */ while(command_buffer[arg_ptr] != ' ') { arg_ptr++; } /* adds to argument list */ command_buffer[arg_ptr] = 0; arg_ptr++; // pc_serial.printf("## argument no: %d : %s \n\r", argc, argv[argc-1]); } /* finds and execute the command table */ } /** * @brief shell commands processing thread */ static void shell_task(void) { char serial_buffer[1024] = {0}; int read_ptr = 0; const char msg[] = {"Welcome to NXP FTF !\0"}; /* setup the serial as 115200 bps */ pc_serial.baud(115200); /* setup our on-board glcd */ glcd.set_contrast(0x35); glcd.cls(); /* Center the LCD cursor based on message size*/ glcd.locate(LCD_WIDTH - (sizeof(msg) * FONT_WIDTH), (LCD_HEIGHT - FONT_HEIGHT) / 2); /* prints a welcome message */ glcd.printf(msg); glcd.cls(); Thread::wait(1000); pc_serial.printf("******************************************************************\n\r"); pc_serial.printf("*** Welcome to NXP FTF Simple Shell application ****\n\r"); pc_serial.printf("*** Type some commands or just Enter key to see the available ****\n\r"); pc_serial.printf("******************************************************************\n\r"); pc_serial.printf(">>"); for(;;Thread::wait(50)) { /* check if we have character available */ if(pc_serial.readable()) { bool new_cmd = false; /* get the incoming character */ char c = pc_serial.getc(); if( (c == '\n') || (c == '\r')) { /* handle enter key */ new_cmd = true; pc_serial.printf("\n\r"); }else if( (c == 0x7F) || (c == 0x08)){ /* handle backspace and del keys */ pc_serial.printf("\033[1D"); pc_serial.putc(' '); pc_serial.printf("\033[1D"); read_ptr--; if(read_ptr < -1) read_ptr = 1023; serial_buffer[read_ptr] = ' '; } else { /* loopback the pressed key */ pc_serial.putc(c); /* store the incoming character on command circular buffer */ serial_buffer[read_ptr] = c; read_ptr = (read_ptr + 1) % 1024; } if(new_cmd != false) { /* command arrived, has other characters? */ if(read_ptr != 0) { shell_parser(&serial_buffer[0], read_ptr); } else { print_usage(); } /* reset the buffer command */ memset(&serial_buffer, 0, sizeof(serial_buffer)); read_ptr = 0; pc_serial.printf(">>"); } } } } /** * @brief main application loop */ int main(void) { glcd.cls(); /* starts the shell task and applications task*/ shell_thread.start(shell_task); acc_thread.start(acc_task); lcd_thread.start(lcd_task); align_thread.start(align_event_task); return 0; }