Files
secs-gem/docs/03_vocabulary_and_a_wafers_journey.md
T
raphael 60fa164626 docs: chapters 02 + 03 of the guided tour (Part 1 complete)
02 — The cast of characters: equipment, EAP, MES, fab planner, AMHS,
operator.  Who initiates which conversation, why the equipment is
the passive side of HSMS by convention, how the AMHS handshake is
out-of-band relative to SECS.  Cross-references the relevant
namespace and test files for each actor.

03 — Vocabulary + a wafer's journey: follows one 300 mm wafer
end-to-end through a fab and labels every SECS message and acronym
that fires.  Introduces SVID / DVID / ECID / CEID / RPTID / ALID /
PPID / MDLN / SOFTREV / HCACK / ALCD / OFLACK / CAACK / SMACK / etc.
in context rather than as a list.  Includes one-screen reference
tables for the remaining acknowledge codes, T-timers in all four
contexts (HSMS / SECS-I / E84 / E30 communication state), and a
stream-by-stream summary.

Part 1 (Foundations) of the guided tour is now complete — a reader
who reads chapters 01–03 can describe the protocol stack, identify
the actors, and recognise every acronym they'll meet in Part 2.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 19:35:43 +02:00

593 lines
28 KiB
Markdown

# 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.hpp`](../include/secsgem/gem/e84.hpp)
defines the FSM; [`include/secsgem/gem/e84_timers.hpp`](../include/secsgem/gem/e84_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/carrier_store.hpp`](../include/secsgem/gem/carrier_store.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/process_jobs.hpp`](../include/secsgem/gem/process_jobs.hpp),
[`include/secsgem/gem/control_jobs.hpp`](../include/secsgem/gem/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/report_store.hpp`](../include/secsgem/gem/report_store.hpp),
[`include/secsgem/gem/event_store.hpp`](../include/secsgem/gem/event_store.hpp).
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/host_command_registry.hpp`](../include/secsgem/gem/host_command_registry.hpp)
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/alarm_store.hpp`](../include/secsgem/gem/alarm_store.hpp);
the dispatcher gates emission on the enable list in
[`include/secsgem/gem/alarm_dispatcher.hpp`](../include/secsgem/gem/alarm_dispatcher.hpp).
---
## 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/generate_messages.py`](../tools/generate_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)