Chenillard 16 voies

 

Réalisé en 1997, ce chenillard utilise un micro-contrôleur ST6225 aidé d'un driver MM5450

Manuel d'inztruczion: on a 16 boutons: quand on presse brièvement un bouton, on lance ou on arrête l'une des seize animations lumineuses, dont la vitesse est réglable par potentiomètre. Si l'on maintient un bouton pressé plus longtemp, alors on force la voie correspondante successivement à ON, OFF ou AUTO.

Aspect extérieur

Câblage interne

Schéma théorique

Description

Ce " chenillard " comporte 16 voies indépendantes : il permet de faire défiler 16 motifs différents, à une vitesse variable. De plus, chaque sortie peut être forcée à l'allumage ou à l'extinction, ce qui augmente les possibilités.

Caractéristiques principales :

- Alimentation sur secteur monophasé 240 Veff 50 Hz, par câble 2 + T et socle type filtre limitant la propagation des parasites.
- Interrupteur Marche / Arrêt général bipolaire, avec voyant de mise en marche.
- 16 boutons poussoirs permettent de lancer un motif, l'arrêter , et forcer les sorties. Ces boutons comprennent des voyants lumineux afin de visualiser le motif joué.
- Potentiomètre de réglage de la vitesse de défilement, entre 1 motif complet en environ 0.5s (la plus rapide : les 16 sorties sont balayées en 0.5s) et 1 motif toutes les 5s environ.
- Protection de la partie commande, et protection individuelle de chaque sortie, par fusibles.
- Déclenchement des triacs au zéro de tension secteur, limitant la création de parasites, avec filtres RC sur toutes les sorties à triacs, et commande via des opto triacs.

Schéma :

La gestion de l'ensemble est confiée à un microcontrôleur ST 6225, dont les ports A et B sont configurés en entrées avec résistances de rappel, et scrutent en permanence les boutons poussoirs. Le port C est utilisé de trois façons différentes :

- En entrée analogique (PC7), pour le potentiomètre de variation de vitesse
- En entrée Tout Ou Rien (PC4), pour la détection du zéro de tension secteur
- En sortie symétrique (PC5 et PC6), pour le dialogue série avec le composant MM5450

Ce composant MM5450 est un driver de puissance, bien pratique pour commander en intensité jusqu'à 34 charges (ici les DELs et les opto triacs). La valeur de cette intensité est fixée par la résistance R1.

Chaque triac de sortie est associé à un opto triac, qui permet de limiter la propagation des dégâts en cas de problème. De plus, un réseau RC limite la vitesse de variation de la tension aux bornes du triac, qui peut provoquer des enclenchements intempestifs (dV/dt).

L'alimentation basse tension est classique, avec transformateur, redresseur, filtrage, régulation, plus un petit montage annexe composé de D18 à D20, R34 et R35, qui va permettre au microcontrôleur de connaître l'instant où la tension secteur s'annule, afin d'enclencher les triacs à ce moment, et limiter ainsi la création de parasites.

Le programme source ne peut pas être placé dans l'article : il fait 24 pages ! Il faut dire qu'il est très largement commenté, et que tout y est détaillé : calcul des temporisations, dialogue entre ST6225 et MM5450, chien de garde, gestion des boutons poussoirs, " zéro cross ", etc. Il est téléchargeable sur le site de la revue, ainsi que le fichier binaire associé.

Un mot à propos de la puissance :

- L'appareil est prévu pour des charges résistives, à savoir de simples ampoules à filament.

- En l'absence de radiateurs sur les triacs, il est conseillé de ne pas dépasser une puissance de 240 W environ par voie ( soit 1 A en 240 V avec un cos j de 1).

- La puissance totale absorbée ne doit pas dépasser 2400 W :

- Aucun problème en mode automatique, les motifs utilisés n'allumant jamais toutes les lampes en même temps.

- Par contre, avec des forçages en mode manuel, il faudra être prudent, et veiller à ne pas dépasser une puissance globale de 2400 W (on peut s'affranchir de cette contrainte en limitant la puissance par sortie à 150 W).

Réalisation :

- Ce montage travaille sur le secteur, et le plus grand soin s'impose pour sa réalisation : Fil de câblage souple de 1.5 mm², cosses rapides isolées, fixer les câbles avec des liens plastiques, vernir le coté cuivre du circuit imprimé, relier le boîtier métallique à la terre, utiliser des entretoises pour éloigner le circuit imprimé du boîtier d'au moins 5 mm.

- Les filtres RC des triacs doivent impérativement être réalisés avec des condensateurs dont la tension de service est de 400V, et des résistances de ½ W.

- Vous pouvez modifier les motifs, soit en modifiant le fichier source, et en assemblant à nouveau, soit encore, en réalisant un " patch " sur le fichier binaire, à l'aide d'un éditeur binaire : repérer la séquence du motif à modifier, et la remplacer par la séquence désirée.

Utilisation :

- Utiliser impérativement un câble d'alimentation 2 + terre, et brancher toujours l'appareil sur une prise munie d'une terre.

- A la mise sous tension, le chenillard est arrêté, et les sorties sont en mode automatique.

- Si l'on presse sur un bouton poussoir quelconque moins de 0.5 s environ, alors que tout est arrêté, on lance le motif qui correspond au bouton pressé (il y a 16 motifs différents, correspondant aux 16 boutons poussoirs différents).

- Si l'on presse sur un bouton poussoir quelconque moins de 0.5 s environ, alors qu'un motif est en train de défiler, on arrête le motif en cours.

- Si l'on presse sur un bouton poussoir quelconque plus de 0.5 s environ, on force la sortie qui correspond au bouton pressé (bouton 1 > sortie 1, bouton 2 > sortie 2, etc.) : le forçage est le suivant : première pression du bouton, forçage à 1, c'est à dire que la sortie reste toujours enclenchée. Seconde pression sur le même bouton, forçage à 0, c'est à dire que la sortie reste toujours arrêtée. Troisième pression sur le bouton, la sortie retourne en mode automatique, c'est à dire qu'elle est gérée par le motif.

- La combinaison des motifs et des forçages permet de varier les animations lumineuses.

Attention :

- Lorsque l'on débranche l'appareil, une tension subsiste pendant quelques secondes sur les broches mâles de la prise secteur, liée à la présence du condensateur de filtrage incorporé dans le filtre secteur : cette tension, non dangereuse, est cependant fort désagréable : éviter le contact des broches pendant les quelques secondes qui suivent le débranchement de l'appareil.

- A l'intérieur du boîtier, plusieurs composants sont reliés directement au secteur : ne pas introduire d'objet dans le boîtier par les ouies d'aération, ni renverser de liquide.

- Si l'ouverture du boîtier est nécessaire, par exemple pour changer un fusible, il est impératif de débrancher au préalable l'appareil.

Typon (à remettre à l'échelle: extérieur 210 * 158 mm)

Liste des composants

Chenillard 16 voies

Résistances (1/4 W sauf contre indication)
-----------
1   R1                                      2.2 kohm
16  R2,R4,R6,R8,R10,R12,R14,R16,R18,        100 ohm 1/2W
    R20,R22,R24,R26,R28,R30,R32
16  R3,R5,R7,R9,R11,R13,R15,R17,R19,        220 ohm
    R21,R23,R25,R27,R29,R31,R33
1   R34                                     100 kohm
1   R35                                     10 kohm

Condensateurs
-------------
2   C1,C2                                   22 pF
2   C3,C4			 	    100 nF 63V
16  C7,C8,C9,C10,C11,C12,C13,C14,C15, C16   100 nF 400 V
    C17,C18,C19,C20,C21,C22
1   C5                                      670 nF 63V
1   C6                                      1000 microF 16V

Circuits intégrés
-----------------
1   U1                                      Micro contrôleur ST 6225
1   U2                                      Régulateur 7805
1   U3                                      Driver de leds MM5450N
16  U4,U5,U6,U7,U8,U9,U10,U11,U12,U13,      Opto triac MOC3023
    U14,U15,U16,U17,U18,U19

Diodes
------
16  D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,     Del (intégrées aux BP)
    D12,D13,D14,D15,D16
1   D17                                     Pont 0.2A
3   D18,D19,D20                             1N914

Divers
------
16  FU1,FU2,FU3,FU4,FU5,FU6,FU7,FU8,        Fusible rapide 2A
    FU9,FU10,FU11,FU12,FU13,FU14,FU15,
    FU16
1   FU17                                    Fusible lent 0.1A
16  I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,     Bouton poussoir NO
    I12,I13,I14,I15,I16,
16  T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,	    Triac 4A 600V type ST 435 600D
    T12,T13,T14,T15,T16
1   I17                                     Interrupteur double 250V 10A
1   P1                                      Potentiomètre 10k linéaire
1   TR1                                     Transformateur plat 240/6V 10VA
1   X1                                      Quartz 3.2768MHz

1   Boîtier type rack 19 pouces
1   Socle mâle antiparasite VDE 10A 250V 2 + terre
1   Cordon secteur 10A 250V 2 + terre
16  Socles femelles CEE 10A 2 + terre
16  Prises mâles CEE 2 + terre
Divers: Pieds, entretoises, visserie, borniers de jonction 2 broches
	Cosses fast on, gaine thermorétractable, fil souple 1.5 mm².

Schéma d'implantation

Fichier assembleur

;---------------------------------------------------------------------------
;                    Programme pour chenillard 16 voies
;
;                           Carte à base de ST6225
;
;                                  dB
;
;                                  28/02/99
;
;       Fonctionnement:
;
;       A la mise sous tension, tout est éteint
;
;       Si on presse un BP quelconque moins de 0.5 s alors que tout est
;       arrêté, on lance le motif correspondant au BP pressé (les leds
;       suivent les triacs)
;
;       Si on presse un BP quelconque moins de 0.5 s alors qu'un motif
;       est exécuté, on arrête le motif.
;
;       Si on presse un BP plus de 0.5 s, forçage de la sortie, avec un
;       cycle ON/OFF/AUTO/ON/OFF/AUTO/...
;
;       Pour diminuer les parasites, le déclenchement des triacs se fait
;       peu après le passage à zéro du secteur, lequel est surveillé par
;       la broche PC4: après abaissement par un transformateur, on se
;       retrouve en tension sinusoïdale de 8.5 V d'amplitude (6 Veff), puis
;       redressement en double alternance par deux diodes signal et un pont
;       de puissance, ce qui amène donc un seuil d'environ 2 * 0.6 V = 1.2 V.
;
;       Le temps pendant lequel la broche PC4 du ST6225 est au niveau logique
;       zéro (soit inférieur à 1.6 V pour une alimentation en 5 V) est donc
;       à peu près égal à deux fois celui mis par la sinusoïde de 8.5 V
;       d'amplitude pour passer de 0 V à (1.6 + 1.2) = 2.8 V.
;
;       On a donc: 8 * sin (2 * pi * 50 * t) = 2.8, ce qui donne:
;
;               t = (asin (2.8 / 8)) / ( 2 * pi * 50 ), soit 1.1 ms
;
;               On double (chûte première sinusoïde, et montée suivante), et
;               on trouve donc finalement un temps pour le niveau logique 0
;               égal à environ 2 * 1.1 = 2.2 ms
;
;       Remarques:
;
;       a) Led 1: celle située la plus à gauche quand on regarde la façade
;       b) Bouton poussoir 1: idem
;       c) Sortie 1: idem
;
;               Récapitulation:
;
;            ------------ MSB ------------   ------------ LSB ------------
;    Motif   7   6   5   4   3   2   1   0   7   6   5   4   3   2   1   0

;    Led     1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
;    MM5450 16  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1

;    Triacs  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
;    MM5450 19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34

;    BP      1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
;    Port  PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7

;       d) Gestion du watchdog qui ne peut être masqué sur les versions
;          ST62E25FI-HWD
;       e) Utilisation de call subroutines
;       f) Travail sans interruptions
;
;       Essentiel sur le ST6225, très difficile à retrouver dans un certain
;       livre sur les ST62XX particulièrement mal fait, et dont je tairai
;       le nom:
;
;       Drapeaux                C       retenue
;                               Z       zéro
;
;       Flag Carry du ST6225 (différent pour un ST60):
;               - mis à 1 si dépassement capacité lors d'additions ADD ADDI
;               - contient le MSB du registre avant un complément COM
;               - mis à 1 si A < toto et mis à 0 si A>= toto
;                 dans CP A, toto et CPI A, toto
;               - contient l'ancien MSB du registre après un RLC
;                 (et le nouveau LSB du registre est l'ancien flag C)
;               - contient l'ancien MSB du registre après un SLA
;                 (et le nouveau LSB du registre est 0)
;               - mis à 1 si A < toto et mis à 0 si A>= toto
;                 dans SUB A, toto et SUBI A, toto
;
;       Espace mémoire          ST6210/20       Les deux        ST6215/25
;               Fenêtre ROM                     040h  à 07Fh
;               Registre X                      080h
;               Registre Y                      081h
;               Registre V                      082h
;               Registre W                      083h
;               Données RAM                     084h à 0BFh
;               Registre DRA                    0C0h
;               Registre DRB                    0C1h
;               Registre DRC                    0C2h
;               Registre DDRA                   0C4h
;               Registre DDRB                   0C5h
;               Registre DDRC                   0C6h
;               Registre IOR                    0C8h
;               Registre DRWR                   0C9h
;               Registre ORA                    0CCh
;               Registre ORB                    0CDh
;               Registre ORC                    0CEh
;               Registre ADR                    0D0h
;               Registre ADCR                   0D1h
;               Registre PSC                    0D2h
;               Registre TCR                    0D3h
;               Registre TSCR                   0D4h
;               Registre WDR                    0D8h
;               Registre 8b A                   0FFh
;               Programme       880h à F9Fh                     080h à F9Fh
;               Vecteur CAN                     FF0h & FF1h
;               Vecteur Timer                   FF2h & FF3h
;               Vecteur Pb & Pc                 FF4h & FF5h
;               Vecteur Pa                      FF6h & FF7h
;               Vecteur Nmi                     FFCh & FFDh
;               Vecteur Reset                   FFEh & FFFh
;
;       Configuration des entrées sorties: ports A, B, C
;       bit DDR bit OR  bit DR  Mode
;       0       0       0       Entrée avec rappel, ss interruption (initial)
;       0       0       1       Entrée sans rappel ni interruption
;       0       1       0       Entrée avec rappel et interruption
;       0       1       1       Entrée sans rappel ni interruption (PA0 à 3)
;                               ou Entrée  analogique (autres)
;       1       0       X       Sortie drain ouvert 10 mA (PA0 à 3)
;                               ou Sortie drain ouvert 5 mA (autres)
;                               X est l'état dans lequel la sortie est placée
;                               1 = haut  et 0 = bas
;       1       1       X       Sortie symétrique
;                               X est l'état dans lequel la sortie est placée
;                               1 = haut  et 0 = bas
;
;       Attention: ne pas utiliser de set ou reset sur les bits d'un
;       registre DRA, DRB ou DRC, car il y a alors lecture, positionnement et
;       réécriture: la lecture n'étant pas fiable (certains registres sont
;       à écriture seule), en faisant cela on peut modifier la configuration
;       du registre.
;
;       1 cycle = 13 périodes de l'oscillateur, soit ici 3.97 µs avec le
;       quartz à 3.2768 MHz. Avec en moyenne 4 cycles par instruction,
;       on trouve un temps approximatif de 15.9 µs par instruction, et donc
;       on pourra exécuter environ (10E-3 - 2.21E-3)/(15.9E-6) = 490
;       instructions pendant la fenêtre dans laquelle il n'y a pas de zéro
;       secteur, ce qui est très juste.
;
;       Convertisseur analogique > numérique:
;
;       Registre ADR à lecture seule, pour le résultat
;
;       Registre ADCR pour le contrôle
;       ADCR    b7    b6    b5    b4    b3    b2    b1    b0
;               EAI   EOC   STA   PDS   -     -     -     -
;
;               Bit             0                      1
;               PDS        CAN inactif         CAN prêt ou en cours
;               STA     Doit être mis à 0      Au front montant, déclenche
;                       avant une acquisition  une acquisition
;               EOC     Mis à 0 quand STA      Mis à 1 en fin de conversion
;                       passe à 1
;               EAI     Pas d'interruption     Interruption ADC générée en
;                                              fin de conversion
;       La fréquence du quartz doit être au moins de 1.2 MHz pour pouvoir
;       utiliser le CAN.

;       Fenêtre ROM: la mémoire ROM n'est accessible que via une fenêtre de
;       64 octets dans l'espace adressable par le micro. L'adresse du premier
;       octet de la fenêtre est 0040h, et celle du dernier octet est 007Fh.
;       On choisi le segment de ROM visible dans la fenêtre par le chargement
;       préalable du registre Data Rom Window Register, l'adresse dans la ROM
;       étant définie ainsi sur 12 bits:
;
;       Adresse ROM          11 10 09 08 07 06 05 04 03 02 01 00
;               DRWR   00 00 D5 D4 D3 D2 D1 D0
;       Adresse dans fenêtre              0  1 D5 D4 D3 D2 D1 D0
;                                            î
;                                            Ce 1 est là car la première
;                                            adresse de la fenêtre est 64
;
;       Timer: un registre TCR (compteur) et un registre TSCR (contrôle)
;
;       registre TSCR:
;       b7   b6   b5   b4   b3   b2   b1   b0
;       TMZ  ETI  TOUT DOUT PSI  PS2  PS1  PS0
;
;       TMZ : Mis à 1 si le registre TCR passe à 0, et déclenche une
;             interruption si ETI est à 1
;
;       ETI : autorise les interruptions, si mis à 1

;       TOUT DOUT TMZ   Déterminent la fonction de la broche Timer ainsi:
;         0    0    -   Entrée, front montant actif, compteur d'évennements
;         0    1    -   Entrée, niveau 1 = comptage horloge interne
;                                      0 = arrêt comptage
;                                      utilisé pour mesure durées
;         1    -    0   Sortie, niveau = valeur précédente
;         1    0    1   Sortie, niveau = 0 (DOUT) } utilisé pour générer un
;         1    1    1   Sortie, niveau = 1 (DOUT) } niveau en fin comptage
;
;       PSI : Si mis à 1, commande la mise à 1 de tous les bits du TCR et du
;             prédiviseur PSC, et autorise fonctionnement et accès.
;             Si mis à 0, le TCR est gelé et le PSC est forcé à 7Fh
;
;       PS2     PS1     PS0     Rapport de division
;         0       0       0     1
;         0       0       1     2
;         0       1       0     4
;         0       1       1     8
;         1       0       0     16
;         1       0       1     32
;         1       1       0     64
;         1       1       1     128
;
;       Chien de garde : registre DWDR dont les bits DWDR1 (MSB ! ) à
;       DWDR7 (LSB !) sont décrémentés à une fréquence égale à celle du
;       quartz, divisée par 3072: en fait, le basculement du bit DWDR2
;       provoque un reset, donc la valeur utile du watchdog se charge
;       sur DWD2 à DWD7, soit un mot de 6 bits, variant donc de 0 à 63.
;       Comme il faut 13 coups d'horloge pour un cycle machine, le registre
;       DWDR est donc décrémenté tous les 3072 / 13 = 236 cycles machine
;       environ, soit en moyenne toutes les 59 instructions.

;       Après un reset, le chien de garde doit être réarmé avant la 28ème
;       instruction, et ensuite au moins toutes les 59 instructions environ,
;       pour un rechargement avec la valeur 10000000b, et toutes les 3750
;       instructions environ, pour un rechargement avec la valeur 11111110b.

;       Brochage du MM 5450
;
;                       Broche  Fonction        Composant
;                        1      Vss
;                        2      Q17             NC             
;                        3      Q16             Led 1 (La plus à gauche)
;                        4      Q15             Led 2
;                        5      Q14             Led 3
;                        6      Q13             Led 4
;                        7      Q12             Led 5            
;                        8      Q11             Led 6            
;                        9      Q10             Led 7            
;                       10      Q 9             Led 8            
;                       11      Q 8             Led 9            
;                       12      Q 7             Led 10            
;                       13      Q 6             Led 11            
;                       14      Q 5             Led 12            
;                       15      Q 4             Led 13            
;                       16      Q 3             Led 14            
;                       17      Q 2             Led 15            
;                       18      Q 1             Led 16            
;                       19      Réglage luminosite
;                       20      Vdd
;                       21      Horloge
;                       22      Data
;                       23      /Enable
;                       24      Q34             Sortie triac 16
;                       25      Q33             Sortie triac 15
;                       26      Q32             Sortie triac 14             
;                       27      Q31             Sortie triac 13             
;                       28      Q30             Sortie triac 12             
;                       29      Q29             Sortie triac 11             
;                       30      Q28             Sortie triac 10             
;                       31      Q27             Sortie triac 9             
;                       32      Q26             Sortie triac 8             
;                       33      Q25             Sortie triac 7             
;                       34      Q24             Sortie triac 6             
;                       35      Q23             Sortie triac 5             
;                       36      Q22             Sortie triac 4             
;                       37      Q21             Sortie triac 3             
;                       38      Q20             Sortie triac 2             
;                       39      Q19             Sortie triac 1             
;                       40      Q18             NC             
;
;       Dialogue avec le MM 5450
;
;                       - Validation sur front montant horloge
;                       - Fréquence maximale horloge: 500 kHz
;                       - Envoi dans l'ordre de 1, Q1, ..., Q35
;                         (Q35 inexistante mais doit être gérée pour
;                         compatibilité avec le MM 5451)
;                       - Séquence: positionnement data
;                                   attente de 300 ns
;                                   montée de l'horloge
;                                   attente de 300 ns
;                                   descente de l'horloge
;                                   etc ...
;                       La tempo de 300 ns n'est pas gérée par le timer
;                       mais se fait si besoin par boucle d'attente, et en
;                       fait il n'y en a pas besoin ici, car avec une
;                       horloge à 3.2768 MHz, on a un temps de cycle de
;                       1 / (3.2768 E6 / 13) = 3.9 µs, soit un temps
;                       d'instruction de 15.8 µs environ, largement au
;                       dessus des 300 ns nécessaires.
;
;       Affectation des E/S:
;
;                       - PA0: entrée bouton poussoir 1 ( 0 si enfoncé)
;                       - PA1: entrée bouton poussoir 2 ( 0 si enfoncé)
;                       - PA2: entrée bouton poussoir 3 ( 0 si enfoncé)
;                       - PA3: entrée bouton poussoir 4 ( 0 si enfoncé)
;                       - PA4: entrée bouton poussoir 5 ( 0 si enfoncé)
;                       - PA5: entrée bouton poussoir 6 ( 0 si enfoncé)
;                       - PA6: entrée bouton poussoir 7 ( 0 si enfoncé)
;                       - PA7: entrée bouton poussoir 8 ( 0 si enfoncé)
;
;                       - PB0: entrée bouton poussoir 9 ( 0 si enfoncé)
;                       - PB1: entrée bouton poussoir 10 ( 0 si enfoncé)
;                       - PB2: entrée bouton poussoir 11 ( 0 si enfoncé)
;                       - PB3: entrée bouton poussoir 12 ( 0 si enfoncé)
;                       - PB4: entrée bouton poussoir 13 ( 0 si enfoncé)
;                       - PB5: entrée bouton poussoir 14 ( 0 si enfoncé)
;                       - PB6: entrée bouton poussoir 15 ( 0 si enfoncé)
;                       - PB7: entrée bouton poussoir 16 ( 0 si enfoncé)
;
;                       - PC4: entrée détection zéro secteur
;                       - PC5: horloge MM5450
;                       - PC6: données MM5450
;                       - PC7: entrée tension potentiomètre vitesse
;                              (0 V quand le potentiomètre est tourné à fond
;                              dans le sens lévogyre, et + 5 V si tourné à
;                              fond dans le sens dextrogyre (aiguilles d'une
;                              montre)).
;
;       Ne pas oublier:
;
;               - effacage aux U.V. 30 minutes
;               - d'obstruer la fenêtre du ST6225 après programmation ou
;                 mieux griller un OTP (composant non effaçable, et donc
;                 programmable une seule fois), quand tout est OK.
;
;	Assemblage du programme:
;
;               - Le programme assembleur source est par exemple CHENILLE.ASM
;               - Pour un ST6225, l'assembler par AST6 -L CHENILLE
;
;	Programmation du ST6:
;
;               - copier le programme assemblé (.hex) sur la disquette
;                 bootable chenille
;               - Rebooter le PC sur cette disquette (démarrage sous un
;                 ancien DOS, le logiciel ne tournant pas sous WIN95)
;               - Utiliser la carte branchée sur le port parallèle
;               - Alimenter la carte en 12V DC
;		- Lancer le programme ST6PGM.BAT
;
;
;---------------------------------------------------------------------------
;                           Directives d'assemblage

                .title "Chenillard"             ; titre sur le listing
		.vers "st6225"
                .input "6215_reg.asm"           ; définition noms registres


;---------------------------------------------------------------------------
;         Définition des constantes utilisées pour l'assembleur

ktempo          .equ 5                  ; valeur chargée dans TCR qui donne
                                        ; un pulse de 58.59 * 5 = 293 µs

kdureebp        .equ 5                  ; (5-1) * .293 * 256 = 300 ms tst BP

knonos          .equ 254                ; Un gros os pour le chien de garde
                                        ; qui va ronger pendant 15000 cycles
                                        ; soit environ 3750 instructions


;---------------------------------------------------------------------------
;              Définition des emplacements des variables en RAM

brouill         .def 0084h              ; variable servant de brouillon
dureebp         .def 0085h              ; tempo décrémentée pression BP

       ; Flags de forçage ci-dessous: 0 si pas de forçage, 1 si forçage
f0tr0108        .def 0086h              ; flags forçage à zéro sorties 1 à 8
f0tr0916        .def 0087h              ; flags forçage à zéro sorties 9 à 16
f1tr0108        .def 0088h              ; flags forçage à un sorties 1 à 8
f1tr0916        .def 0089h              ; flags forçage à un sorties 9 à 16

flags           .def 008Ah              ; drapeaux
                                        ; b0 à 1 si traitement BP en cours
                                        ; b1 bit à envoyer au MM5450
                                        ; b2
                                        ; b3
                                        ; b4
                                        ; b5
                                        ; b6
                                        ; b7
imagepa         .def 008Bh              ; image du port A (BP 1 à 8) COMPLEM
imagepb         .def 008Ch              ; image du port B (BP 9 à 16) COMPLEM

       ; Les images des ports sont complémentées car quand un bouton poussoir
       ; est pressé, cela donne un niveau 0 plus long à gérer qu'un 1

ligne           .def 008Dh              ; numéro de la ligne du motif: 0 à 15
lignelsb        .def 008Eh              ; octet faible de la ligne jouée
lignemsb        .def 008Fh              ; octet fort de la ligne jouée
mempa           .def 0090h              ; Mémoire de imagepa
mempb           .def 0091h              ; Mémoire de imagepb
motif           .def 0092h              ; numéro du motif choisi: 0 à 16
numbit          .def 0093h              ; numéro du bit envoyé au MM5450
tempobp         .def 0094h              ; variable décrémentée dans gesttemp
tension         .def 0095h              ; tension potentiomètre mesurée


;---------------------------------------------------------------------------
;   Définition des vecteurs d'interruption CAN, timer, ports, NMI et reset
;   Travail sans aucune interruption

                .org 0FF0h              ; Vecteurs d'interruption CAN
                reti

                .org 0FF2h              ; Vecteur d'interruption du timer
                reti

                .org 0FF4h              ; Vecteur interruption ports B & C
                reti

                .org 0FF6h              ; Vecteur interruption port A
                reti

                .org 0FFCh              ; Vecteur interruption NMI
                reti

                .org 0FFEh              ; Vecteur de reset
                jp reset


;---------------------------------------------------------------------------
;       Table de données contenant les différents motifs du chenillard
;       Il y a 16 motifs utiles différents: Motif01 à Motif16: chacun
;       comprend 16 étapes sur 16 bits (2 octets) soit 16 * 16 * 2 = 512
;       octets à définir. Un 17ème motif vide, le Motif00, permet une
;       extinction totale.

;       Les octets sont rangés ainsi:
;               adresse         octet
;               0C00h           fort   ligne 1 motif 00
;               0C01h           faible ligne 1 motif 00
;               0C02h           fort   ligne 2 motif 00
;               0C03h           faible ligne 2 motif 00
;               etc ...

                .org 0C00h

Motif00         .byte 00000000b, 00000000b      ; Vide: c'est celui qui
                .byte 00000000b, 00000000b      ; est joué pour l'extinction
                .byte 00000000b, 00000000b      ; totale
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00000000b

Motif01         .byte 10001000b, 10001000b      ; Progression sur 4 sorties
                .byte 01000100b, 01000100b      ; Ce motif peut être utilisé
                .byte 00100010b, 00100010b      ; avec 4, 8 ou 16 sorties
                .byte 00010001b, 00010001b
                .byte 10001000b, 10001000b
                .byte 01000100b, 01000100b
                .byte 00100010b, 00100010b
                .byte 00010001b, 00010001b
                .byte 10001000b, 10001000b
                .byte 01000100b, 01000100b
                .byte 00100010b, 00100010b
                .byte 00010001b, 00010001b
                .byte 10001000b, 10001000b
                .byte 01000100b, 01000100b
                .byte 00100010b, 00100010b
                .byte 00010001b, 00010001b

Motif02         .byte 10000000b, 00000000b      ; Ricochet
                .byte 00000000b, 00000001b
                .byte 01000000b, 00000000b
                .byte 00000000b, 00000010b
                .byte 00100000b, 00000000b
                .byte 00000000b, 00000100b
                .byte 00010000b, 00000000b
                .byte 00000000b, 00001000b
                .byte 00001000b, 00000000b
                .byte 00000000b, 00010000b
                .byte 00000100b, 00000000b
                .byte 00000000b, 00100000b
                .byte 00000010b, 00000000b
                .byte 00000000b, 01000000b
                .byte 00000001b, 00000000b
                .byte 00000000b, 10000000b

Motif03         .byte 10000000b, 00000000b      ; Progression d'une lampe
                .byte 01000000b, 00000000b      ; seule, sur les 16 sorties.
                .byte 00100000b, 00000000b      ; Gnniiiiiooooouuuuu ....
                .byte 00010000b, 00000000b      ; (sans doppler ici)
                .byte 00001000b, 00000000b
                .byte 00000100b, 00000000b
                .byte 00000010b, 00000000b
                .byte 00000001b, 00000000b
                .byte 00000000b, 10000000b
                .byte 00000000b, 01000000b
                .byte 00000000b, 00100000b
                .byte 00000000b, 00010000b
                .byte 00000000b, 00001000b
                .byte 00000000b, 00000100b
                .byte 00000000b, 00000010b
                .byte 00000000b, 00000001b

Motif04         .byte 10000000b, 00000001b      ; Croisement de lampes se
                .byte 01000000b, 00000010b      ; promenant en sens inverse
                .byte 00100000b, 00000100b
                .byte 00010000b, 00001000b
                .byte 00001000b, 00010000b
                .byte 00000100b, 00100000b
                .byte 00000010b, 01000000b
                .byte 00000001b, 10000000b
                .byte 00000001b, 10000000b
                .byte 00000010b, 01000000b
                .byte 00000100b, 00100000b
                .byte 00001000b, 00010000b
                .byte 00010000b, 00001000b
                .byte 00100000b, 00000100b
                .byte 01000000b, 00000010b
                .byte 10000000b, 00000001b

Motif05         .byte 10000000b, 00000001b      ; croisement idem ci-dessus
                .byte 00100000b, 00000100b      ; mais utilisable avec 8 ou 
                .byte 00000100b, 00100000b      ; 16 sorties
                .byte 00000001b, 10000000b
                .byte 00000001b, 10000000b
                .byte 00000100b, 00100000b
                .byte 00100000b, 00000100b
                .byte 10000000b, 00000001b
                .byte 10000000b, 00000001b
                .byte 00100000b, 00000100b
                .byte 00000100b, 00100000b
                .byte 00000001b, 10000000b
                .byte 00000001b, 10000000b
                .byte 00000100b, 00100000b
                .byte 00100000b, 00000100b
                .byte 10000000b, 00000001b

Motif06         .byte 00000011b, 11000000b      ; tic tac
                .byte 00000000b, 00000000b
                .byte 11000000b, 00000011b
                .byte 00000000b, 00000000b
                .byte 00001100b, 00110000b
                .byte 00000000b, 00000000b
                .byte 00110000b, 00001100b
                .byte 00000000b, 00000000b
                .byte 00000011b, 11000000b
                .byte 00000000b, 00000000b
                .byte 00001100b, 00110000b
                .byte 00000000b, 00000000b
                .byte 00110000b, 00001100b
                .byte 00000000b, 00000000b
                .byte 11000000b, 00000011b
                .byte 00000000b, 00000000b

Motif07         .byte 00000000b, 00000000b      ; Replis
                .byte 10000000b, 00000001b
                .byte 11000000b, 00000011b
                .byte 11100000b, 00000111b
                .byte 11110000b, 00001111b
                .byte 01111000b, 00011110b
                .byte 11110000b, 00001111b
                .byte 11100000b, 00000111b
                .byte 11000000b, 00000011b
                .byte 10000000b, 00000001b
                .byte 01000000b, 00000010b
                .byte 00100000b, 00000100b
                .byte 00010000b, 00001000b
                .byte 00001000b, 00010000b
                .byte 00000100b, 00100000b
                .byte 00000011b, 11000000b

Motif08         .byte 10000000b, 00001000b      ; Double ondulation
                .byte 01000000b, 00000010b      ; asymétrique
                .byte 00100000b, 00000001b
                .byte 00010000b, 00000001b
                .byte 00001000b, 00000100b
                .byte 00000100b, 00010000b
                .byte 00000010b, 01000000b
                .byte 00000001b, 10000000b
                .byte 00000001b, 10000000b
                .byte 00000010b, 01000000b
                .byte 00000100b, 00010000b
                .byte 00001000b, 00000100b
                .byte 00010000b, 00000001b
                .byte 00100000b, 00000001b
                .byte 01000000b, 00000100b
                .byte 10000000b, 00001000b

Motif09         .byte 10000000b, 10000000b      ; Double ondulation
                .byte 01000000b, 01000000b      ; utilisable en 8 ou 16
                .byte 00100000b, 00100000b      ; voies
                .byte 00010000b, 00010000b
                .byte 00001000b, 00001000b
                .byte 00000100b, 00000100b
                .byte 00000010b, 00000010b
                .byte 00000001b, 00000001b
                .byte 00000001b, 00000001b
                .byte 00000010b, 00000010b
                .byte 00000100b, 00000100b
                .byte 00001000b, 00001000b
                .byte 00010000b, 00010000b
                .byte 00100000b, 00100000b
                .byte 01000000b, 01000000b
                .byte 10000000b, 10000000b
                               
Motif10         .byte 00001000b, 00000000b      ; Aléatoire
                .byte 00000000b, 10000000b
                .byte 00000000b, 00000100b
                .byte 00100000b, 00000000b
                .byte 00000000b, 01000000b
                .byte 00010000b, 00000000b
                .byte 00000000b, 00001000b
                .byte 01000000b, 00000000b
                .byte 00000001b, 00000000b
                .byte 00000000b, 00100000b
                .byte 00000100b, 00000000b
                .byte 00000000b, 00000010b
                .byte 00000000b, 00000001b
                .byte 10000000b, 00000000b
                .byte 00000000b, 00010000b
                .byte 00000010b, 00000000b

Motif11         .byte 00000000b, 00000000b      ; Pétard
                .byte 00001000b, 00010000b
                .byte 00000000b, 00000000b
                .byte 00001000b, 00010000b
                .byte 00000000b, 00000000b
                .byte 00001000b, 00010000b
                .byte 00000000b, 00000000b
                .byte 00001000b, 00010000b
                .byte 00011100b, 00111000b
                .byte 00111100b, 00111100b
                .byte 00000000b, 00000000b
                .byte 00111100b, 00111100b
                .byte 00000000b, 00000000b
                .byte 01100110b, 01100110b
                .byte 00000000b, 00000000b
                .byte 10000000b, 00000001b

Motif12         .byte 10000000b, 00000000b      ; Chenille progressant
                .byte 11100000b, 00000000b      ; avec longueur variable
                .byte 11111000b, 00000000b
                .byte 00111110b, 00000000b
                .byte 00001110b, 00000000b
                .byte 00000010b, 00000000b
                .byte 00000011b, 00000000b
                .byte 00000011b, 10000000b
                .byte 00000001b, 10000000b
                .byte 00000000b, 10000000b
                .byte 00000000b, 11000000b
                .byte 00000000b, 01110000b
                .byte 00000000b, 01111100b
                .byte 00000000b, 00011111b
                .byte 00000000b, 00000111b
                .byte 00000000b, 00000001b

Motif13         .byte 10000000b, 00000000b      ; progression régulière de 
                .byte 11000000b, 00000000b      ; 3 lampes
                .byte 11100000b, 00000000b
                .byte 01110000b, 00000000b
                .byte 00111000b, 00000000b
                .byte 00011100b, 00000000b
                .byte 00001110b, 00000000b
                .byte 00000111b, 00000000b
                .byte 00000011b, 10000000b
                .byte 00000001b, 11000000b
                .byte 00000000b, 11100000b
                .byte 00000000b, 01110000b
                .byte 00000000b, 00111000b
                .byte 00000000b, 00011100b
                .byte 00000000b, 00001110b
                .byte 00000000b, 00000111b

Motif14         .byte 11110000b, 00000000b      ; saccades: groupes de 4
                .byte 00000000b, 00000000b      ; lampes se baladant
                .byte 00000000b, 00001111b
                .byte 00000000b, 00000000b
                .byte 00001111b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 11110000b
                .byte 00000000b, 00000000b
                .byte 11110000b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 00001111b
                .byte 00000000b, 00000000b
                .byte 00001111b, 00000000b
                .byte 00000000b, 00000000b
                .byte 00000000b, 11110000b
                .byte 00000000b, 00000000b
                               
Motif15         .byte 00000001b, 10000000b      ; Effilement
                .byte 00000001b, 10000000b
                .byte 00000011b, 11000000b
                .byte 00000111b, 11100000b
                .byte 00001111b, 11110000b
                .byte 00011110b, 01111000b
                .byte 00111000b, 00011100b
                .byte 01100000b, 00000110b
                .byte 10000000b, 00000001b
                .byte 01100000b, 00000110b
                .byte 00111000b, 00011100b
                .byte 00011110b, 01111000b
                .byte 00001111b, 11110000b
                .byte 00000111b, 11100000b
                .byte 00000011b, 11000000b
                .byte 00000001b, 10000000b
                               
Motif16         .byte 00001000b, 00000000b      ; ondulation
                .byte 00000100b, 00000000b
                .byte 00000010b, 00000000b
                .byte 00001000b, 00000000b
                .byte 00010000b, 00000000b
                .byte 00001000b, 00000000b
                .byte 00000100b, 00000000b
                .byte 00000001b, 00000000b
                .byte 00000000b, 01000000b
                .byte 00000000b, 00010000b
                .byte 00000000b, 10000100b
                .byte 00000000b, 01000010b
                .byte 00000000b, 00001000b
                .byte 00000000b, 01000000b
                .byte 00000100b, 00000000b
                .byte 00000000b, 00000001b

;---------------------------------------------------------------------------
;                             Début du programme
;                               initialisations

                .org 0200h

reset           ldi wdr, knonos         ; On calme le chien de garde

                ldi ddra,00000000b      ; A0..7 entrée rappel ss interruption
                ldi ora, 00000000b      ; (boutons poussoirs)
                ldi dra, 00000000b

                ldi ddrb,00000000b      ; B0..7 entrée rappel ss interruption
                ldi orb, 00000000b      ; (boutons poussoirs)
                ldi drb, 00000000b

                ldi ddrc,01100000b      ; C4 entr 0 cross ni rappel ni inter
                ldi orc, 11100000b      ; C5 C6 sorties symétriques MM5450
                ldi drc, 10010000b      ; C7 entrée analogique potar vitesse

                ldi tcr, ktempo
                ldi tscr, 00011100b     ; b7 passe à 1 si TCR passe à 0
                                        ; b6 interdit interruptions par b7
                                        ; b5 broche timer en entrée (+Vcc)
                                        ; b4 TCR valide si b5 à 1 (exact)
                                        ; b3 2 1: prédivision par 16
                                        ; ici 3.2768/(12*16) => 58.59 µs

                ret                     ; car niveau pile aléatoire à la
                ret                     ; mise sous tension ...
                ret
                ret
                ret
                ret

                ldi adcr, 00010000b     ; Activation du CAN et reset

                clr brouill             ; variable servant de brouillon
                clr dureebp             ; tempo incrémentée pression BP
                clr f0tr0108            ; flags forçage à zéro sorties 1 à 8
                clr f0tr0916            ; flags forçage à zéro sorties 9 à 16
                clr f1tr0108            ; flags forçage à un sorties 1 à 8
                clr f1tr0916            ; flags forçage à un sorties 9 à 16
                clr flags               ; drapeaux
                                        ; b0 à 1 si traitement BP en cours
                                        ; b1 à 1 si un BP enfoncé
                                        ; b2
                                        ; b3
                                        ; b4
                                        ; b5
                                        ; b6
                                        ; b7
                clr imagepa             ; image du port A (BP 1 à 8) COMPLEM
                clr imagepb             ; image du port B (BP 9 à 16) COMPLEM
                clr ligne               ; numéro de la ligne du motif: 0 à 15
                clr lignelsb            ; octet faible de la ligne jouée
                clr lignemsb            ; octet fort de la ligne jouée
                clr mempa               ; Mémoire de imagepa
                clr mempb               ; Mémoire de imagepb
                clr motif               ; numéro du motif choisi: 0 à 16
                clr numbit              ; numéro du bit envoyé au MM5450
                clr tempobp             ; variable décrémentée dans gesttemp
                clr tension             ; tension potentiomètre mesurée


;---------------------------------------------------------------------------
;                             Boucle principale
;
;       Le principe retenu est le suivant:

;               - on attend patiemment le passage à zéro du secteur, par la
;                 routine zerosect: c'est pendant cette attente que l'on
;                 exécute en boucle la routine de gestion du temps gesttemp.
;                 En fait, selon la vitesse de défilement choisie, on attend
;                 un nombre de passages au zéro variable entre 1 et 16.

;               - Dès qu'on a passé le zéro, on envoie la salve de commande
;                 au circuit MM5450 par la routine gest5450, qui va d'une
;                 part allumer les leds, et d'autre part commander (en
;                 continu) les triacs.

;               - Une fois la salve envoyée, on gère les boutons (acne), le
;                 potentiomètre (potar), le choix et la progression du motif
;                 (progres): tout ceci se fait sans problèmes pendant les
;                 9 ms (environ) qui restent dans une demi sinusoïde.

boucle          call acne               ; traitement des boutons poussoirs
                call potar              ; mesure tension potentiomètre
                call progres            ; choix et progression du motif
                call zerosect           ; attente passage à zero secteur
                call gest5450           ; gestion des leds et triacs
                call gesttemp           ; gestion du temps qui passe

                jp boucle

;---------------------------------------------------------------------------
;       Traitement des boutons: routine "fluide", c'est à dire qu'il n'y a
;       pas de blocage ou d'attente quelconque en un point.
;               
    
acne            ldi wdr, knonos         ; On calme le chien de garde

                ld a, dra               ; On ne travaille pas directement
                com a                   ; sur les ports A et B (BP), mais
                ld imagepa, a           ; sur des images de ces ports,
                                        ; que l'on complémente, car quand
                ld a, drb               ; un BP est pressé, cela donne un
                com a                   ; niveau 0 sur la broche du port,
                ld imagepb, a           ; plus long à traiter qu'un niveau 1

                jrs 0, flags, acn01     ; si traitement BP en cours, on y va
                                        ; sinon on regarde si un BP est
                                        ; pressé, c'est à dire ...

                ld a, imagepa           ; ... si BP 1 à 8 pressé, on traite
                jrnz acn00

                ld a, imagepb           ; ... si BP 9 à 16 pressé, on traite
                jrnz acn00

                jp acn16                ; ... si aucun BP pressé, on s'en va

acn00           jp acn15                ; renvoi plus loin, où l'on traitera
                                        ; l'enclenchement du traitement BP

acn01           ; Traitement des BP en cours: on regarde maintenant si le BP
                ; a été relâché, c'est à dire ...

                ld a, imagepa           ; ... si BP 1 à 8 pressé, on passe
                jrnz acn02

                ld a, imagepb           ; ... si BP 9 à 16 pressé, on passe
                jrz acn03

acn02           jp acn16                ; si le BP n'est pas relâché, on passe

acn03                                   ; Le BP a été relâché, donc ...

                res 0, flags            ; on baisse le drapeau traitement

                ld a, dureebp           ; Si la pression a duré plus de 0.5s
                jrnz acn04
                jp acn10                ; alors on va en acn10

                ; Ici on traite le cas où un BP a été pressé moins de 0.5s

acn04           ld a, motif             ; Si la pression a duré moins de 0.5s
                jrz acn05               ; et qu'il y avait un motif en cours
                clr motif               ; alors on arrête le chenillard
                jp acn16

acn05           ldi a, 00000001b        ; Si la pression a duré moins de 0.5s

acn06           inc motif               ; et qu'il n'y avait pas de motif en
                cp a, mempa             ; cours, alors on calcule le motif
                jrnz acn07              ; indiqué par le BP pressé
                jp acn16

acn07           sla a                   ; Le principe est d'incrémenter la
                jrnc acn06              ; valeur de motif à chaque fois que

                ldi a, 00000001b        ; l'on décale d'un cran à gauche le

acn08           inc motif               ; masque de test des ports A et B
                cp a, mempb             ; (BP)
                jrnz acn09
                jp acn16

acn09           sla a
                jrnc acn08

                ldi motif, 3            ; XXXXXXXXXXXXXX pour test XXXXXXXXXX
                jp acn16                ; Le programme ne devrait en principe
                                        ; jamais passer ici.

                ; Ici on traite le cas où un BP a été pressé plus de 0.5s

acn10           ; on doit retourner les deux octets Mempa et Mempb car le
                ; BP 1 correspond à PA0 , le BP 8 à PA7, le BP 9 à PB 0, et
                ; le BP 16 à PB 7.

                ; Pas très malin tout ça, mais bon, ça ira pour cette fois

                ld a, mempa             ; le principe est d'analyser
                clr mempa               ; l'ancien octet mempa bit à bit

                sla a                   ; en le faisant tourner par un sla
                jrnc acn10a             ; et en examinant le flag de retenue
                set 0, mempa
acn10a          sla a                   ; on replace alors successivement
                jrnc acn10b             ; les bits à un dans le sens inverse
                set 1, mempa
acn10b          sla a                   ; b7 devient b0
                jrnc acn10c             ; b6 devient b1
                set 2, mempa            ; b5 devient b2
acn10c          sla a                   ; b4 devient b3
                jrnc acn10d             ; b3 devient b4
                set 3, mempa            ; b2 devient b5
acn10d          sla a                   ; b1 devient b6
                jrnc acn10e             ; b0 devient b7
                set 4, mempa
acn10e          sla a                   ; manège tou'n
                jrnc acn10f
                set 5, mempa            ; tou'n manège
acn10f          sla a
                jrnc acn10g
                set 6, mempa            ; tou'n  tou'n
acn10g          sla a
                jrnc acn10h
                set 7, mempa

acn10h          ld a, mempb
                clr mempb

                sla a                   ; et comme on aime les tours de
                jrnc acn10i             ; manège, on recommence avec mempb
                set 0, mempb
acn10i          sla a
                jrnc acn10j
                set 1, mempb
acn10j          sla a
                jrnc acn10k
                set 2, mempb            ; tou'n   comme disait l'autre
acn10k          sla a
                jrnc acn10l
                set 3, mempb
acn10l          sla a
                jrnc acn10m
                set 4, mempb
acn10m          sla a
                jrnc acn10n
                set 5, mempb
acn10n          sla a
                jrnc acn10o             ; allez, encore un petit tour
                set 6, mempb
acn10o          sla a
                jrnc acn10p
                set 7, mempb
                
acn10p          ld a, mempa             ; si le BP enfoncé correspond à
                and a, f0tr0108         ; une voie déja forcée à 0, alors
                jrz acn11               ; on supprime ce forçage à 0
                ld a, mempa             ; (cette voie retourne en auto)
                com a                   ; (on traite ici les BP 1 à 8)
                and a, f0tr0108
                ld f0tr0108, a
                jp acn16

acn11           ld a, mempb             ; si le BP enfoncé correspond à
                and a, f0tr0916         ; une voie déja forcée à 0, alors
                jrz acn12               ; on supprime ce forçage à 0
                ld a, mempb             ; (cette voie retourne en auto)
                com a                   ; (on traite ici les BP 9 à 16)
                and a, f0tr0916
                ld f0tr0916, a
                jp acn16

acn12           ld a, mempa             ; si le BP enfoncé correspond à
                and a, f1tr0108         ; une voie déja forcée à 1, alors ..
                jrz acn13              
                ld a, mempa           
                com a                   ; ... on supprime ce forçage à 1
                and a, f1tr0108         ; et ...
                ld f1tr0108, a

                ld a, f0tr0108
                add a, mempa            ; ... on force cette voie à 0
                ld f0tr0108, a          
                jp acn16                ; (on a traité ici les BP 1 à 8)

acn13           ld a, mempb             ; si le BP enfoncé correspond à
                and a, f1tr0916         ; une voie déja forcée à 1, alors ..
                jrz acn14              
                ld a, mempb           
                com a                   ; ... on supprime ce forçage à 1
                and a, f1tr0916         ; et ...
                ld f1tr0916, a

                ld a, f0tr0916
                add a, mempb            ; ... on force cette voie à 0
                ld f0tr0916, a          
                jp acn16                ; (on a traité ici les BP 9 à 16)
                
acn14           ld a, f1tr0108          ; Il ne reste plus que le cas où
                add a, mempa            ; le BP enfoncé ne correspond à
                ld f1tr0108, a          ; aucun forçage: dans ce cas on

                ld a, f1tr0916          ; force la voie à 1
                add a, mempb
                ld f1tr0916, a

                jp acn16

acn15           ; Enclenchement du traitement des BP

                ld a, imagepa           ; On mémorise le BP enfoncé
                ld mempa, a

                ld a, imagepb
                ld mempb, a

                set 0, flags            ; On lève le drapeau traitement

                ldi dureebp, kdureebp   ; charge compteur durée pression BP

acn16           ret

;---------------------------------------------------------------------------
;       Gestion de la tension du potentiomètre de vitesse: routine avec une
;       très légère attente (environ 200 µs), donc "fluide", c'est à dire
;       qu'il n'y a quasiment pas de blocage en un point.

potar           ldi wdr, knonos         ; on calme le chien de garde

                set 5, adcr             ; on lance la mesure ADC

pot01           jrr 6, adcr, pot01      ; on attend qu'elle soit terminée
                res 5, adcr             ; CAN prêt pour mesure suivante
                ld a, adr
                com a                   ; on complémente, pour que la vitesse
                                        ; augmente quand on tourne le potar
                                        ; dans le sens des aiguilles d'une
                                        ; montre.
                rlc a                   ; on divise cette tension par 8
                rlc a                   ; ce qui donnera 32 valeurs possibles
                rlc a                   ; pour la vitesse de défilement.
                rlc a
                rlc a
                rlc a
                andi a, 00011111b
                ld tension, a
                ret

;---------------------------------------------------------------------------
;       Choix et progression du motif: routine "fluide", c'est à dire qu'il
;       n'y a pas de blocage ou d'attente quelconque en un point.

; Lecture de la table qui contient les valeurs des motifs, et incrémentation
; du numéro de ligne.

; Parenthèse: la mémoire ROM n'est accessible que via une fenêtre de 64
; octets dans l'espace adressable par le micro.

; Attention !!!  L'adresse du premier octet de la fenêtre est 0040h,
; et celle du dernier octet est 007Fh.
;
; On choisi le segment de ROM visible dans la fenêtre par le chargement
; préalable du registre Data Rom Window Register, l'adresse dans la ROM
; étant définie ainsi sur 12 bits:
;
; Adresse ROM          11 10 09 08 07 06 05 04 03 02 01 00
;         DRWR   00 00 D5 D4 D3 D2 D1 D0
; Adresse dans fenêtre              0  1 D5 D4 D3 D2 D1 D0
;                                      î
;                                      Ce 1 est là car la première
;                                      adresse de la fenêtre est 64
;
; Ici la table contient des doubles octets, donc l'adresse s'incrémente de
; 2 en 2, et donc on a:
;
;       
; Adresse ROM          11 10 09 08 07 06 05 04 03 02 01 00
;         DRWR   00 00 D5 D4 D3 D2 D1 D0
;
; Premier ou second octet                                X = 0 ou 1
; Numéro de ligne                            L  L  L  L
; Numéro de motif             M  M  M  M  M
;
; Soit    DRWR    0  0  1  1  M  M  M  M
; Adresse fenêtre                         M  L  L  L  L  0      1er octet
;         ou                              M  L  L  L  L  1      2nd octet
;
; Motif01 = 0  0  0  0  1  1  0  0  0  0  0  0  0  0  0  0b
;    Soit   ^---0----^  ^---C----^  ^----0---^  ^----0---^ = 0C00h

progres         ldi wdr, knonos         ; On calme le chien de garde

lectable        ld a, motif             ; A contient le motif
                rlc a                   ; On ne garde que les bits b1 à b4
                rlc a                   ; qui deviennent
                rlc a                   ; les 4 bits de poids faible du
                rlc a                   ; DRWR (Data Rom Window Register)
                rlc a
                rlc a
                rlc a
                rlc a
                andi a, 00001111b       ; auquel on ajoute la valeur 30h,
                addi a, 30h             ; pour obtenir au minimum l'adresse
                ld drwr, a              ; 0000 1100 0000 0000b soit 0C00h
                                        ; qui est celle de début de table
                
                ld a, motif             ; A contient le motif
                rlc a                   ; on fait avancer le LSB vers
                rlc a                   ; la gauche: il passe de b0 à b4
                rlc a                   ; puis on ne garde que ce bit b4
                rlc a
                andi a, 00010000b

                add a, ligne            ; on ajoute le numéro de ligne
                                        ; (compris entre 0 et 15), qui va
                                        ; donc occuper à ce stade les bits
                                        ; b0 à b3 du mot

                sla a                   ; on redécale tout à gauche, en
                                        ; insérant un 0

                addi a, 01000000b       ; et enfin on ajoute 40h, car le
                                        ; premier octet de la fenêtre est
                                        ; à l'adresse 40h, et on a enfin le
                                        ; pointeur dans la fenêtre

                ld x, a                 ; Miracle de la
                ld a, (x)               ; technique, on obtient l'octet fort
                ld lignemsb, a          ; de la ligne pointée dans la table.
                inc x                   ; A table suite: le plat suivant est
                ld a, (x)               ; l'octet faible de la ligne.
                ld lignelsb, a

                ld a, f0tr0916          ; Forçage à 0 éventuel des voies
                com a                   ; 1 à 8
                and a, lignelsb
                ld lignelsb, a

                ld a, f1tr0916          ; Forçage à 1 éventuel des voies
                com a                   ; 1 à 8
                ld brouill, a
                ld a, lignelsb
                com a
                and a, brouill
                com a
                ld lignelsb, a

                ld a, f0tr0108          ; Forçage à 0 éventuel des voies
                com a                   ; 9 à 16
                and a, lignemsb
                ld lignemsb, a

                ld a, f1tr0108          ; Forçage à 1 éventuel des voies
                com a                   ; 9 à 16
                ld brouill, a
                ld a, lignemsb
                com a
                and a, brouill
                com a
                ld lignemsb, a

                inc ligne               ; On en profite pour passer à la
                ld a, ligne             ; ligne suivante. Si dépassement
                cpi a, 16               ; (ligne 16) alors on revient à la
                jrnz lec00              ; ligne 0
                clr ligne

lec00           ret

;---------------------------------------------------------------------------
; Le déclenchement des triacs se fait par envoi de la salve au MM 5450, peu
; après le passage au zéro de la tension secteur, en laissant passer un
; nombre variable de demi-périodes secteur entre deux salves, afin de faire
; varier la vitesse de défilement: La valeur de la variable attente, qui
; est une copie de la variable tension, laquelle reflète la position du
; potentiomètre de réglage de vitesse (rien à voir avec la tension secteur!),
; est décrémentée à chaque passage à zéro du secteur, soit toutes les 10 ms
; (en effet, la tension secteur est abaissée et redressée en double
; alternance), et on obtient donc une tempo de ligne minimale de 10 * 0 =
; 0 ms, et maximale de 10 * 32 = 320 ms ce qui donne un défilement d'un
; motif complet en 16 * .32 = 5.12 s.

; En fait, la tempo minimale ci-dessus est complètement fausse, car avec un
; quartz à 3.2768 MHz, le micro rame déja pendant environ 20 ms pour faire
; son boulot, le programme n'étant absolument pas optimisé. Pendant ce
; temps, il n'y a pas de risque d'enclenchement intempestif d'un triac, car
; le MM5450 conserve son information sur les sorties, et donc les gachettes
; sont alimentées en permanence: les triacs qui doivent conduire
; s'enclenchent donc naturellement dès la remontée de la tension sinusoïdale.

; Simplement, on ne peut pas atteindre la vitesse maximale de 100 lignes par
; seconde, soit environ 100 / 16= 6 motifs complets par seconde: on a une
; attente minimale de 3 * 10 ms (traitement micro d'un peu plus de 20 ms, et
; attente de la période suivante), soit une vitesse maximale d'environ 33
; lignes par seconde, soit 2 motifs entiers, ce qui est en pratique assez.

; Noter que l'on ne fait pas de test directement sur le port C, car cela
; entraine des changements de configuration (en effet, le test consiste en
; une lecture/écriture, et la valeur lue n'est pas forcément la bonne pour
; configurer le port.

; Noter que pendant que l'on attend l'évolution de la tension secteur, ce
; qui est long à l'échelle du microcontrôleur, on va régulièrement voir la
; routine de gestion du temps, afin de gérer correctement les boutons
; poussoirs.

zerosect        call gesttemp
                ld a, drc               ; on attend le passage au zéro
                jrs 4, a, zerosect      ; du secteur

zer00           call gesttemp
                ld a, drc
                jrr 4, a, zer00         ; on attend qu'il remonte

zer01           ld a, tension           ; il s'agit ici de la tension aux
                jrz zer02               ; bornes du potentiomètre, qui va
                dec a                   ; gérer la vitesse du chenillard
                ld tension, a           ; on attendra donc en fait un
                jp zerosect             ; nombre variable de passages à
                                        ; zéro du secteur, selon la
                                        ; valeur de tension

zer02           ret                     ; Par ici la sortie !!

;---------------------------------------------------------------------------
;       Discussion endiablée avec le MM 5450N: routine "fluide", c'est à
;       dire qu'il n'y a pas de blocage ou d'attente quelconque en un point.
;
;       Dialogue sur la liaison série du MM5450: cette routine envoie en
;       une fois une trame pour le MM5450, c'est à dire une ligne complète
;       de motif, tant sur les leds que sur les triacs.
;
;       Une trame est composée de 36 bits numérotés de 1 à 36 ci-dessous

;
; bit  1      2      3  ...  17    18    19      20 ...      34      35    36
; val  1     Q1     Q2  ... Q16   Q17   Q18     Q19 ...     Q33     Q34     0
;         led16  led15 ... led1    NC    NC  triac1 ... triac15 triac16

;       Remarque: la sortie Q35 n'existe pas sur le MM5450, mais doit être
;       pilotée quand même (ici envoi 0), pour compatibilité avec le MM5451

gest5450        ldi wdr, knonos         ; On calme le chien de garde

                clr numbit

ges00           inc numbit
                
ges01           ld a, numbit            ; Si c'est le premier bit qu'il faut
                cpi a, 1                ; envoyer au MM 5450, alors ne
                jrnz ges02              ; cherchez plus, c'est un 1.
                set 1, flags            ; Data MM 5450 = 1
                call tictac
                jp ges00

ges02           ld a, numbit            ; si c'est le bit 18, il faut envoyer
                cpi a, 18               ; un 0 (par exemple), car il
                jrnz ges03              ; correspond à la sortie Q17 qui n'
                res 1, flags            ; est pas reliée.
                call tictac
                jp ges00

ges03           ld a, numbit            ; si c'est le bit 19, il faut envoyer
                cpi a, 19               ; aussi un 0 (par exemple), car il
                jrnz ges035             ; correspond à la sortie Q18 qui n'
                res 1, flags            ; est pas reliée.
                call tictac
                jp ges00

ges035          ld a, numbit            ; si c'est le bit 36, il faut envoyer
                cpi a, 36               ; aussi un 0 (par exemple), car il
                jrnz ges04              ; correspond à la sortie Q35 qui n'
                res 1, flags            ; existe pas sur le MM 5450
                call tictac
                jp ges00

ges04           ld a, numbit            ; si c'est le bit 37, c'est que le
                cpi a, 37               ; dialogue est terminé (il n'y a
                jrnz ges05              ; que 36 bits à envoyer)

                jp ges26                ; Vers la sortie !!!

ges05           ; Ici, on sait maintenant que le bit n'est pas le 1, ni le
                ; 18, ni le 19, ni le 36 donc on peut commencer à travailler

                ld a, numbit            ; si c'est le bit 2 à 17, c'est
                subi a, 20              ; pour les leds, et si c'est le
                jrc ges06               ; bit 20 à 35, c'est pour les
                jp ges16                ; triacs

ges06           ; ici, gestion des leds, avec numbit variant de 2 à 17

                ld a, lignelsb
                ld x, a
                ld a, numbit            ; gestion des leds: la led 1 (gauche)
                subi a, 2               ; correspond au bit 7 de l'octet
                cpi a, 8                ; fort de la ligne, et au bit 17
                jrc ges07               ; du MM5450, et la led 16 (droite)
                subi a, 8               ; au bit 0 de l'octet faible de la
                ld brouill, a           ; ligne, et au bit 2 du MM5450
                ld a, lignemsb          ; petite alchimie pour pouvoir
                ld x, a                 ; utiliser le registre x
                ld a, brouill

ges07           res 1, flags

                cpi a, 7
                jrnz ges08
                jrr 7, x, ges08
                set 1, flags

ges08           cpi a, 6
                jrnz ges09
                jrr 6, x, ges09
                set 1, flags

ges09           cpi a, 5
                jrnz ges10
                jrr 5, x, ges10
                set 1, flags

ges10           cpi a, 4
                jrnz ges11
                jrr 4, x, ges11
                set 1, flags

ges11           cpi a, 3
                jrnz ges12
                jrr 3, x, ges12
                set 1, flags

ges12           cpi a, 2
                jrnz ges13
                jrr 2, x, ges13
                set 1, flags

ges13           cpi a, 1
                jrnz ges14
                jrr 1, x, ges14
                set 1, flags

ges14           cpi a, 0
                jrnz ges15
                jrr 0, x, ges15
                set 1, flags

ges15           call tictac

                jp ges00


ges16           ; ici, gestion des triacs, avec numbit variant de 20 à 35

                ld a, lignelsb
                ld x, a
                ldi a, 35               ; gestion des triacs: le triac 1
                sub a, numbit           ; correspond au bit 7 de l'octet
                cpi a, 8                ; fort de la ligne, et au bit 20
                jrc ges17               ; du MM5450, et le triac 16
                subi a, 8               ; au bit 0 de l'octet faible de la
                ld brouill, a           ; ligne, et au bit 35 du MM5450
                ld a, lignemsb
                ld x, a
                ld a, brouill

ges17           res 1, flags

                cpi a, 7
                jrnz ges18
                jrr 7, x, ges18
                set 1, flags

ges18           cpi a, 6
                jrnz ges19
                jrr 6, x, ges19
                set 1, flags

ges19           cpi a, 5
                jrnz ges20
                jrr 5, x, ges20
                set 1, flags

ges20           cpi a, 4
                jrnz ges21
                jrr 4, x, ges21
                set 1, flags

ges21           cpi a, 3
                jrnz ges22
                jrr 3, x, ges22
                set 1, flags

ges22           cpi a, 2
                jrnz ges23
                jrr 2, x, ges23
                set 1, flags

ges23           cpi a, 1
                jrnz ges24
                jrr 1, x, ges24
                set 1, flags

ges24           cpi a, 0
                jrnz ges25
                jrr 0, x, ges25
                set 1, flags

ges25           call tictac

                jp ges00                ; on boucle pour balayer les 35 bits
                                        ; à envoyer au MM5450.

ges26           ret

;                  Gestion de l'horloge du MM 5450

tictac          ldi a, 10010000b        ; valeur reset du drc
                                        ; rappelons que l'horloge du MM5450
                                        ; est sur le bit 5 du port C, et que
                                        ; le bit de donnée du MM5450 est sur
                                        ; le bit 6 du port C.

                jrr 1, flags, tic00     ; s'il faut envoyer un 1, on envoie
                set 6, a                ; un 1, et si c'est un 0, alors un 0 !

tic00           ld drc, a               ; on positionne la ligne data

                set 5, a                ; et on envoie un coup d'horloge
                ld drc, a
                
                res 5, a                ; on redescend l'horloge
                ld drc, a

                ret
;---------------------------------------------------------------------------
;       Gestion du temps qui passe: routine avec attente d'un évennement
;       (passage base de temps): ne doit pas s'éterniser, sachant que la
;       scrutation du zéro cross se fait sur une plage de 450 µs environ.

gesttemp        ldi wdr, knonos         ; On calme le chien de garde
                jrs 7, tscr, tem00      ; si la base n'est pas passée
                jp tem01                ; on reviendra plus tard

tem00           ldi tcr, ktempo         ; on recharge le tcr pour suivant
                res 7, tscr             ; on rabaisse le drapeau

                dec tempobp
                jrnz tem01
                ld a, dureebp           ; toutes les tempos sont décrémentées
                jrz tem01               ; jusqu'à zéro, où elles restent
                dec dureebp

tem01           ret


;---------------------------------------------------------------------------