You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

184 lines
4.3 KiB

/*
* Operations for the l3g4200
*/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <debug.h>
#include <arch/board/board.h>
#include <nuttx/spi.h>
#include "sensors.h"
#define DIR_READ (1<<7)
#define DIR_WRITE (0<<7)
#define ADDR_INCREMENT (1<<6)
#define ADDR_WHO_AM_I 0x0f
#define WHO_I_AM 0xd4
#define ADDR_CTRL_REG1 0x20 /* sample rate constants are in the public header */
#define REG1_POWER_NORMAL (1<<3)
#define REG1_Z_ENABLE (1<<2)
#define REG1_Y_ENABLE (1<<1)
#define REG1_X_ENABLE (1<<0)
#define ADDR_CTRL_REG2 0x21
/* high-pass filter - usefulness TBD */
#define ADDR_CTRL_REG3 0x22
#define ADDR_CTRL_REG4 0x23
#define REG4_BDU (1<<7)
#define REG4_BIG_ENDIAN (1<<6)
#define REG4_SPI_3WIRE (1<<0)
#define ADDR_CTRL_REG5 0x24
#define REG5_BOOT (1<<7)
#define REG5_FIFO_EN (1<<6)
#define REG5_HIGHPASS_ENABLE (1<<4)
#define ADDR_REFERENCE 0x25
#define ADDR_TEMPERATURE 0x26
#define ADDR_STATUS_REG 0x27
#define STATUS_ZYXOR (1<<7)
#define SATAUS_ZOR (1<<6)
#define STATUS_YOR (1<<5)
#define STATUS_XOR (1<<4)
#define STATUS_ZYXDA (1<<3)
#define STATUS_ZDA (1<<2)
#define STATUS_YDA (1<<1)
#define STATUS_XDA (1<<0)
#define ADDR_OUT_X 0x28 /* 16 bits */
#define ADDR_OUT_Y 0x2A /* 16 bits */
#define ADDR_OUT_Z 0x2C /* 16 bits */
#define ADDR_FIFO_CTRL 0x2e
#define FIFO_MODE_BYPASS (0<<5)
#define FIFO_MODE_FIFO (1<<5)
#define FIFO_MODE_STREAM (2<<5)
#define FIFO_MODE_STREAM_TO_FIFO (3<<5)
#define FIFO_MODE_BYPASS_TO_STREAM (4<<5)
#define FIFO_THRESHOLD_MASK 0x1f
#define ADDR_FIFO_SRC 0x2f
#define FIFO_THREHSHOLD_OVER (1<<7)
#define FIFO_OVERRUN (1<<6)
#define FIFO_EMPTY (1<<5)
#define L3G4200_RATE_100Hz ((0<<6) | (0<<4))
#define L3G4200_RATE_200Hz ((1<<6) | (0<<4))
#define L3G4200_RATE_400Hz ((2<<6) | (1<<4))
#define L3G4200_RATE_800Hz ((3<<6) | (2<<4))
#define L3G4200_RANGE_250dps (0<<4)
#define L3G4200_RANGE_500dps (1<<4)
#define L3G4200_RANGE_2000dps (3<<4)
static void
write_reg(struct spi_dev_s *spi, uint8_t address, uint8_t data)
{
uint8_t cmd[2] = { address | DIR_WRITE, data };
SPI_SELECT(spi, PX4_SPIDEV_GYRO, true);
SPI_SNDBLOCK(spi, &cmd, sizeof(cmd));
SPI_SELECT(spi, PX4_SPIDEV_GYRO, false);
}
static uint8_t
read_reg(struct spi_dev_s *spi, uint8_t address)
{
uint8_t cmd[2] = {address | DIR_READ, 0};
uint8_t data[2];
SPI_SELECT(spi, PX4_SPIDEV_GYRO, true);
SPI_EXCHANGE(spi, cmd, data, sizeof(cmd));
SPI_SELECT(spi, PX4_SPIDEV_GYRO, false);
return data[1];
}
int
l3gd20_test_configure(struct spi_dev_s *spi)
{
uint8_t id;
id = read_reg(spi, ADDR_WHO_AM_I);
if (id == WHO_I_AM)
{
message("L3GD20 SUCCESS: 0x%02x\n", id);
}
else
{
message("L3GD20 FAIL: 0x%02x\n", id);
}
struct { /* status register and data as read back from the device */
uint8_t cmd;
uint8_t temp;
uint8_t status;
int16_t x;
int16_t y;
int16_t z;
} __attribute__((packed)) report;
report.cmd = 0x26 | DIR_READ | ADDR_INCREMENT;
write_reg(spi, ADDR_CTRL_REG2, 0); /* disable high-pass filters */
write_reg(spi, ADDR_CTRL_REG3, 0); /* no interrupts - we don't use them */
write_reg(spi, ADDR_CTRL_REG5, 0); /* turn off FIFO mode */
write_reg(spi, ADDR_CTRL_REG4, ((3<<4) & 0x30) | REG4_BDU);
write_reg(spi, ADDR_CTRL_REG1,
(((2<<6) | (1<<4)) & 0xf0) | REG1_POWER_NORMAL | REG1_Z_ENABLE | REG1_Y_ENABLE | REG1_X_ENABLE);
SPI_SELECT(spi, PX4_SPIDEV_GYRO, true);
SPI_EXCHANGE(spi, &report, &report, sizeof(report));
SPI_SELECT(spi, PX4_SPIDEV_GYRO, false);
message("Init-read: gyro: x: %d\ty: %d\tz: %d\n", report.x, report.y, report.z);
usleep(1000);
//message("got id 0x%02x, expected ID 0xd4\n", id);
return 0;
}
int
l3gd20_test_read(struct spi_dev_s *spi)
{
struct { /* status register and data as read back from the device */
uint8_t cmd;
uint8_t temp;
uint8_t status;
int16_t x;
int16_t y;
int16_t z;
} __attribute__((packed)) report;
report.cmd = 0x26 | DIR_READ | ADDR_INCREMENT;
SPI_LOCK(spi, true);
SPI_SELECT(spi, PX4_SPIDEV_GYRO, true);
SPI_EXCHANGE(spi, &report, &report, sizeof(report));
SPI_SELECT(spi, PX4_SPIDEV_GYRO, false);
SPI_LOCK(spi, false);
message("gyro: x: %d\ty: %d\tz: %d\n", report.x, report.y, report.z);
usleep(1000);
return 0;
}