Files
upm/src/mcp9808/mcp9808.cxx

184 lines
4.0 KiB
C++
Raw Normal View History

/*
* Author: Marc Graham <marc@m2ag.net>
* Copyright (c) 2015 Intel Corporation.
*
* This program and the accompanying materials are made available under the
* terms of the The MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
*/
#include "mcp9808.hpp"
#include <cmath>
#include <syslog.h>
cmake: Dependency refactoring for includes and libs This commit attempts to use a more cmake-friendly approach when handling inter-target dependencies. A combination of macros and include_directories usage provided overzealous compile -I/blah entries which equates to large catch-all build commands. For example, the last CXX target contains include directories for nearly all preceeding targets (~190). Library dependencies were also often wrong or missing. * Removed nearly all used of include_directories (swig cmake commands still appear to need these for generating the swig command line) * Updated usage of target_link_libraries in upm_module_init, also changed to using target_include_directories per target. This greatly simplifies upm/mixed_module_init usage for libraries which depend on other libraries (in this project). example (src/tb7300/CMakeLists.txt) old: # upm-libbacnetmstp will bring in libbacnet, I hope set (reqlibname "upm-bacnetmstp") include_directories(${BACNET_INCLUDE_DIRS}) include_directories("../bacnetmstp") upm_module_init() upm_target_link_libraries(${libname} bacnetmstp) new: upm_module_init(bacnetmstp) The reason here, is that tb7300 depends on bacnetmstp, which depends on BACNET includes/libs, so tb7300 gets the headers and libraries transitively via its dependency on bacnetmstp. * Updated pkg-config .pc file generation flow to reflect changes with dependencies. * Create a real target for the interfaces (CXX abstract sensor classes). Renamed the directory from 'upm/src/upm' to 'upm/src/interfaces' Also changed the install location of the interface headers to include/upm/interfaces. Updated interface header usage to reflect this. * Updated a few sensor libs to use fwd declarations for mraa. Ideally the UPM libs would do more of this which eases the burden on anyone building on top of the sensor libraries since they would not need to know about mraa headers. * Fixed examples which use symbols not defined in local includes Signed-off-by: Noel Eck <noel.eck@intel.com>
2017-01-30 18:14:48 -08:00
#include "mraa.hpp"
#include "mraa/i2c.hpp"
using namespace upm;
MCP9808::MCP9808 (int bus, uint8_t address){
m_name = "mcp9808";
m_celsius = true;
m_tcrit = false;
m_tupper = false;
m_tlower = false;
if(!(i2c = new mraa::I2c(bus))){
throw std::invalid_argument(std::string(__FUNCTION__) +": I2c.init() failed");
return;
}
if((i2c->address(address) != mraa::SUCCESS)){
throw std::invalid_argument(std::string(__FUNCTION__) + ": I2c.address() failed");
return;
}
if(i2c->frequency( mraa::I2C_FAST) != mraa::SUCCESS){
syslog(LOG_WARNING, "%s: I2c.frequency(I2C_FAST) failed, using default speed", std::string(__FUNCTION__).c_str());
}
}
float
MCP9808::getTemp(){
uint16_t result;
//Read the register
result = i2c->readWordReg(MCP9808_REG_AMBIENT_TEMP);
//Swap the bytes
result = swapWord(result);
//Get the flag bits.
m_tcrit = (result & 0x8000) ;
m_tupper = (result & 0x4000) ;
m_tlower = (result & 0x2000) ;
return getTempValue(result);
}
float
MCP9808::getTemperature() {
return getTemp();
}
void
MCP9808::shutDown(bool sleep){
if(sleep) this->updateConfigRegister(MCP9808_CONFIG_SHUTDOWN);
else this->updateConfigRegister(~(MCP9808_CONFIG_SHUTDOWN), false);
}
void
MCP9808::setMonitorReg(MCP9808_REG reg, float value){
uint16_t t;
if(m_celsius) t = value * 16.0;
else t = ((value - 32) * 5.0/9.0) * 16.0 ;
t = swapWord(t);
if(i2c->writeWordReg(reg, t) != mraa::SUCCESS){
throw std::invalid_argument(std::string(__FUNCTION__) + ": I2c.write() failed");
return;
}
}
float
MCP9808::getMonitorReg(MCP9808_REG reg){
uint16_t value = i2c->readWordReg(reg);
value = swapWord(value);
return getTempValue(value);
}
void
MCP9808::clearInterrupt(){
this->updateConfigRegister(MCP9808_CONFIG_INTCLR);
}
void
MCP9808::setAlertMode(uint16_t command){
this->updateConfigRegister(command);
}
void
MCP9808::clearAlertMode(){
//Preserve hysteresis and shutdown settings but
//set all alert settings to power on default.
this->updateConfigRegister(0x2007, false);
}
void
MCP9808::setHysteresis(MCP9808_CONFIG value){
//Clear hysteresis first.
this->updateConfigRegister(0xFFF9, false);
this->updateConfigRegister(value);
}
float
MCP9808::getHysteresis(){
uint16_t value = i2c->readWordReg(MCP9808_REG_CONFIG);
value = (value >> 1 ) & 0xF ;
float res = (value == 0) ? 0.0 : ( 1.5 * pow( 2.0 , value - 1 )) ;
return (m_celsius) ? res : res * 9/5;
}
void
MCP9808::setResolution(MCP9808_RESOLUTION value){
if(i2c->writeReg(MCP9808_REG_RESOLUTION, value) != mraa::SUCCESS){
throw std::invalid_argument(std::string(__FUNCTION__) + ": I2c.write() failed");
return;
}
}
float
MCP9808::getResolution(){
uint8_t value = i2c->readReg(MCP9808_REG_RESOLUTION);
return 0.5 * (1.0 / std::pow( 2.0, value));
}
uint16_t
MCP9808::getManufacturer(){
return swapWord(i2c->readWordReg(MCP9808_REG_MANUF_ID));
}
uint16_t
MCP9808::getDevicedId(){
return swapWord(i2c->readWordReg(MCP9808_REG_DEVICE_ID));
}
MCP9808::~MCP9808 (){
delete i2c;
}
//Private functions
float
MCP9808::getTempValue(uint16_t result){
bool neg = (result & 0x1000);
float res = (result & 0xFFF) / 16.0;
if(neg) res = 0 - ( 256 - res );
if(!m_celsius) res = res * 9.0/5.0 + 32;
return res;
}
void
MCP9808::updateConfigRegister(uint16_t update, bool on){
uint16_t reg = i2c->readWordReg(MCP9808_REG_CONFIG);
if(on) reg |= update;
else reg &= update;
if(i2c->writeWordReg(MCP9808_REG_CONFIG, reg) != mraa::SUCCESS){
throw std::invalid_argument(std::string(__FUNCTION__) + ": I2c.write() failed");
return;
}
}
uint16_t
MCP9808::swapWord(uint16_t value){
uint16_t res = value;
return ((res & 0xFF) << 8) | ((res >> 8 ) & 0xFF);
}