mma8451q driver with a few minor modifications
Fork of lib_mma8451q by
mma8451q.cpp@1:778b685c3ad0, 2015-05-08 (annotated)
- 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?
User | Revision | Line number | New 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 | } |