Skip to content

Commit

Permalink
Formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
LawrenceStanton committed Nov 26, 2023
1 parent bcd3872 commit 5904d68
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 78 deletions.
78 changes: 50 additions & 28 deletions Inc/HDC1080.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ class HDC1080 {
* This interface is used to abstract the I2C communication from the HDC1080 class.
* A concrete implementation is then aggregated by the HDC1080 class.
* The concrete implementation of this interface should be provided by the user.
* This also allows for the HDC1080 class to be tested without the need for a real I2C bus.
* The concrete implementation's lifetime must be managed by the user and must outlive the HDC1080 class.
* It is recommended that the concrete implementation be a static object.
* This also allows for the HDC1080 class to be tested without the need for a real I2C
* bus. The concrete implementation's lifetime must be managed by the user and must
* outlive the HDC1080 class. It is recommended that the concrete implementation be a
* static object.
*/
class I2C {
public:
Expand All @@ -52,38 +53,47 @@ class HDC1080 {
/**
* @brief Read a register from the HDC1080.
*
* @param memoryAddress The HDC1080 internal memory address of the register to read.
* @return std::optional<Register> The value of the register if the read was successful.
* @param memoryAddress The HDC1080 internal memory address of the register to
* read.
* @return std::optional<Register> The value of the register if the read was
* successful.
*/
virtual std::optional<Register> read(MemoryAddress memoryAddress) noexcept = 0;

/**
* @brief Write a register to the HDC1080.
*
* @param memoryAddress The HDC1080 internal memory address of the register to write.
* @param memoryAddress The HDC1080 internal memory address of the register to
* write.
* @param data The data to write to the register.
* @return std::optional<Register> The value written to the register if the write was successful.
* @return std::optional<Register> The value written to the register if the write
* was successful.
*/
virtual std::optional<Register> write(MemoryAddress memoryAddress, Register data) noexcept = 0;
virtual std::optional<Register>
write(MemoryAddress memoryAddress, Register data) noexcept = 0;

/**
* @brief Transmit a byte of data to the HDC1080.
*
* @param data The byte of data to transmit.
* @return std::optional<uint8_t> The byte of data transmitted to the HDC1080 if successful.
* @return std::optional<uint8_t> The byte of data transmitted to the HDC1080 if
* successful.
*
* @note This function is normally used to get measurement data from the HDC1080, where some measurement
* delays are necessary, and therefore this driver will assume implementation of the I2C protocol.
* @note This function is normally used to get measurement data from the HDC1080,
* where some measurement delays are necessary, and therefore this driver will
* assume implementation of the I2C protocol.
*/
virtual std::optional<uint8_t> transmit(uint8_t data) noexcept = 0;

/**
* @brief Receive a byte of data from the HDC1080.
*
* @return std::optional<uint8_t> The byte of data received from the HDC1080 if successful.
* @return std::optional<uint8_t> The byte of data received from the HDC1080 if
* successful.
*
* @note This function is normally used to get measurement data from the HDC1080, where some measurement
* delays are necessary, and therefore this driver will assume implementation of the I2C protocol.
* @note This function is normally used to get measurement data from the HDC1080,
* where some measurement delays are necessary, and therefore this driver will
* assume implementation of the I2C protocol.
*/
virtual std::optional<uint8_t> receive(void) noexcept = 0;

Expand Down Expand Up @@ -143,14 +153,16 @@ class HDC1080 {
/**
* @brief Get the Temperature Register
*
* @return std::optional<Register> The fetched value of the temperature register if successful.
* @return std::optional<Register> The fetched value of the temperature register if
* successful.
*/
std::optional<Register> getTemperatureRegister(void) const;

/**
* @brief Get the Humidity Register
*
* @return std::optional<Register> The fetched value of the humidity register if successful.
* @return std::optional<Register> The fetched value of the humidity register if
* successful.
*/
std::optional<Register> getHumidityRegister(void) const;

Expand All @@ -174,16 +186,17 @@ class HDC1080 {
*
* @return std::optional<uint64_t> The 41-bit serial ID if successful.
*
* @note The serial ID is a 41-bit number by the register map, but the HDC1080 datasheet states "40-bit".
* This driver will assume the register map is correct.
* @note The serial ID is a 41-bit number by the register map, but the HDC1080
* datasheet states "40-bit". This driver will assume the register map is correct.
* @note Unused bits are set to 0.
*/
std::optional<uint64_t> getSerialID(void) const;

/**
* @brief Get the Battery Status of the HDC1080.
*
* @return std::optional<bool> True if the supply voltage greater than 2V8, false if less than 2V8.
* @return std::optional<bool> True if the supply voltage greater than 2V8, false if
* less than 2V8.
*/
std::optional<Battery> getBatteryStatus(void) const;

Expand All @@ -195,11 +208,14 @@ class HDC1080 {
* @param hRes The resolution of the humidity measurement (8, 11, or 14 bit).
* @param heater The heater setting (on or off).
*
* @note The heater should only be turned on if necessary for saturated conditions. Refer to the datasheet §8.3.3.
* @note If only a single measurement is desired, the other measurement's resolution may be set to any valid value.
* @note All arguments are optional. Unspecified arguments will remain unchanged. If all arguments are specified,
* the config register is not read before being written.
* @note If no arguments are specified the function short circuits and returns an empty optional.
* @note The heater should only be turned on if necessary for saturated conditions.
* Refer to the datasheet §8.3.3.
* @note If only a single measurement is desired, the other measurement's resolution
* may be set to any valid value.
* @note All arguments are optional. Unspecified arguments will remain unchanged. If
* all arguments are specified, the config register is not read before being written.
* @note If no arguments are specified the function short circuits and returns an
* empty optional.
*/
std::optional<Register> setConfig(
std::optional<AcquisitionMode> acqMode, //
Expand All @@ -211,7 +227,8 @@ class HDC1080 {
/**
* @brief Performs a software reset of the HDC1080.
*
* @return std::optional<Register> The written value of the configuration register if successful.
* @return std::optional<Register> The written value of the configuration register if
* successful.
* @note The written value shall always be 0x8000.
*/
std::optional<Register> softReset(void) const;
Expand All @@ -222,9 +239,11 @@ class HDC1080 {
*
* @param memAddr The memory address of the register to fetch.
* @param waitTime The measurement conversion delay time in milliseconds.
* @return std::optional<Register> The fetched value of the measurement register if successful.
* @return std::optional<Register> The fetched value of the measurement register if
* successful.
*/
std::optional<Register> getMeasurementRegister(MemoryAddress memAddr, Duration waitTime = 0ms) const;
std::optional<Register>
getMeasurementRegister(MemoryAddress memAddr, Duration waitTime = 0ms) const;

/* Registration for Private Member Testing Purposes Only */
#ifdef HDC1080_GTEST_TESTING
Expand All @@ -239,7 +258,10 @@ class HDC1080 {
FRIEND_TEST(HDC1080_Test, getHumidityRegisterReturnsEmptyOptionalWhenI2CReceiveFails);

FRIEND_TEST(HDC1080_Test, getMeasurementRegisterNormallyReturnsValue);
FRIEND_TEST(HDC1080_Test, getMeasurementRegisterReturnsEmptyOptionalWhenI2CReceiveFails);
FRIEND_TEST(
HDC1080_Test,
getMeasurementRegisterReturnsEmptyOptionalWhenI2CReceiveFails
);
#endif
};

Expand Down
68 changes: 47 additions & 21 deletions Src/HDC1080.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ using namespace units::literals;
#define HDC1080_CONFIG_HUMIDITY_RESOLUTION_MASK 0x0300u

/**
* @note The below values are given a wide margin above the maximum conversion time specifications
* to allow for a imprecise delay timer method.
* @note The below values are given a wide margin above the maximum conversion time
* specifications to allow for a imprecise delay timer method.
*
* @note As of current in this source, the conversion time does not consider the resolution of the measurement.
* It is possible to reduce the delay time by defining shorter conversion times for lower resolution measurements
* and amending the measurement register getter methods to use these shorter delay times.
* @note As of current in this source, the conversion time does not consider the
* resolution of the measurement. It is possible to reduce the delay time by defining
* shorter conversion times for lower resolution measurements and amending the measurement
* register getter methods to use these shorter delay times.
*/
#define HDC1080_CONVERSION_TIME_TEMPERATURE 15ms
#define HDC1080_CONVERSION_TIME_HUMIDITY 15ms
Expand All @@ -72,11 +73,17 @@ using MemoryAddress = HDC1080::I2C::MemoryAddress;
HDC1080::HDC1080(I2C &i2c) : i2c{i2c} {}

std::optional<Register> HDC1080::getTemperatureRegister(void) const {
return getMeasurementRegister(HDC1080_TEMPERATURE_ADDR, HDC1080_CONVERSION_TIME_TEMPERATURE);
return getMeasurementRegister(
HDC1080_TEMPERATURE_ADDR,
HDC1080_CONVERSION_TIME_TEMPERATURE
);
}

std::optional<Register> HDC1080::getHumidityRegister(void) const {
return getMeasurementRegister(HDC1080_HUMIDITY_ADDR, HDC1080_CONVERSION_TIME_HUMIDITY);
return getMeasurementRegister(
HDC1080_HUMIDITY_ADDR,
HDC1080_CONVERSION_TIME_HUMIDITY
);
}

std::optional<Register> HDC1080::getDeviceID(void) const {
Expand All @@ -94,9 +101,10 @@ std::optional<uint64_t> HDC1080::getSerialID(void) const {
if (transmission.has_value()) serialID[i] = transmission.value();
else return std::nullopt;
}
const uint64_t serialIdValue = (((uint64_t)serialID[0] & 0xFFFF) << 25) // SERIAL_ID[40:25], register bits [15:0]
| (((uint64_t)serialID[1] & 0xFFFF) << 9) // SERIAL_ID[24:9], register bits [15:0]
| (((uint64_t)serialID[2] & 0xFF80) >> 7); // SERIAL_ID[8:0], register bits [15:7]
const uint64_t serialIdValue =
(((uint64_t)serialID[0] & 0xFFFF) << 25) // SERIAL_ID[40:25], register bits [15:0]
| (((uint64_t)serialID[1] & 0xFFFF) << 9) // SERIAL_ID[24:9], register bits [15:0]
| (((uint64_t)serialID[2] & 0xFF80) >> 7); // SERIAL_ID[8:0], register bits [15:7]

return serialIdValue;
}
Expand All @@ -105,12 +113,16 @@ std::optional<HDC1080::Battery> HDC1080::getBatteryStatus(void) const {
auto transmission = this->i2c.read(HDC1080_CONFIG_ADDR);

if (transmission.has_value())
return static_cast<HDC1080::Battery>(!(transmission.value() & HDC1080_CONFIG_BATTERY_STATUS_MASK));
return static_cast<HDC1080::Battery>(
!(transmission.value() & HDC1080_CONFIG_BATTERY_STATUS_MASK)
);
else return std::nullopt;
}

std::optional<HDC1080::I2C::Register>
HDC1080::getMeasurementRegister(HDC1080::I2C::MemoryAddress memAddr, Duration waitTime) const {
std::optional<HDC1080::I2C::Register> HDC1080::getMeasurementRegister(
HDC1080::I2C::MemoryAddress memAddr,
Duration waitTime
) const {
if (!this->i2c.transmit(static_cast<uint8_t>(memAddr))) return {};

this->i2c.delay(waitTime);
Expand All @@ -121,7 +133,9 @@ HDC1080::getMeasurementRegister(HDC1080::I2C::MemoryAddress memAddr, Duration wa
if (!data) return {};
}

return static_cast<HDC1080::I2C::Register>(transmissionData[0].value() << 8 | transmissionData[1].value());
return static_cast<HDC1080::I2C::Register>(
transmissionData[0].value() << 8 | transmissionData[1].value()
);
}

struct Config {
Expand All @@ -144,9 +158,15 @@ static Register constructConfigRegister(Config config) {

static Config decodeConfigRegister(Register configRegister) {
return Config{
static_cast<HDC1080::AcquisitionMode>(configRegister & HDC1080_CONFIG_ACQUISITION_MODE_MASK),
static_cast<HDC1080::TemperatureResolution>(configRegister & HDC1080_CONFIG_TEMPERATURE_RESOLUTION_MASK),
static_cast<HDC1080::HumidityResolution>(configRegister & HDC1080_CONFIG_HUMIDITY_RESOLUTION_MASK),
static_cast<HDC1080::AcquisitionMode>(
configRegister & HDC1080_CONFIG_ACQUISITION_MODE_MASK
),
static_cast<HDC1080::TemperatureResolution>(
configRegister & HDC1080_CONFIG_TEMPERATURE_RESOLUTION_MASK
),
static_cast<HDC1080::HumidityResolution>(
configRegister & HDC1080_CONFIG_HUMIDITY_RESOLUTION_MASK
),
static_cast<HDC1080::Heater>(configRegister & HDC1080_CONFIG_HEATER_MASK),
};
}
Expand Down Expand Up @@ -196,7 +216,9 @@ std::optional<Register> HDC1080::softReset(void) const {
* @return The temperature measurement in degrees Celsius.
*/
static Celsius constexpr convertTemperature(Register temperatureRegister) {
return Celsius(temperatureRegister * (165.0f / 65536.0f) - 40.0f); // Refer to HDC1080 datasheet for formula
return Celsius(
temperatureRegister * (165.0f / 65536.0f) - 40.0f
); // Refer to HDC1080 datasheet for formula
}

/**
Expand All @@ -205,13 +227,16 @@ static Celsius constexpr convertTemperature(Register temperatureRegister) {
* @return The percent relative humidity.
*/
static RelativeHumidity convertHumidity(Register humidityRegister) {
return RelativeHumidity(humidityRegister * (25.0f / 16384.0f) * 100); // Refer to HDC1080 datasheet for formula
return RelativeHumidity(
humidityRegister * (25.0f / 16384.0f) * 100
); // Refer to HDC1080 datasheet for formula
}

Celsius HDC1080_X::getTemperature(void) const {
auto temperatureRegister = getTemperatureRegister();

if (temperatureRegister.has_value()) return convertTemperature(temperatureRegister.value());
if (temperatureRegister.has_value())
return convertTemperature(temperatureRegister.value());

return -40.0_degC;
}
Expand All @@ -228,7 +253,8 @@ std::optional<Register> HDC1080_X::setAcquisitionMode(AcquisitionMode acqMode) c
return setConfig(acqMode, std::nullopt, std::nullopt, std::nullopt);
}

std::optional<Register> HDC1080_X::setTemperatureResolution(TemperatureResolution tRes) const {
std::optional<Register> HDC1080_X::setTemperatureResolution(TemperatureResolution tRes
) const {
return setConfig(std::nullopt, tRes, std::nullopt, std::nullopt);
}

Expand Down
Loading

0 comments on commit 5904d68

Please sign in to comment.