************************************************************************** * * * X S E R v 1.56 date: 14/07/93 * * * * Par T.JAOUEN * * * * * * Gestion des COM1 à l'infini, en simultané, * * avec ou sans IRQ (partageable). * * * * Source écrit pour Turbo Pascal version 6.0 et suivantes * * * * (C) Copyright 1991-93, Thierry JAOUEN * * * * Thierry JAOUEN * * 2, avenue Winston Churchill * * 94220 Charenton le pont (FRANCE) * * * ************************************************************************** ************************************************************************** * * * Cette unité "XSER.TPU" est un SHAREWARE. * * * * Vous avez le droit de copier, d'utiliser et de distribuer cette unité, * * mais vous ne pouvez pas vous en servir dans un but commercial ! * * * * LE FICHIER SOURCE "XSER.PAS" N'EST PAS DANS LE DOMAINE PUBLIC. * * -------------------------------------------------------------- * * (exception pour la partie "interface" de ce fichier) * * * * Vous pouvez contacter l'auteur sur le réseau Français "Télétel 2", au: * * * * tél.: 3614 code service: TEASER boite aux lettres: Logicos * * ---- ------ ------- * * Vos remarques judicieuses seront les bienvenues. * * * ************************************************************************** +--------------------------------------------------------------------------+ | A T T E N T I O N | | | | Cette unité est faite pour les programmeurs qui n'ont pas le temps de | | programmer. | | | | Cette unité est faite pour des programmes qui doivent gérer plusieurs | | ports séries en même temps: les procédures ont été ecrites dans cet | | optique. | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | TURBO PASCAL 6.0, POURQUOI ? | | | | L'assembleur en ligne du Turbo Pascal 6 est fort pratique, et le | | programme est écrit à 99% avec ça. | | | | De plus, XSER est écrit en langage objet ! | | Mais pas de panique, j'en connais trop peu sur la programmation objet | | pour avoir fait quelque chose d'incompréensible ! | | | | Les exemples sont assez limpides. | | | | En gros, au lieu de faire : " TransmitChar(Handle,Char) " | | on écrira : " Handle.TransmitChar(Char) " | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | SOURCES D'INFORMATIONS | | | | 2 livres: | | - Clef pour PC et compatibles, édition PSI. (250 FF) | | | | Pour la description compléte (mais pas forcément claire) des | | registres du PC. | | Hélas, il manque encore des informations, et l'on echappe pas | | aux 150 pages totalement inutile...(mélanger l'apprentissage du | | Basic et du DOS avec le descriptif du matériel! c'est à mourrir de | | rire. non?) | | | | - La Bible PC, édition Micro Application. (340 FF) | | | | Pour la description de l'horloge AT, et des interruptions | | électroniques. | | Ce livre est clair, mais il manque encore des informations sur le | | matériel. | | | +--------------------------------------------------------------------------+ +----------------------------------------------------+ | | | Quelques procédures ... | | | | Elles ne vous seront utiles que si vous allez | | exploiter des ports séries sans IRQ. | | | +----------------------------------------------------+ +--------------------------------------------------------------------------+ | C h e c k U p | | | | Gére les ports séries n'ayant pas d'IRQ. | | Cette procédure ne sert que si vous avez des ports séries qui n'ont pas | | d'IRQ, c'est à dire, des ports séries qui ont été défini avec l'IRQ 0. | | | | Il convient d'appeller cette procédure le plus souvent possible sinon il | | y aura des pertes d'informations en réception, ou une certaine lenteur | | lors des émissions. | | | | Note: - Cette procedure effectue un contrôle pour interdir plus d'une | | éxécution simultanée de son code, car elle n'est pas réentrante | | et n'utilise pas les instructions machines CLI et STI. | | (Vous comprendrez mieux plus loin pourquoi tout cela). | | - Afin de vous evitez une programmation lourde, voir plus loin la | | procedure "InstCheckUp". | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | R a n C h e c k U p | | | | Idem que ci-dessus, sauf que tous les registres sont sauvegardés. | | ("Ran" pour "Random" (Aléatoire)). | | Spécialement conçu pour les programmes en assembleur. | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | I n t C h e c k U p | | | | Idem que ci-dessus, avec en plus un "IRET" à la fin. | | Spécialement conçu pour installer le "CheckUp" sur une interruption. | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | I n s t C h e c k U p | | | | Installe un "CheckUp" sur l'interruption 08h (IRQ0). | | | | Cette interruption est associée à un temporisateur (timer) qui existe | | sur tout compatible PC. Normalement, cette interruption s'execute | | 18.20648193 fois par seconde (1193180/65536), et elle sert à gerer | | l'heure, et tout ce qui en dépend. | | La procédure d'installation "InstCheckUp" ne perturbe pas le systéme. | | | | ATTENTION: Il peut y avoir quelques problémes si un programme résident | | modifie déjà la vitesse d'interruption. | | Vous vous en rendrez compte rapidement, car l'heure du | | systeme sera ralenti (dans le meilleur des cas !). | | | | La vitesse est: 18.20648193*2^Speed interruptions par seconde, avec | | Speed compris entre 0 et 15 | | | | Exemple: Speed=3 => 18.2*2^3 = 145,6 interruptions par seconde. C'est | | suffisant pour des communications à 1200 bauds | | (120 caracteres/seconde) | | | | Note: Cette fonction renvoi "FALSE" si l'installation a déjà eu lieu | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | K i l l C h e c k U p | | | | Désinstalle le "CheckUp" de l'interruption 08h (IRQ0) | | | | Note: - La procedure est ignorée s'il n'y a rien d'installé. | | - la désinstallation est relativement lente. | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | I n s t C h e c k U p A T | | | | Installe un "CheckUp" sur l'interruption 70h (IRQ8) d'un AT (minimun). | | | | Cette interruption est associée à une horloge temps réel propre à l'AT. | | Elle est trés peu utilisé, et elle est conçu pour ce genre de procedures | | qui doivent être appellées régulierement. | | | | ATTENTION: Tant que le "CheckUp" est actif, vous ne devez pas utiliser | | de fonctions modifiant cette horloge, notamment | | l'interruptions 15h, fonction 83h, et l'interruption 15h, | | fonction 86h. | | | | La vitesse est: 2^(Speed+1) interruptions par seconde, avec Speed compris| | entre 0 et 15 | | Exemple: Speed=6 => 2^(6+1) = 128 interruptions par seconde. C'est | | suffisant pour des communications à 1200 bauds (120 cps) | | | | Note: Cette fonction renvoi "FALSE" si l'horloge est active. | | (Normalement, elle ne doit pas l'être.) | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | K i l l C h e c k U p A T | | | | Désinstalle le "CheckUp" de l'interruption 70h (IRQ8) | | | | Note: La procedure est ignorée s'il n'y a rien d'installé. | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | R e m a r q u e s u r C h e c k U p | | | | Vous pouvez installer votre propre systéme d'interruption. Cela n'a pas | | d'importance tant qu'il permet d'éxécuter autant que nécessaire la | | procédure "CheckUp". (ou une dérivé comme "RanCheckUp" ou "IntCheckUp") | | | | La fréquence d'éxécution de la procedure "CheckUp" doit être suffisante | | pour gérer les ports séries les plus rapides. | | Si vous souhaitez utiliser un port série sans IRQ à 9600 bauds, il faudra| | éxécuter la procédure "CheckUp" plus de 960 fois par seconde. | | | | ATTENTION: Sur des PC lents, les fréquentes éxécutions du "CheckUp" | | peuvent ralentir le systéme. | | | | Rien ne s'oppose à l'installation simultanée du "CheckUp" sur l'IRQ 0 et | | l'IRQ 8 (Voir "InstCheckUp..."), si ce n'est la coohérence de votre | | programme... | | | +--------------------------------------------------------------------------+ +----------------------------------------------------+ | | | Quelques procédures ... | | | | Pour désactiver et activer le noyau XSer. | | | +----------------------------------------------------+ +--------------------------------------------------------------------------+ | K e e p X S e r | | | | Mémorise l'etat des communications, puis désactive le noyau de | | communication, en prenant soin de restorer le système dans un état | | proche de ce qu'il était à l'origine. | | (Les interruptions sont restorées, etc...) | | | | Note: - Le "CheckUp" est aussi désinstallé. | | (Rappel: La désinstalation du CheckUp Standard (pour XT) est | | relativement lente...) | | - N'utilisez plus aucune procedure de XSer, tant que vous n'avez | | pas installé denouveau le noyau avec "ResumeXSer" | | - Dés l'appel de "KeepXSer", d'autres procédures peuvent prendre | | le contrôle des ports séries, mais il faudra prendre soin de | | restituer leurs états avant de rendre le contrôle à XSer, avec | | la procédure "ResumeXSer". | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | R e s u m e X S e r | | | | Rétablit le contexte et l'état précédement mémorisés avec la procédure | | "KeepXSer". | | Les communications reprennent là où elles en étaient, avant l'appel de | | "KeepXSer". | | Sauf dans le cas de pertes de données en réceptions, à cause d'un arrêt | | du noyau de communication trop long, l'emploi de "KeepXSer" et | | "ResumeXSer" est totalement transparent: il n'est pas necessaire de vider| | les tampons ou d'initialiser les communications... | | | | Note: Il pourrait y avoir des problèmes de reprises des communications | | si l'état des ports séries a été trop modifiés. (Voir KeepXSer) | +--------------------------------------------------------------------------+ +-------------------------------------------+ | | | L ' o b j e t C o m X | | ------- | | | +-------------------------------------------+ +--------------------------------------------------------------------------+ | | |-- Function Init( RegUART : Word; | | NumIRQ : Byte; | | Baud : Word; | | Parameters : Byte; | | SizeIn, SizeOut : Word ) : Boolean ---------------------| | | | Ouvre la communication. | | | | RegUART : Adresse du registre de base du port série | | (UART signifie "Universal Asynchrone Recepter Transmiter")| | NumIRQ : Numéro de l'IRQ associé (0=>Aucune) | | Pour un XT, l'IRQ peut être comprise entre 1 et 7. | | Pour un AT, l'IRQ peut être comprise entre 1 et 15. | | (Voir plus loin, les informations les IRQs) | | Baud : Vitesse initiale (on peut la changer ultérieurement) | | Parameters : Paramétres de communications: parité, longueur donnée et | | nombre de bits "stop" | | SizeIn : Taille du tampon entrée (minimun:1 maximun:64512) | | SizeOut : Taille du tampon sortie (minimun:1 maximun:64512) | | | | Renvoi FALSE si RegUART=0, ou si NumIRQ incorrect, ou s'il n'y a pas | | assez de mémoire pour créer les tampons. (Si il y a un gestionnaire | | d'erreurs de tas) | | Sinon, fixe l'état du modem comme: DTR=ON RTS=ON OUT2=ON et BRK=OFF | | | | Exemple: If Com1.Init($3F8,4, { COM1 IRQ 4 } | | BAUD1200, | | EVENPARITY+DATA7BITS+STOP1BIT, | | 1024,1024) Then ... { C'est ouvert } | | Else { Erreur } | | | | Note: TOUJOURS APPELLER CETTE PROCEDURE EN PREMIER ! | | L'INITIALISATION D'UN OBJET EST OBLIGATOIRE ! | | | | Voir aussi: SetBaud, SetParam, SetModemCtrl | | | | -------------------- | | | | L e s I R Q s | | | | Toutes les IRQs sont possibles SAUF : | | IRQ 0 : Si vous spécifiez cette IRQ, alors on considére qu'il n'y a | | aucune IRQ pour ce port série. Cela implique que vous devrez | | suppléer à ce manque par des appels fréquents à la procédure | | "CheckUp". (Voir plus haut) | | | | Note: Toutes les IRQ ne sont pas libres: ainsi, l'IRQ 1 ne l'est jamais! | | De plus vous êtes limité par les possibilités de vos propres | | cartes séries: elles sont souvent bridées aux IRQ 3 ou 4. | | Si vous avez un XT, vous n'avez que 8 IRQs (0 à 7), alors que sur | | un AT, vous avez jusqu'à 16 IRQs (0 à 15). | | | | Le partage des IRQs: | | - Une IRQ est partageable entre plusieurs périphériques SI ils | | occupent le même slot: C'est le cas des cartes ayant au moins 2 | | sorties séries. | | Note: Les PS/2 font exception. | | | | - Il est possible d'utiliser une IRQ même si celle-ci est déjà | | utilisé par un "driver". C'est le cas pour les "drivers" de souris | | occupant une sortie série. | | Dans le cas de la souris par exemple, elle continuera à | | fonctionner normalement. | | (Toutefois, quelques problémes ne sont pas exclus en fonction | | de la version du "driver"...) | | | |--------------------------------------------------------------------------| | | |-- Procedure Done --------------------------------------------------------| | | | Ferme la communication | | | | Note: TOUJOURS APPELLER CETTE PROCEDURE AVANT D'ABANDONNER L'OBJET ! | | ENSUITE, IL NE FAUT PLUS UTILISER L'OBJET, SAUF POUR L'INI- | | TIALISER DENOUVEAU. | | | |--------------------------------------------------------------------------| | | |-- Procedure SetBaud( Baud : Word ) --------------------------------------| | | | Fixe la vitesse de communication (Baud). | | | |--------------------------------------------------------------------------| | | |-- Procedure SetParam( Parameters : Byte ) -------------------------------| | | | Fixe les parametres de communications: parités, longueur donnée, et | | nombre de bits "stop". | | | |--------------------------------------------------------------------------| | | |-- Procedure SetBreak( BrkOn : Boolean ) ---------------------------------| | | | Active ou desactive l'emission du signal "Break". | | | |--------------------------------------------------------------------------| | | |-- Procedure SetLoop( LoopOn : Boolean ) ---------------------------------| | | | Active ou desactive le bouclage de l'UART sur lui-même. | | | |--------------------------------------------------------------------------| | | |-- Procedure SetModemCtrl( Param : Byte ) --------------------------------| | | | Fixe le registre de contrôle du modem | | | |--------------------------------------------------------------------------| | | |-- Function GetModemCtrl : Byte ------------------------------------------| | | | Renvoi le contenu du registre de contrôle | | | |--------------------------------------------------------------------------| | | |-- Function LineError : Boolean -----------------------------------------| | | | Renvoi TRUE si une erreur s'est produite sur la ligne | | (Repasse à FALSE aprés la lecture de l'etat de la ligne) | | | |--------------------------------------------------------------------------| | | |-- Function GetLineState : Byte ------------------------------------------| | | | Renvoi l'état de la ligne. | | | |--------------------------------------------------------------------------| | | |-- Function NewModemState : Boolean --------------------------------------| | | | Renvoi TRUE si l'etat du modem a changé depuis la derniére lecture de | | l'etat du modem. | | | |--------------------------------------------------------------------------| | | |-- Function GetModemState : Byte -----------------------------------------| | | | Renvoi l'état du modem. | | | |--------------------------------------------------------------------------| | | |-- Function ReceiveCount : Word ------------------------------------------| | | | Renvoi le nombre de données dans le tampon entrée, et restant à lire. | | | |--------------------------------------------------------------------------| | | |-- Function ReceiveAvail : Word ------------------------------------------| | | | Renvoi la place libre dans le tampon entrée. | | | |--------------------------------------------------------------------------| | | |-- Function ReceiveChar( Var C : Char ) : Boolean ------------------------| | | | Renvoi FALSE si aucun caractere n'est disponible. | | Sinon, renvoi TRUE et le premier caractere en attente. | | | |--------------------------------------------------------------------------| | | |-- Function Receive( Var p; LgMax : Word ) : Word ------------------------| | | | Renvoi une ou plusieurs données en attente. | | | | p : Variable où écrire les données. | | LgMax : Nombre maximun de données à extraire. | | | | Renvoi le nombre de données extraites. | | | |--------------------------------------------------------------------------| | | |-- Procedure ReceiveClear ------------------------------------------------| | | | Supprime les données du tampon entrée. | | | |--------------------------------------------------------------------------| | | |-- Function TransmitCount : Word -----------------------------------------| | | | Renvoi le nombre de données encore présente dans le tampon sortie. | | | |--------------------------------------------------------------------------| | | |-- Function TransmitAvail : Word -----------------------------------------| | | | Renvoi la place libre dans le tampon sortie. | | | |--------------------------------------------------------------------------| | | |-- Function TransmitChar( C : Char ) : Boolean ---------------------------| | | | Envoi un caractére. | | | | Renvoi FALSE s'il y a plus de place sur le buffer sortie, ou si la | | sortie n'est pas prête. | | | |--------------------------------------------------------------------------| | | |-- Function Transmit( Var p; Lg : Word ) : Word --------------------------| | | | Envoi une ou plusieurs données. | | | | p : Variable où sont écrites les données à envoyer. | | LgMax : Nombre de données à envoyer. | | | | Renvoi le nombre de données effectivement envoyé. | | (En fait, le nombre de données placées dans le tampon sortie) | | Tout ne peut être transmis si le tampon sortie est plein, ou si la | | la sortie n'est pas prête. | | | | ATTENTION: Des données dans le tampon ne sont pas forcément en cours | | d'émission! Le cas se présente lorsque la sortie n'est pas | | prête et que donc la premiere donnée ne peut être ecrite! | | Dans ce cas, la procedure renvoi toujours qu'il y au moins | | UNE donnée qui n'a pus être envoyée, ceci afin de forcer | | une nouvelle tentative. | | Exemple: COM2.Transmit(Tas,32) | | Si la sortie n'est pas prête, la valeur "31" sera | | renvoyé, indiquant qu'une donnée n'a pu être | | envoyée. | | Toutefois, ce cas ne se présente que pour les sorties | | sans IRQ, ou avec des vitesses de transmissions trés lentes.| | | |--------------------------------------------------------------------------| | | |-- Procedure TransmitClear -----------------------------------------------| | | | Supprime les données du tampon sortie. | | | +--------------------------------------------------------------------------+ | | | A T T E N T I O N | | | | Les objets "ComX" doivent TOUJOURS rester à la même place en mémoire, | | à partir du moment où ils ont été initialisés. | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | | | R e m a r q u e s | | | | - Toutes les procédures ont été écrites en assembleur. | | | | - Tout a été fait pour minimiser le temps d'éxécution des procedures, | | notamment les procedures de réceptions ou d'émissions de données. | | Ceci s'explique par le fait que cette unité a été developpée pour | | gérer beaucoup de ports series. Il n'est pas concevable, par | | exemple, qu'un port qui a une vitesse de transmission réduite, ou | | qui a le tampon de sortie souvent plein, occupe tout le temps du | | CPU à faire une boucle d'attente !! | | | | - Lors de l'installation, ou la suppression d'un "CheckUp", le travail | | est fait proprement: Les vecteurs d'interruptions et les registres | | importants sont sauvegardées puis restorées. | | | | - Un mécanisme de sortie a été prévu pour supprimer et rétablir tous ce | | qui devraient l'être: Il ne sert que si des ports n'ont pas été | | fermés, ou si le "CheckUp" n'a pas été désinstallé. | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | | | H i s t o r i q u e | | | | XSER 1.2 | | -------- | | Premiére version dans le domaine public. | | | | XSER 1.3 | | -------- | | Correction d'un bogue dans "InstCheckUpAT". | | | | XSER 1.3B | | --------- | | - un bogue dans "ComX.Done" a été supprimé. | | - il y aurait un bogue au niveau du partage des IRQ. (à verifier) | | - Avec "InstCheckUpAT", la méthode de calcule de la fréquence donnée | | dans la doc etait fausse ! (et aussi dans les exemples) | | La fréquence d'interruption doit se calculer ainsi: 2^(Speed+1). | | | | XSER 1.4 | | -------- | | Optimisation pure et simple. | | | | XSER 1.5 | | -------- | | - Modification de la gestion des cartes multi-séries. | | - Ajout des procedures "KeepXSer" et "ResumeXSer". | | | | XSER 1.51 | | --------- | | Correction d'un bogue lors de l'utilisation de l'IRQ 2. | | | | XSER 1.55 | | --------- | | Modification sur l'identification de l'IRQ en cours (voir source...) | | | | XSER 1.56 | | --------- | | Correction sur le contrôle de l'horloge RTC (sur AT, IRQ 8) à la suite | | de problémes survenues sur des micros 99.99% compatibles... | | | +--------------------------------------------------------------------------+