Mise à jour 2013-07-27
Continuant mes expérimentations avec la génération d'un signal NTSC j'ai appris1 qu'il est possible de simplifier la synchronisation. Premièrement il n'est pas nécessaire de générer des lignes de demi-longueur (9 au total) 3 pulses larges, 3 pulses étroits et 3 pulses larges pour assurer la synchronisation verticale. Il suffit de générer 3 lignes avec des pulses larges (H_LINE-H_SYNC) à toute les 262 lignes. De plus au lieu de compter 262,5 lignes on peut en compter 262. Ça fonctionne tout aussi bien avec cette simplification. Voici le code de ta1_ccr0_isr simplifié.
J'ai aussi modifié les constantes suivantes:
#define FIRST_LINE 30 // première ligne avec affichage
#define LAST_LINE 250 // dernière ligne avec affichage
NOTE 1) référence: Programming 32 bits microcontrollers in C, Exploring PIC32, Lucio Di Jasio, Éd. Newnes.
chapitre 13 page 339.
Génération d'un signal NTSC
Ces derniers jours j'ai expérimenter avec la génération d'un signal vidéo NTSC en noir et blanc sur le launchpad avec le processeur G2553. Le programme démo est entièrement en 'C', pas une seule ligne de code assembleur et ça fonctionne. Générer un signal NTSC sur un petit microcontrôleur est grandement simplifié grâce à la technique du progressive scan et à utilisation judicieuse de 2 périphériques, soit une minuterie en mode PWM pour générer le signal de synchronisation et d'un périphérique SPI pour la sortie du signal vidéo. Quand au circuit électronique il est des plus simple puisqu'il ne nécessite que 2 résistances. Je vais expliquer en détail comment ça fonctionne.
Code source
Standard NTSC
Le standard NTSC est le standard de la télé analogique mis au point dans les années 194x. Au départ c'était un standard pour le noir et blanc mais il a été révisé pour ajouter la couleur quelques années plus tard. Dans notre cas on n'est concerné que par la version noir et blanc. Le site internet le plus intéressant sur la description de ce standard est http://www.ntsc-tv.com. C'est grâce aux informations disponibles sur ce site que j'ai pu me débrouiller pour écrire ce programme.
Le signal vidéo NTSC est plutôt complexe, l'image est créé par 2 balayages (fields) en alternance. Un qui affiche les lignes paires et l'autre les lignes impaires. Chaque field est répété 30 fois par seconde. Chaque field est constitué de 262,5 lignes pour un total de 525 lignes. A cause de la persistance rétinienne on a l'impression que les 525 lignes sont affichées simultanément alors que ce n'est pas le cas. Ce système permet de réduire la bande passante du signal mais ça complique le système de synchronisation de l'image. Heureusement il est possible d'ignorer cette alternance paire/impaire et d'envoyer toujours le même field. On ne dispose alors que de 262 lignes d'affichage qui se répètent 60 fois par seconde. De ces 262 lignes 20 sont réservées pour la synchronisation verticale et donc indisponible pour l'affichage. Il ne reste donc que 240 lignes d'affichage soit la moitié d'un signal VGA.
Le circuit électronique est très simple il suffit d'une résistance de 470 ohm branchée sur P1.2 (sortie PWM) pour la synchronisation et d'une autre résistance de 220 ohm branchée sur la sortie P1.7 (sortie SIMO du SPI) pour le signal vidéo. Il n'y a pas de nuances de gris, c'est vraiment du noir et blanc. Les deux résistances sont jointent ensemble et ce point de jonction est la sortie vidéo qui va à l'entrée NTSC du téléviseur.
Configuration des périphériques
La partie synchronisation du signal est générée par PWM grâce à la minuterie TIMER_A1 configurée en mode comparateur avec comptage UP. TA1CCR0 détermine la période qui correspond à la durée d'une seule ligne vidéo soit 62,5µSec. Le DCO étant programmé pour fonctionner à 16Mhz, la période de cycle du SMCLK est de 62,5nSec, ce qui donne 1000 cycles par ligne. De ces 62,5µSec 10,5µSec sont réservés pour l'impulsion de synchronisation plus les seuils avant et arrière. Il reste donc 52µSec disponible pour l'affichage vidéo. Ce qui complique les choses est la synchronisation verticale. A toute les 262,5 lignes il faut générer une série d'impulsions dont la durée varie. 3 courtes, 3 longues et 3 courtes. Ce travail est accomplie dans la sous-routine d'interruption du compteur de période CCR0, appelée dans le programme ta1_ccr0_isr. le registre CCR1 est configuré pour déterminer la longueur de l'impulsion de synchronisation et CCR2 pour la durée du seuil. lorsque le compteur TA1R arrive à la valeur de CCR2 l'ISR ta1_ccrx_isr est appelée et celle-ci est responsable de l'affichage de l'image qui est contenu dans le tableau frame[56][7]. La résolution de l'image n'est que de 56x56 pixels du à la quantité limitée de mémoire RAM qui n'est que de 512 octets. De ces octets une certaine quantité est réservée pour la pile et les autres variables.
L'astuce intéressante est la façon d'utiliser un périphérique SPI pour sortir les bits vidéos. Le périphérique est configuré en mode SPI maître mais au lieu de brancher la sortie SIMO qui normalement envoie les octets vers un périphérique SPI esclave, on s'en sert comme sortie vidéo. le SPI et cadencé par le signal SMCLK divisé par 13. Ce diviseur et calculé pour que les 56 bits par ligne soient envoyées en un temps inférieur à 52µSec. 52µSec/56/62,5nSec= 14,8. J'ai utilisé 13 comme diviseur pour laissé une marge à la fin de la ligne pour être certain que la routine ISR se termine avant l'interruption de fin de ligne. Plus le diviseur est petit plus les pixels sont comprimés horizontalement. Chaque ligne du tableau frame est répétée 4 fois ce qui donne 4*56=224 lignes ce qui nous laisse aussi une marche verticalement.
A titre de démo je fais simplement défilé un texte au centre de l'écran.
Conclusion
Avec un affichage de 56x56 pixels noir/blanc on ne peut pas faire grand chose mais j'ai une idée sur la façon d'augmenter la mémoire vidéo. Puisqu'on utilise un périphérique SPI pour sortir les bits vidéo il serait simple d'utiliser une mémoire RAM externe à interface SPI comme la Microchip 23K256. Avec 32K de RAM SPI on a de la place pour plusieurs buffer de 5760 octets (192x240pixels). On interface la RAM avec le MCU de manière conventionnel mais on branche la sortie SOMI à l'entrée NTSC à travers une résistance de 220 ohm. Donc il suffit que le MCU fasse la lecture de la RAM SPI pour que les bits soient envoyés sur la sortie vidéo. Avec un tel système on pourrait obtenir une résolution vidéo de 320x240.
quelques liens intéressants sur ce sujet
Une image en FLASH affichée avec une résolution de 192x240.
Standard NTSC.
Exemple du jeux pong fourni par Texas Intruments slaa177.
Aucun commentaire:
Publier un commentaire
Remarque : Seuls les membres de ce blogue sont autorisés à publier des commentaires.