Commit fee3d141 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

lsm303c: unified minimalistic driver for both accelerometer and compass

parent 93ba0e61
......@@ -35,7 +35,7 @@ static void spi_init()
GPIO_PinModeSet(gpioPortD, 4, gpioModeInput, 0); /* Mag drdy */
}
void spi_send(uint8_t dev, uint8_t adr, uint8_t dat)
int spi_send(uint8_t dev, uint8_t adr, uint8_t dat)
{
USART_TypeDef *spi = SPI_USART;
......@@ -59,10 +59,12 @@ void spi_send(uint8_t dev, uint8_t adr, uint8_t dat)
/* both CS up */
GPIO_PinOutSet(gpioPortC, ACC_CS_PIN);
GPIO_PinOutSet(gpioPortC, MAG_CS_PIN);
return LSM303_SUCCESS;
}
/* read byte from given a address */
uint8_t spi_read(uint8_t dev, uint8_t adr)
int spi_read(uint8_t dev, uint8_t adr, uint8_t *dat)
{
USART_TypeDef *spi = SPI_USART;
......@@ -96,19 +98,260 @@ uint8_t spi_read(uint8_t dev, uint8_t adr)
GPIO_PinOutSet(gpioPortC, ACC_CS_PIN);
GPIO_PinOutSet(gpioPortC, MAG_CS_PIN);
return spi->RXDATA & 0xff;
*dat = (spi->RXDATA & 0xff);
return LSM303_SUCCESS;
}
/************************************************/
/* LSM303C stuff */
/* LSM303 stuff */
/************************************************/
int lsm303_init()
{
spi_init();
/*setup 3-wire SPI for Accelerometer & Magnetometer*/
LSM303C_ACC_SerialInterfaceMode(LSM303C_ACC_SIM_3WIRE_INTERFACE);
//LSM303_ACC_SerialInterfaceMode(LSM303_ACC_SIM_3WIRE_INTERFACE);
lsm303_serialmode(DEV_ACC, LSM303_ACC_3WIRE);
//lsm303_serialmode(DEV_MAG, LSM303_ACC_3WIRE);
lsm303_enableaxis(DEV_ACC, 0x7);
lsm303_fifo_mode(DEV_ACC, LSM303_FMODE_BYPASS, 1);
lsm303_fifo_mode(DEV_ACC, LSM303_FMODE_BYPASS, 0);
lsm303_odr(DEV_ACC, LSM303_ACC_ODR_10_Hz);
return LSM303_SUCCESS;
}
/* dev: DEV_ACC/DEV_MAG
* en: 1->enable; 0->disable
* dir: 1->positive; 0->negative (for ACC) */
int lsm303_selftest(int dev, int en, int dir)
{
uint8_t val;
if( (dev==DEV_ACC && !spi_read(dev, LSM303_CTRL5, &val)) ||
(dev==DEV_MAG && !spi_read(dev, LSM303_CTRL1, &val)) )
return LSM303_ERROR;
val &= ~( dev==DEV_ACC ? LSM303_ACC_ST_MASK : LSM303_MAG_ST_MASK );
if (dev==DEV_ACC && en && dir)
val |= LSM303_ACC_ST_POS;
else if (dev==DEV_ACC && en && !dir)
val |= LSM303_ACC_ST_NEG;
else if (dev==DEV_MAG && en)
val |= LSM303_MAG_ST_EN;
if( (dev==DEV_ACC && !spi_send(dev, LSM303_CTRL5, val)) ||
(dev==DEV_MAG && !spi_send(dev, LSM303_CTRL1, val)) )
return LSM303_ERROR;
return LSM303_SUCCESS;
}
/* Set output data rate
* dev: DEV_ACC/DEV_MAG
* odr: appropriate constant from lsm303.h */
int lsm303_odr(int dev, LSM303_ODR_t odr)
{
uint8_t val;
if (!spi_read(dev, LSM303_CTRL1, &val))
return LSM303_ERROR;
val &= ~( dev==DEV_ACC ? LSM303_ACC_ODR_MASK : LSM303_MAG_ODR_MASK );
val |= odr;
if (!spi_send(dev, LSM303_CTRL1, val))
return LSM303_ERROR;
return LSM303_SUCCESS;
}
/* set operation mode
* dev: DEV_ACC/DEV_MAG
* opm: constant from lsm303.h */
int lsm303_opmode(int dev, LSM303_OPM_t opm)
{
uint8_t val;
if (!spi_read(dev, LSM303_CTRL1, &val))
return LSM303_ERROR;
val &= ~( dev==DEV_ACC ? LSM303_ACC_OPM_MASK : LSM303_MAG_OPM_MASK );
val |= opm;
if( !spi_send(dev, LSM303_CTRL1, val) )
return LSM303_ERROR;
return LSM303_SUCCESS;
}
/* soft reset
* dev: DEV_ACC/DEV_MAG
* hard: 1-> reboot, 0-> soft reset */
int lsm303_rst(int dev, int hard)
{
uint8_t val;
if( (dev==DEV_ACC && !hard && !spi_read(dev, LSM303_CTRL5, &val)) ||
(dev==DEV_ACC && hard && !spi_read(dev, LSM303_CTRL6, &val)) ||
(dev==DEV_MAG && !spi_read(dev, LSM303_CTRL2, &val)) )
return LSM303_ERROR;
if( hard )
val |= (dev==DEV_ACC ? LSM303_ACC_REBOOT : LSM303_MAG_REBOOT);
else
val |= (dev==DEV_ACC ? LSM303_ACC_SRST : LSM303_MAG_SRST);
if( (dev==DEV_ACC && !hard && !spi_send(dev, LSM303_CTRL5, val)) ||
(dev==DEV_ACC && hard && !spi_send(dev, LSM303_CTRL6, val)) ||
(dev==DEV_MAG && !spi_send(dev, LSM303_CTRL2, val)) )
return LSM303_ERROR;
return LSM303_SUCCESS;
}
/* temperature readout */
int lsm303_temp(int16_t *temp)
{
uint8_t val;
*temp = 0;
/*enable temp sensor*/
if( !spi_read(DEV_MAG, LSM303_CTRL1, &val) )
return LSM303_ERROR;
val |= LSM303_MAG_TEMP_EN;
if( !spi_send(DEV_MAG, LSM303_CTRL1, val) )
return LSM303_ERROR;
/*read temperature*/
if( !spi_read(DEV_MAG, LSM303_MAG_TEMP_L, &val) )
return LSM303_ERROR;
*temp = (int16_t)val;
if( !spi_read(DEV_MAG, LSM303_MAG_TEMP_H, &val) )
return LSM303_ERROR;
*temp |= ((int16_t)val << 8) & 0xFF00;
/*disable temp sensor*/
if( !spi_read(DEV_MAG, LSM303_CTRL1, &val) )
return LSM303_ERROR;
val &= ~LSM303_MAG_TEMP_EN;
if( !spi_send(DEV_MAG, LSM303_CTRL1, val) )
return LSM303_ERROR;
return LSM303_SUCCESS;
}
int lsm303_fullscale(int dev, LSM303_FS_t fs)
{
uint8_t val;
/*check if _fs_ for proper device*/
if( (dev==DEV_ACC && !(LSM303_ACC_FS_MASK & fs)) ||
(dev==DEV_MAG && !(LSM303_MAG_FS_MASK & fs)) )
return LSM303_ERROR;
if( (dev==DEV_ACC && !spi_read(dev, LSM303_CTRL4, &val)) ||
(dev==DEV_MAG && !spi_read(dev, LSM303_CTRL2, &val)) )
return LSM303_ERROR;
val &= ~(dev==DEV_ACC ? LSM303_ACC_FS_MASK : LSM303_MAG_FS_MASK);
val |= fs;
if( (dev==DEV_ACC && !spi_send(dev, LSM303_CTRL4, val)) ||
(dev==DEV_MAG && !spi_send(dev, LSM303_CTRL2, val)) )
return LSM303_ERROR;
return LSM303_SUCCESS;
}
int lsm303_serialmode(int dev, LSM303_SMODE_t mode)
{
uint8_t val;
if( (dev==DEV_ACC && !spi_read(dev, LSM303_CTRL4, &val)) ||
(dev==DEV_MAG && !spi_read(dev, LSM303_CTRL3, &val)) )
return LSM303_ERROR;
val &= ~(dev==DEV_ACC ? LSM303_ACC_3WIRE : LSM303_MAG_3WIRE);
val |= mode;
if( (dev==DEV_ACC && !spi_send(dev, LSM303_CTRL4, val)) ||
(dev==DEV_MAG && !spi_send(dev, LSM303_CTRL3, val)) )
return LSM303_ERROR;
return LSM303_SUCCESS;
}
int lsm303_enableaxis(int dev, int mask)
{
uint8_t val;
if( dev == DEV_MAG )
return LSM303_ERROR;
if(!spi_read(dev, LSM303_CTRL1, &val))
return LSM303_ERROR;
val &= ~LSM303_ACC_AXIS_MASK;
val |= mask;
if(!spi_send(dev, LSM303_CTRL1, val))
return LSM303_ERROR;
return LSM303_SUCCESS;
}
int lsm303_fifo_mode(int dev, LSM303_FMODE_t mode, int en)
{
uint8_t val;
if(dev==DEV_MAG)
return LSM303_ERROR;
/*first enable/disable fifo*/
if(!spi_read(dev, LSM303_CTRL3, &val))
return LSM303_ERROR;
if(en)
val |= LSM303_FIFO_EN;
else
val &= ~LSM303_FIFO_EN;
if(!spi_send(dev, LSM303_CTRL3, val))
return LSM303_ERROR;
/* don't set mode if FIFO disabled */
if(!en) return LSM303_SUCCESS;
/*now set the mode*/
if(!spi_read(dev, LSM303_ACC_FIFO_CTRL, &val))
return LSM303_ERROR;
val &= ~LSM303_FMODE_MASK;
val |= mode;
if(!spi_send(dev, LSM303_ACC_FIFO_CTRL, val))
return LSM303_ERROR;
return LSM303_SUCCESS;
}
int lsm303_get_sample(int dev, int16_t *x, int16_t *y, int16_t *z)
{
uint8_t val_l, val_h;
if( !spi_read(dev, LSM303_OUT_X_L, &val_l) ||
!spi_read(dev, LSM303_OUT_X_H, &val_h) )
return LSM303_ERROR;
*x = (int16_t) ((val_h << 8) | val_l);
if( !spi_read(dev, LSM303_OUT_Y_L, &val_l) ||
!spi_read(dev, LSM303_OUT_Y_H, &val_h) )
return LSM303_ERROR;
*y = (int16_t) ((val_h << 8) | val_l);
if( !spi_read(dev, LSM303_OUT_Z_L, &val_l) ||
!spi_read(dev, LSM303_OUT_Z_H, &val_h) )
return LSM303_ERROR;
*z = (int16_t) ((val_h << 8) | val_l);
return LSM303_SUCCESS;
}
......@@ -2,8 +2,8 @@
#define __LSM303C_H__
#include <em_device.h>
#include "LSM303C_ACC_driver.h"
#include "LSM303C_MAG_driver.h"
//#include "LSM303C_ACC_driver.h"
//#include "LSM303C_MAG_driver.h"
#define HFRCO_FREQUENCY 14000000
#define SPI_PERCLK_FREQUENCY HFRCO_FREQUENCY
......@@ -15,52 +15,148 @@
#define ACC_CS_PIN 8
#define MAG_CS_PIN 10
#define LSM303_SUCCESS 0
#define LSM303_ERROR -1
#define LSM303_SUCCESS 1
#define LSM303_ERROR 0
#define DEV_ACC 0
#define DEV_MAG 1
/* Accelerometer & Magnetometer registers */
//#define LSM303_ACC_TEMP_L 0x0B
//#define LSM303_ACC_TEMP_H 0x0C
#define LSM303_ACC_ACT_TSH 0x1E
#define LSM303_ACC_ACT_DUR 0x1F
#define LSM303_WHO_AM_I_REG 0x0F
#define LSM303_CTRL1 0x20
#define LSM303_CTRL2 0x21
#define LSM303_CTRL3 0x22
#define LSM303_CTRL4 0x23
#define LSM303_CTRL5 0x24
#define LSM303_CTRL6 0x25 /* ACC only */
#define LSM303_CTRL7 0x26 /* ACC only */
#define LSM303_STATUS 0x27
#define LSM303_OUT_X_L 0x28
#define LSM303_OUT_X_H 0x29
#define LSM303_OUT_Y_L 0x2A
#define LSM303_OUT_Y_H 0x2B
#define LSM303_OUT_Z_L 0x2C
#define LSM303_OUT_Z_H 0x2D
#define LSM303_ACC_FIFO_CTRL 0x2E /* ACC only */
#define LSM303_ACC_FIFO_SRC 0x2F /* ACC only */
#define LSM303_MAG_TEMP_L 0x2E /* MAG only */
#define LSM303_MAG_TEMP_H 0x2F /* MAG only */
#define LSM303_INT1_CFG 0x30
#define LSM303_INT1_SRC 0x31
#define LSM303_INT1_THS_X 0x32
#define LSM303_INT1_THS_Y 0x33
#define LSM303_INT1_THS_Z 0x34
#define LSM303_INT1_DUR 0x35
#define LSM303_INT2_CFG 0x36 /* ACC only */
#define LSM303_INT2_SRC 0x37 /* ACC only */
#define LSM303_INT2_THS 0x38 /* ACC only */
#define LSM303_INT2_DUR 0x39 /* ACC only */
#define LSM303_XREF_L 0x3A /* ACC only */
#define LSM303_XREF_H 0x3B /* ACC only */
#define LSM303_YREF_L 0x3C /* ACC only */
#define LSM303_YREF_H 0x3D /* ACC only */
#define LSM303_ZREF_L 0x3E /* ACC only */
#define LSM303_ZREF_H 0x3F /* ACC only */
/* Accelerometer config */
#define LSM303_ACC_ST_MASK 0x0C
#define LSM303_ACC_ST_POS 0x04
#define LSM303_ACC_ST_NEG 0x08
#define LSM303_ACC_REBOOT 0x80
#define LSM303_FIFO_EN 0x80
typedef enum {
LSM303_ACC_ODR_PDOWN = 0x00,
LSM303_ACC_ODR_10_Hz = 0x10,
LSM303_ACC_ODR_50_Hz = 0x20,
LSM303_ACC_ODR_100_Hz = 0x30,
LSM303_ACC_ODR_200_Hz = 0x40,
LSM303_ACC_ODR_400_Hz = 0x50,
LSM303_ACC_ODR_800_Hz = 0x60,
LSM303_ACC_ODR_MASK = 0x60,
LSM303_MAG_ODR_0_625_Hz = 0x00,
LSM303_MAG_ODR_1_25_Hz = 0x04,
LSM303_MAG_ODR_2_5_Hz = 0x08,
LSM303_MAG_ODR_5_Hz = 0x0C,
LSM303_MAG_ODR_10_Hz = 0x10,
LSM303_MAG_ODR_20_Hz = 0x14,
LSM303_MAG_ODR_40_Hz = 0x18,
LSM303_MAG_ODR_80_Hz = 0x1C,
LSM303_MAG_ODR_MASK = 0x1C
} LSM303_ODR_t;
typedef enum {
LSM303_ACC_OPM_NORM = 0x00,
LSM303_ACC_OPM_HIGH = 0x80,
LSM303_ACC_OPM_MASK = 0x80,
LSM303_MAG_OPM_LOW = 0x00,
LSM303_MAG_OPM_MED = 0x20,
LSM303_MAG_OPM_HIGH = 0x40,
LSM303_MAG_OPM_UHIGH= 0x60,
LSM303_MAG_OPM_MASK = 0x60
} LSM303_OPM_t;
#define LSM303_ACC_SRST 0x40
#define LSM303_MAG_SRST 0x04
typedef enum {
LSM303_2G = 0x00,
LSM303_4G = 0x20,
LSM303_8G = 0x30,
LSM303_ACC_FS_MASK = 0x30,
LSM303_4Ga = 0x00,
LSM303_8Ga = 0x20,
LSM303_12Ga= 0x40,
LSM303_16Ga= 0x60,
LSM303_MAG_FS_MASK = 0x60
} LSM303_FS_t;
typedef enum {
LSM303_ACC_4WIRE = 0x00,
LSM303_MAG_4WIRE = 0x00,
LSM303_ACC_3WIRE = 0x01,
LSM303_MAG_3WIRE = 0x04
} LSM303_SMODE_t;
typedef enum {
LEM303_ACC_XEN = 0x01,
LSM303_ACC_YEN = 0x02,
LSM303_ACC_ZEN = 0x04,
LSM303_ACC_AXIS_MASK = 0x07
} LSM303_ENAXIS_t;
typedef enum {
LSM303_FMODE_BYPASS = 0x00,
LSM303_FMODE_STOP_WHEN_FULL = 0x20,
LSM303_FMODE_STREAM = 0x40,
LSM303_FMODE_STREAM_TO_FIFO = 0x60,
LSM303_FMODE_BYPASS_TO_STREAM = 0x80,
LSM303_FMODE_BYPASS_TO_FIFO = 0xE0,
LSM303_FMODE_MASK = 0xE0
} LSM303_FMODE_t;
/* Magnetometer config */
#define LSM303_MAG_ST_MASK 0x01
#define LSM303_MAG_ST_EN 0x01
#define LSM303_MAG_TEMP_EN 0x80
#define LSM303_MAG_REBOOT 0x08
int lsm303_init();
uint8_t spi_read(uint8_t dev, uint8_t adr);
void spi_send(uint8_t dev, uint8_t adr, uint8_t dat);
int lsm303_selftest(int dev, int en, int dir);
int lsm303_odr(int dev, LSM303_ODR_t odr);
int lsm303_opmode(int dev, LSM303_OPM_t opm);
int lsm303_rst(int dev, int hard);
int lsm303_temp(int16_t *temp);
int lsm303_fullscale(int dev, LSM303_FS_t fs);
int lsm303_serialmode(int dev, LSM303_SMODE_t mode);
int lsm303_enableaxis(int dev, int mask);
int lsm303_fifo_mode(int dev, LSM303_FMODE_t mode, int en);
int lsm303_get_sample(int dev, int16_t *x, int16_t *y, int16_t *z);
int spi_read(uint8_t dev, uint8_t adr, uint8_t *dat);
/* Accelerometer & Magnetometer registers */
//#define LSM303C_ACC_TEMP_L 0x0B
//#define LSM303C_ACC_TEMP_H 0x0C
//#define LSM303C_ACC_ACT_TSH 0x1E
//#define LSM303C_ACC_ACT_DUR 0x1F
//#define LSM303C_WHO_AM_I_REG 0x0F
//#define LSM303C_CTRL1 0x20
//#define LSM303C_CTRL2 0x21
//#define LSM303C_CTRL3 0x22
//#define LSM303C_CTRL4 0x23
//#define LSM303C_CTRL5 0x24
//#define LSM303C_CTRL6 0x25 /* ACC only */
//#define LSM303C_CTRL7 0x26 /* ACC only */
//#define LSM303C_STATUS 0x27
//#define LSM303C_OUT_X_L 0x28
//#define LSM303C_OUT_X_H 0x29
//#define LSM303C_OUT_Y_L 0x2A
//#define LSM303C_OUT_Y_H 0x2B
//#define LSM303C_OUT_Z_L 0x2C
//#define LSM303C_OUT_Z_H 0x2D
//#define LSM303C_ACC_FIFO_CTRL 0x2E
//#define LSM303C_ACC_FIFO_SRC 0x2F
//#define LSM303C_ACC_IG_CFG1 0x30
//#define LSM303C_ACC_IG_SRC1 0x31
//#define LSM303C_ACC_IG_THS_X1 0x32
//#define LSM303C_ACC_IG_THS_Y1 0x33
//#define LSM303C_ACC_IG_THS_Z1 0x34
//#define LSM303C_ACC_IG_DUR1 0x35
//#define LSM303C_ACC_IG_CFG2 0x36
//#define LSM303C_ACC_IG_SRC2 0x37
//#define LSM303C_ACC_IG_THS2 0x38
//#define LSM303C_ACC_IG_DUR2 0x39
//#define LSM303C_ACC_XL_REFERENCE 0x3A
//#define LSM303C_ACC_XH_REFERENCE 0x3B
//#define LSM303C_ACC_YL_REFERENCE 0x3C
//#define LSM303C_ACC_YH_REFERENCE 0x3D
//#define LSM303C_ACC_ZL_REFERENCE 0x3E
//#define LSM303C_ACC_ZH_REFERENCE 0x3F
#endif
......@@ -148,8 +148,6 @@ C_SRC += \
../common/drivers/lcd_dma.c \
../common/drivers/i2cdrv.c \
../common/drivers/max17047.c \
../common/drivers/LSM303C/LSM303C_ACC_driver.c \
../common/drivers/LSM303C/LSM303C_MAG_driver.c \
../common/drivers/LSM303C/lsm303c.c \
../common/emlib/src/em_assert.c \
../common/emlib/src/em_cmu.c \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment