Expand Glitch operations hub, cabinet authoring, deployment, and RFID support
Operator hub - Introduce Escape Gallery branding and Glitch: the Dark Machine room views - Add cabinet illustrations, Pac-Man marquee/gameplay artwork, and waiting states - Add device feedback panels with RFID readings, input/output states, and stale status - Add logged operator hardware interventions with request deduplication Room and cabinet authoring - Add a visual custom-PCB connection editor with per-cabinet device inventory - Support device IDs, bindings, wiring notes, input polarity, and validation - Add physical-room label/dimension toggles and editable doorway annotations - Preserve doorway changes through undo, save, and revert - Expand cabinet profiles, room layout, and Glitch scenario resources Scenarios and gameplay - Add per-assignment game configuration and runtime feature validation - Add timed test wins and Frogger individual-home objectives - Add the three-cabinet timed/score/Frogger test scenario - Add Cabinet 1 Pac-Man RFID credits, credit sound, and CREDIT 0/1 display - Require physical Start after an accepted scan and prevent duplicate credits Pi hardware and deployment - Add GPIO feedback sampling and a separate multiplexed RFID helper - Validate reader pin ownership and input/output conflicts - Add SSH cabinet startup and Pi desktop-session service support - Add master packaging, site setup, SSH enrollment, and staged cabinet releases - Verify deployment manifests and support explicit activation/status/log commands Documentation and verification - Consolidate the root README around the current architecture and setup workflow - Add the complete master/Pi/RFID export and deployment walkthrough - Document network isolation, credentials, card identification, and rollback - Add PCB, room-editor, feedback, credit, deployment, and controller tests - Isolate protocol tests from designer-edited cabinet configurations Known limitations - RFID helper compilation and physical Pi commissioning remain unverified - Fleet provisioning does not yet configure RFID-only installations completely - Broader Pac-Man tests retain a ghost-capture assertion failure - Staged exports must be rebuilt and checked before deploying runtime 2.3
This commit is contained in:
1 parent
705ec31e0b
commit
c1b2195834
90 files changed
+4969
-456
No files matched your search
@@ -0,0 +1,92 @@
|
||||
@tool
|
||||
class_name CabinetPCBConfig
|
||||
extends Resource
|
||||
|
||||
# This resource describes wiring. It never configures or writes GPIO.
|
||||
@export var connections: Array[PCBConnection] = []
|
||||
|
||||
const TYPES := {
|
||||
"rfid": "RFID reader", "button": "Button / switch", "sensor": "Digital sensor",
|
||||
"led": "LED / lighting driver", "motor": "Motorized switch / motor driver",
|
||||
"relay": "Relay / MOSFET module", "i2c": "I2C peripheral", "other": "Other (document wiring)"
|
||||
}
|
||||
|
||||
static func ports() -> Array[Dictionary]:
|
||||
var result: Array[Dictionary] = []
|
||||
for index in range(8):
|
||||
result.append({"id": "J%d" % (index + 1), "family": "reader", "label": "%d%d%d" % [(index >> 2) & 1, (index >> 1) & 1, index & 1], "pins": "Selector: BCM22=%d, BCM27=%d, BCM17=%d\nShared reset: BCM20. Reader connector contact pinout is not documented." % [(index >> 2) & 1, (index >> 1) & 1, index & 1], "types": ["rfid", "other"], "bcm": -1})
|
||||
result.append({"id": "J9", "family": "host", "label": "Pi ribbon", "pins": "Host GPIO ribbon connector. Confirm pin-1 orientation against the physical board.", "types": [], "bcm": -1})
|
||||
var signals := [5, 6, 13, 19, 26, 21]
|
||||
for index in range(6):
|
||||
result.append({"id": "J%d" % (10 + index), "family": "powered", "label": "BCM%d" % signals[index], "pins": "1 GND (black) | 2 3V3 (red) | 3 signal (yellow)\nBCM%d" % signals[index], "types": ["button", "sensor", "led", "motor", "relay", "other"], "bcm": signals[index]})
|
||||
result.append({"id": "J16", "family": "i2c", "label": "I2C1", "pins": "1 GND (black) | 2 3V3 (red) | 3 SCL (white) | 4 SDA (yellow)", "types": ["i2c", "other"], "bcm": -1})
|
||||
signals = [16, 12, 24, 23, 18, 25]
|
||||
for index in range(6):
|
||||
result.append({"id": "J%d" % (17 + index), "family": "signal", "label": "BCM%d" % signals[index], "pins": "1 GND (black) | 2 signal (red)\nBCM%d - red is signal, not a power supply." % signals[index], "types": ["button", "sensor", "led", "motor", "relay", "other"], "bcm": signals[index]})
|
||||
return result
|
||||
|
||||
static func port(id: String) -> Dictionary:
|
||||
for definition in ports():
|
||||
if definition.id == id:
|
||||
return definition
|
||||
return {}
|
||||
|
||||
func connection(id: String) -> PCBConnection:
|
||||
for item in connections:
|
||||
if item != null and item.port_id == id:
|
||||
return item
|
||||
return null
|
||||
|
||||
func set_connection(item: PCBConnection) -> void:
|
||||
for index in range(connections.size() - 1, -1, -1):
|
||||
if connections[index] != null and connections[index].port_id == item.port_id:
|
||||
connections.remove_at(index)
|
||||
if not item.device_type.is_empty():
|
||||
connections.append(item)
|
||||
emit_changed()
|
||||
|
||||
func issues(hardware: HardwareConfig = null) -> PackedStringArray:
|
||||
var messages := PackedStringArray()
|
||||
var used_ports: Dictionary = {}
|
||||
var used_ids: Dictionary = {}
|
||||
for item in connections:
|
||||
if item == null:
|
||||
messages.append("Empty connection resource.")
|
||||
continue
|
||||
var definition := port(item.port_id)
|
||||
if definition.is_empty() or not definition.types.has(item.device_type):
|
||||
messages.append("%s: unsupported connector/device combination." % item.port_id)
|
||||
if used_ports.has(item.port_id):
|
||||
messages.append("%s: connector is assigned more than once." % item.port_id)
|
||||
used_ports[item.port_id] = true
|
||||
if item.device_id.strip_edges().is_empty():
|
||||
messages.append("%s: enter a device ID." % item.port_id)
|
||||
elif used_ids.has(item.device_id):
|
||||
messages.append("Duplicate device ID: %s." % item.device_id)
|
||||
used_ids[item.device_id] = true
|
||||
if item.device_type in ["led", "motor", "relay"] and not item.binding_id.is_empty():
|
||||
var action: HardwareAction = hardware.get_action(StringName(item.binding_id)) if hardware else null
|
||||
if action == null:
|
||||
messages.append("%s: hardware action '%s' does not exist." % [item.port_id, item.binding_id])
|
||||
elif not definition.is_empty() and action.gpio_pin != definition.bcm:
|
||||
messages.append("%s: action uses BCM%d, but connector uses BCM%d." % [item.port_id, action.gpio_pin, definition.bcm])
|
||||
if hardware:
|
||||
for action in hardware.actions:
|
||||
if action != null and action.gpio_pin in [17, 27, 22, 20]:
|
||||
messages.append("Action '%s' uses reserved PCB selector/reset BCM%d." % [action.action_id, action.gpio_pin])
|
||||
return messages
|
||||
|
||||
func feedback_devices() -> Array[Dictionary]:
|
||||
var result: Array[Dictionary] = []
|
||||
for item in connections:
|
||||
if item == null:
|
||||
continue
|
||||
var kind := ""
|
||||
if item.device_type == "rfid": kind = "rfid"
|
||||
elif item.device_type in ["button", "sensor"]: kind = "input"
|
||||
elif item.device_type in ["led", "motor", "relay"]: kind = "output"
|
||||
else:
|
||||
push_warning("Feedback driver not implemented for %s (%s)" % [item.device_id, item.device_type])
|
||||
continue
|
||||
result.append({"id": item.device_id, "name": item.display_name, "port": item.port_id, "kind": kind, "pull_up": item.input_pull_up})
|
||||
return result
|
||||
Reference in new issue
Block a user