From e0b8c614ec4d11f432963e48d94e4497d31a9ddc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:27:58 -0700 Subject: [PATCH] altos: Add mpu6000 and hmc5883 stubs No real drivers here yet, just some testing stubs Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 139 +++++++++++++++++++++++++++++++++++++++ src/drivers/ao_hmc5883.h | 41 ++++++++++++ src/drivers/ao_mpu6000.c | 97 +++++++++++++++++++++++++++ src/drivers/ao_mpu6000.h | 30 +++++++++ 4 files changed, 307 insertions(+) create mode 100644 src/drivers/ao_hmc5883.c create mode 100644 src/drivers/ao_hmc5883.h create mode 100644 src/drivers/ao_mpu6000.c create mode 100644 src/drivers/ao_mpu6000.h diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c new file mode 100644 index 00000000..0077daf9 --- /dev/null +++ b/src/drivers/ao_hmc5883.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static uint8_t ao_hmc5883_wake; +static uint8_t ao_hmc5883_configured; + +static void +ao_hmc5883_isr(void) +{ + ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_hmc5883_wake = 1; + ao_wakeup(&ao_hmc5883_wake); +} + +static uint8_t ao_hmc5883_addr_reg; + +static void +ao_hmc5883_update_addr (uint8_t len) +{ + ao_hmc5883_addr_reg += len; + if (ao_hmc5883_addr_reg == 9) + ao_hmc5883_addr_reg = 3; + else if (ao_hmc5883_addr_reg > 12) + ao_hmc5883_addr_reg = 0; + +} + +static void +ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_HMC5883_I2C_INDEX); + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr_reg = addr; + if (len) { + ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX); + ao_hmc5883_update_addr(len); + } + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); +} + +static void +ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_HMC5883_I2C_INDEX); + if (addr != ao_hmc5883_addr_reg) { + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr_reg = addr; + } + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + if (len) { + ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX); + ao_hmc5883_update_addr(len); + } + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); +} + +static uint8_t +ao_hmc5883_setup(void) +{ + uint8_t present; + if (ao_hmc5883_configured) + return 1; + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_HMC5883_INT_PORT); + ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, + AO_EXTI_MODE_FALLING, ao_hmc5883_isr); + + ao_hmc5883_addr_reg = 0xff; + + ao_i2c_get(AO_HMC5883_I2C_INDEX); + present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (!present) + return 0; + ao_hmc5883_configured = 1; + return 1; +} + +static void +ao_hmc5883_show(void) +{ + uint8_t addr, data; + + for (addr = 0x00; addr <= 0x7f; addr++) + { + ao_i2c_get(AO_HMC5883_I2C_INDEX); + data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (data) + printf("address %02x responds\n", addr << 1); + } + if (!ao_hmc5883_setup()) { + printf("hmc5883 not present\n"); + return; + } + for (addr = 0; addr <= 12; addr++) { + ao_hmc5883_read(addr, &data, 1); + printf ("hmc5883 register %2d: %02x\n", + addr, data); + } +} + +static const struct ao_cmds ao_hmc5883_cmds[] = { + { ao_hmc5883_show, "M\0Show HMC5883 status" }, + { 0, NULL } +}; + +void +ao_hmc5883_init(void) +{ + ao_hmc5883_configured = 0; + + ao_cmd_register(&ao_hmc5883_cmds[0]); +} diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h new file mode 100644 index 00000000..399ddcdd --- /dev/null +++ b/src/drivers/ao_hmc5883.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_HMC5883_H_ +#define _AO_HMC5883_H_ + +#define HMC5883_ADDR_WRITE 0x3c +#define HMC5883_ADDR_READ 0x3d + +#define HMC5883_CONFIG_A 0 +#define HMC5883_CONFIG_B 1 +#define HMC5883_MODE 2 +#define HMC5883_X_MSB 3 +#define HMC5883_X_LSB 4 +#define HMC5883_Y_MSB 5 +#define HMC5883_Y_LSB 6 +#define HMC5883_Z_MSB 7 +#define HMC5883_Z_LSB 8 +#define HMC5883_STATUS 9 +#define HMC5883_ID_A 10 +#define HMC5883_ID_B 11 +#define HMC5883_ID_C 12 + +void +ao_hmc5883_init(void); + +#endif /* _AO_HMC5883_H_ */ diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c new file mode 100644 index 00000000..290f1390 --- /dev/null +++ b/src/drivers/ao_mpu6000.c @@ -0,0 +1,97 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static uint8_t ao_mpu6000_wake; +static uint8_t ao_mpu6000_configured; + +static void +ao_mpu6000_isr(void) +{ + ao_exti_disable(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN); + ao_mpu6000_wake = 1; + ao_wakeup(&ao_mpu6000_wake); +} + +static void +ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + if (len) + ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX); + ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_put(AO_MPU6000_I2C_INDEX); +} + +static void +ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); + if (len) + ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX); + ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_put(AO_MPU6000_I2C_INDEX); +} + +static void +ao_mpu6000_setup(void) +{ + if (ao_mpu6000_configured) + return; + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_MPU6000_INT_PORT); + ao_exti_setup(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN, + AO_EXTI_MODE_FALLING, ao_mpu6000_isr); + + ao_mpu6000_configured = 1; +} + +static void +ao_mpu6000_show(void) +{ + uint8_t addr; + uint8_t data[14]; + uint8_t i; + + ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1); + printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); + ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 1); + for (i = 0; i < 14; i++) + printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); +} + +static const struct ao_cmds ao_mpu6000_cmds[] = { + { ao_mpu6000_show, "I\0Show MPU6000 status" }, + { 0, NULL } +}; + +void +ao_mpu6000_init(void) +{ + ao_mpu6000_configured = 0; + + ao_cmd_register(&ao_mpu6000_cmds[0]); +} diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h new file mode 100644 index 00000000..d436a3e0 --- /dev/null +++ b/src/drivers/ao_mpu6000.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MPU6000_H_ +#define _AO_MPU6000_H_ + +#define MPU6000_ADDR_WRITE 0xd0 +#define MPU6000_ADDR_READ 0xd1 + +#define MPU6000_ACCEL_XOUT_H 0x3b +#define MPU6000_WHO_AM_I 0x75 + +void +ao_mpu6000_init(void); + +#endif /* _AO_MPU6000_H_ */ -- 2.30.2