— Basé sur l'article publié dans Quasar CPC numéro 10, Initiation à l'Assembleur, par Zik.
Ici, c'est du AY-3-8912, le chip sonore du CPC (de l'Oric1) et de l'Atari ST2) ) que nous allons parler. Comme celui-ci est, sur CPC, intimement lié au PPI, nous parlerons également brièvement de ce-dernier mais vous êtes invités à aller lire la rubrique qui lui est consacrée pour vraiment approfondir la question.
Une fois la théorie assimiliée, vous trouverez des articles détaillant l'exploitation du PSG via les DMA audio de l'ASIC ou expliquant comment jouer des sons SID-voices, un effet bien connu sur Atari ST.
Le PSG du CPC est un générateur de sons carrés sur trois canaux A, B et C. Il permet de contrôler indépendamment la fréquence et le volume sur chacun des canaux et offre également la possibilité de générer du bruit (utile pour faire des percussions ou des bruits de moteurs atroces dans les jeux vidéos).
Sur CPC, les trois canaux sont câblés en stéréo de telle manière à ce que le canal A soit à gauche, le B au milieu et le C à droite. Bien évidemment, sur CPC ancienne génération, on ne peut bénéficier du stéréo qu'en utilisant la sortie audio auxiliaire puisque l'unique haut-parleur intégré est, par définition, mono.
Sa programmation se fait par le biais de registres auxquels on accède au travers du PPI.
Le PSG possède 16 registres dont 15 peuvent être utilisés (c'est comme ça). Ils sont numérotés de 0 à 15, leur description suit.
Ce sont les poids faible et fort de la période sur 12 bits du son sur le canal A (gauche). Cette période ne correspond pas à la période telle qu'on la conçoit en physique, mais sont déduits de l'architecture à 1MHz du PSG. Il y a donc des calculs un peu particuliers pour faire la correspondance :
et
Par exemple, pour connaître la valeur à placer dans ces registres pour entendre le LA international de fréquence 440 Hz, le calcul donne :
Vous devez donc mettre &8E
dans le registre 0 et &00
dans le registre 1.
Notes :
Ces registres ont la même fonction que les précédents mais pour le canal B (milieu).
Idem mais pour la canal C (droit).
Ce registre permet de modifier la période du générateur de bruit grâce à une valeur codée sur 5 bits (allant de 1 à 31, 0 est équivalent à 1). Plus la valeur est élevée, plus le bruit est conséquent (Le petit blond à lunette semble scandalisé par l'aspect totalement vague de cette dernière observation).
Ce registre est très important puisque c'est le registre de contrôle. La valeur qu'il contient définit quels canaux doivent être ouverts ou non, etc… Cette valeur n'a un sens que si on la voit en binaire :
Il détermine le volume du canal A, les 4 bits inférieurs fixent le volume (de 0 à 15). Le bit 4 a une signification particulière, s'il est mis à 1, le PSG utilise alors le générateur de courbes d'enveloppe (voir registres 11 à 13) et le contenu des bits 0 à 3 est ignoré. Les autres bits sont inutilisés.
Comme reg8 pour le canal B.
Ce sont les poids faible et fort sur 16 bits qui déterminent la période de la courbe d'enveloppe (typiquement ce que l'on appelle les sons hard). Pour une enveloppe en dents-de-scie (16 pas) on peut effectuer les calculs suivants :
La période étant exprimée en secondes.
Notes :
Les bis 0 à 3 de ce registre déterminent la forme de la courbe du générateur de courbes d'enveloppe. Les courbes disponibles sont représentées dans le schéma ci-dessous. Les variation correspondent à des variations de volume dont le PSG s'occupe de façon autonome et indéfiniment pour les courbes dont le numéro traduit en binaire aurait le bit 4 à 1 (“continue” actif).
Voici la signification de chacun des bits de ce registre :
Ce qui nous donne les formes d'ondes suivantes :
Sur CPC, le PSG s'occupe également du clavier par le biais de son port A (le registre 14) mais ce sujet est plutôt abordé dans l'article consacré au PPI car c'est intimement lié au fonctionnement de ce dernier, le registre 14 du PSG ne servant que de tampon entrée/sortie.
Il s'agit techniquement du port B, un deuxième registre entrée/sortie 8 bits identique au registre 14… à la différence que celui-ci n'est pas câblé. En effet, sur le AY-3-8912 seul le premier port est présent parmi les broches du circuit intégré. Donc le registre 15 n'est pas valable.
Pour information, sachez qu'il existe aussi le AY-3-8910 qui est exactement le même que notre PSG en interne, mais qui lui a les broches du deuxième port en plus…
Vous aurez pu constater que le registre 6 (bruit) et les registres 11, 12 13 (qui concernent le générateur de courbe d'enveloppe) sont les mêmes pour les trois canaux. C'est-à-dire que si vous mettez du “bruit” sur plusieurs canaux, le niveau de bruit sera le même pour les trois canaux ; si plusieurs canaux ont le bit 4 de leur registre de volume à 1 (on utilise alors une courbe du générateur d'enveloppe ou son hard) et bien les sons émis sur ces canaux auront obligatoirement la même enveloppe et exécutée à la même vitesse. Mais ça n'est pas vraiment contraignant, il suffit de le savoir.
Enfin, les niveaux de volume ne sont pas linéaires mais logarithmiques. C'est à dire que les pas de volume sont d'autant plus faibles que le volume est faible (par exemple la différence de volume entre les niveaux 1 et 2 est plus faible qu'entre les niveaux 14 et 15). Si ça n'a pas réellement d'importance en usage standard, c'est nettement plus ennuyeux lorsque l'on veut utiliser le PSG pour jouer des samples.
Sur notre cher CPC, le PSG est adressé au travers du PPI dont vous trouverez une description détaillée ici.
Le PPI est un composant qui s'occupe de la gestion des périphériques, il minimise le nombre de ports utilisés. Afin de bien comprendre comment accéder au PSG, voici un bref résumé de ses ports et leurs fonctions :
&F4xx
: son in/out et clavier in/out (port de données du PSG)&F5xx
: en lecture seulement sur CPC (sans lien avec le PSG)&F6xx
: en écriture seulement sur CPC (signaux de sélection du PSG)&F7xx
: port de contrôle (permet de placer le port &F4xx
en entrée ou sortie)
Comme vous pouvez le voir, seuls les ports &F4xx
et &F6xx
servent directement pour adresser le PSG. Par le port &F4xx
passent les données, voici les détails du port &F6xx
:
Bit | Description |
---|---|
7 | BDIR (Bus DIRection, signal PSG, voir ci-dessous) |
6 | BC1 (Bus Control 1, signal PSG, voir ci-dessous |
5 | Data write (signal cassette) |
4 | Moteur cassette (signal cassette, 1=marche / 0=arrêt) |
3 | Sélection numéro de ligne clavier (voir PPI) |
2 | Sélection numéro de ligne clavier (voir PPI) |
1 | Sélection numéro de ligne clavier (voir PPI) |
0 | Sélection numéro de ligne clavier (voir PPI) |
Ce qui nous intéresse principalement, ce sont les signaux BDIR et BC1 du PSG :
Fonctions des bits 7 et 6 du port &F6xx | BDIR | BC1 |
---|---|---|
Validation (le PSG valide l'opération précédente) | 0 | 0 |
Read Data (le PSG envoie une valeur à lire sur &F4xx ) | 0 | 1 |
Write Data (le PSG récupère la valeur placée sur &F4xx ) | 1 | 0 |
Select AY register (le PSG sélectionne le numéro de registre placé sur &F4xx ) | 1 | 1 |
Voici donc le protocole à suivre pour écrire dans un registre du PSG :
OUT &F4xx,numéro de registre OUT &F6xx,&C0 ' Lecture du registre par le PSG OUT &F6xx,0 ' Validation de la donnée OUT &F4xx,valeur OUT &F6xx,&80 ' Lecture du data par le PSG OUT &F6xx,0 ' Validation de la donnée
Il existe un vecteur système qui fait tout ça pour vous :
ld a,registre ld c,valeur call &bd34
Et pour terminer voici une routine complète en assembleur pour lire un registre du PSG :
ld a,registre ReadPSG ld b,&f4 out (c),a ld bc,&f6c0 ; %11000000 out (c),c ld bc,&f600 out (c),c ld bc,&f792 out (c),c ; Port &F4xx en lecture ld bc,&f640 ; %01000000 out (c),c ld b,&f4 in a,(c) ld bc,&f782 out (c),c ; Port &F4xx en écriture ; Ici A=valeur du registre ret