(* ********************************************************** ********************************************************** ** ** ** ls-Prozess 1 ** ** ** ** Anpassung für AKTRONIC-Adapter ** ** ** ** Version 1.02 ** ** ** ** (Stand : 26.01.90) ** ** ** ** ** ** Autoren: Bruno Pollok, Bielefeld ** ** Wolfgang Weber, Bielefeld ** ** ** ** Copyright (C) 1988 Eva Latta-Weber, Bielefeld ** ** Copyright (C) 1990 ERGOS GmbH, Siegburg ** ********************************************************** ********************************************************** *) PACKET ls prozess 1 DEFINES run pdv, run pdv again, initialisiere interface, schalte alles aus, ausgeben, eingabe, warte, abbruch gewuenscht, tue nichts, trage kanaldaten ein, beende kanaldaten eintragen, hole spannungsbereich, letzte ausgabe, pruefe kanal, pruefe abbruch, teste interface, oeffne interface, schliesse interface, nicht belegt, digital aus, analog aus, digital ein, analog ein, kanalbreite, ganzzahl obergrenze, adapterart, (* ------------------------- *) kanalkoppler, interface kanal, oeffne interface direkt, schliesse interface direkt, initialisiere interface direkt, direkt ausgeben, direkt eingabe: (******** A N P A S S U N G A N A K T R O N I C - A D A P T E R ********) LET interface test code = ""240"", interface open code = ""176"", interface close code = ""176"", adresse 0 code = ""176"", interface write code = 64 , interface read code = 192 ; TEXT CONST adapterart :: "AKTRONIC-Adapter"; TEXT PROC interface anpassung (INT CONST kanalnummer, steuerungscode): IF es ist ein ausgabekanal THEN code (interface write code + device + faktor * steuerungscode) ELIF es ist ein eingabekanal THEN lesecode in abhaengigkeit von der taktzahl ELSE "" FI. es ist ein ausgabekanal: kanal [kanalnummer].betriebsart < 0. es ist ein eingabekanal: kanal [kanalnummer].betriebsart > 0. device: IF steckplatznummer < 3 THEN 16 ELSE 32 FI. faktor: IF steckplatznummer MOD 2 = 0 THEN 4 ELSE 1 FI. steckplatznummer: IF kanalnummer < 10 THEN 1 ELSE kanalnummer DIV 10 FI. lesecode in abhaengigkeit von der taktzahl: SELECT kanal [kanalnummer].taktzahl OF CASE 1: code fuer digital oder analog eingang CASE 2: code fuer kombi e1 CASE 3: code fuer kombi e2 OTHERWISE "" END SELECT. code fuer digital oder analog eingang: IF kanal [kanalnummer].betriebsart = analog ein THEN kanal [kanalnummer].taktzahl := 2; (* ad wandler muss hier *) lesecode + lesecode (* 2x gelesen werden! *) ELSE lesecode FI. lesecode : code (interface read code + device + faktor * steuerungscode). code fuer kombi e1: kanal [kanalnummer].taktzahl INCR 1; (* bei Analogport1 der Kombikarte *) adresse 0 code + (3 * lesecode). (* sind hier 3 Takte noetig ! *) code fuer kombi e2: kanal [kanalnummer].taktzahl DECR 1; (* hier nur 2 Takte noetig ! *) adresse 0 code + lesecode + lesecode. END PROC interface anpassung; (************ H A R D W A R E U N A B H Ä N G I G E R T E I L ************) LET max kanalanzahl = 49, initcode = 50, endcode = 51, alles aus code = 52, endezeichen = "q", abbruchzeichen = "h", esc = ""27""; INT CONST analog aus :: -2, (* Betriebsarten *) digital aus :: -1, nicht belegt :: 0, digital ein :: 1, analog ein :: 2, kanalbreite :: 8, ganzzahl obergrenze :: 2 ** kanalbreite, configuration error code :: -1, kanal besetzt code :: -3, interface error code :: -4, not init code :: -5; INT VAR interfacechannel :: 2, dummy; TEXT VAR meldung :: ""; BOOL VAR kanaldaten sind eingetragen :: FALSE, endezeichen gegeben :: FALSE, programm mit pdv gestartet :: FALSE, fehler zu melden :: FALSE; TASK VAR interface task :: niltask; DATASPACE VAR ds :: nilspace; TYPE KANAL = STRUCT (INT betriebsart, taktzahl, TEXT steuercode), SPANNUNG = STRUCT (REAL minimalwert, maximalwert); ROW max kanalanzahl INT VAR vorherige ausgabe; ROW max kanalanzahl KANAL VAR kanal; ROW max kanalanzahl SPANNUNG VAR spannung; ROW 5 TEXT CONST fehlermeldung :: ROW 5 TEXT : ("Interface ist noch nicht konfiguriert!", "Interface-Task ist besetzt!", "Interface-Kanal ist belegt!", "Interface meldet sich nicht!", "Interface kann nicht geöffnet werden!"); PROC run pdv: run pdv (last param) END PROC run pdv; PROC run pdv (TEXT CONST programmname): enable stop; last param (programmname); programm mit pdv gestartet := TRUE; teste interface; disable stop; run (programmname); IF is error THEN fehlerbehandlung ELSE melde programmende FI; schliesse interface; programm mit pdv gestartet := FALSE; enable stop; IF fehler zu melden THEN errorstop (meldung) FI END PROC run pdv; PROC run pdv again: enable stop; programm mit pdv gestartet := TRUE; teste interface; disable stop; run again; IF is error THEN fehlerbehandlung ELSE melde programmende FI; schliesse interface; programm mit pdv gestartet := FALSE; enable stop; IF fehler zu melden THEN errorstop (meldung) FI END PROC run pdv again; PROC melde programmende: page; menufootnote ("Programmende! Zum Weitermachen bitte irgendeine Taste tippen."); pause; schalte alles aus END PROC melde programmende; PROC initialisiere interface: enable stop; pruefe abbruch; IF programm mit pdv gestartet THEN schalte alles aus ELSE errorstop ("PDV-Programme müssen mit 'run pdv' gestartet werden!") FI END PROC initialisiere interface; PROC schalte alles aus: INT VAR k; FOR k FROM 1 UPTO max kanalanzahl REP vorherige ausgabe [k] := 0 PER; forget (ds); ds := nilspace; call (interface task, alles aus code, ds, dummy) END PROC schalte alles aus; PROC ausgeben (INT CONST kanalnummer, wert): merke wert; gib wert aus. merke wert: vorherige ausgabe [kanalnummer] := wert. gib wert aus: call (interface task, 256 * kanalnummer + wert, ds, dummy). END PROC ausgeben; INT PROC eingabe (INT CONST kanalnummer): INT VAR eingabewert; call (interface task, kanalnummer, ds, eingabewert); eingabewert END PROC eingabe; PROC warte (REAL CONST sekunden): TEXT VAR eingabe; pruefe abbruch; eingabe := incharety (int (sekunden * 10.0 + 0.5)); IF eingabe = esc THEN untersuche naechstes zeichen FI. untersuche naechstes zeichen: eingabe := incharety (30); IF eingabe = endezeichen THEN endezeichen gegeben := TRUE ELIF eingabe = abbruchzeichen THEN errorstop ("Programm-Abbruch durch <" + abbruchzeichen + ">!") FI. END PROC warte; PROC warte (INT CONST sekunden): TEXT VAR eingabe; pruefe abbruch; eingabe := incharety (sekunden * 10); IF eingabe = esc THEN untersuche naechstes zeichen FI. untersuche naechstes zeichen: eingabe := incharety (30); IF eingabe = endezeichen THEN endezeichen gegeben := TRUE ELIF eingabe = abbruchzeichen THEN errorstop ("Programm-Abbruch durch <" + abbruchzeichen + ">!") FI. END PROC warte; BOOL PROC abbruch gewuenscht: pruefe abbruch; BOOL VAR entscheidung :: endezeichen gegeben; endezeichen gegeben := FALSE; entscheidung END PROC abbruch gewuenscht; PROC tue nichts: pruefe abbruch END PROC tue nichts; PROC trage kanaldaten ein (INT CONST kanalnummer, ROW 2 REAL CONST spannungsbereich, ROW 3 INT CONST kanalparameter): spannung [kanalnummer].minimalwert := spannungsbereich [1]; spannung [kanalnummer].maximalwert := spannungsbereich [2]; kanal [kanalnummer].betriebsart := kanalparameter [1]; kanal [kanalnummer].taktzahl := kanalparameter [2]; kanal [kanalnummer].steuercode := interface anpassung (kanalnummer, kanalparameter [3]) END PROC trage kanaldaten ein; PROC beende kanaldaten eintragen: loesche interface task; begin (PROC kanal koppler, interface task); kanaldaten sind eingetragen := TRUE. loesche interface task: disable stop; end (interface task); IF is error THEN clear error FI; enable stop. END PROC beende kanaldaten eintragen; PROC hole spannungsbereich (INT CONST kanalnummer, REAL VAR u min, u max): u min := spannung [kanalnummer].minimalwert; u max := spannung [kanalnummer].maximalwert END PROC hole spannungsbereich; INT PROC letzte ausgabe (INT CONST kanalnummer): vorherige ausgabe [kanalnummer] END PROC letzte ausgabe; PROC pruefe kanal (INT CONST kanalnummer, gewuenschte betriebsart): pruefe abbruch; pruefe kanalnummer; pruefe betriebsart. pruefe kanalnummer: IF kanalnummer < 1 OR kanalnummer > max kanalanzahl THEN errorstop ("Kanalnummer " + text (kanalnummer) + " ist unzulaessig !") FI. pruefe betriebsart: IF gewuenschte betriebsart <> kanal [kanalnummer].betriebsart THEN errorstop ("An Kanal " + text (kanalnummer) + " keine " + wunsch + " moeglich!") FI. wunsch: IF gewuenschte betriebsart = analog aus THEN "Analog-Ausgabe" ELIF gewuenschte betriebsart = digital aus THEN "Digital-Ausgabe" ELIF gewuenschte betriebsart = digital ein THEN "Digital-Eingabe" ELIF gewuenschte betriebsart = analog ein THEN "Analog-Eingabe" ELSE "Ein- oder Ausgabe" FI. END PROC pruefe kanal; PROC pruefe abbruch: IF incharety = esc THEN pruefe weiter FI. pruefe weiter: TEXT CONST zeichen :: incharety (30); IF zeichen = endezeichen THEN endezeichen gegeben := TRUE ELIF zeichen = abbruchzeichen THEN errorstop ("Programm-Abbruch durch <" + abbruchzeichen + ">!") FI. END PROC pruefe abbruch; PROC oeffne interface (INT VAR status): enable stop; forget (ds); ds := nilspace; IF kanaldaten sind eingetragen THEN pingpong (interfacetask, initcode, ds, status) ELSE status := configuration error code FI; IF status > 0 THEN status DECR maxint FI; forget (ds); ds := nilspace END PROC oeffne interface; PROC schliesse interface: enable stop; forget (ds); ds := nilspace; pingpong (interface task, end code, ds, dummy); forget (ds); ds := nilspace END PROC schliesse interface; PROC teste interface: INT VAR test; oeffne interface (test); IF test < 0 THEN errorstop (fehlermeldung [min (5, abs (test))]) ELSE fehler zu melden := FALSE; endezeichen gegeben := FALSE FI END PROC teste interface; PROC fehlerbehandlung: meldung := errormessage; IF meldung <> "" THEN meldung CAT fehlerzeile; fehler zu melden := TRUE FI; clear error; initialisiere interface. fehlerzeile: IF errorline = 0 THEN "" ELSE " (bei Zeile " + text (errorline) + ")" FI. END PROC fehlerbehandlung; (******************** EIN-/AUSGABE AM INTERFACE-KANAL ********************) PROC kanalkoppler: IF name (myself) <> "-" THEN errorstop ("Unzulässiges Kommando!") ELSE warte auf anrufe FI. warte auf anrufe: TASK VAR absender; TEXT VAR dummy; INT VAR codenummer, antwort; disable stop; REP forget (ds); wait (ds, codenummer, absender); IF codenummer = initcode THEN kopple an interface kanal; IF interface ist betriebsbereit THEN bearbeite weitere auftraege ELSE gib negative rueckmeldung FI; gib kanal frei ELSE antwort := not init code; gib negative rueckmeldung FI PER. kopple an interface kanal: continue (interface channel); IF is error THEN clear error; antwort := kanal besetzt code ELSE oeffne interface direkt (antwort) FI. interface ist betriebsbereit: antwort = 0. gib negative rueckmeldung: send (absender, antwort, ds). gib kanal frei: break (quiet); send (absender, 0, ds, antwort); collect heap garbage. bearbeite weitere auftraege: REP call (absender, antwort, ds, codenummer); IF codenummer > 255 THEN sende wert an interface ELIF codenummer < 50 THEN hole wert von interface ELIF codenummer = alles aus code THEN initialisiere interface direkt FI UNTIL codenummer = endcode PER; IF is error THEN clear error FI; schliesse interface direkt. sende wert an interface: out (kanal [codenummer DIV 256].steuercode); out (code (codenummer)). hole wert von interface: out (kanal [codenummer].steuercode); SELECT kanal [codenummer].taktzahl OF CASE 1 : antwort := erstes zeichen CASE 2 : antwort := zweites zeichen CASE 3 : antwort := drittes zeichen OTHERWISE antwort := -1 END SELECT. erstes zeichen: code (incharety (1)). zweites zeichen: dummy := incharety (1); code (incharety (1)). drittes zeichen: dummy := incharety (1); dummy := incharety (1); code (incharety (1)). END PROC kanalkoppler; PROC interface kanal (INT CONST kanalnummer): enable stop; IF kanalnummer < 1 OR kanalnummer > 24 THEN errorstop ("Unzulaessige Kanalnummer") ELSE interface channel := kanalnummer FI END PROC interface kanal; INT PROC interface kanal: interface channel END PROC interface kanal; PROC oeffne interface direkt (INT VAR status): leere puffer; out (interface test code); IF antwort <> "" THEN status := 0; out (interface open code) ELSE status := interface error code FI. leere puffer: REP UNTIL incharety = "" PER. antwort: incharety (1). END PROC oeffne interface direkt; PROC schliesse interface direkt: out (interface close code) END PROC schliesse interface direkt; PROC initialisiere interface direkt: schalte alles aus. schalte alles aus: INT VAR kanalnummer, kanalbetriebsart; FOR kanalnummer FROM 1 UPTO max kanalanzahl REP kanalbetriebsart := kanal [kanalnummer].betriebsart; IF kanalbetriebsart = digital aus THEN direkt ausgeben (kanalnummer, 0) ELIF kanalbetriebsart = analog aus THEN direkt ausgeben (kanalnummer, gewandelte nullspannung) FI PER. gewandelte nullspannung: int(- real (ganzzahl obergrenze) * u min / (u max - u min) + 0.5). u max : spannung [kanalnummer].maximalwert. u min : spannung [kanalnummer].minimalwert. END PROC initialisiere interface direkt; PROC direkt ausgeben (INT CONST kanalnummer, wert): out (kanal [kanalnummer].steuercode); out (code (wert)) END PROC direkt ausgeben; INT PROC direkt eingabe (INT CONST kanalnummer): gib lesecode aus; erhaltene antwort. gib lesecode aus: out (kanal [kanalnummer].steuercode). erhaltene antwort: TEXT VAR dummy; SELECT kanal [kanalnummer].taktzahl OF CASE 1 : erstes zeichen CASE 2 : zweites zeichen CASE 3 : drittes zeichen OTHERWISE -1 END SELECT. erstes zeichen: code (incharety (1)). zweites zeichen: dummy := incharety (1); code (incharety (1)). drittes zeichen: dummy := incharety (1); dummy := incharety (1); code (incharety (1)). END PROC direkt eingabe; PROC initialisiere die kanaele: INT VAR kanalnummer; FOR kanalnummer FROM 1 UPTO max kanalanzahl REP trage kanaldaten ein (kanalnummer, keine spannung, leere karte); vorherige ausgabe [kanalnummer] := 0 PER. keine spannung: ROW 2 REAL : (0.0, 0.0). leere karte: ROW 3 INT : (nicht belegt, 0, 0). END PROC initialisiere die kanaele; initialisiere die kanaele; END PACKET ls prozess 1