mirror of
https://github.com/esphome/esphome.git
synced 2026-10-17 03:32:50 +00:00
[pcf85063] Convert the weekday to and from the chip's 0-6 range (#20736)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user