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.

Revision:
6:254b7e5820e7
Parent:
5:a979c36482fc
Parent:
3:2035a4a54d3f
Child:
8:40dcaa912883
Child:
9:45495ac12b89
--- a/AK9752.cpp	Wed Nov 02 17:34:13 2016 +0000
+++ b/AK9752.cpp	Wed Nov 02 17:41:22 2016 +0000
@@ -2,20 +2,23 @@
 #include "AK9752_reg.h"
 #include "debug.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. 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
+#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() {
@@ -51,14 +54,14 @@
 }
 
 AK9752::Status AK9752::read(char registerAddress, char *buf, int length) {
-    // Writes the first register address
+    // Tell slave address of where to read data
     if (connection->write((slaveAddress << 1), &registerAddress, LEN_ONE_BYTE) != 0) {
         // I2C write failed.
         MSG("Error: I2C write failure.\r\n");
         return AK9752::ERROR_I2C_WRITE;
     }
     
-    // Reads register data
+    // Read register data (converts 7-bit address to 8-bit)
     if (connection->read((slaveAddress << 1), buf, length) != 0) {
         // I2C read failed.
         MSG("Error: I2C read failure.\r\n");
@@ -69,16 +72,16 @@
 }
 
 AK9752::Status AK9752::write(char registerAddress, const char *buf, int length) {
-    int bufLength = length + 1;
+    int bufLength = length + 1; // Increase size to account for address byte
     char data[bufLength];
 
     // Creates data to be sent.
-    data[0] = registerAddress;    
+    data[0] = registerAddress;           // Place register address in first byte 
     for (int i=0; i < length; i++) {
-        data[1+i] = buf[i];
+        data[1+i] = buf[i];              // Load write data starting at second byte (i.e. data[1])
     }
     
-    // Writes data. 
+    // Initiate I2C write command
     if (connection->write((slaveAddress << 1), data, bufLength) != 0) {
         // I2C write failed.
         return AK9752::ERROR_I2C_WRITE;
@@ -92,48 +95,45 @@
     
     char buf = 0;
     if((status=read(AK9752_REG_ADDR_INTEN, &buf, LEN_ONE_BYTE)) != SUCCESS) {
-        return status;
+        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;
+    return SUCCESS;     // Read succeeded
 }
 
-AK9752::Status AK9752::setInterruptEnable(const AK9752::InterruptStatus *intStatus) {
+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;
-    }
-    if ((readback & INT_STATUS_MASK) != buf) {
-        return ERROR;
+        return status;  // Read back operation failed
     }
     
-    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;
+    if ((readback & INT_STATUS_MASK) != buf) {
+        return ERROR;   // Read back succeeded, but values incorrect
     }
+    
     return SUCCESS;
 }
 
@@ -141,101 +141,110 @@
     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
+    // 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;
+        return status;  // Write operation failed
     }
 
-    return SUCCESS;
+    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;
+        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;
+    return SUCCESS;     // Read operation succeeded
 }
 
 AK9752::Status AK9752::getOperationMode(OperationMode *mode, FcTmp *fc_tmp, FcIr *fc_ir){
-        Status status;
+    Status status;
     
     char buf[2];
     if ((status=read(AK9752_REG_ADDR_CNTL1, buf, 2)) != SUCCESS) {
-        return status;
+        return status;  // Read operation failed
     }
-    *fc_tmp = AK9752::FcTmp((buf[0] & 0x1C)>>2);
-    *fc_ir = AK9752::FcIr(buf[0] & 0x03);
-    *mode = AK9752::OperationMode(buf[1] & 0x03);
     
-    return SUCCESS;
+    *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);
+    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;
+        return status;  // Write operation failed
     }
-    return SUCCESS;
+    return SUCCESS;     // Write operation succeeded
 }
 
 AK9752::Status AK9752::reset() {
     Status status;
-    char val = VAL_SOFTWARE_RESET;
+    
+    char val = VAL_SOFTWARE_RESET;      // char instance required for write()
     if ((status=write(AK9752_REG_ADDR_CNTL3, &val, LEN_ONE_BYTE)) != SUCCESS) {
-        return status;
+        return status;  // Write operation failed
     }    
-    return SUCCESS;
+    return SUCCESS;     // Write operation succeeded
 }
 
-AK9752::Status AK9752::getSensorData(AK9752::SensorData *data) {
-    Status status;
+AK9752::Status AK9752::getSensorData(SensorData *data) {
+    
     char buf[LEN_BUF_IR_DATA];
     
-    if ((status=getData(buf)) != SUCCESS) {
-        return status;
+    // 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 DRDY 
-    if( (buf[0] & ST1_STATUS_FLAG_DRDY) == 0 ){
-        // DRDY=0, data not ready
+    // Check Data ReaDY 
+    if( (buf[0] & ST1_STATUS_FLAG_DRDY) == 0 ){     // DRDY=0, data not ready
         return ERROR;
     }
     
-    // Interrupt Status
+    // 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;
     
-    // IR sensor data
-    data->ir = (int16_t)((buf[3] << 8) | buf[2]);
+    // Extract IR sensor data
+    data->ir = (int16_t)((buf[3] << 8) | buf[2]); // Combine IRL & IRH
     
-    // Temperature sensor data
-    data->temperature = (int16_t)((buf[5] << 8) | buf[4]);
+    // Extract Temperature sensor data
+    data->temperature = (int16_t)((buf[5] << 8) | buf[4]);  // Combine TMPL & TMPH
 
-    // DOR Status
+    // Extract Data Overrun status
     data->dor = ((buf[1] & ST2_STATUS_FLAG_DOR) > 0) ? true : false;
     
     return SUCCESS;