implement ads1015 driver (#2458)
* first approximation of ads1015 * fix ads * misc * comment Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
ef65c01a40
commit
9d7436c062
|
@ -0,0 +1,65 @@
|
|||
#include "ads1015.h"
|
||||
#include "efilib.h"
|
||||
|
||||
constexpr uint8_t addr = 0x48;
|
||||
|
||||
#define ADS1015_CONV (0)
|
||||
#define ADS1015_CONFIG (1)
|
||||
#define ADS1015_LO_THRESH (2)
|
||||
#define ADS1015_HI_THRESH (3)
|
||||
|
||||
bool Ads1015::init(brain_pin_e scl, brain_pin_e sda) {
|
||||
m_i2c.init(scl, sda);
|
||||
|
||||
// ADS1015 has no ID register - so we read the Lo_thresh instead
|
||||
uint16_t loThresh = readReg(ADS1015_LO_THRESH);
|
||||
|
||||
if (loThresh != 0x8000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hasInit = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Ads1015::readChannels(float (&result)[4]) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
result[i] = readChannel(i);
|
||||
}
|
||||
}
|
||||
|
||||
float Ads1015::readChannel(uint8_t ch) {
|
||||
// set the channel
|
||||
// set to +-6.144v full scale, fastest sampling, manual conversion start
|
||||
writeReg(ADS1015_CONFIG, 0xC1E0 | ch << 12);
|
||||
|
||||
// Wait for conversion to complete
|
||||
// Bit is cleared while conversion is ongoing, set when done
|
||||
while ((readReg(ADS1015_CONFIG) & 0x8000) == 0) ;
|
||||
|
||||
// Read the result
|
||||
int16_t result = readReg(ADS1015_CONV);
|
||||
// Result is 12 bits left aligned, so right align the result
|
||||
result = result >> 4;
|
||||
|
||||
// 2048 counts = positive 6.144 volts
|
||||
constexpr float ratio = 6.144f / 2048;
|
||||
return result * ratio;
|
||||
}
|
||||
|
||||
void Ads1015::writeReg(uint8_t reg, uint16_t data) {
|
||||
uint8_t packet[3];
|
||||
|
||||
packet[0] = reg;
|
||||
packet[1] = data >> 8;
|
||||
packet[2] = data & 0xFF;
|
||||
|
||||
m_i2c.write(addr, packet, 3);
|
||||
}
|
||||
|
||||
uint16_t Ads1015::readReg(uint8_t reg) {
|
||||
uint16_t res;
|
||||
m_i2c.write(addr, ®, 1);
|
||||
m_i2c.read(addr, reinterpret_cast<uint8_t*>(&res), 2);
|
||||
return SWAP_UINT16(res);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "i2c_bb.h"
|
||||
|
||||
class Ads1015 {
|
||||
public:
|
||||
bool init(brain_pin_e scl, brain_pin_e sda);
|
||||
void readChannels(float (&result)[4]);
|
||||
|
||||
private:
|
||||
float readChannel(uint8_t ch);
|
||||
|
||||
void writeReg(uint8_t reg, uint16_t data);
|
||||
uint16_t readReg(uint8_t reg);
|
||||
|
||||
bool m_hasInit = false;
|
||||
BitbangI2c m_i2c;
|
||||
};
|
|
@ -31,6 +31,7 @@ HW_LAYER_EMS_CPP = $(HW_LAYER_EGT_CPP) \
|
|||
$(PROJECT_DIR)/hw_layer/lcd/lcd_HD44780.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/adc/adc_inputs.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/adc/adc_subscription.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/adc/ads1015.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/sensors/hip9011.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/sensors/hip9011_logic.cpp \
|
||||
$(PROJECT_DIR)/hw_layer/mc33816.cpp \
|
||||
|
|
|
@ -188,8 +188,11 @@ void BitbangI2c::writeRead(uint8_t addr, const uint8_t* writeData, size_t writeS
|
|||
for (size_t i = 0; i < writeSize; i++) {
|
||||
writeByte(writeData[i]);
|
||||
}
|
||||
|
||||
// Send a repeated start bit to indicate transition to read
|
||||
|
||||
read(addr, readData, readSize);
|
||||
}
|
||||
|
||||
void BitbangI2c::read(uint8_t addr, uint8_t* readData, size_t readSize) {
|
||||
start();
|
||||
|
||||
// Address + read
|
||||
|
|
|
@ -23,6 +23,8 @@ public:
|
|||
|
||||
// Write a sequence of bytes to the specified device
|
||||
void write(uint8_t addr, const uint8_t* data, size_t size);
|
||||
// Read a sequence of bytes from the device
|
||||
void read(uint8_t addr, uint8_t* data, size_t size);
|
||||
// Write some bytes then read some bytes back after a repeated start bit
|
||||
void writeRead(uint8_t addr, const uint8_t* writeData, size_t writeSize, uint8_t* readData, size_t readSize);
|
||||
|
||||
|
|
Loading…
Reference in New Issue