mirror of
https://github.com/fairwaves/UHD-Fairwaves.git
synced 2025-10-23 07:42:00 +00:00
150 lines
3.9 KiB
C++
150 lines
3.9 KiB
C++
//
|
|
// Copyright 2014 Fairwaves LLC
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
#include "ads1015_ctrl.hpp"
|
|
#include <boost/assign/list_of.hpp>
|
|
|
|
#include <iostream>
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER <= 1700)
|
|
#define nan(arg) std::strtod("NAN()", (char**)NULL)
|
|
#endif
|
|
|
|
using namespace uhd;
|
|
|
|
ads1015_ctrl::ads1015_ctrl()
|
|
: _addr(ADS1015_NONE)
|
|
, _config_reg(0)
|
|
{
|
|
|
|
}
|
|
|
|
bool ads1015_ctrl::check(const uhd::i2c_iface::sptr& iface, ads1015_addr addr)
|
|
{
|
|
byte_vector_t cmd = boost::assign::list_of(ADS1015_REG_LO_THRES);
|
|
iface->write_i2c(addr, cmd);
|
|
|
|
byte_vector_t vec = iface->read_i2c(addr, 2);
|
|
uint16_t res = (((uint16_t)vec.at(0)) << 8) | vec.at(1);
|
|
if (res == 0 || ((res & 0xF) != 0)) {
|
|
return false;
|
|
}
|
|
|
|
cmd[0] = ADS1015_REG_HI_THRES;
|
|
iface->write_i2c(addr, cmd);
|
|
vec = iface->read_i2c(addr, 2);
|
|
res = (((uint16_t)vec.at(0)) << 8) | vec.at(1);
|
|
if (res == 0xFFFF || ((res & 0xF) != 0xF)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ads1015_ctrl::init(i2c_iface::sptr iface, ads1015_addr addr)
|
|
{
|
|
_iface = iface;
|
|
_addr = addr;
|
|
_config_reg = get_reg(ADS1015_REG_CONFIG);
|
|
}
|
|
|
|
void ads1015_ctrl::set_input(ads1015_input input)
|
|
{
|
|
_config_reg = (_config_reg & ~ADS1015_CONF_MUX_MASK) |
|
|
(input << ADS1015_CONF_MUX_OFFS);
|
|
set_reg(ADS1015_REG_CONFIG, _config_reg);
|
|
}
|
|
|
|
void ads1015_ctrl::set_pga(ads1015_pga pga)
|
|
{
|
|
_config_reg = (_config_reg & ~ADS1015_CONF_PGA_MASK) |
|
|
(pga << ADS1015_CONF_PGA_OFFS);
|
|
set_reg(ADS1015_REG_CONFIG, _config_reg);
|
|
}
|
|
|
|
void ads1015_ctrl::set_mode(bool powerdown)
|
|
{
|
|
if (powerdown) {
|
|
_config_reg |= ADS1015_CONF_MODE;
|
|
} else {
|
|
_config_reg &= ~ADS1015_CONF_MODE;
|
|
}
|
|
set_reg(ADS1015_REG_CONFIG, _config_reg);
|
|
}
|
|
|
|
double ads1015_ctrl::get_value()
|
|
{
|
|
if (!_iface)
|
|
return nan("");
|
|
|
|
struct coeffs {
|
|
unsigned u;
|
|
unsigned d;
|
|
};
|
|
|
|
static const coeffs gain_cfs[] = {
|
|
{2,3}, // 6
|
|
{1,1}, // 4
|
|
{2,1}, // 2
|
|
{4,1}, // 1
|
|
{8,1}, // 0.5
|
|
{16,1}, // 0.25
|
|
};
|
|
|
|
unsigned pga = (_config_reg & ADS1015_CONF_PGA_MASK) >> ADS1015_CONF_PGA_OFFS;
|
|
if (pga > 5)
|
|
pga = 5;
|
|
|
|
if ((_config_reg & ADS1015_CONF_MODE) == ADS1015_CONF_MODE) {
|
|
// Power-down mode, start conversion
|
|
set_reg(ADS1015_REG_CONFIG, _config_reg | ADS1015_CONF_OS);
|
|
|
|
// Wait for conversion ready
|
|
unsigned i;
|
|
for (i = 0; i < ADS1015_POLL_RDY_WATCHDOG; i++) {
|
|
if (get_reg(ADS1015_REG_CONFIG) & ADS1015_CONF_OS)
|
|
break;
|
|
}
|
|
|
|
if (i == ADS1015_POLL_RDY_WATCHDOG)
|
|
return nan("");
|
|
}
|
|
|
|
uint16_t raw = get_reg(ADS1015_REG_CONVERSION);
|
|
double val = (raw >> 4);
|
|
val = val * gain_cfs[pga].d * 2 / (1000 * gain_cfs[pga].u );
|
|
return val;
|
|
}
|
|
|
|
|
|
uint16_t ads1015_ctrl::get_reg(ads1015_regs reg)
|
|
{
|
|
byte_vector_t cmd = boost::assign::list_of(reg);
|
|
_iface->write_i2c(_addr, cmd);
|
|
|
|
byte_vector_t vec = _iface->read_i2c(_addr, 2);
|
|
uint16_t res = (((uint16_t)vec.at(0)) << 8) | vec.at(1);
|
|
return res;
|
|
}
|
|
|
|
void ads1015_ctrl::set_reg(ads1015_regs reg, uint16_t value)
|
|
{
|
|
byte_vector_t cmd = boost::assign::list_of((uint8_t)reg)((uint8_t)(value >> 8))((uint8_t)(value & 0xFF));
|
|
_iface->write_i2c(_addr, cmd);
|
|
}
|
|
|