mercredi 24 janvier 2024

jeu FALL sur stm8 gamepad

J'ai ajouté le jeu **FALL** sur la console stm8 gamepad. Comme le jeu TETRIS est bien connu ça se passe d'explication.

vidéo démonstration

Oui je sais, je joue très mal.

jeudi 18 janvier 2024

jeu CADENA sur stm8 gamepad

J'ai ajouté un nouveau jeu sur la console stm8-gamepad. Il s'agit d'une variante du jeu Mastermind qui consiste à deviner la combinaison d'un cadena à 4 chiffres. Le joueur dispose de 12 essais et une parti dure 3 manches.

mercredi 10 janvier 2024

stm8 gamepad v1.1R0

J'ai continué à travaillé sur la console stm8-gamepad

  • Ajout d'un splash screen au démarrage.
  • Ajout du simulateur du jeu de la vie de John H. Conway.

Vidéo de démonstration

Turing complete

Game of life est Turing complete c'est à dire qu'un ordinateur peut-être réalisé dans un univers game of life et ça a été fait. Dans le vidéo suivant réalisé par Nicolas Loizeau on voit un tel ordinateur ordinateur dessiner un carré à l'intérieur d'un cercle. L'auteur ne nous donne pas la dimension de la grille mais elle est énorme. Ce n'est pas le grenre de truc qui peut-être réalisé dans une grille de 32x22 cellules.

Game of life in Game of life

Et puisque game of life est Turing complete ça veut aussi dire qu'on peut créer un univers game of life à l'intérieur d'un autre. Ça aussi a été fait. .
Imaginez on peut répéter ça à n'importe quel niveau de récursion la seule limitation étant le matériel requis. Jusqu'à quel niveau de récursion pourrait-on aller sur un super ordinateur?

jeudi 4 janvier 2024

stm8 gamepad

Il s'agit d'une petite console de jeux rétro fabriquée à partir d'un microcontrôleur STM8S207K8 ou d'une carte NUCLEO-8S207K8 qui utilise le même µC mais inclu un programmeur ST-LINK. J'ai fabriqué 2 prototypes un de chaque modèle.

Prototype 1

Prototype 2

Spécifications

  • Sortie vidéo composite NTSC monochrome
  • Résolution graphique de 200x192 pixels
  • Sortie son générant des tonalités ou du bruit blanc
  • Pad de 6 boutons, croix et boutons A,B.
  • Les programmes de jeux doivent-être compilés avec le projet et réside dans la mémoire flash du µC.

Source du projet

Comme tous mes projets celui-ci est sous licence GPLv3 et le dépôt est sur github.

démo

Pour le moment je n'ai écris qu'un seul jeu appellé SNAKE. Dans la vidéo il manque un élément à droite qui a été coupé par Youtube lors de la conversion du format. Il s'agit d'une barre de chronomètre qui décroit. Lorsque cette barre arrive à zéro il y a un TIME OUT et la parti est terminé. Ce chronomètre est réinitialisé chaque fois que le serpent mange la souris.

SNAKE

règles

  1. Si le serpent entre en collision avec un des murs la parti se termine.
  2. Si le serpent se mort lui-même la parti se termine.
  3. Si le serpent entre en collision avec avec une crotte la parti se termine.
  4. Le serpent doit manger la souris avant que le chronomètre expire.

Contrôle

  • FLÈCHE HAUT Augmente la vitesse du serpent.
  • FLÈCHE BAS Diminue la vitesse du serpent.
  • FLÈCHE GAUCHE Le serpent vire à gauche.
  • FLÈCHE DROITE Le serpent vire à droite.

Pointage

Le nombre de points gagné dépend de la vitesse du serpent. Celle-ci peut-être ajustée entre 1 et 9.
Si la souris est le long d'une barrière le nombre de points est doublé.
Si la souris est dans un coin le nombre de points est triplé.
Pour les vitesses supérieures à 5, le serpent laisse une crotte chaque fois qu'il mange la souris. Ces crottes sont mortelles pour le serpent. La vitesse par défaut est 5.

Vidéo

lundi 1 janvier 2024

stm8 terminal

Puisque je viens de mettre à jour le projet stm8 terminal vers la version 1.0R14. Je vais parler de la génération d'un signal composite au standard NTSC à partir d'un microcontrolleur 8 bits.

Qu'est-ce que le standard NTSC

Ce standard prend son origine aux U.S.A. en 1941 pour la première version noir et blanc et en 1953 pour la version couleurs. NSTC est l'acronyme de National Television System Committee. Il s'agit d'un signal vidéo composite, c'est à dire que toute l'information est contenue dans un seul signal, i.e. synchronisation, luminance et chrominance. Il s'agit d'un signal analogique qui à l'origine était transmit par radiodiffusion.

Générer un signal NTSC monochrome comme pour le projet stm8 terminal est relativement simple et peut se faire même avec le plus petit des microcontrolleurs 8 bits. Dans le passé j'ai réalisé ce genre de signal sur un PIC12F322 pour le projet pong. Comme le projet stm8 terminal ce projet était réalisé entièrement en assembleur.

Comme à l'époque où a été créer ce standard, la télévision était entièrement analogique, l'image était recréé grâce à un tube cathodique par balayage d'un faisceau d'électrons sur une surface phosphorencente appliquée sur la face avant du tube cathodique. Chaque image est constituée de 2 trames entrelacées de 262,5 lignes et le taux de répétition est de 30 images par seconde (60 trames).

Ce qui complique un peu la génération de ce signal est justement cet entrelacement de trames car les trames paires et impaires sont décalées d'une demi-ligne l'une rapport à l'autre.

Le balayage commence en haut à gauche de l'écran en allant vers la droite et se termine en bas à droite.

Balayage entrelace affichage trames.svg
Par <a href="//commons.wikimedia.org/wiki/User:Cdang" title="User:Cdang">Christophe Dang Ngoc Chan</a> — <span class="int-own-work" lang="fr">Travail personnel</span>, CC BY-SA 3.0, Lien

Chaque ligne horizontal de balayage débute par une impulsion de synchronisation qui dure 4,7µSec. La partie visible qui affiche l'information vidéo dure 52µSec.

Une autre complication est la façon dont la synchronisation verticale qui indique le début de chaque trame est générée. Habituellement j'utilise une minuterie avec sortie PWM pour générer le signal de synchronistation. Hors la synchronisation verticale oblige à reprogrammer la minuterie pour réduire la période de la minuterie de moitier lors de la synchronisation verticale. En plus cette synchronisation se fait en 3 étapes. pré-égalisation, synchronisation, post-égalisation. Et chacune de ces phase oblige une reprogrammation de la minuterie et pour finir il faut revenir à la génération pleine ligne à la fin de la synchronisation. Comme les trames sont décalées d'une demi-ligne l'une par rapport à l'autre, le signal est différent entre trame paire et impaire.

Pourquoi NTSC plutôt que VGA

Pourquoi ne pas utiliser le standar VGA au lieu du standard NTSC ce serait tellement plus simple à générer comme signal, signal de synchronisation plus simple, pas de trames entrelacées. En effet c'est plus simple sauf que la fréquence du signal vidéo est plus élevée. en VGA pour générer 640 pixels par ligne il faut une fréquence de 25.1Mhz (pixel clock frequency). Pour le signal VGA on ne dispose que de 25,4µSec visible pour afficher tous les pixels d'une ligne de balayage. La moitié de ce qu'on dispose en NTSC.

Le mcu du stm8 terminal utilise une fréquence système de 20Mhz et le périphérique SPI utilisé pour sérialiser les pixels sur la ligne vidéo fonctionne à 10Mhz ce qui permet d'afficher 496 pixels par ligne de balayage (62 caractères par lignes). En utilisant le standard VGA on ne pourrait qu'afficher 254 pixels soit 31 caractères par ligne.

Ce que j'ai dit jusqu'ici ne concerne que le NTSC noir et blanc. S'il faut ajouter la couleur à ça, c'est d'autant plus complexe même si j'ai réussi à le faire sur un microcontrôleur PIC12F1572 pour mon projet breakout, ce qui sans me vanter m'a demander de faire preuve d'imagination avec l'utilisation des périphériques.

Donc avec un microcontrôleur à une fréquence système de 48Mhz ou plus il est plus intéressant d'utiliser le standard VGA cependant. Mais en bas de cette fréquence vaut mieux s'en tenir au NTSC malgré la difficulté de générer un tel signal.

Difficultés de la génération d'un signal de qualité.

Je m'en tiendrai ici qu'au monochrome. La façon la plus simple que j'ai trouvé de générer un signal NTSC est d'utiliser une minuterie avec périphérique PWM (Output Compare) pour générer le signal de synchronisation et la sortie MOSI d'un périphérique SPI pour sérialiser les pixels vidéo. Évidemment cette méthode utilisant un SPI n'est valide que pour les signaux vidéo monochromes.

La gigue

La précision de la synchronisation du signal vidéo est fondamentale pour obtenir un signal de qualité. Le problème est d'obtenir un délais constant au niveaux des interruptions vidéos. En effet le temps de réponse aux interruptions, ce qu'on appelle la latence, n'est pas constant. Alors que pour les µC PIC cette latence ne varie que d'un cycle pour les STM8 elle peut variée de plusieurs cycles car l'instruction en cours d'exécution au moment ou le signal d'interruption est généré doit-être complétée avant de répondre à l'interruption. Pour les µC PIC le temps d'exécution des instructions est constant sauf pour les sauts et appels de sous-routine qui prennent un cycle de plus. Pour les µC STM8 le temps d'exécution d'une instruction varie entre 1 et 5 cycles. Il y a donc une plus grande variabilité de la latence. Ce qui génère la gigue (jitter en anglais). Dans le cas d'un signal vidéo cette gigue est très visible et embêtante. Heureusement il y a une méthode pour la contrecarrer.

Dans la routine ntsc_video_interrupt qui est une interruption générée par la minuterie TIM1 qui synchronise le signal vidéo. j'utilise le code suivant pour annuler la gigue.


     ld a,TIM1_CNTRL 
    and a,#7 
    push a 
    push #0 
    ldw x,#jitter_cancel 
    addw x,(1,sp)
    _drop 2 
    jp (x)
jitter_cancel:
    nop 
    nop 
    nop 
    nop 
    nop 
    nop 
    nop
 

Le principe de fonctionnement est le suivant. Le compteur de la minuterie demeure régulié même si le temps de latence varie. Donc si au moment d'entrée dans la routine d'interruption on lit la valeur du compteur (il suffit de lire l'octet faible), le compte va varier en fonction de la latence. Si la latence prend 3 cycles supplémentaire le compte aura augmenter de 3. Comme cette latence ne variera jamais plus que de 5 cycles on ne tiens compte que des 3 derniers bits avec l'opératipon and a,#7. On charge le registre X avec l'adresse cible jitter_cancel. On fait un saut indirect en utilsant la valeur dans X indixé par la valeur des 3 bits les moins significatifs du compteur. Si le compte est nul 6 instructions nop seront exécutées avant de débuter l'envoie des pixels vidéo. Chaque nop s'exéctute en un seul cycle. Si le compte est de 7 le saut se fera après les nop. Il s'agit donc de créer un délais supplémentaire variable inversement proprotionnel à la durée de la latence pour annuller la variabilité de celle-ci. Ainsi l'envoie des pixels vidéo débute toujours au même point par rapport au début de la ligne de balayage.

Interférence

Un problème plus difficile à résoudre est celui des interruptions qui se produisent avant le début d'une ligne vidéo et n'ont pas le temps de se terminer avant le début de la ligne vidéo. La révision V1.0R14 de stm8 terminal avait pour but de corriger un tel problème causé par l'interruption de la minuterie TIM4 qui était générée à un intervalle de 1 msec. Cette interruption se produisait donc plusieurs fois pendant la période visible du signal vidéo ce qui produisait un glissement des pixels vidéos sur les lignes affectées par cette interruption. La seule façon que j'ai trouvé de régler ce problème est de simplement ne plus utiliser la minuterie TIM4. Celle-ci ne servait qu'à synchroniser le clignotement du curseur texte. Hors cette opération pouvait tout aussi bien être réalisée en utilisant l'interruption de la minuterie TIM1 qui sert pour générer la synchronisation vidéo. J'ai donc modifier le code dans ce but.

Problèmes non résolus

Il reste 2 problèmes qui interfèrent encore avec le signal vidéo et pour lesquels je n'ai pas de solution. Le premier est l'interruption de lecture du clavier PS/2 et le second est l'interruption sur réception d'un caractère sur le UART.

  1. Sur l'ordinateur pomme I qui utilise le stm8 terminal, si on écris un programme BASIC qui envoie en boucle des caractères au terminal sans arrêt on voit très nettement que la réception de ces caractères crée de l'interférence dans l'affichage vidéo.
  2. Lorsqu'on saisie une ligne au clavier sur le pomme I on voit aussi que le signal vidéo est perturbé mais dans une moindre mesure.