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>
23 static uint8_t mma655x_configured;
26 ao_mma655x_start(void) {
27 ao_spi_get_bit(AO_MMA655X_CS_GPIO,
35 ao_mma655x_stop(void) {
36 ao_spi_put_bit(AO_MMA655X_CS_GPIO,
39 AO_MMA655X_SPI_INDEX);
45 /* down to four bits */
46 v = (v ^ (v >> 4)) & 0xf;
48 /* Cute lookup hack -- 0x6996 encodes the sixteen
49 * even parity values in order.
51 return (~0x6996 >> v) & 1;
55 ao_mma655x_cmd(uint8_t d[2])
58 ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX);
59 ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX);
64 ao_mma655x_reg_write(uint8_t addr, uint8_t value)
68 addr |= (1 << 6); /* write mode */
69 d[0] = addr | (ao_parity(addr^value) << 7);
76 ao_mma655x_reg_read(uint8_t addr)
80 d[0] = addr | (ao_parity(addr) << 7);
87 ao_mma655x_value(void)
92 d[0] = ((0 << 7) | /* Axis selection (X) */
93 (1 << 6) | /* Acceleration operation */
94 (1 << 5)); /* Raw data */
95 d[1] = ((1 << 3) | /* must be one */
96 (1 << 2) | /* Unsigned data */
97 (0 << 1) | /* Arm disabled */
98 (1 << 0)); /* Odd parity */
100 v = (uint16_t) d[1] << 2;
102 v |= (uint16_t) (d[0] & 3) << 10;
107 ao_mma655x_reset(void) {
108 ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
109 (0 << AO_MMA655X_DEVCTL_RES_1) |
110 (0 << AO_MMA655X_DEVCTL_RES_1));
111 ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
112 (1 << AO_MMA655X_DEVCTL_RES_1) |
113 (1 << AO_MMA655X_DEVCTL_RES_1));
114 ao_mma655x_reg_write(AO_MMA655X_DEVCTL,
115 (0 << AO_MMA655X_DEVCTL_RES_1) |
116 (1 << AO_MMA655X_DEVCTL_RES_1));
119 #define DEVCFG_VALUE (\
120 (1 << AO_MMA655X_DEVCFG_OC) | /* Disable offset cancelation */ \
121 (1 << AO_MMA655X_DEVCFG_SD) | /* Receive unsigned data */ \
122 (0 << AO_MMA655X_DEVCFG_OFMON) | /* Disable offset monitor */ \
123 (AO_MMA655X_DEVCFG_A_CFG_DISABLE << AO_MMA655X_DEVCFG_A_CFG))
125 #define AXISCFG_VALUE (\
126 (0 << AO_MMA655X_AXISCFG_LPF)) /* 100Hz 4-pole filter */
130 ao_mma655x_setup(void)
136 if (mma655x_configured)
138 mma655x_configured = 1;
139 ao_delay(AO_MS_TO_TICKS(10)); /* Top */
141 ao_delay(AO_MS_TO_TICKS(10)); /* Top */
142 (void) ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
143 v = ao_mma655x_reg_read(AO_MMA655X_DEVSTAT);
145 /* Configure R/W register values.
146 * Most of them relate to the arming feature, which
147 * we don't use, so the only registers we need to
148 * write are DEVCFG and AXISCFG
151 ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
152 DEVCFG_VALUE | (0 << AO_MMA655X_DEVCFG_ENDINIT));
157 ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
159 (1 << AO_MMA655X_AXISCFG_ST));
160 a_st = ao_mma655x_value();
162 stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL);
164 ao_mma655x_reg_write(AO_MMA655X_AXISCFG,
166 (0 << AO_MMA655X_AXISCFG_ST));
167 a = ao_mma655x_value();
168 printf ("normal: %u self_test: %u stdefl: %u\n",
171 ao_mma655x_reg_write(AO_MMA655X_DEVCFG,
172 DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT));
176 ao_mma655x_dump(void)
178 uint8_t s0, s1, s2, s3;
184 s0 = ao_mma655x_reg_read(AO_MMA655X_SN0);
185 s1 = ao_mma655x_reg_read(AO_MMA655X_SN1);
186 s2 = ao_mma655x_reg_read(AO_MMA655X_SN2);
187 s3 = ao_mma655x_reg_read(AO_MMA655X_SN3);
188 lot = ((uint32_t) s3 << 24) | ((uint32_t) s2 << 16) |
189 ((uint32_t) s1 << 8) | ((uint32_t) s0);
190 serial = lot & 0x1fff;
192 printf ("MMA655X lot %d serial %d\n", lot, serial);
193 mma655x_configured = 0;
196 __code struct ao_cmds ao_mma655x_cmds[] = {
197 { ao_mma655x_dump, "A\0Display MMA655X data" },
206 ao_data_ring[ao_data_head].mma655x = ao_mma655x_value();
208 AO_DATA_PRESENT(AO_DATA_MMA655X);
214 static __xdata struct ao_task ao_mma655x_task;
217 ao_mma655x_init(void)
219 mma655x_configured = 0;
221 ao_cmd_register(&ao_mma655x_cmds[0]);
222 ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS));
224 ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x");