unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Buttons, StdCtrls, CPort, ComCtrls, Gauges; type TForm1 = class(TForm) ComPort1: TComPort; GroupBox1: TGroupBox; Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Edit4: TEdit; SpeedButton1: TSpeedButton; SpeedButton2: TSpeedButton; SpeedButton3: TSpeedButton; SpeedButton4: TSpeedButton; SpeedButton5: TSpeedButton; GroupBox2: TGroupBox; TrackBar1: TTrackBar; TrackBar2: TTrackBar; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; GroupBox3: TGroupBox; GroupBox4: TGroupBox; Label5: TLabel; Edit5: TEdit; SpeedButton6: TSpeedButton; Edit6: TEdit; SpeedButton7: TSpeedButton; Label6: TLabel; Label7: TLabel; Label8: TLabel; Label9: TLabel; Label10: TLabel; GroupBox5: TGroupBox; Label11: TLabel; Label12: TLabel; Gauge1: TGauge; Gauge2: TGauge; Label13: TLabel; Label14: TLabel; Label15: TLabel; ComDataPacket1: TComDataPacket; Edit7: TEdit; Edit8: TEdit; Edit9: TEdit; Label16: TLabel; SpeedButton8: TSpeedButton; SpeedButton9: TSpeedButton; SpeedButton10: TSpeedButton; Label17: TLabel; Label18: TLabel; procedure FormCreate(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure SpeedButton1Click(Sender: TObject); procedure SpeedButton2Click(Sender: TObject); procedure SpeedButton3Click(Sender: TObject); procedure SpeedButton4Click(Sender: TObject); procedure SpeedButton5Click(Sender: TObject); procedure TrackBar1Change(Sender: TObject); procedure TrackBar2Change(Sender: TObject); procedure SpeedButton6Click(Sender: TObject); procedure SpeedButton7Click(Sender: TObject); procedure ComDataPacket1Packet(Sender: TObject; const Str: String); procedure SpeedButton8Click(Sender: TObject); procedure SpeedButton9Click(Sender: TObject); procedure SpeedButton10Click(Sender: TObject); private { Déclarations privées } public { Déclarations publiques } end; var Form1: TForm1; CARAC : String; CARACIN : String; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); // Executé au lancement de l'application. begin ComPort1.BaudRate:=br19200; // Port à 19200 bauds. Attention, ne changez pas la vitesse de communication série. ComPort1.Port:='COM1'; // Com 1 ouvert par défaut. !!!! A CHANGER SELON LE VOTRE PORT SERIE. Ex : COM1, COM2, COM3, COM4, etc... !!!! //** Configuration de la réception par paquet : ComDataPacket1 ** ComDataPacket1.StartString:='!'; // On définit le caractère de début de chaine '!'. ComDataPacket1.StopString:='#'; // On définit le caractère de fin de chaine '#'. ComDataPacket1.IncludeStrings:=True; ComDataPacket1.Size:=7; // On définit 9 caractères dans la chaine Packet1. //*************************************************************** Comport1.Open; // Ouverture le port de communucation série au lancement de l'application. //*** Nombre maximal de caractères admissibles pour chaque ligne du LCD *** // Ligne n°1 // Edit1.MaxLength:=8 // 8 caractères maxi à saisir dans Edit pour un afficheur n X 8 caractères. // Edit1.MaxLength:=16; // 16 caractères maxi à saisir dans Edit pour un afficheur n X 16 caractères. Edit1.MaxLength:=20; // 20 caractères maxi à saisir dans Edit pour un afficheur n X 20 caractères. // Ligne n°2 // Edit2.MaxLength:=8 // 8 caractères maxi à saisir dans Edit pour un afficheur n X 8 caractères. // Edit2.MaxLength:=16; // 16 caractères maxi à saisir dans Edit pour un afficheur n X 16 caractères. Edit2.MaxLength:=20; // 20 caractères maxi à saisir dans Edit pour un afficheur n X 20 caractères. // Ligne n°3 // Edit3.MaxLength:=8 // 8 caractères maxi à saisir dans Edit pour un afficheur n X 8 caractères. // Edit3.MaxLength:=16; // 16 caractères maxi à saisir dans Edit pour un afficheur n X 16 caractères. Edit3.MaxLength:=20; // 20 caractères maxi à saisir dans Edit pour un afficheur n X 20 caractères. // Ligne n°4 // Edit4.MaxLength:=8 // 8 caractères maxi à saisir dans Edit pour un afficheur n X 8 caractères. // Edit4.MaxLength:=16; // 16 caractères maxi à saisir dans Edit pour un afficheur n X 16 caractères. Edit4.MaxLength:=20; // 20 caractères maxi à saisir dans Edit pour un afficheur n X 20 caractères. // Positions par défaut du TrackBar1 pour la sortie J7 permettant de définir le rapport cyclique du signal PWM TrackBar1.Max:=255; // Valeur maxi du rapport cyclique TrackBar1.Min:=0; // Valeur mini du rapport cyclique TrackBar1.Position:=127; // Position par défaut du rapport cyclique de la sortie J7 à 50% // Positions par défaut du TrackBar1 pour la sortie J8 permettant de définir le rapport cyclique du signal PWM TrackBar2.Max:=255; // Valeur maxi du rapport cyclique TrackBar2.Min:=0; // Valeur mini du rapport cyclique TrackBar2.Position:=127; // Position par défaut du rapport cyclique de la sortie J8 à 50% // Détermination des paramètres des GAUGE1 et GAUGE2 pour les entrées analogiques J5 et J6 du CAN 12 bits. GAUGE1.MinValue:=0; GAUGE1.MaxValue:=4096; GAUGE2.MinValue:=0; GAUGE2.MaxValue:=4096; // Sorties digitales J3, J4, J9, J10, J11 Edit5.MaxLength:=3; // Autorise une valeur maxi composée de 3 chiffres. Soit de 0 à 999. Edit6.MaxLength:=3; // Autorise une valeur maxi composée de 3 chiffres. Soit de 0 à 999. Edit7.MaxLength:=3; // Autorise une valeur maxi composée de 3 chiffres. Soit de 0 à 999. Edit8.MaxLength:=3; // Autorise une valeur maxi composée de 3 chiffres. Soit de 0 à 999. Edit9.MaxLength:=3; // Autorise une valeur maxi composée de 3 chiffres. Soit de 0 à 999. Edit5.Text:='0'; // Valeur par défaut de l'octet à zéro. Edit6.Text:='0'; // Valeur par défaut de l'octet à zéro. Edit7.Text:='0'; // Valeur par défaut de l'octet à zéro. Edit8.Text:='0'; // Valeur par défaut de l'octet à zéro. Edit9.Text:='0'; // Valeur par défaut de l'octet à zéro. end; procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); // Si l'utilisateur ferme l'application. begin Comport1.Close; // Ferme le port de commununication série.l'application. C'est plus prudent... end; //*********************************************************** //*********************************************************** //** Procedures de transfert des données du PC vers le PIC ** //*********************************************************** //*********************************************************** //******************** //** GESTION DU LCD ** //******************** procedure TForm1.SpeedButton1Click(Sender: TObject); // Bouton "Transfert ligne 1 du LCD" begin Carac:='$1'+Edit1.Text+'|#'; // $1 = 2 caractères indiquant première ligne du LCD. Edit1.Text= votre texte. |# = 2 caractères obligatoires de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; procedure TForm1.SpeedButton2Click(Sender: TObject); // Bouton "Transfert ligne 2 du LCD" begin Carac:='$2'+Edit2.Text+'|#'; // $2 = 2 caractères indiquant la seconde ligne du LCD. Edit1.Text= votre texte. |# = 2 caractères obligatoires de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; procedure TForm1.SpeedButton3Click(Sender: TObject); // Bouton "Transfert ligne 3 du LCD" begin Carac:='$3'+Edit3.Text+'|#'; // $3 = 2 caractères indiquant la troisième ligne du LCD. Edit1.Text= votre texte. |# = 2 caractères obligatoires de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; procedure TForm1.SpeedButton4Click(Sender: TObject); // Bouton "Transfert ligne 4 du LCD" begin Carac:='$4'+Edit4.Text+'|#'; // $4 = 2 caractères indiquant la quatrième ligne du LCD. Edit1.Text= votre texte. |# = 2 caractères obligatoires de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; procedure TForm1.SpeedButton5Click(Sender: TObject); // Bouton "Effacer le LCD" begin Carac:='$5#'; // $5# => $ = caractère d'entête. 5 = correspond à l'effacement du LCD. # = caractère de fin de chaine. Comport1.WriteStr(CARAC); // Transmission RS232. end; //************************ //** FIN GESTION DU LCD ** //************************ //*********************************** //** 2 Sorties analogiques et PWM ** //*********************************** procedure TForm1.TrackBar1Change(Sender: TObject); // Sortie J7 begin // Affiche la position du Trackbar1 Label3.Caption:=IntToStr(TrackBar1.Position); Carac:='$6'+IntToStr(TrackBar1.Position)+'|#'; // $= caractère d'entête. 6 = correspond au PMW de la sortie J7. TrackBar1.Position= est compris entre 0 et 255. |# = caractère de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; procedure TForm1.TrackBar2Change(Sender: TObject); // Sortie J8 begin // Affiche la position du Trackbar2 Label4.Caption:=IntToStr(TrackBar2.Position); Carac:='$7'+IntToStr(TrackBar2.Position)+'|#'; // $= caractère d'entête. 7 = correspond au PMW de la sortie J8. TrackBar2.Position= est compris entre 0 et 255. |# = caractère de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; //*************************************** //** FIN 2 Sorties analogiques et PWM ** //*************************************** //************************************************************* //** Sorties digitales J3 sur 1 octet compris entre 0 et 255 ** //************************************************************* procedure TForm1.SpeedButton6Click(Sender: TObject); begin if Edit5.Text='' then // Si le champs est vide on ne fait rien. begin Edit5.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit5.Text)<0) or (StrToInt(Edit5.Text)>255) then // Les valeurs négatives ou supérieures à 255 sont rejetées. begin Edit5.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit5.Text)>=0) and (StrToInt(Edit5.Text)<=255) then // Valeur comprise entre 0 et 255 => on envoie l'octet au PIC. begin Carac:='$8'+Edit5.Text+'|#'; // $= caractère d'entête. 8 = correspond à la sortie digitale J3. Edit5.Text= est compris entre 0 et 255. |# = caractère de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; end; //***************************************************************** //** FIN Sorties digitales J3 sur 1 octet compris entre 0 et 255 ** //***************************************************************** //************************************************************* //** Sorties digitales J4 sur 1 octet compris entre 0 et 255 ** //************************************************************* procedure TForm1.SpeedButton7Click(Sender: TObject); begin if Edit6.Text='' then // Si le champs est vide on ne fait rien. begin Edit6.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit6.Text)<0) or (StrToInt(Edit6.Text)>255) then // Les valeurs négatives ou supérieures à 255 sont rejetées. begin Edit6.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit6.Text)>=0) and (StrToInt(Edit6.Text)<=255) then // Valeur comprise entre 0 et 255 => on envoie l'octet au PIC. begin Carac:='$9'+Edit6.Text+'|#'; // $= caractère d'entête. 8 = correspond à la sortie digitale J4. Edit6.Text= est compris entre 0 et 255. |# = caractère de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; end; //***************************************************************** //** FIN Sorties digitales J4 sur 1 octet compris entre 0 et 255 ** //***************************************************************** //************************************************************* //** Sorties digitales J9 sur 1 octet compris entre 0 et 255 ** //************************************************************* procedure TForm1.SpeedButton8Click(Sender: TObject); begin if Edit7.Text='' then // Si le champs est vide on ne fait rien. begin Edit7.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit7.Text)<0) or (StrToInt(Edit7.Text)>255) then // Les valeurs négatives ou supérieures à 255 sont rejetées. begin Edit7.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit7.Text)>=0) and (StrToInt(Edit7.Text)<=255) then // Valeur comprise entre 0 et 255 => on envoie l'octet au PIC. begin Carac:='$A'+Edit7.Text+'|#'; // $= caractère d'entête. 8 = correspond à la sortie digitale J7. Edit7.Text= est compris entre 0 et 255. |# = caractère de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; end; //***************************************************************** //** FIN Sorties digitales J9 sur 1 octet compris entre 0 et 255 ** //***************************************************************** //************************************************************* //** Sorties digitales J10 sur 1 octet compris entre 0 et 255 ** //************************************************************* procedure TForm1.SpeedButton9Click(Sender: TObject); begin if Edit8.Text='' then // Si le champs est vide on ne fait rien. begin Edit8.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit8.Text)<0) or (StrToInt(Edit8.Text)>255) then // Les valeurs négatives ou supérieures à 255 sont rejetées. begin Edit8.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit8.Text)>=0) and (StrToInt(Edit8.Text)<=255) then // Valeur comprise entre 0 et 255 => on envoie l'octet au PIC. begin Carac:='$B'+Edit8.Text+'|#'; // $= caractère d'entête. 8 = correspond à la sortie digitale J10. Edit8.Text= est compris entre 0 et 255. |# = caractère de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; end; //***************************************************************** //** FIN Sorties digitales J10 sur 1 octet compris entre 0 et 255 ** //***************************************************************** //************************************************************* //** Sorties digitales J11 sur 1 octet compris entre 0 et 255 ** //************************************************************* procedure TForm1.SpeedButton10Click(Sender: TObject); begin if Edit9.Text='' then // Si le champs est vide on ne fait rien. begin Edit9.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit9.Text)<0) or (StrToInt(Edit9.Text)>255) then // Les valeurs négatives ou supérieures à 255 sont rejetées. begin Edit9.Text:='0'; // Valeur par défaut Exit; end; if (StrToInt(Edit9.Text)>=0) and (StrToInt(Edit9.Text)<=255) then // Valeur comprise entre 0 et 255 => on envoie l'octet au PIC. begin Carac:='$C'+Edit9.Text+'|#'; // $= caractère d'entête. 8 = correspond à la sortie digitale J11. Edit9.Text= est compris entre 0 et 255. |# = caractère de fin de chaîne. Comport1.WriteStr(CARAC); // Transmission RS232. end; end; //***************************************************************** //** FIN Sorties digitales J11 sur 1 octet compris entre 0 et 255 ** //***************************************************************** //*************************************************************** //*************************************************************** //** FIN Procedures de transfert des données du PC vers le PIC ** //*************************************************************** //*************************************************************** //**************************************************************** //**************************************************************** //* Fonction dédiée au transfert des données du PIC vers le PC. ** //**************************************************************** //**************************************************************** procedure TForm1.ComDataPacket1Packet(Sender: TObject; const Str: String); // Procedure de réception par paquets au rythme de la liaison série. var Texte: String; Valeur : Integer; Erreur : Integer; Mille : Integer; Centaine : Integer; Dizaine : Integer; Unite : Integer; J1 : Integer; J2 : Integer; J5 : Integer; J6 : Integer; begin // La chaine de caractère reçue est toujours composée de 7 caractères. // - "A0000" à "!A0255#' pour la transmission de J1 compris entre 0 et 255. // - "B0000" à "!B0255#' pour la transmission de J2 compris entre 0 et 255. // - "C0000" à "!C4096#' pour la transmission de J5 compris entre 0 et 4096. // - "D0000" à "!D4096#' pour la transmission de J6 compris entre 0 et 4096. CARACIN:=Str; // Transfert de la chaine de caractères reçue STR vers CARACIN. //************************************************************************************************ //** Traitement de J1. "!A0000#" à "!A0255#' pour la transmission de J1 compris entre 0 et 255. ** //************************************************************************************************ IF CARACIN[2]='A' then begin Texte:=CARACIN[4]; // Recupération de la centaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Centaine:=Valeur; end else begin Centaine:=1; // Si le caractère reçu pour la centaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 1, de 127. end; Texte:=CARACIN[5]; // Recupération de la dizaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Dizaine:=Valeur; end else begin Dizaine:=1; // // Si le caractère reçu pour la dizaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 2, de 127. end; Texte:=CARACIN[6]; // Recupération de l'unité. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Unite:=Valeur; end else begin Unite:=7; // // Si le caractère reçu pour la l'unité n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 7, de 127. end; J1:=((Centaine*100)+(Dizaine*10)+Unite); // Reconstitution de la valeur reçue. Label8.Caption:=IntToStr(J1); // Affiche la valeur de l'octet. end; //**************************************************************************************************** //** FIN Traitement de J1. "!A0000#" à "!A0255#' pour la transmission de J1 compris entre 0 et 255. ** //**************************************************************************************************** //************************************************************************************************* //** Traitement de J2. "!B0000#" à "!!B0255#' pour la transmission de J2 compris entre 0 et 255. ** //************************************************************************************************* IF CARACIN[2]='B' then begin Texte:=CARACIN[4]; // Recupération de la centaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Centaine:=Valeur; end else begin Centaine:=1; // Si le caractère reçu pour la centaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 1, de 127. end; Texte:=CARACIN[5]; // Recupération de la dizaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Dizaine:=Valeur; end else begin Dizaine:=1; // // Si le caractère reçu pour la dizaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 2, de 127. end; Texte:=CARACIN[6]; // Recupération de l'unité. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Unite:=Valeur; end else begin Unite:=7; // // Si le caractère reçu pour la l'unité n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 7, de 127. end; J2:=((Centaine*100)+(Dizaine*10)+Unite); // Reconstitution de la valeur reçue. Label10.Caption:=IntToStr(J2); // Affiche la valeur de l'octet. end; //***************************************************************************************************** //** FIN Traitement de J2. "!B0000#" à "!!B0255#' pour la transmission de J2 compris entre 0 et 255. ** //***************************************************************************************************** //************************************************************************************************* //** Traitement de J5. "!C0000#" à "!!C4096#' pour la transmission de J5 compris entre 0 et 4096. ** //************************************************************************************************* IF CARACIN[2]='C' then begin Texte:=CARACIN[3]; // Recupération de Mille. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Mille:=Valeur; end else begin Mille:=1; // Si le caractère reçu pour les mille n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 0, de 0127. end; Texte:=CARACIN[4]; // Recupération de la centaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Centaine:=Valeur; end else begin Centaine:=1; // Si le caractère reçu pour la centaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 1, de 0127. end; Texte:=CARACIN[5]; // Recupération de la dizaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Dizaine:=Valeur; end else begin Dizaine:=1; // // Si le caractère reçu pour la dizaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 2, de 0127. end; Texte:=CARACIN[6]; // Recupération de l'unité. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Unite:=Valeur; end else begin Unite:=7; // // Si le caractère reçu pour la l'unité n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 7, de 0127. end; J5:=((Mille*1000)+(Centaine*100)+(Dizaine*10)+Unite); // Reconstitution de la valeur reçue. Label13.Caption:=IntToStr(J5); // Affiche la valeur. GAUGE1.Progress:=J5; // Affecte la valeur à la GAUGE1. end; //****************************************************************************************************** //** FIN Traitement de J5. "!C0000#" à "!!C4096#' pour la transmission de J5 compris entre 0 et 4096. ** //****************************************************************************************************** //************************************************************************************************** //** Traitement de J6. "!D0000#" à "!!D4096#' pour la transmission de J6 compris entre 0 et 4096. ** //************************************************************************************************** IF CARACIN[2]='D' then begin Texte:=CARACIN[3]; // Recupération de Mille. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Mille:=Valeur; end else begin Mille:=1; // Si le caractère reçu pour les mille n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 0, de 0127. end; Texte:=CARACIN[4]; // Recupération de la centaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Centaine:=Valeur; end else begin Centaine:=1; // Si le caractère reçu pour la centaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 1, de 0127. end; Texte:=CARACIN[5]; // Recupération de la dizaine. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Dizaine:=Valeur; end else begin Dizaine:=1; // // Si le caractère reçu pour la dizaine n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 2, de 0127. end; Texte:=CARACIN[6]; // Recupération de l'unité. Val(Texte,Valeur,Erreur); // Conversion chiffrée. if Erreur=0 then begin Unite:=Valeur; end else begin Unite:=7; // // Si le caractère reçu pour la l'unité n'est pas un chiffre (erreur transmission), on lui affecte par défaut la valeur 7, de 0127. end; J6:=((Mille*1000)+(Centaine*100)+(Dizaine*10)+Unite); // Reconstitution de la valeur reçue. Label14.Caption:=IntToStr(J6); // Affiche la valeur. GAUGE2.Progress:=J6; // Affecte la valeur à la GAUGE1. end; //****************************************************************************************************** //** FIN Traitement de J6. "!D0000#" à "!!D4096#' pour la transmission de J6 compris entre 0 et 4096. ** //****************************************************************************************************** //******************************************************************** //******************************************************************** //* FIN Fonction dédiée au transfert des données du PIC vers le PC. ** //******************************************************************** //******************************************************************** end; end.