Les manettes de N64 et Gamecube sont d'excellentes manettes qui conviennent
parfaitement à une multitude de jeux sur PC. Comme ce circuit utilise la
class HID du standard USB, il n'est pas nécéssaire d'utiliser des pilotes spécifiques. J'ai
testé sous Linux et Windows.
Caractéristiques:
Supporte les Manettes Gamecube et les tapis de danse (Officiels et Clonés)
Supporte les Manettes Sans-fil pour Gamecube, dont la Nintendo Wavebird (depuis la version 1.2) et les manettes Sans-fil Intec.
Supporte les Manettes de N64 (Officielles et Clonées, incluant la célèbre HORI-mini)
Support du "Rumble Pack" pour la vibration N64 et support de la vibration intégrée des manettes Gamecube. (Depuis la version 2.0)
Support le clavier Gamecube ASCII ASC-1901P0. (Depuis la version 2.9)
Support les Bongos DK
NE SUPPORTE PAS ENCORE: Les cartes mémoires N64.
Pourquoi?
Un de mes amis souhaitait pouvoir jouer à des jeux de Nintendo 64 sur son
PC avec une manette d'origine. J'ai donc mis au point ce convertisseur. Puisque
le protocol des manettes de Gamecube est très similaire, il m'a été facile
de supporter du même coup les manettes de Gamecube.
Étant donné que les manettes de N64 et Gamecube requièrent une alimentation
à 3.3 volts et que le bus USB fournit seulement du 5 volts, il est nécéssaire
d'utiliser un régulateur de voltage. À l'exception du logiciel, c'est la seule
différence (et complexité additionelle) avec mon projet de
Manettes Nes/Snes à USB.
Convertisseur N64 ou Gamecube à USB avec régulateur sur petit circuit imprimé:
Conversion de manette
Exemple de conversion permanente d'une manette N64. Il n'y a pas beaucoup d'espace, mais en coupant un peu de plastique, on arrive à installer le circuit dans le «doigt» central de la manette. Il faut faire attention au passage des fils pour ne pas bloquer le couvercle lors de la fermeture. Pour fixer les fils au bons endroits, j'ai utilisé de la colle chaude.
Photos historiques et/ou de développement
Photos du circuit-imprimé avec régulateur lm1117:
Dessus
Dessous
Correction
Développement avec le nouveau circuit imprimé:
Photos du prototype N64. J'ai utilisé un régulateur lm317:
La N64 Hori-mini et la manette Gamecube blanche avec câble très long fonctionnent!
Le clavier Gamecube ASCII est supporté depuis la version 2.9.
Contributions
Voici des photos que Declan Williams (16 ans!), m'a fait parvenir: Sean Green a construit et utilisé ce circuit pour certains projets:
The Bliss 4-pack
The Bliss Worm
NOTE: Le bliss-4pack n'est pas une version à 4 joueurs du circuit. Il s'ajit seulement d'un HUB USB et 4 circuits
Gamecube/N64 à USB. 2013-02-14: Ludivine a fabriqué un adaptateur basé sur ce projet. Le régulateur de tension est sur la face arrière.
19 juillet 2014 (Samedi) TALENTO m'envoie de Bulgarie ces photos de l'adaptateur GC/N64 à USB qu'il s'est fabriqué.
5 octobre 2014 (Dimanche) Browner87 a utilisé son imprimante 3D pour fabriquer un boîtier contenant
deux circuits GC/N64 à USB et un concentrateur USB. Il a conçu le boîtier pour qu'il s'installe sous son bureau. Commentaires
et photos supplémentaires disponibles sur imgur.
11 octobre 2014 (Samedi) Jonathan m'envoie ces photos de l'adaptateur Gamecube à USB qu'il a réalisé. Il a utilisé un
Atmega8L-8PU, malgré qu'il soit surcadancé dans ce circuit. Cela fonctionne sans problèmes pour lui.
10 mars 2015 (Mardi) Rickey m'a envoyé cette photo d'un adaptateur fabriqué sur une platine d'expérimentation. Il a utilisé un ATMega328P programmé avec le firmware et les fuses pour Atmega168 et tout fonctionne!
25 mars 2015 (Mercredi) Ashley de Queensland, Australie, aide son petit frère Shaun (Agé de 14 ans) à réaliser quelques projets
pour l'intéresser à autre chose que de jouer. Ensemble, ils ont construit un adaptateur SNES/NES à USB ainsi qu'un adaptateur
Gamecube/N64 à USB une même platine d'expérimentation. Les composantes pour la version finale sont en chemin.
Schéma
Voici les schémas: Notes et commentaires:
Certains documents sur internet prétendent que les manettes de Gamecube fonctionnent à 3.43 volts,
d'autres disent que c'est avec un voltage entre 3.3 à 3.8! volts... J'ai vu un vieux message dans
le newsgroup comp.emulators.game-consoles ou l'auteur prétendait que le N64 donne du 5 volts
à ses manettes! (C'est faux). Certains projets abaissent le voltage à 3.3 volts (plus ou moins)
en faisant passer l'alimentation de la manette à travers des diodes. J'ai mesuré 3.36 volts
sur mon N64 alors pour ma part, je choisi d'alimenter les manettes de N64 et Gamecube avec 3.3 volts.
Pour obtenir du 3.3 volts, vous pouvez utiliser un régulateur de voltage fixe tel que le
78M33C ou un régulateur de voltage variable comme le lm317 ou lm1117 (exemple). Si vous utilisez
un régulateur variable comme le lm317, voici un petit outil permettant de trouver une valeur de
résistance R1 adéquate. Un voltage de sortie entre 3.26 à 3.40 volts devrait être parfait. Code de couleur wavebird
On m'a fait savoir qu'à l'intérieur du récepteur de la
manette wavebird, le code de couleur des fils utilisés
entre le connecteur gamecube et le circuit imprimé
semble être contant:
+3.3v: Rouge
Data: Vert
GND: Brun (broche)
GND: Violet (bouclier)
Attention, la couleur des fils varie d'un manufacturier à l'autre. Il est toujours mieux de vérifier pour éviter des catastrophes.
Circuit imprimé
Dessus
Le circuit imprimé est une amélioration du PCB du projet
Manettes Nes/Snes à USB. Sur celui-ci,
il y a maintenant un régulateur et des contacts de reprogrammatin sur la face
inférieure. Voici des vues composées pour connaître le placement des composantes:
Dessous
Le régulateur utilisé est un lm1117mp-adj. Des résistances
de 0 ohms doivent être installés pour sélectionner la source d'alimentation (5 volts d'USB
ou voltage de sortie du régulateur) du Microcontrôleur et de
la sortie d'alimentation du circuit (ce qui va à la manette). Dans notre cas, il faut
installer R5 et R8:
Voici un shéma de câblage pour ce circuit imprimé:
Et voici finalement les fichiers gerbers à partir desquels vous pouvez reproduire ce circuit: multiuse.zip
Étant donné tout les 'vias' sur ce circuit, le fabriquer chez soi peut être difficile ou désagréable.
J'offre donc des circuits fait en usine dans mon magasin
en ligne. Cependant, les circuits que j'offre ne sont pas aussi à jour que dans les gerbers ci-haut. J'en ai
fait produire quelques centaines avec une légère erreur: Le 5 volts d'USB ne se rends pas au régulateur!
Il est donc nécéssaire de souder un petit fil sur la face inférieure du circuit:
Prévention d'un «overflow» 8bit. Corrige le symptôme « Direction gauche ne fonctionne pas » pour certaines manettes de mauvaise qualité.
Correction du délai de détection initiale de manette qui ne fonctionnait pas. L'adaptateur sera donc à nouveau détecté lorsqu'il n'y a pas de manette, comme par le passé.
Correction de la détection USB qui depuis la version 2.0 ne fonctionnait pas lorsqu'aucune manette n'était présente. Il était toutefois possible de changer de type de manette.
Changement du nom de périphérique pour facilier l'identification des adaptateurs version 2.
Support du «Rumble pack» pour N64 et de la fonction vibration des manettes Gamecube! Implémentation standard USB HID PID (Physical Interface Device) ne demandant pas de pilotes spéciaux. Testé sous Linux (fftest) et Window 7 (project 64/DirectX)
Remerciements spéciaux à Sean Green qui m'a généreusement fourni une version du descripteur HID et un fichier main.c l'utilisant pour faire fonctionner la vibration. Sans lui, je n'aurais probablement jamais implémenté le support de la vibration.
La fonctionnalité analogique des leviers L et R sur les manettes Gamecube peut être déactivée si elle vous cause des ennuis et que vous pouvez vous contenter des boutons digitaux s'activant en fin de course. Il suffit de maintenir L et R enfoncés lors du branchement pour déactiver la partie analogique L et R.
L'outil permettant de retoucher les donnés de calibration sous Windows pour restaurer l'état central des axes contrôlés par les leviers L et R est maintenant inclus avec le code source. Voir calibration_fixer/readme.txt pour plus d'information.
Nettoyage du code source:
Nouvelle routine de transmission en assembleur capable de transmettre un nombre variable d'octets vers une manette N64 ou GC à un ryhtme parfait.
Consolidation du code envoi/réception N64 et GC. Puisque le protocol sur le fil est le même, avoir une seule implémentation centralisée était désirable.
Mise à jour du code de réception gamecube d'après le nouvel algorithme pour N64 de la version 1.3. À ma connaissance, ceci ne règle pas de problèmes connus mais augmenterait la fiabilité de la compatiblité.
L'interrogation de la manette est maintenant faite en synchronisme avec la communication USB. Ceci permet d'éviter que la communication USB perturbe la partie critique du code communiquant avec la manette. Avec le matériel que je possède, cette modification corrige les événements de boutons appuyés spontanément d'eux-mêmes qui se produisaient à l'occasion (Une fois pour plusieurs minutes).
Le bon fonctionnement des nouvelles manettes Gamecube blanches avec câble très long (Importées du Japon) est confirmé.
Support plus fiable des manettes HORI-mini. J'ai compris pourquoi certaines manettes HORI-mini pour N64 ne fonctionnaient pas correctement (sauts aléatoires du joystick et événement boutons spontanés). Ceci était dû au rythme de transmission des manettes HORI qui est très différent des manettes Nintendo. (1.5 fois plus lent). J'ai mis en place un nouvel algorithme de réception qui devrait maintenant être très tolérant aux variations. Fonctionne parfaitement avec toutes mes manettes.
Il est maintenant possible de passer d'un manette N64 à Gamecube (ou vis versa) pendant l'utilisation. Auparavant il fallait débrancher et rebrancher le câble USB pour redémarrer l'adaptateur. Il n'est plus nécessaire d'avoir une manette présente pour que l'adaptateur soit détecté par l'ordinateur (USB).
Mise à jour du code USB à vusb-20100715 depuis http://www.obdev.at/products/vusb/index.html.
Ce projet est aussi disponible sur GitHub! Pour suggérer de nouvelles fonctionnalités, signaler un problème ou contribuer au projet,
vous pouvez m'écrire ou utiliser le dépôt GitHub: https://github.com/raphnet/gc_n64_usb
Code source:
Le code source est rendu publique sous la license GPL version 2. Voir
License.txt pour plus d'information. Le projet se compile avec avr-gcc.
Utilisation des fichiers .hex
Les fichiers au format gc_n64_usb-m8-x.x.hex sont pour Atmega8, les fichiers gc_n64_usb-m168-x.x.hex sont
pour l'Atmega168. (Note: On me rapporte qu'il est aussi possible d'utiliser un Amega328p avec le firmware et les fuses pour Atmega168)
Pour que le microcontrôleur fonctionne à la bonne vitesse,
il est essentiel de configurer les 'fuses' correctement. Les valeurs
pour ce projet sont:
Pour Atmega8, utilisez high_byte=0xc9 low_byte=0x9f.
Depuis la version 1.3 du firmware, toutes les manettes HORI-Mini pour N64
devraient fonctionner correctement grâce à un nouvel algorithme plus
tolérant aux différences de timing. Une explicaiton technique
du problème et de la solution est donnée ci-dessous.
Il est connu que les manettes HORI-mini pour N64 ne se comportent
pas bien avec bien des adaptateurs. Après un premier test
avec le mien, je croyais qu'elles fonctionnait correctement... Jusqu'à
ce qu'on me contacte à propos de problèmes. Lorsqu'on effectuait
un déplacement du joystick, la position de celui-ci semblait
sauter d'un point à l'autre de manière imprévisible rendant
le jeu difficile, voir impossible. J'ai donc réessayé mon adaptateur
avec plusieurs de mes adaptateurs sur différents ordinateurs. J'ai
fini par trouver une combinaison ayant le même problème et me suis
penché sur le problème.
Dès que j'ai regardé les signaux avec un oscilloscope, j'ai remarqué
quelque chose d'inhabituel. La vitesse de transmission de la manette
HORI semblait être plus basse et très différente de ce à quoi je
m'attendais. Les images ci-dessous montre que les ratios haut/bas
pour chauque bit est très différent entre l'interrogation (provenant
de l'adaptateur) et la réponse (provenant de la manette). La
manette HORI répond à 66% de la vitesse 'normale' d'une manette N64:
Vous savez peut-être déjà que l'encodage des bits est fait comme suit. Normalement (
du moins, avec les manettes Nintendo), un bit 0 est représenté par un niveau bas de
1μS suivi d'un niveau haut de 3μS. Et l'inverse pour un bit 1 (1μS bas, 3μS haut).
(Consultez les références pour plus d'informations).
Le code d'origine de cet adaptateur attend simplement le front descendant initial
et prend un échantillon 2μS plus tard. Si les conditions sont idéales (ou normales),
la valeur de l'échantillon (1 ou 0) représentera le bit transmit. Le délai de
2μS positionne le moment de l'échantillonage en plein centre du bit, ce
qui est l'endroit le plus fiable sauf si la manette transmet à
un rythme trop différent duquel nous nous attendons...
Vous pouvez voir à droite ce qu'il advient de la position d'échantillonage
lorsque nous communiquons avec une manette HORI. L'échantillon est pris très
près du front montant. Cela fonctionne toujours en théorie. Mais c'est une
mauvaise idée car il ne reste plus de tolérance et le moindre ralentissement
supplémentaire risque de causer des problèmes. Et la vraie vie nous
l'a prouvé comme d'habitude.
Vitesse normale
Bon: Échantillon centré.
Vitesse Hori
Mauvais: Échantillon près du front.
Pourquoi échantillonner près du front est un problème:
L'échantillonnage ne peut pas être fait exactement après 2μS.. Le
moment exact dépends de la synchronisation entre la boucle de détection
et le front. En d'autre termes, l'échantillon sera parfois prit un peu plus
tôt ou pendant le front montant.
il se pourrait que la fréquence d'horloge interne à la manette HORI soit
différente d'une unité à l'autre.. Cela veut dire que certaines manettes
pourraient transmettre encore plus lentement (ce qui nuit) ou plus rapidement (ce qui aide).
La lenteur du front montant pourrait aussi nuire. À quel moment exactement le MCU
verra-t-il un niveau logique 1? Ceci fait partie des spécifications, mais il pourrait
y avoir de petites différences d'une unité à l'autre ou encore avec les nouvelles
versions de la puce (Le Atmega8a, par exemple). Et si l'utilisation d'un câble
d'extension augmente la capacité, la situation empirera.
Le correctif: (depuis la version 1.3)
J'ai conclu qu'il me fallait un meilleur algorithme de réception. Plutôt que de
simplement retarder l'échantillon ou modifier le code pour que la position
d'échantillonage se déplace automatiquement, j'ai opté pour un algorithme
complètement différent qui pourra tolérer une transmission plus rapide ou
sinon beaucoup plus lente:
Mesurer le temps passé à attendre un front montant (temps bas)
Mesurer le temps passé à attendre le front descendant (temps haut)
Comparer le temps bas vs. temps haut. Si le temps passé bas est plus
long, il s'agit d'un bit 0, sinon il s'agit d'un bit 1.
Repeat
Le chronométrage est fait en assembleur pour la vitesse et la prédictabilité
(pas d'optimisations du compilateur C dans le chemin, etc). À 16Mhz, chaque cycle
d'échantillonage prends environ 312.5nS. Un niveau maintenu pendant 1μS mesurera
3 cycles et un niveau maintenu pendant 3μS mesurera 9 cycles. Si la vitesse
de transmission est plus lente, ces mesures seront plus élevées mais la relation
du temps passé bas vs. le temps passé haut sera toujours valide.
Synchro-usb
Depuis la version 1.4, le "polling" de la manette est maintenant synchronisé avec
la communication USB afin d'aider à maintenir la stabilité du rythme des
impulsions lors de la communication avec les manettes. En théorie, cela
augmente la compatiblité et fiabilité du circuit. L'explication technique suit.
Pause dans la transmission
Rappelons que l'implémentation USB est entièrement logicielle. Le MCU peut donc
se faire interrompre à tout moment pour s'occuper de communication USB. Il arrive
donc que ces interruptions se produisent en pleine communication avec
la manette et empêche le maintient d'un rythme constant. La partie marquée en rouge sur la photo à droite montre que la
transmission (trace d'en haut) s'est arrêté pendant la communication usb (trace
d'en bas).
Lorsque qu'une interruption USB survient au mauvais moment, la trame gamecube/n64
est potentiellement corrompue et doit être ignorée si c'est le cas. En transmission,
nous comptons sur la manette pour détecter l'erreur et ne pas répondre. Il y a donc
un 'timeout' à la réception qui suit. Si au contraire, la corruption survient
pendant la réception, nous manquerons des transitions et le nombre de bits reçus
sera inférieur à ce qui était attendu.
Malgré la théorie énoncée ci-haut, il semblerait qu'il arrive très rarement
(une fois dans plusieurs minutes) qu'il se produise une erreur non
détectée. En effet, quelques utilisateurs prétendaient avoir vécu des cas
où des boutons semblaient à l'occasion s'appuyer d'eux mêmes un bref instant.
J'ai donc décidé d'enlever ce risque en trouvant une solution aux interruptions USB
survenant au mauvais moment. Et avec les nouvelles manettes blanches pour Gamecube,
la seule manette avec laquelle j'ai pu oberver ce problème, ce comportement très rare
semble maintenant avoir complètement disparu.
Déactiver les interruptions pendant cette phase critique n'est pas possible
en raison du pilote USB qui nous empêche de pouvoir les déactiver assez longtemps
pour être utile. En revanche, les interruptions sont espacés d'environ 900μS
ce qui nous laisse le temps d'interroger la manette, pourvu que nous
puissions nous enligner pour le faire pendant la période d'inactivité.
J'ai pensé à une solution logicielle très simple. La logique contrôlant
le rythme auquel la manette est interrogée reste la même. Mais juste
avant l'interrogation, le MCU est mis en veille (mode IDLE). En ce mode,
l'exécution normale s'arrête jusqu'à ce qu'une interruption survienne. À la reprise
de l'exécution, le simple fait que l'exécution ait reprit nous donne le feu vert pour
effectuer l'interrogation de la manette qui est faite après un court délais
permettant d'éviter les autres interruptions qui suivent parfois de près l'interruption
initiale.
Avec la mise en place de cette solution, nous obtenons un "polling" de la manette
de jeu sagement placé dans l'espace de 900μS disponible entre les interruptions
tel que ci-dessous:
GC/N64 et USB
Correctif de calibration
Leviers L/R non corrigés
Leviers L/R corrigés
Le fait que les leviers analogiques L et R des manettes Gamecube n'aient pas une position de repos centrale cause
souvent des problèmes. Plusieurs jeux voient l'axe correspondant comme actif dès que la valeur reçue s'éloigne
suffisamment du centre. Lorsqu'on configure les boutons, les leviers L et R sont souvent pris en compte immédiatement
et nuisent à la configuration (Lorsqu'elle n'est pas complètement empêchée.).
Pour palier à ce problème, exécutez l'outil suivant après avoir effectué la calibration
de la manette avec les outils standard de Windows. Lorsque cet outil s'exécute, il trouve les
adaptateurs raphnet GC/N64 à USB et retouche les donnés de calibration en vigueur. La calibration
des axes liées aux leviers sont modifiés afin que dorénavant ils apparaissent centrés lorsqu'au
repos.
Depuis la version 2.9, le clavier pour Gamecube est supporté et peut être utilisé sous Windows et Linux. Notez
que je n'ai pu tester que le modèle ASC-1901P0 de ASCII. Ce clavier comporte un câble à deux connecteurs. Le
connecteur gris correspond à la fonction clavier, le violet à la fonction manette. Pour utiliser les deux simultanément,
sur un PC, il faut deux adaptateurs.
Voici quelques photos du clavier:
L'extérieur
L'extérieur
L'extérieur
L'intérieur
L'intérieur
L'intérieur
Journal et détails techniques
23 Novembre 2013
Pour débuter, j'ai regardé quelle était la réponse à la commande 0x00 (GET ID).
L'adaptateur envoi déjà cette commande pour détecter le type de manette (N64 ou GC?)
raccordé à l'adaptateur, alors il est logique d'effectuer la détection du clavier
à cet endroit. J'ai décodé la réponse manuellement (plus facile que pour la
communication de Dreamcast avec laquelle j'ai récemment travaillé, ce qui fait du bien.)
0000 1000 0010 0000 0000 0000 : 0x082000
Note: Seuls les 16 premiers bits sont l'identification. Donc en fait, 0x0820.
J'ai ensuite consulté de la documentation pour gamecube[1] pour constater que
nous avions le même code d'identification. Donc tout allait bien. J'ai continué
en essayant d'interroger le clavier avec la même commande que pour obtenir
l'état d'une manette (0x400300) mais il n'y avait pas de réponse. Normal car
ce n'est pas la bonne commande. Retour à la documentation qui m'a alors apprise
qu'il faut utiliser 0x540000. Et cela fonctionne évidemment.
Le clavier retourne 64 bits (8 octets):
Premier mot 32 bit
Deuxième mot:
Bit 31: Errstat
Bits 31-24: Code de touche (1)
Bit 30: Errlatch
Bits 29-28: ?
Bits 27-24: Semble être un compteur 4 bits
Bits 23-0: ?
Bits 23-16: Code de touche (2)
Bits 15-8: Code de touche (3)
Bits 7: ?
Bits 6-4: Peut-être une sorte de checksum. Variable en fonction des touches et combinaisons.
Bits 3-0: Semble être un compteur 4 bits
Le clavier gamecube supporte un maximum de 3 touches simultanées alors j'ai construit
le descripteur de rapport d'état HID en conséquence. Habituellement les touches
«spéciales» comme CTRL, SHIFT et ALT sont transmises via des bits dédiés
dans le rapport d'état HID, mais comme le clavier Gamecube n'a pas ce concept et
rapporte l'état de ces touches comme les autres (par codes de touches 8 bits),
je pense simplement faire la même chose. Sinon j'aurai à «émulter» fonctionnalité.
Contrairement au clavier de Dreamcast, le clavier gamecube ne semple pas
utiliser les codes de touches standard figurant dans le manuel des tables
HID (USB HID Usage Tables, section 10 : Keyboard/Keypad page [0x07]).
J'ai donc créé le tableau de conversion suivant. Puisqu'il s'agit d'un clavier de style Japonais,
il y a quelques touches inhabituelles et pour que certaines produisent le caractère voulu,
il faut évidemment configurer son PC pour utiliser un clavier Japonais.
Je ne saurais être tenu responsable pour les dommages
que l'utilisation des informations ou la mise en œuvre des instructions présentées
sur cette page pourrait causer à votre équipement,
à vous-même ou à autrui. Aussi, je ne donne aucune garantie quant
à l'exactitude des informations et à leur fonctionnement.