Library for Adafruit AMG8833. Forked from arduino version

Dependents:   AMG3x3

Files at this revision

API Documentation at this revision

Comitter:
hisyamfs
Date:
Fri Jun 14 12:49:30 2019 +0000
Commit message:
okey;

Changed in this revision

AMG8833.cpp Show annotated file Show diff for this revision Revisions of this file
AMG8833.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AMG8833.cpp	Fri Jun 14 12:49:30 2019 +0000
@@ -0,0 +1,351 @@
+#include "AMG8833.h"
+
+//#define I2C_DEBUG 
+
+/**************************************************************************/
+/*! 
+    @brief  Setups the I2C interface and hardware
+    @param  addr Optional I2C address the sensor can be found on. Default is 0x69
+    @returns True if device is set up, false on any failure
+*/
+/**************************************************************************/
+Adafruit_AMG88xx::Adafruit_AMG88xx(PinName mysda, PinName myscl) : _i2c(mysda, myscl)
+{
+
+}
+
+int Adafruit_AMG88xx::begin(char addr)
+{
+    _i2caddr = addr;
+    
+    //enter normal mode
+    _pctl.PCTL = AMG88xx_NORMAL_MODE;
+    write8(AMG88xx_PCTL, _pctl.get());
+    
+    //software reset
+    _rst.RST = AMG88xx_INITIAL_RESET;
+    write8(AMG88xx_RST, _rst.get());
+    
+    //disable interrupts by default
+    disableInterrupt();
+    
+    //set to 10 FPS
+    _fpsc.FPS = AMG88xx_FPS_10;
+    write8(AMG88xx_FPSC, _fpsc.get());
+
+    wait_ms(100);
+
+    return 1;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Set the moving average mode.
+    @param  mode if True is passed, output will be twice the moving average
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::setMovingAverageMode(int mode)
+{
+    _ave.MAMOD = mode;
+    write8(AMG88xx_AVE, _ave.get());
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Set the interrupt levels. The hysteresis value defaults to .95 * high
+    @param  high the value above which an interrupt will be triggered
+    @param  low the value below which an interrupt will be triggered
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::setInterruptLevels(float high, float low)
+{
+    setInterruptLevels(high, low, high * .95);
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Set the interrupt levels
+    @param  high the value above which an interrupt will be triggered
+    @param  low the value below which an interrupt will be triggered
+    @param hysteresis the hysteresis value for interrupt detection
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::setInterruptLevels(float high, float low, float hysteresis)
+{
+    int highConv = high / AMG88xx_PIXEL_TEMP_CONVERSION;
+    highConv = constrain(highConv, -4095, 4095);
+    _inthl.INT_LVL_H = highConv & 0xFF;
+    _inthh.INT_LVL_H = (highConv & 0xF) >> 4;
+    this->write8(AMG88xx_INTHL, _inthl.get());
+    this->write8(AMG88xx_INTHH, _inthh.get());
+    
+    int lowConv = low / AMG88xx_PIXEL_TEMP_CONVERSION;
+    lowConv = constrain(lowConv, -4095, 4095);
+    _intll.INT_LVL_L = lowConv & 0xFF;
+    _intlh.INT_LVL_L = (lowConv & 0xF) >> 4;
+    this->write8(AMG88xx_INTLL, _intll.get());
+    this->write8(AMG88xx_INTLH, _intlh.get());
+    
+    int hysConv = hysteresis / AMG88xx_PIXEL_TEMP_CONVERSION;
+    hysConv = constrain(hysConv, -4095, 4095);
+    _ihysl.INT_HYS = hysConv & 0xFF;
+    _ihysh.INT_HYS = (hysConv & 0xF) >> 4;
+    this->write8(AMG88xx_IHYSL, _ihysl.get());
+    this->write8(AMG88xx_IHYSH, _ihysh.get());
+}
+
+/**************************************************************************/
+/*! 
+    @brief  enable the interrupt pin on the device.
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::enableInterrupt()
+{
+    _intc.INTEN = 1;
+    this->write8(AMG88xx_INTC, _intc.get());
+}
+
+/**************************************************************************/
+/*! 
+    @brief  disable the interrupt pin on the device
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::disableInterrupt()
+{
+    _intc.INTEN = 0;
+    this->write8(AMG88xx_INTC, _intc.get());
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Set the interrupt to either absolute value or difference mode
+    @param  mode passing AMG88xx_DIFFERENCE sets the device to difference mode, AMG88xx_ABSOLUTE_VALUE sets to absolute value mode.
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::setInterruptMode(uint8_t mode)
+{
+    _intc.INTMOD = mode;
+    this->write8(AMG88xx_INTC, _intc.get());
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Read the state of the triggered interrupts on the device. The full interrupt register is 8 chars in length.
+    @param  buf the pointer to where the returned data will be stored
+    @param  size Optional number of chars to read. Default is 8 chars.
+    @returns up to 8 chars of data in buf
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::getInterrupt(uint8_t *buf, uint8_t size)
+{
+    uint8_t charsToRead = min(size, (uint8_t)8);
+    
+    this->read(AMG88xx_INT_OFFSET, buf, charsToRead);
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Clear any triggered interrupts
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::clearInterrupt()
+{
+    _rst.RST = AMG88xx_FLAG_RESET;
+    write8(AMG88xx_RST, _rst.get());
+}
+
+/**************************************************************************/
+/*! 
+    @brief  read the onboard thermistor
+    @returns a the floating point temperature in degrees Celsius
+*/
+/**************************************************************************/
+float Adafruit_AMG88xx::readThermistor()
+{
+    uint8_t raw[2];
+    this->read(AMG88xx_TTHL, raw, 2);
+    uint16_t recast = ((uint16_t) raw[1] << 8) | ((uint16_t) raw[0]);
+
+    return signedMag12ToFloat(recast) * AMG88xx_THERMISTOR_CONVERSION;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Read Infrared sensor values
+    @param  buf the array to place the pixels in
+    @param  size Optionsl number of chars to read (up to 64). Default is 64 chars.
+    @return up to 64 chars of pixel data in buf
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::readPixels(float *buf, uint8_t size)
+{
+    uint16_t recast;
+    float converted;
+    uint8_t charsToRead = min((uint8_t)(size << 1), (uint8_t)(AMG88xx_PIXEL_ARRAY_SIZE << 1));
+    uint8_t rawArray[charsToRead];
+    this->read(AMG88xx_PIXEL_OFFSET, rawArray, charsToRead);
+    
+    for(int i=0; i<size; i++){
+        uint8_t pos = i << 1;
+        recast = ((uint16_t)rawArray[pos + 1] << 8) | ((uint16_t)rawArray[pos]);
+        
+        converted = int12ToFloat(recast) * AMG88xx_PIXEL_TEMP_CONVERSION;
+        buf[i] = converted;
+    }
+}
+
+/**************************************************************************/
+/*! 
+    @brief  write one char of data to the specified register
+    @param  reg the register to write to
+    @param  value the value to write
+*/
+/**************************************************************************/
+void Adafruit_AMG88xx::write8(uint8_t reg, uint8_t value)
+{
+    this->write(reg, &value, 1);
+}
+
+/**************************************************************************/
+/*! 
+    @brief  read one char of data from the specified register
+    @param  reg the register to read
+    @returns one char of register data
+*/
+/**************************************************************************/
+uint8_t Adafruit_AMG88xx::read8(uint8_t reg)
+{
+    uint8_t ret;
+    this->read(reg, &ret, 1);
+    return ret;
+}
+
+int Adafruit_AMG88xx::read(uint8_t reg, uint8_t *buf, uint8_t num)
+{
+//  char value;
+//  char pos = 0;
+    
+//  //on arduino we need to read in AMG_I2C_CHUNKSIZE char chunks
+//  while(pos < num){
+//      char read_now = min((char)AMG_I2C_CHUNKSIZE, (char)(num - pos));
+//      Wire.beginTransmission((char)_i2caddr);
+//      Wire.write((char)reg + pos);
+//      Wire.endTransmission();
+//      Wire.requestFrom((char)_i2caddr, read_now);
+
+// #ifdef I2C_DEBUG
+//      Serial.print("[$"); Serial.print(reg + pos, HEX); Serial.print("] -> ");
+// #endif
+//      for(int i=0; i<read_now; i++){
+//          buf[pos] = Wire.read();
+// #ifdef I2C_DEBUG
+//          Serial.print("0x"); Serial.print(buf[pos], HEX); Serial.print(", ");
+// #endif
+//          pos++;
+//      }
+// #ifdef I2C_DEBUG
+//      Serial.println();
+// #endif
+//  }
+    char reg_dest = reg;
+    char rx_buf[num];
+    int nack = _i2c.write(_i2caddr, &reg_dest, 1, 1); // no stop
+    nack = _i2c.read(_i2caddr, rx_buf, num);
+    for (int i = 0; i < num; i++) {
+        buf[i] = (uint8_t) rx_buf[i];
+    }
+    return nack;
+}
+
+int Adafruit_AMG88xx::write(uint8_t reg, uint8_t *buf, uint8_t num)
+{
+// #ifdef I2C_DEBUG
+        // Serial.print("[$"); Serial.print(reg, HEX); Serial.print("] <- ");
+// #endif
+    // Wire.beginTransmission((char)_i2caddr);
+    // Wire.write((char)reg);
+    // for (int i=0; i<num; i++) {
+    //   Wire.write(buf[i]);
+// #ifdef I2C_DEBUG
+    //   Serial.print("0x"); Serial.print(buf[i], HEX); Serial.print(", ");
+// #endif
+    // }
+    // Wire.endTransmission();
+// #ifdef I2C_DEBUG
+    // Serial.println();
+// #endif
+    char reg_dest = reg;
+    char tx_buf[num];
+    for (int i = 0; i < num; i++) {
+        tx_buf[i] = (char) buf[i];
+    }
+    int nack = _i2c.write(_i2caddr, &reg_dest, 1, 1); // no stop
+    nack = _i2c.write(_i2caddr, tx_buf, num);
+    return nack;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  convert a 12-bit signed magnitude value to a floating point number
+    @param  val the 12-bit signed magnitude value to be converted
+    @returns the converted floating point value
+*/
+/**************************************************************************/
+float Adafruit_AMG88xx::signedMag12ToFloat(uint16_t val)
+{
+    //take first 11 bits as absolute val
+    uint16_t absVal = (val & 0x7FF);
+    
+    return (val & 0x800) ? 0 - (float)absVal : (float)absVal ;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  convert a 12-bit integer two's complement value to a floating point number
+    @param  val the 12-bit integer  two's complement value to be converted
+    @returns the converted floating point value
+*/
+/**************************************************************************/
+float Adafruit_AMG88xx::int12ToFloat(uint16_t val)
+{
+    uint16_t sVal = (val << 4); //shift to left so that sign bit of 12 bit integer number is placed on sign bit of 16 bit signed integer number
+    return sVal >> 4; //shift back the signed number, return converts to float
+}
+
+/** 
+ * @brief helper function, constraints the value 
+ * @param value variable to be constrained
+ * @param min minimum value of the variable
+ */
+int Adafruit_AMG88xx::constrain(int value, int min, int max)
+{
+    if (value > max) {
+        return max;
+    }
+    else if (value < min) {
+        return min;
+    }
+    else {
+        return value;
+    }
+}
+
+int Adafruit_AMG88xx::min(int val1, int val2) {
+    if (val1 < val2) return val1;
+    else return val2;
+}
+
+int Adafruit_AMG88xx::max(int val1, int val2) {
+    if (val1 > val2) return val1;
+    else return val2;
+}
+
+uint8_t Adafruit_AMG88xx::min(uint8_t val1, uint8_t val2) {
+    if (val1 < val2) return val1;
+    else return val2;
+}
+
+uint8_t Adafruit_AMG88xx::max(uint8_t val1, uint8_t val2) {
+    if (val1 > val2) return val1;
+    else return val2;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AMG8833.h	Fri Jun 14 12:49:30 2019 +0000
@@ -0,0 +1,340 @@
+#ifndef LIB_ADAFRUIT_AMG88XX_H
+#define LIB_ADAFRUIT_AMG88XX_H
+
+#include "mbed.h"
+
+/*=========================================================================
+    I2C ADDRESS/BITS
+    -----------------------------------------------------------------------*/
+    #define AMG88xx_ADDRESS                (0x69 << 1)
+/*=========================================================================*/
+
+/*=========================================================================
+    REGISTERS
+    -----------------------------------------------------------------------*/
+    enum
+    {
+        AMG88xx_PCTL = 0x00,
+        AMG88xx_RST = 0x01,
+        AMG88xx_FPSC = 0x02,
+        AMG88xx_INTC = 0x03,
+        AMG88xx_STAT = 0x04,
+        AMG88xx_SCLR = 0x05,
+        //0x06 reserved
+        AMG88xx_AVE = 0x07,
+        AMG88xx_INTHL = 0x08,
+        AMG88xx_INTHH = 0x09,
+        AMG88xx_INTLL = 0x0A,
+        AMG88xx_INTLH = 0x0B,
+        AMG88xx_IHYSL = 0x0C,
+        AMG88xx_IHYSH = 0x0D,
+        AMG88xx_TTHL = 0x0E,
+        AMG88xx_TTHH = 0x0F,
+        AMG88xx_INT_OFFSET = 0x010,
+        AMG88xx_PIXEL_OFFSET = 0x80
+    };
+    
+    enum power_modes{
+        AMG88xx_NORMAL_MODE = 0x00,
+        AMG88xx_SLEEP_MODE = 0x01,
+        AMG88xx_STAND_BY_60 = 0x20,
+        AMG88xx_STAND_BY_10 = 0x21
+    };
+    
+    enum sw_resets {
+        AMG88xx_FLAG_RESET = 0x30,
+        AMG88xx_INITIAL_RESET = 0x3F
+    };
+    
+    enum frame_rates {
+        AMG88xx_FPS_10 = 0x00,
+        AMG88xx_FPS_1 = 0x01
+    };
+    
+    enum int_enables{
+        AMG88xx_INT_DISABLED = 0x00,
+        AMG88xx_INT_ENABLED = 0x01
+    };
+    
+    enum int_modes {
+        AMG88xx_DIFFERENCE = 0x00,
+        AMG88xx_ABSOLUTE_VALUE = 0x01
+    };
+    
+/*=========================================================================*/
+
+#define AMG88xx_PIXEL_ARRAY_SIZE 64
+#define AMG88xx_PIXEL_TEMP_CONVERSION .25
+#define AMG88xx_THERMISTOR_CONVERSION .0625
+
+/**************************************************************************/
+/*! 
+    @brief  Class that stores state and functions for interacting with AMG88xx IR sensor chips
+*/
+/**************************************************************************/
+class Adafruit_AMG88xx {
+    public:
+        //constructors
+        Adafruit_AMG88xx(PinName sda, PinName scl);
+        
+        int begin(char addr = AMG88xx_ADDRESS);
+        
+        void readPixels(float *buf, uint8_t size = AMG88xx_PIXEL_ARRAY_SIZE);
+        float readThermistor();
+        
+        void setMovingAverageMode(int mode);
+        
+        void enableInterrupt();
+        void disableInterrupt();
+        void setInterruptMode(uint8_t mode);
+        void getInterrupt(uint8_t *buf, uint8_t size = 8);
+        void clearInterrupt();
+                
+        //this will automatically set hysteresis to 95% of the high value
+        void setInterruptLevels(float high, float low);
+                
+        //this will manually set hysteresis
+        void setInterruptLevels(float high, float low, float hysteresis);
+        
+    private:
+        char _i2caddr;
+
+        I2C _i2c;
+        
+        void write8(uint8_t reg, uint8_t value);
+        void write16(uint8_t reg, uint16_t value);
+        uint8_t read8(uint8_t reg);
+        
+        int read(uint8_t reg, uint8_t *buf, uint8_t num);
+        int write(uint8_t reg, uint8_t *buf, uint8_t num);
+        void _i2c_init();
+        
+        float signedMag12ToFloat(uint16_t val);
+        float int12ToFloat(uint16_t val);
+
+        int constrain(int value, int min, int max);
+        int min(int val1, int val2);
+        int max(int val1, int val2);
+
+        uint8_t min(uint8_t val1, uint8_t val2);
+        uint8_t max(uint8_t val1, uint8_t val2);
+        
+         // The power control register
+        struct pctl {
+            // 0x00 = Normal Mode
+            // 0x01 = Sleep Mode
+            // 0x20 = Stand-by mode (60 sec intermittence)
+            // 0x21 = Stand-by mode (10 sec intermittence)
+           
+            uint8_t PCTL : 8;
+
+            uint8_t get() {
+                return PCTL;
+            }
+        };
+        pctl _pctl;
+        
+        //reset register
+        struct rst {
+            //0x30 = flag reset (all clear status reg 0x04, interrupt flag and interrupt table)
+            //0x3F = initial reset (brings flag reset and returns to initial setting)
+            
+            uint8_t RST : 8;
+            
+            uint8_t get() {
+                return RST;
+            }
+        };
+        rst _rst;
+        
+        //frame rate register
+        struct fpsc {
+            
+            //0 = 10FPS
+            //1 = 1FPS
+            uint8_t FPS : 1;
+            
+            uint8_t get() {
+                return FPS & 0x01;
+            }
+        };
+        fpsc _fpsc;
+        
+        //interrupt control register
+        struct intc {
+            
+            // 0 = INT output reactive (Hi-Z)
+            // 1 = INT output active
+            uint8_t INTEN : 1;
+            
+            // 0 = Difference interrupt mode
+            // 1 = absolute value interrupt mode
+            uint8_t INTMOD : 1;
+            
+            uint8_t get(){
+                return (INTMOD << 1 | INTEN) & 0x03;
+            }
+        };
+        intc _intc;
+        
+        //status register
+        struct stat {
+            uint8_t unused : 1;
+            //interrupt outbreak (val of interrupt table reg)
+            uint8_t INTF : 1;
+            
+            //temperature output overflow (val of temperature reg)
+            uint8_t OVF_IRS : 1;
+            
+            //thermistor temperature output overflow (value of thermistor)
+            uint8_t OVF_THS : 1;
+            
+            uint8_t get(){
+                return ( (OVF_THS << 3) | (OVF_IRS << 2) | (INTF << 1) ) & 0x0E;
+            }
+        };
+        stat _stat;
+        
+        //status clear register
+        //write to clear overflow flag and interrupt flag
+        //after writing automatically turns to 0x00
+        struct sclr {
+            uint8_t unused : 1;
+            //interrupt flag clear
+            uint8_t INTCLR : 1;
+            //temp output overflow flag clear
+            uint8_t OVS_CLR : 1;
+            //thermistor temp output overflow flag clear
+            uint8_t OVT_CLR : 1;
+            
+            uint8_t get(){
+                return ((OVT_CLR << 3) | (OVS_CLR << 2) | (INTCLR << 1)) & 0x0E;
+            }
+        };
+        sclr _sclr;
+        
+        //average register
+        //for setting moving average output mode
+        struct ave {
+            uint8_t unused : 5;
+            //1 = twice moving average mode
+            uint8_t MAMOD : 1;
+            
+            uint8_t get(){
+                return (MAMOD << 5);
+            }
+        };
+        struct ave _ave;
+        
+        //interrupt level registers
+        //for setting upper / lower limit hysteresis on interrupt level
+        
+        //interrupt level upper limit setting. Interrupt output
+        // and interrupt pixel table are set when value exceeds set value
+        struct inthl {
+            uint8_t INT_LVL_H : 8;
+            
+            uint8_t get(){
+                return INT_LVL_H;
+            }
+        };
+        struct inthl _inthl;
+        
+        struct inthh {
+            uint8_t INT_LVL_H : 4;
+            
+            uint8_t get(){
+                return INT_LVL_H;
+            }
+        };
+        struct inthh _inthh;
+        
+        //interrupt level lower limit. Interrupt output
+        //and interrupt pixel table are set when value is lower than set value
+        struct intll {
+            uint8_t INT_LVL_L : 8;
+            
+            uint8_t get(){
+                return INT_LVL_L;
+            }
+        };
+        struct intll _intll;
+        
+        struct intlh {
+            uint8_t INT_LVL_L : 4;
+            
+            uint8_t get(){
+                return (INT_LVL_L & 0xF);
+            }
+        };
+        struct intlh _intlh;
+        
+        //setting of interrupt hysteresis level when interrupt is generated.
+        //should not be higher than interrupt level
+        struct ihysl {
+            uint8_t INT_HYS : 8;
+            
+            uint8_t get(){
+                return INT_HYS;
+            }
+        };
+        struct ihysl _ihysl;
+        
+        struct ihysh {
+            uint8_t INT_HYS : 4;
+            
+            uint8_t get(){
+                return (INT_HYS & 0xF);
+            }
+        };
+        struct ihysh _ihysh;
+        
+        //thermistor register
+        //SIGNED MAGNITUDE FORMAT
+        struct tthl {
+            uint8_t TEMP : 8;
+            
+            uint8_t get(){
+                return TEMP;
+            }
+        };
+        struct tthl _tthl;
+        
+        struct tthh {
+            uint8_t TEMP : 3;
+            uint8_t SIGN : 1;
+            
+            uint8_t get(){
+                return ( (SIGN << 3) | TEMP) & 0xF;
+            }
+        };
+        struct tthh _tthh;
+        
+        //temperature registers 0x80 - 0xFF
+        /*
+        //read to indicate temperature data per 1 pixel
+        //SIGNED MAGNITUDE FORMAT
+        struct t01l {
+            char TEMP : 8;
+            
+            char get(){
+                return TEMP;
+            }
+        };
+        struct t01l _t01l;
+        
+        struct t01h {
+            char TEMP : 3;
+            char SIGN : 1;
+            
+            char get(){
+                return ( (SIGN << 3) | TEMP) & 0xF;
+            }
+        };
+        struct t01h _t01h;
+        */
+        
+        
+};
+
+#endif
\ No newline at end of file