ftf mbed os semaphores lab

Dependencies:   ST7567

Revision:
0:30211b394890
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Nov 06 00:56:46 2016 +0000
@@ -0,0 +1,376 @@
+/**
+ *  @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;
+}