Something went wrong. Try again.
A fork of https://github.com/crosspoint-reader/crosspoint-reader
Something went wrong. Try again.
4.3 kB · 169 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170#include "HalTiltSensor.h"
#include <Logging.h>
HalTiltSensor halTiltSensor; // Singleton instance
bool HalTiltSensor::readGyro(float& gx, float& gy, float& gz) const { Imu::Sample sample; if (!_sdkImu.read(sample)) return false; gx = sample.gx; gy = sample.gy; gz = sample.gz; return true;}
void HalTiltSensor::begin() { _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", "SDK IMU initialized"); return; } LOG_ERR("GYR", "SDK IMU not found");}
bool HalTiltSensor::wake() { if (!_available) { return false; }
if (!_sdkImu.wake()) { LOG_ERR("GYR", "IMU wake failed"); return false; }
_lastPollMs = millis(); _lastTiltMs = millis(); _wakeMs = millis(); _isAwake = true; return true;}
bool HalTiltSensor::deepSleep() { if (!_available) { return false; }
if (!_sdkImu.sleep()) { LOG_ERR("GYR", "IMU sleep failed"); return false; }
clearPendingEvents(); _inTilt = false; _isAwake = false; return true;}
void HalTiltSensor::update(const uint8_t mode, const uint8_t orientation, const bool inReader) { if (!_available) { return; }
// State machine: wake up or sleep based on the enabled flag if ((mode != CrossPointTiltPageTurn::TILT_OFF) && !_isAwake) { _isAwake = wake(); return; } else if ((mode == CrossPointTiltPageTurn::TILT_OFF) && _isAwake) { _isAwake = !deepSleep(); return; }
// If disabled, skip the rest of the polling logic and avoid unnecessary I2C traffic in non-reader activities if ((mode == CrossPointTiltPageTurn::TILT_OFF) || !inReader) { return; }
const unsigned long now = millis(); // Stabilization: discard readings during gyro startup transient if ((now - _wakeMs) < WAKE_STABILIZE_MS) { return; }
if ((now - _lastPollMs) < POLL_INTERVAL_MS) { return; } _lastPollMs = now;
float gx, gy, gz; if (!readGyro(gx, gy, gz)) { return; }
// Map the gyro axis to left/right tilt based on reader orientation. // On the X3 PCB: X axis = left/right in portrait, Y axis = left/right in landscape. float tiltAxis; switch (orientation) { case CrossPointOrientation::PORTRAIT: tiltAxis = mode == CrossPointTiltPageTurn::TILT_INVERTED ? -gx : gx; break; case CrossPointOrientation::INVERTED: tiltAxis = mode == CrossPointTiltPageTurn::TILT_INVERTED ? gx : -gx; break; case CrossPointOrientation::LANDSCAPE_CW: tiltAxis = mode == CrossPointTiltPageTurn::TILT_INVERTED ? gy : -gy; break; case CrossPointOrientation::LANDSCAPE_CCW: tiltAxis = mode == CrossPointTiltPageTurn::TILT_INVERTED ? -gy : gy; break; default: tiltAxis = gx; break; }
if (_inTilt) { // Wait for device to return to neutral before allowing next trigger if (fabsf(tiltAxis) < NEUTRAL_RATE_DPS) { _inTilt = false; } } else { // Check for new tilt gesture (with cooldown) if ((now - _lastTiltMs) >= COOLDOWN_MS) { if (tiltAxis > RATE_THRESHOLD_DPS) { _tiltForwardEvent = true; _hadActivity = true; _inTilt = true; _lastTiltMs = now; LOG_INF("GYR", "Forward Trigger=(%.1f) dps", tiltAxis); } else if (tiltAxis < -RATE_THRESHOLD_DPS) { _tiltBackEvent = true; _hadActivity = true; _inTilt = true; _lastTiltMs = now; LOG_INF("GYR", "Backward Trigger=(%.1f) dps", tiltAxis); } } }}
bool HalTiltSensor::wasTiltedForward() { const bool val = _tiltForwardEvent; _tiltForwardEvent = false; return val;}
bool HalTiltSensor::wasTiltedBack() { const bool val = _tiltBackEvent; _tiltBackEvent = false; return val;}
bool HalTiltSensor::hadActivity() { const bool val = _hadActivity; _hadActivity = false; return val;}
void HalTiltSensor::clearPendingEvents() { _tiltForwardEvent = false; _tiltBackEvent = false; _hadActivity = false; // Intentionally preserve _inTilt so a held tilt doesn't retrigger on next poll}