Files
clawdmeter/firmware/src/usage_rate.cpp
T
Hermann Björgvin Haraldsson f1feacb3dc Remove dead functions and unused Montserrat font flags
Six public API functions had no callers anywhere in the firmware:
splash_prev, splash_set_active, splash_current_name, splash_count,
ble_is_connected, imu_set_rotation, power_is_usb_connected,
power_usb_changed. Trimming them lets power.cpp drop the VBUS state
machine (cached_usb, usb_changed_flag, last_vbus_ms,
enableVbusVoltageMeasure). usage_rate_reset becomes file-static since
the only caller is in usage_rate.cpp itself. Montserrat font flags in
platformio.ini were enabled but never referenced.
2026-05-11 02:19:45 +00:00

74 lines
2.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "usage_rate.h"
#include <Arduino.h>
// Thresholds in %/min. A 5-hour (300 min) session ÷ 100% = 0.33 %/min to fill
// exactly at the same pace as the session itself resets — the user wants the
// "heavy" tier to start right there (filling in 45 hours).
// < 0.10 → Idle (17h+ to fill, basically dormant)
// < 0.20 → Normal (817h to fill, slow steady use)
// < 0.33 → Active (58h, heavy but not yet pace-matching)
// >=0.33 → Heavy (≤5h, matching or beating the session reset)
#define RATE_THRESH_NORMAL 0.10f
#define RATE_THRESH_ACTIVE 0.20f
#define RATE_THRESH_HEAVY 0.33f
// Minimum span between oldest and newest sample before we trust the computed
// rate. The whole point of the ring buffer is to smooth out single-sample
// jitter — at 60s daemon polling, a 1% bump between two consecutive samples
// looks like 1 %/min (Heavy) but really just means you grew 1% in the last
// minute. We require ~4 min of accumulated history so the rate reflects a
// real trend, not one noisy delta. Side-effect: ~4 min warm-up after boot
// during which we report Idle.
#define MIN_WINDOW_MS 240000UL
#define RING_SIZE 6
struct Sample { uint32_t ms; float pct; };
static Sample ring[RING_SIZE];
static uint8_t count = 0;
static uint8_t head = 0; // index of next write slot
static inline uint8_t oldest_idx(void) {
return (head + RING_SIZE - count) % RING_SIZE;
}
static void usage_rate_reset(void) {
count = 0;
head = 0;
}
void usage_rate_sample(float session_pct) {
uint32_t now = millis();
if (count > 0) {
uint8_t latest = (head + RING_SIZE - 1) % RING_SIZE;
// Session reset: pct dropped substantially. Restart tracking.
if (session_pct + 5.0f < ring[latest].pct) {
usage_rate_reset();
}
}
ring[head] = { now, session_pct };
head = (head + 1) % RING_SIZE;
if (count < RING_SIZE) count++;
}
int usage_rate_group(void) {
if (count < 2) return 0;
uint8_t o = oldest_idx();
uint8_t l = (head + RING_SIZE - 1) % RING_SIZE;
uint32_t dt = ring[l].ms - ring[o].ms;
if (dt < MIN_WINDOW_MS) return 0;
float dp = ring[l].pct - ring[o].pct;
if (dp < 0.0f) dp = 0.0f;
float rate = dp * 60000.0f / (float)dt;
if (rate < RATE_THRESH_NORMAL) return 0;
if (rate < RATE_THRESH_ACTIVE) return 1;
if (rate < RATE_THRESH_HEAVY) return 2;
return 3;
}