altos: Add MMA655X driver
authorKeith Packard <keithp@keithp.com>
Sun, 19 Aug 2012 04:26:34 +0000 (21:26 -0700)
committerKeith Packard <keithp@keithp.com>
Sun, 19 Aug 2012 04:26:34 +0000 (21:26 -0700)
Just debug code at this point, will complete on real hardware

Signed-off-by: Keith Packard <keithp@keithp.com>
src/drivers/ao_mma655x.c [new file with mode: 0644]
src/drivers/ao_mma655x.h [new file with mode: 0644]
src/megametrum-v0.1/Makefile
src/megametrum-v0.1/ao_megametrum.c
src/megametrum-v0.1/ao_pins.h

diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c
new file mode 100644 (file)
index 0000000..e4e4162
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * 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 <ao.h>
+#include <ao_mma655x.h>
+
+static uint8_t mma655x_configured;
+uint8_t                ao_mma655x_valid;
+
+static void
+ao_mma655x_start(void) {
+       ao_spi_get_bit(AO_MMA655X_CS_GPIO,
+                      AO_MMA655X_CS,
+                      AO_MMA655X_CS_PIN,
+                      AO_MMA655X_SPI_INDEX,
+                      AO_SPI_SPEED_FAST);
+}
+
+static void
+ao_mma655x_stop(void) {
+       ao_spi_put_bit(AO_MMA655X_CS_GPIO,
+                      AO_MMA655X_CS,
+                      AO_MMA655X_CS_PIN,
+                      AO_MMA655X_SPI_INDEX);
+}
+
+static uint8_t
+ao_parity(uint8_t v)
+{
+       /* down to four bits */
+       v = (v ^ (v >> 4)) & 0xf;
+
+       /* Cute lookup hack -- 0x6996 encodes the sixteen
+        * even parity values in order.
+        */
+       return (~0x6996 >> v) & 1;
+}
+
+static void
+ao_mma655x_cmd(uint8_t d[2])
+{
+       ao_mma655x_start();
+       ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX);
+       ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX);
+       ao_mma655x_stop();
+}
+
+static uint8_t
+ao_mma655x_reg_write(uint8_t addr, uint8_t value)
+{
+       uint8_t d[2];
+
+       addr |= (1 << 6);       /* write mode */
+       d[0] = addr | (ao_parity(addr^value) << 7);
+       d[1] = value;
+       ao_mma655x_cmd(d);
+       return d[1];
+}
+
+static uint8_t
+ao_mma655x_reg_read(uint8_t addr)
+{
+       uint8_t d[2];
+
+       d[0] = addr | (ao_parity(addr) << 7);
+       d[1] = 0;
+       ao_mma655x_cmd(d);
+       return d[1];
+}
+
+static uint16_t
+ao_mma655x_value(void)
+{
+       uint8_t         d[2];
+       uint16_t        v;
+
+       d[0] = ((0 << 7) |      /* Axis selection (X) */
+               (1 << 6) |      /* Acceleration operation */
+               (1 << 5));      /* Raw data */
+       d[1] = ((1 << 3) |      /* must be one */
+               (1 << 2) |      /* Unsigned data */
+               (0 << 1) |      /* Arm disabled */
+               (1 << 0));      /* Odd parity */
+       ao_mma655x_cmd(d);
+       v = (uint16_t) d[1] << 2;
+       v |= d[0] >> 6;
+       v |= (uint16_t) (d[0] & 3) << 10;
+       return v;
+}
+
+static void
+ao_mma655x_reset(void) {
+       ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+                            (0 << AO_MMA655X_DEVCTL_RES_1) |
+                            (0 << AO_MMA655X_DEVCTL_RES_1));
+       ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+                            (1 << AO_MMA655X_DEVCTL_RES_1) |
+                            (1 << AO_MMA655X_DEVCTL_RES_1));
+       ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
+                            (0 << AO_MMA655X_DEVCTL_RES_1) |
+                            (1 << AO_MMA655X_DEVCTL_RES_1));
+}
+
+#define DEVCFG_VALUE   (\
+       (1 << AO_MMA655X_DEVCFG_OC) |           /* Disable offset cancelation */ \
+       (1 << AO_MMA655X_DEVCFG_SD) |           /* Receive unsigned data */ \
+       (0 << AO_MMA655X_DEVCFG_OFMON) |        /* Disable offset monitor */ \
+       (AO_MMA655X_DEVCFG_A_CFG_DISABLE << AO_MMA655X_DEVCFG_A_CFG))
+
+#define AXISCFG_VALUE  (\
+               (0 << AO_MMA655X_AXISCFG_LPF))  /* 100Hz 4-pole filter */
+
+
+static void
+ao_mma655x_setup(void)
+{
+       uint8_t         v;
+       uint16_t        a, a_st;
+       uint8_t         stdefl;
+
+       if (mma655x_configured)
+               return;
+       mma655x_configured = 1;
+       ao_delay(AO_MS_TO_TICKS(10));   /* Top */
+       ao_mma655x_reset();
+       ao_delay(AO_MS_TO_TICKS(10));   /* Top */
+       (void) ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
+       v = ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
+
+       /* Configure R/W register values.
+        * Most of them relate to the arming feature, which
+        * we don't use, so the only registers we need to
+        * write are DEVCFG and AXISCFG
+        */
+
+       ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
+                            DEVCFG_VALUE | (0 << AO_MMA655X_DEVCFG_ENDINIT));
+
+       /* Test X axis
+        */
+       
+       ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
+                            AXISCFG_VALUE |
+                            (1 << AO_MMA655X_AXISCFG_ST));
+       a_st = ao_mma655x_value();
+
+       stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL);
+
+       ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
+                            AXISCFG_VALUE |
+                            (0 << AO_MMA655X_AXISCFG_ST));
+       a = ao_mma655x_value();
+       printf ("normal: %u self_test: %u stdefl: %u\n",
+               a, a_st, stdefl);
+
+       ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
+                            DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT));
+}
+
+static void
+ao_mma655x_dump(void)
+{
+       uint8_t s0, s1, s2, s3;
+       uint32_t        lot;
+       uint16_t        serial;
+
+       ao_mma655x_setup();
+
+       s0 = ao_mma655x_reg_read(AO_MMA655X_SN0);
+       s1 = ao_mma655x_reg_read(AO_MMA655X_SN1);
+       s2 = ao_mma655x_reg_read(AO_MMA655X_SN2);
+       s3 = ao_mma655x_reg_read(AO_MMA655X_SN3);
+       lot = ((uint32_t) s3 << 24) | ((uint32_t) s2 << 16) |
+               ((uint32_t) s1 << 8) | ((uint32_t) s0);
+       serial = lot & 0x1fff;
+       lot >>= 12;
+       printf ("MMA655X lot %d serial %d\n", lot, serial);
+       mma655x_configured = 0;
+}
+
+__code struct ao_cmds ao_mma655x_cmds[] = {
+       { ao_mma655x_dump,      "A\0Display MMA655X data" },
+       { 0, NULL },
+};
+
+void
+ao_mma655x_init(void)
+{
+       mma655x_configured = 0;
+       ao_mma655x_valid = 0;
+
+       ao_cmd_register(&ao_mma655x_cmds[0]);
+       ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS));
+
+//     ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x");
+}
diff --git a/src/drivers/ao_mma655x.h b/src/drivers/ao_mma655x.h
new file mode 100644 (file)
index 0000000..9c0c59d
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * 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_MMA655X_H_
+#define _AO_MMA655X_H_
+
+
+#define AO_MMA655X_SN0         0x00
+#define AO_MMA655X_SN1         0x01
+#define AO_MMA655X_SN2         0x02
+#define AO_MMA655X_SN3         0x03
+#define AO_MMA655X_SN3         0x03
+#define AO_MMA655X_STDEFL      0x04
+#define AO_MMA655X_FCTCFG      0x06
+# define AO_MMA655X_FCTCFG_STMAG       7
+
+#define AO_MMA655X_PN          0x08
+#define AO_MMA655X_DEVCTL      0x0a
+#define AO_MMA655X_DEVCTL_RES_1                7
+#define AO_MMA655X_DEVCTL_RES_0                6
+#define AO_MMA655X_DEVCTL_OCPHASE      4
+#define AO_MMA655X_DEVCTL_OCPHASE_MASK 3
+#define AO_MMA655X_DEVCTL_OFFCFG_EN    3
+
+#define AO_MMA655X_DEVCFG      0x0b
+#define AO_MMA655X_DEVCFG_OC           7
+#define AO_MMA655X_DEVCFG_ENDINIT      5
+#define AO_MMA655X_DEVCFG_SD           4
+#define AO_MMA655X_DEVCFG_OFMON                3
+#define AO_MMA655X_DEVCFG_A_CFG                0
+#define AO_MMA655X_DEVCFG_A_CFG_DISABLE                0
+#define AO_MMA655X_DEVCFG_A_CFG_PCM            1
+#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_HIGH        2
+#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_LOW 3
+#define AO_MMA655X_DEVCFG_A_CFG_COUNT_HIGH     4
+#define AO_MMA655X_DEVCFG_A_CFG_COUNT_LOW      5
+#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_HIGH        6
+#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_LOW 7
+#define AO_MMA655X_DEVCFG_A_CFG_MASK           7
+
+#define AO_MMA655X_AXISCFG     0x0c
+#define AO_MMA655X_AXISCFG_ST          7
+#define AO_MMA655X_AXISCFG_LPF         0
+#define AO_MMA655X_AXISCFG_LPF_MASK    0xf
+
+#define AO_MMA655X_ARMCFG      0x0e
+#define AO_MMA655X_ARMCFG_APS          4
+#define AO_MMA655X_ARMCFG_APS_MASK     3
+#define AO_MMA655X_ARMCFG_AWS_N                2
+#define AO_MMA655X_ARMCFG_AWS_N_MASK   3
+#define AO_MMA655X_ARMCFG_AWS_P                0
+#define AO_MMA655X_ARMCFG_AWS_P_MASK   3
+
+#define AO_MMA655X_ARMT_P      0x10
+#define AO_MMA655X_ARMT_N      0x12
+
+#define AO_MMA655X_DEVSTAT     0x14
+#define AO_MMA655X_DEVSTAT_IDE         6
+#define AO_MMA655X_DEVSTAT_DEVINIT     4
+#define AO_MMA655X_DEVSTAT_MISOERR     3
+#define AO_MMA655X_DEVSTAT_OFFSET      1
+#define AO_MMA655X_DEVSTAT_DEVRES      0
+
+#define AO_MMA655X_COUNT       0x15
+#define AO_MMA655X_OFFCORR     0x16
+
+
+void
+ao_mma655x_init(void);
+
+#endif /* _AO_MMA655X_H_ */
index 4a4c983ac544d701f4299851e7f5d11c885fddb6..1dfebca0730cff328ae176daae27aa1a77241bee 100644 (file)
@@ -19,6 +19,7 @@ INC = \
        ao_ms5607.h \
        ao_hmc5883.h \
        ao_mpu6000.h \
+       ao_mma655x.h \
        ao_cc1120_CC1120.h \
        ao_profile.h \
        ao_whiten.h \
@@ -56,6 +57,7 @@ ALTOS_SRC = \
        ao_fec_tx.c \
        ao_fec_rx.c \
        ao_ms5607.c \
+       ao_mma655x.c \
        ao_adc_stm.c \
        ao_beep_stm.c \
        ao_storage.c \
index 55324514cb062d3b0eba7720279dda4ea7917e20..d3ae4690c41de2e85c9ea4b402fb35cc8e009d48 100644 (file)
@@ -18,6 +18,7 @@
 #include <ao.h>
 #include <ao_hmc5883.h>
 #include <ao_mpu6000.h>
+#include <ao_mma655x.h>
 #include <ao_log.h>
 #include <ao_exti.h>
 #include <ao_packet.h>
@@ -53,6 +54,9 @@ main(void)
 #if HAS_MPU6000
        ao_mpu6000_init();
 #endif
+#if HAS_MMA655X
+       ao_mma655x_init();
+#endif
 
        ao_storage_init();
        
index 42715968160a18b6966c11b4d7288ba2735a1719..6256d2f64a07f37790b7e75177ded24ecce7fa3a 100644 (file)
@@ -305,6 +305,15 @@ struct ao_adc {
 
 #define HAS_HIGHG_ACCEL                0
 
+/*
+ * mma655x
+ */
+
+#define HAS_MMA655X            1
+#define AO_MMA655X_SPI_INDEX   AO_SPI_1_PA5_PA6_PA7
+#define AO_MMA655X_CS_GPIO     (&stm_gpiod)
+#define AO_MMA655X_CS          4
+
 #define NUM_CMDS               16
 
 /*