MMA8451Q driver

Fork of lib_mma8451q by canuck lehead

Committer:
dudmuck
Date:
Fri May 08 01:31:18 2015 +0000
Revision:
1:778b685c3ad0
Parent:
0:cb0046a629c1
Child:
2:4bc96749141e
added interrupt handling

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:cb0046a629c1 1 #include "mma8451q.h"
dudmuck 0:cb0046a629c1 2 /* turn on: CTRL_REG1 active_bit = 1
dudmuck 0:cb0046a629c1 3 * back to standby: CTRL_REG1 active_bit = 0
dudmuck 0:cb0046a629c1 4 */
dudmuck 0:cb0046a629c1 5
dudmuck 0:cb0046a629c1 6 /* STANDBY: SYSMOD = 00 */
dudmuck 0:cb0046a629c1 7
dudmuck 0:cb0046a629c1 8 /*
dudmuck 0:cb0046a629c1 9 * MMA8451 I2C address
dudmuck 0:cb0046a629c1 10 */
dudmuck 0:cb0046a629c1 11 #define MMA8451_I2C_ADDRESS 0x38 //0x1C
dudmuck 0:cb0046a629c1 12
dudmuck 0:cb0046a629c1 13
dudmuck 1:778b685c3ad0 14 MMA8451Q::MMA8451Q(I2C& r, DigitalIn& int_pin) : m_i2c(r), m_int_pin(int_pin)
dudmuck 0:cb0046a629c1 15 {
dudmuck 1:778b685c3ad0 16 /* INT pins on this chip default to push-pull output */
dudmuck 1:778b685c3ad0 17 write(MMA8451_CTRL_REG3, 0x01); // set PP_OD
dudmuck 1:778b685c3ad0 18 /* INT1 and INT2 are tied together */
dudmuck 0:cb0046a629c1 19
dudmuck 0:cb0046a629c1 20 }
dudmuck 0:cb0046a629c1 21
dudmuck 0:cb0046a629c1 22 MMA8451Q::~MMA8451Q()
dudmuck 0:cb0046a629c1 23 {
dudmuck 0:cb0046a629c1 24 }
dudmuck 0:cb0046a629c1 25
dudmuck 0:cb0046a629c1 26 void MMA8451Q::read(uint8_t addr, uint8_t *dst_buf, int length)
dudmuck 0:cb0046a629c1 27 {
dudmuck 0:cb0046a629c1 28 char cmd[2];
dudmuck 0:cb0046a629c1 29
dudmuck 0:cb0046a629c1 30 cmd[0] = addr;
dudmuck 0:cb0046a629c1 31 if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 1, true))
dudmuck 1:778b685c3ad0 32 printf("MMA write-fail %02x\n", addr);
dudmuck 0:cb0046a629c1 33 if (m_i2c.read(MMA8451_I2C_ADDRESS, (char *)dst_buf, length))
dudmuck 1:778b685c3ad0 34 printf("MMA read-fail\n");
dudmuck 0:cb0046a629c1 35 }
dudmuck 0:cb0046a629c1 36
dudmuck 0:cb0046a629c1 37 uint8_t MMA8451Q::read_single(uint8_t addr)
dudmuck 0:cb0046a629c1 38 {
dudmuck 0:cb0046a629c1 39 char cmd[2];
dudmuck 0:cb0046a629c1 40
dudmuck 0:cb0046a629c1 41 cmd[0] = addr;
dudmuck 0:cb0046a629c1 42 if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 1, true))
dudmuck 1:778b685c3ad0 43 printf("MMA write-fail %02x\n", addr);
dudmuck 0:cb0046a629c1 44 if (m_i2c.read(MMA8451_I2C_ADDRESS, cmd, 1))
dudmuck 1:778b685c3ad0 45 printf("MMA read-fail\n");
dudmuck 0:cb0046a629c1 46
dudmuck 0:cb0046a629c1 47 return cmd[0];
dudmuck 0:cb0046a629c1 48 }
dudmuck 0:cb0046a629c1 49
dudmuck 0:cb0046a629c1 50 void MMA8451Q::print_regs()
dudmuck 0:cb0046a629c1 51 {
dudmuck 1:778b685c3ad0 52 printf("ID: %02x\n", read_single(MMA8451_ID));
dudmuck 1:778b685c3ad0 53 printf("sysmod:%02x\n", read_single(MMA8451_SYSMOD));
dudmuck 0:cb0046a629c1 54 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
dudmuck 1:778b685c3ad0 55 printf("ctrl_reg1:%02x\n", ctrl_reg1.octet);
dudmuck 1:778b685c3ad0 56 printf("ctrl_reg2:%02x\n", read_single(MMA8451_CTRL_REG2));
dudmuck 1:778b685c3ad0 57 printf("ctrl_reg3:%02x\n", read_single(MMA8451_CTRL_REG3)); /* TODO: PP_OD is bit 0 (1=open drain) */
dudmuck 1:778b685c3ad0 58 printf("(int en) ctrl_reg4:%02x\n", read_single(MMA8451_CTRL_REG4));
dudmuck 1:778b685c3ad0 59 printf("(int cfg) ctrl_reg5:%02x\n", read_single(MMA8451_CTRL_REG5));
dudmuck 1:778b685c3ad0 60 printf("status:%02x\n", read_single(MMA8451_STATUS));
dudmuck 1:778b685c3ad0 61 /* (interrupt status) int src at 0x0c (MMA8451_INT_SOURCE): data ready, motion/freefall, pulse, orientation, transient, auto sleep */
dudmuck 1:778b685c3ad0 62 printf("INT_SOURCE:%02x\n", read_single(MMA8451_INT_SOURCE));
dudmuck 0:cb0046a629c1 63 }
dudmuck 0:cb0046a629c1 64
dudmuck 0:cb0046a629c1 65 void MMA8451Q::write(uint8_t addr, uint8_t data)
dudmuck 0:cb0046a629c1 66 {
dudmuck 0:cb0046a629c1 67 uint8_t cmd[2];
dudmuck 0:cb0046a629c1 68
dudmuck 0:cb0046a629c1 69 cmd[0] = addr;
dudmuck 0:cb0046a629c1 70 cmd[1] = data;
dudmuck 0:cb0046a629c1 71
dudmuck 0:cb0046a629c1 72 if (m_i2c.write(MMA8451_I2C_ADDRESS, (char *)cmd, 2))
dudmuck 1:778b685c3ad0 73 printf("MMA write-fail %02x\n", addr);
dudmuck 0:cb0046a629c1 74 }
dudmuck 0:cb0046a629c1 75
dudmuck 0:cb0046a629c1 76 void MMA8451Q::set_active(char arg)
dudmuck 0:cb0046a629c1 77 {
dudmuck 0:cb0046a629c1 78 char cmd[2];
dudmuck 0:cb0046a629c1 79
dudmuck 0:cb0046a629c1 80 cmd[0] = MMA8451_CTRL_REG1;
dudmuck 0:cb0046a629c1 81 cmd[1] = arg;
dudmuck 0:cb0046a629c1 82
dudmuck 0:cb0046a629c1 83 if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 2))
dudmuck 1:778b685c3ad0 84 printf("MMA write-fail %02x\n", cmd[0]);
dudmuck 0:cb0046a629c1 85 }
dudmuck 0:cb0046a629c1 86
dudmuck 1:778b685c3ad0 87 bool MMA8451Q::get_active(void)
dudmuck 0:cb0046a629c1 88 {
dudmuck 0:cb0046a629c1 89 uint8_t ret = read_single(MMA8451_CTRL_REG1);
dudmuck 1:778b685c3ad0 90 //printf("CTRL_REG1: %x\n", ret);
dudmuck 1:778b685c3ad0 91 if (ret & 1)
dudmuck 1:778b685c3ad0 92 return true;
dudmuck 1:778b685c3ad0 93 else
dudmuck 1:778b685c3ad0 94 return false;
dudmuck 0:cb0046a629c1 95 }
dudmuck 0:cb0046a629c1 96
dudmuck 0:cb0046a629c1 97
dudmuck 0:cb0046a629c1 98 void MMA8451Q::transient_detect()
dudmuck 0:cb0046a629c1 99 {
dudmuck 0:cb0046a629c1 100 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
dudmuck 0:cb0046a629c1 101 /* AN4071 Sensors Freescale Semiconductor, Inc.
dudmuck 0:cb0046a629c1 102 * 7.1 Example Steps for Configuring Transient Detection
dudmuck 0:cb0046a629c1 103 * Change in X or Y > 0.5g for 50 ms at 100 Hz ODR, Normal mode */
dudmuck 0:cb0046a629c1 104
dudmuck 0:cb0046a629c1 105 /* Step 1: Put the device in Standby Mode: Register 0x2A CTRL_REG1 */
dudmuck 0:cb0046a629c1 106 ctrl_reg1.bits.ACTIVE = 0;
dudmuck 0:cb0046a629c1 107 write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
dudmuck 0:cb0046a629c1 108 ctrl_reg1.bits.DR = 3; //Set device in 100 Hz ODR, Standby
dudmuck 0:cb0046a629c1 109 write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
dudmuck 0:cb0046a629c1 110
dudmuck 0:cb0046a629c1 111 /* Step 2: Enable X and Y Axes and enable the latch: Register 0x1D Configuration Register */
dudmuck 0:cb0046a629c1 112 transient_cfg.octet = 0;
dudmuck 0:cb0046a629c1 113 transient_cfg.bits.ELE = 1; // enable latch
dudmuck 0:cb0046a629c1 114 transient_cfg.bits.YTEFE = 1; // enable Y
dudmuck 0:cb0046a629c1 115 transient_cfg.bits.XTEFE = 1; // enable X
dudmuck 0:cb0046a629c1 116 transient_cfg.bits.ZTEFE = 1; // enable Z
dudmuck 0:cb0046a629c1 117 write(MMA8451_TRANSIENT_CFG, transient_cfg.octet);
dudmuck 0:cb0046a629c1 118
dudmuck 0:cb0046a629c1 119 /* Step 3: Set the Threshold: Register 0x1F
dudmuck 0:cb0046a629c1 120 * Note: Step count is 0.063g per count, 0.5g / 0.063g = 7.93.
dudmuck 0:cb0046a629c1 121 * Therefore set the threshold to 8 counts */
dudmuck 0:cb0046a629c1 122 write(MMA8451_TRANSIENT_THS, 8);
dudmuck 0:cb0046a629c1 123
dudmuck 0:cb0046a629c1 124 /* Step 4: Set the Debounce Counter for 50 ms: Register 0x20
dudmuck 0:cb0046a629c1 125 * Note: 100 Hz ODR, therefore 10 ms step sizes */
dudmuck 0:cb0046a629c1 126 write(MMA8451_TRANSIENT_COUNT, 5);
dudmuck 0:cb0046a629c1 127
dudmuck 0:cb0046a629c1 128 /* Step 5: Enable Transient Detection Interrupt in the System (CTRL_REG4) */
dudmuck 0:cb0046a629c1 129 ctrl_reg4.octet = 0;
dudmuck 0:cb0046a629c1 130 ctrl_reg4.bits.INT_EN_TRANS = 1;
dudmuck 0:cb0046a629c1 131 write(MMA8451_CTRL_REG4, ctrl_reg4.octet);
dudmuck 0:cb0046a629c1 132
dudmuck 0:cb0046a629c1 133 /* Step 6: Route the Transient Interrupt to INT 1 hardware pin (CTRL_REG5) */
dudmuck 0:cb0046a629c1 134 ctrl_reg5.octet = 0;
dudmuck 0:cb0046a629c1 135 ctrl_reg5.bits.INT_CFG_TRANS = 1;
dudmuck 0:cb0046a629c1 136 write(MMA8451_CTRL_REG5, ctrl_reg5.octet);
dudmuck 0:cb0046a629c1 137
dudmuck 0:cb0046a629c1 138 /* Step 7: Put the device in Active Mode: Register 0x2A CTRL_REG1 */
dudmuck 0:cb0046a629c1 139 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
dudmuck 0:cb0046a629c1 140 ctrl_reg1.bits.ACTIVE = 1;
dudmuck 0:cb0046a629c1 141 write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
dudmuck 0:cb0046a629c1 142
dudmuck 0:cb0046a629c1 143 /* Step 8: Write Interrupt Service Routine Reading the
dudmuck 0:cb0046a629c1 144 * System Interrupt Status and the Transient Status */
dudmuck 0:cb0046a629c1 145 }
dudmuck 0:cb0046a629c1 146
dudmuck 1:778b685c3ad0 147 void MMA8451Q::service()
dudmuck 1:778b685c3ad0 148 {
dudmuck 1:778b685c3ad0 149 mma_int_source_t int_src;
dudmuck 1:778b685c3ad0 150 if (m_int_pin)
dudmuck 1:778b685c3ad0 151 return; // no interrupt
dudmuck 1:778b685c3ad0 152
dudmuck 1:778b685c3ad0 153 int_src.octet = read_single(MMA8451_INT_SOURCE);
dudmuck 1:778b685c3ad0 154
dudmuck 1:778b685c3ad0 155 if (int_src.bits.SRC_DRDY) {
dudmuck 1:778b685c3ad0 156 read(MMA8451_OUT_X_MSB, out.octets, 6);
dudmuck 1:778b685c3ad0 157 }
dudmuck 1:778b685c3ad0 158 if (int_src.bits.SRC_FF_MT) {
dudmuck 1:778b685c3ad0 159 read_single(MMA8451_FF_MT_SRC);
dudmuck 1:778b685c3ad0 160 }
dudmuck 1:778b685c3ad0 161 if (int_src.bits.SRC_PULSE) {
dudmuck 1:778b685c3ad0 162 read_single(MMA8451_PULSE_SRC);
dudmuck 1:778b685c3ad0 163 }
dudmuck 1:778b685c3ad0 164 if (int_src.bits.SRC_LNDPRT) {
dudmuck 1:778b685c3ad0 165 read_single(MMA8451_PL_STATUS);
dudmuck 1:778b685c3ad0 166 }
dudmuck 1:778b685c3ad0 167 if (int_src.bits.SRC_TRANS) {
dudmuck 1:778b685c3ad0 168 transient_src_t t_src;
dudmuck 1:778b685c3ad0 169 t_src.octet = read_single(MMA8451_TRANSIENT_SRC);
dudmuck 1:778b685c3ad0 170 printf("transient src:%x ", t_src.octet);
dudmuck 1:778b685c3ad0 171 if (t_src.bits.XTRANSE)
dudmuck 1:778b685c3ad0 172 printf("X_Pol:%d ", t_src.bits.X_Trans_Pol);
dudmuck 1:778b685c3ad0 173 if (t_src.bits.YTRANSE)
dudmuck 1:778b685c3ad0 174 printf("Y_Pol:%d ", t_src.bits.Y_Trans_Pol);
dudmuck 1:778b685c3ad0 175 if (t_src.bits.ZTRANSE)
dudmuck 1:778b685c3ad0 176 printf("Z_Pol:%d ", t_src.bits.Z_Trans_Pol);
dudmuck 1:778b685c3ad0 177 printf("\n");
dudmuck 1:778b685c3ad0 178 }
dudmuck 1:778b685c3ad0 179
dudmuck 1:778b685c3ad0 180 if (int_src.bits.SRC_ASLP) {
dudmuck 1:778b685c3ad0 181 read_single(MMA8451_SYSMOD);
dudmuck 1:778b685c3ad0 182 }
dudmuck 1:778b685c3ad0 183
dudmuck 1:778b685c3ad0 184 }