Files
clawdmeter/firmware/src/boards/waveshare_amoled_216/imu.cpp
T
wenilandClaude Opus 4.8 578bc04248 v2 firmware: HA command channel, battery screen, dynamic Home buttons, tilt-dimmer
Watch-side features developed on the AMOLED-2.06 and shared across all boards:

- BLE command channel (…0005, notify watch→PC) via ble_send_command(); the
  watch stays "dumb" and the daemon maps commands to Home Assistant.
- Battery detail screen + protective low-voltage cutoff; power HAL gains
  battery_mv() / shutdown(), with battery_est.{h,cpp} for the time-left anchor.
- Home screen: dynamic 2-column button grid driven by the desktop config
  (RX "btns" labels); tap notifies {"cmd":"btn","i":N}.
- Dimmer screen: IMU tilt-joystick over the light's brightness / color temp.
  imu_hal_read_accel() added to the HAL (real on 2.06/2.16, no-op elsewhere);
  streams absolute {"cmd":"bri"|"ct","v":..}; daemon seeds the dial via "dim".
  Per-board tilt axis is calibrated with the DIM_CALIB overlay (off by default).

Multi-board fix: enable LV_FONT_MONTSERRAT_20/28 on the 2.16, 1.8 and C6 envs.
Shared ui.cpp uses these glyphs for the launcher tiles and back chevron, so
those three boards had failed to compile since the Phase-2 UI landed. All four
envs now build clean. README: correct the Windows pairing name to "Clawdmeter".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 20:20:04 +03:00

72 lines
2.1 KiB
C++

#include "../../hal/imu_hal.h"
#include "board.h"
#include <Arduino.h>
#include <Wire.h>
#include <SensorQMI8658.hpp>
// Poll and hysteresis timing
#define IMU_POLL_MS 100 // ~10 Hz
#define STABLE_TIME_MS 300 // orientation must hold this long before rotating
#define TILT_THRESHOLD 0.5f // ~30° from axis (sin 30° ≈ 0.5)
static SensorQMI8658 imu;
static uint8_t current_rotation = 0;
static uint8_t candidate_rotation = 0;
static uint32_t candidate_since = 0;
static uint32_t last_poll_ms = 0;
static bool imu_ok = false;
static uint8_t accel_to_rotation(float ax, float ay) {
float abs_ax = fabsf(ax);
float abs_ay = fabsf(ay);
if (abs_ax < TILT_THRESHOLD && abs_ay < TILT_THRESHOLD) {
return 255; // ambiguous (face-up/down)
}
if (abs_ay > abs_ax) return (ay > 0) ? 3 : 1;
return (ax > 0) ? 0 : 2;
}
void imu_hal_init(void) {
if (!imu.begin(Wire, QMI8658_L_SLAVE_ADDRESS, IIC_SDA, IIC_SCL)) {
Serial.println("QMI8658 init failed");
return;
}
Serial.println("QMI8658 init OK");
imu.configAccelerometer(
SensorQMI8658::ACC_RANGE_4G,
SensorQMI8658::ACC_ODR_LOWPOWER_21Hz,
SensorQMI8658::LPF_MODE_3);
imu.enableAccelerometer();
imu_ok = true;
}
void imu_hal_tick(void) {
if (!imu_ok) return;
uint32_t now = millis();
if (now - last_poll_ms < IMU_POLL_MS) return;
last_poll_ms = now;
float ax, ay, az;
if (!imu.getAccelerometer(ax, ay, az)) return;
uint8_t target = accel_to_rotation(ax, ay);
if (target == 255 || target == current_rotation) {
candidate_rotation = current_rotation;
return;
}
if (target != candidate_rotation) {
candidate_rotation = target;
candidate_since = now;
} else if (now - candidate_since >= STABLE_TIME_MS) {
current_rotation = target;
Serial.printf("Rotation: %d\n", current_rotation);
}
}
uint8_t imu_hal_rotation_quadrant(void) { return current_rotation; }
bool imu_hal_read_accel(float* x, float* y, float* z) {
if (!imu_ok || !imu.getDataReady()) return false;
return imu.getAccelerometer(*x, *y, *z);
}