Driver for the AKM AK9752 IR sensor device.
Library for the AK9752 Ultra-Small IR Sensor with I2C Interface. Includes integrated temperature sensor (0 - 50C) and 16-bit ADC.
AK9752.cpp
- Committer:
- tkstreet
- Date:
- 2016-11-02
- Revision:
- 5:a979c36482fc
- Parent:
- 4:2f4c8e641ce9
- Child:
- 6:254b7e5820e7
File content as of revision 5:a979c36482fc:
#include "AK9752.h" #include "AK9752_reg.h" #include "debug.h" #define CONV16I(high,low) ((int16_t)(((high) << 8) | (low))) #define LEN_ONE_BYTE 1 /**<! Data length of 1 byte data. */ #define LEN_BUF_THRESHOLD 8 /**<! Data length of Threshold settings. From THIRH to THTMPL */ #define LEN_BUF_IR_DATA 7 /**<! Data length of IR sensor data. From ST1 to ST2. */ #define VAL_SOFTWARE_RESET 0x01 #define ST1_STATUS_FLAG_DRDY 0x01 #define INT_STATUS_FLAG_DR 0x01 #define INT_STATUS_FLAG_TMPL 0x02 #define INT_STATUS_FLAG_TMPH 0x04 #define INT_STATUS_FLAG_IRL 0x08 #define INT_STATUS_FLAG_IRH 0x10 #define INT_STATUS_MASK 0x1F #define ST2_STATUS_FLAG_DOR 0x01 AK9752::AK9752() { } void AK9752::init(I2C *conn, SlaveAddress addr) { slaveAddress = addr; connection = conn; } AK9752::Status AK9752::checkConnection() { // Gets the WIA register value - ID and ID2 char buf[2]; if ((AK9752::read(AK9752_REG_ADDR_WIA1, buf, 2)) != AK9752::SUCCESS) { MSG("WIA1/WIA2 Read Operation Failed.\r\n"); return AK9752::ERROR; } // Manufacturer is AKM _and_ device is AK9752 _or_ device is AK9752-Prototype if ( (buf[0] == AK9752_REG_VALUE_WIA1) && ((buf[1] == AK9752_REG_VALUE_WIA2) || (buf[1] == AK9752_REG_VALUE_WIA2P)) ) { MSG("Manufacturer and Device ID Check Passed.\r\n"); return AK9752::SUCCESS; } else { MSG("ID check failed.\r\n"); MSG("WIA1: %d\r\n", buf[0]); MSG("WIA2: %d\r\n", buf[1]); return AK9752::ERROR; } } AK9752::Status AK9752::read(char registerAddress, char *buf, int length) { // Writes the first register address if (connection->write((slaveAddress << 1), ®isterAddress, LEN_ONE_BYTE) != 0) { // I2C write failed. MSG("Error: I2C write failure.\r\n"); return AK9752::ERROR_I2C_WRITE; } // Reads register data if (connection->read((slaveAddress << 1), buf, length) != 0) { // I2C read failed. MSG("Error: I2C read failure.\r\n"); return AK9752::ERROR_I2C_READ; } return AK9752::SUCCESS; } AK9752::Status AK9752::write(char registerAddress, const char *buf, int length) { int bufLength = length + 1; char data[bufLength]; // Creates data to be sent. data[0] = registerAddress; for (int i=0; i < length; i++) { data[1+i] = buf[i]; } // Writes data. if (connection->write((slaveAddress << 1), data, bufLength) != 0) { // I2C write failed. return AK9752::ERROR_I2C_WRITE; } return AK9752::SUCCESS; } AK9752::Status AK9752::getInterruptEnable(InterruptStatus *intStatus){ Status status; char buf = 0; if((status=read(AK9752_REG_ADDR_INTEN, &buf, LEN_ONE_BYTE)) != SUCCESS) { return status; } intStatus->irh = ((buf & INT_STATUS_FLAG_IRH) > 0) ? true : false; intStatus->irl = ((buf & INT_STATUS_FLAG_IRL) > 0) ? true : false; intStatus->tmph = ((buf & INT_STATUS_FLAG_TMPH) > 0) ? true : false; intStatus->tmpl = ((buf & INT_STATUS_FLAG_TMPL) > 0) ? true : false; intStatus->dr = ((buf & INT_STATUS_FLAG_DR) > 0) ? true : false; return SUCCESS; } AK9752::Status AK9752::setInterruptEnable(const AK9752::InterruptStatus *intStatus) { char buf = 0; buf += intStatus->irh ? INT_STATUS_FLAG_IRH : 0; buf += intStatus->irl ? INT_STATUS_FLAG_IRL : 0; buf += intStatus->tmph ? INT_STATUS_FLAG_TMPH : 0; buf += intStatus->tmpl ? INT_STATUS_FLAG_TMPL : 0; buf += intStatus->dr ? INT_STATUS_FLAG_DR : 0; Status status; if ((status=write(AK9752_REG_ADDR_INTEN, &buf, LEN_ONE_BYTE)) != SUCCESS) { return status; } char readback = 0; if ((status=read(AK9752_REG_ADDR_INTEN, &readback, LEN_ONE_BYTE)) != SUCCESS) { return status; } if ((readback & INT_STATUS_MASK) != buf) { return ERROR; } return SUCCESS; } AK9752::Status AK9752::getData(char *buf) { Status status; if ((status=read(AK9752_REG_ADDR_ST1, buf, LEN_BUF_IR_DATA)) != SUCCESS) { return status; } return SUCCESS; } AK9752::Status AK9752::setThreshold(const Threshold *th) { Status status; char buf[LEN_BUF_THRESHOLD]; buf[0] = (char)(((uint16_t)th->thirh & 0x00FF)); // THIRHL buf[1] = (char)(((uint16_t)th->thirh & 0xFF00) >> 8); // THIRHH buf[2] = (char)(((uint16_t)th->thirl & 0x00FF)); // THIRLL buf[3] = (char)(((uint16_t)th->thirl & 0xFF00) >> 8); // THIRLH buf[4] = (char)(((uint16_t)th->thtmph & 0x00FF)); // THTMPHL buf[5] = (char)(((uint16_t)th->thtmph & 0xFF00) >> 8); // THTMPHH buf[6] = (char)(((uint16_t)th->thtmpl & 0x00FF)); // THTMPLL buf[7] = (char)(((uint16_t)th->thtmpl & 0xFF00) >> 8); // THTMPLH if ((status=write(AK9752_REG_ADDR_THIRHL, buf, LEN_BUF_THRESHOLD)) != SUCCESS) { return status; } return SUCCESS; } AK9752::Status AK9752::getThreshold(Threshold *th) { Status status; char buf[LEN_BUF_THRESHOLD]; if ((status=read(AK9752_REG_ADDR_THIRHL, buf, LEN_BUF_THRESHOLD)) != SUCCESS) { return status; } th->thirh = CONV16I(buf[1], buf[0]); th->thirl = CONV16I(buf[3], buf[2]); th->thtmph = CONV16I(buf[5], buf[4]); th->thtmpl = CONV16I(buf[7], buf[6]); return SUCCESS; } AK9752::Status AK9752::getOperationMode(OperationMode *mode, FcTmp *fc_tmp, FcIr *fc_ir){ Status status; char buf[2]; if ((status=read(AK9752_REG_ADDR_CNTL1, buf, 2)) != SUCCESS) { return status; } *fc_tmp = AK9752::FcTmp((buf[0] & 0x1C)>>2); *fc_ir = AK9752::FcIr(buf[0] & 0x03); *mode = AK9752::OperationMode(buf[1] & 0x03); return SUCCESS; } AK9752::Status AK9752::setOperationMode(OperationMode mode, FcTmp fc_tmp, FcIr fc_ir){ Status status; char buf[2]; buf[0] = (fc_tmp<<2 | fc_ir&0x03); buf[1] = mode; if ((status=write(AK9752_REG_ADDR_CNTL1, buf, 2)) != SUCCESS) { return status; } return SUCCESS; } AK9752::Status AK9752::reset() { Status status; char val = VAL_SOFTWARE_RESET; if ((status=write(AK9752_REG_ADDR_CNTL3, &val, LEN_ONE_BYTE)) != SUCCESS) { return status; } return SUCCESS; } AK9752::Status AK9752::getSensorData(AK9752::SensorData *data) { Status status; char buf[LEN_BUF_IR_DATA]; if ((status=getData(buf)) != SUCCESS) { return status; } // check DRDY if( (buf[0] & ST1_STATUS_FLAG_DRDY) == 0 ){ // DRDY=0, data not ready return ERROR; } // Interrupt Status data->intStatus.irh = ((buf[1] & INT_STATUS_FLAG_IRH) > 0) ? true : false; data->intStatus.irl = ((buf[1] & INT_STATUS_FLAG_IRL) > 0) ? true : false; data->intStatus.tmph = ((buf[1] & INT_STATUS_FLAG_TMPH) > 0) ? true : false; data->intStatus.tmpl = ((buf[1] & INT_STATUS_FLAG_TMPL) > 0) ? true : false; data->intStatus.dr = ((buf[1] & INT_STATUS_FLAG_DR) > 0) ? true : false; // IR sensor data data->ir = (int16_t)((buf[3] << 8) | buf[2]); // Temperature sensor data data->temperature = (int16_t)((buf[5] << 8) | buf[4]); // DOR Status data->dor = ((buf[1] & ST2_STATUS_FLAG_DOR) > 0) ? true : false; return SUCCESS; }