Manette Nintendo SNES

Ce tutoriel explique comment lire les messages de la manette Nintendo SNES avec Micropython.

Description

La console Nintendo Super NES (ou SNES) se contrôle avec une manette ayant les caractéristiques suivantes :

  • Une croix directionnelle (haut, bas, droite, gauche)
  • Quatre boutons poussoirs à sa droite (A, B, X et Y)
  • Deux boutons poussoirs en son centre (START et SELECT)
  • Deux boutons poussoirs sur sa tranche avant (L et R)

Elle communique en protocole SPI avec la console qui fonctionne sur le principe d’un maître qui envoie les informations (ici la manette) et d’un esclave qui les reçoit (ici la console remplacée par la carte NUCLEO-WB55).

Le protocole de communication procède de cette façon :

  1. On envoie une pulsation sur la ligne LATCH pour capturer l’état des boutons de la manette.
  2. On récupère ensuite les 16 bits en SPI en utilisant les lignes DATA et CLOCK.
  3. On lit l’état des bits reçus.

Chaque bit correspond à un bouton. On obtient alors le tableau suivant :

Bit 15 Bit 14 Bit 13 Bit 12 Bit 11 Bit 10 Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
"1" "1" "1" "1" R L X A Droite Gauche Bas Haut Start Select Y B

Montage

La connectique de la manette SNES s’organise de la manière suivante :


Schéma de montage manette SNES


Manette SNES ST Nucleo
5V 5V
CLOCK D3
LATCH D2
DATA D4
GND GND

Le code MicroPython

Les scripts présentés ci-après sont disponibles dans la zone de téléchargement.

Etape 1 : Pour réaliser le programme nous devons dans un premier temps importer les bibliothèques permettant l’utilisation des ports et les temporisations. On en profitera également pour associer à chaque bouton la valeur lui correspondant. Pour ce faire on place ce code au début de notre programme :


from pyb import Pin # Gestion des broches
from time import sleep_ms # Pour temporiser

# Constantes pour associer les boutons aux valeurs
BTN_A = 256
BTN_B = 1
BTN_X = 512
BTN_Y = 2
BTN_SELECT = 4
BTN_START = 8
BTN_UP = 16
BTN_DOWN = 32
BTN_LEFT = 64
BTN_RIGHT = 128
BTN_L = 1024
BTN_R = 2048

Etape 2 : Ensuite on initialise les ports en entrée/sortie :

# Mise en entrée/sortie des ports
PIN_LATCH = Pin('D2', Pin.OUT)
PIN_CLOCK = Pin('D3', Pin.OUT)
PIN_DATA = Pin('D4', Pin.IN)

Etape 3 : On crée une fonction qui se chargera de récupérer les données transmises par la manette :

# Fonction d'acquisition des données
def getSnesButtons():
	value = 0
	PIN_LATCH.high()
	PIN_LATCH.low()
	# Lecture de la valeur des 16 bits de données
	for i in range(0, 16, 1):
		value |= PIN_DATA.value() << i
		PIN_CLOCK.high()
		PIN_CLOCK.low()
	# Retour de la valeur
	return ~value

Etape 4 : On crée une fonction qui se chargera d’appeler la boucle précédente et d’afficher les données dans le terminal MicroPython sur l’USB user.

# Fonction d'affichage des données
def boucle():

	oldBtns = -65536

	# Appel de la fonction d'acquisition
	btns = getSnesButtons()

	# Tant que les valeurs sont les mêmes on ne fait rien
	while(oldBtns == btns):
		btns = getSnesButtons()
	oldBtns = btns

	# Affichage en fonction des données récupérées
	if(btns & BTN_A):
		print("A ", end = '')
	else:
		print("- ", end = '')

	if(btns & BTN_B):
		print("B ", end = '')
	else:
		print("- ", end = '')

	if(btns & BTN_X):
		print("X ", end = '')
	else:
		print("- ", end = '')

	if(btns & BTN_Y):
		print("Y ", end = '')
	else:
		print("- ", end = '')

	if(btns & BTN_SELECT):
		print("SELECT ", end = '')
	else:
		print("------ ", end = '')

	if(btns & BTN_START):
		print("START ", end = '')
	else:
		print("----- ", end = '')

	if(btns & BTN_UP):
		print("UP ", end = '')
	else:
		print("-- ", end = '')

	if(btns & BTN_DOWN):
		print("DOWN ", end = '')
	else:
		print("---- ", end = '')

	if(btns & BTN_LEFT):
		print("LEFT ", end = '')
	else:
		print("---- ", end = '')

	if(btns & BTN_RIGHT):
		print("RIGHT ", end = '')
	else:
		print("----- ", end = '')

	if(btns & BTN_L):
		print("L ", end = '')
	else:
		print("- ", end = '')

	if(btns & BTN_R):
		print("R ")
	else:
		print("- ")

	sleep_ms(500) # Temporisation d'une demi-seconde

Etape 5 : Enfin on ajoute une boucle infinie pour que le programme ne s’arrête jamais (enfin, seulement lorsqu’on débranche la NUCLEO-WB55 de son alimentation !).


# Boucle infinie d'acquisition et affichage
while True:
	boucle()

Résultat

Nous pouvons à présent lire les données extraites de la manette SNES sous cette forme, dans PuTTY :


Affichage des données de la manette SNES


Appuyez sur les différents boutons de la manette ainsi que sur la croix directionnelle et vous devriez voir le retour d’informations sur votre écran.