Quantcast
Channel: PICatout
Viewing all 192 articles
Browse latest View live

LPC810, partie 8, pong

$
0
0

Pour mettre en pratique ce que j'ai appris sur le LPC810 j'ai réalisé un jeux PONG sur le LPC810. Le montage est si simple qu'il tiens sur une carde perma-proto 1/4.

Montage

schématique

Liste du matériel

  • 1 MCU LPC810M021FN28, U1
  • 1 carte perma-proto 1/4.Un produit de bonne qualité. Peut-être soudé sur les 2 faces, pratique pour les SMD 0805 (voir photo du prototype ci-haut).
  • 2 jack RCA phono, J1 jaune (vidéo), J2 blanc (audio)
  • 1 LED rouge 3mm, D2
  • 2 résistances 120 ohm 1/8 watt, R3,R8.
  • 1 résistance 620 ohm 1/8 watt, R1.
  • 1 résistance 680 ohm 1/8 watt, R2.
  • 2 résistances 1Kohm 1/8 watt, R6, R7.
  • 2 résistance 10Kohm 1/8 watt, R4, R5.
  • 2 potentiomètre 10Kohm linéaire, P1, P2.
  • 1 condensateur céramique 2,2nF, C1
  • 4 condensateurs céramique 100nF, C2,C3,C4,C5. J'ai utilisé un format SMD 0805 car c'est juste de la bonne dimension pour être souder entre deux rangés adjacentes.
  • 1 diode schottkey 1N6263, D1
  • 2 boutons momentanés SW1, SW3.
  • 1 porte pile avec commutateur pour 2 piles AA ou AAA
  • 1 barrette de pin header 100mil.

Démo

Description du programme

L'ensemble du projet LPCXpresso est sur github sous licence GPLv3. Vous pouvez télécharger le fichier zip et l'importer dans l'IDE LPCXpresso. Le projet doit être compilé avec l'option -O2 sinon il n'y a pas suffisamment d'espace flash.

Le jeux est contrôlé par des potentiomètres de 10Kohm. Chaque joueur en a un. Le pointage apparait en haut de l'écran. Le gagnant est celui qui atteint 21 points le premier. La balle est collée sur la raquette du joueur qui a le service. Le joueur doit déplacer sa raquette pour lancer la balle. La direction que prend la balle est tirée au hasard. ATTENTION! au démarrage le potentiomètre que est branché sur la broche 5 doit-être en position Vdd. S'il est en position Vss le bootloader va entrer en mode programmation au lieu de démarrer le jeux.

Le fichier hardware.c Initialise les périphériques utilisés. Le PLL permet de monter la fréquence à 30Mhz. Le SCT génère le signal vidéo et le signal audio. Le MRT est utilisé pour les délais. Le comparateur analogique est utilisé pour lire les potentiomètres. Il y a deux gestionnaires d'interruption d'utilisé, l'un pour la génération audio MRT_IRQHandler() situé dans hardware.c, l'autre pour la génération des signaux vidéo SCT_IRQHandler() situé dans tvout.c.

Le fichier tvout.c génère un signal NTSC composite monochrome. La résolution est de 64x56 pixels et le video_buffer occupe 448 octets RAM des 1024 disponible. Comme toujours j'utilise un PWM pour la synchronisation et un périphérique SPI pour sérialiser les pixels vidéo.

Les potentiomètres qui contrôle les raquettes des joueurs sont branchés sur les 2 entrées du comparateur analogique ACMP_I1 et ACMP_I2. Ce comparateur contient une référence de voltage programmable sur 32 niveaux. J'ai donc décidé d'utiliser cette référence en conjonction avec le comparateur pour créer un convertisseur A/N à 5 bits. Le convertisseur est de type SAR (Successive Approximation Register). Pour son fonctionnement voir la routine read_pot() dans le fichier hardware.c. La routine fait une division binaire de L'intervalle pour obtenir un résultat en 5 comparaisons.

Tout le code est écris en 'C' et peut-être adapter facilement à un autre MCU LPC. Le fichier tvout.c est particulièrement utile pour l'utilisation dans d'autres projets avec sortie vidéo NTSC. Il peut être adapté facilement au standard PAL en modifiant les constantes dans le fichier tvout.h


LPC810, partie 9, comparateur analogique

$
0
0

Dans cet article je discute du comparateur analogique. Celui-ci possède une référence de voltage programmable sur 32 niveaux. Dans le démo j'utilise cette référence programmable pour créer un convertisseur analogique/numérique avec un résolution de 5 bits. Un potentiomètre est lu et sert à contrôler l'intensité d'une LED par PWM.

Le LPC810 possède 2 entrées analogiques, ACMP0_1 et ACMP0_2. L'entrée ACMP0_1 peut-être reliée à la broche 8 et l'entrée ACMP0_2 peut-être reliée à la broche 5. Cette liaison se fait par le registre LPC_SWM->PINENABLE0. Chacune de ces 2 entrées peut-être connectée soit à l'entrée positive, soit la négative du comparateur. C'est le registre LPC_CMP->CTRL qui sert à effectuer les branchements sur les entrées du comparateur. Dans le démo ci-bas, l'entrée ACMP0_1 est branchée sur l'entrée positive du comparateur. L'entrée négative du comparateur est reliée à la sortie de la référence de voltage programmable (Voltage ladder).

Un comparateur analogique fonctionne de la façon suivante, Il y a 2 entrées, une positive et l'autre négative. Lorsque le voltage sur l'entrée positive est plus élevé que celui sur l'entrée négative la sortie du comparateur est à 1 sinon elle est à 0. Le symbole d'un comparateur est le suivant:

Mais si les 2 voltages sont égaux? Les entrées des comparateurs sont conçues pour avoir ce qu'on appelle de l’hystérésis. L'idée est la suivante, supposons que l'entrée négative est branchée sur une référence de voltage fixe et que la positive est branchée sur un signal variable. Sitôt que l'entrée positive dépasse l'entrée négative la sortie du comparateur passe à 1. Mais à cause du bruit s'il n'y avait pas d'hystérésis la sortie pourrait commuter rapidement entre 0 et 1. Mais l'hystéris fait que l'entrée positive doit redescendre d'une certaine valeur avant que la sortie ne repasse à zéro. Le comparateur du LPC810 a une hystérésis programmable avec 4 valeurs possibles, 0mV, 5mV, 10mV et 20mV. Ces valeurs représentent la variation minimale de voltage entre les 2 entrées pour que la sortie commute à nouveau. Donc si on programme 20mV et que le voltage sur l'entrée positive monte jusqu'à ce que la sortie passe à 1. Ce voltage doit redescendre d'au moins 20mV avant que la sortie ne repasse à zéro.

Si le signal d'entrée est bruyant on utilise une hystérésis forte, s'il est propre on utilise une hystérésis faible. Dans le démo j'ai programmé l'hystérésis à 20mV. Mon calcul est le suivant, le potentiomètre est alimenté à 3 volts, 3/32 donne 94mV donc on peut utiliser l'hystérésis maximale sans perdre de résolution sur le potentiomètre tout en maximisant l'immunité aux interférences.

Un convertisseur A/N improvisé

Le LPC810 n'a pas de convertisseur A/N mais on peut en improviser un en utilisant le comparateur et la référence de voltage programmable. Ce convertisseur n'a qu'un résolution de 5 bits étant limité par la résolution du voltage ladder.

Voici comment fonctionne le convertisseur à 5 bits. On commence par programmer le voltage ladderà sa valeur médiane. Si la sortie du comparateur est à 1 c'est que le voltage sur l'entrée positive est supérieur à 1,5volt, sinon il est inférieur à cette valeur. On change la valeur de référence en fonction de l'état de sortie du comparateur. Si la sortie est à 1, on programme le voltage ladderà la position médiane entre 1,5 volts et 3 volts. Si la sortie du comparateur est à 0 on programme le voltage ladderà la position médiane entre 0 volt et 1,5 volts. On vérifie encore la sortie du comparateur et chaque fois que c'est à 1 on augmente le voltage du voltage ladder de la moitié de l'intervalle restant. Par cette division binaire de l'intervalle restant on obtient un résultat avec 5 comparaisons. Cette technique de conversion A/N s'appelle convertisseur à approximations successives. C'est le type de convertisseur le plus souvent utilisé sur les MCU. Le nombre de comparaisons nécessaires est le nombre de bits de résolution du convertisseur, 8,10 ou 12. Ce type de conversion est plus rapide que le sigma-delta ou les convertisseurs à pente.

Schématique du montage

Code source du démo

utilisation des resssources

  • La LED est branchée sur PIO0_2 (broche 4).
  • Le bras mobile du potentiomètre est branché sur PIO0_0 (broche 8) qui est utilisé en mode analogique.
  • Le canal 1 du MRT (Multi Rate Timer) est utilisé pour générer une interruption 50 fois par seconde.
  • Le module SCT est utilisé pour générer un signal PWM dont le rapport cyclique est contrôlé par le potentiomètre. La sortie COUT0 du SCT est reliée à PIO0_2 et contrôle l'intensité de la LED.
  • Le comparateur analogique avec la référence programmable est utilisé comme convertisseur A/N à 5 bits pour lire le potentiomètre.

C'est la fonction read_pot() qui implémente le convertisseur A/N. La fonction main() ne fait qu'initialiser les périphériques.

Une fois que le module SCT est configuré pour généner un signal PWM à une fréquence 200 hertz le MCU est mis en mode sleep. En mode sleep le PWM continu à fonctionner mais le core M0+ est arrêté. Le module MRT est utilisé pour générer une interruption 50 fois par seconde. Le gestionnaire d'interruption MRT_IRQHandler() fait une lecture du potientiomètre et ajuste le rapport cyclique du PWM en fonction de cette lecture. A la sortie du gestionnaire d'interruption le MCU retourne en mode sleep. l'instruction __WFI() est une macro pour l'instruction en assembleur wfiWait For Interrupt. Cette instruction suspend le core jusqu'à ce qu'il y est une interruption.


Liens vers les articles précédents:

  1. Introduction au LPC810 (ARM M0+)
  2. LPC810, partie 2, anatomie
  3. LPC810, création d'un projet
  4. LPC810, partie 4, programmation
  5. LPC810, partie 5, module SCT et PWM
  6. LPC810, partie 8, pong

Il était une fois CP/M

$
0
0

Cet article concerne l'histoire de l'informatique, j'y parle du premier système d'exploitation pour micro-ordinateur, CP/M l'ancêtre du DOS.

Les premiers ordinateurs n'avaient pas de système d'exploitation et n'était pas interactif. Un programme était écris pour être ensuite chargé dans la machine pour exécution. Il y avait alors sur ces machines ce qui s’appelait un programme de contrôle. Ce programme présentait à l'opérateur une interface de commande simple lui permettant de charger et d'exécuter les programmes et autres tâches nécessaire à l'utilisation de la machine. Les programmes étaient souvent exécutés en lot (batch). Les programmes étaient fournis à la machine sous forme de ruban ou de carte perforées. Lors de mon premier cours d’informatique je programmais sur des cartes perforées dans un langage appelé FORTRAN IV. On écrivait notre programme à la main sur papier pour ensuite transcrire ce code source sur des cartes en utilisant la machine appelée justement perforatrice1. Nous déposions nos cartes sur une étagère à l'entrée d'un local et le lendemain nous allions chercher le résultat sur la même étagère. Tous les programmes étaient exécutés en lot pendant la nuit. Ce n'était pas vraiment excitant l'informatique à cette époque. C'était au début des années 70.

Control Program for Micro-computer

Donc au milieu des années 70 une compagnie du Nouveau Mexique appelée Micro Instrumentation and Telemetry Systems, MITS a mis sur le marché le premier micro-ordinateur digne de ce nom, l'Altair 8800 qui utilisait le microprocesseur 8080 d'Intel. C'est alors que Gary Kildall a décidé de créer un programme de contrôle pour cet ordinateur en s'inspirant de ce qui se faisait à l'époque sur les Mainframe. Sa femme et lui on créé une compagnie qui s’appelait Digital Research Inc dans le but de vendre ce programme baptisé CP/M, signifiant Control Programm for Micro-computer.

BIOS

C'est alors que de nombreuses compagnies sont entrées dans le marché des micro-ordinateurs en utilisant l'Intel 8080 ou sa version amélioré le Z80 fabriqué par Zilog2. Gary Kildall devait donc porté son CP/M pour ces différentes machines. C'est alors qu'il eu l'idée de séparer les fonctions de bases qui contrôle directement le matériel des fonctions de plus haut niveau. De cette façon pour modifier CP/M pour qu'il fonctionne sur une autre machine il n'avait qu'à modifier ces fonctions de bases sans avoir à modifier le reste du système. Il baptisa cette couche d'abstraction matérielle le Basic Input Output System, BIOS.

Évolution

MS-DOS de Microsoft a été directement inspiré par CP/M. Lorsque les PC sont sortie sur le marché avec leur processeur 16 bits Intel 8088 et 8086. Microsoft a créé MS-DOS en s'inspirant de CP/M. Les fabriquants de PC fournissaient la couche d'abstraction matérielle qui avait été standardisé en conservant le nom que lui avait donné Kildall, BIOS. Le BIOS interfaçait avec le DOS via les fonctions de l'interruption 13hex. Les applications interfaçaient DOS via les fonctions de l'interruption 21hex.

Système d'exploitation

Les interfaces utilisateurs graphiques apparues avec Apple MacIntosh et Microsoft Windows ont mis fin à l'évolution de CP/M et MS-DOS, DR-DOS3 et IBM-DOS4, quoiqu'il existe encore une version libre appelée FREEDOS ainsi que l'émulateur DOSBOX qui tournent sur les systèmes d'exploitation modernes tel que Linux,OSX et Windows.

Aujourd’hui tous les systèmes d'exploitations utilisent cette structure en multi-couches appelée en anglais software stack. Au plus bas niveau il y a la couche d'abstraction matérielle Hardware Abstraction LayerHAL. Au dessus de celle-ci il y a les pilotes de périphériques. Ensuite viens le noyaux du système d'exploitation qui dans un système moderne est le seul qui est autorisé à parler au pilotes de périphériques. Finalement il y a les applications dans la couche utilisateur. Chaque couche présente une interface standardisée à la couche supérieur ce qui a 2 avantages. Premièrement ça rends le système plus facilement transportable sur une autre machine ou architecture car les couches supérieures ne sont pas affectées par les détails de l'implémentation des couches inférieures et n'ont donc pas besoin d'être modifiées chaque fois qu'une couche inférieure l'est. Deuxièment ça facilite la création de programmes ou pilotes, le programmeur n'ayant qu'à connaître les fonctions de l'interface sans se soucier des détails sous-jacents.


1) Il existait aussi des trieuses de cartes pour venir au secours de ceux qui avaient le maleur de laissé tomber leur boite à chaussure remplie de cartes perforées. C'est peut-être pour ça qu'à l'époque il y avait une instruction par carte et que chaque carte débutait avec un numéro de ligne.
2) Zilog existe encore et est maintenant un fabriquant de Microcontroleurs. Ils vendent encore une version CMOS du Z80. L'original était en technologie NMOS. Le Z80 avec le 6502 est un des rares micro-processeur de cette époque qui est encore fabriqué.
3) Pour répondre à la concurrence de Microsoft, Digital Reseach inc. avait développé son propre système DR-DOS avant que la compagnie soit rachetée par Novell.
4) IBM-DOS était développé par Microsoft et c'est d'ailleurs ce contrat avec IBM qui a fait la fortune initiale de Microsoft.

Qu'est-ce qu'un système d'exploitation

$
0
0

Cet article fait suite à mon article précédent sur CP/M. J'y explique brièvement le pourquoi et le comment des systèmes d'exploitations.

Qu'est-ce qu'un système d'exploitation?

Un système d'exploitation a pour but de faciliter l'utilisation de l'ordinateur et d'assurer la sécurité et l'intégrité des données. Disons qu'au départ l'objectif principal était le premier car au début les besoins en sécurité n'était pas aussi évidents. Donc CP/M et DOS n'offrait aucune sécurité mais offrait des services aux programmeurs d'applications en leur offrant des interfaces simplifiées et standardisées pour l'accès au matériel, c'est à dire clavier, disques, imprimantes, vidéo, etc. Malgré tout il était possible de contourner ces services pour accéder directement au matériel. Ainsi à l'époque de MS-DOS beaucoup de programmeurs de jeux manipulaient directement la mémoire vidéo pour améliorer la vitesse d'exécution. l'interface standard pour la vidéo passait par l'interruption 10hex et son contournement provoquait souvent des problèmes de compatibilité mais les fabricants de jeux considéraient que c'était le prix à payer pour obtenir des jeux plus dynamiques.

Plus tard est apparu la nécessité de limiter les accès aux informations mais aussi au matériel. Les nouveaux microprocesseurs ont des gestionnaires de mémoires qui permettent de diviser celle-ci en segments et de contrôler l'accès à ces segments. Ainsi les PIC32MX de Microchip permettent de fragmenter aussi bien la mémoire flash que la mémoire des données en segment noyau et utilisateur. Mais les processeurs d'usage général comme on retrouvent dans nos ordinateurs ont des gestionnaires encore plus sophistiqués qui permettent d'attribuer des segments mémoire pour chaque application.

Structure d'un système moderne

Comme on le voie sur ce diagramme l'espace mémoire est divisé en espace noyau et en espace utilisateur. Les applications elle-même sont isolées les unes des autres dans leur propre segments de mémoire les protégeant les unes des autres. De cette façon une application défectueuse ou malicieuse ne peut pas affecter le noyau ou une autre application.

La question alors est comment les applications font-elles pour accéder aux périphériques? Elle doivent obligatoirement passer par une interface spéciale basée sur une interruption et qu'on appelle syscall. En fait les programmeurs d'applications n'ont pas la plupart du temps à se soucier de cette interface car les systèmes modernes offrent des couches d'abstractions supplémentaire sous formes de librairies. Sous windows 32bits ces librairies s'appellent user32.dll, kernel32.dll, gdi32.dll, mmedia32.dll, etc (les versions 64 bits existent aussi). Les interfaces (liste de fonctions) pour ces librairies sont documentées et utilisées par les programmeurs, simplifiant grandement la vie de ceux-ci. Chaque application charge dans son espace mémoire une copie des DLL qu'elle utilise.

Le niveau d'abstraction augmente continuellement, alors que dans les années 90 les programmeurs utilisaient directement l'API32 (Application Programming Interface) de Windows, c'est de plus en plus rare aujourd'hui avec les framework comme .NET1, METRO, QT, etc. Ces framework ne sont rien d'autre que des librairies logicielles construites par dessus les API de bases mais qui simplifient encore plus le travail des programmeurs d'applications. Le nombre de couches logicielles augmente sans cesse, mais la complexité des systèmes modernes exigent de plus en plus d'abstraction pour réduire le temps de développement et donc le coût des logiciels.


1) En ce qui concerne .NET il s'agit plus que d'un ensemble de librairies. Les applications sont compilées pour une machine virtuelle qui exécute du bytecode. Mais cette machine doit-elle utiliser l'API32 ou l'API64 pour s'interfacer avec le système d'exploitation.

Du nouveau chez Microchip

$
0
0

Je viens de découvrir que Microchip offre maintenant de nouveaux PIC32MX1xx/2xx. Lorsque j'ai créé mon projet VPC-32 il y a de ça un peut plus d'un an, le plus gros PIC32MX disponible en format PDIP-28 était le PIC32MX150F128B qui dispose de 128Ko de flash et 32Ko de RAM. Le PIC32MX170F256B qui est aussi en format PDIP-28 double les quantités de mémoire, soit 256Ko de flash et 64Ko de RAM. Pour le reste les 2 MCU sont identiques donc je n'ai qu'à remplacé le PIC32MX150F128B dans le VPC-32 par le nouveau PIC32MX170F256B pour doubler les quantités de mémoire.

GCC, optimisation et portabilité

$
0
0

Je travaille présentement sur un projet utilisant un atMega328 avec Atmel studio 6. Dans cet article je discute des différents niveaux d'optimisation utilisés par GCC (GNU C Compiler) ainsi que des problèmes de portabilité causé par la taille variable du type de donnée int.

Optimisation

Atmel studio comme MPLABX utilise GCC comme compilateur et par défaut lorsqu'on cré un projet le niveau d'optimisation est -Os. À ce niveau GCC tente de créer le code le plus compacte possible. Comme les microcontrôleurs sont en général limités en mémoire, c'est logique d'utiliser cette optimisation. Donc lors de la première compilation de mon projet j'ai obtenu un code très compact. Malheureusement ça ne fonctionnais pas. Le projet utilise une routine de service d'interruption qui doit avoir un délais de réponse rapide (low latency), mais le résultat n'était pas à la hauteur des besoins. Après avoir examiner le code assembleur (fichier *.lss dans output files du projet), j'ai été sidéré de voir la quantité de code utilisé en préambule par la routine. C'est là que j'ai décidé de changer le niveau d'optimisation pour -O3 dans les propriétés du projet. Là ça fonctionnais mais la taille du code avait grossis plus que je ne l'aurais cru!

Voici la taille du code généré pour mon projet (non complété) selon les différents niveaux d'optimisation:

  • -O0 Ne compile pas! affiche l'avertissement suivant:
    Warning 8 #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
  • -O1
    Program Memory Usage : 4652 bytes 14,2 % Full
    Data Memory Usage : 1604 bytes 78,3 % Full
  • -O2
    Program Memory Usage : 4728 bytes 14,4 % Full
    Data Memory Usage : 1604 bytes 78,3 % Full
  • -O3
    Program Memory Usage : 5514 bytes 16,8 % Full
    Data Memory Usage : 1604 bytes 78,3 % Full
  • -Os
    Program Memory Usage : 4434 bytes 13,5 % Full
    Data Memory Usage : 1604 bytes 78,3 % Full

Donc lorsqu'on veut optimiser pour la taille on utilise -Os. Mais si on veut optimiser pour la vitesse on utilise -O1,-O2 ou -O3. Chacun prenant plus d'espace de code. Cette augmentation du code est du au fait que pour augmenter la vitesse le compilateur transforme certaines sous-routines en inline même si on ne l'a pas spécifié et aussi il peut dérouler certaines boucles simple avec petit nombre de répétitions.

Au final j'ai décidé de compiler mon projet en -O2, à ce niveau le délais de l'ISR étant suffisamment cours.

Portabilité du code

Comme je ne veut pas avoir à réécrire le même code chaque fois que je change de microcontrôleur je réutilise des fichiers d'autres projets. C'était le cas pour ce projet. Mais lorsque j'ai adapter le code j'ai eu quelques problèmes du au fait que le type de donnée int peut varié de taille d'une plateforme à l'autre. Ainsi sur PIC32MX un int est 32 bits mais sur un AVR il est de 16 bits.

Pour rendre un code source 'C' plus portable il est préférable de préciser la taille des entiers utilisés et dans ce but d'inclure #include <stdint.h> dans le projet. Ce fichier contient des définitions de différentes tailles d'entiers tel que:

  • int8_t entier sur 8 bits et sa version non signé uint8_t.
  • int16_t entier sur 16 bits et sa version non signé uint16_t.
  • int32_t entier sur 32 bits et sa version non signé uint32_t.
En utilisant ces types d'entiers au lieu de simplement utiliser int on rend le code plus facile à porter d'une plateforme à l'autre. Autre avantage c'est qu'on peut sauver de l'espace RAM. En effet si je sais que la valeur de ma variable ne dépassera pas 255 je peut utilisé uint8_t au lieu de unsigned int qui va occupé 2 octets de RAM. Et de plus comme les AVR sont des MCU 8 bits les opérations sur les int demandes plus d'instructions. Donc sur un MCU 8 bits utilisé int8_t ou uint8_t lorsque le domaine de la variable le permet, sauve de l'espace RAM, de l'espace de code et augmente la rapidité des opérations sur cette variable.

Cherchez l'erreur

$
0
0

Il était tard et j'avais travaillé toute la journée sur ce projet. Après avoir écris la routine ISR suivante et l'avoir compilée j'ai examiné immédiatement le code assembleur généré pour en estimer le temps d'exécution.

code source
code assembleur généré
Première réaction: C'est court parfait! Non en fait ce n'est pas parfais du tout. Rapidement je constate que le compilateur a laissé tomber une bonne partie du code source! Le code résultant aurais du être ceci:
code assembleur généré, une fois mon erreur corrigée.
Lorsqu'un compilateur laisse tomber du code source c'est pour optimiser. Ici tout le bloc if a été supprimé dans la première version du code. Je regardais mon code source pourtant si simple sans voir mon erreur. Je me suis dis qu'il était tard et que c'était la fatigue qui me rendais aveugle. J'ai donc fermer l'ordinateur en remettant ça au lendemain.

Je m'appraîtais à me mettre au lit lorsque j'ai compris mon erreur. Je vous laisse regarder le code source et trouver par vous même où est l'erreur.

Belle astuce

$
0
0

Je suis toujours en train de travailler sur un projet utilisant un atMega328 et je regarde régulièrement le code assembleur généré par le compilateur. Aujourd'hui je suis tombé sur un morceau de code assembleur qui m'a laissé perplexe. A prime abord ça ne semblais rimé à rien! En le relisant avec attention j'ai fini par comprendre, voici le code assembleur en question tel que je l'ai commenté. Une variable de 8 bits est chargée dans le registre R24. R24 est additionnée à lui-même, puis mis à zéro par l'instruction eor r24, r24. Ensuite on additionne encore R24 à lui-même, avant d'enregistrer le résultat dans une autre variable. Si on ne porte très attention à ce qui ce passe c'est plutôt étonnant, mais en fait c'est une belle astuce pour faire ceci:


// code C original
vms.var[15]=(vms.var[x]&128)>>7;
Donc R24 est additionné avec lui-même avec l'instruction adc r24, r24. Si le bit 7 de r24 était à 1 avant cette opération le Carry bit sera à 1 après l'addition. On met r24 à zéro et ensuite on additionne r24+r24+Carry. Donc si le carry est à 1 r24 = 1 sinon il égal 0. C'est ce qu'on voulais avoir dans vms.var[15], c'est à dire l'état du bit 7 de vms.var[x].

Beaucoup de travail d'optimisation a été fait sur ce compilateur. Bravo! à ces créateurs.


CHIPcon partie 1

$
0
0

CHIPcon est une console de jeux peut coûteuse et facile à assembler soi-même, pour les jeux écris en super CHIP. Dans cette première partie je fais un rappel historique du langage CHIP pour ensuite présenter le schéma électronique de la console. Le circuit est basé sur un atMega328P-PU avec une sortie NTSC monochrome.

Présentation historique

  • En 1970 l'ingénieur Joseph Weisbecker (1932-1990) conçoit un processeur 8 bits à architecture Von Neumann RISC.
  • Au début de 1976 la compagnie RCA met sur le marché un microprocesseur nommé CDP-1802. Ce microprocesseur est en technologie CMOS. Son architecture est basé sur le processseur défini par Joseph Weisbecker. Il contient 16 registres de 16 bits d'usage général et 4 registres de 4 bits P,N,I,X. Et un registre de 8 bits T. Les registres de 16 bits peuvent-être divisés en 2 registres de 8 bits, on a donc 32 registres de 8 bits. Il n'y a pas de compteur ordinal dédié, n'importe quel des 16 registres de 16 bits peut-être sélectionné pour cette fonction. C'est la valeur de P qui détermine lequel est le compteur ordinal. Un appel de sous-routine se fait en initialisant un registre avec l'adresse de la sous-routine pour ensuite modifier le registre P pour définir ce registre comme compteur ordinal. Lorsque la sous-routine a terminée son travail elle réinitialise P avec la valeur originale pour revenir au programme appelant. Ce microprocesseur a été utilisé dans plusieurs sondes spatiales dont la sonde Galileo. Ce microprocesseur a un surnom COSMAC (Co mplementary S ymmetry M onolithic A rray C omputer)
  • Dans l'édition de août 1976 de Popular electronics, Joseph Weisbecker présente le COSMAC ELF. Petit ordinateur disponible en kit à faible coût. Ces kits étaient vendu par Netronics et Quest Electronics.
    • Processeur CDP-1802
    • RAM statique de 256 octets
    • 11 commutateurs à bascule et 1 à pression pour la saisie et l'exécution du code.
    • 1 affichage 7 segments à 2 digits
    • 1 LED contrôlé par la sortie Q.
    • fréquence maximale du cristal 3.2Mhz
  • Juillet 1977, Weisbecker ajoute un générateur graphique CDP-1861 au ELF. Ce dernier génère un signal monochrome de 64x128pixels.
  • En 1977 RCA entre sur le marché des micro-ordinateurs avec le COSMAC VIP (photo). Avec 2Ko de RAM en kit de base, celle-ci pouvait être augmenté à 4Ko sur la carte principale.
    • CDP-1861/CDP-1864 pour sortie NTSC monochrome.
    • 2Ko RAM en base, 4Ko possible sur carte mère.
    • Clavier hexadécimal
    • Ajout possible de 2 connecteurs pour cartes d'options.
    • Fréquence d'oscillateur 1,76Mhz.
  • Dans l'édition de décembre 1978 de BYTE, Joseph Weisbecker présente CHIP-8, un système pour simplifier la programmation de jeux sur le COSMAC VIP. Il s'agit d'un interpréteur qui exécute du bytecode. Les instructions sont encodées sur 16 bits. L'affichage est de 64x32 pixels.
  • 1990 Erik Bryntse cré un descendant de CHIP-8 baptisé SCHIP (Super CHIP). L'interpréteur est conçu pour fonctionner sur une calculatrice HP-48 et l'affichage est de 128x64 pixels. SCHIP reconnait les programmes CHIP-8 sauf pour l'instruction 0xxx qui est un appel de sous-routine en code machine, non pertinent sur la HP-48.
  • Plusieurs émulateurs CHIP-8/SCHIP/MégaCHIP ont été écris pour fonctionner sur PC. Il existe aussi un assembleur qui permet de programmer en mnémoniques plutôt qu'en code hexadécimal. Voir le site de David Winter chip.com

CHIPcon

CHIPcon est donc une console de jeux rétro qui implémente un interpréteur SCHIP sur un microcontrôleur atMega328P-PU. Cette console permet de charger et jouer tout fichier binaire en bytecode SCHIP. J'en ai trouvé plusieurs sur le site de David Winter, www.chip8.com

Caractéristique de la console

  • microcontrôleur atMega328P-PU format DIP-28.
  • expansion RAM SPI de 64Ko Microchhip 23LC512.
  • Support carte SD (pilotes écris par Roland Riegel).
  • Fréquence oscillateur 16Mhz.
  • graphiques 128x64pixels, sortie vidéo NTSC monochrome.
  • Sortie son monofréquence sur prise RCA PHONO, ou sur piezo speaker.
  • Quelques jeux en mémoire programme du MCU lorsqu'il qu'il n'y a pas de carte SD dans le support.
  • Interface Humain-machine par clavier hexadécimal comme le COSMAC VIP.
  • Potientiomètre pour contrôler la vitesse d'exécution de l'interpréteur SCHIP.

Le montage permanent n'étant pas complété voici une photo du montage sur carte sans soudure.

Schématique

Liste matériel

  • Z1    PIEZO speaker (option 2)
  • C1    electrolytic 100µF/16V
  • C2,C3    18pF ceramic NPO
  • C6,C7,C8,C9,C10    100nF ceramic (CMS)
  • C5,C10    1µF ceramic (CMS)
  • C11    10µF/16V electrolytic
  • CON1    2.1 mm BARREL_JACK
  • D1    diode 1N4148
  • D2    LED 5mm/20ma
  • J1,J2    RCA phono jack
  • k1    KEYPAD 16 touches, Grayhill 96BB2-056-R
  • P1    réceptacle SD card
  • P2    connecteur 2x3 100mil mâle
  • R1    4k7
  • R2    150R
  • R3    620R
  • R4    470R
  • R5,R6,R7,R8    10K
  • R9    10R
  • R10    100R
  • RV1    10K potentiomètre linéaire
  • SW1    bouton momentanné N.O.
  • SW2    commutateur alimentaion S.P.S.T
  • U1    MCU ATMEGA328P-PU
  • U2    SRAM 23LC512
  • U3    LDO LT1117-3,3
  • X1    cristal 16Mhz (TXC 9B-16.000MEEJ-B)
  • 8015-1 Circbord    carte à points Vector pour montage final. 10cm x 10cm

Le modèle mémoire des programmes CHIP-8/SCHIP est de 4Ko et les 512 premiers octets étaient réservés pour le système sur le COSMAC VIP. Donc le binaire du jeux est chargée en mémoire à l'adresse 512 (0x200) et a une taille maximale de 3584 octets. Le 328P-PU n'a que 2Ko de RAM dont 1Ko est occupé par la mémoire vidéo. Ce n'est donc pas suffisant pour SCHIP. Microchip vend des mémoire RAM statique à interface SPI. Le 23LC512 contient 64Ko de RAM. Les jeux sont chargée dans cette SRAM à l'adresse 0x200 et exécutés à partir de cette mémoire externe. Le vidéo NTSC est généré par 2 périphériques. La minuterie TMR1 de 16 bits génère le signal de synchronisation par PWM et le USART configuré en mode SPI est utilisé pour sérialiser les pixels vidéo à partir du video_buffer situé dans la RAM du atMega328P-PU. Le périphérique SPI principal est utilisé pour communiquer avec la SRAM externe et la carte SD.

Au départ je me demandais si l'utilisation de la SRAM externe comme mémoire d'exécution pour l'interpréteur SCHIP serait suffisamment rapide, la vitesse du clock SPI maximale étant de Fosc/2 soit 8Mhz. Il s'est avéré à l'usage qu'en fait pour certains jeux l'interpréteur était trop rapide. Il ne faut pas oublier que le COSMAC VIP original fonctionnait à 1,76Mhz et que le CPU CDP-1802 utilise 16 cycles d'oscillateur par instruction, donc un maximum de 110000 instructions par seconde sur le COSMAC VIP. Comme CHIP-8 est un interpréteur exécutant plusieurs instructions 1802 par bytecode les programmes CHIP-8 étaient encore plus lent que ça. L'atMega328P lui fonctionne à 16Mhz et la majorité des instructions s'exécute en 1 seul clock. Donc même si l'interpréteur nécessite le transfert de 5 octets sur l'interface SPI pour lire une seule instruction on est encore à 8Mhz/8/5=200000 instructions lues par seconde. Bien sur le nombre d'instructions par secondes est beaucoup plus bas que ça car une bonne partie du temps CPU est utilisé par le générateur vidéo. Quoi qu'il en soit j'ai du ajouter un potentiomètre au circuit dont la lecture est faite par le périphérique ADC 10 bits sur le canal 1 (broche 24). La valeur lue sur le potentiomètre détermine le nombre d'instructions que l'interpréteur exécute par intervalle vertical sync (16,7 msec).

Pour la sortie audio il y a 2 options. La première option consiste à sortir le signal sur un connecteur RCA phono et utiliser le téléviseur comme amplificateur audio. La deuxième option est d'utiliser simplement un petit haut-parleur piézo monté sur la carte du circuit.

Le support pour carte SD est optionnel si on ne l'utilise pas l'utilisation de la mémoire flash de l'atMega328P-PU tombe à 50% environ ce qui libère plus d'espace pour y mettre des jeux.

Avec cette option installée au démarrage le firmware vérifie la présence d'une carte SD dans le support. s'il y a une carte il lit le répertoire racine et affiche à l'écran la liste des fichiers jeux disponibles. l'utilisateur sélectionne le jeux désiré et celui-ci est alors transféré de la carte vers la SRAM et exécuté.

S'il n'y pas de carte dans le support le firmware affiche la liste des jeux enregistrés dans la flash du MCU. Le jeux sélectionné est transféré de la flash du MCU à la SRAM pour exécution.

Dans le prochain article je vais commencer la présentation du firmware en commençant par l'interpréteur super CHIP. D'ici là j'aurai sans doute le temps de compléter le montage sur la carte à points et peut-être filmer un vidéo de démonstration.


liens

  • Article CHIP-8 sur wikipedia anglais et français.
  • Page de David Winter beaucoup d'information disponible sur cette page et des jeux à télécharger.
  • Page consacré au COSMAC ELF, histoire, archives logicielles et photos.
  • Page consacré à CHIP-8 sur revival studio.
  • Vous pouvez télécharger à partir de cette page l'émulateur pour PC Fish'n chip. je l'ai testé et il est fonctionnel sur windows 7.

CHIPcon partie 2, machine virtuelle

$
0
0

Dans ce deuxième article du projet CHIPcon j'explique ce qu'est une machine virtuelle et plus spécifiquement celle du projet.

Mais d'Abord

Avant de débuter le sujet principal voici un photo du montage du prototype de CHIPcon v1.0. et un vidéo de la console en action.

Émulateur, interpréteur et machine virtuelle

Quel est la différence entre ces 3 termes. On utilise le mot émulateur pour désigner un logiciel qui implémente le fonctionnement d'un circuit matériel, par exemple si on veut faire tourner un logiciel pour un MCU particulier mais qu'on a pas le MCU en main on peut le faire tourner à l'intérieur d'un émulateur logiciel qui fonctionne sur le PC. Ainsi l'environnement MPLABX offre des émulateurs pour chaque MCU PIC 8 bits vendu par Microchip. On peut donc tester un logiciel avant de le mettre en mémoire flash du MCU.

On utilise le terme interpréteur pour désigner le compilateur d'un langage de haut-niveau qui au lieu de générer du code binaire pour un CPU génère du code pour une machine virtuelle (bytecode) et exécute ce programme sur cette machine virtuelle. Par exemple Java et Python compile pour une machine virtuelle et non du binaire pour un microprocesseur.

Une machine virtuelle est un logiciel qui exécute du bytecode pour un modèle d'exécution particulier. Cette machine est semblable à un microprocesseur sauf qu'elle n'est pas gravé dans le silicium, d'où le qualificatif de virtuelle.

Par modèle d'exécution on entend l'ensemble des registres, de l'espace mémoire et des instructions que peut exécuter cette machine.

CHIP-8 et SCHIP sont des machines virtuelles qui partagent le modèle d'exécution suivant.

  • Une banque de 16 registres de 8 bits notés V0-VF. Le registre VF est utilisé pour sauvegarder l'indicateur de débordement (carry flag).
  • Un compteur ordinal pouvant adresser 4096 octets (12 bits)
  • Un pointeur de donnée pouvant adresser 4096 octets (12 bits)
  • Une minuterie de délais de 8 bits cadencé à 60Hertz.
  • Une générateur de tonalité avec compteur de duré de 8 bits cadencé à 60Hertz.
  • L'espace d'adressage mémoire est de 4096 octets, mais les programmes à exécuter doivent-être chargés à l'adresse 512 (0x200). Leur taille est donc limité à 3584 octets.
  • Le jeux d'instructions de la machine virtuelle est codé sur 16 bits
  • Le système possède une police de caractère hexadécimal 3x5 pixels.
  • Le système possède une police de caractère décimal de 8x10 pixels.
  • CHIP-8 a une capacité graphique de 64x32 pixels (mémoire vidéo 256 octets).
  • SCHIP a une capacité graphique de 128x64 pixels (mémoire vidéo de 1024 octets).
  • SCHIP a une compatilibilité ascendante avec CHIP-8 sauf pour l'instruction 0NNN (syscall).
  • SCHIP ajoute 10 instructions au jeux d'instructions de CHIP-8 qui a 35 instructions.
  • SCHIP possède une deuxième banque de 16 registres appellée RPL. Un transfert de données peut-être fait entre les 2 banques.
Si on fabriquait cette machine dans du silicium son diagramme bloc ressemblerais à ceci.

Jeux d'instructions de SCHIP

Dans la table ci-bas NNN représente un nombre de 12 bits en hexadécimal (000-FFF).
KK représente une constante de 8 bits en hexadécimal (00-FF).
X et Y représentent un registre V en hexadécimal (0-F).
Les instructions suivies d'un * sont spécifiques à SCHIP.

OPCODEDescription
00CN*défile l'affichage vers le bas de N lignes.
00E0Efface l'affichage.
00EEQuitte une sous-routine.
00FB*Défile l'écran vers la droite de 4 pixels.
00FC*Défile l'écran vers la gauche de 4 pixels.
00FD*Fin de programme, quitte la machine virtuelle.
00FE*Désactive le mode SCHIP, retour au mode CHIP-8 de 64x32 pixels.
00FF*Active le mode étendu, 128x64 pixels.
1NNNSaute à l'adresse NNN.
2NNNExécute la sous-routine à l'adresse NNN.
3XKKSaute l'instruction suivante si VX == KK
4XKKSaute l'instruction suivante si VX <> KK
5XY0Saute l'instruction suivante si VX == VY
6XKKVX := KK
7XKKVX := VX + KK
8XY0VX := VY
8XY1VX := VX or VY
8XY2VX := VX and VY
8XY3VX := VX xor VY
8XY4VX := VX + VY, VF := carry
8XY5VX := VX - VY, VF := not borrow
8XY6VX := VX shr 1, VF := carry
8XY7VX := VY - VX, VF := not borrow
8XYEVX := VX shl 1, VF := carry
9XY0Saute l'instruction suivante si VX <> VY
ANNNI := NNN
BNNNsaute à l'adresse NNN+V0
CXKKVX := nombre aléatoire and KK
DXYN*Affiche un sprite de N-octets aux coordonnées d'écran VX, VY.
Le contenu du sprite se trouve à l'adresse débutan M(I).
VF := 1 si il y a collision.
Si N==0 indique un sprite de 16x16 pixels.
EX9ESaute l'instruction suivante si la touche dont la valeur est indiquée dans VX est enfoncée.
EXA1Saute l'instruction suivante si la touche dont la valeur est indiquée dans VX n'est pas enfoncée.
FX07VX := valeur de la minuterie délais.
FX0AAttend qu'une touche sois enfoncée et met sa valeur dans VX.
FX15minuterie de délais := VX, elle est décrémentée jusqu'à zéro 60 fois par seconde.
FX18minuterie son := VX, La minuterie est décrémentée, le son s'arrête lorsqu'elle atteint zéro.
FX1EI := I + VX
FX29VX contient une valeur entre 0 et 15. La valeur du registre I est ajusté au début du sprite qui représente ce caractère dans la table 3x5.
FX30*VX contient une valeur entre 0 et 9. La valeur du registre I est ajusté au début du sprite qui représente ce caractère dans la table 8x10.
FX33Met à l'adresse M(I)..M(I+2) la valeur BCD du nombre qui est dans VX.
FX55Enregistres les valeurs des registres V0..VX dans la mémoire RAM en débutant à l'adresse M(I).
FX65Charge les V0..VX à partir de la mémoire RAM en débutant à l'adresse M(I).
FX75*Sauvegarde les registres V0..VX dans la banque de registres RPL.
FX85*Charge les registres V0..VX à partir des registres RPL.

Implémentation de la VM SCHIP sur CHIPcon.

Pour suivre cette description référez-vous au dépôt github du projet CHIPcon. tout les fichiers y sont.

Cette machine virtuelle n'ayant que 43 codes opérationnels est simple à implémenter. Les états du modèle d'exécution sauf pour la mémoire RAM sont rassemblés dans une seule variable appellée vms. Le type de donnée qui définie cette structure est déclaré dans le fichier d'entête chip8.h et le code 'C' de la machine est dans le fichier chip8.c.


// structure de donnée définissant le modèle d'exécution de la VM
typedef struct vm_state{
uint16_t pc; // compteur ordinal
uint16_t ix; // pointeur de données
uint8_t sp; // pointeur de la pile
uint8_t var[16]; // banque de registres
uint8_t rpl[16]; // banque de registres SCHIP
union {
uint16_t opcode; // dernier code machine exécuté
struct{
uint8_t b1; // octet fort du code
uint8_t b2; // octet faible du code
};
};
uint16_t stack[32]; // pile des retours
uint8_t src_mem:1 ; // indicateur de source du sprite
uint8_t debug:1; // pour support déboguage
uint8_t trace:1; // pour support déboguage
}vm_state_t;

La fonction uint8_t schip(uint8_t flags) exécute le code qui est enregistré dans la SRAM à partir de l'adresse 0x200. Deux octets de code sont lues pour chaque instruction. Comme le code opérationnel est répartie dans 2 champs séparés, il y a d'abord une phase appelée décodeur d'instruction qui rassemble les 2 champs dans la variable uint16_t code. code est ensuite utilisé par le switch de la phase exécution. Il s'agit d'une organisation classique pour une machine virtuelle. Il n'y a pas de difficulté particulière, une simple lecture du fichier chip8.c devrait permettre de comprendre le fonctionnement de la machine virtuelle.

La VM transige avec l'affichage par les interfaces des modules tvout et text, avec l'unité son par l'interface de celui de tone, avec le clavier via l'interface de keypad et avec la mémoire sram par l'interface du module sram.


liens

CHIPcon partie 1
dépot githup du projet.
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8

CHIPcon partie 3, module SRAM

$
0
0

Dans cet article je discute de l'utilisation de la mémoire RAM à interface SPI Microchip 23LC512

Cette mémoire RAM à interface SPI est vraiment pratique puisqu'elle ne requiert que 4 GPIO, SCK, MISO, MOSI et SELECT. Et comme l'atMega328P possède un périphérique SPI l'utilisation en est très simple. C'est le même périphérique SPI qui est utilisé pour la carte SD chacun ayant un SELECT différent.

Le 23LC512-IP possède 64Ko de RAM, j'aurais pu utiliser un 23K640-IP (8Ko) pour un coût moindre, mais j'ai utilisé ce que j'avais en main. Le 23LC512 a 3 modes de fonctionnement, BYTE, PAGE et SEQUENTIAL. Pour cette application il est configuré en mode séquentiel. Ce mode permet de lire ou d'écrire un bloc de mémoire de n'importe quel dimension avec une seule commande, alors qu'en mode BYTE on ne peut lire ou écrire qu'un octet par commande. En mode PAGE, 32 octets peuvent-être lus ou écris et ces pages sont alignées modulo 32. Donc si on envoie la commande READ 0x0003 et qu'on lit 32 octets, les octets lus seront aux adresses 3-31 et 0-2 et non 3-34. Pas de problème de cette sorte avec le mode SEQUENTIAL.

Évidemment on ne peut stocker de code binaire dans cette SRAM sauf si on l'utilise avec des MCU à architecture Von Neumann comme les MSP430 par exemple. Dans ce cas on pourrait charger des routines de la SRAM vers la RAM du MCU pour les exécuter. Quoi que pour une telle application une mémoire EEPROM ou flash SPI serait plus utile. Dans le cas d'un atMega328P on ne peut utiliser cette méthode mais c'est néanmoins utile comme espace de stockage de données temporaire. Dans l'application CHIPcon la SRAM est utiliser de 3 façons.

  1. stockage de la liste des noms de fichiers jeux pour utilisation par la routine display_page() du fichier chipcon.c
  2. tvout utilise la SRAM pour sauvegarder un écran temporairement afin d'afficher les informations de débogage pendant le mode TRACE. Voir les routines screen_save() et screen_restore() dans tvout.c ainsi que la routine print_vms() dans chip8.c.
  3. La mémoire SRAM contient le programme SCHIP à exécuter. Le programme est chargé à l'adresse 512 (0x200).

Pour le détail de l'implémentation voir les fichiers sram.h et sram.c.


liens

CHIPcon partie 1
chipcon partie 2, machine virtuelle
dépot githup du projet.
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8

CHIPcon partie 4, tvout

$
0
0

Dans cet article je décris le fonctionnement du module tvout du projet CHIPcon.

tvout

Le module tvout est constitué des fichiers tvout.h et tvout.c. Ce module est responsable de la génération du signal NTSC et comprends les fonctions d'interface suivantes:

  • void tvout_init()
    Initialisation du module.
  • void plot(int8_t x, int8_t y, optype op)
    Desssine un point à la position x,y. optype peut prendre une des valeurs suivantes: WHITE, BLACK, INVERT.
  • int8_t put_sprite(uint8_t x, uint8_t y, uint8_t n, const uint8_t *sprite, int8_t memory)
    Desssine un sprite. x,y sont les coordonnées du coin supérieur gauche. Le sprite a 8 pixels de large par n pixels en hauteur. memory indique si le sprite est en mémoire flash (FLASH_MEM) ou en RAM (RAM_MEM).
  • int8_t put_big_sprite(uint8_t x, uint8_t y,const uint8_t *sprite)
    Dessine un sprite de 16x16 pixels. Les coordonnées sont le coin supérieur gauche.
  • void cls()
    Efface l'écran.
  • void scroll_down(uint8_t lines)
    Défile l'écran vers le bas d'un nombre de lignes entre 0 et 31.
  • void scroll_up(uint8_t lines)
    Défine l'écran vers le bas d'un nombre de lignes entre 0 et 31.
  • void scroll_right(uint8_t pixels)
    Défile l'écran vers la droite d'un nombre de pixels entre 0 et 8.
  • void chip_scroll_right()
    Défile l'écran vers la droite de 4 pixels. Optimisé pour l'engin schip()
  • void scroll_left(uint8_t pixels)
    Défile l'écran vers la gauche d'un nombre de pixels entre 0 et 8.
  • void chip_scroll_left()
    Défile l'écran vers la gauche de 4 pixels. Optimisé pour l'engin shcip().
  • void screen_save()
    Sauvegarde l'écran dans la SRAM.
  • void screen_restore()
    Restaurate l'écran à partir de la SRAM.

Génération du signal NTSC

La façon la plus efface de générer un signal NTSC sur un MCU en utilisant le moins de cycles CPU possible est d'utiliser une minuterie avec un output compare en mode PWM pour le signal de synchroniation. Pour sérialiser les pixels contenu dans le video_buffer un périphérique SPI fait l'affaire. l'atMega328P permet de configuré le module USART en mode SPI c'est donc de cette façon que j'ai procédé car le module SPI lui-même est utiliser pour interfacer la carte SD et la SRAM.

Il n'y a qu'une seule interruption qui se produit lorsque le compteur du TIMER1 atteint la valeur du registre OCR1B. Ce qui se produit à la fin de l'impulsion de synchronisation. Il y a donc une interruption à chaque ligne horizontale soit à toute les 63,5µsec.

Cette interruption fait fonction de céduleur de tâche. La tâche à exécuter est déterminée par le numéro ligne.


liens

CHIPcon partie 1, présentation du projet.
chipcon partie 2, machine virtuelle
CHIPcon partie 3, module SRAM
dépot githup du projet. mise à jour le 2014-10-24, utilitaire chip-dasm (schip dé-assembleur).
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8

CHIPcon partie 5, clavier et émulateur PC

$
0
0

Cette partie documente le module keypad constitué des 2 fichiers keypad.h et keypad.h.

Agencement du clavier

La mojorité des jeux CHIP-8/SCHIP que j'ai trouvé dans l'internet ont été écris pour fonctionner dans des émulateurs tournant sous Windows. Donc la disposition du clavier est différente. Certains émulateurs sont configurés en pensant à l'utilisation du pavé numérique d'autres utilisent certaines lettres du pavé alphanumérique. Par exemple l'émulateur Fish'n chip utilise les touches à gauche du clavier alphanumérique. La correspondance avec le clavier COSMAC VIP est représenté en caractères gras.

clavier QWERTY
1 12 23 34 C
Q 4W 5E 6R D
A 7S 8D 9F E
Z AX 0C BV F

CHIPcon utilise un clavier Grayhill 96BB2-056-R représenté ici à côté du clavier COSCMAC VIP. On voie donc que la disposition est différente. Pour CHIPcon [*] correspond à [E] et [#] correspond à [F]. Donc lorsqu'on télécharge un jeux pour l'utiliser avec CHIPcon on doit tenir compte de ces différences.

interface keypad

  • void keypad_init()
    Initialisation matérielle du clavier.
  • uint8_t keypad_read()
    Lecture d'une touche avec anti-rebond.
  • uint8_t wait_key()
    Attend qu'une touche soit enfoncée et retourne sa valeur. Lecture avec anti-rebond.
  • void prompt_key()
    Affiche le message "any key..." et attend une touche.
  • uint8_t keypad_break()
    Vérifie si les touches [*] et [#] sont enfoncées en même temps. Retourne vrai si c'est le cas. Utilisé pour sortir de la fonction schip() lorsqu'un programme est bloqué dans une bouche infinie.
  • uint8_t key_down(uint8_t key)
    Vérifie si la touche key est enfoncée. Il n'y a pas d'anti-rebond, le programme SCHIP doit gérer lui-même l'anti-rebond.

Outils de développement

Dans le répertoire tools du projets il y a 2 utilitaires.

cvt-chip est utilisé pour convertir un fichier binaire SCHIP en fichiers source *.c et *.h dans le but d'intégrer un jeux dans la mémoire flash de CHIPcon. Voici un exemple pour sokoban.sc.

commande pour convertir le fichier binaire.


cvt-chip.exe sokoban.sc
Gènère les fichiers sokoban.h

sokoban.c

Le texte


"Sokoban by Hap\n"
"keys:\n"
"5 up\n"
"8 down\n"
"7 left\n"
"9 right\n"
"A select\n"
Doit-être ajouter manuellement. Ce texte défile à l'écran avant le démarrage du jeux.

Un autre utilitaire est chip-dasm qui est un dé-assembleur. A partir d'un fichier binaire SCHIP il génère un fichier lisible par l'humain ou chaque instruction est représenté par un mnémonique. Voici ce que ça donne avec le fichier field.ch8

D'autres utilitaires sont disponibles en téléchargement sur http://www.chip.com. En autre MegaCHIP devkit 1.0. Ainsi que l'émulateur fish'n chip


liens

CHIPcon partie 1, présentation du projet.
chipcon partie 2, machine virtuelle
CHIPcon partie 3, module SRAM
CHIPcon partie 4, tvout
dépot githup du projet. mise à jour le 2014-10-24, utilitaire chip-dasm (schip dé-assembleur).
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8

CHIPcon partie 6, interface carte SD

$
0
0

Dans cette partie je documente l'interface avec la carte SD. Pour l'accès à la carte SD j'ai utilisé la librairie créé par Roland Riegel.

Il y a plusieurs librairie SD/SDHC/MMC disponible pour les atMega, j'ai choisie celle de Roland Riegel pour sa facilité d'utilisation. Pour l'intégrer à mon projet j'ai eu très peut de travail à faire. S'il avait fallu que je cré ma propre librairie le temps travail aurait plus que doublé. Chaque module de la librairie a un fichier *_config.h qu'il suffit d'adapter à ses besoins.

Pour commencer dans le fichier hardware.h de mon projet j'ai ajouter la définition suivante:


#define __CHIP_COMP__ 1
J'ai ensuite utiliser cette définition pour contrôler une compilation conditionnelle de certaines variables dans les fichiers sd_raw_config.h et fat_config.h. Je ne détaillerai pas l'interface de cette librairie. Je ne l'ai d'ailleurs pas étudier en détail. J'ai plutôt créé une interface entre cette librairie et CHIPcon en m'inspirant d'un exemple d'application fourni par Roland Riegel. Mon interface comprend les fichiers suivants: filesys.h et filesys.c
  • uint8_t fs_mount()
    Vérifie s'il y a une carte dans le support et si c'est le cas monte le système de fichier. Retourne 1 en cas de succès et 0 autrement. Un seul système de fichier peut-être ouvert à la fois.
  • void fs_umount()
    Ferme le système de fichier.
  • uint8_t fs_open_dir(char *dir_name)
    Ouvre un répertoire. Un seul répertoire peut-être ouvert à la fois. Retourne 1 en cas de succès et 0 autrement.
  • void fs_close_dir()
    Ferme un répertoire.
  • uint8_t fs_open_file(char *file_name)
    Ouvre un fichier. Un seul fichier peut-être ouvert à la fois. Retourne 1 en cas de succès et 0 en cas d'échec.
  • void fs_close_file()
    Ferme le fichier ouvert.
  • uint8_t fs_load_file(uint16_t file_no)
    Charge le contenu du fichier dans la mémoire SRAM. Retourne le nombre d'octets chargés.
  • uint8_t fs_read_dir(struct fat_dir_entry_struct *dir_entry)
    Retourne l'entrée suivante du répertoire. Retourne 0 à la fin de la liste.

CHIPcon n'affiche que la liste des fichiers qui se trouve dans le répertoire racine. Notez qu'il affiche le nom de tous les fichiers. Donc si l'utilisateur sélectionne un fichier qui n'est pas un binaire SCHIP la machine virtuelle schip() va plantée à l'exéctuion d'un tel fichier laissant une message CRASH! BAD OPCODEà l'écran.

La librairie de Roland Riegel est configurée pour utilisation en lecture seule afin de sauver de l'espace code. Tel quel elle consomme environ 5Ko de flash.


liens

CHIPcon partie 1, présentation du projet.
chipcon partie 2, machine virtuelle
CHIPcon partie 3, module SRAM
CHIPcon partie 4, tvout
CHIPcon partie 5, clavier et émulateur PC.
dépot githup du projet. mise à jour le 2014-10-24, utilitaire chip-dasm (schip dé-assembleur).
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8
Page de Roland Riegel concernant sa librairie MMC/SD/SDHC.

CHIPcon partie 7, le boitier

$
0
0

J'ai complété la fabrication du boitier pour CHIPcon. Entièrement fabriqué à partir d'une feuille de plastique noir récupérée d'une horloge pendule et de colle.

Voici un deuxième vidéo pour démontrer l'effet du bouton game speed sur la vitesse d'exécution des jeux. Ici il s'agit du jeux blinky, clone de Packman créé par Hans Christian Egeberg.


liens

CHIPcon partie 1, présentation du projet.
chipcon partie 2, machine virtuelle
CHIPcon partie 3, module SRAM
CHIPcon partie 4, tvout
CHIPcon partie 5, clavier et émulateur PC.
CHIPcon partie 6, interface carte SD
dépot githup du projet. mise à jour le 2014-10-24, utilitaire chip-dasm (schip dé-assembleur).
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8
Page de Roland Riegel concernant sa librairie MMC/SD/SDHC.

CHIPcon partie 8, ccasm

$
0
0

C'est bien beau d'avoir une console de jeux mais il faut aussi pouvoir écrire des programmes pour cette console. Comme CHIPcon ajoute 4 instructions à celles de SCHIP il a bien fallu que je cré un assembleur spécifique à CHIPcon. J'ai baptisé cet assembleur ccasm (CHIPcon assembler). Le code source et le binaire compilé pour Windows avec minGW gcc 4.8.1 se trouve dans le répertoire tools. Son utilisation est des plus simple:


ccasm test.chp test.bin [-p test.ppf]
test.chp est le nom du fichier source assembleur CHIPcon.
test.bin est le nom du fichier binaire qui sera généré par ccasm.
L'option -p si elle est présente produit un fichier contenant les lignes pré-processées tel que passées à l'assembleur. test.ppf est le nom du fichier générer par le pré-processeur.

ccasm

Pour connaître les instructions supportées par la machine virtuelle de CHIPcon il faut se référer à la table présentée dans la partie 2 de cette série.

En plus des instructions machines l'assembleur supporte les directives suivantes:

directiveutilisationdescription
EQU
EQU identifier expression
Directive de pré-processeur.
Comme pour la plupart des assembleurs cette directive permet de définir des symboles de substitution pour des constantes numériques.
exemple:
EQU BYTE_PER_ROW 128/8
DEFNDEFN identifier stringDirective de pré-processeur.
Permet de substiuer une chaîne de caratère par un nom symbolique. Utile pour nommer les variables VX.
exemple:
DEFN xpos V4
DB
DB BYTE [,BYTE]
Directive d'assembleur.
Permet de créer une ou plusieurs donnée de type BYTE (8 bits) dans l'espace programme.
DW
DW WORD [,WORD]
Directive d'assembleur.
Permet de créer une ou plusieurs donnée de type word (16 bits) dans l'espace programme.
ASCII
ASCII "text..."
Directiver d'assembeur.
Permet de créer une chaîne de caractères terminée par un zéro dans l'espace programme. Cette chaîne peut-être affichée à l'écran en utilisant le code opérationnel PRT.

Expressions

Partout où une constante numérique est applicable une expression arithmétique peut-être utilisée. Les opérateurs reconnus sont '+' addition, '-' soustraction, '*' multiplication, '/' division et '%' modulo ainsi que les parenthèses '(',')'.
exemple:


;programme hello world

equ SCREEN_WIDTH 128
equ SCREEN_HEIGH 64
equ CHAR_HEIGH 8
equ CHAR_WIDTH 6
equ CHAR_PER_LINE SCREEN_WIDTH/CHAR_WIDTH
equ TEXT_LEN 12

defn XPOS V3
defn YPOS V4

high
cls
ld I, REG_INIT
ld V4,[i] ; initialisation registres V0..V4
ld I, MSG
prt XPOS,YPOS ; imprime message à  l'écran
exit
REG_INIT:
db 0, 0, CHAR_HEIGH*4, CHAR_WIDTH*(CHAR_PER_LINE-TEXT_LEN)/2
MSG:
ascii "hello world!"

Assemblé avec l'option -p le fichier pré-processé contiendrais:


13 HIGH
14 CLS
15 LD I , REG_INIT
16 LD V4 , [ I ]
17 LD I , MSG
18 PRT V3 , V4
19 EXIT
20 REG_INIT:
21 DB 0 , 0 , 8 * 4 , 6 * ( 21 - 12 ) / 2
22 MSG:
23 ASCII "hello world!"

Commentaires

Les commentaires commence par ';' et se termine à la fin de la ligne.

Identificateur

Les identificateurs commence par une lettre ou le caractère '_'. Ce premier caractère peut-être suivi de lettres,chiffres et '_'. Les identificateurs sont utilisées pour les étiquettes et les symboles définis par EQU et DEFN.

Étiquettes

Les étiquettes sont placées en début de ligne et immédiatement suivie du caractère ':'. Les étiquettes sont des repères pour les instructions JP étiquette, les appels de sous-routines CALL étiquette ainsi que pour le chargement du registre pointeur de données LD I, étiquette. Le caractères ':' ne fait pas partie du nom de l'étiquette et ne doit donc être utilisé qu'à l'endroit où l'étiquette est définie. Une instruction peut suivre une étiquette sur la même ligne.


boucle: LD V1, 4 ; ceci est valide
MSG: ascii "hello world!" ; ceci est valide

Nombres et bases

ccasm reconnait les nombres entiers seulement dans les bases décimal, hexadécimal et binaire. Le caractère # indique un nombre hexadécimal et le caractère '$' indique un nombre binaire. Dans les nombres binaires le zéro peut-être remplacé par un point '.' dans le but d'accentuer la forme des sprites.
exemples:


546 ; nombre décimal
#f585 ; nombre hexadécimal
$101001 ; nombre binaire
$1.1..1 ; même nombre binaire

; le point à la place du zéro permet
; de mieux visualiser la forme du sprite
sprite:
DB $..1111..
DB $.1....1.
DB $1......1
DB $1.1..1.1
DB $1......1
DB $1..11..1
DB $.1....1.
DB $..1111..

code source

Le code source du programme doit-être en ASCII ou ANSI (Windows). L'assembleur est insensible à la casse, les lettres étant converties automatiquement en majuscules. Il n'y a qu'une instruction par ligne. Le traitement se fait par ligne en 2 phases. En première phase si la ligne est une directive EQU ou DEFN le nouveau symbole est créé dans la liste. Si la ligne est une instruction assembleur ou une directive de donnée, le pré-processeur analyse chaque mot de la ligne et substitue les symboles définis par des EQU et DEFN. Il converti aussi les lettres minuscules en majuscules. Cette ligne pré-processée est ensuite assemblée en phase 2.
La description formelle de la syntaxe reconnue par ccasm est dans le fichier tools/ccasm_bnf.txt

Avec son assembleur et son dé-assembleur CHIPcon est prêt pour le développement de jeux. Mais ce serait mieux s'il y avait un émulateur sur le PC pour éviter d'avoir à copier le fichier binaire sur carte SD afin de le tester sur la console. Opération qui doit-être répétée de nombreuses fois lors du développement. La création de cet émulateur ccemul est donc la prochaine étape de ce projet.


liens

CHIPcon partie 1, présentation du projet.
chipcon partie 2, machine virtuelle
CHIPcon partie 3, module SRAM
CHIPcon partie 4, tvout
CHIPcon partie 5, clavier et émulateur PC.
CHIPcon partie 6, interface carte SD
CHIPcon partie 7, le boitier
dépot githup du projet.
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8
Page de Roland Riegel concernant sa librairie MMC/SD/SDHC.

CHIPcon partie 9, ccemul

$
0
0

Dans ce neuvième article sur le projet CHIPcon je présente l'utilitaire ccemul. Il s'agit d'un simulateur de la console CHIPcon fonctionnant sous Windows. Ce simulateur ne permet pas seulement d'exécuter des jeux CHIPcon et SCHIP mais possède aussi des facilités de débogages. Avec les utilitaires ccasm et cc-dasm il complète le CHIPcon DEV KIT. Voici une capture d'écran de la fenêtre principale de l'émulateur.

Utilisation du clavier

Le simulateur est configuré pour le clavier Nord-Américain QWERTY et utilise les touches à gauche du clavier de la façon suivante. Le chiffre entre parenthèse représente la correspondance sur le keypad de la console CHIPcon.

1 (1)2 (2)3 (3)4 (A)
Q (4)W (5)E (6)R (B)
A (7)S (8)D (9)F (C)
Z (E)X (0)C (F)V (D)

Sur la fenêtre principale de l'application le seul contrôle qui peut avoir le focus du clavier, hormis le menu, est le contrôle de vitesse (speed). Donc pour lire les touches du clavier l'émulateur utilise les événements keydown et keyup associé à ce contrôle. Si on presse la touche altà gauche de la barre d'espacement le focus du clavier passe à la barre de menu et donc le jeux ne réponds plus événements du clavier. Il faut donc s'assurer que c'est bien le contrôle d'ajustement de la vitesse qui a le focus, ce qui par défaut est bien le cas.

Flux de travail

Le développement d'un jeux pour la console CHIPcon se fait selon le flux de travail suivant:

Après avoir écris le programme source dans son éditeur préféré en prenant soin d'utiliser un encodage ANSI pour le fichier, l'auteur utilise ccasm pour assembler ce code source en fichier binaire. Optionnellement il peut générer un fichier *.ppf en utilisant l'option -p pour voir de quoi a l'air le code pré-traité tel qu'il est transmis à l'assembleur proprement dit. Cette option est surtout utile lors du développement de l'assembleur lui-même. L'autre option -s sert à générer un fichier texte qui contient la liste des cibles (labels) qui sont dans le programme source. Ce fichier est utilisé pour le débogage du jeux dans le simulateur ccemul. Une fois le jeux complété et débogué le fichier binaire est copié sur une carte SD et utilisé sur la console CHIPcon.

Pour créer un fichier *.lbl il faut utiliser l'option -s symbol_file lors de l'assemblage du fichier source.


ccasm lem.chp lem.bin -slem.lbl
Si on ouvre un fichier xyz.bin dans le simulateur, celui-ci regarde s'il y a un fichier xyz.lbl dans le même répertoire et charge la liste des symboles qu'il contient. La boite de dialogue Break points affiche cette liste et permet ainsi de créer un point d'arrêt à la position d'une de ces étiquettes. Si aucun fichier xyz.lbl n'existe un message d'erreur apparait mais le jeux va quand être exécuté mais il ne sera pas possible de mettre des points d'arrêt. Si vous donnez une autre extension à ce fichier vous devrez le charger manuellement avec l'option Load labels file du menu debug.
Le nombre à droite du nom de l'étiquette est l'adresse programme où est situé cette étiquette.

Vidéo de présentaion de ccemul

Le vidéo suivant présente le fonctionnement de ccemul.

Jeux LEM

J'ai créé une version du jeux des années 197x lunar landing pour CHIPcon. Je l'ai baptisé LEM du nom du module lunaire du projet Apollo. Il s'agit de faire alunir le LEM de façon sécuritaire. Sous l'effet de la gravité lunaire le LEM accélère continuellement alors qu'il se dirige vers le sol. Il faut le ralentir en utilisant la fusée principale touche 2. Il faut aussi le posé sur le seul endroit plat. Pour se déplacer horizontalement il y a 2 fusées latérales. touche 4 vers la gauche et touche 6 vers la droite. Pour un alunissage sécuritaire non seulement il faut se poser sur le plat mais il faut que les vitesses horizontales et verticales soient inférieures à 2 unités. Au départ le réservoir contient 100 unités de carburant. Le coin supérieur gauche indique le niveau de carburant.

Un alunissage réussi fait apparaitre le message congratulation! sinon c'est écris You crashed!. Le score (nombre de succès/nombre d'essais) s'affiche à la fin de chaque essais. Il faut enfoncer n'importe qu'elle touche pour le prochain essai.

Conclusion

Bien qu'un projet n'est jamais vraiment complété, ceci est le dernier article de cette série. Il y a peut-être encore un (des) bogue(s) moins évident qui se cache dans le firmware de la console ou de l'un des programmes du DEV KIT, mais tel qu'il est se projet est suffisamment stable pour être utilisable.

Ce projet m'a conduit beaucoup plus loin que ce que j'avais prévu au départ. Tout ça est open source donc si ça vous intéresse vous pouvez le prendre en main et le mener plus loin, ou simplement construire votre propre console CHIPcon pour y jouer les jeux disponible sur www.chip.com.


liens

CHIPcon partie 1, présentation du projet.
chipcon partie 2, machine virtuelle
CHIPcon partie 3, module SRAM
CHIPcon partie 4, tvout
CHIPcon partie 5, clavier et émulateur PC.
CHIPcon partie 6, interface carte SD
CHIPcon partie 7, le boitier
CHIPcon partie 8, ccasm
dépot githup du projet.
page www.chip.com rassemblant beauceaup d'information sur CHIP-8/SCHIP/MegaCHIP
article de wikipedia sur CHIP-8
Page de Roland Riegel concernant sa librairie MMC/SD/SDHC.

NOTE: ccemul a été développé avec SharpDevelop version 5 et compilé pour le .NET version 3 et processeur Intel 32 bits. Le programme compilé devrait donc fonctionné sur tout PC avec un windows 32/64 bits avec les librairies runtime .NET version 3+ installées.

Lazarus

$
0
0

Ce matin je me réjouis car j'ai découvert que Lazare est ressuscité1. Dans les années 80 je suivais des cours d'informatique à l'UQAR et le langage de programmation utilisé pour ces cours était le Borland Turbo Pascal qui était très populaire à cette époque. Puis MS-DOS a été remplacé par Windows et Turbo Pascal est devenu Borland Delphi maintenant vendu par Embarcadero. Professionnellement j'ai développé quelques applications en delphi 6 mais à titre personnel je n'ai jamais été intéressé à défrayer le coût de la version la moins coûteuse de cet environnement qui vaut 209US$ Je suis donc passé à d'autre IDE comme SharpDevelop. C# est un langage intéressant et l'IDE de SharpDevelop aussi mais comme c'est construit par dessus .NET c'est restrictif en terme de plateformes cibles.

Lazarus

Ce que j'ai découvert ce matin c'est l'existance d'un projet open source appellé Lazarus. C'est un IDE qui utilise le compilateur Free Pascal. Cet IDE est un clone libre et gratuit de Delphi. les projets Delphi peuvent même être importés dans cet environnement, le langage étant le même c'est à dire Pascal Objet.

Cet IDE est disponible sous Windows 32/64bits, GNU/Linux 32/64 bits, OSX Intel 32bits/PowerPC. Le compilateur Free Pascal compile du code natif. Il ne nécessite donc pas l'installation de machine virtuelle Java ou CLI (.NET) et tout les librairies associés à ces gros systèmes.

Formidable avec cet IDE je vais pouvoir développer des applications Desktop aussi bien pour Windows que pour Linux dans un environnement et un langage qui me sont familiers.


1) humour hautement dépendant de la culture d'origine de l'auteur.

oscillateur

$
0
0

Dans cet article j'explique le fonctionnement des oscillateurs électroniques.

Le pendule

Avant d'expliquer l'oscillateur électronique je vais débuter par une analogie mécanique, le pendule, une balançoire en fait. l'enfant assis dans la balançoire apprend rapidement comment la mettre en mouvement mais aussi comment la freiner. Pour la mettre en mouvement il se laisse tomber vers l'arrière en tirant sur les cordes puis reprends sa position initiale. En répétant de mouvement il augmente l'amplitude des oscillations. Il n'applique pas cette force à n'importe quel moment met lorsque la balançoire atteint le point mort haut arrière, juste au moment ou la descente s'entame. Ainsi l'énergie qu'il apporte au pendule est en phase est le mouvement de celui-ci. Par contre lorsqu'il veut diminuer l'amplitude il pousse sur les cordes vers l'avant lorsqu'il est en ascension frontale. A ce moment l'énergie qu'il applique est en anti-phase.

Si on accrochait un crayon sur le bord du siège de la balançoire et qu'on faisait défiler a vitesse régulière un large bande de papier le long de la balançoire de sorte que le crayon frotte sur celle-ci, on verrait apparaître sur la bande de papier une onde sinusoïdale.

Circuit accordé

L'inductance et le condensateur sont en quelque sortent des composants complémentaires en électronique. En effet l'inductance accumule de l'énergie dans un champ magnétique et le condensateur dans dans un champ électrique. Si on les combines comme sur cette illustration on obtient un circuit accordé qui possède une fréquence de résonance.

Supposons le montage suivant:

C'est l'équivalent électronique de la balançoire. Si on enfonce le bouton le transistor Q1 entre en conduction et fourni de l'énergie au circuit accordé. Lorsqu'on relâche le bouton. Une certaine quantité d'énergie est accumulée dans le champ magnétique de l'inductance L et le champ électrique du condensateur c. Lorsque le transistor cesse de conduire le champ magnétique de l'inductance s'effondre créant une tension au bornes de celle-ci. Cette tension génère un courant qui va accumuler une charge supplémentaire dans le condensateur. Lorsque le champ magnétique est complètement effondré le condensateur ne reçoit plus de courant par contre il commence à se décharger à travers l'inductance. Ainsi l'énergie est transférée en alternance entre le champ magnétique et le champ électrique. La fréquence à laquelle cette oscillation se produit dépend des valeurs de L et C selon la formule Fosc=1/(2*PI*√(L*C)). C'est l'équivalent du pendule ou l'énergie oscille entre la forme énergie potentielle maximale lorsque le pendule est à l'arrêt aux extrémités de sa course et énergie cinétique maximale lorsque le pendule est au point le plus bas.

Oscillateur électronique

Pour obtenir un oscillateur électronique dont l'oscillation est entretenue il suffit de peser sur le bouton au bon rythme et en phase avec l'oscillation du circuit accordé. Évidemment on ne peut faire ça à la main mais il y a une façon simple d'y arrivé. En récoltant une partie de l'énergie fournie au circuit accordée et en la renvoyant à l'entrée du transistor Q1 de sorte que ce signal une fois amplifié soit en phase avec l'oscillation naturelle du circuit accordée. On appelle ça une rétro-action positive. Examinons le circuit.

Ce montage s'appelle base commune car du point de vue de l'analyse circuit A.C. (courant alternatif) la base du transistor est maintenue au commun de l'alimentation (négatif de la pile dans ce schéma) à travers le condensateur C3 dont l'impédance (résistance AC) est très faible à la fréquence de fonctionnement de l'oscillateur. L'entrée de l'amplificateur ici c'est l'émetteur et le signal de rétro-action est fournie à travers C2. C2 est choisi de sorte qu'il y a suffisamment de signal qui est retourné à l'entrée de l'amplificateur pour maintenir une oscillation stable. Si C2 fourni trop de rétro-action au lieu d'avoir une onde sinusoïdale à la sortie on va avoir de la distorsion, sa valeur ne doit donc être ni trop grande ni trop petite.

J'ai mentionné le terme base commune. Il y a 3 types de montages pour les transistors bi-jonctions, base-commune, émetteur-commun qui est le plus utilisé et finalement collecteur-commun. On peut fabriquer un oscillateur avec n'importe quel type de montage. Le critère pour obtenir une oscillation soutenue est que le gain en boucle fermée soit >= 1. Avec un gain 1 l'onde est sinusoïdale, supérieur à 1 on ajoute de la distorsion. Un gain de 1 signifie qu'on ajoute juste de qu'il faut d'énergie au circuit accordé pour compenser les pertes du aux résistances parasites. A cette valeur de gain on obtient une onde sinusoïdale d'amplitude constante.

Oscillateur à cristal

J'ai commencé cet article par une analogie mécanique, l'oscillateur à cristal est intéressant parce qu'il est à la fois mécanique et électronique. En effet il utilise l'effet piézo-électrique qui est un phénomène électro-mécanique. Un cristal est constitué d'une lamelle de quartz avec une électrode sur chaque face. Lorsqu'une tension électrique est appliquée sur ces électrodes il y a une déformation mécanique du cristal. Lorsque cette tension électrique est relâchée le cristal oscille à une fréquence précise. Comme pour un pendule cette oscillation va s'amortir si elle n'est pas entretenue. N'essayer pas de sortir un cristal de son boitier pour le voir osciller, cette oscillation est à l'échelle microscopique au niveau du réseau d'atomes.

Le schéma suivant illustre un oscillateur à cristal dans un montage collecteur-commun. On l'appelle ainsi car le collecteur est au commun de l'alimentation car en haute fréquence la résistance entre le collecteur et le commun est à toute fin pratique nulle. Ici l'entrée de l'amplificateur c'est la base et la sortie c'est l'émetteur.

C1 et C2 forment un diviseur de tension qui permet de déterminer la valeur de la rétro-action. Ils ont aussi une influence sur la fréquence d'oscillation du cristal puisqu'ils sont en parallèle avec celui-ci.

Oscillateur avec porte logique

Habituellement dans les montages en circuits logiques ont utilise des portes logiques pour fabriquer l'oscillateur. En voici une illustration.

Ici un inverseur est utilisé dans un montage dit Pierce gate oscillator. La résistance de 1M produit une rétro-action négative de sorte que la porte fonctionne comme un amplificateur linéaire au lieu de son mode logique normal. Notez qu'il s'agit d'un inverseur donc le signal en sortie est en anti-phase avec l'entrée. Donc pour produire une oscillation soutenue il faut ajouter un déphasage supplémentaire de 180 degrés. Un déphasage de 360 degrés est équivalent à 0 degrés donc en phase. Le réseau formé par XTAL,C1,C2,C3 produit le déphasage nécessaire. La résistance de 1K réduit l'intensité de la rétro-action. Les condensateurs C1,C2,C3 ont un influence sur la fréquence d'oscillation, c'est pourquoi C1 est ajustable. En pratique dans la majorité des cas on néglige l'installation de C1à moins que le montage requiert une très grande précision en fréquence. Les MCUs qui ont un circuit pour oscillateur à cristal en interne utilisent en fait ce type de montage.

Pour conclure voici un vidéo qui montre comment fabriquer un mouchard qui transmet dans la bande FM. Une recherche dans Google permet de trouver de nombreux exemples de ce type de montage ainsi que plusieurs autres vidéo sur youtube.

Arduino + pro trinket

$
0
0

Cet article est une présentation du projet open source Arduino ainsi que de la carte d'expérimentation pro trinket d'Adrafuit.

Arduino1 est une série de carte microcontrôleurs pour le prototypage rapide et simplifié. Le projet a démarré en 2005 à l'institue de design Ivrea en Italie. Il avait pour but de fournir aux étudiants un remplacement aux BASIC stamp vendu par Parallax jugés trop coûteux. Le projet a rapidement gagné en popularité et est aujourd'hui le plus populaire auprès des amateurs et artistes dans le monde entier. Aujourd'hui il existe de nombreuses cartes clones tel que les trinkets d'Adafruit. Sur la première carte le processeur utilisé était un atMega8, mais maintenant il y a différent modèles avec des processeurs plus puissants dont le Due avec un processeur Atmel SAM3X8E ARM Cortex-M3.

Pour les démos de cet article j'utilise un pro trinket d'Adafruit comme mentionné ci-haut. Les cartes Arduino viennent avec un firmware pré-installé dans le MCU qui sert à télécharger les applications écrites dans l'IDE. L'intérêt ce ces cartes pour les amateurs est qu'il n'est pas nécessaire de potasser les spécifications du MCU car les périphériques sont pré-configurés et qu'il existe un API de programmation simplifié. C'est d'ailleurs ce qui a fait la popularité de ce projet.

Environnement de développement

Adruino possède son propre IDE disponible gratuitement en téléchargement. Pour l'utilisation des trinkets il est préférable de télécharger la version fournie par Adafruit qui est adaptée aux cartes vendues par cette compagnie. L'IDE comme les cartes est simplifié, il est donc facile à prendre en main, d'autant plus qu'il est multilingues. Les menus s'affichent dans la langue du système d'exploitation.

La première chose à faire une fois le logiciel installé est de sélectionner le type de carte utilisé en allant dans le menu outils - type de carte.

Ensuite on peut se débrouiller avec les 5 boutons de gauche sur la barre d'outils qui apparaît sous le menu. Le crochet sert à compiler le programme. s'il y a des erreurs elles sont affichées dans une fenêtre en bas de l'IDE.

Lorsqu'un programme compile correctement on peut le téléversé sur la carte en cliquant sur le 2ième bouton flèche vers la droite. En ce qui concerne le pro trinket il faut peser d'abord sur le bouton reset pour que le bootloader s'active. Le bootloader attend 10 secondes avant de retourner au programme utilisateur.

Le 3ième bouton feuille avec coin plié sert à créer un nouveau projet. Chaque projet apparaît dans une fenêtre séparée.

Le quatrième bouton flèche vers le haut sert à ouvrir un projet existant.

le cinquième bouton flèche vers la bas sert à sauvegarder le projet sur le disque dur.

Le langage de programmation utilise la même syntaxe que C/C++ au point ou nombreux sont ceux qui pensent que c'en est. Il s'agit en fait du langage Wiring, une version simplifié de C++. Il n'y a pas de fonction main()à la place il y a 2 fonctions obligatoires. void setup() qui est exécutée automatiquement au démarrage du processeur et sert à l'initialisation. void loop() qui une boucle dans laquelle le programme principal s'exécute indéfiniment jusqu'à la réinitialisation du MCU.

Donc lorsque vous avez créé un nouveau projet vous devriez inscrire le squelette de ces fonctions avant toute chose. La référence du langage est disponible ici. Si vous connaissez le C/C++ la prise en main sera simple et rapide. Cependant la fonction loop m'a réservée une petite surprise, j'en reparle plus bas.

cartes trinkets

Adafruit vends 4 cartes trinkets. En fait il y a 2 modèles mais une version 5 volt et 3 volt pour chaque modèle. Le trinket (6,95US$) utilise un MCU atTiny84 et a peut de I/O. Le pro trinket (9,95US$) utilise un MCU atMega328P et a plus de I/O. Les cartes on une largeur de 600mil avec espacement entre les broches de 100mil ce qui permet de les brancher sur une carte de prototypage sans soudure. Ces cartes peuvent-être commandées directement via le site d'Adafruit mais aussi chez Digikey.

Premier démo

Écrire un programme qui fait varier en intensité une LED de manière cyclique en utilisant une sortie PWM est si simple avec Arduino qu'on va sauter le traditionnel blinky pour y passer directement. Le montage est simple, il suffit de brancher une LED en série avec une résistance sur une sortie PWM. Sur les cartes trinket ces sorties sont identifiées avec une barre au dessus du numéro. J'ai choisi la sortie 3. Simple n'est-ce pas? Notez que la fonction setup() doit-être présente même si elle est vide. La fonction analogWrite détermine la valeur du rapport cyclique sur les sortie PWM. Cette valeur varie de 0 à 255.

Surprise

La surprise dont je parlais plus haut concerne les variables i et delta. Normalement ces variables devraient-être locales à la fonction loop. Donc dans ma première version je les avaient définies et initialisées au début de loop().


void loop(){
byte i=0;
char delta=1;

Ça ne fonctionnais pas et je me grattais la tête à me demander pourquoi? En C/C++ ça aurait fonctionner car les variables locales ne sont initialisées que lors de l'entrée dans la fonction. Mais ici elles le sont à chaque bouclage!!! Même si la syntaxe est à s'y méprendre ce n'est pas C/C++ c'est Wiring. J'ai donc du définir ces 2 variables au niveau global.

Clap switch

J'ai vu ça dans un commercial à la télé cette semaine, un gadget qui allume ou éteint un lampe en claquant dans les mains. J'ai décidé d'essayer ça en utilisant le trinket. Mon démo utilise la LED rouge qui est sur le trinket et branchée sur la sortie digitale 13. J'ai aussi conservé la LED sur la sortie barre-3 comme indicateur d'intensité sonore. Voici le circuit.

Le signal d'un microphone de type electret est amplifié par le transistor Q1 puis redressé et filtré pour ne garder que l'enveloppe du signal. Si on observe à l'oscilloscope le signal au bornes de C3-R4 on obtient ceci lors d'un claquement de mains.
Le niveau sonore monte rapidement pour diminuer lentement pour une durée totale d'environ 135 millisecondes.

J'ai testé 2 versions différentes du logiciel et elle se valent, en sensibilité et en taux de détection.

La première version utilise un seuil de déclenchement et celle-ci utilise un taux de changement entre 2 lectures. Il doit y avoir 2 claquements de main avec un intervalle maximum de 500 millisecondes entre chaque. La switch répond aussi aux sifflements.


1) Article plus complet sur le wikipedia anglophone.

Viewing all 192 articles
Browse latest View live