Gabriel Silva / Mbed OS LOG

TMP117.cpp

Committer:
glsfacom
Date:
2020-10-06
Revision:
4:0e3e93c26d83
Parent:
3:23ecb85b6e8b

File content as of revision 4:0e3e93c26d83:

/*!
 * @file    TMP117.cpp
 * @author  Nils Minor
 * 
 * @license  GNU GENERAL PUBLIC LICENSE (see license.txt)
 * 
 * v1.0.0   - Initial library version
 * 
 * 
 */
#include "TMP117.h"

/*!
    @brief   Constructor 
    @param   addr device I2C address [0x48 - 0x4B]
*/
TMP117::TMP117 (uint8_t tmp_quant) 
{  
  TMP117::tmp_quant = tmp_quant;
  alert_pin = -1;
  alert_type = NOALERT;
  newDataCallback = NULL;
}

/*!
    @brief   Initialize in default mode 
    @param   _newDataCallback   callback function will be called when new data is available
*/
void TMP117::init ( void (*_newDataCallback) (void), int addr ) {
  setConvMode (CONTINUOUS, addr);
  setConvTime (C125mS, addr);
  setAveraging (AVE8, addr);
  setAlertMode (DATA, addr);
  setOffsetTemperature(0, addr);    
  
  newDataCallback = _newDataCallback;
}

/*!
    @brief    Read configuration register and handle events.
              Should be called in loop in order to call callback functions 
*/
void TMP117::update (void) {
  readConfig ();
}

/*!
    @brief   Performs a soft reset. All default values will be loaded to the configuration register
*/
void TMP117::softReset ( int addr ) {
  uint16_t reg_value = 0;
  reg_value |= 1UL << 1;
  writeConfig ( reg_value, addr );
}

/*!
    @brief   Set alert pin mode 
    
    @param   mode TMP117_PMODE [Thermal-Alert-Data]
*/
void      TMP117::setAlertMode ( TMP117_PMODE mode, int addr) {
  uint16_t reg_value = readConfig ();
  if (mode == THERMAL) {
    reg_value |= 1UL << 4;    // change to thermal mode
    reg_value &= ~(1UL << 2); // set pin as alert flag
    reg_value &= ~(1UL << 3); // alert pin low active
  }
  else if (mode == ALERT) {
    reg_value &= ~(1UL << 4); // change to alert mode
    reg_value &= ~(1UL << 2); // set pin as alert flag
    reg_value &= ~(1UL << 3); // alert pin low active
  } 
  else if (mode == DATA) {
    reg_value |= 1UL << 2;    // set pin as data ready flag
  } 
  writeConfig ( reg_value, addr );
}

///*!
//    @brief   Set alert callback function and ISR pin
//    @param   *allert_callback  callback function
//    @param   pin callback pin (INT?)
//*/
//void      TMP117::setAllertCallback (void (*allert_callback)(void), uint8_t pin) {
//  alert_pin = pin;
//  pinMode(pin, INPUT_PULLUP);
//   
//  attachInterrupt(digitalPinToInterrupt(pin), allert_callback, FALLING ); // Sets up pin 2 to trigger "alert" ISR when pin changes H->L and L->H
//}

/*!
    @brief    Set alert temperature
    
    @param    lowtemp   low boundary alert temperature
    @param    hightemp  high boundary alert temperature  
*/
void      TMP117::setAllertTemperature (double lowtemp, double hightemp, int addr) {
  
 uint16_t high_temp_value = hightemp / TMP117_RESOLUTION;
 uint16_t low_temp_value = lowtemp / TMP117_RESOLUTION;

 i2cWrite2B (TMP117_REG_TEMP_HIGH_LIMIT , high_temp_value, addr);
 i2cWrite2B (TMP117_REG_TEMP_LOW_LIMIT , low_temp_value, addr);  
}

/*!
    @brief    Set conversion mode
    
    @param    cmode   ::TMP117_CMODE [CONTINUOUS-SHUTDOWN-ONESHOT]
*/
void      TMP117::setConvMode ( TMP117_CMODE cmode, int addr) {
   uint16_t reg_value = readConfig ();
   reg_value &= ~((1UL << 11) | (1UL << 10));       // clear bits
   reg_value = reg_value | ( cmode  & 0x03 ) << 10; // set bits   
   writeConfig ( reg_value , addr);
}

/*!
    @brief    Set conversion time
    
    @param    convtime  ::TMP117_CONVT [C15mS5-C125mS-C250mS-C500mS-C1S-C4S-C8S-C16S]
*/
void      TMP117::setConvTime ( TMP117_CONVT convtime, int addr ) {
  uint16_t reg_value = readConfig ();
  reg_value &= ~((1UL << 9) | (1UL << 8) | (1UL << 7));       // clear bits
  reg_value = reg_value | ( convtime  & 0x07 ) << 7;          // set bits
  writeConfig ( reg_value, addr );
}
/*!
    @brief    Set averaging mode
    
    @param    ave  ::TMP117_AVE [NOAVE-AVE8-AVE32-AVE64]
*/
void      TMP117::setAveraging ( TMP117_AVE ave, int addr ) {
  uint16_t reg_value = readConfig ();
  reg_value &= ~((1UL << 6) | (1UL << 5) );       // clear bits
  reg_value = reg_value | ( ave & 0x03 ) << 5;          // set bits
  writeConfig ( reg_value, addr );
}

/*!
    @brief    Set offset temperature
    
    @param    double  target offset temperature  in the range of ±256°C  
*/
void      TMP117::setOffsetTemperature ( double offset, int addr ) {
  int16_t offset_temp_value = offset / TMP117_RESOLUTION;
  i2cWrite2B (TMP117_REG_TEMPERATURE_OFFSET , offset_temp_value, addr);
}

/*!
    @brief    Set target temperature for calibration purpose
    
    @param    double  target temperature to calibrate to in the range of ±256°C  
*/
void      TMP117::setTargetTemperature ( double target, int addr ) {
  getTemperatures();
  double actual_temp = temps[addr];
  double delta_temp =  target - actual_temp;
  setOffsetTemperature ( delta_temp, addr );
} 

/*!
    @brief    Read configuration register and handle events.

    @return   uint16_t  read value of the configuration regsiter          
*/
uint16_t  TMP117::readConfig (void) {
  uint16_t reg_value = i2cRead2B ( TMP117_REG_CONFIGURATION );
  bool high_alert = reg_value >> 15 & 1UL;
  bool low_alert = reg_value >> 14 & 1UL;   
  bool data_ready = reg_value >> 13 & 1UL;   
  bool eeprom_busy = reg_value >> 12 & 1UL;   

  if (data_ready && newDataCallback != NULL)
    newDataCallback ();

  if (reg_value >> 15 & 1UL) {
    alert_type = HIGHALERT;
  }
  else if (reg_value >> 14 & 1UL) {
    alert_type = LOWALERT;
  }
  else {
    alert_type = NOALERT;
  }
  
  //printConfig ( reg_value );
    
  return reg_value;  
}


/*!
    @brief    Returns the recalculated temperature
    
    @return   double  temperature in °C
*/
void     TMP117::getTemperatures (void) {
  for(int i = 0; i < tmp_quant; i++)
  {
    temps[i] = (double)i2cRead2B( TMP117_REG_TEMPERATURE, TMP117_BASE_ADDR + i )  * TMP117_RESOLUTION;
  }
}
/*!
    @brief    Get Device Revision 
    
    @return   uint16_t device revision
*/
uint16_t  TMP117::getDeviceRev (void) {
  // read bits [15:12]
  uint16_t raw = i2cRead2B( TMP117_REG_DEVICE_ID );
  
  return ( (raw >> 12) & 0x3);
}

/*!
    @brief    Get Device ID (always 0x117)
    
    @return   uint16_t  device ID
*/
uint16_t  TMP117::getDeviceID (void) {
  // read bits [11:0]
  uint16_t raw = i2cRead2B( TMP117_REG_DEVICE_ID );
  return (raw & 0x0fff);
}

/*!
    @brief    Returns the information which alert type happend
    
    @return   TMP117_ALERT [NoAlert-HighTempAlert-LowTempAlert]
*/
TMP117_ALERT TMP117::getAlertType ( void ) {
  return alert_type;
}

/*!
    @brief    Returns the content of the offset register in °C
    
    @return   double  offset temperature in °C
*/
double    TMP117::getOffsetTemperature (void) {
  int16_t temp = i2cRead2B( TMP117_REG_TEMPERATURE_OFFSET );
  return  (temp * TMP117_RESOLUTION);
}

/*!
    @brief    Write data to EEPROM register
    
    @param    data        data to write to the EEPROM
    
    @param    eeprom_nr   represents the EEPROM number [1 - 3] 
*/
void      TMP117::writeEEPROM (uint16_t data, uint8_t eeprom_nr, int addr) {
  if (!EEPROMisBusy()) {
    unlockEEPROM(addr);
      switch (eeprom_nr) {
        case 1 : i2cWrite2B ( TMP117_REG_EEPROM1, data, addr); break;
        case 2 : i2cWrite2B ( TMP117_REG_EEPROM2, data, addr); break;
        case 3 : i2cWrite2B ( TMP117_REG_EEPROM3, data, addr); break;
        default: printf("EEPROM value must be between 1 and 3");
      }
    lockEEPROM(addr);
  }
  else {
    printf("EEPROM is busy");
  }
}

/*!
    @brief    Read data from EEPROM register
    
    @param    eeprom_nr  represents the EEPROM number [1 - 3] 
    
    @return   uint16_t   read EEPROM data
*/
uint16_t  TMP117::readEEPROM (uint8_t eeprom_nr) {
  // read the 48 bit number from the EEPROM
  if (!EEPROMisBusy()) {
    uint16_t eeprom_data = 0;
    switch (eeprom_nr) {
        case 1 : eeprom_data = i2cRead2B( TMP117_REG_EEPROM1 ); break;
        case 2 : eeprom_data = i2cRead2B( TMP117_REG_EEPROM2 ); break;
        case 3 : eeprom_data = i2cRead2B( TMP117_REG_EEPROM3 ); break;
        default: printf("EEPROM value must be between 1 and 3");
      }
    return eeprom_data;
  }
  else {
    printf("EEPROM is busy");
    return NULL;
  }
}


/**************************************************************************/
/* ********************* Library internal functions  ******************** */
/**************************************************************************/

/*!
    @brief    Write two bytes (16 bits) to TMP117 I2C sensor
    
    @param    reg  target register
    @param    data data to write
*/
void      TMP117::i2cWrite2B (uint8_t reg, uint16_t data, int addr ){
  TMP117::i2c.start(); 
  TMP117::i2c.write(reg);
  char* w;
  w[0] = (char)data>>8;
  w[1] = (char)data & 0xff;
  TMP117::i2c.write(addr, w, 2);
  TMP117::i2c.stop();
  wait_us(10*1000);
}

/*!
    @brief    Read two bytes (16 bits) from TMP117 I2C sensor
    
    @param    reg  target register to read from
    
    @return   uint16_t  read data
*/
uint16_t  TMP117::i2cRead2B (uint8_t reg) {
  int ACK = 0;
  uint8_t read[2] = {0}; 
  int16_t temp = 0;   

  TMP117::i2c.start(); 
  ACK = TMP117::i2c.write(TMP117_BASE_ADDR<<1);
  if(!ACK) return -1;
  ACK = TMP117::i2c.write((0x0f)&reg);
  if(!ACK) return -1;
  TMP117::i2c.start();
  TMP117::i2c.write((TMP117_BASE_ADDR<<1)|0x01);
  if(!ACK) return -1;
  read[0] = TMP117::i2c.read(ACK);
  if(!ACK) return -1;
  read[1] = TMP117::i2c.read(ACK);
  TMP117::i2c.read(ACK);
  temp = (read[0] << 8) | read[1];
  msb = read[0];
  lsb = read[1];
  return temp;
}

/*!
    @brief    Read two bytes (16 bits) from TMP117 I2C sensor
    
    @param    reg  target register to read from
    
    @return   uint16_t  read data
*/
uint16_t  TMP117::i2cRead2B (uint8_t reg, uint8_t addr) {
  int ACK = 0;
  uint8_t read[2] = {0}; 
  int16_t temp = 0;   

  TMP117::i2c.start(); 
  ACK = TMP117::i2c.write(addr<<1);
  if(!ACK) return -1;
  ACK = TMP117::i2c.write((0x0f)&reg);
  if(!ACK) return -1;
  TMP117::i2c.start();
  TMP117::i2c.write((addr<<1)|0x01);
  if(!ACK) return -1;
  read[0] = TMP117::i2c.read(ACK);
  if(!ACK) return -1;
  read[1] = TMP117::i2c.read(ACK);
  TMP117::i2c.read(ACK);
  temp = (read[0] << 8) | read[1];
  msb = read[0];
  lsb = read[1];
  return temp;
}

/*!
    @brief    Write configuration to config register
    
    @param    config_data  configuration
*/
void      TMP117::writeConfig (uint16_t config_data, int addr) {
  i2cWrite2B (TMP117_REG_CONFIGURATION, config_data, addr);
}

/*!
    @brief    Prints configuration in user readable format
    
    @param    reg_value  configuration value
*/
//void      TMP117::printConfig (uint16_t reg_value) {
//
////  printf(reg_value, BIN);
//
//  printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
//  printf ("HIGH alert:  ");
//  printf( ( reg_value >> 15) & 0b1 , BIN);
//  printf ("LOW alert:   ");
//  printf( ( reg_value >> 14) & 0b1 , BIN);
//  printf ("Data ready:  ");
//  printf( ( reg_value >> 13) & 0b1 , BIN);
//  printf ("EEPROM busy: ");
//  printf( ( reg_value >> 12) & 0b1 , BIN);
//  printf ("MOD[1:0]:    ");
//  printf( ( reg_value >> 10) & 0b11 , BIN);
//  printf ("CONV[2:0]:   ");
//  printf( ( reg_value >> 7)  & 0b111 , BIN);
//  printf ("AVG[1:0]:    ");
//  printf( ( reg_value >> 5)  & 0b11 , BIN);
//  printf ("T/nA:        ");
//  printf( ( reg_value >> 4) & 0b1 , BIN);
//  printf ("POL:         ");
//  printf( ( reg_value >> 3) & 0b1 , BIN);
//  printf ("DR/Alert:    ");
//  printf( ( reg_value >> 2) & 0b1 , BIN);
//  printf ("Soft_Reset:  ");
//  printf( ( reg_value >> 1) & 0b1 , BIN);
//}
/*!
    @brief    Lock EEPROM, write protection
*/
void      TMP117::lockEEPROM ( int addr) {
  // clear bit 15
  uint16_t code = 0;
  code &= ~(1UL << 15);
  i2cWrite2B ( TMP117_REG_EEPROM_UNLOCK, code, addr );
  wait_us(100*1000);
}

/*!
    @brief    Unlock EEPROM, remove write protection
*/
void      TMP117::unlockEEPROM ( int addr) {
  // set bit 15
  uint16_t code = 0;
  code |= 1UL << 15;
  i2cWrite2B ( TMP117_REG_EEPROM_UNLOCK, code, addr );
  wait_us(100*1000);
}

/*!
    @brief    States if the EEPROM is busy
    
    @return   Ture if the EEPROM is busy, fals else
*/
bool      TMP117::EEPROMisBusy (void) {
  // Bit 14 indicates the busy state of the eeprom
  uint16_t code = i2cRead2B ( TMP117_REG_EEPROM_UNLOCK );
  return (bool) ((code >> 14) & 0x01);
}