2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include <ao_mma655x.h>
21 static uint8_t mma655x_configured;
22 uint8_t ao_mma655x_valid;
25 ao_mma655x_start(void) {
26 ao_spi_get_bit(AO_MMA655X_CS_GPIO,
34 ao_mma655x_stop(void) {
35 ao_spi_put_bit(AO_MMA655X_CS_GPIO,
38 AO_MMA655X_SPI_INDEX);
44 /* down to four bits */
45 v = (v ^ (v >> 4)) & 0xf;
47 /* Cute lookup hack -- 0x6996 encodes the sixteen
48 * even parity values in order.
50 return (~0x6996 >> v) & 1;
54 ao_mma655x_cmd(uint8_t d[2])
57 ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX);
58 ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX);
63 ao_mma655x_reg_write(uint8_t addr, uint8_t value)
67 addr |= (1 << 6); /* write mode */
68 d[0] = addr | (ao_parity(addr^value) << 7);
75 ao_mma655x_reg_read(uint8_t addr)
79 d[0] = addr | (ao_parity(addr) << 7);
86 ao_mma655x_value(void)
91 d[0] = ((0 << 7) | /* Axis selection (X) */
92 (1 << 6) | /* Acceleration operation */
93 (1 << 5)); /* Raw data */
94 d[1] = ((1 << 3) | /* must be one */
95 (1 << 2) | /* Unsigned data */
96 (0 << 1) | /* Arm disabled */
97 (1 << 0)); /* Odd parity */
99 v = (uint16_t) d[1] << 2;
101 v |= (uint16_t) (d[0] & 3) << 10;
106 ao_mma655x_reset(void) {
107 ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
108 (0 << AO_MMA655X_DEVCTL_RES_1) |
109 (0 << AO_MMA655X_DEVCTL_RES_1));
110 ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
111 (1 << AO_MMA655X_DEVCTL_RES_1) |
112 (1 << AO_MMA655X_DEVCTL_RES_1));
113 ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
114 (0 << AO_MMA655X_DEVCTL_RES_1) |
115 (1 << AO_MMA655X_DEVCTL_RES_1));
118 #define DEVCFG_VALUE (\
119 (1 << AO_MMA655X_DEVCFG_OC) | /* Disable offset cancelation */ \
120 (1 << AO_MMA655X_DEVCFG_SD) | /* Receive unsigned data */ \
121 (0 << AO_MMA655X_DEVCFG_OFMON) | /* Disable offset monitor */ \
122 (AO_MMA655X_DEVCFG_A_CFG_DISABLE << AO_MMA655X_DEVCFG_A_CFG))
124 #define AXISCFG_VALUE (\
125 (0 << AO_MMA655X_AXISCFG_LPF)) /* 100Hz 4-pole filter */
129 ao_mma655x_setup(void)
135 if (mma655x_configured)
137 mma655x_configured = 1;
138 ao_delay(AO_MS_TO_TICKS(10)); /* Top */
140 ao_delay(AO_MS_TO_TICKS(10)); /* Top */
141 (void) ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
142 v = ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
144 /* Configure R/W register values.
145 * Most of them relate to the arming feature, which
146 * we don't use, so the only registers we need to
147 * write are DEVCFG and AXISCFG
150 ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
151 DEVCFG_VALUE | (0 << AO_MMA655X_DEVCFG_ENDINIT));
156 ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
158 (1 << AO_MMA655X_AXISCFG_ST));
159 a_st = ao_mma655x_value();
161 stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL);
163 ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
165 (0 << AO_MMA655X_AXISCFG_ST));
166 a = ao_mma655x_value();
167 printf ("normal: %u self_test: %u stdefl: %u\n",
170 ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
171 DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT));
175 ao_mma655x_dump(void)
177 uint8_t s0, s1, s2, s3;
183 s0 = ao_mma655x_reg_read(AO_MMA655X_SN0);
184 s1 = ao_mma655x_reg_read(AO_MMA655X_SN1);
185 s2 = ao_mma655x_reg_read(AO_MMA655X_SN2);
186 s3 = ao_mma655x_reg_read(AO_MMA655X_SN3);
187 lot = ((uint32_t) s3 << 24) | ((uint32_t) s2 << 16) |
188 ((uint32_t) s1 << 8) | ((uint32_t) s0);
189 serial = lot & 0x1fff;
191 printf ("MMA655X lot %d serial %d\n", lot, serial);
192 mma655x_configured = 0;
195 __code struct ao_cmds ao_mma655x_cmds[] = {
196 { ao_mma655x_dump, "A\0Display MMA655X data" },
201 ao_mma655x_init(void)
203 mma655x_configured = 0;
204 ao_mma655x_valid = 0;
206 ao_cmd_register(&ao_mma655x_cmds[0]);
207 ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS));
209 // ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x");