Add Pac-Man power-on flow and document Odin integration
- Add a four-second arcade-style boot sequence followed by the Character / Nickname introduction. - Separate cabinet power-on from RFID credit and player Start. - Add operator Power on control and cabinet power-state reporting. - Prevent repeated power commands from restarting boot or gameplay. - Ignore RFID scans received before the cabinet is ready. - Add power-state, RFID, controller, and GPIO feedback regression tests. - Expand the master walkthrough with export, packaging, file transfer, fresh-Pi setup, RFID compilation, and end-to-end testing instructions. - Correct tester hardware documentation: BCM23/J20 drives an LED; physical buttons connect through a separate I2C1 input board. - Document operator-triggered power-on as the current test workflow and retain the temporary 2.4 configuration compatibility notes. - Record successful physical testing of power-on, RFID credit, and player Start. - Add an Odin integration README describing the proposed Rust/NATS bridge, shared messages, Flutter GM interface, autopilot sequencing, hardware ownership, and Starfish SSH-management role. - Define migration milestones and information needed from the framework owner; link the integration guide from the root README. Validation: 69 controller tests, 10 GPIO tests, Pac-Man power/RFID checks, managed-cabinet lifecycle checks, and visual screen inspection.
This commit is contained in:
1 parent
c1b2195834
commit
41ef12f954
27 files changed
+577
-48
No files matched your search
@@ -1,5 +1,5 @@
|
||||
extends Node
|
||||
const VERSION := "arcade-cabinet-2.3"
|
||||
const VERSION := "arcade-cabinet-2.4"
|
||||
var cabinet_id := "cabinet_01"
|
||||
var database: ProjectDatabase = preload("res://data/project_database.tres")
|
||||
var cabinet: CabinetProfile
|
||||
@@ -55,12 +55,12 @@ func _ready() -> void:
|
||||
func poll() -> void:
|
||||
if busy or executing: return
|
||||
busy = true
|
||||
if game != null and phase == "ready" and game.has_method("receive_device_feedback") and HardwareManager.real_gpio and HardwareManager.client != null:
|
||||
if game != null and phase in ["ready", "powered_off", "booting"] and game.has_method("receive_device_feedback") and HardwareManager.real_gpio and HardwareManager.client != null:
|
||||
game.receive_device_feedback(HardwareManager.client.get_feedback())
|
||||
var sent := reports.duplicate(true)
|
||||
var result: Dictionary = await connection.post("/cabinet/poll", {
|
||||
"cabinet": cabinet_id, "protocol": 2, "boot": boot, "version": VERSION,
|
||||
"features": ["assignment_config_v1", "device_feedback_v1", "rfid_credit_v1"],
|
||||
"features": ["assignment_config_v1", "device_feedback_v1", "rfid_credit_v1", "pacman_power_v1"],
|
||||
"feedback": HardwareManager.client.get_feedback() if HardwareManager.real_gpio and HardwareManager.client != null else {},
|
||||
"gpio": "real" if HardwareManager.real_gpio else "simulation", "reports": sent,
|
||||
})
|
||||
@@ -127,14 +127,19 @@ func execute(command: Dictionary) -> void:
|
||||
if str(definition.game_id) == "missile_command": game.set("relative_mouse_aim", true)
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if str(definition.game_id) in ["missile_command", "tempest"] else Input.MOUSE_MODE_VISIBLE
|
||||
add_child(game)
|
||||
if game.has_signal("power_state_changed"):
|
||||
game.power_state_changed.connect(_power_changed)
|
||||
game.configure(command.get("game_config", {}).duplicate(true))
|
||||
if game.has_method("receive_device_feedback") and HardwareManager.client != null:
|
||||
game.receive_device_feedback(HardwareManager.client.get_feedback())
|
||||
game.game_started.connect(func(): event("started"))
|
||||
game.game_won.connect(func(): event("won"))
|
||||
game.game_lost.connect(func(): event("lost"))
|
||||
phase = "ready"
|
||||
acknowledge(command, true, definition.display_name + " loaded and ready")
|
||||
phase = {"off": "powered_off", "booting": "booting", "ready": "ready"}.get(str(game.get("power_state")), "ready") if game.has_signal("power_state_changed") else "ready"
|
||||
acknowledge(command, true, definition.display_name + " loaded: " + phase)
|
||||
"power_on":
|
||||
var ok: bool = game != null and phase == "powered_off" and game.has_method("power_on") and game.power_on()
|
||||
acknowledge(command, ok, "Power-on requested" if ok else "Cabinet is not powered off")
|
||||
"start":
|
||||
var ok: bool = game != null and phase == "ready" and game.start_game()
|
||||
acknowledge(command, ok, "Game started" if ok else "Cabinet was not ready")
|
||||
@@ -158,3 +163,8 @@ func execute(command: Dictionary) -> void:
|
||||
acknowledge(command, ok, "GPIO bridge accepted pulse; delivery unconfirmed" if ok else "GPIO failed or acknowledgement lost; inspect cabinet")
|
||||
_:
|
||||
acknowledge(command, false, "Unsupported command")
|
||||
|
||||
func _power_changed(state: String) -> void:
|
||||
if state == "off": return # prepare acknowledgement establishes this state
|
||||
phase = "booting" if state == "booting" else "ready"
|
||||
event("power_booting" if state == "booting" else "power_ready")
|
||||
Reference in new issue
Block a user