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
+28 -93
View File
@@ -4,84 +4,29 @@
HalTiltSensor halTiltSensor; // Singleton instance
bool HalTiltSensor::writeReg(uint8_t reg, uint8_t val) const {
Wire.beginTransmission(_i2cAddr);
Wire.write(reg);
Wire.write(val);
return Wire.endTransmission() == 0;
}
bool HalTiltSensor::readReg(uint8_t reg, uint8_t* val) const {
Wire.beginTransmission(_i2cAddr);
Wire.write(reg);
if (Wire.endTransmission(false) != 0) {
return false;
}
Wire.requestFrom(_i2cAddr, (uint8_t)1);
if (Wire.available() < 1) {
return false;
}
*val = Wire.read();
return true;
}
bool HalTiltSensor::readGyro(float& gx, float& gy, float& gz) const {
Wire.beginTransmission(_i2cAddr);
Wire.write(REG_GX_L); // Start reading at Gyro X Low
if (Wire.endTransmission(false) != 0) {
return false;
}
Wire.requestFrom(_i2cAddr, (uint8_t)6);
if (Wire.available() < 6) {
return false;
}
auto readInt16 = [&]() -> int16_t {
const uint8_t lo = Wire.read();
const uint8_t hi = Wire.read();
return static_cast<int16_t>((hi << 8) | lo);
};
// If Full Scale is ±512 dps, the scale factor is 32768 / 512 = 64 LSB/dps
constexpr float SCALE = 1.0f / 64.0f;
gx = readInt16() * SCALE;
gy = readInt16() * SCALE;
gz = readInt16() * SCALE;
Imu::Sample sample;
if (!_sdkImu.read(sample)) return false;
gx = sample.gx;
gy = sample.gy;
gz = sample.gz;
return true;
}
void HalTiltSensor::begin() {
if (!gpio.deviceIsX3()) {
_available = false;
return;
}
// Try primary address, then alternate
uint8_t whoami = 0;
_i2cAddr = I2C_ADDR_QMI8658;
if (!readReg(QMI8658_WHO_AM_I_REG, &whoami) || whoami != QMI8658_WHO_AM_I_VALUE) {
_i2cAddr = I2C_ADDR_QMI8658_ALT;
if (!readReg(QMI8658_WHO_AM_I_REG, &whoami) || whoami != QMI8658_WHO_AM_I_VALUE) {
LOG_ERR("GYR", "QMI8658 IMU not found");
_available = false;
return;
_available = _sdkImu.begin();
if (_available) {
_initMs = millis();
_lastPollMs = millis();
// begin() leaves the sensors sampling; stand them by until tilt page turn
// actually wakes them, so a disabled IMU doesn't drain the battery.
if (!_sdkImu.sleep()) {
LOG_ERR("GYR", "IMU standby failed");
}
}
LOG_INF("GYR", "QMI8658 IMU found at 0x%02X", _i2cAddr);
if (!writeReg(REG_CTRL7, CTRL7_DISABLE_ALL) || !writeReg(REG_CTRL3, CTRL3_FS_512DPS | CTRL3_ODR_28HZ) ||
!writeReg(REG_CTRL1, CTRL1_BASE | CTRL1_SENSOR_DISABLE)) {
LOG_ERR("GYR", "QMI8658 register configuration failed");
_available = false;
LOG_INF("GYR", "SDK IMU initialized");
return;
}
_available = true;
_initMs = millis();
_lastPollMs = millis();
LOG_INF("GYR", "QMI8658 gyro initialized and put to sleep");
LOG_ERR("GYR", "SDK IMU not found");
}
bool HalTiltSensor::wake() {
@@ -89,21 +34,16 @@ bool HalTiltSensor::wake() {
return false;
}
// Wait for init to complete before waking
if ((millis() - _initMs) < SLEEP_STABILIZE_MS) {
if (!_sdkImu.wake()) {
LOG_ERR("GYR", "IMU wake failed");
return false;
}
if (writeReg(REG_CTRL1, CTRL1_BASE) && writeReg(REG_CTRL7, CTRL7_GYRO_ENABLE)) {
_lastPollMs = millis();
_lastTiltMs = millis();
_wakeMs = millis();
LOG_INF("GYR", "QMI8658 woke up");
return true;
} else {
LOG_ERR("GYR", "Failed to wake QMI8658");
return false;
}
_lastPollMs = millis();
_lastTiltMs = millis();
_wakeMs = millis();
_isAwake = true;
return true;
}
bool HalTiltSensor::deepSleep() {
@@ -111,20 +51,15 @@ bool HalTiltSensor::deepSleep() {
return false;
}
if ((millis() - _wakeMs) < SLEEP_STABILIZE_MS) {
if (!_sdkImu.sleep()) {
LOG_ERR("GYR", "IMU sleep failed");
return false;
}
if (writeReg(REG_CTRL7, CTRL7_DISABLE_ALL) && writeReg(REG_CTRL1, CTRL1_BASE | CTRL1_SENSOR_DISABLE)) {
// Clear any residual state so it doesn't immediately trigger upon waking
clearPendingEvents();
_inTilt = false;
LOG_INF("GYR", "QMI8658 entered sleep mode");
return true;
} else {
LOG_ERR("GYR", "Failed to put QMI8658 to sleep");
return false;
}
clearPendingEvents();
_inTilt = false;
_isAwake = false;
return true;
}
void HalTiltSensor::update(const uint8_t mode, const uint8_t orientation, const bool inReader) {