ftf mbed os semaphores lab

Dependencies:   ST7567

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;
}