User Tools

Site Tools


start:eti:carte:sources:vcl8255

Vcl8255.pas

UNIT Vcl8255;
{-----------------------------------------------------------------------------
  NOM DE L'UNITE : VCL8255.PAS
  BUT            : Composant VCL 8255 renfermant tout les contrôles du PPI
  AUTEUR         : S.Claus / M.Amarantidis
  DATE           : Novembre 1996
 
  MODIFIE LE     : 05.12.1996  -  1.01  -  S.Claus
  RAISON         : - Ajouté le type TPort
                   - Ajouté les propriétés ChenillardStop, ChenillardDelai et
                     ChenillardPort
                   - Ajouté la méthode Chenillard
 
  MODIFIE LE     : 08.12.1996  -  1.02  -  S.Claus
  RAISON         : - Ajouté l'état mpIndefini pour le type TModePort
                   - Ajouté le type TPortPattern
                   - Ajouté les propriétés PatternPorts, PatternStop,
                     PatternNbErreurs, PatternMessage et PatternNbOK
                   - Ajouté la méthode Pattern
                   - Ajouté l'événement OnErrorPattern
 
  MODIFIE LE     : 08.12.1996  -  1.03  -  S.Claus
  RAISON         : - Correction de la procédure Chenillard: Un port en sortie,
                     deux ports en entrée.
                   - Correction de la procédure Chenillard: Lors de la mise à 1
                     du bit, il faut soustraire 1 à NoBit car la procédure
                     SetBitB va de 0 à 7 et non pas de 1 à 8
                   - Ajouté l'événement OnChenillardBouge pour une utilisation
                     dans le programme.
 
  MODIFIE LE     : 14.12.1996  -  1.04  -  S.Claus
  RAISON         : - Quelques adaptations en vue de l'utilisation de ce
                     composant sous Delphi 2.0
 
  MODIFIE LE     : 22.12.1996  -  1.05  -  S.Claus
                   - Changé le type des propriétés PatternNbErreurs et
                     PatternNbOK de WORD à LONGINT car sinon, on peut passer en
                     négatif.
                   - Ajouté la propriété Version afin de pouvoir lire la
                     version de la VCL depuis le programme appelant.
 
  MODIFIE LE     : 08.01.1997  -  1.06  -  M.Amarantidis
                   - Correction du chenillard pour n'allumer qu'une LED à la
                     fois et non pas n'importe quoi.
 
  MODIFIE LE     : 15.01.1997  -  1.07  -  S.Claus
                   - Ajout de nouveaux type de tests de pattern, en utilisant
                     uniquement deux ports: un en émission et un un réception.
                     Seul un des ports est configuré en sortie. Ces nouveaux
                     paramètres sont: ppAB, ppAC, ppBA, ppBC, ppCA et ppCB
                   - Empêche toute modification de l'état des ports si le
                     chenillard ou le test de pattern est en cours d'exécution
                   - N'exécute pas une seconde fois le Chenillard ou le test de
                     pattern si une de ces deux procédures est déjà en cours
                     d'exécution.
 
  MODIFIE LE     : 22.01.1997  -  1.08  -  M.Amarantidis
                   - Modification pour la configuration des modes des ports:
                     réécrit chaque fois la configuration complète du port, car
                     la lecture du mot de contrôle est INTERDITE.
                   - Empêche l'exécution du chenillard pendant le test de
                     pattern et empêche l'exécution du pattern pendant le
                     chenillard
 
  MODIFIE LE     : 22.01.1997  -  1.09  -  S.Claus
                   - Ajout de commentaires...
                   - Les variables internes au composant commencent toutes par
                     F...
                   - Utilise partout les fonctions d'E/S en assembleur au lieu
                     du tableau Port de Delphi
                   - N'arrête pas le Pattern si on exécute le chenillard en
                     même temps
                   - Ne reconfigure les port que si la nouvelle configuration
                     est différente de l'actuelle
 
 
  REMARQUES      : - Pour la configuration du 8255, la structure du mot de
                     contrôle qu'il faut écrire à l'adresse de contrôle est la
                     suivante:
 
                     D7 D6 D5 D4 D3 D2 D1 D0
                     ¦  ¦  ¦  ¦  ¦  ¦  ¦  ¦
                     ¦  +--+  ¦  ¦  ¦  ¦  ¦      GROUPE B
                     ¦  ¦     ¦  ¦  ¦  ¦  +----- Port C (bas):
                     ¦  ¦     ¦  ¦  ¦  ¦         1: Entrée / 0: Sortie
                     ¦  ¦     ¦  ¦  ¦  +-------- Port B:
                     ¦  ¦     ¦  ¦  ¦            1: Entrée / 0: Sortie
                     ¦  ¦     ¦  ¦  +----------- Sélection de mode:
                     ¦  ¦     ¦  ¦               0: Mode 0 / 1: Mode 1
                     ¦  ¦     ¦  ¦
                     ¦  ¦     ¦  ¦               GROUPE A
                     ¦  ¦     ¦  +-------------- Port C (haut):
                     ¦  ¦     ¦                  1: Entrée / 0: Sortie
                     ¦  ¦     +----------------- Port A:
                     ¦  ¦                        1: Entrée / 0: Sortie
                     ¦  +----------------------- Sélection de mode:
                     ¦                           00: Mode 0 / 01: Mode 1
                     ¦                           1X: Mode 2
                     ¦
                     +-------------------------- Drapeau de mode défini:
                                                 1: Actif
 
                   - Dans cette VCL, le 8255 n'est utilisé que dans le mode 0,
                     qui est un mode d'entrée/sortie simple.
 
                   - Les propriétés PatternNbOK et PatternMessage sont en
                     lecture seule et ne peuvent être vues avec l'inspecteur
                     d'objet.
 
 -----------------------------------------------------------------------------}
 
 
{=============================================================================}
INTERFACE   {============================================== I N T E R F A C E }
{=============================================================================}
 
 
 
USES
  WinTypes, WinProcs, Classes, SysUtils;
 
 
CONST
  versionvcl            = '1.09';                            { Version du VCL }
  adressebase           = $300;                     { Adresse de base du 8255 }
  nbpas = 100;                            { Pattern pour le test de transfert }
  patterntest : ARRAY[1..nbpas] OF BYTE =
                       ($00, $01, $02, $03, $04, $05, $06, $07, $08, $09,
                        $10, $11, $12, $13, $14, $15, $16, $17, $18, $19,
                        $20, $21, $22, $23, $24, $25, $26, $27, $28, $29,
                        $30, $31, $32, $33, $34, $35, $36, $37, $38, $39,
                        $40, $41, $42, $43, $44, $45, $46, $47, $48, $49,
                        $50, $51, $52, $53, $54, $55, $56, $57, $58, $59,
                        $60, $61, $62, $63, $64, $65, $66, $67, $68, $69,
                        $70, $71, $72, $73, $74, $75, $76, $77, $78, $79,
                        $80, $81, $82, $83, $84, $85, $86, $87, $88, $89,
                        $90, $91, $92, $93, $94, $95, $96, $97, $98, $99);
 
 
TYPE
  TModePort = (mpSortie, mpEntree, mpIndefini);   { Etats possibles des ports }
  TPort = (pPortA, pPortB, pPortC);                                    { Port }
 
  TPortPattern = (ppABC, ppBAC, ppCAB,              { Type de test de pattern }
  {1.07  Nouvelles configurations possibles }
                  ppAB, ppAC, ppBA, ppBC, ppCA, ppCB);
 
 
  TPPI8255 = CLASS(TComponent)
    {=========================================================================}
    PRIVATE { Private-déclarations ---------------------------------- PRIVATE }
 
      {-- Divers }
      FVersion         : STRING;            { Version de la VCL }
      FAdresseBase8255 : WORD;              { Adresse de base du 8255 }
      FAdresseCtrl,                         { Adresse du port de contrôle }
      FAdressePortA,                        { Adresse du port A }
      FAdressePortB,                        { Adresse du port B }
      FAdressePortC    : WORD;              { Adresse du port C }
      FCanWrite        : BOOLEAN;           { Accès au hardware autorisé ? }
 
      {-- Configuration des ports }
      FModeDuPortA,                         { Mode de fonctionnement du port A }
      FModeDuPortB,                         { Mode de fonctionnement du port B }
      FModeDuPortC     : TModePort;         { Mode de fonctionnement du port C }
 
      {-- Chenillard }
      FPortChenillard  : TPort;             { Port utilisé par le chenillard }
      FStopChenillard  : BOOLEAN;           { Arrêt du chenillard }
      FDelaiChenillard : WORD;              { Délai entre chaque chgmnt d'état }
      FOnChenillardBouge : TNotifyEvent;    { Changemement d'état }
      { Le type TNotifyEvent est le type des événements qui n'ont pas de
      paramètre. Ces événements se contentent de notifier au composant qu'un
      événement particulier s'est produit. Par exemple, OnClick, qui est de
      type TNotifyEvent, indique au contrôle qu'un clic s'est produit sur le
      contrôle. }
 
      {-- Pattern }
      FPortsPattern    : TPortPattern;      { Ports utilisés par le pattern }
      FStopPattern     : BOOLEAN;           { Arrêt du pattern }
      FNbErrPattern    : LONGINT;           { Nb pattern transmis AVEC erreur }
      FNbOkPattern     : LONGINT;           { Nb pattern transmis SANS erreur }
      FMsgErrPattern   : STRING;            { Description de l'erreur }
      FOnErrorPattern  : TNotifyEvent;      { Erreur de transm. survenue }
 
      {-- Divers }
      PROCEDURE AjusteAdresses;             { Set des adresses des ports }
      PROCEDURE SetAdresseBase(Adresse:WORD);   { Config de l'adresse de base }
      PROCEDURE SetCanWrite(WriteEnabled:BOOLEAN); { Change état de FCanWrite }
 
      {-- Configuration des ports }
      PROCEDURE SetPortA(Mode:TModePort);    { Init du port A et FModeDuPortA }
      PROCEDURE SetPortB(Mode:TModePort);    { Init du port B et FModeDuPortB }
      PROCEDURE SetPortC(Mode:TModePort);    { Init du port C et FModeDuPortC }
 
      {-- Lecture / Ecriture }
      FUNCTION  LitPortA:BYTE;            { Lit valeur présente sur le port A }
      PROCEDURE EcritPortA(Valeur:BYTE);  { Ecrit une valeur sur le port A }
      FUNCTION  LitPortB:BYTE;            { Lit valeur présente sur le port B }
      PROCEDURE EcritPortB(Valeur:BYTE);  { Ecrit une valeur sur le port B }
      FUNCTION  LitPortC:BYTE;            { Lit valeur présente sur le port C }
      PROCEDURE EcritPortC(Valeur:BYTE);  { Ecrit une valeur sur le port C }
 
      {-- Chenillard }
      PROCEDURE SetFPortChenillard(LePort:TPort);  { Sélection du port }
      PROCEDURE SetFStopChenillard(Stop:BOOLEAN);  { Arrête le chenillard }
      PROCEDURE SetFDelaiChenillard(Delay:WORD);   { Modif de la "vitesse" }
 
      {-- Pattern }
      PROCEDURE SetFPortsPattern(Valeur:TPortPattern);  { Sélection du port }
      PROCEDURE SetFStopPattern(Stop:BOOLEAN);          { Arrête le pattern }
 
    {=========================================================================}
    PUBLIC { Public-déclarations ------------------------------------- PUBLIC }
      CONSTRUCTOR Create(AOwner:TComponent); OVERRIDE;         { Constructeur }
      DESTRUCTOR Destroy; OVERRIDE;                             { Destructeur }
 
    {=========================================================================}
    PUBLISHED { Published declarations ---------------------------- PUBLISHED }
 
      { Le mot déclaré property permet de déclarer une propriété.
      La définition d'une propriété dans une classe déclare un attribut nommé
      pour les objets de la classe et pour les actions associées à la lecture
      et à l'écriture de l'attribut.
 
      READ    => Fonction / Variable utilisé lors de la lecture de la propriété
      WRITE   => Fonction / Variable utilisé lors de l'affectation d'une valeur
                 à la propriété
      DEFAULT => Valeur par défaut (optionnel)
 
      S'il n'y a pas de "section" WRITE, la propriété est en lecture seule... }
 
 
      { DIVERS ------------------------------------------------------- Divers }
      PROPERTY Version : STRING                        { Version du composant }
        READ FVersion;                     { Renvoie la valeur de la variable }
 
      PROPERTY Enabled : BOOLEAN                         { Composant activé ? }
        READ FCanWrite                     { Renvoie la valeur de la variable }
        WRITE SetCanWrite;                     { Modifie la vaiable FCanWrite }
 
      PROPERTY Adresse : WORD                    { Adresse de base du PPI8255 }
        READ FAdresseBase8255              { Renvoie la valeur de la variable }
        WRITE SetAdresseBase;
 
 
      { CONFIGURATION DES PORTS --------------------- Configuration des ports }
      PROPERTY ModePortA : TModePort                       { Config du port A }
        READ FModeDuPortA                  { Renvoie la valeur de la variable }
        WRITE SetPortA                    { Initialise le port et la variable }
        DEFAULT mpIndefini;                       { Par défaut: état indéfini }
 
      PROPERTY ModePortB : TModePort                   { Comme pour le port A }
        READ FModeDuPortB
        WRITE SetPortB
        DEFAULT mpIndefini;
 
      PROPERTY ModePortC : TModePort                   { Comme pour le port A }
        READ FModeDuPortC
        WRITE SetPortC
        DEFAULT mpIndefini;
 
 
      { LECTURE / ECRITURE ------------------------------- Lecture / Ecriture }
      PROPERTY PortA : BYTE                                { Valeur du port A }
        READ LitPortA       { Lit la valeur actuellement présente sur le port }
        WRITE EcritPortA;                      { Ecrit une valeur sur le port }
 
      PROPERTY PortB : BYTE                            { Comme pour le port A }
        READ LitPortB
        WRITE EcritPortB;
 
      PROPERTY PortC : BYTE                            { Comme pour le port A }
        READ LitPortC
        WRITE EcritPortC;
 
 
      { CHENILLARD ----------------------------------------------- Chenillard }
      PROPERTY ChenillardPort : TPort        { Port utilisé par le chenillard }
        READ FPortChenillard                    { Lit quel est le port choisi }
        WRITE SetFPortChenillard                     { Initialise la variable }
        DEFAULT pPortA;                               { Par défaut, le port A }
 
      PROPERTY ChenillardStop : BOOLEAN                 { Arrêt du chenillard }
        READ FStopChenillard               { Renvoie la valeur de la variable }
        WRITE SetFStopChenillard                     { Initialise la variable }
        DEFAULT TRUE;                  { Par défaut, le chenillard est arrêté }
 
      PROPERTY ChenillardDelai : WORD { Attente entre chaque changemnt d'état }
        READ FDelaiChenillard               { Lit la valeur actuelle du délai }
        WRITE SetFDelaiChenillard                     { Modification du délai }
        DEFAULT 300;                                   { Par défaut, 300 [ms] }
 
      PROPERTY OnChenillardBouge:TNotifyEvent       { Le chenillard avance... }
        READ FOnChenillardBouge                 { Notification de l'événement }
        WRITE FOnChenillardBouge;               { Notification de l'événement }
 
      PROCEDURE Chenillard; VIRTUAL;                          { LE chenillard }
 
 
      { PATTERN ----------------------------------------------------- Pattern }
      PROPERTY PatternPorts : TPortPattern    { Ports utilisés par le pattern }
        READ FPortsPattern                  { Lit quel sont les ports choisis }
        WRITE SetFPortsPattern                       { Initialise la variable }
        DEFAULT ppABC;                 { Test du port A vers les ports B et C }
 
      PROPERTY PatternStop : BOOLEAN               { Arrêt du test de pattern }
        READ FStopPattern                  { Renvoie la valeur de la variable }
        WRITE SetFStopPattern                        { Initialise la variable }
        DEFAULT TRUE;                     { Par défaut, le pattern est arrêté }
 
      PROPERTY PatternNbOK:LONGINT             { Nb de transferts sans erreur }
        READ FNbOkPattern                  { Renvoie la valeur de la variable }
        DEFAULT 0;                     { Par défaut, pas encore de transferts }
 
      PROPERTY PatternNbErreurs:LONGINT        { Nb de transferts avec erreur }
        READ FNbErrPattern                 { Renvoie la valeur de la variable }
        DEFAULT 0;                                 { Par défaut, pas d'erreur }
 
      PROPERTY PatternMessage:STRING      { Message descriptif erreur pattern }
        READ FMsgErrPattern;               { Renvoie la valeur de la variable }
 
      PROPERTY OnErrorPattern : TNotifyEvent       { Erreur de transmisson... }
        READ FOnErrorPattern                    { Notification de l'événement }
        WRITE FOnErrorPattern;                  { Notification de l'événement }
 
      PROCEDURE Pattern; VIRTUAL;                        { LE test de pattern }
  END; {CLASS TPPI8255}
 
PROCEDURE Register;    { Enregistrement de l'objet dans l'inspecteur d'objets }
 
 
 
{=============================================================================}
IMPLEMENTATION   {================================= I M P L E M E N A T I O N }
{=============================================================================}
 
 
USES
  Forms,   { Pour "Application.ProcessMessages" }
  Dialogs;  
 
 
{1.04  Ajouté le tableau de constantes Poids }
CONST
  Poids : ARRAY[0..7] OF WORD = (1, 2, 4, 8, 16, 32, 64, 128);
 
 
TYPE
  bbit = 0..7;                                        { Pour l'accés aux bits }
 
 
 
{-----------------------------------------------------------------------------}
{ INITIALISATIONS ------------------------------------------- Initialisations }
{-----------------------------------------------------------------------------}
 
 
 
CONSTRUCTOR TPPI8255.Create;
{-----------------------------------------------------------------------------
  BUT ........... : C'est le CONSTRUCTOR. On initialise les variables du
                    composant et on appel le constructeur hérité de TComponent
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : Les variables globales sont initialisées
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  {  Toujours appeler le constructeur reçu en héritage }
  INHERITED Create(AOwner);
  FVersion := versionvcl;                                           { Version }
  FCanWrite        := FALSE;            { Interdiction d'écrire sur les ports }
  SetAdresseBase(adressebase);               { Valeur par défaut des adresses }
  FModeDuPortA     := mpIndefini;             { Etat des ports infédini (T'as }
  FModeDuPortB     := mpIndefini;                   { une boule de cristal ?) }
  FModeDuPortC     := mpIndefini;
  (*SetPortA(mpEntree);   Si FCanWrite est à FALSE, cette initialisation n'est
  SetPortB(mpEntree);     pas possible . . .
  SetPortC(mpEntree); *)
  FStopChenillard  := TRUE;                        { Le Chenillard est arrêté }
  FDelaiChenillard := 300;          { 300ms d'attente entre chaque changement }
  FStopPattern     := TRUE;                   { Le test de pattern est arrêté }
  FNbOkPattern     := 0;                                { Pas de transfert OK }
  FNbErrPattern    := 0;                                      { Pas d'erreurs }
  FMsgErrPattern   := '';                                    { Pas de message }
END; {CONSTRUCTOR Create}
 
 
DESTRUCTOR TPPI8255.Destroy;
{-----------------------------------------------------------------------------
  BUT ........... : Tout remettre en ordre quand on a fini
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  INHERITED Destroy;                  { Toujours appeler le destructor hérité }
END; {DESTRUCTOR Destroy}
 
 
 
{-----------------------------------------------------------------------------}
{ ACCES BAS NIVEAU ----------------------------------------- Accés bas niveau }
{-----------------------------------------------------------------------------}
 
 
 
FUNCTION InPortB(LePort:WORD):BYTE;
{-----------------------------------------------------------------------------
  BUT ........... : Lecture de l'état d'un port
  ENTREE ........ : LePort = Port sur lequel la valeur doit être lue
  SORTIE ........ : Valeur actuellement présente sur le port
  EFFETS DE BORDS : --
  REMARQUE(S) ... : 1.04:  Sauvegarde puis restauration du registre DX par un
                           PUSH/POP
 -----------------------------------------------------------------------------}
VAR
  Valeur : BYTE;
BEGIN
  ASM
    PUSH DX
    MOV  DX, LePort
    IN   AL, DX
    MOV  Valeur, AL
    POP  DX
  END; {ASM}
  InPortB := Valeur;
END; {FUNCTION InPortB}
 
 
PROCEDURE OutPortB(LePort:WORD; Value:BYTE); {ASSEMBLER;}
{-----------------------------------------------------------------------------
  BUT ........... : Ecrit une valeur sur un port
  ENTREE ........ : LePort = Port sur lequel la valeur doit être écrite
                    Valuer = Valeur à écrire sur le port
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : 1.04:  Sauvegarde puis restauration du registre DX par un
                           PUSH/POP
 -----------------------------------------------------------------------------}
BEGIN
  ASM
    PUSH  DX
    MOV   DX, LePort
    MOV   AL, Value
    OUT   DX, AL
    POP   DX
  END; {ASM}
END; {PROCEDURE OutPortB}
 
 
PROCEDURE SetBitB(VAR B : Byte; bit : bbit);
{-----------------------------------------------------------------------------
  BUT ........... : Mise à 1 d'un bit
  ENTREE ........ : B = Le byte à modifier
                    bit = le no du bit à changer (entre 0 et 7)
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : 1.04  Ce test logique remplace la fonction en assembleur
                          suivante:
                    PROCEDURE SetBitB(VAR B : Byte; bit : bbit); ASSEMBLER;
                    ASM
                      MOV CL, bit
                      MOV BL, 1
                      SHL BL, CL
                      LES DI, B
                      OR ES:[DI], BL  (*OR positionne le bit*)
                    END; (*PROCEDURE SetBitB*)
 -----------------------------------------------------------------------------}
BEGIN
  B := B OR Poids[bit]
END; {PROCEDURE SetBitB}
 
 
PROCEDURE ClearBitB(VAR B : Byte; bit : bbit);
{-----------------------------------------------------------------------------
  BUT ........... : Mise à 0 d'un bit
  ENTREE ........ : B = Le byte à modifier
                    bit = le no du bit à changer (entre 0 et 7)
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : 1.04  Ce test logique remplace la fonction en assembleur
                          suivante:
                    PROCEDURE ClearBitB(VAR B : Byte; bit : bbit); ASSEMBLER;
                    ASM
                      MOV CL, bit
                      MOV BL, 1
                      SHL BL, CL
                      NOT BL
                      LES DI, B
                      AND ES:[DI], BL (*AND of NOT BL met à zéro le bit*)
                    END; (*PROCEDURE ClearBitB*)
 -----------------------------------------------------------------------------}
BEGIN
  B := B AND NOT Poids[bit];
END; {PROCEDURE ClearBitB}
 
 
(*1.04  Supprimé cette procédure qui n'est pas utilisée
PROCEDURE ToggleBitB(VAR B : Byte; bit : bbit); ASSEMBLER;
{-----------------------------------------------------------------------------
  BUT ........... : Inverse l'état d'un bit (0->1 et 1->0)
  ENTREE ........ : B = Le byte à modifier
                    bit = le no du bit à changer (entre 0 et 7)
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... :
 -----------------------------------------------------------------------------}
ASM
  MOV CL, bit
  MOV BL, 1
  SHL BL, CL
  LES DI, B
  XOR ES:[DI], BL {XOR bascule le bit}
END; {PROCEDURE ToggleBitB} *)
 
 
 
{-----------------------------------------------------------------------------}
{ UTILITAIRES --------------------------------------------------- Utilitaires }
{-----------------------------------------------------------------------------}
 
 
 
FUNCTION Delay(DelayMS:LONGINT):BOOLEAN;
{-----------------------------------------------------------------------------
  BUT ........... : Remplace la fonction DELAY qui existrait sous DOS
  ENTREE ........ : DelayMS = Délai d'attente en MS
                    bit = le no du bit à changer (entre 0 et 7)
  SORTIE ........ : TRUE s'il a été demandé à l'application de quitter
  EFFETS DE BORDS : --
  REMARQUE(S) ... : 1.04  Remplacé GetTick par GetTickCount + Simplification
                    (*FUNCTION Delay(DelayMS:LONGINT):BOOLEAN;
                    VAR
                      ET : LONGINT;
                    FUNCTION GetTick:LONGINT;
                    (* BUT: Indique depuis combien de temps Windows est en
                            fonction *)
                    VAR
                      TI:TTimerInfo;
                    BEGIN
                      (* Initialise la taille du RECORD TTimerInfo *)
                      TI.dwSize := SizeOf(TI);
                      TimerCount(@TI);
                      (* Retourne le temps écoulé *)
                      Result := TI.dwmsThisVM;
                    END; (*FUNCTION GetTick:LONGINT*)
 
                    BEGIN (*FUNCTION Delay*)
                      ET := GetTick;
                      REPEAT
                        Application.ProcessMessages;
                      UNTIL Application.Terminated OR (GetTick-ET > DelayMS);
                      Result := Application.Terminated;
                    END; (*FUNCTION Delay*)
 -----------------------------------------------------------------------------}
VAR
  ET : LONGINT;
BEGIN
  IF DelayMS = 0 THEN BEGIN           {1.09 Si pas d'attente, quitte de suite }
    Result := Application.Terminated;
    Exit;
  END; {IF}
  ET := GetTickCount;
  REPEAT
    Application.ProcessMessages;
  UNTIL Application.Terminated OR (GetTickCount-ET > DelayMS);
  Result := Application.Terminated;
END;{FUNCTION Delay}
 
 
PROCEDURE Register;
{-----------------------------------------------------------------------------
  BUT ........... : Ajoute ce composant dans la palette des composants de
                    Delphi
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : Le composant est ajouté à la page "More..."
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  RegisterComponents('More...', [TPPI8255]);
END; {PROCEDURE Register}
 
 
 
{-----------------------------------------------------------------------------}
{ ENTREE/SORTIE ----------------------------------------------- Entrée/Sortie }
{-----------------------------------------------------------------------------}
 
 
 
PROCEDURE TPPI8255.SetCanWrite(WriteEnabled:BOOLEAN);
{-----------------------------------------------------------------------------
  BUT ........... : Autorise ou non l'écriture sur les ports
  ENTREE ........ : WriteEnabled : L'état futur de la variable FCanWrite
  SORTIE ........ : --
  EFFETS DE BORDS : FCanWrite prend la valeur du paramètre WriteEnabled
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  FCanWrite := WriteEnabled;
END; {PROCEDURE SetCanWrite}
 
 
PROCEDURE TPPI8255.AjusteAdresses;
{-----------------------------------------------------------------------------
  BUT ........... : Ajuste toutes les adresses du 8255 en fonction de l'adresse
                    de base
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : Les variables FAdressePortA, FAdressePortB, FAdressePortC
                    et FAdresseCtrl sont ajustées en fonction de la variable
                    FAdresseBase8255
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  FAdressePortA := FAdresseBase8255 + 0;
  FAdressePortB := FAdresseBase8255 + 1;
  FAdressePortC := FAdresseBase8255 + 2;
  FAdresseCtrl  := FAdresseBase8255 + 3;
END; {PROCEDURE TPPI8255.AjusteAdresses}
 
 
PROCEDURE TPPI8255.SetAdresseBase(Adresse:WORD);
{-----------------------------------------------------------------------------
  BUT ........... : Configuration de l'adresse de base
  ENTREE ........ : Adresse = L'adresse de base
  SORTIE ........ : --
  EFFETS DE BORDS : Les différentes adresses des ports du PPI sont modifiées
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  FAdresseBase8255 := Adresse;
  AjusteAdresses;                                   { MAJ des autres adresses }
END; {PROCEDURE TPPI8255.SetAdresseBase}
 
 
PROCEDURE TPPI8255.SetPortA(Mode:TModePort);
{-----------------------------------------------------------------------------
  BUT ........... : Initialisation du port A en entrée ou en sortie
  ENTREE ........ : Mode = Comment doit être configuré le port A
  SORTIE ........ : --
  EFFETS DE BORDS : La variable FModeDuPortA est initialisée à la valeur de Mode
  REMARQUE(S) ... : - Cette modification n'est possible que si:
                      a) les E/S sont autorisées, soit que FCanWrite est à TRUE
                      b) On ne configure pas le port dans un mode indéfini (on
                         sait ce qu'on veut faire)
                      c) Le chenillard et le pattern ne sont pas en cours
                         d'exécution
 -----------------------------------------------------------------------------}
VAR
  ValeurControle : BYTE;
BEGIN
  {1.07  Empêche toute modification de l'état du port si le chenillard ou
         le pattern est en cours d'exécution
  IF FCanWrite AND (Mode <> mpIndefini) THEN BEGIN }
  IF FCanWrite AND (Mode <> mpIndefini)
   AND FStopChenillard AND FStopPattern THEN BEGIN
    {1.09 Ne reconfigure le port que si la configuration change }
    IF FModeDuPortA = Mode THEN Exit;
    FModeDuPortA := Mode;                               { MAJ de la propriété }
    {1.08  Cette lecture est interdite ! }
    (*ValeurControle := InPortB(FAdresseCtrl);  { Valeur de contrôle actuelle }
    ValeurControle := Port[FAdresseCtrl];    { Valeur de contrôle actuelle } *)
    ValeurControle := 0;
    SetBitB(ValeurControle, 7);               { Drapeau de mode défini: Actif }
    ClearBitB(ValeurControle, 6);     { Passe en mode 0 pour tous les groupes }
    ClearBitB(ValeurControle, 5);
    ClearBitB(ValeurControle, 2);
    {1.08  Reconfigure chaque fois tous les ports}
    IF FModeDuPortA = mpSortie THEN ClearBitB(ValeurControle, 4)   { A Sortie }
                               ELSE SetBitB  (ValeurControle, 4);  { A Entree }
    IF FModeDuPortB = mpSortie THEN ClearBitB(ValeurControle, 1)   { B Sortie }
                               ELSE SetBitB  (ValeurControle, 1);  { B Entree }
    IF FModeDuPortC = mpSortie THEN ClearBitB(ValeurControle, 0)   { C Sortie }
                               ELSE SetBitB  (ValeurControle, 0);  { C Entree }
    IF FModeDuPortC = mpSortie THEN ClearBitB(ValeurControle, 3)   { C Sortie }
                               ELSE SetBitB  (ValeurControle, 3);  { C Entree }
    OutPortB(FAdresseCtrl, ValeurControle);   { Configure correctement le 8255 }
  END; {IF}
END; {PROCEDURE SetPortA}
 
 
PROCEDURE TPPI8255.SetPortB(Mode:TModePort);
{-----------------------------------------------------------------------------
  BUT ........... : Initialisation du port B en entrée ou en sortie
  ENTREE ........ : Mode = Comment doit être configuré le port B
  SORTIE ........ : --
  EFFETS DE BORDS : La variable FModeDuPortB est initialisée à la valeur de Mode
  REMARQUE(S) ... : - Cette modification n'est possible que si:
                      a) les E/S sont autorisées, soit que FCanWrite est à TRUE
                      b) On ne configure pas le port dans un mode indéfini (on
                         sait ce qu'on veut faire)
                      c) Le chenillard et le pattern ne sont pas en cours
                         d'exécution
 -----------------------------------------------------------------------------}
VAR
  ValeurControle : BYTE;
BEGIN
  {1.07  Empêche toute modification de l'état du port si le chenillard ou
         le pattern est en cours d'exécution
  IF FCanWrite AND (Mode <> mpIndefini) THEN BEGIN }
  IF FCanWrite AND (Mode <> mpIndefini)
     AND FStopChenillard AND FStopPattern THEN BEGIN
    {1.09 Ne reconfigure le port que si la configuration change }
    IF FModeDuPortB = Mode THEN Exit;
    FModeDuPortB := Mode;                               { MAJ de la propriété }
    {1.08  Cette lecture est interdite ! }
    (*ValeurControle := InPortB(FAdresseCtrl);  { Valeur de contrôle actuelle }
    ValeurControle := Port[FAdresseCtrl];    { Valeur de contrôle actuelle } *)
    ValeurControle := 0;
    SetBitB(ValeurControle, 7);               { Drapeau de mode défini: Actif }
    ClearBitB(ValeurControle, 6);     { Passe en mode 0 pour tous les groupes }
    ClearBitB(ValeurControle, 5);
    ClearBitB(ValeurControle, 2);
    {1.08  Reconfigure chaque fois tous les ports}
    IF FModeDuPortA = mpSortie THEN ClearBitB(ValeurControle, 4)   { A Sortie }
                               ELSE SetBitB  (ValeurControle, 4);  { A Entree }
    IF FModeDuPortB = mpSortie THEN ClearBitB(ValeurControle, 1)   { B Sortie }
                               ELSE SetBitB  (ValeurControle, 1);  { B Entree }
    IF FModeDuPortC = mpSortie THEN ClearBitB(ValeurControle, 0)   { C Sortie }
                               ELSE SetBitB  (ValeurControle, 0);  { C Entree }
    IF FModeDuPortC = mpSortie THEN ClearBitB(ValeurControle, 3)   { C Sortie }
                               ELSE SetBitB  (ValeurControle, 3);  { C Entree }
    OutPortB(FAdresseCtrl, ValeurControle);   { Configure correctement le 8255 }
  END; {IF}
END; {PROCEDURE SetPortB}
 
 
PROCEDURE TPPI8255.SetPortC(Mode:TModePort);
{-----------------------------------------------------------------------------
  BUT ........... : Initialisation du port C en entrée ou en sortie
  ENTREE ........ : Mode = Comment doit être configuré le port C
  SORTIE ........ : --
  EFFETS DE BORDS : La variable FModeDuPortC est initialisée à la valeur de Mode
  REMARQUE(S) ... : - Cette modification n'est possible que si:
                      a) les E/S sont autorisées, soit que FCanWrite est à TRUE
                      b) On ne configure pas le port dans un mode indéfini (on
                         sait ce qu'on veut faire)
                      c) Le chenillard et le pattern ne sont pas en cours
                         d'exécution
                    - L'initialisation de se port se fait en deux fois, car il
                      ne s'agit pas d'un port 8 bits, mais de deux ports de 4
                      bits
 -----------------------------------------------------------------------------}
VAR
  ValeurControle : BYTE;
BEGIN
  {1.07  Empêche toute modification de l'état du port si le chenillard ou
         le pattern est en cours d'exécution
  IF FCanWrite AND (Mode <> mpIndefini) THEN BEGIN }
  IF FCanWrite AND (Mode <> mpIndefini)
     AND FStopChenillard AND FStopPattern THEN BEGIN
    {1.09 Ne reconfigure le port que si la configuration change }
    IF FModeDuPortC = Mode THEN Exit;
    FModeDuPortC := Mode;                               { MAJ de la propriété }
    {1.08  Cette lecture est interdite ! }
    (*ValeurControle := InPortB(FAdresseCtrl);  { Valeur de contrôle actuelle }
    ValeurControle := Port[FAdresseCtrl];    { Valeur de contrôle actuelle } *)
    ValeurControle := 0;
    SetBitB(ValeurControle, 7);               { Drapeau de mode défini: Actif }
    ClearBitB(ValeurControle, 6);     { Passe en mode 0 pour tous les groupes }
    ClearBitB(ValeurControle, 5);
    ClearBitB(ValeurControle, 2);
    {1.08  Reconfigure chaque fois tous les ports}
    IF FModeDuPortA = mpSortie THEN ClearBitB(ValeurControle, 4)   { A Sortie }
                               ELSE SetBitB  (ValeurControle, 4);  { A Entree }
    IF FModeDuPortB = mpSortie THEN ClearBitB(ValeurControle, 1)   { B Sortie }
                               ELSE SetBitB  (ValeurControle, 1);  { B Entree }
    IF FModeDuPortC = mpSortie THEN ClearBitB(ValeurControle, 0)   { C Sortie }
                               ELSE SetBitB  (ValeurControle, 0);  { C Entree }
    IF FModeDuPortC = mpSortie THEN ClearBitB(ValeurControle, 3)   { C Sortie }
                               ELSE SetBitB  (ValeurControle, 3);  { C Entree }
    OutPortB(FAdresseCtrl, ValeurControle);   { Configure correctement le 8255 }
  END; {IF}
END; {PROCEDURE SetPortC}
 
 
FUNCTION TPPI8255.LitPortA:BYTE;
{-----------------------------------------------------------------------------
  BUT ........... : Lit la valeur actuellement présente sur le port A
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  Result := InPortB(FAdressePortA)
END; {FUNCTION LitPortA}
 
 
PROCEDURE TPPI8255.EcritPortA(Valeur:BYTE);
{-----------------------------------------------------------------------------
  BUT ........... : Ecrit une valeur sur le port A
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : - L'écriture n'est possible que si
                      a) le port est configuré en sortie
                      b) les E/S sont permises
 -----------------------------------------------------------------------------}
BEGIN
  IF FCanWrite AND (FModeDuPortA = mpSortie) THEN BEGIN
    OutPortB(FAdressePortA, Valeur);
  END; {IF}
END; {PROCEDURE EcritPortA}
 
 
FUNCTION TPPI8255.LitPortB:BYTE;
{-----------------------------------------------------------------------------
  BUT ........... : Lit la valeur actuellement présente sur le port B
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  Result := InPortB(FAdressePortB)
END; {FUNCTION LitPortB}
 
 
PROCEDURE TPPI8255.EcritPortB(Valeur:BYTE);
{-----------------------------------------------------------------------------
  BUT ........... : Ecrit une valeur sur le port B
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : - L'écriture n'est possible que si
                      a) le port est configuré en sortie
                      b) les E/S sont permises
 -----------------------------------------------------------------------------}
BEGIN
  IF FCanWrite AND (FModeDuPortB = mpSortie) THEN BEGIN
    OutPortB(FAdressePortB, Valeur);
  END; {IF}
END; {PROCEDURE EcritPortB}
 
 
FUNCTION TPPI8255.LitPortC:BYTE;
{-----------------------------------------------------------------------------
  BUT ........... : Lit la valeur actuellement présente sur le port C
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  Result := InPortB(FAdressePortC)
END; {FUNCTION LitPortC}
 
 
PROCEDURE TPPI8255.EcritPortC(Valeur:BYTE);
{-----------------------------------------------------------------------------
  BUT ........... : Ecrit une valeur sur le port C
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : - L'écriture n'est possible que si
                      a) le port est configuré en sortie
                      b) les E/S sont permises
 -----------------------------------------------------------------------------}
BEGIN
  IF FCanWrite AND (FModeDuPortC = mpSortie) THEN BEGIN
    OutPortB(FAdressePortC, Valeur);
  END; {IF}
END; {PROCEDURE EcritPortC}
 
 
 
{-----------------------------------------------------------------------------}
{ CHENILLARD ----------------------------------------------------- Chenillard }
{-----------------------------------------------------------------------------}
 
 
 
PROCEDURE TPPI8255.SetFStopChenillard(Stop:BOOLEAN);
{-----------------------------------------------------------------------------
  BUT ........... : Arrête le Chenillard en mettant à TRUE la variable
                    FStopChenillard
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  FStopChenillard := Stop;
END; {PROCEDURE SetFStopChenillard}
 
 
PROCEDURE TPPI8255.SetFPortChenillard(LePort:TPort);
{-----------------------------------------------------------------------------
  BUT ........... : Change le port utilisé par le chenillard
  ENTREE ........ : LePort = Le port choisi pour le chenillard
  SORTIE ........ : --
  EFFETS DE BORDS : FPortChenillard est initialisé à la valeur de LePort
  REMARQUE(S) ... : - Si le chenillard est en fonction, il sera arrêté
 -----------------------------------------------------------------------------}
BEGIN
   SetFStopChenillard(TRUE);  { Arrête le chenillard s'il était en train de..
                                                                    ..tourner }
   FPortChenillard := LePort; { Hissez les voiles, et virer à babord, on..
                                                             ..change de port }
END; {PROCEDURE SetFPortChenillard}
 
 
PROCEDURE TPPI8255.SetFDelaiChenillard(Delay:WORD);
{-----------------------------------------------------------------------------
  BUT ........... : Fixe la vitesse du Chenillard, càd le temps qu'il faut
                    attendre entre chaque changement d'état
  ENTREE ........ : Delay = Le nombre de [ms] qu'il faut attendre. Cette valeur
                            va de 0 à 65535 (1000 = 1 seconde)
  SORTIE ........ : --
  EFFETS DE BORDS : FDelaiChenillard est initialisé à la valeur de Delay
  REMARQUE(S) ... : - Si le chenillard est en fonction, il sera arrêté
 -----------------------------------------------------------------------------}
BEGIN
  FDelaiChenillard := Delay;
END; {PROCEDURE SetFDelaiChenillard}
 
 
PROCEDURE TPPI8255.Chenillard;
{-----------------------------------------------------------------------------
  BUT ........... : Effet de Chenillard sur un des ports
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : - Pour arrêter le chenillard une fois qu'il est lancé, il
                      faut mettre à TRUE la variable FStopChenillard via la
                      propriété ChenillardStop
                    - A chaque changement d'état du chenillard, l'événement
                      OnChenillardBouge est déclenché
 -----------------------------------------------------------------------------}
VAR
  EtatPort : BYTE;                                      { Etat actuel du port }
  Sens     : SHORTINT;                       { Sens de déplacement du bit à 1 }
  NoBit    : SHORTINT;                                { No du bit qui est à 1 }
BEGIN
  {-- Initialisations }
  EtatPort := 0;
  Sens     := +1;
  NoBit    := 0;
 
  {-- Si le test de pattern est en cours, l'arrête et quitte cette procédure }
  IF NOT FStopPattern THEN BEGIN
    { 1.09 Il n'est pas nécessaire de l'arrêter }
    {SetFStopPattern(TRUE);}
    {1.07  Quitte la procédure }
    Exit;
  END {IF}
  ELSE IF NOT FStopChenillard THEN BEGIN
    {1.07  Si le chenillard est déjà activé quitte la procédure }
    Exit;
  END; {IF}
 
  {-- Set du mode de fonctionnement des différents ports en fonction du port
      choisi pour le chenillard }
  CASE FPortChenillard OF
    pPortA : BEGIN
               SetPortA(mpSortie);  SetPortB(mpEntree);  SetPortC(mpEntree);
               EcritPortA(EtatPort);
             END; {BRANCH OF CASE}
    pPortB : BEGIN
               SetPortA(mpEntree);  SetPortB(mpSortie);  SetPortC(mpEntree);
               EcritPortB(EtatPort);
             END; {BRANCH OF CASE}
    pPortC : BEGIN
               SetPortA(mpEntree);  SetPortB(mpEntree);  SetPortC(mpSortie);
               EcritPortC(EtatPort);
             END; {BRANCH OF CASE}
  END; {CASE OF}
 
  {-- C'est parti !! pour le chenillard style K2000 }
  FStopChenillard := FALSE;
  REPEAT
    IF Sens > 0 THEN BEGIN                    { Déplacement de la LED allumée }
      NoBit := NoBit + 1;
      IF NoBit > 8 THEN BEGIN                                 { Débordement ? }
        Sens := -1;                           { Oui, alors changement de sens }
        NoBit := NoBit - 2;
      END; {IF}
    END {IF}
    ELSE BEGIN
      NoBit := NoBit - 1;
      IF NoBit < 1 THEN BEGIN                                 { Débordement ? }
        Sens := +1;                           { Oui, alors changement de sens }
        NoBit := NoBit + 2;
      END; {IF}
    END; {ELSE}
    {1.06  Remplace le ClearBitB par un := 0, car sinon, on affiche
     n'importe quoi ! }
    {ClearBitB(EtatPort, NoBit);                                  { RAZ du bit }
    EtatPort := 0;
    {1.03  NoBit-1, pas NoBit, car SetBitB va de 0 à 7 et non pas de 1 à 8 }
    SetBitB(EtatPort, NoBit-1);                            { Mise à un du bit }
    CASE FPortChenillard OF                              { Sortie sur le port }
      pPortA : EcritPortA(EtatPort);
      pPortB : EcritPortB(EtatPort);
      pPortC : EcritPortC(EtatPort);
    END; {CASE OF}
 
    IF Assigned(FOnChenillardBouge) THEN BEGIN
      FOnChenillardBouge(Self);     { Signale que ça a bougé en déclenchant..
                                              ..l'evénement OnChenillardBouge }
    END; {IF}
 
    IF Delay(FDelaiChenillard) THEN BEGIN            { On attend un moment... }
      {Il a été demandé de quitter l'application, alors on arrête ! }
      FStopChenillard := TRUE;
    END; {IF}
    { -- Laisse Windows faire son boulot.
         Cette ligne est OBLIGATOIRE, sinon on Windows ne pourra jamais prendre
         exécuter le code d'un contrôle qui met la variable FStopChenillard à
         TRUE, donc arrête le chenillard... }
    Application.ProcessMessages;
  UNTIL FStopChenillard;                                        { On arrête ? }
 
  CASE FPortChenillard OF                         { Met la valeur du port à 0 }
    pPortA : EcritPortA(0);
    pPortB : EcritPortB(0);
    pPortC : EcritPortC(0);
  END; {CASE OF}
 
  IF Assigned(FOnChenillardBouge) THEN BEGIN
    FOnChenillardBouge(Self);                        { Signale que ça a bougé }
  END; {IF}
 
END; {PROCEDURE Chenillard}
 
 
 
{-----------------------------------------------------------------------------}
{ PATTERN ----------------------------------------------------------- Pattern }
{-----------------------------------------------------------------------------}
 
 
 
PROCEDURE TPPI8255.SetFPortsPattern(Valeur:TPortPattern);
{-----------------------------------------------------------------------------
  BUT ........... : Choix des ports à utiliser pour le test de pattern
  ENTREE ........ : Valeur = les différents ports à utiliser pour le test
  SORTIE ........ : --
  EFFETS DE BORDS : FPortsPattern est initialisé à Valeur
  REMARQUE(S) ... : Si le test est déjà en cours de fonctionnement, l'arrête
 -----------------------------------------------------------------------------}
BEGIN
  {1.09 C'est pas le chenillard qu'il faut arrêter, mais le pattern ! }
  (*{ Arrête le chenillard s'il était en train de tourner }
  SetFStopChenillard(TRUE); *)
  SetFStopPattern(TRUE);
  { Choix des ports à utiliser pour le test de pattern }
  FPortsPattern := Valeur;
END; {PROCEDURE SetFPortsPattern}
 
 
PROCEDURE TPPI8255.SetFStopPattern(Stop:BOOLEAN);
{-----------------------------------------------------------------------------
  BUT ........... : Arrête (peut-être) le test de transmission de Pattern
  ENTREE ........ : Stop = TRUE si on veut arrêter le test, sinon FALSE
  SORTIE ........ : --
  EFFETS DE BORDS : - FStopPattern est initialisé à la valeur de Stop
                    - Le test n'est arrêté que si FStopPattern vaut TRUE
  REMARQUE(S) ... : --
 -----------------------------------------------------------------------------}
BEGIN
  FStopPattern := Stop;
END; {PROCEDURE SetFStopPattern}
 
 
PROCEDURE TPPI8255.Pattern;
{-----------------------------------------------------------------------------
  BUT ........... : Test de transfert de données entre deux ports
  ENTREE ........ : --
  SORTIE ........ : --
  EFFETS DE BORDS : --
  REMARQUE(S) ... : - Pour arrêter le test une fois qu'il est lancé, il
                      faut mettre à TRUE la variable FStopPattern via la
                      propriété PatternStop
                    - A chaque changement d'état du chenillard, l'événement
                      OnChenillardBouge est déclenché
 -----------------------------------------------------------------------------}
VAR
  NoPattern     : INTEGER;                      { No du pattern à transmettre }
  LuA, LuB, LuC : BYTE;                              { Valeur réellement lues }
  MessageErr    : STRING;    { Message d'erreur en cas de transmission loupée }
BEGIN
 
  { On ne commence pas si le chenillard ou le test de pattern sont déjà en
    cours d'exécution }
  IF NOT FStopChenillard THEN BEGIN
    {1.09 Il n'y a pas besoin de l'arrêter ! on ne commence pas quelque chose
          de nouveau, c'est tout }
    {SetFStopChenillard(TRUE);}
    {1.07  Quitte la procédure si le chenillard est en cours de fonctionnement }
    Exit;
  END {IF}
  ELSE IF NOT FStopPattern THEN BEGIN
    {1.07  Quitte la procédure si le test de pattern est déjà activé }
    Exit;
  END; {IF}
 
  { Set des ports en fonction du port choisi pour le pattern }
  {1.07  Nouvelles configurations possibles, en utilisant que 2 ports au lieu
         de trois }
  CASE FPortsPattern OF
    ppAB,
    ppAC,
    ppABC : BEGIN                             { A => B, A => C ou A => B et C }
              SetPortA(mpSortie); SetPortB(mpEntree); SetPortC(mpEntree);
            END; {BRANCH OF CASE}
    ppBA,
    ppBC,
    ppBAC : BEGIN                             { B => A, B => C ou B => A et C }
              SetPortA(mpEntree); SetPortB(mpSortie); SetPortC(mpEntree);
            END; {BRANCH OF CASE}
    ppCA,
    ppCB,
    ppCAB : BEGIN                             { C => A, C => B ou C => A et B }
              SetPortA(mpEntree); SetPortB(mpEntree); SetPortC(mpSortie);
             END; {BRANCH OF CASE}
  END; {CASE OF}
 
  FNbErrPattern    := 0;                                { Pas encore d'erreur }
  FNbOkPattern     := 0;
  FMsgErrPattern:= '';
  NoPattern        := 1;                   { Commence avec le premier pattern }
  LuA := 0; LuB := 0; LuC := 0;                   { Rien vu, rien bu, rien lu }
 
  { C'est parti !! }
  FStopPattern := FALSE;
  REPEAT
    CASE FPortsPattern OF
      ppABC : BEGIN { -------------------------------------------- A => B & C }
                { Ecrit une valeur }
                EcritPortA(patterntest[NoPattern]);
                { Lit ce qu'il y a sur les autres ports }
                LuB := LitPortB;
                LuC := LitPortC;
                IF ((patternTest[NoPattern] <> LuB) OR              { Compare }
                    (patternTest[NoPattern] <> LuC)) THEN BEGIN
                  { IL Y A UN BOGUE !! }
                  Inc(FNbErrPattern);               { MAJ du nombre d'erreurs }
                  { Création du message d'erreur }
                  MessageErr := ' A('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> B('+IntToHex(LuB,2)+'h)';
                  MessageErr := MessageErr+' & C('+IntToHex(LuC, 2) + 'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  Inc(FNbOkPattern);                          {  Transfert OK }
                END; {ELSE}
              END; {BRANCH OF CASE}
      ppBAC : BEGIN                                      { Pattern B => A & C }
                EcritPortB(patterntest[NoPattern]);
                LuA := LitPortA;
                LuC := LitPortC;
                IF ((patternTest[NoPattern] <> LuA) OR
                    (patternTest[NoPattern] <> LuC)) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' B('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> A('+IntToHex(LuA,2)+'h)';
                  MessageErr := MessageErr+' & C('+IntToHex(LuC, 2) + 'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
      ppCAB : BEGIN                                      { Pattern C => A & B }
                EcritPortC(patterntest[NoPattern]);
                LuA := LitPortA;
                LuB := LitPortB;
                IF ((patternTest[NoPattern] <> LuA) OR
                    (patternTest[NoPattern] <> LuB)) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' C('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> A('+IntToHex(LuA,2)+'h)';
                  MessageErr := MessageErr+' & B('+IntToHex(LuB, 2) + 'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
      {1.07  Nouvelles configurations possibles }
      ppAB  : BEGIN                                          { Pattern A => B }
                EcritPortA(patterntest[NoPattern]);
                LuB := LitPortB;
                IF (patternTest[NoPattern] <> LuB) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' A('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> B('+IntToHex(LuB,2)+'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
      ppAC  : BEGIN                                          { Pattern A => C }
                EcritPortA(patterntest[NoPattern]);
                LuC := LitPortC;
                IF (patternTest[NoPattern] <> LuC) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' A('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> C('+IntToHex(LuC,2)+'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
      ppBA  : BEGIN                                          { Pattern B => A }
                EcritPortB(patterntest[NoPattern]);
                LuA := LitPortA;
                IF (patternTest[NoPattern] <> LuA) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' B('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> A('+IntToHex(LuA,2)+'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
      ppBC  : BEGIN                                          { Pattern B => C }
                EcritPortB(patterntest[NoPattern]);
                LuC := LitPortC;
                IF (patternTest[NoPattern] <> LuC) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' B('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> C('+IntToHex(LuC,2)+'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
      ppCA  : BEGIN                                          { Pattern C => A }
                EcritPortC(patterntest[NoPattern]);
                LuA := LitPortA;
                IF (patternTest[NoPattern] <> LuB) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' C('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> A('+IntToHex(LuB,2)+'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
      ppCB  : BEGIN                                          { Pattern C => B }
                EcritPortC(patterntest[NoPattern]);
                LuB := LitPortB;
                IF (patternTest[NoPattern] <> LuB) THEN BEGIN
                  {-- Erreur lors du transfert }
                  Inc(FNbErrPattern);                { Une erreur de plus ... }
                  MessageErr := ' C('+IntToHex(patterntest[NoPattern],2)+'h)';
                  MessageErr := MessageErr+' -> B('+IntToHex(LuB,2)+'h)';
                  FMsgErrPattern := MessageErr;
                  IF Assigned(FOnErrorPattern) THEN BEGIN
                    FOnErrorPattern(Self);         { Notification de l'erreur }
                  END; {IF}
                END {IF}
                ELSE BEGIN
                  {-- Transfert OK }
                  Inc(FNbOkPattern);
                END; {ELSE}
              END; {BRANCH OF CASE}
    END; {CASE OF}
    {-- Passe au pattern suivant }
    Inc(NoPattern);
    IF NoPattern > nbpas THEN BEGIN
      { Tout a été transmis, on recommence au départ }
      NoPattern := 1;
    END; {IF}
    { -- Laisse Windows faire son boulot.
         Cette ligne est OBLIGATOIRE, sinon on Windows ne pourra jamais prendre
         exécuter le code d'un contrôle qui met la variable FStopChenillard à
         TRUE, donc arrête le chenillard... }
    Application.ProcessMessages;
    IF Application.Terminated THEN BEGIN
      { Il a été demandé d'arrêter l'application, alors on fait ce qui a été
        demandé, on arrête.}
      FStopPattern := TRUE;
    END; {IF}
  UNTIL FStopPattern;
 
END; {PROCEDURE Pattern}
 
 
 
{-----------------------------------------------------------------------------}
{ THAT'S ALL -------------------------------------------------------- The end }
{-----------------------------------------------------------------------------}
 
 
 
INITIALIZATION
END. {UNIT Vcl8255}
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
start/eti/carte/sources/vcl8255.txt · Last modified: 2016/07/24 01:23 by admin