Complete DS1621 library (all functions implemented)

ds1621.cpp

Committer:
bborredon
Date:
2012-07-14
Revision:
0:096dbb58d60e

File content as of revision 0:096dbb58d60e:

/***********************************************************
Author: Bernard Borredon
Date: 27 december 2011
Version: 1.0
************************************************************/
#include "ds1621.h"

#define BIT_SET(x,n) (x=x | (0x01<<n))
#define BIT_TEST(x,n) (x & (0x01<<n))
#define BIT_CLEAR(x,n) (x=x & ~(0x01<<n))

// Constructor
DS1621::DS1621(PinName sda, PinName scl, uint8_t address) : _i2c(sda, scl) 
{
  _errnum = DS1621_NoError;
  _config = DS1621_PolHigh;
  
  // Check address range (0 to 7)
  _address = address;
  if(address > 7) {
    _errnum = DS1621_BadAddress;
  }
  _address = _address << 1;
  
  // Set I2C frequency
  _i2c.frequency(100000);
}

// Get temperature with 0.5 degrees resolution
float DS1621::getTemp(void) 
{
  char cmd;
  int8_t temp8[2];
  float temp;
  int ack;
  
  // Check error
  if(_errnum) 
    return(0.0);
    
  // No error
  _errnum = DS1621_NoError;
  
  // Start convert
  startConvert(true);
  if(getError() != 0)
    return(0.0);
  
  cmd = 0xAA; // Read Temperature [AAh]
  ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
    
  // Read value
  ack = _i2c.read(DS1621_address | _address,(char *)temp8,sizeof(temp8));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
  
  // Format temperature
  temp8[1] = temp8[1] >> 7;
  if(temp8[0] < 0) { // -
    temp = -~temp8[0] + 0.5 * temp8[1];
  }
  else { // +
    temp = temp8[0] - 0.5 * temp8[1];
  }

  return(temp);
}

// Get temperature with 0.01 degrees resolution
float DS1621::getHrTemp(void) 
{
  char cmd;
  int8_t temp8[2];
  int ack;
  uint8_t count_remain, count_per_c;
  uint8_t config,config_mem;
  int16_t ifract;
  int16_t itemp;
  float temp;
    
  // Check error
  if(_errnum) 
    return(0.0);
    
  // No error
  _errnum = DS1621_NoError;
  
  // Get config register
  config = getConfig();
  if(getError() != 0)
    return(0.0);
  
  // Force 1Shot if needed
  config_mem = 0;
  if(!BIT_TEST(config,DS1621_CFG_1SHOT)) {
    config_mem = config;
    BIT_SET(config,DS1621_CFG_1SHOT);
    setConfig(config);
    if(getError() != 0)
      return(0.0);
    startConvert(false);
    if(getError() != 0)
      return(0.0);
  }
  
  // Start conversion
  startConvert(true);
  if(getError() != 0)
    return(0.0);
  
  // Wait end of conversion
  waitEndConvert();
  if(getError() != 0)
    return(0.0);
  
  cmd = 0xAA; // Read Temperature [AAh]
  ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
  
  // Read value
  ack = _i2c.read(DS1621_address | _address,(char *)temp8,sizeof(temp8));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
  
  cmd = 0xA8; // Read Counter [A8H]
  ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
  
  // Read value
  ack = _i2c.read(DS1621_address | _address,(char *)&count_remain,sizeof(count_remain));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
  
  cmd = 0xA9; // Read Slope [A9H]
  ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
  
  // Read value
  ack = _i2c.read(DS1621_address | _address,(char *)&count_per_c,sizeof(count_per_c));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
    
  // Format temperature
  ifract = ((int16_t)(count_per_c - count_remain) * 100) / 25;
  if(temp8[0] < 0) { // -
    itemp = -~temp8[0] * 100 + ifract;
  }
  else { // +
    itemp = temp8[0] * 100 + ifract;
  }
  temp = (float)itemp / 100.0;
  
  // Restore config if needed
  if(config_mem) {
    setConfig(config_mem);
    if(getError() != 0)
      return(0.0);
    startConvert(true);
    if(getError() != 0)
      return(0.0);
  }

  return(temp);
}

// Read config register
uint8_t DS1621::getConfig(void) 
{
  char cmd;
  uint8_t config;
  int ack;
  
  // Check error
  if(_errnum) 
    return(0);
    
  // No error
  _errnum = DS1621_NoError;
  
  cmd = 0xAC; // Access Config [ACh]
  ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0);
  }
  
  // Read value
  ack = _i2c.read(DS1621_address | _address,(char *)&config,sizeof(config));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0);
  }
  
  return(config);
}

// Write config register
void DS1621::setConfig(uint8_t config) 
{
  char cmd[2];
  int ack;
  
  // Check error
  if(_errnum) 
    return;
  
  // No error
  _errnum = DS1621_NoError; 
   
  _config = config;
    
  cmd[0] = 0xAC; // Access Config [ACh]
  cmd[1] = config;
  ack = _i2c.write(DS1621_address | _address,cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
  }
}

// Start or stop convert
void DS1621::startConvert(bool flag) 
{
  char cmd;
  int ack;
  
  // Check error
  if(_errnum) 
    return;
    
  // No error
  _errnum = DS1621_NoError;
      
  if(flag)
    cmd = 0xEE; // Start Convert [EEh]
  else
    cmd = 0x22; // Stop Convert [22h]
    
  ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
  }
}

// Wait end of conversion
void DS1621::waitEndConvert(void) 
{
  uint8_t cfg;
  
  // Check error
  if(_errnum) 
    return;
    
  // No error
  _errnum = DS1621_NoError;
  
  // Wait end of conversion
  do {
       // Get Config register and test bit DONE
       cfg = getConfig();
       if(getError() != 0)
         return;
  }
  while(cfg < DS1621_DONE);
}

// Read Temperature High Flag
bool DS1621::getTHF(void) 
{
  uint8_t cfg;
  bool thf;
  
  // Check error
  if(_errnum) 
    return(0);
    
  // No error
  _errnum = DS1621_NoError;
  
  // get Config register
  cfg = getConfig();
  if(getError() != 0)
    return(0);
  
  // Test THF bit
  if(BIT_TEST(cfg,DS1621_CFG_THF))
    thf = true;
  else
    thf = false;
    
  return(thf);
}

// Read Temperature Low Flag
bool DS1621::getTLF() 
{
  uint8_t cfg;
  bool tlf;
  
  // Check error
  if(_errnum) 
    return(0);
  
  // No error
  _errnum = DS1621_NoError;
  
  // get Config register
  cfg = getConfig();
  if(getError() != 0)
    return(0);
    
  // Test TLF bit
  if(BIT_TEST(cfg,DS1621_CFG_TLF))
    tlf = true;
  else
    tlf = false;
    
  return(tlf);
}

// Read Temperature Low and High Flag
void DS1621::getTF(bool& tlf,bool& thf) 
{
  uint8_t cfg;
  
  // Check error
  if(_errnum) 
    return;
  
  // No error
  _errnum = DS1621_NoError;
  
  // get Config register
  cfg = getConfig();
  if(getError() != 0)
    return;
  
  // Test TLF bit
  tlf = false;
  if(BIT_TEST(cfg,DS1621_CFG_TLF))
    tlf = true;
    
  // Test THF bit
  thf = false;
  if(BIT_TEST(cfg,DS1621_CFG_THF))
    thf = true;
}

// Read 1Shot bit
bool DS1621::get1Shot(void) 
{
  
  // Test 1Shot bit
  if(BIT_TEST(_config,DS1621_CFG_1SHOT))
    return(true);
  else
    return(false);
}

// Write Temperature (High or Low)
void DS1621::setTemperature(float temp,uint8_t trig) 
{
  uint8_t temp8[3];
  int ack;
  float r;
  
  // Chack param
  if(trig > 1) {
    _errnum = DS1621_ParamError;
    return;
  }
    
  // Check error
  if(_errnum) 
    return;
    
  // No error
  _errnum = DS1621_NoError;
  
  // Format temperature
  if(temp >= 0.0) {
    temp8[1] = (uint8_t)temp;
    r = temp - (int)temp;
    if(r >= 0.5)
      temp8[2] = 0x80;
    else
      temp8[2] = 0;
  }
  else {
    temp8[1] = ~(-(int8_t)temp);
    r = -temp + (int)temp;
    if(r >= 0.5)
      temp8[2] = 0x80;
    else
      temp8[2] = 0;
  }
  
  wait_ms(100);
    
  temp8[0] = 0xA1 + trig; // Access TH or TL [A1h or A2h]
  ack = _i2c.write(DS1621_address | _address,(char *)temp8,sizeof(temp8));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
  }
}

// Read Temperature (High or Low)
float DS1621::getTemperature(uint8_t trig) 
{
  char cmd;
  float temp;
  int8_t temp8[2];
  int ack;
  
  // Check param
  if(trig > 1) {
    _errnum = DS1621_ParamError;
    return(0.0);
  }
    
  // Check error
  if(_errnum) 
    return(0.0);
    
  // No error
  _errnum = DS1621_NoError;
    
  wait_ms(100);
    
  cmd = 0xA1 + trig; // Access TH or TL [A1h or A2h]
  ack = _i2c.write(DS1621_address| _address,&cmd,sizeof(cmd));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
    
  ack = _i2c.read(DS1621_address | _address,(char *)temp8,sizeof(temp8));
  if(ack != 0) {
    _errnum = DS1621_I2cError;
    return(0.0);
  }
  
  // Format temperature
  temp8[1] = temp8[1] >> 7;
  if(temp8[0] < 0) { // -
    temp = -~temp8[0] + 0.5 * temp8[1];
  }
  else { // +
    temp = temp8[0] - 0.5 * temp8[1];
  }
  
  return(temp);
}

// Get current error number
uint8_t DS1621::getError(void)
{ 
  return(_errnum);
}