A3: S12 Wafer Maps stream (E5 §13)
Adds the core map-management messages: setup send/request (F1-F4), transmit inquire/grant (F5/F6), data send in row format (F7/F8), and the one-way error report (F19). Reference points (REFP) are an external struct shared across F1 and F4. The alternative data encodings — array format (F9/F10), coordinate format (F11/F12), and the corresponding request pairs (F13-F18) — are scope-deferred. They're mechanical YAML edits once a tool needs them; the codec already handles the underlying BINARY/list shapes. Three new ack enums: MapSetupAck (SDACK), MapTransmitGrant (GRANT), MapDataAck (MAPER). No state machine yet — maps are a data exchange, not a lifecycle. secsgem-py ships S12F0-F19 as a single block; this commit covers the practically-used subset and matches their wire shapes where they overlap. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -657,3 +657,83 @@ TEST_CASE("S16F27 / S16F28 CJobCommand round-trip") {
|
||||
CHECK(parsed->ctljobcmd == "CJSTART");
|
||||
CHECK(*ack_byte(s16f28_cj_command_ack(HostCmdAck::Accept)) == 0);
|
||||
}
|
||||
|
||||
// ---- S12 Wafer Maps (E5 §13) -------------------------------------------
|
||||
|
||||
TEST_CASE("S12F1 / S12F2 Map Setup Data Send round-trip") {
|
||||
std::vector<ReferencePoint> refp = {{0, 0}, {100, 200}};
|
||||
std::vector<std::string> dutms = {"01", "02"};
|
||||
auto m = s12f1_map_setup_send("WAFER-1", /*idtyp=*/0, /*fnloc=*/0,
|
||||
/*ffrot=*/0, /*orloc=*/2, /*rpsel=*/2,
|
||||
refp, dutms);
|
||||
CHECK(m.stream == 12);
|
||||
CHECK(m.function == 1);
|
||||
CHECK(m.reply_expected);
|
||||
|
||||
auto parsed = parse_s12f1(m);
|
||||
REQUIRE(parsed.has_value());
|
||||
CHECK(parsed->mid == "WAFER-1");
|
||||
CHECK(parsed->idtyp == 0);
|
||||
CHECK(parsed->orloc == 2);
|
||||
REQUIRE(parsed->refp.size() == 2);
|
||||
CHECK(parsed->refp[1].x == 100);
|
||||
CHECK(parsed->refp[1].y == 200);
|
||||
REQUIRE(parsed->dutms.size() == 2);
|
||||
CHECK(parsed->dutms[0] == "01");
|
||||
|
||||
CHECK(*ack_byte(s12f2_map_setup_ack(MapSetupAck::Accept)) == 0);
|
||||
CHECK(*ack_byte(s12f2_map_setup_ack(MapSetupAck::Error)) == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("S12F3 / S12F4 Map Setup Data Request round-trip") {
|
||||
auto req = s12f3_map_setup_request("WAFER-1", /*idtyp=*/0, /*mapft=*/0);
|
||||
auto parsed = parse_s12f3(req);
|
||||
REQUIRE(parsed.has_value());
|
||||
CHECK(parsed->mid == "WAFER-1");
|
||||
CHECK(parsed->mapft == 0);
|
||||
|
||||
std::vector<ReferencePoint> refp = {{0, 0}};
|
||||
auto reply = s12f4_map_setup_reply("WAFER-1", /*idtyp=*/0, /*fnloc=*/270,
|
||||
/*orloc=*/0, /*rpsel=*/1, refp,
|
||||
{"R1C1"}, /*xdies=*/4, /*ydies=*/4);
|
||||
auto preply = parse_s12f4(reply);
|
||||
REQUIRE(preply.has_value());
|
||||
CHECK(preply->fnloc == 270);
|
||||
CHECK(preply->xdies == 4);
|
||||
CHECK(preply->ydies == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("S12F5 / S12F6 Map Transmit Inquire / Grant round-trip") {
|
||||
auto m = s12f5_map_transmit_inquire("WAFER-1", /*idtyp=*/0,
|
||||
/*mapft=*/0, /*mlcl=*/256);
|
||||
auto parsed = parse_s12f5(m);
|
||||
REQUIRE(parsed.has_value());
|
||||
CHECK(parsed->mlcl == 256);
|
||||
|
||||
CHECK(*ack_byte(s12f6_map_transmit_grant(MapTransmitGrant::Granted)) == 0);
|
||||
CHECK(*ack_byte(s12f6_map_transmit_grant(MapTransmitGrant::BusyTryAgain)) == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("S12F7 / S12F8 Map Data Send (row format) round-trip") {
|
||||
std::vector<std::string> rows = {
|
||||
std::string({0x01, 0x02, 0x03}),
|
||||
std::string({0x04, 0x05, 0x06}),
|
||||
};
|
||||
auto m = s12f7_map_data_send_row("WAFER-1", /*idtyp=*/0, rows);
|
||||
auto parsed = parse_s12f7(m);
|
||||
REQUIRE(parsed.has_value());
|
||||
REQUIRE(parsed->rows.size() == 2);
|
||||
CHECK(parsed->rows[0].size() == 3);
|
||||
CHECK(static_cast<uint8_t>(parsed->rows[1][2]) == 0x06);
|
||||
|
||||
CHECK(*ack_byte(s12f8_map_data_send_row_ack(MapDataAck::Accept)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("S12F19 Map Error Send round-trip") {
|
||||
auto m = s12f19_map_error_send(/*mapercd=*/2, "unrecognized MID");
|
||||
auto parsed = parse_s12f19(m);
|
||||
REQUIRE(parsed.has_value());
|
||||
CHECK(parsed->mapercd == 2);
|
||||
CHECK(parsed->errtext == "unrecognized MID");
|
||||
CHECK_FALSE(m.reply_expected);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user