[pcf85063] Convert the weekday to and from the chip's 0-6 range (#20736)

This commit is contained in:
Panoplian
2026-10-14 08:43:23 -10:00
committed by GitHub
parent b994e081c3
commit fee47fe2f1
3 changed files with 86 additions and 2 deletions
+3 -2
View File
@@ -37,7 +37,8 @@ void PCF85063Component::read_time() {
.second = uint8_t(pcf85063_.reg.second + 10 * pcf85063_.reg.second_10),
.minute = uint8_t(pcf85063_.reg.minute + 10u * pcf85063_.reg.minute_10),
.hour = uint8_t(pcf85063_.reg.hour + 10u * pcf85063_.reg.hour_10),
.day_of_week = uint8_t(pcf85063_.reg.weekday),
// The chip counts weekdays 0-6 from Sunday, ESPTime counts 1-7
.day_of_week = uint8_t(this->pcf85063_.reg.weekday + 1),
.day_of_month = uint8_t(pcf85063_.reg.day + 10u * pcf85063_.reg.day_10),
.month = uint8_t(pcf85063_.reg.month + 10u * pcf85063_.reg.month_10),
.year = uint16_t(pcf85063_.reg.year + 10u * pcf85063_.reg.year_10 + 2000),
@@ -62,7 +63,7 @@ void PCF85063Component::write_time() {
pcf85063_.reg.month_10 = now.month / 10;
pcf85063_.reg.day = now.day_of_month % 10;
pcf85063_.reg.day_10 = now.day_of_month / 10;
pcf85063_.reg.weekday = now.day_of_week;
this->pcf85063_.reg.weekday = now.day_of_week - 1;
pcf85063_.reg.hour = now.hour % 10;
pcf85063_.reg.hour_10 = now.hour / 10;
pcf85063_.reg.minute = now.minute % 10;
+6
View File
@@ -0,0 +1,6 @@
from tests.testing_helpers import ComponentManifestOverride
def override_manifest(manifest: ComponentManifestOverride) -> None:
# The driver lives in the time platform, so pull in what it builds against.
manifest.dependencies = manifest.dependencies + ["i2c", "time"]
@@ -0,0 +1,77 @@
#include <gtest/gtest.h>
#include <array>
#include <ctime>
#include "esphome/components/pcf85063/pcf85063.h"
#include "esphome/core/time.h"
namespace esphome::pcf85063::testing {
static constexpr uint8_t ADDRESS = 0x51;
static constexpr uint8_t WEEKDAYS_REG = 0x08;
static constexpr uint8_t CHIP_DAYS_PER_WEEK = 7; // The chip counts weekdays 0-6, Sunday = 0
// The chip's 18 registers behind an address pointer that moves on after every byte.
class RegisterBus final : public i2c::I2CBus {
public:
i2c::ErrorCode write_readv(uint8_t address, const uint8_t *data, size_t size, uint8_t *out,
size_t out_size) override {
EXPECT_EQ(address, ADDRESS);
if (size != 0) {
this->pointer_ = data[0];
for (size_t i = 1; i < size; i++)
this->registers[this->next_()] = data[i];
}
for (size_t i = 0; i < out_size; i++)
out[i] = this->registers[this->next_()];
return i2c::ERROR_OK;
}
std::array<uint8_t, 18> registers{};
protected:
size_t next_() { return this->pointer_++ % this->registers.size(); }
uint8_t pointer_{0};
};
// write_time() takes the host's current time, so reading it back never changes the host clock.
class PCF85063Test : public ::testing::Test {
protected:
void SetUp() override {
this->rtc_.set_i2c_bus(&this->bus_);
this->rtc_.set_i2c_address(ADDRESS);
this->rtc_.add_on_time_sync_callback([this]() { ++this->syncs_; });
this->rtc_.setup();
}
RegisterBus bus_;
PCF85063Component rtc_;
unsigned syncs_{0};
};
TEST_F(PCF85063Test, WriteTimeStoresTheChipsWeekday) {
// Read the clock on both sides of the write, in case UTC midnight falls in between.
const int before = ESPTime::from_epoch_utc(::time(nullptr)).day_of_week - 1;
this->rtc_.write_time();
const int after = ESPTime::from_epoch_utc(::time(nullptr)).day_of_week - 1;
const int stored = this->bus_.registers[WEEKDAYS_REG];
EXPECT_TRUE(stored == before || stored == after) << "stored " << stored << ", expected " << before;
}
// After a write the chip keeps counting on its own and goes from Saturday (6) back to Sunday (0) at midnight.
// Seven steps from the written value visit every weekday once, and each has to read back as a valid time.
// Only the weekday moves, so the time read back is still the host's time.
TEST_F(PCF85063Test, WeekdayRoundTripsThroughSundayAndSaturday) {
this->rtc_.write_time();
uint8_t &weekday = this->bus_.registers[WEEKDAYS_REG];
for (uint8_t day = 0; day < CHIP_DAYS_PER_WEEK; day++) {
weekday = (weekday + 1) % CHIP_DAYS_PER_WEEK;
const unsigned syncs_before = this->syncs_;
this->rtc_.read_time();
EXPECT_EQ(this->syncs_, syncs_before + 1) << "chip weekday " << unsigned(weekday);
}
}
} // namespace esphome::pcf85063::testing