diff --git a/src/ui.rs b/src/ui.rs
index c2a2019..aab61be 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -20,11 +20,13 @@ const VCORE_MARGIN: f64 = 0.05;
/// Safety limit, volts. User-tunable config value. Intel max Vcore
/// spec default for the 12600KF.
const VCORE_LIMIT: f64 = 1.403;
-const VCORE_BAR_MAX: f64 = 1.50;
+const VCORE_BAR_MAX: f64 = 1.50; // default; auto-scaled above by peak
const TEMP_WARN: f64 = 80.0;
const TEMP_CRIT: f64 = 95.0;
-/// Package power bar scale, watts (dGPU PPT ceiling as a sane display max).
+/// Package power bar scale, watts (default; auto-scaled above by peak).
const POWER_BAR_MAX: f64 = 200.0;
+/// Auto-scale headroom above the session peak, as a fraction.
+const SCALE_MARGIN: f64 = 0.05;
/// Temp bar scale, °C.
const TEMP_BAR_MAX: f64 = 100.0;
@@ -33,7 +35,11 @@ pub struct App {
vcore_peak: Option<f64>,
/// (timestamp, volts) per-tick maxima inside the 5-min peak window
peak_ring: Vec<(Instant, f64)>,
+ /// Highest vCore ever seen this session (auto-scale anchor)
+ vcore_all_time_peak: f64,
package_watts: Option<f64>,
+ /// Highest pkg watts ever seen this session (auto-scale anchor)
+ watts_all_time_peak: f64,
package_temp: Option<f64>,
/// Per physical core: label (coretemp "Core N"), freq kHz, bar-max kHz
/// (that core's cpuinfo_max_freq), temperature °C.
@@ -41,6 +47,12 @@ pub struct App {
last_pkg_energy: Option<(u64, Instant)>,
}
+/// Bar max = static default, or last peak + margin once the peak exceeds it.
+/// The margin keeps the value text off the bar's right edge at the peak.
+fn dynamic_max(peak: f64, static_max: f64, margin: f64) -> f64 {
+ (peak * (1.0 + margin)).max(static_max)
+}
+
/// One physical core's row in the per-core section.
struct CoreRow {
label: String,
@@ -57,7 +69,9 @@ impl App {
vcore: None,
vcore_peak: None,
peak_ring: Vec::new(),
+ vcore_all_time_peak: 0.0,
package_watts: None,
+ watts_all_time_peak: 0.0,
package_temp: None,
cores: Vec::new(),
last_pkg_energy: None,
@@ -77,6 +91,7 @@ impl App {
.map(|(_, v)| *v)
.fold(f64::MIN, f64::max),
);
+ self.vcore_all_time_peak = self.vcore_all_time_peak.max(v);
}
if let Some(chip) = sensors::discover_chips()
@@ -146,8 +161,12 @@ impl App {
Some((prev, t0)) => {
let dt = t0.elapsed().as_secs_f64();
if dt > 0.0 && e >= prev {
- self.package_watts =
- Some((e - prev) as f64 / 1_000_000.0 / dt);
+ let w = (e - prev) as f64 / 1_000_000.0 / dt;
+ self.package_watts = Some(w);
+ if w.is_finite() {
+ self.watts_all_time_peak =
+ self.watts_all_time_peak.max(w);
+ }
}
Some((e, Instant::now()))
}
@@ -285,13 +304,18 @@ pub fn draw(f: &mut Frame, app: &App) {
"vCore",
Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD),
)));
+ // Bar maxima auto-scale: session all-time peak + margin, floored at the
+ // static defaults. OC'ing past a default compresses the bar to fit.
+ let vc_max = dynamic_max(app.vcore_all_time_peak, VCORE_BAR_MAX, SCALE_MARGIN);
+ let watt_max = dynamic_max(app.watts_all_time_peak, POWER_BAR_MAX, SCALE_MARGIN);
+
lines.push(meter_line(
"",
&hero_text,
- app.vcore.map(|v| v / VCORE_BAR_MAX),
+ app.vcore.map(|v| v / vc_max),
vc_color,
w,
- Some(VCORE_LIMIT / VCORE_BAR_MAX),
+ Some(VCORE_LIMIT / vc_max),
));
lines.push(Line::from(""));
@@ -299,7 +323,7 @@ pub fn draw(f: &mut Frame, app: &App) {
lines.push(meter_line(
"Pkg power",
&fmt_opt_watts(app.package_watts),
- app.package_watts.map(|v| v / POWER_BAR_MAX),
+ app.package_watts.map(|v| v / watt_max),
Color::Blue,
w,
None,
TUI: auto-scaling bars for vCore & pkg power (session peak + margin, static floor)
0f53d389d8cf5c1c9b72104f543d1401fcc489d0
josie <administrator@josie-c.com> · 2026-08-29T12:36 ·
browse files at this commit
parents:
c5ccef7