Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of AK9752 by
AK9752.cpp
- Committer:
- tkstreet
- Date:
- 2016-11-01
- Revision:
- 1:2035a4a54d3f
- Parent:
- 0:51fa46d39a3e
File content as of revision 1:2035a4a54d3f:
#include "AK9752.h"
#include "AK9752_reg.h"
/**
* Combine low and high int8_t bytes of Temp/IR data and store in int16_t variable
*/
#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: ST1,INTCAUSE,IR(16),TMP(16),ST2. */
#define VAL_SOFTWARE_RESET 0x01 /**<! Software reset value. */
#define ST1_STATUS_FLAG_DRDY 0x01 /**<! Data Ready*/
#define INT_STATUS_FLAG_DR 0x01 /**<! Data Read */
#define INT_STATUS_FLAG_TMPL 0x02 /**<! Temp low threshold reached */
#define INT_STATUS_FLAG_TMPH 0x04 /**<! Temp high threshold reached */
#define INT_STATUS_FLAG_IRL 0x08 /**<! IR low threshold reached */
#define INT_STATUS_FLAG_IRH 0x10 /**<! IR high threshold reached */
#define INT_STATUS_MASK 0x1F /**<! Mask highest 3 bits of status */
#define ST2_STATUS_FLAG_DOR 0x01 /**<! Data overrun (data read is required) */
AK9752::AK9752() {
}
void AK9752::init(I2C *conn, SlaveAddress addr) {
slaveAddress = addr;
connection = conn;
}
AK9752::Status AK9752::checkConnection() {
AK9752::Status status = AK9752::SUCCESS;
// Gets the WIA register value.
char buf[2];
if ((status=AK9752::read(AK9752_REG_ADDR_WIA1, buf, 2)) != SUCCESS) {
return status;
}
// Checks the obtained value equals to the supposed value.
if ( (buf[0] != AK9752_REG_VALUE_WIA1) || (buf[1] != AK9752_REG_VALUE_WIA2) ) {
return AK9752::ERROR;
}
return status;
}
AK9752::Status AK9752::read(char registerAddress, char *buf, int length) {
// Tell slave address of where to read data
if (connection->write((slaveAddress << 1), ®isterAddress, LEN_ONE_BYTE) != 0) {
// I2C write failed.
return AK9752::ERROR_I2C_WRITE;
}
// Read register data (converts 7-bit address to 8-bit)
if (connection->read((slaveAddress << 1), buf, length) != 0) {
// I2C read failed.
return AK9752::ERROR_I2C_READ;
}
return AK9752::SUCCESS;
}
AK9752::Status AK9752::write(char registerAddress, const char *buf, int length) {
int bufLength = length + 1; // Increase size to account for address byte
char data[bufLength];
// Creates data to be sent.
data[0] = registerAddress; // Place register address in first byte
for (int i=0; i < length; i++) {
data[1+i] = buf[i]; // Load write data starting at second byte (i.e. data[1])
}
// Initiate I2C write command
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; // Read failed
}
// Set interrupt status flags individually
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; // Read succeeded
}
AK9752::Status AK9752::setInterruptEnable(const InterruptStatus *intStatus) {
char buf = 0;
// If interrupt bit is 1, set corresponding buf bit to 1, otherwise set to 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;
// Perform interrupt status write operation
Status status;
if ((status=write(AK9752_REG_ADDR_INTEN, &buf, LEN_ONE_BYTE)) != SUCCESS) {
return status;
}
// Read back the interrupt status
char readback = 0;
if ((status=read(AK9752_REG_ADDR_INTEN, &readback, LEN_ONE_BYTE)) != SUCCESS) {
return status; // Read back operation failed
}
if ((readback & INT_STATUS_MASK) != buf) {
return ERROR; // Read back succeeded, but values incorrect
}
return SUCCESS;
}
AK9752::Status AK9752::setThreshold(const Threshold *th) {
Status status;
char buf[LEN_BUF_THRESHOLD];
// Mask off irrelevant byte, cast 8-bit values to 16-bit
//
buf[0] = (char)(((uint16_t)th->thirh & 0x00FF)); // THIRHL Register
buf[1] = (char)(((uint16_t)th->thirh & 0xFF00) >> 8); // THIRHH Register
buf[2] = (char)(((uint16_t)th->thirl & 0x00FF)); // THIRLL Register
buf[3] = (char)(((uint16_t)th->thirl & 0xFF00) >> 8); // THIRLH Register
buf[4] = (char)(((uint16_t)th->thtmph & 0x00FF)); // THTMPHL Register
buf[5] = (char)(((uint16_t)th->thtmph & 0xFF00) >> 8); // THTMPHH Register
buf[6] = (char)(((uint16_t)th->thtmpl & 0x00FF)); // THTMPLL Register
buf[7] = (char)(((uint16_t)th->thtmpl & 0xFF00) >> 8); // THTMPLH Register
// Perform threshold register write operaton
if ((status=write(AK9752_REG_ADDR_THIRHL, buf, LEN_BUF_THRESHOLD)) != SUCCESS) {
return status; // Write operation failed
}
return SUCCESS; // Write operation succeeded
}
AK9752::Status AK9752::getThreshold(Threshold *th) {
Status status;
char buf[LEN_BUF_THRESHOLD];
// Perform threshold register read operation
if ((status=read(AK9752_REG_ADDR_THIRHL, buf, LEN_BUF_THRESHOLD)) != SUCCESS) {
return status; // Read operation failed
}
// Combine low and high bytes of data
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; // Read operation succeeded
}
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; // Read operation failed
}
*fc_tmp = AK9752::FcTmp((buf[0] & 0x1C)>>2); // Read CNTL1[2]-CNTL1[4]
*fc_ir = AK9752::FcIr(buf[0] & 0x03); // Read CNTL1[0]-CNTL1[1]
*mode = AK9752::OperationMode(buf[1] & 0x03); // Read CNTL2[0]-CNTL2[1]
return SUCCESS; // Read operation succeeded
}
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); // Combine FCTMP & FCIR in 1 byte
buf[1] = mode;
// Write 2 bytes starting from CNTL1 -> write CNTL1 and CNTL2
if ((status=write(AK9752_REG_ADDR_CNTL1, buf, 2)) != SUCCESS) {
return status; // Write operation failed
}
return SUCCESS; // Write operation succeeded
}
AK9752::Status AK9752::reset() {
Status status;
char val = VAL_SOFTWARE_RESET; // char instance required for write()
if ((status=write(AK9752_REG_ADDR_CNTL3, &val, LEN_ONE_BYTE)) != SUCCESS) {
return status; // Write operation failed
}
return SUCCESS; // Write operation succeeded
}
AK9752::Status AK9752::getSensorData(SensorData *data) {
char buf[LEN_BUF_IR_DATA];
// Read 7 bytes starting at ST1: reads ST1, INTCAUSE, data and ST2 at once
if ((read(AK9752_REG_ADDR_ST1, buf, LEN_BUF_IR_DATA)) != SUCCESS) {
return ERROR; // Read operation failed
}
// Check Data ReaDY
if( (buf[0] & ST1_STATUS_FLAG_DRDY) == 0 ){ // DRDY=0, data not ready
return ERROR;
}
// Read IR threshold, temp threshold and data ready flags
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;
// Extract IR sensor data
data->ir = (int16_t)((buf[3] << 8) | buf[2]); // Combine IRL & IRH
// Extract Temperature sensor data
data->temperature = (int16_t)((buf[5] << 8) | buf[4]); // Combine TMPL & TMPH
// Extract Data Overrun status
data->dor = ((buf[1] & ST2_STATUS_FLAG_DOR) > 0) ? true : false;
return SUCCESS;
}
