src/adxl345.c
author Tero Marttila <terom@paivola.fi>
Wed, 08 Oct 2014 23:20:34 +0300
changeset 11 a383e22204f2
permissions -rw-r--r--
adxl345: control/data registers read/write
#include "adxl345.h"

#include "spi.h"

#include <util/delay.h>

/*
 * SPI format
 */
enum adxl345_header_bits {
    ADXL345_READ        = 0b10000000,
    ADXL345_WRITE       = 0b00000000,

    ADXL345_MULTI       = 0b01000000,
};

enum adxl345_reg {
    ADXL345_DEVID       = 0x00,

    ADXL345_POWER_CTL   = 0x2D,

    ADXL345_DATA_FORMAT = 0x31,
    ADXL345_DATAX0      = 0x32,
    ADXL345_DATAX1      = 0x33,
    ADXL345_DATAY0      = 0x34,
    ADXL345_DATAY1      = 0x35,
    ADXL345_DATAZ0      = 0x36,
    ADXL345_DATAZ1      = 0x37,
};

enum adxl345_power_ctl {
    ADXL345_POWER_CTL_LINK          = 0b00100000,
    ADXL345_POWER_CTL_AUTO_SLEEP    = 0b00010000,
    ADXL345_POWER_CTL_MEASURE       = 0b00001000,
    ADXL345_POWER_CTL_SLEEP         = 0b00000100,
    ADXL345_POWER_CTL_WAKEUP        = 0b00000011,
};

enum adxl345_power_ctl_wakeup {
    ADXL345_POWER_CTL_WAKEUP_8      = 0b00000011,
    ADXL345_POWER_CTL_WAKEUP_4      = 0b00000001,
    ADXL345_POWER_CTL_WAKEUP_2      = 0b00000010,
    ADXL345_POWER_CTL_WAKEUP_1      = 0b00000000,
};

enum adxl345_data_format {
    ADXL345_DATA_FORMAT_SELF_TEST   = 0b10000000,
    ADXL345_DATA_FORMAT_SPI         = 0b01000000,
    ADXL345_DATA_FORMAT_INT_INVERT  = 0b00100000,
    ADXL345_DATA_FORMAT_FULL_RES    = 0b00001000,
    ADXL345_DATA_FORMAT_JUSTIFY     = 0b00000100,
    ADXL345_DATA_FORMAT_RANGE       = 0b00000011,
};

enum adxl345_data_format_range {
    ADXL345_DATA_FORMAT_RANGE_2G    = 0b00000000,
    ADXL345_DATA_FORMAT_RANGE_4G    = 0b00000001,
    ADXL345_DATA_FORMAT_RANGE_8G    = 0b00000010,
    ADXL345_DATA_FORMAT_RANGE_16G   = 0b00000011,
};

#define ADXL345_DDR DDRB
#define ADXL345_PORT PORTB
#define ADXL345_CS PORTB2

void adxl345_init ()
{
    // set CS pin
    sbi(&ADXL345_DDR,    ADXL345_CS);   // out
    sbi(&ADXL345_PORT,   ADXL345_CS);   // high (off)
}

static inline void adxl345_start ()
{
    cbi(&ADXL345_PORT,   ADXL345_CS);    // low (on)
    _delay_us(1);
}

static inline void adxl345_stop ()
{
    sbi(&ADXL345_PORT,   ADXL345_CS);    // high (off)
    _delay_us(100);
}

static void adxl345_write (enum adxl345_reg reg, byte value)
{
    adxl345_start();

    spi_readwrite(ADXL345_WRITE | reg);
    spi_readwrite(value);

    adxl345_stop();
}

static byte adxl345_read (enum adxl345_reg reg)
{
    byte value;

    adxl345_start();

    spi_readwrite(ADXL345_READ | reg);
    value = spi_readwrite(0);

    adxl345_stop();

    return value;
}

static int8_t adxl345_read_s8 (enum adxl345_reg reg)
{
    int8_t value = 0;

    adxl345_start();

    spi_readwrite(ADXL345_READ | ADXL345_MULTI | reg);
    value = spi_readwrite(0);

    adxl345_stop();

    return value;
}

static int16_t adxl345_read_s16 (enum adxl345_reg reg)
{
    char v0, v1;

    adxl345_start();

    spi_readwrite(ADXL345_READ | ADXL345_MULTI | reg);
    v0 = spi_readwrite(0);
    v1 = spi_readwrite(0);
    adxl345_stop();

    return ((int) v1 << 8) | (int) v0;
}

byte adxl345_read_devid ()
{
    return adxl345_read(ADXL345_DEVID);
}

void adxl345_setup ()
{
    adxl345_write(ADXL345_POWER_CTL,
            // enable measrurement mode
            ADXL345_POWER_CTL_MEASURE
    );

    /*
    adxl345_write(ADXL345_DATA_FORMAT,
            // self-test
            ADXL345_DATA_FORMAT_SELF_TEST
    );
    */
}

int16_t adxl345_read_x ()
{
    return adxl345_read_s16(ADXL345_DATAX0);
}

int16_t adxl345_read_y ()
{
    return adxl345_read_s16(ADXL345_DATAY0);
}

int16_t adxl345_read_z ()
{
    return adxl345_read_s16(ADXL345_DATAZ0);
}