Driver for the AKM AK9752 IR sensor device.

Dependents:   AKDP-RevD7_014

Library for the AK9752 Ultra-Small IR Sensor with I2C Interface. Includes integrated temperature sensor (0 - 50C) and 16-bit ADC.

Committer:
tkstreet
Date:
Wed Nov 02 00:14:52 2016 +0000
Revision:
4:2f4c8e641ce9
Parent:
1:0b59cfeee8ee
Child:
5:a979c36482fc
AK9752 working version. ID2 checking needs debugging.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
masahikofukasawa 0:51fa46d39a3e 1 #include "AK9752.h"
masahikofukasawa 0:51fa46d39a3e 2 #include "AK9752_reg.h"
tkstreet 4:2f4c8e641ce9 3 #include "debug.h"
masahikofukasawa 0:51fa46d39a3e 4
masahikofukasawa 0:51fa46d39a3e 5 #define CONV16I(high,low) ((int16_t)(((high) << 8) | (low)))
masahikofukasawa 0:51fa46d39a3e 6
masahikofukasawa 0:51fa46d39a3e 7 #define LEN_ONE_BYTE 1 /**<! Data length of 1 byte data. */
masahikofukasawa 0:51fa46d39a3e 8 #define LEN_BUF_THRESHOLD 8 /**<! Data length of Threshold settings. From THIRH to THTMPL */
masahikofukasawa 0:51fa46d39a3e 9 #define LEN_BUF_IR_DATA 7 /**<! Data length of IR sensor data. From ST1 to ST2. */
masahikofukasawa 0:51fa46d39a3e 10 #define VAL_SOFTWARE_RESET 0x01
masahikofukasawa 0:51fa46d39a3e 11 #define ST1_STATUS_FLAG_DRDY 0x01
masahikofukasawa 0:51fa46d39a3e 12 #define INT_STATUS_FLAG_DR 0x01
masahikofukasawa 0:51fa46d39a3e 13 #define INT_STATUS_FLAG_TMPL 0x02
masahikofukasawa 0:51fa46d39a3e 14 #define INT_STATUS_FLAG_TMPH 0x04
masahikofukasawa 0:51fa46d39a3e 15 #define INT_STATUS_FLAG_IRL 0x08
masahikofukasawa 0:51fa46d39a3e 16 #define INT_STATUS_FLAG_IRH 0x10
masahikofukasawa 0:51fa46d39a3e 17 #define INT_STATUS_MASK 0x1F
masahikofukasawa 0:51fa46d39a3e 18 #define ST2_STATUS_FLAG_DOR 0x01
masahikofukasawa 0:51fa46d39a3e 19
masahikofukasawa 0:51fa46d39a3e 20
masahikofukasawa 0:51fa46d39a3e 21 AK9752::AK9752() {
masahikofukasawa 0:51fa46d39a3e 22 }
masahikofukasawa 0:51fa46d39a3e 23
masahikofukasawa 0:51fa46d39a3e 24 void AK9752::init(I2C *conn, SlaveAddress addr) {
masahikofukasawa 0:51fa46d39a3e 25 slaveAddress = addr;
masahikofukasawa 0:51fa46d39a3e 26 connection = conn;
masahikofukasawa 0:51fa46d39a3e 27 }
masahikofukasawa 0:51fa46d39a3e 28
masahikofukasawa 0:51fa46d39a3e 29 AK9752::Status AK9752::checkConnection() {
tkstreet 4:2f4c8e641ce9 30 //AK9752::Status status = AK9752::SUCCESS;
masahikofukasawa 0:51fa46d39a3e 31
tkstreet 4:2f4c8e641ce9 32 // Gets the WIA register value - ID and ID2
masahikofukasawa 0:51fa46d39a3e 33 char buf[2];
tkstreet 4:2f4c8e641ce9 34 if ((AK9752::read(AK9752_REG_ADDR_WIA1, buf, 2)) != AK9752::SUCCESS) {
tkstreet 4:2f4c8e641ce9 35 MSG("Read of WIA1 failed.\r\n");
tkstreet 4:2f4c8e641ce9 36 return AK9752::ERROR;
masahikofukasawa 0:51fa46d39a3e 37 }
masahikofukasawa 0:51fa46d39a3e 38
masahikofukasawa 0:51fa46d39a3e 39 // Checks the obtained value equals to the supposed value.
tkstreet 4:2f4c8e641ce9 40 if ( (buf1 != AK9752_REG_VALUE_WIA1) || (buf2 != AK9752_REG_VALUE_WIA2) ) {
tkstreet 4:2f4c8e641ce9 41 MSG("ID check failed.\r\n");
tkstreet 4:2f4c8e641ce9 42 MSG("WIA1: %d\r\n", buf[0]);
tkstreet 4:2f4c8e641ce9 43 MSG("WIA2: %d\r\n", buf[1]);
tkstreet 4:2f4c8e641ce9 44 // return AK9752::ERROR;
masahikofukasawa 0:51fa46d39a3e 45 }
masahikofukasawa 0:51fa46d39a3e 46
tkstreet 4:2f4c8e641ce9 47 return AK9752::SUCCESS;
masahikofukasawa 0:51fa46d39a3e 48 }
masahikofukasawa 0:51fa46d39a3e 49
masahikofukasawa 0:51fa46d39a3e 50 AK9752::Status AK9752::read(char registerAddress, char *buf, int length) {
masahikofukasawa 1:0b59cfeee8ee 51 // Writes the first register address
masahikofukasawa 0:51fa46d39a3e 52 if (connection->write((slaveAddress << 1), &registerAddress, LEN_ONE_BYTE) != 0) {
masahikofukasawa 0:51fa46d39a3e 53 // I2C write failed.
tkstreet 4:2f4c8e641ce9 54 MSG("Error: I2C write failure.\r\n");
masahikofukasawa 0:51fa46d39a3e 55 return AK9752::ERROR_I2C_WRITE;
masahikofukasawa 0:51fa46d39a3e 56 }
masahikofukasawa 0:51fa46d39a3e 57
masahikofukasawa 0:51fa46d39a3e 58 // Reads register data
masahikofukasawa 0:51fa46d39a3e 59 if (connection->read((slaveAddress << 1), buf, length) != 0) {
masahikofukasawa 0:51fa46d39a3e 60 // I2C read failed.
tkstreet 4:2f4c8e641ce9 61 MSG("Error: I2C read failure.\r\n");
masahikofukasawa 0:51fa46d39a3e 62 return AK9752::ERROR_I2C_READ;
masahikofukasawa 0:51fa46d39a3e 63 }
masahikofukasawa 0:51fa46d39a3e 64
masahikofukasawa 0:51fa46d39a3e 65 return AK9752::SUCCESS;
masahikofukasawa 0:51fa46d39a3e 66 }
masahikofukasawa 0:51fa46d39a3e 67
masahikofukasawa 0:51fa46d39a3e 68 AK9752::Status AK9752::write(char registerAddress, const char *buf, int length) {
masahikofukasawa 0:51fa46d39a3e 69 int bufLength = length + 1;
masahikofukasawa 0:51fa46d39a3e 70 char data[bufLength];
masahikofukasawa 0:51fa46d39a3e 71
masahikofukasawa 0:51fa46d39a3e 72 // Creates data to be sent.
masahikofukasawa 0:51fa46d39a3e 73 data[0] = registerAddress;
masahikofukasawa 0:51fa46d39a3e 74 for (int i=0; i < length; i++) {
masahikofukasawa 0:51fa46d39a3e 75 data[1+i] = buf[i];
masahikofukasawa 0:51fa46d39a3e 76 }
masahikofukasawa 0:51fa46d39a3e 77
masahikofukasawa 1:0b59cfeee8ee 78 // Writes data.
masahikofukasawa 0:51fa46d39a3e 79 if (connection->write((slaveAddress << 1), data, bufLength) != 0) {
masahikofukasawa 0:51fa46d39a3e 80 // I2C write failed.
masahikofukasawa 0:51fa46d39a3e 81 return AK9752::ERROR_I2C_WRITE;
masahikofukasawa 0:51fa46d39a3e 82 }
masahikofukasawa 0:51fa46d39a3e 83
masahikofukasawa 0:51fa46d39a3e 84 return AK9752::SUCCESS;
masahikofukasawa 0:51fa46d39a3e 85 }
masahikofukasawa 0:51fa46d39a3e 86
masahikofukasawa 0:51fa46d39a3e 87 AK9752::Status AK9752::getInterruptEnable(InterruptStatus *intStatus){
masahikofukasawa 0:51fa46d39a3e 88 Status status;
masahikofukasawa 0:51fa46d39a3e 89
masahikofukasawa 0:51fa46d39a3e 90 char buf = 0;
masahikofukasawa 0:51fa46d39a3e 91 if((status=read(AK9752_REG_ADDR_INTEN, &buf, LEN_ONE_BYTE)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 92 return status;
masahikofukasawa 0:51fa46d39a3e 93 }
masahikofukasawa 0:51fa46d39a3e 94
masahikofukasawa 0:51fa46d39a3e 95 intStatus->irh = ((buf & INT_STATUS_FLAG_IRH) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 96 intStatus->irl = ((buf & INT_STATUS_FLAG_IRL) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 97 intStatus->tmph = ((buf & INT_STATUS_FLAG_TMPH) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 98 intStatus->tmpl = ((buf & INT_STATUS_FLAG_TMPL) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 99 intStatus->dr = ((buf & INT_STATUS_FLAG_DR) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 100
masahikofukasawa 0:51fa46d39a3e 101 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 102 }
masahikofukasawa 0:51fa46d39a3e 103
masahikofukasawa 0:51fa46d39a3e 104 AK9752::Status AK9752::setInterruptEnable(const AK9752::InterruptStatus *intStatus) {
masahikofukasawa 0:51fa46d39a3e 105 char buf = 0;
masahikofukasawa 0:51fa46d39a3e 106
masahikofukasawa 0:51fa46d39a3e 107 buf += intStatus->irh ? INT_STATUS_FLAG_IRH : 0;
masahikofukasawa 0:51fa46d39a3e 108 buf += intStatus->irl ? INT_STATUS_FLAG_IRL : 0;
masahikofukasawa 0:51fa46d39a3e 109 buf += intStatus->tmph ? INT_STATUS_FLAG_TMPH : 0;
masahikofukasawa 0:51fa46d39a3e 110 buf += intStatus->tmpl ? INT_STATUS_FLAG_TMPL : 0;
masahikofukasawa 0:51fa46d39a3e 111 buf += intStatus->dr ? INT_STATUS_FLAG_DR : 0;
masahikofukasawa 0:51fa46d39a3e 112
masahikofukasawa 0:51fa46d39a3e 113 Status status;
masahikofukasawa 0:51fa46d39a3e 114 if ((status=write(AK9752_REG_ADDR_INTEN, &buf, LEN_ONE_BYTE)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 115 return status;
masahikofukasawa 0:51fa46d39a3e 116 }
masahikofukasawa 0:51fa46d39a3e 117
masahikofukasawa 0:51fa46d39a3e 118 char readback = 0;
masahikofukasawa 0:51fa46d39a3e 119 if ((status=read(AK9752_REG_ADDR_INTEN, &readback, LEN_ONE_BYTE)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 120 return status;
masahikofukasawa 0:51fa46d39a3e 121 }
masahikofukasawa 0:51fa46d39a3e 122 if ((readback & INT_STATUS_MASK) != buf) {
masahikofukasawa 0:51fa46d39a3e 123 return ERROR;
masahikofukasawa 0:51fa46d39a3e 124 }
masahikofukasawa 0:51fa46d39a3e 125
masahikofukasawa 0:51fa46d39a3e 126 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 127 }
masahikofukasawa 0:51fa46d39a3e 128
masahikofukasawa 0:51fa46d39a3e 129 AK9752::Status AK9752::getData(char *buf) {
masahikofukasawa 0:51fa46d39a3e 130 Status status;
masahikofukasawa 0:51fa46d39a3e 131 if ((status=read(AK9752_REG_ADDR_ST1, buf, LEN_BUF_IR_DATA)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 132 return status;
masahikofukasawa 0:51fa46d39a3e 133 }
masahikofukasawa 0:51fa46d39a3e 134 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 135 }
masahikofukasawa 0:51fa46d39a3e 136
masahikofukasawa 0:51fa46d39a3e 137 AK9752::Status AK9752::setThreshold(const Threshold *th) {
masahikofukasawa 0:51fa46d39a3e 138 Status status;
masahikofukasawa 0:51fa46d39a3e 139 char buf[LEN_BUF_THRESHOLD];
masahikofukasawa 0:51fa46d39a3e 140
masahikofukasawa 0:51fa46d39a3e 141 buf[0] = (char)(((uint16_t)th->thirh & 0x00FF)); // THIRHL
masahikofukasawa 0:51fa46d39a3e 142 buf[1] = (char)(((uint16_t)th->thirh & 0xFF00) >> 8); // THIRHH
masahikofukasawa 0:51fa46d39a3e 143 buf[2] = (char)(((uint16_t)th->thirl & 0x00FF)); // THIRLL
masahikofukasawa 0:51fa46d39a3e 144 buf[3] = (char)(((uint16_t)th->thirl & 0xFF00) >> 8); // THIRLH
masahikofukasawa 0:51fa46d39a3e 145 buf[4] = (char)(((uint16_t)th->thtmph & 0x00FF)); // THTMPHL
masahikofukasawa 0:51fa46d39a3e 146 buf[5] = (char)(((uint16_t)th->thtmph & 0xFF00) >> 8); // THTMPHH
masahikofukasawa 0:51fa46d39a3e 147 buf[6] = (char)(((uint16_t)th->thtmpl & 0x00FF)); // THTMPLL
masahikofukasawa 0:51fa46d39a3e 148 buf[7] = (char)(((uint16_t)th->thtmpl & 0xFF00) >> 8); // THTMPLH
masahikofukasawa 0:51fa46d39a3e 149
masahikofukasawa 0:51fa46d39a3e 150 if ((status=write(AK9752_REG_ADDR_THIRHL, buf, LEN_BUF_THRESHOLD)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 151 return status;
masahikofukasawa 0:51fa46d39a3e 152 }
masahikofukasawa 0:51fa46d39a3e 153
masahikofukasawa 0:51fa46d39a3e 154 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 155 }
masahikofukasawa 0:51fa46d39a3e 156
masahikofukasawa 0:51fa46d39a3e 157 AK9752::Status AK9752::getThreshold(Threshold *th) {
masahikofukasawa 0:51fa46d39a3e 158 Status status;
masahikofukasawa 0:51fa46d39a3e 159 char buf[LEN_BUF_THRESHOLD];
masahikofukasawa 0:51fa46d39a3e 160
masahikofukasawa 0:51fa46d39a3e 161 if ((status=read(AK9752_REG_ADDR_THIRHL, buf, LEN_BUF_THRESHOLD)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 162 return status;
masahikofukasawa 0:51fa46d39a3e 163 }
masahikofukasawa 0:51fa46d39a3e 164
masahikofukasawa 0:51fa46d39a3e 165 th->thirh = CONV16I(buf[1], buf[0]);
masahikofukasawa 0:51fa46d39a3e 166 th->thirl = CONV16I(buf[3], buf[2]);
masahikofukasawa 0:51fa46d39a3e 167 th->thtmph = CONV16I(buf[5], buf[4]);
masahikofukasawa 0:51fa46d39a3e 168 th->thtmpl = CONV16I(buf[7], buf[6]);
masahikofukasawa 0:51fa46d39a3e 169
masahikofukasawa 0:51fa46d39a3e 170 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 171 }
masahikofukasawa 0:51fa46d39a3e 172
masahikofukasawa 0:51fa46d39a3e 173 AK9752::Status AK9752::getOperationMode(OperationMode *mode, FcTmp *fc_tmp, FcIr *fc_ir){
masahikofukasawa 0:51fa46d39a3e 174 Status status;
masahikofukasawa 0:51fa46d39a3e 175
masahikofukasawa 0:51fa46d39a3e 176 char buf[2];
masahikofukasawa 0:51fa46d39a3e 177 if ((status=read(AK9752_REG_ADDR_CNTL1, buf, 2)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 178 return status;
masahikofukasawa 0:51fa46d39a3e 179 }
masahikofukasawa 0:51fa46d39a3e 180 *fc_tmp = AK9752::FcTmp((buf[0] & 0x1C)>>2);
masahikofukasawa 0:51fa46d39a3e 181 *fc_ir = AK9752::FcIr(buf[0] & 0x03);
masahikofukasawa 0:51fa46d39a3e 182 *mode = AK9752::OperationMode(buf[1] & 0x03);
masahikofukasawa 0:51fa46d39a3e 183
masahikofukasawa 0:51fa46d39a3e 184 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 185 }
masahikofukasawa 0:51fa46d39a3e 186
masahikofukasawa 0:51fa46d39a3e 187 AK9752::Status AK9752::setOperationMode(OperationMode mode, FcTmp fc_tmp, FcIr fc_ir){
masahikofukasawa 0:51fa46d39a3e 188 Status status;
masahikofukasawa 0:51fa46d39a3e 189
masahikofukasawa 0:51fa46d39a3e 190 char buf[2];
masahikofukasawa 0:51fa46d39a3e 191 buf[0] = (fc_tmp<<2 | fc_ir&0x03);
masahikofukasawa 0:51fa46d39a3e 192 buf[1] = mode;
masahikofukasawa 0:51fa46d39a3e 193 if ((status=write(AK9752_REG_ADDR_CNTL1, buf, 2)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 194 return status;
masahikofukasawa 0:51fa46d39a3e 195 }
masahikofukasawa 0:51fa46d39a3e 196 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 197 }
masahikofukasawa 0:51fa46d39a3e 198
masahikofukasawa 0:51fa46d39a3e 199 AK9752::Status AK9752::reset() {
masahikofukasawa 0:51fa46d39a3e 200 Status status;
masahikofukasawa 0:51fa46d39a3e 201 char val = VAL_SOFTWARE_RESET;
masahikofukasawa 0:51fa46d39a3e 202 if ((status=write(AK9752_REG_ADDR_CNTL3, &val, LEN_ONE_BYTE)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 203 return status;
masahikofukasawa 0:51fa46d39a3e 204 }
masahikofukasawa 0:51fa46d39a3e 205 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 206 }
masahikofukasawa 0:51fa46d39a3e 207
masahikofukasawa 0:51fa46d39a3e 208 AK9752::Status AK9752::getSensorData(AK9752::SensorData *data) {
masahikofukasawa 0:51fa46d39a3e 209 Status status;
masahikofukasawa 0:51fa46d39a3e 210 char buf[LEN_BUF_IR_DATA];
masahikofukasawa 0:51fa46d39a3e 211
masahikofukasawa 0:51fa46d39a3e 212 if ((status=getData(buf)) != SUCCESS) {
masahikofukasawa 0:51fa46d39a3e 213 return status;
masahikofukasawa 0:51fa46d39a3e 214 }
masahikofukasawa 0:51fa46d39a3e 215
masahikofukasawa 0:51fa46d39a3e 216 // check DRDY
masahikofukasawa 0:51fa46d39a3e 217 if( (buf[0] & ST1_STATUS_FLAG_DRDY) == 0 ){
masahikofukasawa 0:51fa46d39a3e 218 // DRDY=0, data not ready
masahikofukasawa 0:51fa46d39a3e 219 return ERROR;
masahikofukasawa 0:51fa46d39a3e 220 }
masahikofukasawa 0:51fa46d39a3e 221
masahikofukasawa 0:51fa46d39a3e 222 // Interrupt Status
masahikofukasawa 0:51fa46d39a3e 223 data->intStatus.irh = ((buf[1] & INT_STATUS_FLAG_IRH) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 224 data->intStatus.irl = ((buf[1] & INT_STATUS_FLAG_IRL) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 225 data->intStatus.tmph = ((buf[1] & INT_STATUS_FLAG_TMPH) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 226 data->intStatus.tmpl = ((buf[1] & INT_STATUS_FLAG_TMPL) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 227 data->intStatus.dr = ((buf[1] & INT_STATUS_FLAG_DR) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 228
masahikofukasawa 0:51fa46d39a3e 229 // IR sensor data
masahikofukasawa 0:51fa46d39a3e 230 data->ir = (int16_t)((buf[3] << 8) | buf[2]);
masahikofukasawa 0:51fa46d39a3e 231
masahikofukasawa 0:51fa46d39a3e 232 // Temperature sensor data
masahikofukasawa 0:51fa46d39a3e 233 data->temperature = (int16_t)((buf[5] << 8) | buf[4]);
masahikofukasawa 0:51fa46d39a3e 234
masahikofukasawa 0:51fa46d39a3e 235 // DOR Status
masahikofukasawa 0:51fa46d39a3e 236 data->dor = ((buf[1] & ST2_STATUS_FLAG_DOR) > 0) ? true : false;
masahikofukasawa 0:51fa46d39a3e 237
masahikofukasawa 0:51fa46d39a3e 238 return SUCCESS;
masahikofukasawa 0:51fa46d39a3e 239 }