Gamoover

[move]Vous aimez le couscous-boulettes, le chorizo, la Force 4, et la mimolette ? Alors soyez les bienvenus sur Gamoover ! [/move]

Menu

Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.

Voir les contributions Menu

Sujets - NoisilySilent

#1
Oh le beau titre racoleur, putassier et menteur ! :D

Enfin, menteur qu'à moitié en fait.
Je ne possède effectivement pas d'écran plasma de 29 pouces au format 4/3.  Si ça existait, ça se saurait.
Mais avec un peu de bidouille, on peut faire un truc qui y ressemble, en cachant la misère.

C'est le projet que je me suis lancé il y a environ deux ans et que je propose de découvrir dans ce billet.

Tout a commencé lorsque j'ai acheté ma première mobo Naomi, un rêve de gosse qui se réalisait.
J'avais dans l'idée de me construire une borne 29 pouces avec écran pivotant (en essayant de copier le mécanisme de l'Egret 2 par exemple).
Pour cela j'avais acquis un écran Shanghai Novel avec platine Sanwa. Déjà, j'avais galéré à en trouver un, ensuite je trouvais que c'était cher, plus pas pratique à trouver près de chez soi et enfin, c'était du matériel vieillissant qui tomberait nécessairement en panne un jour ou l'autre, sans compter les défauts d'image (convergence et parallélisme vraiment perfectibles...)

Du coup, l'idée a commencé à germer d'utiliser un écran plus moderne, moins cher, plus facile à trouver et plus léger aussi : la TV LCD ou plasma !
Elle répondait au moins à ces critères-ci :

  • pas de souci de convergence ni de parallélisme
  • facile à trouver d'occasion près de chez moi
  • facile à manipuler.

Mais bien sûr, il y avait l'inconvénient du form factor.
Je ne voulais pas d'un écran 16/9 dans ma borne, je voulais un 4/3.
C'est à ce moment-là que je me suis dit : "Facile ! Y'a qu'à mettre la télé verticalement et trouver un truc de traitement du signal pour pivoter l'image ! Ca doit forcément se trouver sur AliExpress !"

Oui, ben non en fait, ce genre d'appareil ça existe mais ça coûte une véritable fortune, et je n'étais même pas convaincu que le résultat me conviendrait car idéalement, je voulais du pixelperfect.

Et j'ai commencé alors à regarder si je ne pouvais pas programmer une telle machine. Je suis informaticien, j'ai donc eu une approche très naïve du genre : "Facile ! Y'a qu'à invertir lignes et colonnes !"

Mais quel boulet, quand j'y pense !  ::)

Bref, après quelques heures passées sur le web j'en viens à la triste conclusion qu'il va falloir faire ça avec de l'électronique...  :-\
En effet, sur plusieurs forums je peux lire des question de traitement du signal, et je vois des réponses qui parlent de FPGA...

FPGA ? késako ?

Bon, j'imagine qu'il y en a plein ici qui savent ce que c'est depuis des lustres, mais pour les autres, je vais tenter d'expliquer.
Grosso modo, un FPGA est un circuit qui permet de simuler d'autres circuits !
A l'aide d'un langage spécifique (Hardware Description Language), on conçoit des circuits intégrés (on déclare les entrées, les sorties et on décrit comment le tout fonctionne), et on les relies entre eux à l'aide de fils/bus virtuels, on branche les horloges etc.
Ensuite, on injecte ça dans le FPGA et il simule le circuit en question !

Bon, c'est vraiment très grosse maille comme explication, mais en gros c'est ça.

J'ai donc commencé à chercher un FPGA qui était doté d'au moins une entrée vidéo et une sortie vidéo... et surtout abordable  :D
Après plusieurs recherches, un modèle semble ce préciser : L'Atlys de chez Digilent.
C'est un FPGA de la famille Spartan 6 de chez Xilinx.
Cerise sur le gâteau, sur la page web du constructeur, on peut télécharger un exemple qui lit depuis une entrée HDMI, stocke dans un framebuffer en RAM, et lit depuis ce framebuffer vers la sortie HDMI !
Retour de l'informaticien débile : "Facile, y'aura qu'à intervertir les lignes et les colonnes" ...
150€ sur la baie, banco !



Je vous passe les moultes péripéties rencontrées :

  • Installation sur Centos 6 d'un kit de dev Xilinx pour Spartan 6 avec prise en charge du HDMI... (j'en ai bien chié)
  • Apprentissage du VHDL et du Verilog (deux HDL différent, l'un employé aux USA, l'autre partout ailleurs)
  • Apprentissage de l'utilisation du SDK Xilinx (autant vous dire que quand vous bossez pas dans le milieu, google n'est pas le meilleur des amis pour ces produits ultra propriétaires...)
  • Récupération de specs du Spartan 6 (la lecture la plus indigeste de toute ma vie !)
  • Limitations matérielles qui m'ont obligé à me faire des noeuds au cerveau et trouver des hacks.

En fin de compte, plus d'un an après l'achat du FPGA, je commence à entrevoir une solution implantable dans l'Atlys, compte tenu de ces specs un peu en carton.
Pour ceux que ne se sont pas encore endormi, ceux qui ne se sont pas encore barré et que ça intéresse, voilà comment ça fonctionne :

J'utilise donc la démo trouvée sur le site de Digilent pour l'Atlys (HDMI Demo) et je l'ai modifié comme suit :
Le flux vidéo arrive donc sur le HDMI in. Au lieu d'écrire directement toute la frame dans la RAM (code d'origine de la démo), je la stock par bandes dans une mémoire spéciale appelée Block RAM (BRAM pour les intimes), ultra rapide car on ne peut pas traiter en RAM, ça serait beaucoup mais alors beaucoup trop lent de faire pivoter l'image de la RAM à la RAM.

Pourquoi par bandes et pas la frame toute entière ?
Ben parce que je n'ai pas assez de BRAM sur l'Atlys pour stocker toute la frame :D Donc pas le choix.
L'Atlys propose au total une grosse centaine de BRAM de 18Kbits chacun.
Une ligne de 640 pixels codés chacun sur 2 octets fait 10Kbits => donc obligation d'utiliser un BRAM par ligne => on ne peut pas stocker les 480 lignes de la frame, il faut traiter par bandes.

Comme le flux vidéo arrive constamment, il faut de plus deux tampons de BRAM : un dans lequel on écrit depuis le HDMI, et un dont on lit pour écrire en RAM.
Pendant qu'on écrit dans le premier, on transfère en RAM depuis le second...

j'utilise donc 2 tampons de 32 BRAM chacun. On va donc procéder 32 lignes par 32 lignes.

Pour résumer :
Pendant qu'on écrit "en lignes" 32 lignes du flux entrant dans un tampon de BRAM, on lit "en colonnes" les 32 lignes précédemment stockées dans l'autre tampon à destination de la RAM, puis on intervertit les deux tampons et on traite les 32 prochaines lignes etc etc.

De l'autre côté, on a un module qui lit la RAM et affiche sur la sortie HDMI (code non modifié ou presque).

La grosse contrainte technique  (et le "hack" dont je suis le plus fier) est que pour des raisons d'efficacité d'écriture en RAM (on parle de "burst"), il faut écrire des quantité bien spécifiques de bits à partir d'adresses elles aussi bien spécifiques ! On parle "d'alignement de la donnée", c'est du à la conception même de la RAM.
Bien sûr, il fallait que là encore ça ne passe pas comme une lettre à la poste... :D
Sur l'Atlys, l'écriture en RAM se fait à des adresses multiples de 128 octets...
Pour ceux que je n'ai pas encore perdu, je vous fait le topo :
j'écris en RAM une bande de 32 pixels de large... chacun codé sur 2 octets ... donc 64 octets au total. je ne peux donc pas aligner mes bandes les unes à côté des autres :'( Il y a un "trou" de 64 octets avant le prochain alignement RAM qui me permet de faire une écriture "burst"
La solution "hack" : la machine veut que j'écrive 128 octets alors que je n'ai que 64 à lui fournir ? Grand bien lui fasse ! Je vais doubler chaque pixel !! Je rajoute une horloge à deux fois le pixel clock, et pour l'écriture en RAM j'utilise cette horloge. De fait chaque pixel est écrit deux fois et ma bande fait maintenant 128 comme exigé par la RAM de l'Atlys.

Mais alors, vous allez me dire "OK, mais maintenant ton image elle est totalement déformée !"
Oui, dans le framebuffer effectivement, elle est déformée. (la frame d'origine qui faisait 640x480 est donc pivotée/étirée dans le framebuffer : 960x640)
Mais on va ruser aussi dans la partie sortie HDMI. Au lieu d'écrire tous les pixels lu depuis la RAM vers la sortie HDMI, on va plutôt utiliser 1 seul BRAM pour stocker un pixel sur deux pendant qu'on affiche des pixels noirs sur la partie gauche de la télé jusqu'à la moitié de l'écran, ensuite on pop pixel par pixel depuis le BRAM et magie ! On se retrouve bien avec une image 480x640 sur la télé :D

Janvier 2019, j'ai un premier POC concluant :


Le truc bien c'est qu'avec un petit bouton, on peut aussi "annuler la rotation" et donc passer facilement du mode YOKO ou mode TATE, sans rien faire de plus qu'agir sur un slide switch !  ^-

Je vous mets une vidéo récente de ma borne encore en cours de construction.
J'ai fait un châssis en acier (profilé U) sur lequel j'ai commencé à plaque l'habillage.



Tout n'est pas fini niveau traitement vidéo, car en sortie je lis à framerate constant alors qu'en entrée le framerate varie. Donc ça crée parfois une désynchro et une sorte de tearing de l'image (on voit apparaître les bandes, ça fait une sorte d'escalier... cf video de HOTD2, on arrive à le voir à certains moments).

Sur la deuxième vidéo, on peut voir le test du passage en mode TATE en agissant sur le slide switch.

Quand tout sera bien fonctionnel, je mettrai à disposition le code pour le Atlys, si d'aventure certains veulent s'amuser à faire un truc similaire.

N.B : j'ai chopé cet écran plasma sur LBC à 20 euros à 2 kilomètres de chez moi, car il a un défaut sur sa partie gauche. En fait, tout écran dont seule une moitié de l'écran est exploitable convient. En d'autres mots, c'est ultra facile de trouver un écran de remplacement pour une bouchée de pain.
Dernière remarque, c'est un plasma HD Ready, sa dalle fait donc 768 lignes. je suis en mode "pixel perfect", la TV Samsung le propose : l'image utilise 640 pixel, c'est du pixel pour pixel, d'où les bandes noires à gauche et à droite de l'image de 64 pixel chacune..
La diagonale fait bien 29 pouces.