Skip to content

Commit 0669a38

Browse files
committed
dashd: show active VCU event mode in driver pill cluster
Adds a MODE pill below the TC/REGEN cluster on ScreenOne that shows which params table the VCU is running (ACCEL/SKID/AUTOX/ ENDUR). Sourced from Controls.event_mode (proto field declared float to match the prndl/soc convention; cast to u8 in dashd since the wire value is uint8 0..4). Pill matches the TC style — burnt-orange border/bg when an event is active, muted when the VCU is unassigned (0/null) so a stale or unprovisioned car reads as "—". useDemoData cycles through 1..4 so the layout is visible without a live VCU.
1 parent 9b49fd9 commit 0669a38

4 files changed

Lines changed: 68 additions & 0 deletions

File tree

BEVO/dashd/frontend/src/hooks/useDemoData.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ export function useDemoData(enabled: boolean): DashMessage | null {
170170
const tcLevel = (Math.floor(Date.now() / 5000) % 3) + 1; // 1,2,3
171171
const tcEnabled = (Math.floor(Date.now() / 9000) % 3) !== 0; // ~66% on
172172
const regenEnabled = (Math.floor(Date.now() / 8000) % 4) !== 0; // ~75% on
173+
// Rotate through 1=ACCEL, 2=SKID, 3=AUTOX, 4=ENDUR so each pill
174+
// label is visible during demo.
175+
const eventMode = (Math.floor(Date.now() / 6000) % 4) + 1;
173176

174177
// Pit-diagnostic fakes — derived from the existing sim where
175178
// possible so values move with the rest of the dash.
@@ -232,6 +235,7 @@ export function useDemoData(enabled: boolean): DashMessage | null {
232235
tcLevel,
233236
tcEnabled,
234237
regenEnabled,
238+
eventMode,
235239
apps,
236240
bpps,
237241
brakePressureFront,

BEVO/dashd/frontend/src/screens/ScreenOne.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import ConnectivityIndicator from '../components/ConnectivityIndicator';
33
import { useDash } from '../context/DashContext';
44
import { useEnergyPacing } from '../hooks/useEnergyPacing';
5+
import { eventModeLabel } from '../types/DashData';
56
import './ScreenOne.css';
67

78
// Screen One: Main Dashboard (Modern EV Style)
@@ -54,6 +55,11 @@ const ScreenOne: React.FC = () => {
5455
const tcLevel = data?.can.tcLevel ?? null;
5556
const tcEnabled = data?.can.tcEnabled ?? null;
5657
const regenEnabled = data?.can.regenEnabled ?? null;
58+
// Active VCU event mode (Controls.event_mode). 0/null shows "—"; 1-4 map
59+
// to ACCEL/SKID/AUTOX/ENDUR via EVENT_MODE_LABELS in DashData.ts.
60+
const eventMode = data?.can.eventMode ?? null;
61+
const eventModeText = eventModeLabel(eventMode);
62+
const eventModeActive = eventMode !== null && eventMode !== undefined && eventMode !== 0;
5763
// BACKEND TODO: dashd needs MqttData.lapDeltaRate — d(lapDelta)/dt,
5864
// units of seconds per second. Drivers want this as the primary
5965
// glance bar because absolute delta lags. Compute off-car to keep
@@ -582,6 +588,33 @@ const ScreenOne: React.FC = () => {
582588
: regenEnabled ? 'ON' : 'OFF'}
583589
</span>
584590
</div>
591+
592+
{/* MODE pill — which VCU params table is active. Burnt
593+
orange matches TC: same "armed/active" pattern. Shows
594+
the firmware-picked event (ACCEL/SKID/AUTOX/ENDUR);
595+
the driver can't change it here, it's set by which
596+
params header was compiled into the VCU. */}
597+
<div style={{
598+
height: '26px',
599+
padding: '0 14px',
600+
borderRadius: '5px',
601+
border: `2px solid ${eventModeActive ? '#BF5700' : 'var(--card-border-hover)'}`,
602+
background: eventModeActive ? 'rgba(191,87,0,0.20)' : 'var(--card-bg)',
603+
display: 'flex',
604+
justifyContent: 'space-between',
605+
alignItems: 'center',
606+
gap: '8px'
607+
}}>
608+
<span className="label-small" style={{ marginBottom: 0, fontSize: '0.9rem', letterSpacing: '2px' }}>MODE</span>
609+
<span className="value-display" style={{
610+
fontSize: '1.3rem',
611+
fontWeight: 'bold',
612+
lineHeight: 1,
613+
color: eventModeActive ? 'var(--fg-primary)' : 'var(--fg-muted)'
614+
}}>
615+
{eventModeText ?? '—'}
616+
</span>
617+
</div>
585618
</div>
586619

587620
{/* Right cluster: GEAR + HV, mirroring TC/REGEN on the

BEVO/dashd/frontend/src/types/DashData.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ export interface CanData {
4040
tcEnabled?: boolean | null; // TC armed?
4141
regenEnabled?: boolean | null; // Regenerative braking enabled?
4242

43+
// Active VCU event mode — which params table the firmware is running.
44+
// Source: Controls.event_mode (byte 6 of 0x1C7 VCU State). See
45+
// EVENT_MODE_LABELS for the enum->label mapping.
46+
eventMode?: number | null;
47+
4348
// Pit-diagnostic fields. Not yet emitted by dashd (per-field BACKEND
4449
// TODOs in PitDiagnostic.tsx); demo hook synthesizes values so the
4550
// layout is testable.
@@ -106,6 +111,22 @@ export interface DashMessage {
106111
pacing: PacingData;
107112
}
108113

114+
// VCU event mode enum (matches firmware VCU_DEFAULT_PARAMS + per-event override
115+
// in VCU/firmware/Core/Inc/params/*.h). Anything outside this range is shown
116+
// as the raw integer so a new mode added on the VCU isn't silently dropped.
117+
export const EVENT_MODE_LABELS: Record<number, string> = {
118+
0: "—",
119+
1: "ACCEL",
120+
2: "SKID",
121+
3: "AUTOX",
122+
4: "ENDUR",
123+
};
124+
125+
export function eventModeLabel(mode: number | null | undefined): string | null {
126+
if (mode === null || mode === undefined) return null;
127+
return EVENT_MODE_LABELS[mode] ?? String(mode);
128+
}
129+
109130
// Shutdown circuit / safety-fault items, in the order dashd emits them.
110131
// LEG 1–4 are the hardware shutdown legs from DiagnosticsLow.shutdown_legX;
111132
// BMS / IMD are *_error flags inverted into shutdown convention. Electrical

BEVO/dashd/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ struct CanData {
177177
/// `regenEnabled` pill.
178178
#[serde(rename = "regenEnabled")]
179179
regen_enabled: Option<bool>,
180+
181+
/// Active VCU event mode (which params table the VCU is running).
182+
/// 0 = unassigned, 1 = acceleration, 2 = skidpad, 3 = autocross, 4 = endurance.
183+
/// Lives on Controls.event_mode (byte 6 of 0x1C7 VCU State).
184+
#[serde(rename = "eventMode")]
185+
event_mode: Option<u8>,
180186
}
181187

182188
#[derive(Serialize, Clone, Default)]
@@ -592,6 +598,10 @@ fn extract_can_data(data: &OrionSensorData, last_qualified_soc: &mut Option<f32>
592598
// confirmed it carries the regen-enabled bit. Plumb to the
593599
// frontend's regenEnabled pill. Lives on the Controls message.
594600
regen_enabled: controls.map(|c| c.line_lock_enabled),
601+
602+
// Wire value is uint8 but the proto declares the field as float
603+
// (matches prndl/soc convention); cast back for the frontend enum.
604+
event_mode: controls.map(|c| c.event_mode as u8),
595605
}
596606
}
597607

0 commit comments

Comments
 (0)