Andrea Ricci, cofondatore dell’azienda italiana Reloc, ha portato DOOM su SCINTIX P4, un modulo che mette un ESP32-P4 e un ESP32-C6 nel formato meccanico delle Raspberry Pi CM4 e CM5, e poi ha lasciato che a giocarci fosse Claude Sonnet. Il modello non riceve mai un fotogramma: al suo posto arriva una descrizione testuale di quello che il marine ha davanti, e da l� decide se avanzare, girare, sparare o aprire una porta. Il progetto � interamente open source, firmware e server di controllo compresi.
La scheda � un system-on-module: l’ESP32-P4 � un dual-core RISC-V a 400 MHz con controller MIPI-DSI, acceleratore 2D per i pixel e USB host, mentre la parte radio � delegata all’ESP32-C6 affiancato. DOOM continua a disegnare i propri fotogrammi a 320×200, e l’ingrandimento fino ai 1024×600 del pannello MIPI-DSI � lavoro dell’acceleratore, che tiene il gioco su 30 fotogrammi al secondo stabili. Il collegamento con il modello passa dalla stessa rete Wi-Fi che il C6 porta al P4, dato che il P4 non ha una radio propria.
Un’osservazione testuale al posto dei pixel
L’osservazione che il modello riceve a ogni turno � fatta di poche voci, tutte ricavate da quello che sarebbe visibile sullo schermo. C’� un ventaglio di 51 raggi che misurano la distanza delle pareti lungo il campo visivo, l’elenco dei nemici e degli oggetti effettivamente inquadrati e in linea di vista, ordinati da sinistra a destra, e una mappa ASCII che riporta soltanto le pareti gi� scoperte, esattamente come l’automap del gioco. Si aggiungono due indizi: door_ahead segnala una porta chiusa in vista, blocked dice che l’ultima mossa non ha prodotto avanzamento. Nessuna posizione letta dalla mappa completa, nessun nemico visto attraverso i muri.
Il ventaglio era partito da sette raggi, e con sette raggi l’agente continuava a camminare addosso agli ostacoli: i vani delle porte e gli spigoli dei muri cadevano negli spazi fra un raggio e l’altro, quindi per il modello non esistevano proprio. Con 51 raggi distribuiti su tutto il campo visivo il mondo � diventato leggibile, perch� un raggio molto pi� lungo dei suoi vicini indica un’apertura. Anche door_ahead ha richiesto la stessa rifinitura: punta al centro della porta e ricompare quando una porta si � richiusa, cos� che il modello capisca di dover premere di nuovo il comando di apertura invece di leggere un muro pieno.
Il problema che ha insegnato di pi� era un errore di segno. Le direzioni riportate al modello risultavano invertite rispetto a quanto diceva la documentazione, e l’angolo di orientamento seguiva una convenzione diversa da quella della mappa, con il risultato che l’agente scambiava sistematicamente destra e sinistra. La correzione � consistita nel rendere positivo il verso destro ovunque, per oggetti, pareti e porte, e nel trasformare l’orientamento in una bussola allineata alla mappa orientata a nord: da l� l’agente ha smesso di prendere i muri a testate e ha cominciato a navigare. Anche blocked � stato riscritto, proiettando lo spostamento sull’asse di marcia, cos� che strisciare di lato lungo una parete continui a contare come mancato avanzamento nella direzione in cui si punta.
Il canale in lockstep e il server MCP
Il canale di controllo � un endpoint WebSocket che fa girare il gioco in lockstep: il client invia un’azione, il gioco avanza di qualche tic e restituisce l’osservazione in JSON, poi si ferma di nuovo e aspetta la mossa successiva. Il determinismo � il punto dell’esercizio, perch� il modello ragiona sempre su una scena congelata e coerente, non su un mondo che continua a muoversi mentre lui pensa. � anche il motivo per cui, nel video, il marine si sposta a scatti brevi: fra una mossa e l’altra il gioco � letteralmente in pausa.
Sopra il canale WebSocket c’� un piccolo server MCP che espone la partita come un insieme di strumenti: observe, move_forward, move_back, turn_left, turn_right, strafe_left, strafe_right, fire, use, select_weapon e get_map. Il gioco si registra cos� presso qualunque client compatibile con MCP, Claude Code compreso, e basta puntare il client all’indirizzo IP della scheda perch� il modello possa giocare. Non serve codice di collegamento e non serve leggere lo schermo.
Lo scaler hardware, la radio e le periferiche
L’ingrandimento da 320×200 a 1024×600 era il vero collo di bottiglia del port. Fatto in software costava circa 24 ms per fotogramma fra scalatura e copia, e teneva il gioco intorno ai 20 fotogrammi al secondo. Passando il compito al PPA, l’acceleratore 2D dell’ESP32-P4, l’immagine viene scalata direttamente nel buffer posteriore del pannello MIPI-DSI, che � gi� di propriet� del driver di visualizzazione: presentarlo diventa uno scambio di buffer senza copie aggiuntive, il costo scende a circa 9 ms e il gioco si assesta su 30 fotogrammi al secondo. Oltre quella soglia il limite non � pi� la scalatura, ma il renderer di DOOM e il suo tick di gioco a 35 Hz.
Il passaggio all’acceleratore ha portato con s� un difetto visivo curioso. Il PPA quantizza il fattore di scala a passi di 1/16, quindi il 3,2x richiesto diventa 3,1875x, cio� 1020 pixel di larghezza: le ultime quattro colonne del pannello non vengono mai scritte. Con il doppio buffering le due aree contenevano residui diversi del pattern di avvio, e il bordo destro sfarfallava a ogni scambio di buffer. La soluzione � stata azzerare al nero entrambi i framebuffer una volta sola all’accensione, lasciando una striscia nera di quattro pixel che nessuno nota.
La connettivit� arriva dall’ESP32-C6, raggiunto via ESP-Hosted su un collegamento SDIO a 4 bit. Dal punto di vista del P4 il Wi-Fi si comporta come se fosse locale: al primo avvio la scheda apre una rete propria con SSID SCINTIX-P4-xxxx e un portale di configurazione per ricevere le credenziali, dopodich� si collega come stazione. � lo stesso collegamento che il modello usa per raggiungere il gioco.
L’ingresso umano passa dall’USB host del P4, con tastiere in boot protocol mappate sui tasti classici di DOOM e gamepad HID generici, e le due cose convivono senza conflitti. C’� per� un dettaglio da tenere a mente per chiunque lavori con l’USB host su questo chip: un dispositivo full-speed dietro un hub high-speed richiede un Transaction Translator, che non � implementato nello stack USB host dell’IDF usato qui, quindi un controller full-speed collegato attraverso un hub high-speed non viene enumerato affatto. Collegato direttamente funziona.
Per l’audio � stato agganciato via I2S un codec ES8311 esterno. Il modulo non ha un MCLK dedicato, quindi il codec ricava il clock dal bit clock, e a 22050 Hz con campioni a 16 bit il moltiplicatore interno cade sul rapporto corretto. L’amplificatore a bordo si sblocca attraverso un espansore di I/O PI4IOE invece che da un normale pin GPIO, e DOOM ha di nuovo i suoi effetti sonori, senza la musica.
Il controller senza fili � il pezzo ancora incompleto. Sempre perch� il P4 non ha radio propria, l’host NimBLE gira sul P4 e il C6 fa da controller BLE, con l’HCI trasportato sul canale VHCI dell’ESP-Hosted, e l’obiettivo � accoppiare un 8BitDo Micro senza dongle USB: la scansione BLE gi� funziona attraverso il C6, la parte HID host � il passo successivo. Il resto, port di DOOM, firmware e server MCP, � pubblicato su GitHub nel repository relocsrl/scintix-p4-playing-doom.
#Adessonews seleziona nella rete articoli di particolare interesse.
Se vuoi leggere l’articolo completo clicca sul seguente link



