/* * Author: Marc Graham * Copyright (c) 2015 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "ads1x15.hpp" #include "mraa/i2c.hpp" #include "upm_string_parser.hpp" #include #include using namespace upm; ADS1X15::ADS1X15(int bus, uint8_t address){ 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::runtime_error(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()); } //Will be reset by sub class. m_bitShift = 0; m_conversionDelay = .001; m_config_reg = 0x0000; } ADS1X15::ADS1X15(std::string initStr) { mraaIo = new mraa::MraaIo(initStr); if(mraaIo == NULL) { throw std::invalid_argument(std::string(__FUNCTION__) + ": Failed to allocate memory for internal member"); } if(!mraaIo->i2cs.empty()) { i2c = &mraaIo->i2cs[0]; } else { throw std::invalid_argument(std::string(__FUNCTION__) +": I2c.init() failed"); } 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()); } //Will be reset by sub class. m_bitShift = 0; m_conversionDelay = .001; m_config_reg = 0x0000; std::vector upmTokens; if(!mraaIo->getLeftoverStr().empty()) { upmTokens = UpmStringParser::parse(mraaIo->getLeftoverStr()); } std::string::size_type sz; for (std::string tok : upmTokens) { if(tok.substr(0,12) == "setCompMode:") { bool mode = std::stoi(tok.substr(12),nullptr,0); setCompMode(mode); } if(tok.substr(0,11) == "setCompPol:") { bool mode = std::stoi(tok.substr(11),nullptr,0); setCompPol(mode); } if(tok.substr(0,13) == "setCompLatch:") { bool mode = std::stoi(tok.substr(13),nullptr,0); setCompLatch(mode); } if(tok.substr(0,14) == "setContinuous:") { bool mode = std::stoi(tok.substr(14),nullptr,0); setContinuous(mode); } if(tok.substr(0,21) == "updateConfigRegister:") { uint16_t update = std::stoi(tok.substr(21),&sz,0); tok = tok.substr(21); bool read = std::stoi(tok.substr(sz+1),nullptr,0); updateConfigRegister(update,read); } } } ADS1X15::~ADS1X15(){ delete mraaIo; } float ADS1X15::getSample(ADSMUXMODE mode){ updateConfigRegister((m_config_reg & ~ADS1X15_MUX_MASK) | mode, true); usleep(m_conversionDelay); return getLastSample(); } float ADS1X15::getLastSample(int reg){ uint16_t value = i2c->readWordReg(reg); bool neg = false; value = swapWord(value); if(value & 0x8000){ neg = true; value = ~value; } if(m_name == "ADS1015") value = value >> m_bitShift; if(neg) return 0.0 - value * getMultiplier(); else return value * getMultiplier(); } void ADS1X15::setGain(ADSGAIN gain){ updateConfigRegister((m_config_reg & ~ADS1X15_PGA_MASK) | gain); } void ADS1X15::setSPS(ADSSAMPLERATE rate){ updateConfigRegister((m_config_reg & ~ADS1X15_DR_MASK) | rate); } void ADS1X15::setCompMode(bool mode){ if(mode) updateConfigRegister((m_config_reg & ~ADS1X15_CMODE_MASK)); else updateConfigRegister((m_config_reg & ~ADS1X15_CMODE_MASK) | ADS1X15_CMODE_WINDOW); } void ADS1X15::setCompPol(bool mode){ if(!mode) updateConfigRegister((m_config_reg & ~ADS1X15_CPOL_MASK)); else updateConfigRegister((m_config_reg & ~ADS1X15_CPOL_MASK) | ADS1X15_CPOL_ACTVHI); } void ADS1X15::setCompLatch(bool mode){ if(mode) updateConfigRegister((m_config_reg & ~ADS1X15_CLAT_MASK)); else updateConfigRegister((m_config_reg & ~ADS1X15_CLAT_MASK) | ADS1X15_CLAT_LATCH); } void ADS1X15::setCompQue(ADSCOMP mode){ updateConfigRegister((m_config_reg & ~ADS1X15_CQUE_MASK) | mode); } void ADS1X15::setContinuous(bool mode){ if(mode) updateConfigRegister((m_config_reg & ~ADS1X15_MODE_MASK)); else updateConfigRegister((m_config_reg & ~ADS1X15_MODE_MASK) | ADS1X15_MODE_SINGLE); } float ADS1X15::getThresh(ADSTHRESH reg){ if(reg == THRESH_HIGH || reg == THRESH_LOW) return getLastSample(reg); else return 0.0; } void ADS1X15::setThresh(ADSTHRESH reg, float value){ uint16_t set_value; switch((int)reg){ case 4: //set conversion_rdy operation if(i2c->writeWordReg(ADS1X15_REG_POINTER_LOWTHRESH, 0x0000) != mraa::SUCCESS){ throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write() failed"); return; } if(i2c->writeWordReg(ADS1X15_REG_POINTER_HITHRESH, 0x0080) != mraa::SUCCESS){ throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write() failed"); return; } break; case 2: case 3: set_value = value / getMultiplier(); set_value = set_value << m_bitShift; if(i2c->writeWordReg(reg, swapWord(set_value)) != mraa::SUCCESS){ throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write() failed"); return; } break; case 5: //set default default: if(i2c->writeWordReg(ADS1X15_REG_POINTER_LOWTHRESH, 0x0080) != mraa::SUCCESS){ throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write() failed"); return; } if(i2c->writeWordReg(ADS1X15_REG_POINTER_HITHRESH, 0xF07F) != mraa::SUCCESS){ throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write() failed"); return; } break; } } //Private functions void ADS1X15::getCurrentConfig(){ m_config_reg = i2c->readWordReg(ADS1X15_REG_POINTER_CONFIG); m_config_reg = swapWord(m_config_reg); setDelay(); } void ADS1X15::updateConfigRegister(uint16_t update, bool read){ uint16_t temp = update; //Mask out read bit if we are just updating the configuration. if(!read) temp = update & 0x7FFF; if(i2c->writeWordReg(ADS1X15_REG_POINTER_CONFIG, swapWord(temp)) != mraa::SUCCESS){ throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write() failed"); return; } //If we update the configuration re-set the in memory copy. if(!read) getCurrentConfig(); } uint16_t ADS1X15::swapWord(uint16_t value){ uint16_t res = value; return ((res & 0xFF) << 8) | ((res >> 8 ) & 0xFF); } std::string ADS1X15::getLeftoverStr(){ return mraaIo->getLeftoverStr(); }