Implement modern C++ driver base
This commit is contained in:
parent
2768009720
commit
54b8917705
130
ds3231.hpp
Normal file
130
ds3231.hpp
Normal file
@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
|
||||
#include "../clock.hpp"
|
||||
|
||||
#include "../i2c/i2c.hpp"
|
||||
#include "../type/type.hpp"
|
||||
|
||||
#include "registers.hpp"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
struct Date {
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
};
|
||||
|
||||
struct Time {
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
};
|
||||
|
||||
struct DateTime : Date, Time {
|
||||
};
|
||||
|
||||
template <typename I2cDriver>
|
||||
class DS3231 {
|
||||
public:
|
||||
static constexpr auto I2C_ADDRESS = 0x68;
|
||||
|
||||
static constexpr auto TIME_REG_ADDR = 0x00;
|
||||
static constexpr auto ALARM1_REG_ADDR = 0x07;
|
||||
static constexpr auto ALARM2_REG_ADDR = 0x0B;
|
||||
static constexpr auto CONTROL_REG_ADDR = 0x0E;
|
||||
static constexpr auto CONTROL_STATUS_REG_ADDR = 0x0F;
|
||||
static constexpr auto AGING_OFFSET_REG_ADDR = 0x10;
|
||||
static constexpr auto TEMP_REG_ADDR = 0x11;
|
||||
|
||||
// Construction does not call init and is only available for convenience
|
||||
DS3231() = default;
|
||||
|
||||
// Moving and copying ds3231 objects is not supported
|
||||
DS3231(const DS3231 &) = delete;
|
||||
DS3231(DS3231 &&) = delete;
|
||||
DS3231 &operator=(const DS3231 &) = delete;
|
||||
DS3231 &operator=(DS3231 &&) = delete;
|
||||
|
||||
static inline void init()
|
||||
{
|
||||
I2cDriver::init();
|
||||
}
|
||||
|
||||
static auto getDate()
|
||||
{
|
||||
const auto timeReg = readRegister<TIME_REG_ADDR>();
|
||||
|
||||
Date date;
|
||||
date.year = timeReg.getYear();
|
||||
date.month = timeReg.getMonth();
|
||||
date.day = timeReg.getDate();
|
||||
return date;
|
||||
}
|
||||
static auto getTime()
|
||||
{
|
||||
const auto timeReg = readRegister<TIME_REG_ADDR>();
|
||||
|
||||
Time time;
|
||||
time.hour = timeReg.getHours();
|
||||
time.minute = timeReg.getMinutes();
|
||||
time.second = timeReg.getSeconds();
|
||||
return time;
|
||||
}
|
||||
static auto getDateTime()
|
||||
{
|
||||
const auto timeReg = readRegister<TIME_REG_ADDR>();
|
||||
|
||||
DateTime dateTime;
|
||||
dateTime.year = timeReg.getYear();
|
||||
dateTime.month = timeReg.getMonth();
|
||||
dateTime.day = timeReg.getDate();
|
||||
dateTime.hour = timeReg.getHours();
|
||||
dateTime.minute = timeReg.getMinutes();
|
||||
dateTime.second = timeReg.getSeconds();
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
static void setDate(const Date &date) {}
|
||||
static void setTime(const Time &time) {}
|
||||
static void setDateTime(const DateTime &dateTime) {}
|
||||
|
||||
private:
|
||||
template <uint8_t Address, typename Register>
|
||||
static Register readRegisterHelper()
|
||||
{
|
||||
I2cDriver::template start<I2C_ADDRESS>(false);
|
||||
I2cDriver::write(Address);
|
||||
I2cDriver::stop();
|
||||
|
||||
Register reg;
|
||||
I2cDriver::template start<I2C_ADDRESS>(true);
|
||||
I2cDriver::template readBytes<sizeof(Register)>(reinterpret_cast<uint8_t *>(®));
|
||||
I2cDriver::stop();
|
||||
return reg;
|
||||
}
|
||||
|
||||
template <uint8_t Address>
|
||||
static auto readRegister()
|
||||
{
|
||||
if constexpr (Address == TIME_REG_ADDR) {
|
||||
return readRegisterHelper<Address, detail::TimeReg>();
|
||||
} else if constexpr (Address == ALARM1_REG_ADDR) {
|
||||
return readRegisterHelper<Address, detail::Alarm1Reg>();
|
||||
} else if constexpr (Address == ALARM2_REG_ADDR) {
|
||||
return readRegisterHelper<Address, detail::Alarm2Reg>();
|
||||
} else if constexpr (Address == CONTROL_REG_ADDR) {
|
||||
return readRegisterHelper<Address, detail::ControlReg>();
|
||||
} else if constexpr (Address == CONTROL_STATUS_REG_ADDR) {
|
||||
return readRegisterHelper<Address, detail::ControlStatusReg>();
|
||||
} else if constexpr (Address == AGING_OFFSET_REG_ADDR) {
|
||||
return readRegisterHelper<Address, detail::AgingOffsetReg>();
|
||||
} else if constexpr (Address == TEMP_REG_ADDR) {
|
||||
return readRegisterHelper<Address, detail::TempReg>();
|
||||
} else {
|
||||
static_assert(type::always_false_v<decltype(Address)>, "Invalid register address");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rtc
|
71
flags.hpp
Normal file
71
flags.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename FlagsT>
|
||||
struct [[gnu::packed]] FlagsImpl
|
||||
{
|
||||
static_assert(sizeof(FlagsT) == sizeof(uint8_t), "Must use uint8_t enum class flags");
|
||||
|
||||
uint8_t data;
|
||||
using Flags = FlagsT;
|
||||
|
||||
FlagsImpl() : data(0) {}
|
||||
FlagsImpl(const Flags &flag) : data(static_cast<uint8_t>(flag)) {}
|
||||
|
||||
FlagsImpl(const FlagsImpl &other) : data(other.data) {}
|
||||
FlagsImpl(const FlagsImpl &&) = delete;
|
||||
|
||||
FlagsImpl &operator=(const FlagsImpl &rhs)
|
||||
{
|
||||
data = rhs.data;
|
||||
return *this;
|
||||
}
|
||||
FlagsImpl &operator=(const FlagsImpl &&) = delete;
|
||||
|
||||
FlagsImpl &operator=(const FlagsT &rhs)
|
||||
{
|
||||
data = static_cast<uint8_t>(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlagsImpl &operator|=(const FlagsT &flag)
|
||||
{
|
||||
data |= static_cast<uint8_t>(flag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlagsImpl &operator&=(const FlagsT &flag)
|
||||
{
|
||||
data &= static_cast<uint8_t>(flag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlagsImpl &operator~()
|
||||
{
|
||||
data = ~data;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FlagsT>
|
||||
FlagsT operator|(const FlagsT &lhs, const FlagsT &rhs)
|
||||
{
|
||||
const auto lhsInt = static_cast<uint8_t>(lhs);
|
||||
const auto rhsInt = static_cast<uint8_t>(rhs);
|
||||
return static_cast<FlagsT>(lhsInt | rhsInt);
|
||||
}
|
||||
|
||||
template <typename FlagsT>
|
||||
FlagsT operator&(const FlagsT &lhs, const FlagsT &rhs)
|
||||
{
|
||||
const auto lhsInt = static_cast<uint8_t>(lhs);
|
||||
const auto rhsInt = static_cast<uint8_t>(rhs);
|
||||
return static_cast<FlagsT>(lhsInt & rhsInt);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace rtc
|
419
registers.hpp
Normal file
419
registers.hpp
Normal file
@ -0,0 +1,419 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "flags.hpp"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace detail {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <uint8_t Mask = 0xFF>
|
||||
static inline uint8_t toBcd(const uint8_t &data)
|
||||
{
|
||||
return ((data / 10 * 16) + (data % 10)) & Mask;
|
||||
}
|
||||
|
||||
template <uint8_t Mask = 0xFF>
|
||||
static inline uint8_t fromBcd(const uint8_t &data)
|
||||
{
|
||||
const auto maskedData = data & Mask;
|
||||
return ((maskedData / 16 * 10) + (maskedData % 16));
|
||||
}
|
||||
|
||||
static inline uint8_t convertTo24Hour(const uint8_t &hoursReg)
|
||||
{
|
||||
constexpr auto FLAG_12_HOUR = 6;
|
||||
constexpr auto FLAG_PM = 5;
|
||||
|
||||
const bool time12HourFormat = (hoursReg >> FLAG_12_HOUR) & 1;
|
||||
|
||||
if (time12HourFormat) {
|
||||
const auto pmFlag = (hoursReg >> FLAG_PM) & 1;
|
||||
constexpr auto HOUR_12_MASK = 0b00011111;
|
||||
const auto hour12 = fromBcd<HOUR_12_MASK>(hoursReg);
|
||||
if (hour12 == 12 && !pmFlag)
|
||||
return 0;
|
||||
return hour12 + pmFlag ? 12 : 0;
|
||||
} else // 24 hour format
|
||||
{
|
||||
constexpr auto HOUR_MASK = 0b00111111;
|
||||
return fromBcd<HOUR_MASK>(hoursReg);
|
||||
}
|
||||
}
|
||||
|
||||
template <uint8_t Mask = 0b01111111>
|
||||
static inline uint8_t getMaskedBcd(const uint8_t ®)
|
||||
{
|
||||
return fromBcd<Mask>(reg);
|
||||
}
|
||||
|
||||
template <uint8_t Mask = 0b01111111>
|
||||
static inline void setMaskedBcd(uint8_t ®, const uint8_t &value)
|
||||
{
|
||||
reg &= ~Mask;
|
||||
reg |= toBcd<Mask>(value);
|
||||
}
|
||||
|
||||
static inline bool getEncodedDay(uint8_t &value, const uint8_t ®)
|
||||
{
|
||||
constexpr auto DAY_FLAG = 6;
|
||||
if ((reg >> DAY_FLAG) & 1) {
|
||||
constexpr auto DAY_MASK = 0b00001111;
|
||||
value = reg & DAY_MASK;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool getEncodedDate(uint8_t &value, const uint8_t ®)
|
||||
{
|
||||
constexpr auto DAY_FLAG = 6;
|
||||
if (!((reg >> DAY_FLAG) & 1)) {
|
||||
value = getMaskedBcd<0b00111111>(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void setEncodedDay(uint8_t ®, const uint8_t &value)
|
||||
{
|
||||
constexpr auto DAY_MASK = 0b11110000;
|
||||
reg &= DAY_MASK;
|
||||
reg |= value & DAY_MASK;
|
||||
constexpr auto DAY_FLAG = 6;
|
||||
reg |= (1 << DAY_FLAG);
|
||||
}
|
||||
|
||||
static inline void setEncodedDate(uint8_t ®, const uint8_t &value)
|
||||
{
|
||||
setMaskedBcd<0b00111111>(reg, value);
|
||||
constexpr auto DAY_FLAG = 6;
|
||||
reg &= ~(1 << DAY_FLAG);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct [[gnu::packed]] TimeReg
|
||||
{
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
uint8_t hours;
|
||||
uint8_t day;
|
||||
uint8_t date;
|
||||
uint8_t month_century;
|
||||
uint8_t year;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline uint8_t getSeconds() const
|
||||
{
|
||||
return getMaskedBcd(seconds);
|
||||
}
|
||||
inline uint8_t getMinutes() const
|
||||
{
|
||||
return getMaskedBcd(minutes);
|
||||
}
|
||||
inline uint8_t getHours() const
|
||||
{
|
||||
return convertTo24Hour(hours);
|
||||
}
|
||||
inline uint8_t getDay() const
|
||||
{
|
||||
return getMaskedBcd<0b00000111>(day);
|
||||
}
|
||||
inline uint8_t getDate() const
|
||||
{
|
||||
return getMaskedBcd<0b00111111>(date);
|
||||
}
|
||||
inline uint8_t getMonth() const
|
||||
{
|
||||
return getMaskedBcd<0b00011111>(month_century);
|
||||
}
|
||||
inline bool getCentury() const
|
||||
{
|
||||
constexpr auto CENTURY_FLAG = 7;
|
||||
return (month_century >> CENTURY_FLAG) & 1;
|
||||
}
|
||||
inline uint16_t getYear() const
|
||||
{
|
||||
return 2000 + fromBcd(year);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void setSeconds(uint8_t seconds)
|
||||
{
|
||||
setMaskedBcd(this->seconds, seconds);
|
||||
}
|
||||
inline void setMinutes(uint8_t minutes)
|
||||
{
|
||||
setMaskedBcd(this->minutes, minutes);
|
||||
}
|
||||
inline void setHours(uint8_t hours)
|
||||
{
|
||||
setMaskedBcd(this->hours, hours);
|
||||
}
|
||||
inline void setDay(uint8_t day)
|
||||
{
|
||||
this->day = day & 0b111;
|
||||
}
|
||||
inline void setDate(uint8_t date)
|
||||
{
|
||||
setMaskedBcd<0b00111111>(this->date, date);
|
||||
}
|
||||
inline void setMonth(uint8_t month)
|
||||
{
|
||||
setMaskedBcd<0b00011111>(month_century, month);
|
||||
}
|
||||
inline void setCentury(bool century)
|
||||
{
|
||||
constexpr auto CENTURY_POS = 7;
|
||||
month_century &= ~(1 << CENTURY_POS);
|
||||
month_century |= (century << CENTURY_POS);
|
||||
}
|
||||
inline void setYear(uint16_t year)
|
||||
{
|
||||
year = year % 100;
|
||||
this->year = toBcd(year);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(TimeReg) == 7, "Invalid time register size");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct [[gnu::packed]] Alarm1Reg
|
||||
{
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
uint8_t hours;
|
||||
uint8_t day_date;
|
||||
|
||||
enum class AlarmRate {
|
||||
ONCE_PER_S = 0b1111,
|
||||
WHEN_S_MATCH = 0b1110,
|
||||
WHEN_M_S_MATCH = 0b1100,
|
||||
WHEN_H_M_S_MATCH = 0b1000,
|
||||
WHEN_DATE_H_M_S_MATCH = 0b00000,
|
||||
WHEN_DAY_H_N_S_MATCH = 0b10000,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline uint8_t getSeconds() const
|
||||
{
|
||||
return getMaskedBcd(seconds);
|
||||
}
|
||||
inline uint8_t getMinutes() const
|
||||
{
|
||||
return getMaskedBcd(minutes);
|
||||
}
|
||||
inline uint8_t getHours() const
|
||||
{
|
||||
return convertTo24Hour(hours);
|
||||
}
|
||||
inline bool getDay(uint8_t & day) const
|
||||
{
|
||||
return getEncodedDay(day, day_date);
|
||||
}
|
||||
inline bool getDate(uint8_t & date) const
|
||||
{
|
||||
return getEncodedDate(date, day_date);
|
||||
}
|
||||
inline AlarmRate getAlarmRate() const
|
||||
{
|
||||
constexpr auto M_FLAG = 7;
|
||||
const auto m1 = (seconds >> M_FLAG) & 1;
|
||||
const auto m2 = (minutes >> M_FLAG) & 1;
|
||||
const auto m3 = (hours >> M_FLAG) & 1;
|
||||
const auto m4 = (day_date >> M_FLAG) & 1;
|
||||
const auto m = (m4 << 3) | (m3 << 2) | (m2 << 1) | (m1 << 0);
|
||||
if (m == 0) {
|
||||
constexpr auto DAY_FLAG = 6;
|
||||
const auto dayFormat = ((day_date >> DAY_FLAG) & 1) << 4;
|
||||
return static_cast<AlarmRate>(dayFormat);
|
||||
}
|
||||
return static_cast<AlarmRate>(m);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void setSeconds(uint8_t seconds)
|
||||
{
|
||||
setMaskedBcd(this->seconds, seconds);
|
||||
}
|
||||
inline void setMinutes(uint8_t minutes)
|
||||
{
|
||||
setMaskedBcd(this->minutes, minutes);
|
||||
}
|
||||
inline void setHours(uint8_t hours)
|
||||
{
|
||||
setMaskedBcd(this->hours, hours);
|
||||
}
|
||||
inline void setDay(uint8_t day)
|
||||
{
|
||||
setEncodedDay(day_date, day);
|
||||
}
|
||||
inline void setDate(uint8_t date)
|
||||
{
|
||||
setEncodedDate(day_date, date);
|
||||
}
|
||||
inline void setAlarmRate(const AlarmRate &alarmRate)
|
||||
{
|
||||
const auto alarmRateFlags = static_cast<uint8_t>(alarmRate);
|
||||
constexpr auto M_FLAG = 7;
|
||||
seconds &= ~(1 << M_FLAG);
|
||||
seconds |= (alarmRateFlags & 1) << M_FLAG;
|
||||
minutes &= ~(1 << M_FLAG);
|
||||
minutes |= ((alarmRateFlags >> 1) & 1) << M_FLAG;
|
||||
hours &= ~(1 << M_FLAG);
|
||||
hours |= ((alarmRateFlags >> 2) & 1) << M_FLAG;
|
||||
day_date &= ~(1 << M_FLAG);
|
||||
day_date |= ((alarmRateFlags >> 3) & 1) << M_FLAG;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Alarm1Reg) == 4, "Invalid alarm1 register size");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct [[gnu::packed]] Alarm2Reg
|
||||
{
|
||||
uint8_t minutes;
|
||||
uint8_t hours;
|
||||
uint8_t day_date;
|
||||
|
||||
enum class AlarmRate {
|
||||
ONCE_PER_M = 0b111,
|
||||
WHEN_M_MATCH = 0b110,
|
||||
WHEN_H_M_MATCH = 0b100,
|
||||
WHEN_DATE_H_M_MATCH = 0b0000,
|
||||
WHEN_DAY_H_N_MATCH = 0b1000,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline uint8_t getMinutes() const
|
||||
{
|
||||
return getMaskedBcd(minutes);
|
||||
}
|
||||
inline uint8_t getHours() const
|
||||
{
|
||||
return convertTo24Hour(hours);
|
||||
}
|
||||
inline bool getDay(uint8_t & day) const
|
||||
{
|
||||
return getEncodedDay(day, day_date);
|
||||
}
|
||||
inline bool getDate(uint8_t & date) const
|
||||
{
|
||||
return getEncodedDate(date, day_date);
|
||||
}
|
||||
inline AlarmRate getAlarmRate() const
|
||||
{
|
||||
constexpr auto M_FLAG = 7;
|
||||
const auto m2 = (minutes >> M_FLAG) & 1;
|
||||
const auto m3 = (hours >> M_FLAG) & 1;
|
||||
const auto m4 = (day_date >> M_FLAG) & 1;
|
||||
const auto m = (m4 << 2) | (m3 << 1) | (m2 << 0);
|
||||
if (m == 0) {
|
||||
constexpr auto DAY_FLAG = 6;
|
||||
const auto dayFormat = ((day_date >> DAY_FLAG) & 1) << 3;
|
||||
return static_cast<AlarmRate>(dayFormat);
|
||||
}
|
||||
return static_cast<AlarmRate>(m);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void setMinutes(uint8_t minutes)
|
||||
{
|
||||
setMaskedBcd(this->minutes, minutes);
|
||||
}
|
||||
inline void setHours(uint8_t hours)
|
||||
{
|
||||
setMaskedBcd(this->hours, hours);
|
||||
}
|
||||
inline void setDay(uint8_t day)
|
||||
{
|
||||
setEncodedDay(day_date, day);
|
||||
}
|
||||
inline void setDate(uint8_t date)
|
||||
{
|
||||
setEncodedDate(day_date, date);
|
||||
}
|
||||
inline void setAlarmRate(const AlarmRate &alarmRate)
|
||||
{
|
||||
const auto alarmRateFlags = static_cast<uint8_t>(alarmRate);
|
||||
constexpr auto M_FLAG = 7;
|
||||
minutes &= ~(1 << M_FLAG);
|
||||
minutes |= (alarmRateFlags & 1) << M_FLAG;
|
||||
hours &= ~(1 << M_FLAG);
|
||||
hours |= ((alarmRateFlags >> 1) & 1) << M_FLAG;
|
||||
day_date &= ~(1 << M_FLAG);
|
||||
day_date |= ((alarmRateFlags >> 2) & 1) << M_FLAG;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Alarm2Reg) == 3, "Invalid alarm2 register size");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum class ControlRegFlags : uint8_t {
|
||||
N_EOSC = 1 << 7,
|
||||
BBSQW = 1 << 6,
|
||||
CONV = 1 << 5,
|
||||
RS2 = 1 << 4,
|
||||
RS1 = 1 << 3,
|
||||
INTCN = 1 << 2,
|
||||
A2IE = 1 << 1,
|
||||
A1IE = 1 << 0,
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] ControlReg : FlagsImpl<ControlRegFlags>{};
|
||||
|
||||
static_assert(sizeof(ControlReg) == 1, "Invalid control register size");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum class ControlStatusRegFlags : uint8_t {
|
||||
OSF = 1 << 7,
|
||||
EN32KHZ = 1 << 3,
|
||||
BSY = 1 << 2,
|
||||
A2F = 1 << 1,
|
||||
A1F = 1 << 0,
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] ControlStatusReg : FlagsImpl<ControlStatusRegFlags>{};
|
||||
|
||||
static_assert(sizeof(ControlStatusReg) == 1, "Invalid control/status register size");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct [[gnu::packed]] AgingOffsetReg
|
||||
{
|
||||
uint8_t data;
|
||||
};
|
||||
|
||||
static_assert(sizeof(AgingOffsetReg) == 1, "Invalid aging offset register size");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct [[gnu::packed]] TempReg
|
||||
{
|
||||
uint8_t msb_temp;
|
||||
uint8_t lsb_temp;
|
||||
};
|
||||
|
||||
static_assert(sizeof(TempReg) == 2, "Invalid temperature register size");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace rtc
|
Loading…
Reference in New Issue
Block a user