#if HAS_MMC5983
-#define AO_MMC5983_SPI_SPEED ao_spi_speed(10000000)
+struct ao_mmc5983_sample ao_mmc5983_current;
+
+static uint8_t ao_mmc5983_configured;
+
+#ifdef MMC5983_I2C
+#include <ao_i2c_bit.h>
+
+static void
+ao_mmc5983_reg_write(uint8_t addr, uint8_t data)
+{
+ uint8_t d[2];
+
+ d[0] = addr;
+ d[1] = data;
+
+ ao_i2c_bit_start(MMC5983_I2C_ADDR);
+ ao_i2c_bit_send(d, 2);
+ ao_i2c_bit_stop();
+}
+
+static uint8_t
+ao_mmc5983_reg_read(uint8_t addr)
+{
+ uint8_t d[1];
+
+ ao_i2c_bit_start(MMC5983_I2C_ADDR);
+ d[0] = addr;
+ ao_i2c_bit_send(d, 1);
+ ao_i2c_bit_restart(MMC5983_I2C_ADDR | 1);
+ ao_i2c_bit_recv(d, 1);
+ ao_i2c_bit_stop();
+ return d[0];
+}
+
+static void
+ao_mmc5983_sample(struct ao_mmc5983_sample *sample)
+{
+ struct ao_mmc5983_raw raw;
+
+ ao_i2c_bit_start(MMC5983_I2C_ADDR);
+ raw.addr = MMC5983_X_OUT_0;
+ ao_i2c_bit_send(&raw.addr, 1);
+ ao_i2c_bit_restart(MMC5983_I2C_ADDR | 1);
+ ao_i2c_bit_recv(&raw.x0, 7);
+ ao_i2c_bit_stop();
+
+ sample->x = raw.x0 << 10 | raw.x1 << 2 | ((raw.xyz2 >> 6) & 3);
+ sample->y = raw.y0 << 10 | raw.y1 << 2 | ((raw.xyz2 >> 4) & 3);
+ sample->z = raw.z0 << 10 | raw.z1 << 2 | ((raw.xyz2 >> 2) & 3);
+}
+
+#else
+#define AO_MMC5983_SPI_SPEED ao_spi_speed(2000000)
static void
ao_mmc5983_start(void) {
AO_MMC5983_SPI_INDEX);
}
-struct ao_mmc5983_sample ao_mmc5983_current;
-
-static uint8_t ao_mmc5983_configured;
static void
ao_mmc5983_reg_write(uint8_t addr, uint8_t data)
ao_mmc5983_stop();
}
-static uint8_t ao_mmc5983_done;
-
-static void
-ao_mmc5983_isr(void)
-{
- ao_exti_disable(AO_MMC5983_INT_PORT, AO_MMC5983_INT_PIN);
- ao_mmc5983_done = 1;
- ao_wakeup(&ao_mmc5983_done);
-}
-
-static uint32_t ao_mmc5983_missed_irq;
-
static void
ao_mmc5983_sample(struct ao_mmc5983_sample *sample)
{
struct ao_mmc5983_raw raw;
- ao_mmc5983_done = 0;
- ao_exti_enable(AO_MMC5983_INT_PORT, AO_MMC5983_INT_PIN);
- ao_mmc5983_reg_write(MMC5983_CONTROL_0,
- (1 << MMC5983_CONTROL_0_INT_MEAS_DONE_EN) |
- (1 << MMC5983_CONTROL_0_TM_M));
- ao_arch_block_interrupts();
- while (!ao_mmc5983_done)
- if (ao_sleep_for(&ao_mmc5983_done, AO_MS_TO_TICKS(10)))
- ++ao_mmc5983_missed_irq;
- ao_arch_release_interrupts();
raw.addr = MMC5983_X_OUT_0 | MMC5983_READ;
ao_mmc5983_duplex((uint8_t *) &raw, sizeof (raw));
sample->y = raw.y0 << 10 | raw.y1 << 2 | ((raw.xyz2 >> 4) & 3);
sample->z = raw.z0 << 10 | raw.z1 << 2 | ((raw.xyz2 >> 2) & 3);
}
+#endif
+
+static uint8_t product_id;
static uint8_t
ao_mmc5983_setup(void)
{
- uint8_t product_id;
if (ao_mmc5983_configured)
return 1;
- /* Place device in 3-wire mode */
- ao_mmc5983_reg_write(MMC5983_CONTROL_3,
- 1 << MMC5983_CONTROL_3_SPI_3W);
+ /* Delay for power up time (10ms) */
+ ao_delay(AO_MS_TO_TICKS(10));
+
+ ao_mmc5983_reg_write(MMC5983_CONTROL_1,
+ 1 << MMC5983_CONTROL_1_SW_RST);
+
+ /* Delay for power up time (10ms) */
+ ao_delay(AO_MS_TO_TICKS(10));
/* Check product ID */
product_id = ao_mmc5983_reg_read(MMC5983_PRODUCT_ID);
- if (product_id != MMC5983_PRODUCT_ID_PRODUCT)
+ if (product_id != MMC5983_PRODUCT_ID_PRODUCT_I2C &&
+ product_id != MMC5983_PRODUCT_ID_PRODUCT_SPI)
+ {
AO_SENSOR_ERROR(AO_DATA_MMC5983);
+ }
- /* Set high bandwidth to reduce sample collection time */
+ /* Set bandwidth to 200Hz */
ao_mmc5983_reg_write(MMC5983_CONTROL_1,
- MMC5983_CONTROL_1_BW_800 << MMC5983_CONTROL_1_BW);
+ MMC5983_CONTROL_1_BW_200 << MMC5983_CONTROL_1_BW);
- /* Clear automatic measurement and 'set' operation */
+ /* Measure at 200Hz so we get recent samples by just reading
+ * the registers
+ */
ao_mmc5983_reg_write(MMC5983_CONTROL_2,
- 0);
+ (1 << MMC5983_CONTROL_2_CMM_EN) |
+ (MMC5983_CONTROL_2_CM_FREQ_200HZ << MMC5983_CONTROL_2_CM_FREQ));
ao_mmc5983_configured = 1;
return 1;
static void
ao_mmc5983_show(void)
{
- printf ("X: %d Z: %d Y: %d missed irq: %lu\n",
- ao_mmc5983_current.x, ao_mmc5983_current.z, ao_mmc5983_current.y, ao_mmc5983_missed_irq);
+ printf ("X: %d Z: %d Y: %d id: %d\n",
+ ao_mmc5983_current.x, ao_mmc5983_current.z, ao_mmc5983_current.y,
+ product_id);
}
static const struct ao_cmds ao_mmc5983_cmds[] = {
{
ao_mmc5983_configured = 0;
- ao_spi_init_cs(AO_MMC5983_SPI_CS_PORT, (1 << AO_MMC5983_SPI_CS_PIN));
+#ifdef MMC5983_I2C
+ ao_enable_output(AO_MMC5983_SPI_CS_PORT, AO_MMC5983_SPI_CS_PIN, 1);
+#else
+ ao_enable_input(AO_MMC5983_SPI_MISO_PORT,
+ AO_MMC5983_SPI_MISO_PIN,
+ AO_EXTI_MODE_PULL_NONE);
+
+ ao_enable_output(AO_MMC5983_SPI_CLK_PORT,
+ AO_MMC5983_SPI_CLK_PIN,
+ 1);
- ao_enable_port(AO_MMC5983_INT_PORT);
- ao_exti_setup(AO_MMC5983_INT_PORT,
- AO_MMC5983_INT_PIN,
- AO_EXTI_MODE_RISING | AO_EXTI_MODE_PULL_NONE,
- ao_mmc5983_isr);
+ ao_enable_output(AO_MMC5983_SPI_MOSI_PORT,
+ AO_MMC5983_SPI_MOSI_PIN,
+ 0);
+
+ ao_spi_init_cs(AO_MMC5983_SPI_CS_PORT, (1 << AO_MMC5983_SPI_CS_PIN));
+#endif
ao_add_task(&ao_mmc5983_task, ao_mmc5983, "mmc5983");
ao_cmd_register(&ao_mmc5983_cmds[0]);