Compare commits
3 Commits
2a90cdee18
...
3029c3cfe0
Author | SHA1 | Date | |
---|---|---|---|
3029c3cfe0 | |||
c3f9aa6a13 | |||
db5197b3b1 |
56
ds3231.hpp
56
ds3231.hpp
@ -154,7 +154,7 @@ class DS3231 {
|
||||
constexpr auto DATE_START_OFFSET = offsetof(detail::TimeReg, day);
|
||||
constexpr auto DATE_END_OFFSET = offsetof(detail::TimeReg, year);
|
||||
|
||||
writePartialRegister<TIME_REG_ADDR, DATE_START_OFFSET, DATE_END_OFFSET>(timeReg);
|
||||
writePartialRegister<DATE_START_OFFSET, DATE_END_OFFSET>(timeReg);
|
||||
}
|
||||
static void setTime(const Time &time)
|
||||
{
|
||||
@ -166,7 +166,7 @@ class DS3231 {
|
||||
constexpr auto TIME_START_OFFSET = offsetof(detail::TimeReg, seconds);
|
||||
constexpr auto TIME_END_OFFSET = offsetof(detail::TimeReg, hours);
|
||||
|
||||
writePartialRegister<TIME_REG_ADDR, TIME_START_OFFSET, TIME_END_OFFSET>(timeReg);
|
||||
writePartialRegister<TIME_START_OFFSET, TIME_END_OFFSET>(timeReg);
|
||||
}
|
||||
static void setDateTime(const DateTime &dateTime)
|
||||
{
|
||||
@ -184,7 +184,7 @@ class DS3231 {
|
||||
constexpr auto START_OFFSET = offsetof(detail::TimeReg, seconds);
|
||||
constexpr auto END_OFFSET = offsetof(detail::TimeReg, year);
|
||||
|
||||
writePartialRegister<TIME_REG_ADDR, START_OFFSET, END_OFFSET>(timeReg);
|
||||
writePartialRegister<START_OFFSET, END_OFFSET>(timeReg);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -224,9 +224,31 @@ class DS3231 {
|
||||
}
|
||||
}
|
||||
|
||||
template <uint8_t Address, uint8_t StartOffset, uint8_t EndOffset, typename Register>
|
||||
template <uint8_t StartOffset, uint8_t EndOffset, typename Register>
|
||||
static void writePartialRegister(const Register ®)
|
||||
{
|
||||
constexpr auto getRegisterAddress = []() {
|
||||
if constexpr (util::is_same_v<Register, detail::TimeReg>) {
|
||||
return TIME_REG_ADDR;
|
||||
} else if constexpr (util::is_same_v<Register, detail::Alarm1Reg>) {
|
||||
return ALARM1_REG_ADDR;
|
||||
} else if constexpr (util::is_same_v<Register, detail::Alarm2Reg>) {
|
||||
return ALARM2_REG_ADDR;
|
||||
} else if constexpr (util::is_same_v<Register, detail::ControlReg>) {
|
||||
return CONTROL_REG_ADDR;
|
||||
} else if constexpr (util::is_same_v<Register, detail::ControlStatusReg>) {
|
||||
return CONTROL_STATUS_REG_ADDR;
|
||||
} else if constexpr (util::is_same_v<Register, detail::AgingOffsetReg>) {
|
||||
return AGING_OFFSET_REG_ADDR;
|
||||
} else if constexpr (util::is_same_v<Register, detail::TempReg>) {
|
||||
return TEMP_REG_ADDR;
|
||||
} else {
|
||||
static_assert(util::always_false_v<Register>, "Invalid register type");
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto ADDRESS = getRegisterAddress();
|
||||
|
||||
static_assert(StartOffset <= EndOffset, "Invalid offset range");
|
||||
static_assert(StartOffset < sizeof(Register), "Start offset out of bounds");
|
||||
static_assert(EndOffset < sizeof(Register), "End offset out of bounds");
|
||||
@ -234,30 +256,18 @@ class DS3231 {
|
||||
constexpr auto WRITE_SIZE = EndOffset + 1 - StartOffset;
|
||||
static_assert(StartOffset + WRITE_SIZE <= sizeof(Register), "Writing out of bounds");
|
||||
|
||||
if constexpr (Address == TIME_REG_ADDR) {
|
||||
static_assert(util::is_same_v<Register, detail::TimeReg>, "Invalid register type");
|
||||
} else if constexpr (Address == ALARM1_REG_ADDR) {
|
||||
static_assert(util::is_same_v<Register, detail::Alarm1Reg>, "Invalid register type");
|
||||
} else if constexpr (Address == ALARM2_REG_ADDR) {
|
||||
static_assert(util::is_same_v<Register, detail::Alarm2Reg>, "Invalid register type");
|
||||
} else if constexpr (Address == CONTROL_REG_ADDR) {
|
||||
static_assert(util::is_same_v<Register, detail::ControlReg>, "Invalid register type");
|
||||
} else if constexpr (Address == CONTROL_STATUS_REG_ADDR) {
|
||||
static_assert(util::is_same_v<Register, detail::ControlStatusReg>, "Invalid register type");
|
||||
} else if constexpr (Address == AGING_OFFSET_REG_ADDR) {
|
||||
static_assert(util::is_same_v<Register, detail::AgingOffsetReg>, "Invalid register type");
|
||||
} else if constexpr (Address == TEMP_REG_ADDR) {
|
||||
static_assert(util::is_same_v<Register, detail::TempReg>, "Invalid register type");
|
||||
} else {
|
||||
static_assert(util::always_false_v<Register>, "Invalid register address");
|
||||
}
|
||||
|
||||
i2c_t::template start<I2C_ADDRESS>(false);
|
||||
i2c_t::write(Address + StartOffset);
|
||||
i2c_t::write(ADDRESS + StartOffset);
|
||||
i2c_t::template writeBytes<WRITE_SIZE>(reinterpret_cast<const uint8_t *>(®) + StartOffset);
|
||||
i2c_t::stop();
|
||||
}
|
||||
|
||||
template <typename Register>
|
||||
static void writeRegister(const Register ®)
|
||||
{
|
||||
writePartialRegister<0, sizeof(Register) - 1>(reg);
|
||||
}
|
||||
|
||||
static uint8_t calcDayOfWeek(uint16_t year, uint8_t month, uint16_t day)
|
||||
{
|
||||
day += month < 3 ? year-- : year - 2;
|
||||
|
17
flags.hpp
17
flags.hpp
@ -37,17 +37,34 @@ struct [[gnu::packed]] FlagsImpl
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlagsImpl &operator|=(const uint8_t &flag)
|
||||
{
|
||||
data |= flag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlagsImpl &operator&=(const FlagsT &flag)
|
||||
{
|
||||
data &= static_cast<uint8_t>(flag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlagsImpl &operator&=(const uint8_t &flag)
|
||||
{
|
||||
data &= flag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlagsImpl &operator~()
|
||||
{
|
||||
data = ~data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const FlagsT &flag) const
|
||||
{
|
||||
return data & static_cast<uint8_t>(flag);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FlagsT>
|
||||
|
@ -375,6 +375,11 @@ enum class ControlRegFlags : uint8_t {
|
||||
A1IE = 1 << 0,
|
||||
};
|
||||
|
||||
static inline uint8_t operator~(const ControlRegFlags &flag)
|
||||
{
|
||||
return ~static_cast<uint8_t>(flag);
|
||||
}
|
||||
|
||||
struct [[gnu::packed]] ControlReg : FlagsImpl<ControlRegFlags>{};
|
||||
|
||||
static_assert(sizeof(ControlReg) == 1, "Invalid control register size");
|
||||
@ -389,6 +394,11 @@ enum class ControlStatusRegFlags : uint8_t {
|
||||
A1F = 1 << 0,
|
||||
};
|
||||
|
||||
static inline uint8_t operator~(const ControlStatusRegFlags &flag)
|
||||
{
|
||||
return ~static_cast<uint8_t>(flag);
|
||||
}
|
||||
|
||||
struct [[gnu::packed]] ControlStatusReg : FlagsImpl<ControlStatusRegFlags>{};
|
||||
|
||||
static_assert(sizeof(ControlStatusReg) == 1, "Invalid control/status register size");
|
||||
|
Loading…
Reference in New Issue
Block a user