APP 1 S5.

Dependencies:   mbed

APP.cpp

Committer:
vinbel93
Date:
2016-01-12
Revision:
14:d48d869ed365
Parent:
13:08ef55cd14c6

File content as of revision 14:d48d869ed365:

// APP.cpp
// Vincent Belanger - belv1802
// Jeremy Pare      - parj2713

#include <math.h>
#include <stdint.h>

#include "mbed.h"
#include "APP.h"


static I2C    i2c(p28, p27);
static Serial uart(p9, p10);

void setup()
{
    // Setup UART and I2C.
    uart.format(8, Serial::None, 1);
    uart.baud(9600);
    i2c.frequency(100000);
 
    // Clear display
    uart.putc(0x76);
 
    // Decimal point for display
    uart.putc(0x77);
    uart.putc(0x02);
 
    // Maximum brightness
    uart.putc(0x7A);
    uart.putc(0xFF);
}
 
void activateAccelerometer()
{
    uint8_t data[2] = {CTRL_REG, 0x01};
    i2c.write(ACC_ADDRESS, (char*) data, 2);
}
 
uint8_t readStatus()
{
    uint8_t result[1];
    uint8_t reg[1] = {STATUS_REG};
    i2c.write(ACC_ADDRESS, (char*) reg, 1, true);
    i2c.read(ACC_ADDRESS, (char*) result, 1);
 
    return result[0];
}    
 
int16_t convertToAcceleration(uint8_t hi, uint8_t lo)
{
    int16_t value = (lo >> 2) | (hi << 6);
    if (value > UINT14_MAX/2)
    {
        value -= UINT14_MAX;
    }
 
    return value;
}
 
int16_t readAndComputeAngle()
{
    uint8_t result[6];
    uint8_t reg[1] = {ACC_X_REG};
    i2c.write(ACC_ADDRESS, (char*) reg, 1, true);
    i2c.read(ACC_ADDRESS, (char*) result, 6);
    int16_t accX = convertToAcceleration(result[0], result[1]);
    int16_t accY = convertToAcceleration(result[2], result[3]);
    int16_t accZ = convertToAcceleration(result[4], result[5]);

    float angle = acos((float) accZ / sqrt((float) accX*accX + accY*accY + accZ*accZ)) * 180.0 / PI;
 
    // To use integer operations instead of floating-point arithmetic, the angle is multiplied by 100.
    // This allows for two decimals of precision on the display.
    int16_t angleHundreds = angle * 100;
    if (angleHundreds > 9000)
    {
        angleHundreds = 18000 - angleHundreds;
    }
 
    return angleHundreds;
}
 
void updateDisplay(int16_t angle)
{
    uint8_t digits[4];
    sprintf((char*) digits, "%d", angle);

    if (angle < 100)
    {
        uart.putc('0');
        uart.putc('0');
        uart.putc(digits[0]);
        uart.putc(digits[1]);
    }
    else if (angle < 1000)
    {
        uart.putc('0');
        uart.putc(digits[0]);
        uart.putc(digits[1]);
        uart.putc(digits[2]);
    }
    else
    {
        uart.putc(digits[0]);
        uart.putc(digits[1]);
        uart.putc(digits[2]);
        uart.putc(digits[3]);
    }
}
 
int32_t main()
{
    setup();
    activateAccelerometer();
 
    while (true)
    {
        // Read bit 3 from the status register
        int8_t status = (readStatus() >> 3) & 0x01;
 
        if (status == 1)
        {
            // Get accelerations, compute angle
            uint16_t angle = readAndComputeAngle();
 
            // Update 7 segment display
            updateDisplay(angle);
        }
 
        wait(0.4);
    }
}