# 03 — Vocabulary + a wafer's journey ← [02 The cast of characters](02_the_cast.md) | [Back to index](00_index.md) | Next: [10 E5 — SECS-II data items](10_e5_secs_ii_data_items.md) → The SEMI standards bury everything in acronyms. Three-letter, four- letter, sometimes the same letter pattern (`ACKC5`, `ACKC6`, `ACKC7`, `ACKC10`) but with completely different semantics depending on which stream you're in. Most readers learn them by absorbing them over years of integration work. This chapter accelerates that. We follow **one 300 mm wafer** from the moment it enters the fab to the moment it leaves as a finished die, and at every step we name every acronym that fires, what it means, and where it lives in this codebase. By the end you'll have seen `SVID`, `CEID`, `ALID`, `PPID`, `HCACK`, `ALCD`, `RPTID`, `OFLACK`, `MDLN`, `SOFTREV`, `CAACK`, `SMACK`, and the rest in *context* — not as a vocabulary list. If you're confident with the vocabulary already, skip to Part 2, Chapter [10](10_e5_secs_ii_data_items.md) (SECS-II encoding). --- ## The setup - **The wafer**: an unpatterned 300 mm silicon disc, 775 µm thick, with a serial number `W-2026-06-09-A47` etched on the bevel. - **The carrier**: a Front-Opening Universal Pod (**FOUP**) that holds 25 wafers in vertical slots. Our wafer is in slot 14. The FOUP's bar code reads `C-31415`. - **The tools**: - **PVD-1** (physical vapour deposition — deposits a metal layer) - **LITHO-3** (photolithography — patterns the metal layer) - **ETCH-7** (plasma etch — removes uncovered metal) - **The host**: a fab-wide MES called `meta-fab.example`. - **The recipe**: `RECIPE-Cu-A` for PVD-1, `RECIPE-193nm-X` for LITHO-3, `RECIPE-CL2-B` for ETCH-7. For brevity we'll only show the wafer's first pass through PVD-1. The same pattern repeats for LITHO-3 and ETCH-7. --- ## Stage 1 — Establishing communications (already done) Before any wafer arrives, **PVD-1 and meta-fab.example have already HSMS-SELECTed each other**. That's the once-per-power-on dance: ``` host (active) equipment (passive) ───────────── ─────────────────── TCP SYN ─────────────────────────► (bind on :5000) ◄──── TCP SYN-ACK HSMS Select.req (sessionID=0) ───► ◄──── HSMS Select.rsp (SELECT_STATUS=0=accept) [transport state: SELECTED] S1F13 Establish Communications ──► ◄──── S1F14 (COMMACK=0=accepted, [MDLN, SOFTREV]) [GEM communication state: COMMUNICATING] ``` This introduces three acronyms: - **`MDLN`** — Model Name. An ASCII string up to 20 chars identifying the equipment model. PVD-1 returns `"ACME-PVD-3000"`. - **`SOFTREV`** — Software Revision. ASCII string up to 20 chars identifying the firmware / EAP version. PVD-1 returns `"1.4.2"`. - **`COMMACK`** — Communication Acknowledge. One byte; 0 = accepted, 1 = denied. Defined in E30 §6.5. **Where:** see `equipment.yaml` device block; emission flows through [`gem::Router`](../include/secsgem/gem/router.hpp) → [`secsgem::secs2::Message`](../include/secsgem/secs2/message.hpp). --- ## Stage 2 — The carrier arrives at PVD-1's load port The AMHS overhead hoist swings FOUP `C-31415` onto load port 1. *Before* anything SECS happens, the **E84 handshake** runs on the physical I/O lines: ``` AMHS robot load port 1 ────────── ─────────── CS_0 asserted ───────────────────► (carrier select bit 0) CS_1 asserted ───────────────────► (carrier select bit 1) VALID asserted ──────────────────► (lines above are stable) ◄──── L_REQ asserted (LOAD allowed) TR_REQ asserted ─────────────────► (transfer requested) ◄──── READY asserted (kinematic interlocks ok) BUSY asserted ───────────────────► (placement in progress) … mechanical placement happens (~5 seconds) … BUSY de-asserted ────────────────► (placement done) ◄──── COMPT asserted (complete) CONT asserted ───────────────────► (carrier connected to load port) ``` This introduces the E84 line-name acronyms (`VALID`, `CS_0`, `CS_1`, `TR_REQ`, `READY`, `BUSY`, `COMPT`, `CONT`, `L_REQ`, `U_REQ`, `ES`) and three timer names: - **`TA1`** — armed when `VALID` asserts; the load port must respond with `L_REQ` within `TA1`. Default ~2 seconds. - **`TA2`** — armed when `L_REQ` asserts; `TR_REQ` must follow within `TA2`. Default ~2 seconds. - **`TA3`** — armed when `BUSY` asserts (transfer in progress); the whole transfer must finish within `TA3`. Default ~60 seconds. Any of these timing out → both sides go to `HandoffFault` and the operator gets paged. No FOUP gets dropped because the protocol guarantees both sides agreed on every step. **Where:** [`include/secsgem/gem/e84_state.hpp`](../include/secsgem/gem/e84_state.hpp) defines the FSM; [`include/secsgem/gem/e84_asio_timers.hpp`](../include/secsgem/gem/e84_asio_timers.hpp) defines the timer enforcement; chapter [18](18_e84_parallel_io.md) walks the whole handshake. --- ## Stage 3 — The carrier is on the load port; PVD-1 tells the MES The E84 handshake gave PVD-1 a docked carrier. Now SECS messages flow: ``` PVD-1 (equipment) meta-fab (host) ───────────────── ─────────────── S6F11 CarrierArrived ────────────► CEID = 10001 DATAID = 1 [ {RPTID=100, V=[CarrierID="C-31415", PortID=1]} ] ◄──── S6F12 (ACKC6=0=accepted) S3F19 Slot Map Verify ───────────► CARRIERID = "C-31415" [ slot_state[1..25] ] ◄──── S3F20 (SMACK=0=match) ``` New acronyms in this stage: - **`CEID`** — Collection Event ID. An identifier (any unsigned width; we'll use `U4`) for a noteworthy thing that happened. CEIDs are *defined in the equipment's YAML* and the MES learns them via `S1F23/F24`. CEID 10001 = `CarrierArrived` per E87. - **`RPTID`** — Report ID. A bundle of variables. When CEID 10001 fires, the MES gets back the values of every variable linked to every report linked to CEID 10001. Reports are *defined by the host* via `S2F33` and linked to CEIDs via `S2F35`. - **`DATAID`** — Data ID, a per-host transaction counter. Lets the host correlate report data to a specific request. - **`ACKC6`** — Acknowledge Code 6. S6F12 reply byte. 0 = accepted, anything else = MES couldn't process the event. - **`CARRIERID`** — Carrier ID, an ASCII string. Matches what the AMHS told us via E84. - **`SMACK`** — Slot Map Acknowledge. S3F20 reply byte. 0 = matches what the MES expected, 1 = mismatch. Defined in E87. - **`CAACK`** — Carrier Action Acknowledge (we'll see this one shortly). S3F18 reply byte for carrier-action commands. Note the pattern: every primary message ends in an odd function (F11, F19), every reply ends in the next even function (F12, F20). This is invariant across SECS-II. See chapter [10](10_e5_secs_ii_data_items.md) for the encoding details. **Where:** `gem::CarrierStore` in [`include/secsgem/gem/store/carriers.hpp`](../include/secsgem/gem/store/carriers.hpp); the E87 wire tests in [`tests/test_e87_wire_scenarios.cpp`](../tests/test_e87_wire_scenarios.cpp). --- ## Stage 4 — The host authorises processing ``` meta-fab (host) PVD-1 (equipment) ─────────────── ───────────────── S3F17 CarrierAction ─────────────► CARRIERACTION = "ProceedWithCarrier" CARRIERID = "C-31415" ◄──── S3F18 (CAACK=0=accepted) ``` - **`CARRIERACTION`** — an ASCII string from a fixed E87 set: `ProceedWithCarrier`, `CancelCarrier`, `CarrierOut`, … - **`CAACK`** — Carrier Action Acknowledge. S3F18 reply byte. 0 = accepted, 1 = unknown carrier, 2 = invalid action, 3 = invalid state, 4 = mismatch, 5 = unknown. The host could have sent `CancelCarrier` here instead and PVD-1 would have rejected the FOUP without processing. That decision lives entirely on the host side. --- ## Stage 5 — The host queues a process job ``` meta-fab (host) PVD-1 (equipment) ─────────────── ───────────────── S16F11 PRJobCreate ──────────────► PRJobID = "PJ-2026-06-09-001" MF = "Substrate" PRMtlOutSpec = [] PRRecipeMethod = "RecipeOnly" RCPSpec = "RECIPE-Cu-A" PRProcessStart = false (we'll start it explicitly later) PRMtlnameList = ["W-2026-06-09-A47"] ◄──── S16F12 (PRJobAck=0) S14F9 CreateControlJob ─────────► CJobID = "CJ-2026-06-09-001" PRJobIDList = ["PJ-2026-06-09-001"] ◄──── S14F10 (OBJACK=0) ``` New acronyms: - **`PRJobID`** — Process Job ID, an ASCII string the host invents for tracking. Sometimes called `PJID`. - **`MF`** — Material Format. ASCII; `Substrate`, `Carrier`, `SubstrateLocation`. Tells the equipment what scale the job is about. - **`RCPSpec`** — Recipe specification. References a recipe by ID (`PPID`, below). - **`PPID`** — Process Program ID. The recipe's identifier. In our case `"RECIPE-Cu-A"`. - **`PRJobAck`** — S16F12 reply byte. 0 = accepted, non-zero values for each failure mode. - **`CJobID`** — Control Job ID. A control job wraps one or more process jobs and adds scheduling semantics (start order, abort policy, dependency on other CJs). - **`OBJACK`** — Object Acknowledge. S14F10 reply byte. Generic E39 object-services ack: 0 = accepted, 1 = error. E40 governs process jobs; E94 governs control jobs above them. **Where:** [`include/secsgem/gem/store/process_jobs.hpp`](../include/secsgem/gem/store/process_jobs.hpp), [`include/secsgem/gem/store/control_jobs.hpp`](../include/secsgem/gem/store/control_jobs.hpp). The state machines are loaded from [`data/process_job_state.yaml`](../data/process_job_state.yaml) and [`data/control_job_state.yaml`](../data/control_job_state.yaml). See chapter [14](14_e40_e94_jobs.md) for the lifecycle in full. --- ## Stage 6 — The host configures event reports Before processing starts, the MES wants to subscribe to specific events. This is a three-message dance: ``` meta-fab (host) PVD-1 (equipment) ─────────────── ───────────────── S2F33 DefineReport ──────────────► DATAID = 2 [ { RPTID=200, VID=[1, 2, 5] } ] (link RPTID 200 to SVIDs 1,2,5) ◄──── S2F34 (DRACK=0=accepted) S2F35 LinkEvent ─────────────────► DATAID = 3 [ { CEID=300, RPTID=[200] } ] (when CEID 300 fires, send RPTID 200) ◄──── S2F36 (LRACK=0=accepted) S2F37 EnableEvent ───────────────► CEED = true CEID = [300] (enable CEID 300) ◄──── S2F38 (ERACK=0=accepted) ``` New acronyms: - **`SVID`** — Status Variable ID. An identifier (`U4` typical) for a *long-lived* value the host can read at any time — current control state, chamber pressure, wafer counter, recipe in progress, clock. Roughly: instance variables that survive across events. - **`DVID`** — Data Variable ID. Same shape, but only meaningful *at the moment an event fires*. E.g. the temperature at the time the `ProcessStarted` event was emitted. Not readable independently via `S1F3`; only delivered as part of a report. - **`ECID`** — Equipment Constant ID. Same shape, but the host can *set* it (within declared `min`/`max` bounds) via `S2F15`. Settings that survive power-cycle: nominal chamber pressure, T3 timeout, T7 timeout, etc. - **`VID`** — Variable ID. A generic SVID-or-DVID, used in report definitions. - **`CEED`** — Collection Event Enable Disable. Boolean. `true` = enable the listed CEIDs, `false` = disable them. - **`DRACK`** — Define Report Acknowledge. S2F34 reply. - **`LRACK`** — Link Report Acknowledge. S2F36 reply. - **`ERACK`** — Enable Report Acknowledge. S2F38 reply. Acknowledge bytes are *distinct enums per stream/function*. `DRACK = 0` = accepted; `LRACK = 0` = accepted; `ERACK = 0` = accepted — same value, but each one has its own enumeration of failure codes (`3 = at least one CEID does not exist`, etc.). Don't reuse one stream's enum for another's. **Where:** [`include/secsgem/gem/store/event_reports.hpp`](../include/secsgem/gem/store/event_reports.hpp) (reports + collection events live together — the same store backs S2F33/F35/F37). The configuration flow is the heart of E30 §6.6 Dynamic Event Report Configuration; see chapter [13](13_e30_gem.md). --- ## Stage 7 — Processing begins ``` meta-fab (host) PVD-1 (equipment) ─────────────── ───────────────── S2F41 RemoteCommand ─────────────► RCMD = "START" CPNAME[] / CPVAL[] = [] ◄──── S2F42 (HCACK=0=accepted) S6F11 ProcessStarted ──────────► CEID = 300 DATAID = 4 [ {RPTID=200, V=[ControlState="OnlineRemote", Clock="20260609173000", WaferCount=147]} ] ◄──── S6F12 (ACKC6=0) ``` New acronyms: - **`RCMD`** — Remote Command name. ASCII. `"START"`, `"STOP"`, `"PAUSE"`, `"ABORT"`, `"VENT"`, etc. Equipment-vendor-defined. - **`CPNAME` / `CPVAL`** — Command Parameter name / value pairs. Empty list here; some commands take parameters (e.g. `RCMD="CHANGE-RECIPE", CPNAME="PPID", CPVAL="RECIPE-Cu-B"`). - **`HCACK`** — Host Command Acknowledge. S2F42 reply. 0 = accepted, 1 = invalid command, 2 = cannot perform now, 3 = at least one parameter is invalid, 4 = accepted-and-will-finish-later, 5 = rejected, 6 = invalid object. The `S6F11(CEID=300)` that fires next is the event report **defined three messages earlier**. The MES correlated this by: 1. Earlier sent `S2F33` → equipment now knows that "RPTID 200 = [SVID 1, SVID 2, SVID 5]." 2. Earlier sent `S2F35` → equipment now knows that "when CEID 300 fires, the report payload should include RPTID 200." 3. Earlier sent `S2F37` → CEID 300 is enabled, so when the processing logic fires it, an `S6F11` actually leaves the wire. (If CEID 300 had been left *disabled*, the processing logic would still fire it but the wire would stay quiet.) **Where:** [`include/secsgem/gem/store/host_commands.hpp`](../include/secsgem/gem/store/host_commands.hpp) (`HostCommandRegistry`) maps `RCMD` strings to handlers; the report-emission machinery lives in `EquipmentDataModel` ([`include/secsgem/gem/data_model.hpp`](../include/secsgem/gem/data_model.hpp)) via `compose_reports_for(ceid)`. Wire-level tests: [`tests/test_wire_ceid_emission.cpp`](../tests/test_wire_ceid_emission.cpp). --- ## Stage 8 — An alarm fires Mid-processing, the chamber pressure sensor reads above its configured `ECID="ChamberPressureMax"` threshold. The EAP's alarm monitor decides this is alarm-worthy and calls `alarms.set(ALID=42)`: ``` PVD-1 (equipment) meta-fab (host) ───────────────── ─────────────── S5F1 AlarmReport ────────────────► ALCD = 0x84 (bit 7 set + category 4 = process) ALID = 42 ALTX = "Chamber pressure above max threshold" ◄──── S5F2 (ACKC5=0) ``` - **`ALID`** — Alarm ID. An identifier (`U4` typical) for one named alarm in the equipment's alarm directory. - **`ALCD`** — Alarm Code. One byte. Bit 7 = "set" (1) or "clear" (0). Lower 7 bits = category (1 = personal safety, 2 = equipment safety, 3 = parameter control warning, 4 = parameter control error, 5 = irrecoverable error, 6 = equipment status warning, 7 = attention flag, 8 = data integrity, others reserved). E5 §13. - **`ALTX`** — Alarm Text. ASCII description, up to 120 chars per E5 §13. - **`ACKC5`** — Acknowledge Code 5. S5F2 reply. 0 = accepted. If the host had previously *disabled* ALID 42 (via `S5F3 ALED=0x00`), this `S5F1` wouldn't have left the wire — the equipment would still note the alarm internally (so `S5F5` would list it), but the host wouldn't get pinged. When the pressure returns to range, a second `S5F1` fires with `ALCD=0x04` (bit 7 cleared) and the same ALID, signalling "alarm cleared." **Where:** [`include/secsgem/gem/store/alarms.hpp`](../include/secsgem/gem/store/alarms.hpp) defines `AlarmRegistry`, which both stores the definitions and gates S5F1 emission on the enable list. --- ## Stage 9 — Processing completes ``` PVD-1 (equipment) meta-fab (host) ───────────────── ─────────────── S6F11 ProcessCompleted ──────────► CEID = 301 DATAID = 5 [ {RPTID=200, V=[…]} ] ◄──── S6F12 (ACKC6=0) ``` Same pattern as `ProcessStarted` — just a different CEID for a different lifecycle moment. The MES sees `CEID=301` and updates its tracking: process job `PJ-2026-06-09-001` is now `ProcessComplete` per E40. It clears its "in progress" counter and updates wafer `W-2026-06-09-A47`'s location in E90 substrate tracking. --- ## Stage 10 — Carrier transfers out ``` meta-fab (host) PVD-1 (equipment) ─────────────── ───────────────── S3F25 CarrierTransfer ───────────► CARRIERID = "C-31415" PortID = 2 (transfer from LP1 to LP2 = outbound) ◄──── S3F26 (CAACK=0) PVD-1 (equipment) meta-fab (host) ───────────────── ─────────────── S6F11 CarrierTransfered ─────────► CEID = 10002 [ … ] ◄──── S6F12 (ACKC6=0) ``` Then E84 runs in reverse: the AMHS robot couples to the load port, the parallel I/O lines hand control back, the OHT hoist lifts the FOUP, and `C-31415` heads to LITHO-3 for the next process step. --- ## Wait, what other acronyms exist? The journey above covered the most common acronyms but skipped a handful that show up in other contexts. A reference list for the rest: ### Acknowledge codes you haven't met yet | Code | Stream | Where | 0 = accepted, then… | |----------|--------|--------------------------------|----------------------------------------------| | `OFLACK` | 1 | S1F16 reply to "Request Offline" | 0=accept, 1=already offline | | `ONLACK` | 1 | S1F18 reply to "Request Online" | 0=accept, 1=not allowed, 2=already online | | `ACKC7` | 7 | S7F4 / S7F18 (recipe send/delete) | 0=accept, 1=permission denied, 2=length err,3=matrix err,4=PPID not found,5=mode unsupported,6=other | | `ACKC10` | 10 | S10F2 / F4 / F6 (terminal services)| 0=accept, 1=not displayed, 2=no terminal | | `CMDA` | 2 | S2F22 reply to legacy `S2F21` | 0=ok, 1=invalid command, 2=cannot do now,3=invalid arg | | `TIACK` | 2 | S2F32 reply to "Set Clock" | 0=accept, 1=err not done | | `EAC` | 2 | S2F16 reply to "Set EC values" | 0=accept, 1=≥1 constant out of range, 2=busy, 3=≥1 constant unknown | | `RSPACK` | 2 | S2F44 reply to "Set Spool Streams" | 0=accept, 1=spool not supported, 2=≥1 stream unknown | | `RSDA` | 6 | S6F24 reply to "Spool Data Send" | 0=ok, 1=denied | | `PPGNT` | 7 | S7F2 reply to "PP Load Inquire"| 0=permit, 1=already have, 2=no room, 3=invalid PPID, 4=mode unsupported, 5=PP non-existent, 6=other | ### Control codes you haven't met | Code | Stream | Where | What it means | |----------|--------|-----------------------------|----------------------------------------------------------------| | `RSDC` | 6 | S6F23 host command to spool | 0=transmit spooled, 1=purge spool | | `ALED` | 5 | S5F3 host enable/disable alarm | bit 7 set = enable, bit 7 cleared = disable | | `TID` | 10 | S10F1/F3/F5 terminal display | Which terminal screen to address (0 = main) | | `TEXT` | 10 | S10F1/F3/F5 terminal display | The ASCII text payload | ### Object-services codes (E39) | Code | Stream | Where | What it means | |-----------|--------|-----------------------------|--------------------------------------------------------------| | `OBJSPEC` | various | S2F49, S14F1 | An "object specifier" — a typed path identifying a target object | | `OBJACK` | 14 | S14F2 / F10 / F12 reply | 0=ok, 1=command failed | | `CPACK` | 2 | S2F42 reply (modern) | Per-parameter ack for each `CPNAME/CPVAL` in the command | | `CEPACK` | 2 | S2F50 reply (enhanced) | Per-parameter ack for enhanced remote commands | --- ## All the T-timers in one place You'll meet timer acronyms in three different contexts. They use the same letters with different meanings — pin them down: ### HSMS T-timers (E37 §10) These bound the *network* behaviour. Only fire when something is slow or stuck. | Name | Default | What it bounds | |------|-------------|------------------------------------------------------| | `T3` | 45 s | Reply timeout for a W=1 primary message | | `T5` | 10 s | How long active side waits between connect attempts | | `T6` | 5 s | Control-transaction (Select / Linktest) reply timeout | | `T7` | 10 s | Passive side: max time without Select.req after TCP | | `T8` | 5 s | Max time between bytes of a single frame | Chapter [11](11_e37_hsms.md) covers each one in detail. ### SECS-I T-timers (E4 §10) These bound the *serial-block* behaviour. Distinct from HSMS T-timers despite the name overlap. | Name | Default | What it bounds | |------|-------------|------------------------------------------------------| | `T1` | 500 ms | Inter-character timeout within one block | | `T2` | 10 s | Protocol timer (handshake state) | | `T3` | 45 s | Reply timeout for a W=1 primary message | | `T4` | 45 s | Inter-block timeout in a multi-block message | `T3` exists in both HSMS and SECS-I with the same semantics — it's load-bearing in both transports. ### E84 timers (E84 §6) These bound the *physical handoff* timing. Distinct again. | Name | Default | What it bounds | |-------|---------|-------------------------------------------------| | `TA1` | ~2 s | `VALID` → `L_REQ` | | `TA2` | ~2 s | `L_REQ` → `TR_REQ` | | `TA3` | ~60 s | `BUSY` → transfer complete | ### E30 communication-state timers (E30 §6.5) These bound the *application-level* establish-communications loop: | Name | Default | What it bounds | |-----------|---------|-----------------------------------------------------------------| | `T_CRA` | 45 s | Wait for `S1F14` (Comm Request Acknowledge) reply after `S1F13` | | `T_DELAY` | 10 s | Retry interval after a failed `S1F13` round-trip | Defined in [`include/secsgem/gem/communication_state.hpp`](../include/secsgem/gem/communication_state.hpp); tested in [`tests/test_communication_state.cpp`](../tests/test_communication_state.cpp). --- ## Stream-by-stream summary The streams you'll meet most often, with one sentence each: | Stream | What it's for | Most-used messages | |--------|----------------------------------------------------------|---------------------------------------------------| | S1 | Identification, status, control | `S1F1/F2`, `S1F3/F4`, `S1F11/F12`, `S1F13/F14`, `S1F15-F18`, `S1F19/F20`, `S1F21-F24` | | S2 | Equipment constants, clock, events, commands | `S2F13-F18`, `S2F29-F38`, `S2F41/F42`, `S2F43-F50` | | S3 | Carrier management (E87) | `S3F17/F18`, `S3F19/F20`, `S3F25-F28` | | S5 | Alarms, exception recovery | `S5F1-F8`, `S5F9-F18` | | S6 | Data collection, event reports, spool | `S6F11/F12`, `S6F15/F16`, `S6F19-F22`, `S6F23-F26` | | S7 | Recipe / process program management | `S7F1-F6`, `S7F17-F20`, `S7F23-F26` | | S9 | Protocol-error reports (auto-emitted by equipment) | `S9F1`, `S9F3`, `S9F5`, `S9F7`, `S9F9`, `S9F11`, `S9F13` | | S10 | Terminal services | `S10F1-F6` | | S12 | Wafer maps | (per-stream — chapter [10](10_e5_secs_ii_data_items.md) §6) | | S14 | Generic object services (E39), control jobs (E94) | `S14F1/F2`, `S14F9-F12` | | S16 | Process jobs (E40) | `S16F5-F8`, `S16F9`, `S16F11-F14`, `S16F27/F28` | Where every named message lives in code: [`build/generated/secsgem/gem/messages.hpp`](../build/generated/secsgem/gem/messages.hpp) (after a build) — generated from [`data/messages.yaml`](../data/messages.yaml) by [`tools/gen_messages.py`](../tools/gen_messages.py). Chapter [31](31_spec_as_data_and_codegen.md) walks the codegen. --- ## You've made it through Part 1 You can now: - Explain why SECS/GEM exists, and what each of "SECS", "HSMS", and "GEM" actually refers to. - Name every actor in the fab automation stack and describe who talks to whom. - Recognise every common acronym (SVID, ECID, DVID, CEID, RPTID, ALID, PPID, MDLN, SOFTREV, HCACK, ALCD, OFLACK, …) and the acknowledge bytes that go with each stream. - List the T-timers in four different contexts (HSMS, SECS-I, E84, E30 communication state) and not confuse them. Part 2 of this guide takes one standard at a time, from the ground up: byte-level encoding, wire diagrams, every message, every ack value, the FSMs, and the code that implements each. We start with the foundation everything else stands on — **E5 SECS-II**, the data-item encoding. Next: [→ 10 E5 — SECS-II data items](10_e5_secs_ii_data_items.md)