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
diff -r 000000000000 -r 9aaf1afdeac0 AMG8833.cpp
--- /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
diff -r 000000000000 -r 9aaf1afdeac0 AMG8833.h
--- /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