/* $OpenBSD: lis331dl.c,v 1.1 2009/08/12 14:51:20 cnst Exp $ */ /* * Copyright (c) 2009 Constantine A. Murenin * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include /* * STMicroelectronics LIS331DL * MEMS motion sensor * http://www.stm.com/stonline/products/literature/ds/13951.pdf * April 2008 */ /* 3-axis accelerometer */ #define LISA_NUM_AXIS 3 static const struct { const char *name; const uint8_t reg; } lisa_axis[LISA_NUM_AXIS] = { { "OUT_X", 0x29 }, { "OUT_Y", 0x2b }, { "OUT_Z", 0x2d } }; struct lisa_softc { struct device sc_dev; i2c_tag_t sc_tag; i2c_addr_t sc_addr; struct ksensor sc_sensors[LISA_NUM_AXIS]; struct ksensordev sc_sensordev; }; int lisa_match(struct device *, void *, void *); void lisa_attach(struct device *, struct device *, void *); void lisa_refresh(void *); uint8_t lisa_readreg(struct lisa_softc *, uint8_t); void lisa_writereg(struct lisa_softc *, uint8_t, uint8_t); struct cfattach lisa_ca = { sizeof(struct lisa_softc), lisa_match, lisa_attach }; struct cfdriver lisa_cd = { NULL, "lisa", DV_DULL }; int lisa_match(struct device *parent, void *match, void *aux) { struct i2c_attach_args *ia = aux; if (strcmp(ia->ia_name, "lis331dl") == 0) return 1; return 0; } void lisa_attach(struct device *parent, struct device *self, void *aux) { struct lisa_softc *sc = (struct lisa_softc *)self; struct i2c_attach_args *ia = aux; int i; sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; printf(": %s", ia->ia_name); strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, sizeof(sc->sc_sensordev.xname)); for (i = 0; i < LISA_NUM_AXIS; i++) { strlcpy(sc->sc_sensors[i].desc, lisa_axis[i].name, sizeof(sc->sc_sensors[i].desc)); sc->sc_sensors[i].type = SENSOR_INTEGER; sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); } if (sensor_task_register(sc, lisa_refresh, 1) == NULL) { printf(", unable to register update task\n"); return; } sensordev_install(&sc->sc_sensordev); printf("\n"); } void lisa_refresh(void *arg) { struct lisa_softc *sc = arg; struct ksensor *s = sc->sc_sensors; int i; iic_acquire_bus(sc->sc_tag, 0); for (i = 0; i < LISA_NUM_AXIS; i++) s[i].value = (int8_t)lisa_readreg(sc, lisa_axis[i].reg); iic_release_bus(sc->sc_tag, 0); } uint8_t lisa_readreg(struct lisa_softc *sc, uint8_t reg) { uint8_t data; iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); return data; } void lisa_writereg(struct lisa_softc *sc, uint8_t reg, uint8_t data) { iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); }