LED Arcade
Un Pong maison sur matrice LED, joué sur enceinte de voiture
L'idée
Je voulais un Pong sans PC et sans écran classique : un Arduino, une bande LED adressable repliée en matrice pour afficher, et une vieille enceinte de voiture branchée sur une broche pour le son. Tout le code est sur la carte, qui démarre toute seule une fois alimentée.
Pong se prête à l’exercice : deux raquettes, une balle, des collisions simples, une logique qui tient dans la mémoire d’un Arduino sans forcer.
On était trois sur le projet. J’ai pris tout le code Arduino, en particulier le point le plus tendu côté timing : le rendu de l’image et la sortie audio tournent sur le même processeur.
Le matériel
On est partis sur du low-tech dès le départ : pas de Raspberry Pi, pas de carte son ni d’écran, seulement ce qui se branche directement sur un Arduino.
- un Arduino pour le cerveau, avec tout le code en C/C++ embarqué
- une bande LED adressable repliée en matrice : c’est l’écran, où s’affichent la balle, les raquettes et le score
- une vieille enceinte de voiture pour l’audio, pilotée par un signal carré sur une broche
Mono-thread et interruptions
C’est ce qui m’a pris le plus de temps, à cause du conflit de timing entre la bande LED et l’audio. L’Arduino est mono-thread : tout ce qui doit tourner en parallèle de la boucle principale passe par une interruption matérielle.
Le rafraîchissement de l’image reste simple. Dans la boucle principale, j’accumule le delta time dans une variable, et un if déclenche le refresh quand le seuil est atteint, avant de remettre la variable à zéro. Il n’y a pas besoin d’interruption pour ça.
L’audio est différent. Chaque note est un signal carré à une fréquence précise sur la broche de l’enceinte. Pour que cette fréquence reste stable, une interruption matérielle inverse l’état de la broche à intervalles réguliers, quoi que fasse la boucle.
Le problème vient du protocole d’envoi des données aux bandes LED adressables, très sensible au timing. Si une interruption tombe au milieu de la trame, le signal est corrompu et les LEDs partent en sucette. Je désactive donc les interruptions pendant le refresh, je pousse les pixels, puis je réarme l’interruption audio sur la note suivante de la séquence.
- la musique du jeu est découpée en notes, chacune jouée entre deux refresh
- le tempo dépend donc du framerate du jeu
- il n’y a pas de désynchro, puisque le son redémarre juste après chaque refresh
Le rendu sonore
Le son n’a pas la richesse d’une vraie carte son, mais c’était voulu : un grain de signal carré qui colle à l’esthétique LED, et un beep à chaque rebond de la balle qui passe juste.