feat: Add touch coordinate mapping and RTOS task yielding (#2481)

Co-authored-by: Julia Nguyen <julia@uxj.io>
This commit is contained in:
Justin Mitchell
2026-07-20 16:31:07 -04:00
committed by GitHub
co-authored by Julia Nguyen
parent c9188a7347
commit f42fab1c66
123 changed files with 3564 additions and 1380 deletions
+21 -91
View File
@@ -5,46 +5,11 @@
#include <esp_sntp.h>
#include <time.h>
#include <cassert>
HalClock halClock; // Singleton instance
// DS3231 register layout (BCD encoded):
// 0x00: Seconds (bits 6-4 = tens, bits 3-0 = ones)
// 0x01: Minutes (bits 6-4 = tens, bits 3-0 = ones)
// 0x02: Hours (bit 6 = 12/24 mode, bits 5-4 = tens, bits 3-0 = ones)
static uint8_t bcdToDec(uint8_t bcd) { return ((bcd >> 4) * 10) + (bcd & 0x0F); }
static uint8_t decToBcd(uint8_t dec) { return ((dec / 10) << 4) | (dec % 10); }
void HalClock::begin() {
if (!gpio.deviceIsX3()) {
_available = false;
return;
}
// I2C is already initialised by HalPowerManager::begin() for X3.
// Probe the DS3231 by reading the seconds register.
Wire.beginTransmission(I2C_ADDR_DS3231);
Wire.write(DS3231_SEC_REG);
if (Wire.endTransmission(false) != 0) {
LOG_INF("CLK", "DS3231 RTC not found");
_available = false;
return;
}
Wire.requestFrom(I2C_ADDR_DS3231, (uint8_t)1);
if (Wire.available() < 1) {
_available = false;
return;
}
Wire.read(); // discard — just testing connectivity
_available = true;
LOG_INF("CLK", "DS3231 RTC found");
// Prime the cache with an initial read
uint8_t h, m;
getTime(h, m);
_available = _sdkRtc.begin();
LOG_INF("CLK", _available ? "SDK RTC found" : "RTC not found");
}
bool HalClock::getTime(uint8_t& hour, uint8_t& minute) const {
@@ -57,44 +22,18 @@ bool HalClock::getTime(uint8_t& hour, uint8_t& minute) const {
return true;
}
// Read 3 bytes starting at register 0x00: seconds, minutes, hours
Wire.beginTransmission(I2C_ADDR_DS3231);
Wire.write(DS3231_SEC_REG);
if (Wire.endTransmission(false) != 0) {
Rtc::DateTime dt;
if (!_sdkRtc.now(dt)) {
if (!_hasCachedTime) return false;
_lastPollMs = now;
hour = _cachedHour;
minute = _cachedMinute;
return true;
}
Wire.requestFrom(I2C_ADDR_DS3231, (uint8_t)3);
if (Wire.available() < 3) {
if (!_hasCachedTime) return false;
_lastPollMs = now;
hour = _cachedHour;
minute = _cachedMinute;
return true;
}
Wire.read(); // seconds — not needed
const uint8_t rawMin = Wire.read();
const uint8_t rawHour = Wire.read();
_cachedMinute = bcdToDec(rawMin & 0x7F);
// Handle 12/24h mode: bit 6 high = 12h mode
if (rawHour & 0x40) {
// 12h mode: bit 5 = PM, bits 4-0 = hours (1-12)
uint8_t h12 = bcdToDec(rawHour & 0x1F);
bool pm = rawHour & 0x20;
if (h12 == 12) h12 = 0;
_cachedHour = pm ? (h12 + 12) : h12;
} else {
// 24h mode: bits 5-0 = hours (0-23)
_cachedHour = bcdToDec(rawHour & 0x3F);
}
_cachedHour = dt.hour;
_cachedMinute = dt.minute;
_lastPollMs = now;
_hasCachedTime = true;
hour = _cachedHour;
minute = _cachedMinute;
return true;
@@ -127,28 +66,6 @@ bool HalClock::formatTime(char* buf, size_t bufSize, uint8_t utcOffsetQuarterHou
return true;
}
bool HalClock::writeTimeToRTC(uint8_t hour, uint8_t minute, uint8_t second) {
assert(hour < 24);
assert(minute < 60);
assert(second < 60);
Wire.beginTransmission(I2C_ADDR_DS3231);
Wire.write(DS3231_SEC_REG); // Start at register 0x00
Wire.write(decToBcd(second)); // 0x00: Seconds
Wire.write(decToBcd(minute)); // 0x01: Minutes
Wire.write(decToBcd(hour)); // 0x02: Hours (24h mode, bit 6 = 0)
if (Wire.endTransmission() != 0) {
LOG_ERR("CLK", "Failed to write time to DS3231");
return false;
}
// Invalidate cache so next read fetches fresh data
_lastPollMs = 0;
_cachedHour = hour;
_cachedMinute = minute;
_hasCachedTime = true;
return true;
}
bool HalClock::syncFromNTP() {
if (!_available) return false;
@@ -168,8 +85,21 @@ bool HalClock::syncFromNTP() {
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
if (writeTimeToRTC(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec)) {
LOG_INF("CLK", "RTC set to %02d:%02d:%02d UTC", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
Rtc::DateTime dt;
dt.year = static_cast<uint16_t>(timeinfo.tm_year + 1900);
dt.month = static_cast<uint8_t>(timeinfo.tm_mon + 1);
dt.day = static_cast<uint8_t>(timeinfo.tm_mday);
dt.hour = static_cast<uint8_t>(timeinfo.tm_hour);
dt.minute = static_cast<uint8_t>(timeinfo.tm_min);
dt.second = static_cast<uint8_t>(timeinfo.tm_sec);
dt.weekday = static_cast<uint8_t>(timeinfo.tm_wday);
if (_sdkRtc.set(dt)) {
_lastPollMs = 0;
_cachedHour = dt.hour;
_cachedMinute = dt.minute;
_hasCachedTime = true;
LOG_INF("CLK", "RTC set to %04u-%02u-%02u %02u:%02u:%02u UTC", dt.year, dt.month, dt.day, dt.hour, dt.minute,
dt.second);
return true;
}
return false;