Retourner au sommaire

Le PSG

Basé sur l'article publié dans Quasar CPC numéro 10, Initiation à l'Assembleur, par Zik.

Hum... 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.

Présentation

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.

Les registres

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.

Regs 0 et 1 : période A

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 :

Solfasilasirésilasirédoré ! Frequence_Hz = 62500/Periode_PSG

et

Periode_PSG = 62500/Frequence_Hz

Par exemple, pour connaître la valeur à placer dans ces registres pour entendre le LA international de fréquence 440 Hz, le calcul donne :

Periode_PSG = 62500/440 = 142 = &08E

Vous devez donc mettre &8E dans le registre 0 et &00 dans le registre 1.

Regs 2 et 3 : période B

Ces registres ont la même fonction que les précédents mais pour le canal B (milieu).

Regs 4 et 5 : période C

Idem mais pour la canal C (droit).

Reg 6 : bruit

Entre note et bruit il n'y a qu'un pas ! Ce registre permet de modifier la période du générateur de bruit grace à une valeur codée sur 5 bits (allant de 0 à 31). 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).

Reg 7 : contrôle

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 :

  • bit 0 à 0 = son sur le canal A,
  • bit 1 à 0 = son sur le canal B,
  • bit 2 à 0 = son sur le canal C,
  • bit 3 à 0 = bruit sur le canal A,
  • bit 4 à 0 = bruit sur le canal B,
  • bit 5 à 0 = bruit sur le canal C,
  • bit 6 à 0 = mise en entrée du registre 14 (port A) du PSG, le clavier en fait, si ce bit est mis à 1 le clavier est en sortie,
  • bit 7 = non utilisé (registre 15, port B non câblé).

Reg 8 : volume A

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.

Reg 9 : volume B

Comme reg8 pour le canal B.

Reg 10 : volume C

Comme reg8 mais pour le canal C. Laaaaa !

Regs 11 et 12 : période "hard env"

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). Il existe là aussi des calculs :

Periode_s = 125000 * Valeur_PSG / 16

Valeur_PSG = 125000 * Periode_s / 16

La période étant exprimée en secondes.

Reg 13 : forme "hard env"

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).

Les formes et les ondes Voici la signification de chacun des bits de ce registre :

  • bit 0 : hold,
  • bit 1 : alternate,
  • bit 2 : attack,
  • bit 3 : continue,
  • bits 4 à 7 : inutilisés.

Ce qui nous donne les formes d'ondes suivantes :

Reg 14 : le clavier

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.

Reg 15 : le fantôme

Outch ! 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 cricuit 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…

Quelques remarques

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.

Le PSG sur CPC

Show time! 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
1) sic
2) dans sa variante YM
 
assem/psg.txt · Dernière modification: 2018/09/23 21:59 par ast