home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / BBS / 515DISK2.ZIP / DOC515.ZIP / WA8V21B.DOC < prev    next >
Text File  |  1988-01-20  |  21KB  |  494 lines

  1.  
  2.                                                "NORD><LINK schlaegt wieder zu"
  3.  
  4.  
  5. Betrifft: Neue "alte" Hostmode-Firmware fuer den TNC2.
  6.  
  7. Nachdem die Weihnachtsferien und der Jahreswechsel fuer ein ergiebiges Stueck
  8. Arbeit auf dem Gebiet der PR-Software genutzt wurden, sind erste Ergebnisse
  9. dabei herausgekommen, die vielleicht auch fuer andere interessant sind :
  10.  
  11. Die WA8DED-Firmware 2.1 fuer den TNC2 ist (genau wie NET/ROM) bis auf wenige
  12. zeitkritische Routinen komplett in C geschrieben. Der komplette Source
  13. einschliesslich der wenigen Assemblerteile konnte nun vollstaendig
  14. rekonstruiert  u n d  auch komplett verifiziert werden (Uebereinstimmung bis
  15. auf das letzte Bit nach Neuuebersetzen/Linken).
  16.  
  17. Beim Durchgucken des Sources konnten durch einfache Aenderungen einige Fehler
  18. beseitigt und die Antwortgeschwindigkeit im Hostmode sowie die allgemeine
  19. interne Verarbeitungsgeschwindigkeit drastisch erhoeht werden. Da allgemeines
  20. Interesse an der genaueren Erklaerung der Aenderungen besteht, werde ich diese
  21. spaeter ausfuehrlich in weiteren Files erlaeutern.
  22.  
  23.  
  24. Im einzelnen wurde folgendes geaendert :
  25.  
  26. 1. Die Firmware wurde wie die Originalversion mit einem Optimizer bearbeitet,
  27.    im Gegensatz zum Original aber wurden nur auch die Geschwindigkeit
  28.    erhoehende Optimierungen ausgefuehrt, spezielle die Geschwindigkeit
  29.    stark herabsetzende Laengenoptimierungen wurden weggelassen (die Firmware
  30.    passt trotzdem noch komplett in 32kB - im Gegensatz zu NET/ROM, wo man
  31.    die speziellen Laengenoptimierungen unbedingt machen muss, um es in 32kB
  32.    unterzubringen). Durch das Weglassen der stark verlangsamenden
  33.    Optimierungen konnte die interne Verarbeitungsgeschwindigkeit um einiges
  34.    erhoeht werden.
  35.  
  36. 2. Nach einer Aussendung wird das Abschalten der PTT um "ein Byte" verzoegert
  37.    (bei 1200 Baud sind das 6,7ms). Dies loest das Problem der zu fruehen
  38.    PTT-Abschaltung, die sich bei einigen Konfigurationen bemerkbar gemacht
  39.    hat (Abschaltzeit kann ggf. auch noch weiter verlaengert werden).
  40.  
  41. 3. Das L-Kommando im Hostmode gibt auch beim Kaltstart mit nicht
  42.    initialisiertem RAM keine "Hausnummern" beim ersten Ansprechen mehr aus.
  43.  
  44. 4. Ein Fehler im Hostmode-Kommando G wurde beseitigt. In der Originalversion
  45.    wurde nach Ausgabe eines Kopfes eines Monitor-UI/I-Paketes grundsaetzlich
  46.    der Rumpf (die Daten) beim naechsten G/G0/G1 fuer Kanal 0 ausgegeben,
  47.    obwohl laut Beschreibung bei G1 nur Statusmeldungen kommen duerfen.
  48.    Dies fuehrte bei einigen Programmen fuer den TNC1-Hostmode (z.B. TINA) zu
  49.    Schwierigkeiten. Dieser Fehler ist nun beseitigt, das G-Kommando im
  50.    Hostmode ist nun vollstaendig TNC1-kompatibel.
  51.  
  52. 5. Mit "ESC @K" versetzt man den TNC in den KISS-Mode. KISS wurde aus dem
  53.    bekannten TCP/IP-Paket uebernommen. Die Parameter der Hostmode-Firmware
  54.    werden  n i c h t  veraendert (KISS benutzt eigene andere Parameter und
  55.    ueberschreibt nicht die Firmware-Variablen), nach einem Reset sind alle
  56.    Parameter unveraendert (KISS wurde in ein linkfaehiges Codesegement
  57.    umgeschrieben).
  58.  
  59. 6. Die Auswertung von Hostmodekommandos wurde geringfuegig geaendert,
  60.    hierdurch wurde die Antwortgeschwindigkeit im Hostmode drastisch um
  61.    ein Mehrfaches erhoeht. Der TNC2 antwortet nun aehnlich schnell wie
  62.    der TNC1, lange Datenpakete in den TNC werden nun ohne Verzoegerung
  63.    angenommen.
  64.  
  65.  
  66. Weiterhin besteht auch die Moeglichkeit, Versionen mit mehr als 4 Kanaelen
  67. zu erstellen fuer spezielle Mailboxen. Durch diese Moeglichkeit ist die
  68. DK0MAV-Mailbox neuerdings in der Lage, fuer Store-and-Forward mit
  69. anderen Mailboxen grundsaetzlich (auch waehrend laufendem S+F-Versuch) nicht
  70. busy zu sein. Dies kann bei schlechten Strecken und Betrieb mit W0RLI/WA7MBL
  71. aehnlichen Mailboxen, die nur stuendlich S+F initiieren koennen und nach einem
  72. busy erst wieder eine Stunde spaeter neu probieren koennen, wichtig sein.
  73.  
  74. Ich werde die "neue" alte Firmware einigen bekannten OM's zum Testen geben.
  75. Stellen sich keine schwerwiegenden Fehler heraus, wird die Firmware sofort
  76. freigegeben, dann kann sie sich durch Weitergeben von OM zu OM sehr schnell
  77. verteilen. Das geht sicherlich schneller, als wenn sich alle Interessenten bei
  78. mir persoenlich melden. Die aktuelle Version hat die Versionsnummer "2.1b".
  79.  
  80. 73, Michael, DC4OX @ DK0MAV.
  81.  
  82.  
  83.  
  84.                                                 ... Einsichten und Ansichten 1
  85.  
  86.  
  87. Wie versprochen, will ich an dieser Stelle etwas ausfuehrlicher die
  88. Hintergruende einiger Aenderungen an der Hostmode-Software fuer den TNC-2
  89. von WA8DED kundtun. Ich hoffe damit dann auf einmal etliche an mich
  90. herangetragende Fragen erschoepfend zu beantworten.
  91.  
  92. Zunaechst eine Vorbemerkung. Eigentlich gehoert es sich, dass, wenn man Fehler
  93. an einer Software entdeckt hat oder Verbesserungen vorgenommen hat, diese
  94. zuallererst dem Entwickler dieser Software zukommen laesst, bevor man die
  95. Dinge in aller Oeffentlichkeit "breittritt". Leider hat sich WA8DED jeglicher
  96. Zusammenarbeit verschlossen, die seine exzellenten Programme betreffen.
  97. Wir hatten direkten Kontakt mit WA8DED - auf Sourcecodefehlerangaben fuer
  98. NET/ROM in einem Brief reagierte er aber relativ merkwuerdig. "Die Fehler
  99. seien ja gar keine Fehler", oder "Deutsch koenne er nicht lesen". Dabei haben
  100. wir natuerlich jegliche Briefe in Englisch abgefasst und die beschriebenen
  101. allerdings nicht uebermaessig gravierenden Fehler (teilweise sehr versteckt,
  102. von aussen nahezu nicht feststellbar) wurden alle in  s e i n e n  neueren
  103. Versionen behoben ...
  104.  
  105. Soweit dazu. Nun zu den Aenderungen. NET/ROM und auch die TNC-2-Firmware sind
  106. beide fast ausschliesslich in C geschrieben. Uebersetztes C beansprucht mehr
  107. Platz als reiner Assemblercode und so passt das normal uebersetzte NET/ROM
  108. auf gar keinen Fall mehr in ein 32kB-Eprom. Es gibt zu dem benutzten Compiler
  109. einen Assembly-Code-Optimizer, dieser optimiert aber nur JP... in JR...
  110. ueberall wo es moeglich ist. Das bringt so ca. an 1 kB an Codeersparnis
  111. insgesamt, das reicht fuer NET/ROM aber bei weitem noch nicht. Es werden
  112. weitere Optimierungen vorgenommen, unter einigen anderen auch einige, die
  113. die Geschwindigkeit ziemlich herabsetzen. All diese Optimierungen wurden
  114. auch auf die Hostmode-Firmware angewandt - das aber, obwohl die Firmware
  115. auch komplett ohne die verlangsamenden Optimierungen in ein 32k-Eprom gepasst
  116. haette.
  117.  
  118.  
  119. Fuer die Insider beschreibe ich diese Optimierungen im folgenden einmal
  120. genauer :
  121.  
  122.  
  123.  
  124. Zunaechst werden 4 der am haeufigsten benutzten Runtime-Modul-Funktionen
  125. durch Z80 RST-Befehle ersetzt. Ein CALL-Befehl braucht 3 Byte,
  126. ein RST nur ein Byte, pro Aufruf einer dieser 4 Routinen werden also 2
  127. Byte gespart. Ein CALL braucht beim Z80 17 Maschinenzyklen, ein RST
  128. braucht 11 Zyklen. Allerdings sitzt an den RST-Vektoren je ein JP an die
  129. jeweilige Routine mit 10 Zyklen. Jeder Aufruf ueber einen RST braucht also
  130. 4 Zyklen laenger - das ist im Vergleich zu den 17 des CALL sicherlich
  131. nicht so viel, dass es sehr ins Gewicht fallen wuerde.
  132.  
  133.  
  134.  
  135. Die naechsten Laengenoptimierungen sehen in punkto Geschwindigkeit schon
  136. anders aus. Wenn eine Funktion lokale nicht-static Variable braucht oder
  137. der Funktion Parameter uebergeben werden, so wird im Maschinencode auf
  138. diese Variablen/Parameter indiziert ueber das IX-Register zugegriffen. Der
  139. Compiler ruft am Anfang der Funktion eine Library-Routine auf, die das
  140. IX-Register ("Stackframepointer") entsprechend setzt. Der Wert des
  141. BC-Registers erhaelt denselben Wert. Ein Zugriff auf 16 Bit sieht dann
  142. folgendermassen aus :
  143.  
  144.  
  145. Lesen :                 Schreiben :             Loeschen :
  146.  
  147. LD  L,(IX+n)     19     LD  (IX+n),L     19     LD  (IX+n),0     19
  148. LD  H,(IX+n+1)   19     LD  (IX+n+1),H   19     LD  (IX+n+1),0   19
  149. -------------------     -------------------     -------------------
  150.                  38                      38                      38
  151.  
  152.  
  153. Jeder solcher Zugriff ist 6 Byte lang und braucht 38 Zyklen. WA8DED benutzt
  154. nun eine spezielle Library-Routine, so dass die meisten dieser Zugriffe
  155. durch ein RST (ueber den dann diese Routine aufgerufen wird) mit einem
  156. 1-Byte-Parameter ersetzt werden koennen. Die obersten beiden Bit dieses
  157. Bytes geben an, ob es ein Lesen/Schreiben/16-Bit-Loeschen/8-Bit-Loeschen
  158. ist, die restlichen 6 Bit geben den Offset auf IX (bzw. BC) an. Alle Zugriffe
  159. mit einem Offset < 64 (also die meisten) koennen mit diesem RST optimiert
  160. werden, bei jedem Zugriff werden somit 4 Byte gespart. Da Parameter und lokale
  161. Variablen ueberaus haeufig bei nahezu jedem C-Statement auftreten (16 Bit
  162. lang sind alle Pointer, integer, unsigned), ist die erreichte Ersparnis ganz
  163. enorm. Aber wie sieht es mit der Laufzeit aus ?
  164.  
  165. Dazu einen Codeauszug, wie im einzelnen bei einem solchen RST der Ablauf
  166. ist, im Beispiel das Setzen einer Variable :
  167.  
  168.  
  169.        RST   38               11
  170.        DB    n or 01000000b
  171.  
  172.            .
  173.            .
  174.  
  175. RST38: JP    LOCAL            10
  176.  
  177.            .
  178.            .
  179.  
  180. LOCAL: EX    (SP),HL          19
  181.        LD    A,(HL)            7
  182.        INC   HL                6
  183.        EX    (SP),HL          19
  184.        BIT   7,A               8
  185.        JR    NZ,...            7
  186.        BIT   6,A               8
  187.        JR    NZ,LOC1          12
  188.  
  189.            .
  190.            .
  191.  
  192. LOC1:  PUSH  DE               11
  193.        EX    DE,HL             4
  194.        AND   00111111b         7
  195.        LD    L,A               4
  196.        LD    H,0               7
  197.        ADD   HL,BC            11
  198.        LD    (HL),E            7
  199.        INC   HL                6
  200.        LD    (HL),D            7
  201.        EX    DE,HL             4
  202.        POP   DE               10
  203.        RET                    10
  204. --------------------------------
  205.                              195
  206.  
  207.  
  208. 195 - 38 = 157 Zyklen mehr bei jedem lokalen Zugriff (!)
  209.  
  210. Bei den anderen Moeglichkeiten dieser Optimierung werden gebraucht :
  211.  
  212.    LD  HL,(IX+n)      158
  213.    LD  (IX+n),0000h   193
  214.    LD  (IX+n),00h     182
  215.  
  216. Anders ausgedrueckt :  Jeder so laengenoptimierte Zugriff braucht
  217.                        ca. 5-mal solange wie nicht optimiert.
  218.  
  219. Das macht dann doch schon einiges aus.
  220.  
  221.  
  222.  
  223. Eine weitere sehr verkuerzende, aber verlangsamende Optimierung betrifft
  224. Zugriffe in Strukturen ueber Pointer. Der benutzte Compiler laed den
  225. Pointer in HL, laed den Offset in die Struktur in DE und addiert DE auf HL :
  226.  
  227.  
  228.        LD    DE,n             10
  229.        ADD   HL,DE            11
  230. --------------------------------
  231.                               21
  232.  
  233.  
  234. Der Zugriff auf diese Art wird immer bei Offsets > 8 benutzt, wie schon bei
  235. den Zugriffen auf einfache Variable benutzt WA8DED einen RST mit einem Byte
  236. Parameter. Der Parameter gibt den Offset an, bis 255 ist diese Art der
  237. Optimierung also moeglich (da keine so grossen Strukturen im Source benutzt
  238. werden also immer) :
  239.  
  240.  
  241.        RST   30               11
  242.        db    n
  243.  
  244. RST30: JP    ADDHL            10
  245.  
  246. ADDHL: EX    (SP),HL          19
  247.        LD    E,(HL)            7
  248.        LD    D,0               7
  249.        INC   HL                6
  250.        EX    (SP),HL          19
  251.        ADD   HL,DE            11
  252.        RET                    10
  253. --------------------------------
  254.                              100
  255.  
  256.  
  257. Hier werden bei jedem solchen Zugriff 2 Byte gespart, aber der optimierte
  258. Zugriff ist wiederum ca. 5-mal langsamer.
  259.  
  260.  
  261.  
  262. Es werden auch noch einige andere Optimierungen gemacht und spezielle Library-
  263. Routinen benutzt, alles in allem erhaelt man eine Codeersparnis von ueber
  264. einem Drittel (!) - das ist dann doch schon eine ganze Menge. Ein NET/ROM
  265. von ca. 31kB waere also ohne Optimierungen ca. 45kB lang (!!!).
  266.  
  267. Anderseits geht die interne Verarbeitungsgeschwindigkeit merklich herunter
  268. bei den Optimierungen - es ist also wenig verstaendlich, wenn solche
  269. Optimierungen auch dann gemacht werden (Hostmode-Firmware), wenn sie gar nicht
  270. erforderlich sind, weil das Programm auch ohne ins EPROM passt.
  271.  
  272. Wie die Intentionen der Entwickler auch gewesen sein moegen - ich habe nach
  273. dem Motto "Die guten ins Toepfchen, die schlechten auf den Muell" nur die
  274. Optimierungen ausgefuehrt, die auch gleichzeitig eine Verschnellerung
  275. bedeuten. Somit wurde immer noch genug gespart, dass der KISS-Code des
  276. TCP/IP-Paketes mit in das EPROM passte.
  277.  
  278. 73, Michael, DC4OX @ DK0MAV.
  279.  
  280.  
  281.  
  282.  
  283.                                                 ... Einsichten und Ansichten 2
  284.  
  285.  
  286. Bisher habe ich nur (nicht) gemachte Laengenoptimierungen besprochen, aber
  287. noch keine von mir vorgenommenen Aenderungen am Source.
  288.  
  289. Diese will ich jetzt erklaeren :
  290.  
  291.  
  292.  
  293. 1. L-Kommando bei nicht initialisiertem RAM im Hostmode
  294.  
  295.    Im Gegensatz zum Terminalmode konnte es im Hostmode passieren, dass
  296.    Parameter aus einem Linkblock ausgegeben wurden, die noch nicht
  297.    initialisiert waren. Durch Aufruf einer (vorhandenen) weiteren Routine
  298.    waehrend der Initialisierung nach Kaltstart/Reset werden jetzt alle
  299.    in Frage kommenden Parameter initialisiert.
  300.  
  301.  
  302.  
  303. 2. G1 im Hostmode ohne Fehler
  304.  
  305.    Auszug aus dem Original :
  306.  
  307.    <G-Parameter holen>       /* G: par = MBALL, G0: MBINFO, G1: MBSTATUS    */
  308.    if (!actch)               /* wenn actch 0, d.h. wenn Monitorkanal, und   */
  309.      if (mifmbp != NULL)     /* wenn noch Frame am Monitorrestausgabezeiger */
  310.        {                     /* haengt, dann gebe Rest dieses Frames aus    */
  311.          <gebe Monitorframerumpf aus>
  312.        }
  313.      else ...
  314.  
  315.    Wie aus dem Source ersichtlich, falls noch ein Monitorframerumpf
  316.    (I/UI-Paket) auf Abholung wartet, wird dieser ausgegeben, wenn das naechste
  317.    G-Kommando auf Kanal 0 ausgefuehrt wird. Und zwar auch dann, wenn mit einem
  318.    G1 ausschliesslich ein Status abgeholt werden soll.
  319.  
  320.    Durch die simple Aenderung
  321.  
  322.    "if (mifmbp != NULL)"   ->   "if (par != MBSTATUS && mifmbp != NULL)"
  323.  
  324.    wurde diese "Unschoenheit" korrigiert.
  325.  
  326.  
  327.  
  328. 3. ESC @K -> KISS
  329.  
  330.    Der aus dem TCP/IP-Paket stammende KISS-Source wurde so umgeschrieben,
  331.    dass er uebersetzt zum Firmware-Objekt gelinkt werden konnte :
  332.  
  333.      - cseg-Anpassung
  334.      - Interrupt-Vektor im RAM, dadurch frei linkbar
  335.      - Freispeicher so, dass keine Firmware-Variablen betroffen werden
  336.  
  337.    Der Aufruf von KISS erfolgt mit "ESC @K", oder auch ohne ESC aus dem
  338.    Hostmode heraus. Durch einen Reset (z.B. Power-On) gelangt man wieder
  339.    zur Hostmode-Firmware. Hostmode-Firmware-Variable werden durch einen
  340.    KISS-Lauf nicht veraendert.
  341.  
  342.  
  343.  
  344. 4. PTT-Abfall verzoegert
  345.  
  346.    Die Feststellung, wann ein Paket komplett einschliesslich CRC und Flag
  347.    die SIO verlassen hat, geschieht mit einem "Trick". Sowohl Z80 SIO als
  348.    auch Z8530SCC haben weder ein Flag noch einen speziellen Interrupt, der
  349.    anzeigt, wann ein Frame einschliesslich CRC und einem Flag den Baustein
  350.    komplett verlassen hat (Wie ein Entwickler des SCC mal auf Anfrage
  351.    mitteilte, wurde das nie implementiert, weil an eine Anwendung bei
  352.    Halbduplex-Nicht-Standleitungen niemals jemand gedacht hat ... ).
  353.    Wird nun bei PR zu frueh die PTT abgeschaltet, dann kann es je nach
  354.    Schnelligkeit der PTT-Umschaltung (oder immer, falls das Modem
  355.    mitabgeschaltet wird) dazu kommen, dass das letzte Frame einer Aussendung
  356.    nicht korrekt abgeschlossen wird. Fuer die Feststellung des richtigen
  357.    Zeitpunktes der Abschaltung (des Zeitpunktes, zu dem Frame + CRC + Flag
  358.    den Baustein komplett verlassen haben), gibt es mehrere Moeglichkeiten.
  359.    Einmal kann man eine feste "TailTime" verzoegern, nachdem die SIO einem
  360.    mitgeteilt hat, dass das Frame zuende ist (mitten im CRC). Diese TailTime
  361.    ist aber hochgradig von der Baudrate abhaengig. Das andere Verfahren ist,
  362.    dass man einfach ein "Dummyframe" beginnt, und in den jeweiligen TX-
  363.    Interrupts einen Zaehler herunterzaehlt, bis man sicher ist, dass das
  364.    vorherige (Nutz-)Frame komplett heraus ist. Dann wird die PTT
  365.    abgeschaltet und das Dummy-Frame mit Abort beendet. Die letztere Methode
  366.    hat auch WA8DED verwendet - aber er zaehlt dem Anschein nach ein Byte
  367.    zuwenig herunter, so dass sich daraus ein ziemlich haariger Millisekunden-
  368.    Grenzfall ergibt. Ich habe das so geaendert, dass nun ein Byte laenger
  369.    gewartet wird - allerdings muessen genaue Tests (die ich hier nicht
  370.    durchfuehren kann, meine PTT war auch vorher schon langsam genug) erst
  371.    noch zeigen, obs das denn auch wirklich komplett brachte.
  372.  
  373.  
  374.  
  375. 5. Drastische Reduzierung der Hostmode-Antwortzeit
  376.  
  377.    Die interessanteste, einfachste Aenderung, mit der groessten Wirkung, am
  378.    Schluss ...
  379.  
  380.    Es fiel einem ziemlich negativ auf, dass die Antwortzeit im Hostmode
  381.    ziemlich bescheiden war beim TNC2. Genaue Tests brachten sogar hervor,
  382.    dass beim Beschicken des TNC mit langen Frames dieser es nicht einmal
  383.    zuwege brachte, mehr als drei oder vier hintereinander in eine Aussendung
  384.    zu packen. Da dieser Effekt genauso auch im Terminalmode auftrat, dachte
  385.    man zunaechst daran, dass der TNC mit seinem lahmen, in einer Hochsprache
  386.    programmierten Z80 halt einfach zu langsam ist beim Paketepacken.
  387.    Dem ist aber erstaunlicherweise nicht (ganz) so, wie folgende Betrachtungen
  388.    zeigen.
  389.  
  390.    Zunaechst, wie sieht das Hauptprogramm aus :
  391.  
  392.    main()
  393.      {
  394.        <Initialisierungen>
  395.        LOOP
  396.          {
  397.            l2();   /* Level 2 ausfuehren                                 */
  398.            l3();   /* Level 3 ausfuehren (Firmware: L3-Frames wegwerfen) */
  399.            lx();   /* Level x ausfuehren (Firmware: Userein/ausgaben     */
  400.          }
  401.      }
  402.  
  403.    l2()
  404.      {
  405.        l2tx();               /* Level 2, Sender                          */
  406.        l2rx();               /* Level 2, Empfaenger                      */
  407.        l2rest();             /* Level 2, Rest (Busy-Condition etc.)      */
  408.      }
  409.  
  410.    Man sieht, dass von einem Aufruf von lx() bis zum naechsten Aufruf eine
  411.    Menge Zeit vergehen kann. Ausserdem ist es nicht erforderlich, dass
  412.    irgendwelche Routinen innerhalb einer bestimmten Zeitspanne aufgerufen
  413.    werden muessen. Denn einerseits laufen alle HDLC-Ein/Ausgaben
  414.    interruptgesteuert unter Zugriff auf voll dynamische Speicherverwaltung
  415.    (nicht feste FIFOs) ab, es ist nicht erforderlich dass zu bestimmten Zeiten
  416.    irgendwo etwas "abgeholt" wird. Andererseits gibt es auch keine
  417.    "Timerketten", die alle soundsoviel Millisekunden geservt werden muessen,
  418.    sondern die Timer werden durch Uebergabe der vergangenen "Ticks" berechnet.
  419.  
  420.    Wie laeuft nun der interessierende lx() ab ?
  421.  
  422.    lx()
  423.      {
  424.        <vergangene Zeit in Ticks nach letzem Aufruf berechnen>
  425.  
  426.        l2timr(ticks);        /* Level 2, Timerservice                    */
  427.  
  428.        <CON- und STA-Led-Service>
  429.  
  430.        if (!ishmod)          /* wenn kein Hostmode eingeschaltet ...     */
  431.          {
  432.            <Terminalmode>
  433.          }
  434.        else                  /* wenn Hostmode eingeschaltet              */
  435.          {
  436.  
  437.            <selektiere Monitorframes aus>
  438.  
  439.            if (RS232-FIFO nicht leer)
  440.              {
  441.                <hole ein Zeichen aus RS232-FIFO>
  442.                <verarbeite dieses eine Zeichen>
  443.                if (Hostmodekommando abgeschlossen)
  444.                  {
  445.                    <Fuehre Hostmodekommando aus>
  446.                  }
  447.              }
  448.  
  449.          } /* Ende else von if (!ishmod) */
  450.      } /* Ende lx() */
  451.  
  452.    Bei dieser Uebersicht faellt etwas Entscheidendes sofort ins Auge :
  453.    der Level lx() in dieser Form verarbeitet pro Aufruf immer nur
  454.    hoechstens ein einziges Zeichen !
  455.    Das heisst, wenn ich ich ein 256-Byte Frame im Hostmode in den
  456.    TNC schiebe, dass das einzelbyteweise abgearbeitet wird. Also
  457.    256 + Hostmodekommandobytes mal in der main-Hauptkommandoschleife
  458.    herum und alle einzelnen Routinen abarbeiten, alle Linkblocks und
  459.    Timer serven, etc. pp. Und  d a s  ist nicht notwendig, da, wie
  460.    beschrieben, ja ein Herumlaufen in der main-LOOP  n i c h t  alle
  461.    soundoviel Millisekunden erfolgen muss. Ausserdem, nach Beendigung einer
  462.    Hostmodekommandoeingabe wird ja ein komplettes Kommando abgearbeitet, was
  463.    dann ja auch sehr lange dauern kann, mit Sicherheit aber laenger als das
  464.    simple Holen einiger Bytes aus dem RS232-FIFO.
  465.  
  466.    Die ganze Aenderung besteht nun im Ersetzen eines "if" durch "while"
  467.    und Einfuegen eines "return" :
  468.  
  469.            while (RS232-FIFO nicht leer)
  470.              {
  471.                <hole ein Zeichen aus RS232-FIFO>
  472.                <verarbeite dieses eine Zeichen>
  473.                if (Hostmodekommando abgeschlossen)
  474.                  {
  475.                    <Fuehre Hostmodekommando aus>
  476.                    return;
  477.                  }
  478.              }
  479.  
  480.    Im uebrigen laeuft der Terminalmode genauso ab - auch dort koennte man
  481.    eine entsprechende Aenderung anbringen. Ich habe das aber nicht gemacht,
  482.    weil der Terminalmode ausschliesslich fuer Eingaben von Hand gedacht ist
  483.    und dafuer der Ablauf wie vorhanden voellig ausreichend ist.
  484.  
  485.  
  486.  
  487. Bei der einen oder anderen Aenderung oder Erklaerung kann ich mich natuerlich
  488. auch irren - falls jemand irgendwozu eine andere Meinung hat, dann bitte
  489. sofort melden.
  490.  
  491. 73, Michael, DC4OX @ DK0MAV.
  492.  
  493. -----------------------------------
  494.