Reviewd and fixed deadman architecture

This commit is contained in:
2026-09-10 23:53:27 +02:00
parent 31b3595ac0
commit f8d111ef5c
15 changed files with 304 additions and 305 deletions
+27 -30
View File
@@ -19,7 +19,7 @@ temperature and pressure sensors, and an external starter switch.
| --- | ---: | --- |
| Crank trigger input | 1 | 12 V active-low Hall, timer capture |
| Cam trigger input | 1 | 12 V active-low Hall, timer capture |
| Deadman inputs | 2 | Dedicated, independent 5 V vehicle-logic engine-permit inputs |
| Deadman input | 1 | Shared 5 V signal from parallel steering-wheel switches; dedicated hardware engine-permit path |
| Thermistor inputs | 4 | Air, oil, water, and one spare temperature input |
| General analogue inputs | 9 | Protected 0-5 V sensor channels |
| ADC rail-monitor channels | 3 | `VBAT_PROT`, `+5V_SENS`, and `+12V_SENS` |
@@ -150,41 +150,38 @@ actual harness and input-function requirements.
## Deadman Engine-Permit Interlock
The deadman uses two dedicated 5 V vehicle-logic inputs, not generic digital
inputs. The steering-wheel switch provides two electrically independent,
normally-open contacts. Each contact has its own connector pin, protection,
filtering, default-low bias, and conditioned logic path. This makes an open
circuit or a short to the 5 V source on one signal path non-permissive.
The steering wheel has two normally-open switches connected in parallel.
Holding either switch asserts one shared active-high 5 V `DEADMAN_IN` signal
into the ECU; both must be released to deassert it. The ECU uses one dedicated
signal pin, protection/filter network, default-low bias and conditioning path,
separate from generic digital inputs.
The resulting 5 V `DEADMAN_OK` signal is high only when channel A reports
held and the independently conditioned, inverted channel B reports not
released. It has two independent destinations:
The conditioned 5 V `DEADMAN_OK` signal feeds the hardware permission gate.
One protected 3.3 V `DEADMAN_STATUS` input lets the MCU observe the same combined
state. The MCU cannot identify which switch is held or compare their states.
- `DEADMAN_A_STATUS` and `DEADMAN_B_STATUS` enter MCU digital inputs so
firmware can observe each contact, detect disagreement, disable scheduling,
and report the state.
- `DEADMAN_OK` is combined in hardware with the MCU's `MCU_RUN_PERMIT` output
to produce `ENGINE_PERMIT`.
![Parallel switches and single deadman input](diagrams/deadman-inputs.svg)
![Deadman inputs](diagrams/deadman-inputs.svg)
![Single-input engine permission](diagrams/deadman-permit.svg)
![Deadman permit](diagrams/deadman-permit.svg)
`ENGINE_PERMIT = DEADMAN_OK AND MCU_RUN_PERMIT`. The injector command is
`SAFE_INJECTOR_SIG = ENGINE_PERMIT AND MCU_INJECTOR_SIG`; the ignition driver
receives `SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT)`. These paths remove
permission in hardware when the shared input goes low, independently of
firmware response. Driver bias networks must establish off/inhibited states
through power loss and MCU reset.
`ENGINE_PERMIT` controls the enable inputs of the injector and ignition drivers
where those inputs are provided. If a selected driver has no suitable enable
input, `ENGINE_PERMIT` is ANDed with that driver's MCU command signal using
logic that defaults to the disabled state on power-up or loss of power.
Both switches released, an open shared signal or loss of switch supply removes
permission through the default-low input. An open individual switch branch
leaves the other switch usable. A stuck-closed switch or a shared signal shorted
to the asserted source can keep permission asserted; this single-input
arrangement cannot detect those faults or per-switch disagreement.
This hardware path ensures that releasing the deadman, an open circuit, or a
single signal-path short to the 5 V source stops injector and ignition commands
even if firmware or a timer output fails to respond. It does not claim to cover
a common-mode fault that energises both paths. Firmware must clear/disable
pending injection and dwell schedules whenever `DEADMAN_OK` becomes invalid or
the two MCU status inputs disagree. A firmware test mode may assert
`MCU_RUN_PERMIT`, but it does not override the physical deadman inputs; bench
operation requires a deliberate external test arrangement that presents the
valid two-channel held state. The detailed signal and fault model is defined in
[DEAD_MAN.md](IO_MODULES/DEAD_MAN.md).
Firmware clears pending injection and dwell schedules when `DEADMAN_STATUS`
deasserts. A test mode may assert `MCU_RUN_PERMIT`, but cannot bypass a low
physical deadman input; bench operation requires a deliberate external test
arrangement asserting the single shared signal. The detailed interface and
fault behavior are defined in [DEAD_MAN.md](IO_MODULES/DEAD_MAN.md).
## Outputs
+88 -74
View File
@@ -3,106 +3,120 @@
## Purpose
This module provides the hardware run-permission path for the engine outputs.
The steering-wheel dead-man switch must be held to assert permission. Two
electrically independent, normally-open switch contacts and two independent
harness signal paths are required. Releasing the switch, an open circuit,
one signal path shorted to the 5 V source, loss of a logic supply, or MCU reset
must place the engine outputs in their non-energising state independently of
firmware.
The steering wheel has two normally-open deadman switches wired in parallel.
Holding either switch closes the circuit; holding both also closes it. Their
outputs are tied together at the steering wheel and form **one shared deadman
signal entering the ECU**, not two independently monitored inputs.
This document defines the signal relationships and destinations only. Output
driver implementation is documented separately.
The existing active-high 5 V interface is retained: either switch connects the
protected 5 V source to `DEADMAN_IN`. Both switches must be released to remove
permission. The ECU conditions this one signal for hardware gating and MCU
observation. Output-driver implementation is documented separately.
## Logic domains
| Signal | Domain | Active state | Default/fault state |
| --- | --- | --- | --- |
| `DEADMAN_A_HELD` | Protected 5 V logic | High: deadman channel A observes its contact held | Low: released or fault |
| `DEADMAN_B_RELEASED` | Protected 5 V logic | High: deadman channel B does not observe its contact held | Low: contact held |
| `DEADMAN_OK` | Protected 5 V logic | High: channels have the valid held-state relationship | Low: released or fault |
| `MCU_RUN_PERMIT` | 3.3 V MCU logic | High: MCU permits engine operation | Low: no permission |
| `ENGINE_PERMIT` | 5 V logic | High: both hardware and MCU permit operation | Low: no permission |
| `MCU_INJECTOR_SIG` | 3.3 V MCU logic | High: requested injector on-time | Low: injector off |
| `SAFE_INJECTOR_SIG` | 5 V logic | High: permitted injector command | Low: injector off |
| `SAFE_IGNITION_INHIBIT` | 5 V logic | High: ignition output is inhibited | Low: ignition output is permitted |
| `DEADMAN_A_STATUS` | 3.3 V MCU input | High: channel A contact is observed held | Low: released or fault |
| `DEADMAN_B_STATUS` | 3.3 V MCU input | High: channel B contact is observed held | Low: released or fault |
| Signal | Domain | Meaning |
| --- | --- | --- |
| `DEADMAN_IN` | Harness-connected 5 V input | High when either parallel switch is held; ECU-side bias holds it low when both are released or the shared signal is open. |
| `DEADMAN_OK` | Conditioned 5 V logic | Active-high hardware observation of the single deadman input. It is not proof that a switch or harness fault is absent. |
| `DEADMAN_STATUS` | Protected 3.3 V MCU input | MCU observation of the same combined deadman state; high means asserted. |
| `MCU_RUN_PERMIT` | 3.3 V MCU logic | High permits engine operation; defaults low. |
| `ENGINE_PERMIT` | 5 V logic | High only when deadman and MCU permission are both asserted. |
| `MCU_INJECTOR_SIG` | 3.3 V MCU logic | Requested injector on-time; defaults low. |
| `SAFE_INJECTOR_SIG` | 5 V logic | Permitted injector command; low means off. |
| `SAFE_IGNITION_INHIBIT` | 5 V logic | High inhibits ignition; low permits it. The driver must default to inhibited when permission logic is unpowered. |
Each deadman contact has its own harness signal, connector pin, connector-side
protection, series/filter network, and default-low bias. The contacts may share
the protected 5 V source at the switch, but neither signal path may share a
pull-up, pull-down, connector pin, or post-contact conductor with the other.
Each contact closes to the protected 5 V source only while the driver holds the
switch. Thus an open signal path reads low; a short of only one signal path to
the source cannot create the valid two-channel state.
## Steering-wheel wiring and ECU input
Channel A is conditioned non-inverting to create `DEADMAN_A_HELD`. Channel B
is conditioned inverting to create `DEADMAN_B_RELEASED`. This complementary
encoding makes the sole valid held state `A = high`, `B = low`. Both raw,
conditioned contact observations also enter protected 3.3 V MCU inputs as
`DEADMAN_A_STATUS` and `DEADMAN_B_STATUS`; these are diagnostic observations,
not the safety-critical shutoff path.
The two switches share the protected 5 V source and the switched return signal.
The parallel connection is made before the ECU: only one `DEADMAN_IN` signal
conductor and one signal connector pin are required at the ECU, in addition to
the supply connection. No separate contact-status wires are provided.
## Signal tree
Use one dedicated connector-side protection, series/filter network, default-low
bias and non-inverting conditioning path. It produces the 5 V `DEADMAN_OK`
signal and a protected 3.3 V `DEADMAN_STATUS` observation for the MCU. Keep the
hardware gating independent of firmware; the MCU status input is observational.
Exact protection, filtering and connector assignments remain implementation
items. The generic digital-input module does not replace this dedicated path.
The permission gates operate from `+5V_MAIN` and accept 3.3 V MCU logic
levels. Their outputs are 5 V logic levels.
| Left switch held | Right switch held | Shared signal / `DEADMAN_OK` (healthy circuit) |
| --- | --- | --- |
| No | No | Low |
| Yes | No | High |
| No | Yes | High |
| Yes | Yes | High |
![Deadman inputs](../diagrams/deadman-inputs.svg)
## Hardware gating
![Deadman permit](../diagrams/deadman-permit.svg)
The permission gates operate from `+5V_MAIN`, accept 3.3 V MCU logic levels,
and produce 5 V logic outputs.
![Deadman outputs](../diagrams/deadman-outputs.svg)
![Parallel switches and single deadman input](../diagrams/deadman-inputs.svg)
The logic equations are:
![Single-input engine permission](../diagrams/deadman-permit.svg)
![Permitted injector command and ignition inhibit](../diagrams/deadman-outputs.svg)
The healthy-switch relationship is a physical parallel connection at the
steering wheel, not an OR gate or two channels inside the ECU:
```text
DEADMAN_OK = DEADMAN_A_HELD AND NOT(DEADMAN_B_RELEASED)
DEADMAN_IN asserted = LEFT_SWITCH_HELD OR RIGHT_SWITCH_HELD
DEADMAN_OK = conditioned active-high DEADMAN_IN
ENGINE_PERMIT = DEADMAN_OK AND MCU_RUN_PERMIT
SAFE_INJECTOR_SIG = ENGINE_PERMIT AND MCU_INJECTOR_SIG
SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT)
```
`LEFT_SWITCH_HELD` and `RIGHT_SWITCH_HELD` above describe physical switch
states only; they are not separately available ECU signals.
## Output destinations
| Logic output | Destination | Required behavior |
| --- | --- | --- |
| `ENGINE_PERMIT` | Hardware injection-command permission gate | Must prevent an injector command from reaching the injection output stage when low. |
| `SAFE_INJECTOR_SIG` | Dedicated injection output stage command input | The only injector on-command presented to the output stage. |
| `SAFE_IGNITION_INHIBIT` | Dedicated ignition output stage inhibit/enable input | Must inhibit the ignition output stage when high and permit it only when low. |
| `DEADMAN_A_STATUS`, `DEADMAN_B_STATUS` | STM32 digital inputs | Firmware observes both contacts, detects disagreement, clears schedules, and reports diagnostics. Neither input is the safety-critical shutoff path. |
| `ENGINE_PERMIT` | Injection command gate and ignition-permission inverter | Low removes permission from both engine-output paths. |
| `SAFE_INJECTOR_SIG` | Injector driver command input | The only injector on-command presented to the output stage. |
| `SAFE_IGNITION_INHIBIT` | Ignition driver inhibit input | High inhibits the ignition stage; low permits it. |
| `DEADMAN_STATUS` | One STM32 digital input | Firmware observes the combined deadman state and clears schedules when it deasserts. It cannot identify which switch is held. |
## Fail-safe behavior
## Release and fault behavior
- With the switch released, the valid relationship is
`DEADMAN_A_HELD = low` and `DEADMAN_B_RELEASED = high`; `DEADMAN_OK` is low.
- With the switch held, the only permissive relationship is
`DEADMAN_A_HELD = high` and `DEADMAN_B_RELEASED = low`; `DEADMAN_OK` is high.
- An open circuit, an open contact, or a short to the 5 V source on either one
signal path produces a non-permissive relationship. A short to ground on a
held path also removes permission.
- This architecture protects against one fault in one contact or signal path.
It does not claim to detect a common-mode fault that energises both input
paths, or simultaneous faults in both contacts/paths. Harness routing and
connector assignment shall minimise such common-mode faults; any remaining
risk requires explicit system-level acceptance.
- Releasing one switch while the other is held leaves permission asserted.
Releasing both switches deasserts `DEADMAN_OK` and removes `ENGINE_PERMIT`
through hardware, without waiting for firmware.
- An open shared signal conductor or loss of the switch supply deasserts the
input through the ECU-side default-low bias. A shared signal short to ground
also deasserts it; the protected source must tolerate the assigned fault.
- An open individual switch branch disables that switch only. The other
parallel switch can still assert the shared signal.
- A stuck-closed switch, a bridged contact or the shared signal shorted to the
asserted 5 V source can hold `DEADMAN_OK` high after both switches are
released. This single-input arrangement cannot distinguish those faults
from a legitimate held state. It provides no per-switch disagreement or
independent-channel fault detection.
- `MCU_RUN_PERMIT` and `MCU_INJECTOR_SIG` must default low during reset,
boot, brownout, or an unpowered MCU. External bias components shall provide
these states during power sequencing.
- If `ENGINE_PERMIT` becomes low during an injection command,
`SAFE_INJECTOR_SIG` becomes low and removes the command from the injection
output stage.
- If `ENGINE_PERMIT` becomes low during an ignition dwell,
`SAFE_IGNITION_INHIBIT` becomes high and commands the ignition output stage
into its non-sparking shutdown behavior.
- If the 5 V permission logic loses power, the injection command input must
be externally biased low and the ignition output stage's inhibit input must
default to its inhibited state.
boot, brownout or an unpowered MCU. External bias components establish these
states through power sequencing. The MCU can withdraw permission even when
the deadman signal is high.
- If `ENGINE_PERMIT` becomes low during injection, `SAFE_INJECTOR_SIG` becomes
low and removes the injector command.
- If `ENGINE_PERMIT` becomes low during ignition dwell,
`SAFE_IGNITION_INHIBIT` becomes high and requests the ignition driver's
documented non-sparking shutdown behavior.
- If the 5 V permission logic loses power, the injector command must be biased
low and the ignition driver must default to inhibited. Verify this behavior
in the completed input, gate and driver implementation.
## Firmware responsibilities
The hardware path is authoritative; firmware cannot override a released or
faulted deadman switch. Firmware shall sample both `DEADMAN_A_STATUS` and
`DEADMAN_B_STATUS`, clear pending injection and ignition schedules on a
released state or disagreement, report any disagreement, and keep
`MCU_RUN_PERMIT` low except while engine operation is intentionally enabled.
Firmware samples the single `DEADMAN_STATUS` input, clears pending injection
and ignition schedules when it deasserts, and keeps `MCU_RUN_PERMIT` low except
while engine operation is intentionally enabled. It has no individual switch
states to compare and must not claim to detect contact disagreement or a
stuck-high shared signal from this observation alone.
A firmware test mode may assert `MCU_RUN_PERMIT`, but cannot override a low
hardware deadman input. Bench operation requires a deliberate external test
arrangement that asserts the single `DEADMAN_IN` signal.
+2 -2
View File
@@ -7,9 +7,9 @@ NeoECU V1. It accepts externally driven 5 V, 12 V, and protected
battery-domain signals, plus dry-contact and open-collector sources when the
appropriate ECU bias option is fitted.
This is not the crank/cam trigger interface and is not either deadman
This is not the crank/cam trigger interface and is not the dedicated deadman
engine-permit input. Those functions retain their dedicated conditioning and,
for the deadman, its independent two-channel hardware safety path defined in
for the deadman, its single-input hardware permission path defined in
[DEAD_MAN.md](DEAD_MAN.md).
V1 provisionally allocates six generic digital-input channels. The allocation,
+1 -1
View File
@@ -43,7 +43,7 @@ temperature, and ignition noise.
SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT)
```
When `ENGINE_PERMIT` is removed by the two-channel deadman interlock or the
When `ENGINE_PERMIT` is removed by the single-input deadman interlock or the
MCU, `SAFE_IGNITION_INHIBIT` becomes high. If a dwell is active, this invokes
the VBG08H-E soft shutdown so coil current is removed without intentionally
generating a spark. The 1 kOhm resistors on `INP` and `EN` follow the
+2 -3
View File
@@ -29,7 +29,7 @@ low-impedance injector requires a different architecture.
## Command path
`INPUT` is active high. It receives only the hardware-permitted injector
command defined by the two-channel deadman interlock.
command defined by the single-input deadman interlock.
![Injector command](../diagrams/injector-command.svg)
@@ -51,8 +51,7 @@ pin.
When `ENGINE_PERMIT` is removed, `SAFE_INJECTOR_SIG` goes low and turns the
injector output off. This is the hardware shutoff path; firmware also clears
pending injection events when `DEADMAN_OK` becomes invalid or the two deadman
status inputs disagree.
pending injection events when the single `DEADMAN_STATUS` input deasserts.
## Status diagnostic
+5 -2
View File
@@ -66,8 +66,11 @@ Validate each circuit manifest with the installed topology validator:
- The Hall-input drawing separates sensor supply, sensor return and signal;
the original ASCII alignment could suggest an unintended join. The pull-up,
divider and parallel filter follow the existing prose.
- The deadman equations are unchanged. Contact observations, permission gates
and output gates occupy separate figures; shared net names connect them.
- The steering-wheel deadman switches are wired in parallel and present one
shared `DEADMAN_IN` to the ECU. Either switch can assert permission. One
`DEADMAN_STATUS` input reports the combined state; the ECU has no per-switch
observations. The permission and output gates use the single `DEADMAN_OK`
signal. See the module document for release and stuck-high fault behavior.
- `VBG_LOCAL_KELVIN` labels the documented local ignition reference at the
`IGN_PGND` joining point. `LOCAL_GND` in the sink-command figure denotes the
TLE9104SH local ground reference. Neither denotes a new remote ground path.
+93 -87
View File
@@ -658,11 +658,11 @@
]
},
"deadman-inputs": {
"title": "Deadman contacts and observations",
"source": "IO_MODULES/DEAD_MAN.md: Logic domains",
"title": "Parallel switches \u00b7 one ECU deadman input",
"source": "IO_MODULES/DEAD_MAN.md: Steering-wheel wiring and ECU input",
"nodes": {
"title": {
"label": "Deadman contacts and observations",
"label": "Parallel switches \u00b7 one ECU deadman input",
"kind": "note",
"bounds": [
30,
@@ -671,131 +671,137 @@
42
]
},
"As": {
"label": "Protected 5 V\nIndependent NO contact A",
"supply": {
"label": "Protected 5 V",
"kind": "power",
"bounds": [
30,
100,
260,
80
]
},
"Ap": {
"label": "Protected input A\nOwn filter + default-low bias",
"kind": "signal",
"bounds": [
370,
100,
290,
80
]
},
"Ah": {
"label": "DEADMAN_A_HELD\n5 V \u00b7 non-inverting",
"kind": "signal",
"bounds": [
750,
100,
260,
80
]
},
"Ad": {
"label": "DEADMAN_A_STATUS\n3.3 V \u00b7 held = high \u2192 MCU",
"kind": "device",
"bounds": [
370,
200,
220,
330,
75
]
},
"Bs": {
"label": "Protected 5 V\nIndependent NO contact B",
"kind": "power",
"bounds": [
30,
345,
260,
80
]
},
"Bp": {
"label": "Protected input B\nOwn filter + default-low bias",
"kind": "signal",
"bounds": [
370,
345,
290,
80
]
},
"Bh": {
"label": "DEADMAN_B_RELEASED\n5 V \u00b7 inverting",
"kind": "signal",
"bounds": [
750,
345,
260,
80
]
},
"Bd": {
"label": "DEADMAN_B_STATUS\n3.3 V \u00b7 held = high \u2192 MCU",
"left": {
"label": "Left NO switch\nHeld = closed",
"kind": "device",
"bounds": [
370,
465,
330,
75
340,
90,
230,
80
]
},
"note575": {
"label": "Separate harness paths. MCU status observations are diagnostic; the 5 V signals feed the permit gates.",
"right": {
"label": "Right NO switch\nHeld = closed",
"kind": "device",
"bounds": [
340,
300,
230,
80
]
},
"shared": {
"label": "DEADMAN_IN\nJoined at steering wheel",
"kind": "signal",
"bounds": [
740,
200,
270,
80
]
},
"note390": {
"label": "Switches are physically in parallel. Either held \u2192 asserted; both released \u2192 deasserted.",
"kind": "note",
"bounds": [
30,
575,
390,
980,
60
]
},
"input": {
"label": "DEADMAN_IN\nOne ECU signal pin",
"kind": "signal",
"bounds": [
30,
490,
240,
80
]
},
"conditioning": {
"label": "Protection + filter\nDefault-low bias",
"kind": "signal",
"bounds": [
340,
490,
270,
80
]
},
"ok": {
"label": "DEADMAN_OK\n5 V \u00b7 hardware gates",
"kind": "signal",
"bounds": [
740,
490,
270,
80
]
},
"status": {
"label": "DEADMAN_STATUS\n3.3 V \u2192 one MCU input",
"kind": "device",
"bounds": [
340,
630,
310,
80
]
}
},
"connections": [
{
"from": "As",
"to": "Ap",
"from": "supply",
"to": "left",
"label": "",
"kind": "signal"
},
{
"from": "Ap",
"to": "Ah",
"from": "supply",
"to": "right",
"label": "",
"kind": "signal"
},
{
"from": "Ap",
"to": "Ad",
"from": "left",
"to": "shared",
"label": "",
"kind": "signal"
},
{
"from": "Bs",
"to": "Bp",
"from": "right",
"to": "shared",
"label": "",
"kind": "signal"
},
{
"from": "Bp",
"to": "Bh",
"from": "input",
"to": "conditioning",
"label": "",
"kind": "signal"
},
{
"from": "Bp",
"to": "Bd",
"from": "conditioning",
"to": "ok",
"label": "",
"kind": "signal"
},
{
"from": "conditioning",
"to": "status",
"label": "",
"kind": "signal"
}
+17 -9
View File
@@ -99,15 +99,23 @@ f.note('Sensor output is the sensors signal pin. Both ADC channels use +3V3_A
chain('dac-output','Optional analogue-output provision','IO_ARCHITECTURE.md: Analogue-output provision',['MCU DAC','Rail-to-rail buffer','Protection /\nseries impedance','Connector'],'Provision only; final electrical range, load and protection remain to be defined.')
f=Figure('deadman-inputs','Deadman contacts and observations','IO_MODULES/DEAD_MAN.md: Logic domains',1040,650)
for i,c in enumerate('AB'):
y=100+i*245
f.node(c+'s','Protected 5 V\nIndependent NO contact '+c,30,y,260,80,'power')
f.node(c+'p','Protected input '+c+'\nOwn filter + default-low bias',370,y,290,80,'signal')
f.node(c+'h','DEADMAN_A_HELD\n5 V · non-inverting' if c=='A' else 'DEADMAN_B_RELEASED\n5 V · inverting',750,y,260,80,'signal')
f.node(c+'d','DEADMAN_'+c+'_STATUS\n3.3 V · held = high → MCU',370,y+120,330,75,'device')
f.edge(c+'s',c+'p'); f.edge(c+'p',c+'h'); f.edge(c+'p',c+'d',exit=(.5,1),entry=(.5,0))
f.note('Separate harness paths. MCU status observations are diagnostic; the 5 V signals feed the permit gates.',575);f.save()
f=Figure('deadman-inputs','Parallel switches · one ECU deadman input','IO_MODULES/DEAD_MAN.md: Steering-wheel wiring and ECU input',1040,750)
f.node('supply','Protected 5 V',30,200,220,80,'power')
f.node('left','Left NO switch\nHeld = closed',340,90,230,80,'device')
f.node('right','Right NO switch\nHeld = closed',340,300,230,80,'device')
f.node('shared','DEADMAN_IN\nJoined at steering wheel',740,200,270,80,'signal')
f.edge('supply','left',points=[(290,240),(290,130)])
f.edge('supply','right',points=[(290,240),(290,340)])
f.edge('left','shared',points=[(660,130),(660,240)])
f.edge('right','shared',points=[(660,340),(660,240)])
f.note('Switches are physically in parallel. Either held → asserted; both released → deasserted.',390)
f.node('input','DEADMAN_IN\nOne ECU signal pin',30,490,240,80)
f.node('conditioning','Protection + filter\nDefault-low bias',340,490,270,80)
f.node('ok','DEADMAN_OK\n5 V · hardware gates',740,490,270,80)
f.node('status','DEADMAN_STATUS\n3.3 V → one MCU input',340,630,310,80,'device')
f.edge('input','conditioning');f.edge('conditioning','ok')
f.edge('conditioning','status',exit=(.5,1),entry=(.5,0))
f.save()
for name,title,part,pin,load,ground,source in [
('ignition-power','Ignition power path','VBG08H-E','HVC','Coil primary','IGN_PGND','IGNITION'),
+4 -5
View File
@@ -160,11 +160,10 @@ def equation_gate(c,ref,xy,a,b,out,invert_b=False):
c.wire(start,(x-1.2,yy));c.wire((x-1.2,yy),(x-1.2,anchor.y));c.wire((x-1.2,anchor.y),anchor)
c.wire(gate.out,(x+5,y));c.port(ref+'O',(x+5,y),out,loc='right')
c=Circuit('deadman-permit','Hardware engine-permit equations','IO_MODULES/DEAD_MAN.md: Logic equations')
equation_gate(c,'VALID',(0,0),'DEADMAN_A_HELD','DEADMAN_B_RELEASED','DEADMAN_OK',True)
equation_gate(c,'PERMIT',(0,-6),'DEADMAN_OK','MCU_RUN_PERMIT','ENGINE_PERMIT')
c.label((0,3),'Hardware permission · 5 V gate outputs',size=18)
c.label((0,-9),'Bubble inverts channel B. MCU_RUN_PERMIT is 3.3 V; gates must accept that input level.',size=11);c.save()
c=Circuit('deadman-permit','Single-input hardware engine permission','IO_MODULES/DEAD_MAN.md: Hardware gating')
equation_gate(c,'PERMIT',(0,0),'DEADMAN_OK','MCU_RUN_PERMIT','ENGINE_PERMIT')
c.label((0,3),'Single deadman input · hardware permission',size=18)
c.label((0,-3),'DEADMAN_OK: conditioned shared input. MCU_RUN_PERMIT: 3.3 V. Gate output: 5 V.',size=11);c.save()
c=Circuit('deadman-outputs','Hardware permitted output commands','IO_MODULES/DEAD_MAN.md: Logic equations')
equation_gate(c,'INJECT',(0,0),'ENGINE_PERMIT','MCU_INJECTOR_SIG','SAFE_INJECTOR_SIG')
+61 -38
View File
@@ -1,58 +1,81 @@
<?xml version='1.0' encoding='utf-8'?>
<mxfile host="app.diagrams.net">
<diagram name="Deadman contacts and observations" id="deadman-inputs">
<mxGraphModel page="1" pageWidth="1040" pageHeight="650" grid="1" gridSize="10">
<diagram name="Parallel switches · one ECU deadman input" id="deadman-inputs">
<mxGraphModel page="1" pageWidth="1040" pageHeight="750" grid="1" gridSize="10">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="node_title" value="Deadman contacts and observations" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=26;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1">
<mxCell id="node_title" value="Parallel switches · one ECU deadman input" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=26;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1">
<mxGeometry x="30" y="18" width="980" height="42" as="geometry" />
</mxCell>
<mxCell id="node_As" value="Protected 5 V&#10;Independent NO contact A" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#fff1d6;spacing=10;" vertex="1" parent="1">
<mxGeometry x="30" y="100" width="260" height="80" as="geometry" />
<mxCell id="node_supply" value="Protected 5 V" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#fff1d6;spacing=10;" vertex="1" parent="1">
<mxGeometry x="30" y="200" width="220" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Ap" value="Protected input A&#10;Own filter + default-low bias" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="100" width="290" height="80" as="geometry" />
<mxCell id="node_left" value="Left NO switch&#10;Held = closed" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="340" y="90" width="230" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Ah" value="DEADMAN_A_HELD&#10;5 V · non-inverting" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="750" y="100" width="260" height="80" as="geometry" />
<mxCell id="node_right" value="Right NO switch&#10;Held = closed" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="340" y="300" width="230" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Ad" value="DEADMAN_A_STATUS&#10;3.3 V · held = high → MCU" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="220" width="330" height="75" as="geometry" />
<mxCell id="node_shared" value="DEADMAN_IN&#10;Joined at steering wheel" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="740" y="200" width="270" height="80" as="geometry" />
</mxCell>
<mxCell id="e0" source="node_As" target="node_Ap" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxCell id="e0" source="node_supply" target="node_left" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="290" y="240" />
<mxPoint x="290" y="130" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="e1" source="node_supply" target="node_right" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="290" y="240" />
<mxPoint x="290" y="340" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="e2" source="node_left" target="node_shared" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="660" y="130" />
<mxPoint x="660" y="240" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="e3" source="node_right" target="node_shared" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="660" y="340" />
<mxPoint x="660" y="240" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="node_note390" value="Switches are physically in parallel. Either held → asserted; both released → deasserted." style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=16;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1">
<mxGeometry x="30" y="390" width="980" height="60" as="geometry" />
</mxCell>
<mxCell id="node_input" value="DEADMAN_IN&#10;One ECU signal pin" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="30" y="490" width="240" height="80" as="geometry" />
</mxCell>
<mxCell id="node_conditioning" value="Protection + filter&#10;Default-low bias" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="340" y="490" width="270" height="80" as="geometry" />
</mxCell>
<mxCell id="node_ok" value="DEADMAN_OK&#10;5 V · hardware gates" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="740" y="490" width="270" height="80" as="geometry" />
</mxCell>
<mxCell id="node_status" value="DEADMAN_STATUS&#10;3.3 V → one MCU input" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="340" y="630" width="310" height="80" as="geometry" />
</mxCell>
<mxCell id="e4" source="node_input" target="node_conditioning" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e1" source="node_Ap" target="node_Ah" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxCell id="e5" source="node_conditioning" target="node_ok" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e2" source="node_Ap" target="node_Ad" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1">
<mxCell id="e6" source="node_conditioning" target="node_status" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="node_Bs" value="Protected 5 V&#10;Independent NO contact B" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#fff1d6;spacing=10;" vertex="1" parent="1">
<mxGeometry x="30" y="345" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Bp" value="Protected input B&#10;Own filter + default-low bias" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="345" width="290" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Bh" value="DEADMAN_B_RELEASED&#10;5 V · inverting" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="750" y="345" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Bd" value="DEADMAN_B_STATUS&#10;3.3 V · held = high → MCU" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="465" width="330" height="75" as="geometry" />
</mxCell>
<mxCell id="e3" source="node_Bs" target="node_Bp" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e4" source="node_Bp" target="node_Bh" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e5" source="node_Bp" target="node_Bd" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="node_note575" value="Separate harness paths. MCU status observations are diagnostic; the 5 V signals feed the permit gates." style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=16;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1">
<mxGeometry x="30" y="575" width="980" height="60" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -1,42 +1,8 @@
{
"title": "Hardware engine-permit equations",
"source": "IO_MODULES/DEAD_MAN.md: Logic equations",
"title": "Single-input hardware engine permission",
"source": "IO_MODULES/DEAD_MAN.md: Hardware gating",
"reference_scope": "documentation only",
"components": [
{
"ref": "VALID",
"kind": "and-with-inverted-B",
"pins": [
"A",
"B",
"Y"
],
"value": ""
},
{
"ref": "VALIDP0",
"kind": "port",
"pins": [
"P"
],
"value": "DEADMAN_A_HELD"
},
{
"ref": "VALIDP1",
"kind": "port",
"pins": [
"P"
],
"value": "DEADMAN_B_RELEASED"
},
{
"ref": "VALIDO",
"kind": "port",
"pins": [
"P"
],
"value": "DEADMAN_OK"
},
{
"ref": "PERMIT",
"kind": "and",
@@ -73,25 +39,9 @@
}
],
"nets": [
{
"name": "DEADMAN_A_HELD",
"connections": [
"VALID.A",
"VALIDP0.P"
]
},
{
"name": "DEADMAN_B_RELEASED",
"connections": [
"VALID.B",
"VALIDP1.P"
]
},
{
"name": "DEADMAN_OK",
"connections": [
"VALID.Y",
"VALIDO.P",
"PERMIT.A",
"PERMITP0.P"
]