home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / MKLAPI09.ZIP / MARKLIN.DOC < prev    next >
Text File  |  1993-03-02  |  108KB  |  3,092 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.                                                      Märklin-Interface driver
  19.                                                       and High Level Language
  20.                                             Application Programming Interface
  21.                                                      for C-language and BASIC
  22.  
  23.  
  24.  
  25.  
  26.                                                 Document Number RH-MKLAPI 0.9
  27.  
  28.                                                                 March 2, 1993
  29.  
  30.  
  31.                                                                 Rob Hamerling
  32.  
  33.                                                                     Vianen-ZH
  34.                                                               The Netherlands
  35.                                                  Phone: 31-3473-72136 (voice)
  36.                                                            FIDO: 2:512/4.1098
  37.  
  38.                                                      Märklin-Interface driver
  39.  
  40.   Versions 0.9 and up are NOT COMPATIBLE with earlier versions!
  41.  
  42.  
  43.   Märklin-Interface driver
  44.   ───────────────────────────────────────────────────────────────────────────
  45.  
  46.  
  47.   CONTENTS
  48.  
  49.  
  50.     Introduction  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
  51.     What is the Märklin-Interface-driver?   . . . . . . . . . . . . . . . . 1
  52.     Purpose   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
  53.     Realisation   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
  54.     Registration  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
  55.  
  56.     Functional description  . . . . . . . . . . . . . . . . . . . . . . . . 4
  57.     Overview  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
  58.     Terminology   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
  59.     Functional Requirements   . . . . . . . . . . . . . . . . . . . . . . . 4
  60.     Provided Facilities   . . . . . . . . . . . . . . . . . . . . . . . . . 5
  61.     Deliverables  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
  62.     Prerequisites   . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
  63.     Restrictions and Limitations  . . . . . . . . . . . . . . . . . . . . . 7
  64.     Tests   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
  65.     C-language framework  . . . . . . . . . . . . . . . . . . . . . . . . . 7
  66.   | QuickBASIC framework  . . . . . . . . . . . . . . . . . . . . . . . . . 8
  67.     Sample programs   . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
  68.     OS/2 and DOS differences   . . . . . . . . . . . . . . . . . . . . . . 10
  69.  
  70.     Specifications   . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
  71.     Available Functions  . . . . . . . . . . . . . . . . . . . . . . . . . 12
  72.   | mklclose   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
  73.   | mklflush   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
  74.   | mklgetsn   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
  75.   | mklgo  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
  76.   | mklmsecs   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
  77.   | mklopen  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
  78.   | mklpoll  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
  79.   | mklpurge   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
  80.   | mklputc  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
  81.   | mklsleep   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
  82.   | mklstats   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
  83.   | mklstop  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
  84.   | mkltime  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
  85.   | mkltrace   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
  86.     Macro Specifications   . . . . . . . . . . . . . . . . . . . . . . . . 29
  87.       mklput1c   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
  88.       mklput2c   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
  89.   | Use of timer   . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
  90.   | QuickBASIC Function Specifications   . . . . . . . . . . . . . . . . . 30
  91.     Errors and Signals   . . . . . . . . . . . . . . . . . . . . . . . . . 31
  92.  
  93.     Installation   . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
  94.     Application development considerations   . . . . . . . . . . . . . . . 32
  95.     C-Compiler considerations  . . . . . . . . . . . . . . . . . . . . . . 32
  96.   | MicroSoft QuickBASIC compiler 4.5 Considerations   . . . . . . . . . . 32
  97.     Building an EXE-file   . . . . . . . . . . . . . . . . . . . . . . . . 32
  98.   |   C-language and DOS   . . . . . . . . . . . . . . . . . . . . . . . . 33
  99.   |   C-language and BASIC   . . . . . . . . . . . . . . . . . . . . . . . 33
  100.  
  101.   ───────────────────────────────────────────────────────────────────────────
  102.                                                                  Contents  ii
  103.  
  104.   Märklin-Interface driver
  105.   ───────────────────────────────────────────────────────────────────────────
  106.  
  107.  
  108.   |   C-language and OS2 1.3   . . . . . . . . . . . . . . . . . . . . . . 34
  109.   |   C-language and OS2 2.0+  . . . . . . . . . . . . . . . . . . . . . . 35
  110.   | Storage and performance  . . . . . . . . . . . . . . . . . . . . . . . 35
  111.       Memory Utilisation   . . . . . . . . . . . . . . . . . . . . . . . . 35
  112.       Processor utilisation  . . . . . . . . . . . . . . . . . . . . . . . 36
  113.     Comments, Remarks, Bug-reports   . . . . . . . . . . . . . . . . . . . 36
  114.  
  115.     Appendix A.  Summary of changes  . . . . . . . . . . . . . . . . . . . 37
  116.  
  117.     Appendix B.  MKLAPI Internals  . . . . . . . . . . . . . . . . . . . . 39
  118.     Communications Interface Specification   . . . . . . . . . . . . . . . 39
  119.     Problems with OS/2 COM[xx].SYS   . . . . . . . . . . . . . . . . . . . 41
  120.  
  121.     Appendix C.  Design Notes and Tips   . . . . . . . . . . . . . . . . . 42
  122.     Polling Facility   . . . . . . . . . . . . . . . . . . . . . . . . . . 42
  123.       Multitasking   . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
  124.       Background polling task  . . . . . . . . . . . . . . . . . . . . . . 43
  125.     OS/2 and DOS differences   . . . . . . . . . . . . . . . . . . . . . . 44
  126.  
  127.     Appendix D.  Trace facility  . . . . . . . . . . . . . . . . . . . . . 47
  128.     Trace records  . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
  129.     Sample   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.   ─────────────────────
  160.   1   This document is processed: on March 2, 1993 at 20:36
  161.  
  162.   ───────────────────────────────────────────────────────────────────────────
  163.                                                                 Contents  iii
  164.  
  165.   Märklin-Interface driver
  166.   ───────────────────────────────────────────────────────────────────────────
  167.  
  168.  
  169.   INTRODUCTION
  170.  
  171.                   (C) Copyright  -  R. Hamerling, 1991, 1993
  172.                              All Rights Reserved.
  173.  
  174.  
  175.  
  176.   WHAT IS THE MäRKLIN-INTERFACE-DRIVER?
  177.  
  178.   The Märklin-Interface-driver simplifies programming for model-railroads
  179.   which are controlled via a Märklin-Interface.  It provides a
  180.   communications- and a timer-task, and a number of user callable routines
  181.   for elementary functions.  It offers a comfortable high-level programming
  182.   interface and reliefs a programmer from 'low-level' tasks such as
  183.   controlling the communication with the Märklin-Interface, so that he can
  184.   concentrate on the railroad-control logic.  It includes also a
  185.   multi-tasking facility, which is highly desirable for this realtime
  186.   environment.
  187.  
  188.  
  189.   PURPOSE
  190.  
  191.   The driver has been developed for the following purposes:
  192.  
  193.   ■  To have an application programming interface (API) which is independent
  194.      of the operating system (i.c. OS/2 or DOS).
  195.  
  196.   ■  To provide a simple (high level) interface for a number of frequently
  197.      used basic control functions such as sending commands to trains and
  198.      switch points, and reading sensors.
  199.  
  200.   ■  To allow the mainline to be written completely in high-level programming
  201. |    language (i.c. C-language or QuickBASIC).
  202.  
  203.   ■  To obtain a buffered communications facility to the Märklin-Interface,
  204.      including automatic flow control as required by the Märklin-Interface.
  205.  
  206.   ■  To have 'background' tasks for a number of functions that should or
  207.      could be performed independently (and asynchronously) from the mainline
  208.      program.
  209.  
  210.   ■  To provide an accurate timer facility for time-dependent operations,
  211.      events and calculations.
  212.  
  213.  
  214.  
  215.   REALISATION
  216.  
  217.   This package offers a driver with all the functionality of the list in
  218.   "Purpose".  The OS/2-driver and DOS-driver are completely different
  219.   implementations, due to the rather extreme differences in functionality
  220.   provided by OS/2 and DOS for this type of environment.  However the
  221.   railroad control program may be unaware of the underlying operating system:
  222.  
  223.   ───────────────────────────────────────────────────────────────────────────
  224.                                                               Introduction  1
  225.  
  226.   Märklin-Interface driver
  227.   ───────────────────────────────────────────────────────────────────────────
  228.  
  229.  
  230.   the application programming interface is identical.
  231.  
  232.   You may read a number of (possible) differences in "OS/2 and DOS
  233.   differences" on page 10.
  234.  
  235.  
  236.   REGISTRATION
  237.  
  238.   This package is of the 'SHAREWARE' type: You may try it for a reasonably
  239.   short time (say 1 to 2 months).  If you decide to use it for your own
  240.   railroad control program, you may show your appreciation and become a
  241.   'registered user'.  After registration, I'll send you by mail:
  242.  
  243.   ■  A diskette (3-1/2", 720KB), with the following contents:
  244.      -  The most recent version of all the drivers.
  245.      -  Source-files of the sample program provided as executable in the base
  246.         package.
  247.  
  248.   ■  The complete and up-to-date printed documentation, as well as 2
  249.      documentation files on the diskette:
  250.      -  A print-file, formatted for IBM Pro-Printer III.
  251.      -  A file in OS/2 INF format (VIEW-able as online documentation like the
  252.         inline OS/2 Command Reference Manual).
  253.  
  254.   After registration you are allowed to distribute the driver as integral
  255.   part of your own railroad control application programs.  The registration
  256.   fee is 25 Dutch Guilders or equivalent of 15 US-Dollars.  Mention the
  257.   purpose of you payment ("Märklin-Interface-driver"), and the destination
  258.   address of the additional material!
  259.  
  260.   The package (not the material you get after registration) may be
  261.   distributed freely with under the following conditions:
  262.  
  263.   ■  it remains a separate and complete package
  264.   ■  you do not apply changes of any kind
  265.   ■  you do not make profit with it
  266.  
  267.   Please send your comments and registration fee to:
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.   ───────────────────────────────────────────────────────────────────────────
  285.                                                               Introduction  2
  286.  
  287.   Märklin-Interface driver
  288.   ───────────────────────────────────────────────────────────────────────────
  289.  
  290.  
  291.        R. Hamerling
  292.        Vianen-ZH,
  293.        The Netherlands
  294.        Postbank acct#: 2087285
  295.        PC-Square: FIDOnet 2:512/4.1098
  296.  
  297.   Before you ask:  the source material of the drivers will not be published.
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.   ───────────────────────────────────────────────────────────────────────────
  346.                                                               Introduction  3
  347.  
  348.   Märklin-Interface driver
  349.   ───────────────────────────────────────────────────────────────────────────
  350.  
  351.  
  352.   FUNCTIONAL DESCRIPTION
  353.  
  354.   This chapter describes the possibel use of this package.
  355.  
  356.  
  357.   OVERVIEW
  358.  
  359.   The Märklin-Interface-driver package is a set of functions to enable direct
  360. | communications support in a program written in C-language or BASIC for the
  361. | MicroSoft QuickBASIC compiler 4.5(2)  for the family of IBM Personal
  362. | System/2 and compatibles.
  363.  
  364. | Note: The QuickBASIC driver is exactly the same as that for C-language, but
  365. | has not been tested extensively with a full fledge train control program in
  366. | BASIC, so beware of possible bugs.  Please report possible problems with
  367. | the driver as soon as possible.  and accompany your report with as much
  368. | details as might be relevant.
  369.  
  370.  
  371.   TERMINOLOGY
  372.  
  373.   In this document I use a number of terms which should probably be clarified
  374.   first.
  375.  
  376.   Interface The Märklin-Interface. (Märklin partnumber 6050)
  377.  
  378.   Sensor    The Märklin S88 encoder. (Märklin partnumber 6088).  Sometimes
  379.             also called sensor-box or encoder.
  380.  
  381.   Switch    The railroad facility, Märklin K83 decoder (Märklin partnumber
  382.             6083) is used to control these switch points.
  383.  
  384.  
  385.  
  386.   FUNCTIONAL REQUIREMENTS
  387.  
  388.   The Märklin-Interface-driver must provide the following functionality:
  389.  
  390.   ■  Possibility to send commands to the Märklin-Interface in any sequence
  391.      and mix.
  392.  
  393.   ■  Builtin buffered communication with the Märklin-Interface.
  394.  
  395.   ■  Automatic flow control between PC and Märklin-Interface.
  396.  
  397.   ■  Time-base (clock) for for time-dependent control, independent of
  398.  
  399.   ─────────────────────
  400.   2    Please note that this driver is delivered in the form of .OBJ-files,
  401.       and therefore can be used only with compiled programs (other
  402.       .OBJ-files).  QBASIC that comes with DOS 5.0 is not capable of
  403.       producing an .OBJ file, you'll need the MicroSoft QuickBASIC compiler
  404.       4.5 to use this driver with BASIC programs.
  405.  
  406.   ───────────────────────────────────────────────────────────────────────────
  407.                                                     Functional description  4
  408.  
  409.   Märklin-Interface driver
  410.   ───────────────────────────────────────────────────────────────────────────
  411.  
  412.  
  413.      hardware (processor) speed.
  414.  
  415.   ■  Automatic readout of sensor-boxes (Märklin S88 encoder): the mainline
  416.      must be able to obtain sensor positions instantaneously (without
  417.      waittime)
  418.  
  419.   ■  Priority mechanism: mainline activities must be handled with higher
  420.      priority than 'background' service processes.
  421.  
  422.   ■  Ability for emergency stops, regardless of the state of the program or
  423.      the model railroad.
  424.  
  425.  
  426.  
  427.   PROVIDED FACILITIES
  428.  
  429.   To fulfil the functional requirements, a 'driver' has been built.  It
  430.   contains a number of service-routines (and for DOS also hardware interrupt
  431.   routines), and provides the following facilities:
  432.  
  433.   ■  Functions to send train and switch commands to the interface.
  434.  
  435.      Two macro's for output of resp. 1 or 2 consecutive characters (the so
  436.      called 1-byte or 2-byte commands).  With the 2-byte form the subroutines
  437.      ensure that the 2 characters are sent as 2 consecutive characters (not
  438.      interrupted by a 'background' task).
  439.  
  440.   ■  Functions to read sensors (S88-boxes).
  441.  
  442.      This can either be done by immediate reading the status of the last
  443.      polling operation (if polling started).  "Appendix C.  Design Notes and
  444.      Tips" on page 42 contains details about this mechanism.
  445.  
  446.      If the mainline is sending a command to the Märklin-Interface, polling
  447.      is automatically suspended (the command is treated with higher
  448. |    priority).
  449.  
  450. | ■  A 'shadow' of the system timer, but expressed in milliseconds since
  451. |    program start.  This timer has with the OS/2-driver of MKLAPI a
  452. |    precision of 31.25 msecs, using standard OS/2 facilities (the timer
  453. |    tick).  With the DOS-driver of MKLAPI the posibilities of the hardware
  454. |    PC timer are explored, giving a precision of 1 millisecond.
  455.  
  456.   ■  A trace facility is built in for easy program debugging.  All output to
  457.      the interface can [optionally] be traced (OS/2 only) and formatted
  458.      later.
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.   ───────────────────────────────────────────────────────────────────────────
  468.                                                     Functional description  5
  469.  
  470.   Märklin-Interface driver
  471.   ───────────────────────────────────────────────────────────────────────────
  472.  
  473.  
  474.   DELIVERABLES
  475.  
  476.   The shareware components of the Märklin-Interface-driver package are:
  477.  
  478.   ■  This documentation file: MARKLIN.DOC.
  479.   ■  Header file for C-language: MARKLIN.H with function prototypes, data-
  480. |    and macro- definitions.
  481. | ■  Include file for QuickBASIC: MARKLIN.INC with function prototypes.
  482. | ■  2 OS/2-object decks, MARKLIN2.OBJ (16-bits OS/2 version) and
  483. |    MARKLIN3.OBJ (32-bits OS/2 version), with a buffered multitasking
  484. |    communication interface, polling, timer-support and trace facility.
  485. | ■  2 DOS-object decks for C-language programs, SMARKIN.OBJ and
  486. |    LMARKLIN.OBJ, with the same functionality as the OS/2 drivers, (but
  487. |    without a trace facility).  SMARKLIN is the object deck to be linked
  488. |    with your SMALL memory model program, LMARKLIN.OBJ is for LARGE memory
  489. |    model C-language programs.  LMARKLIN.OBJ is also used for QuickBASIC
  490. |    programs.
  491.   ■  TRAIN.EXE and TRAIN2.EXE, which are ready to run sample programs for a
  492.      DOS and OS/2 environment respectively.  See "Sample programs" on page 9
  493.      for some characteristics of these programs.
  494.   ■  MKLTRFMT.EXE, utility to interpret (format) the recorded trace file.
  495.  
  496.   The registration package consists of:
  497.  
  498.   ■  Sources (in C-language) of a sample train control program that makes use
  499.      of the Märklin driver, usable for OS/2 and DOS ('fullscreen'
  500.      application)
  501.   ■  All include and header files
  502.   ■  All MAKE and DEF files, used for compilation with MicroSoft C-compiler
  503.      6.00a or equivalent, IBM C SET/2 compiler for 32-bits programs and
  504.      MicroSoft QuickBASIC compiler 4.5 for QuickBASIC programs.
  505.  
  506.  
  507.  
  508.   PREREQUISITES
  509.  
  510.   The package has been built with the following assumptions:
  511.  
  512.   ■  Your PC-hardware is 100% compatible with the productline of IBM Personal
  513.      Computers (PC, PC/XT, PC/AT, and all current models of the Personal
  514.      System/2 family), in particular the asynchronous communication adapters,
  515.      their port addresses, etc. and the hardware timer.
  516.  
  517.   ■  The operating system is either OS/2 1.2 or higher, or PC-DOS 2.1 or
  518.      MS-DOS 2.1 or higher.  The package has been tested only with IBM PC/DOS
  519.      version 4.0 and 5.0, and with OS/2 version 1.3 and 2.0 (in OS/2
  520. |    session).
  521.  
  522. | ■  Your (16-bits) C-programs (OS/2 and DOS) will be compiled with IBM C/2
  523. |    compiler 1.1  or MicroSoft C-compiler 6.00a, for 32-bits C-programs IBM
  524. |    C SET/2 compiler is assumed.  There may be some specific requirements on
  525. |    system hardware and software for these.  Maybe Borland Turbo C compiler
  526. |    will work as well, but this has not been tested.
  527.  
  528.   ───────────────────────────────────────────────────────────────────────────
  529.                                                     Functional description  6
  530.  
  531.   Märklin-Interface driver
  532.   ───────────────────────────────────────────────────────────────────────────
  533.  
  534.  
  535. | ■  Your BASIC programs will be compiled with the MicroSoft QuickBASIC
  536. |    compiler 4.5.
  537.  
  538.  
  539.  
  540.   RESTRICTIONS AND LIMITATIONS
  541.  
  542.   The following restrictions apply:
  543.  
  544.   ■  One single port can be used between open and close of the COM-port to
  545.      the Märklin-Interface, all other functions apply to the port chosen at
  546. |    open-time.
  547.  
  548. | ■  The transmit buffer of the DOS-driver is 2048 bytes long, for OS/2 it
  549.      depends on COM[xx].SYS, or substitute.
  550.  
  551.   ■  Received data is transferred immediately to the sensor-array (64 bytes).
  552.  
  553.   ■  When the mainline is sending data to the Märklin-Interface and a
  554.      buffer-full situation arises, the data will be discarded.  However it is
  555.      very unlikely that this will happen in real life.
  556.  
  557.   ■  If you read a sensor-box outside the polling-range, the response is
  558.      undefined.
  559.  
  560.  
  561.  
  562.   TESTS
  563.  
  564.   The driver has been tested with the following model railroad equipment:
  565.  
  566.   ■  Märklin Combined Control
  567.   ■  3 Märklin Digital locs
  568.   ■  3 Märklin K83 decoders, each connected to 4 switch points
  569.   ■  1 Märklin S88 encoder, with railroad-section sensoring
  570.  
  571.   Some tests have been performed for a bigger environment (such as simulating
  572.   more than a single S88), but this does not guarantee that is works in a
  573.   real environment different than the one of the list above.
  574.  
  575.   The driver has been tested with the following computer hardware:
  576.  
  577.   ■  IBM PC/AT-3 (8 Mhz 80286) and IBM PS/2 model 80 (16 MHz 80386).
  578.   ■  IBM serial-parallel adapter (primary serial port: COM1).
  579.  
  580.  
  581.  
  582.   C-LANGUAGE FRAMEWORK
  583.  
  584.   A typical model railroad control program with this driver may look like:
  585.  
  586.  
  587.  
  588.  
  589.   ───────────────────────────────────────────────────────────────────────────
  590.                                                     Functional description  7
  591.  
  592.   Märklin-Interface driver
  593.   ───────────────────────────────────────────────────────────────────────────
  594.  
  595.  
  596.  
  597.        #include "marklin.h"
  598.  
  599.        mklopen(1,2400);                  /* open COM1: */
  600.        mklpoll(5);                       /* 5 S88 boxes in yard */
  601.        while (key != ESC) {              /* end program from keyboard */
  602.          if (kbhit()) {                  /* keyboard input */
  603.            if (key = getch()) {          /* normal key (incl alt-numpad) */
  604.              switch(key) {
  605.                case '?':   - - - - -     /* your key, your function */
  606.                            break;
  607.                case ESC:   break;        /* nothing now, exit program */
  608.                default:    fprintf(stdout,"%c",BEL);
  609.                            break;        /* unsupported normal key */
  610.                }
  611.              }
  612.            else {                        /* 'special' key */
  613.              switch(key = getch()) {     /* extended character */
  614.                case PgDn:   - - - - -    /* your 'extended' key function */
  615.                            break;
  616.                default:    fprintf(stdout,"%c",BEL);
  617.                            break;        /* unsupported 'extended' key */
  618.                }
  619.              }
  620.            }
  621.          for (i=0; i<MAXTRAIN; i++) {    /* scan train matrix */
  622.            - - - - -                     /* train control function */
  623.            }
  624.          for (i=1; i<5, ++i) {           /* scan S88 boxes */
  625.            mklgetsn(i);                  /* read sensor bits */
  626.            - - - - - -                   /* process changes */
  627.            }
  628.          if (!(mkltime()%5000)) {        /* every 5 seconds */
  629.            - - - - -                     /* anything else */
  630.            }
  631.          mklsleep();                     /* give up remainder of timeslice */
  632.          }
  633.        mklflush();                       /* wait until output sent */
  634.        mklclose();                       /* terminate */
  635.  
  636.  
  637.   Note: Above code is just a framework to show the general setup of a model
  638. | railroad control program using the Märklin-Interface.
  639.  
  640.  
  641. | QUICKBASIC FRAMEWORK
  642.  
  643. | An equivalent framework in QuickBASIC might look like:
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.   ───────────────────────────────────────────────────────────────────────────
  651.                                                     Functional description  8
  652.  
  653.   Märklin-Interface driver
  654.   ───────────────────────────────────────────────────────────────────────────
  655.  
  656.  
  657.  
  658. |      ' $INCLUDE: 'MARKLIN.INC'
  659.  
  660. |      rc = mklopen(1,2400);
  661. |      mklpoll(5);
  662. |      key$ = INKEY$
  663. |      while key$ <> ESC$
  664. |        select case key$
  665. |          case '?'
  666. |             - - - - -
  667. |          case ESC
  668. |             - - - - -
  669. |          case else
  670. |            print "error key"
  671. |        end select
  672. |        for i=0 to MAXTRAIN
  673. |          - - - - -
  674. |        next i
  675. |        for i=1 to 5
  676. |          mklgetsn(i)
  677. |          - - - - - -
  678. |        next i
  679. |        if MOD(mkltime,5000) < 50 then
  680. |          - - - - -
  681. |        end if
  682. |        mklsleep
  683. |        key$ = INKEY$
  684. |      wend
  685. |      mklflush;
  686. |      mklclose;
  687.  
  688.  
  689. | Note: This code may not be true and workable BASIC!
  690.  
  691. | The file MARKLIN.INC contains the DECLARE lines for all functions contained
  692. | in LMARKLIN.OBJ.  It should be included in a QuickBASIC program to obtain
  693. | the correct calling conventions and activates syntax checking by the
  694. | MicroSoft QuickBASIC compiler 4.5.
  695.  
  696.  
  697.   SAMPLE PROGRAMS
  698.  
  699. | After registration you will receive the sources a sample program (in
  700. | C-language only!).
  701.  
  702.   ■  Control of 8 trains and several other possibilities, with the following
  703.      details:
  704.      -  Speed is controlled from the computer keyboard with arrow (cursor)
  705.         keys: right-key is faster, left-key is slower, up-key is maximum for
  706.         this train, down is maximum backward for this train.
  707.      -  The train for which the command is meant is selected with a
  708.         number-key (program provides control for trains 1 through 8).  The
  709.         corresponding loc-address and other train properties are in a matrix
  710.  
  711.   ───────────────────────────────────────────────────────────────────────────
  712.                                                     Functional description  9
  713.  
  714.   Märklin-Interface driver
  715.   ───────────────────────────────────────────────────────────────────────────
  716.  
  717.  
  718.         (with individual entries for each train), such as minimum and maximum
  719.         speed in Märklin Central Unit values.  The train addresses that are
  720.         programmed are 10 for train 1, 20 for train 2, etc until 80 for train
  721.         8.
  722.      -  The speed-control is indirect: you tell the system the program
  723.         loc-speed, the program does mass-simulation ('slow' increase and
  724.         decrease of speed).  The parameters for enertia simulation are part
  725.         of the train definitions.
  726.      -  For each train its address, desired and actual train speed are
  727.         displayed (in color).  Direction changes are buffered and automatic.
  728.      -  The display also indicates direction and whether the extra function
  729.         is 'on' or 'off'.
  730.  
  731. | ■  Control of 4 Märklin K83 decoder for 16 railroad switch points.  For
  732. |    each switch the position ('normal' or 'bound' in color) and its address
  733. |    is displayed.  The keys are A-P for adresses 253-256, and 1-12
  734. |    respectively.
  735.  
  736. | ■  Polling of Märklin S88 encoder each with 16 sensors (or isolated
  737. |    railroad sections).  The position is displayed real time, nothing but
  738. |    displaying is done with the information.  2 Märklin S88 encoder-boxes
  739. |    are being polled.
  740.  
  741. | ■  Sensor 16 of Märklin S88 encoder-box 1 is designated for speed
  742. |    measurement.  The display shows the time (in milliseconds) between 2
  743. |    successive 'OFF-ON' transitions.  If there is 1 train running and moving
  744.      along the same road, this facility can be used for calibrating speed
  745.      calculations for each speed-command-value.
  746.  
  747.   ■  Other keys:
  748.      Insert    Set Function 'on'
  749.      Delete    Set Function 'off'
  750.      End       Stop polling
  751.      Home      Restart polling
  752.      F3        Stop the program (has to be entered twice consecutively)
  753.      Esc       Emergency Stop (issues the Märklin Central Unit STOP command)
  754.      Enter     Resume (issues the Märklin Central Unit GO command)
  755.  
  756.   The program may be started with 2 numeric parameters:
  757.  
  758.   1. the first parameter indicates the COM-port to be used (1 for COM1, 2 for
  759.      COM2, etc.), The default is COM1.
  760.   2. The second parameter indicates the number of Märklin S88 encoder-boxes
  761.      to include in the polling mechanism.  The default is 2.
  762.  
  763.  
  764.  
  765.   OS/2 AND DOS DIFFERENCES
  766.  
  767.   The OS/2-drivers differ from the DOS drivers:
  768.  
  769.   ■  The OS/2-drivers are written in C-language, the DOS drivers in
  770.      Assembler.
  771.  
  772.   ───────────────────────────────────────────────────────────────────────────
  773.                                                    Functional description  10
  774.  
  775.   Märklin-Interface driver
  776.   ───────────────────────────────────────────────────────────────────────────
  777.  
  778.  
  779.   ■  The OS/2-driver makes use of the services provided by the standard OS/2
  780.      communications driver COM02.SYS (for PS/2) or COM01.SYS for others under
  781.      OS/2 version 1.3, and COM.SYS for OS/2 version 2.0.  The DOS driver
  782.      interfaces directly with the PC hardware.
  783.  
  784.   ■  The OS/2-driver makes use of the standard OS/2 facilities for
  785.      multithreading (task signalling is done with semaphores).  The DOS
  786.      driver performs a form of multi-tasking, driven by interrupts (the
  787. |    COM-port hardware and the standard DOS timer tick).
  788.  
  789. | ■  The DOS-drivers explore the possibilities of the hardware timer of the
  790. |    PC to obtain a accurate time values when needed.  With the DOS
  791. |    timer-tick of 55 msec the average deviation would be about 28 msec.
  792. |    OS/2 does not allow access to the hardware by 'normal' applications,
  793. |    therefore the OS2.-drivers use standard OS/2 function calls.  Since the
  794. |    OS/2 timer tick is 31.25 msec, the average deviation will be about 16
  795. |    msecs.
  796.  
  797.   The sample program under DOS chokes the processor (takes all the cycles
  798.   that are available).  This is OK in a typical single-task environment, but
  799.   not very suitable for a multitasking system.  Under OS/2 a very simple
  800.   solution for this problem is to insert  for example a DosSleep(30L) at the
  801.   end of the infinite (keyboard-) loop.  There may be better solutions.
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.   ───────────────────────────────────────────────────────────────────────────
  834.                                                    Functional description  11
  835.  
  836.   Märklin-Interface driver
  837.   ───────────────────────────────────────────────────────────────────────────
  838.  
  839.  
  840.   SPECIFICATIONS
  841.  
  842.   This chapter describes the use of the provided facilities.
  843.  
  844.  
  845.   AVAILABLE FUNCTIONS
  846.  
  847.   The following user callable functions are provided:
  848.  
  849.   mklopen         Start the communication with the Märklin-Interface and the
  850.                   background tasks.
  851.   mklclose        Stop background tasks and shutdown the communication with
  852.                   the Märklin-Interface.
  853.   mklputc         Transmit 1 or 2 character-commands to the
  854.                   Märklin-Interface.
  855.   mklflush        Wait until all data transmitted.
  856.   mklpurge        Discard remaining data in output buffer.
  857.   mklpoll         Start or stop polling of Märklin S88 encoder boxes.
  858.   mklgetsn        Obtain the status of 1 Märklin S88 encoder (when polling
  859.                   active).
  860.   mklstop         Set Märklin-Interface in 'stop'-state and stop polling
  861.   mklgo           Set Märklin-Interface in 'go'-state and (optionally) resume
  862.                   polling.
  863. | mklmsecs        Give accurate time in milliseconds since program start
  864. |                 (only in DOS-drivers).
  865. | mkltime         Give time of last timer tick in milliseconds since program
  866. |                 start.
  867. | mklstats        Provide statistics (activity counters).
  868.   mklsleep        Give up the remainder of a time slice when running in a
  869.                   multitasking environment.
  870.   mkltrace        Start or stop recording data that is being sent to
  871. |                 Märklin-Interface  (only in OS/2-drivers).
  872.  
  873.   The next sections contain the specifications of available functions of the
  874. | Märklin-driver, in alphabetical sequence.
  875.  
  876. | Note: The descriptions for C-language and QuickBASIC are given both, but in
  877. | the text mainly the C-language notations are used.
  878.  
  879.  
  880. | MKLCLOSE
  881.  
  882. | Name            mklclose - close communications with the Märklin-Interface.
  883.  
  884. | C-language
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.   ───────────────────────────────────────────────────────────────────────────
  895.                                                            Specifications  12
  896.  
  897.   Märklin-Interface driver
  898.   ───────────────────────────────────────────────────────────────────────────
  899.  
  900.  
  901. |   #include "marklin.h"
  902. |   void mklclose(void);
  903.  
  904. | QuickBASIC
  905.  
  906. |   ' $INCLUDE: 'MARKLIN.INC'
  907. |   DECLARE SUB MKLCLOSE CDECL ()
  908.  
  909. | Description     The close-routine disables the communications task of the
  910. |                 driver.  It should be called before termination your
  911. |                 program.  Transmits and receives that were in progress will
  912. |                 be terinated, data might be lost.
  913.  
  914. | Return value    Nothing.
  915.  
  916. | Related functions "mklopen" on page 17
  917.  
  918. | Warning: Mklclose() is not a trivial function!  It must be used when
  919. | mklopen() has been called succesfully (under DOS).  Otherwise your system
  920. | may enter a hang-up situation when for no matter what reason your
  921. | communications port gives an interrupt.  So terminate your program always
  922. | 'neatly' (so intercept Ctrl-Break in your program to prevent uncontrolled
  923. | program termination)!
  924.  
  925.  
  926.  
  927. | MKLFLUSH
  928.  
  929. | Name            mklflush - flush all buffered output.
  930.  
  931. | C-language
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.   ───────────────────────────────────────────────────────────────────────────
  956.                                                            Specifications  13
  957.  
  958.   Märklin-Interface driver
  959.   ───────────────────────────────────────────────────────────────────────────
  960.  
  961.  
  962. |   #include "marklin.h"
  963. |   int mklflush(void);
  964.  
  965. | QuickBASIC
  966.  
  967. |   ' $INCLUDE: 'MARKLIN.INC'
  968. |   DECLARE FUNCTION FLUSH% CDECL ()
  969.  
  970. | Description     Wait until all output is sent to the Märklin-Interface.  In
  971. |                 other words: wait for empty transmit buffer before
  972. |                 returning to caller.  When the buffered data could not be
  973. |                 flushed within 3 seconds, a timeout occurs.  The remaining
  974. |                 bytes in the transmit buffer will be purged and the purge
  975. |                 statistics are updated accordingly.
  976.  
  977. | Return value    Depending on success:
  978. |                 ■  0   when no more bytes to transmit
  979. |                 ■  >0  timeout (3 seconds) with number of bytes (n) left in
  980. |                    transmit buffer.
  981. |                 ■  -1 (DOS) last byte in hardware buffer was not
  982. |                    transmitted
  983.  
  984. | Related functions "mklpurge" on page 20
  985.  
  986.  
  987.  
  988. | MKLGETSN
  989.  
  990. | Name            mklgetsn - get the bit-pattern of a single Märklin S88
  991. |                 encoder.
  992.  
  993. | C-language
  994.  
  995.  
  996.  
  997.  
  998.  
  999.  
  1000.  
  1001.  
  1002.  
  1003.  
  1004.  
  1005.  
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.   ───────────────────────────────────────────────────────────────────────────
  1017.                                                            Specifications  14
  1018.  
  1019.   Märklin-Interface driver
  1020.   ───────────────────────────────────────────────────────────────────────────
  1021.  
  1022.  
  1023. |   #include "marklin.h"
  1024. |   unsigned short int mklgetsn(short int sensor);
  1025.  
  1026. | QuickBASIC
  1027.  
  1028. |   ' $INCLUDE: 'MARKLIN.INC'
  1029. |   DECLARE FUNCTION MKLGETSN% CDECL (BYVAL SENSOR%)
  1030.  
  1031. | Description     Get a single sensor-box word (16 bits) from the sensor
  1032. |                 array.
  1033.  
  1034. |                 This function does not generate any action to the
  1035. |                 Märklin-Interface and returns immediately.  Polling will
  1036. |                 have to be started first, with mklpoll(), before the
  1037. |                 reading of sensors will give meaningful results.  Reading
  1038. |                 outside the range 1..31, or higher than the value as
  1039. |                 specified with the latest mklpoll(maxsensor) or mklgo(
  1040. |                 maxsensor), will give unpredictable results.
  1041.  
  1042. | Return value    A 16-bit word containing the current switch positions.
  1043.  
  1044.  
  1045.  
  1046. | MKLGO
  1047.  
  1048. | Name            mklgo - send the 'go' command.
  1049.  
  1050. | C-language
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.   ───────────────────────────────────────────────────────────────────────────
  1078.                                                            Specifications  15
  1079.  
  1080.   Märklin-Interface driver
  1081.   ───────────────────────────────────────────────────────────────────────────
  1082.  
  1083.  
  1084. |   #include "marklin.h"
  1085. |   int mklgo(short int maxsensor);
  1086.  
  1087. | QuickBASIC
  1088.  
  1089. |   ' $INCLUDE: 'MARKLIN.INC'
  1090. |   DECLARE FUNCTION MKLGO% CDECL (BYVAL MAXSENSOR%)
  1091.  
  1092. | Description     Send the 'go'-command (ASCII 96) to the Märklin-Interface
  1093. |                 immediately.
  1094.  
  1095. |                 The value of MAXSENSOR has the same meaning and effect as
  1096. |                 in mklpoll (see "mklpoll" on page 18).  Polling will be
  1097. |                 resumed if a non-zero parameter is specified.
  1098.  
  1099. |                 OS/2: The go-command is sent via a DevIOCtl operation (send
  1100. |                 immediate), and will be followed by a simulated XON.  If
  1101. |                 there was buffered output (before the stop-state or after
  1102. |                 entering stop-state under OS/2 2.0), it will be transmitted
  1103. |                 now.  If the 'go'-command could not be sent, for example if
  1104. |                 the Interface is not ready to accept data, an
  1105. |                 errorcondition is returned.
  1106.  
  1107. |                 DOS: The go-command is send just as regular data.  The
  1108. |                 returncode is always zero.
  1109.  
  1110. | Return value    Nothing.
  1111.  
  1112. | Related functions "mklstop" on page 25, "mklpoll" on page 18
  1113.  
  1114.  
  1115.  
  1116. | MKLMSECS
  1117.  
  1118. | Name            mklmsecs - obtain time since program start in milliseconds.
  1119.  
  1120. | C-language
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.   ───────────────────────────────────────────────────────────────────────────
  1139.                                                            Specifications  16
  1140.  
  1141.   Märklin-Interface driver
  1142.   ───────────────────────────────────────────────────────────────────────────
  1143.  
  1144.  
  1145. |   #include "marklin.h"
  1146. |   unsigned long int void mklmsecs(void);
  1147.  
  1148. | QuickBASIC
  1149.  
  1150. |   ' $INCLUDE: 'MARKLIN.INC'
  1151. |   DECLARE FUNCTION MKLMSECS& CDECL ()
  1152.  
  1153. | Description     (DOS only!) Returns the exact time in milliseconds after
  1154. |                 program start without waiting for the next timer tick.
  1155. |                 This might be useful for more accurate timing for special
  1156. |                 purposes.  Of course it takes some time to execute the
  1157. |                 necessary instructions to read the timer and format the
  1158. |                 information.  On faster systems mklmsecs() gives the time a
  1159. |                 little more precise than on slower systems, but even on
  1160. |                 relatively slow systems it is much more precise than
  1161. |                 probably needed for the purpose of mode railroad control!
  1162. |                 If this very high precision is not needed, then use the
  1163. |                 function mkltime().
  1164.  
  1165. |                 (OS2.) This function is 100% equivalent to mkltime().
  1166.  
  1167. | Return value    Time in milliseconds after program start.
  1168.  
  1169. | Related functions "mkltime" on page 27
  1170.  
  1171.  
  1172.  
  1173. | MKLOPEN
  1174.  
  1175. | Name            mklopen - open communications line
  1176.  
  1177. | C-language
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.  
  1193.  
  1194.  
  1195.  
  1196.  
  1197.  
  1198.  
  1199.   ───────────────────────────────────────────────────────────────────────────
  1200.                                                            Specifications  17
  1201.  
  1202.   Märklin-Interface driver
  1203.   ───────────────────────────────────────────────────────────────────────────
  1204.  
  1205.  
  1206. |   #include "marklin.h"
  1207. |   void mklopen(short int port, short int speed);
  1208.  
  1209. | QuickBASIC
  1210.  
  1211. |   ' $INCLUDE: 'MARKLIN.INC'
  1212. |   DECLARE SUB MKLOPEN CDECL (BYVAL PORT%, BYVAL SPEED%)
  1213.  
  1214. | Description     Open and initialise communications port driver, high
  1215. |                 resolution timer (DOS only), set all statistics counters to
  1216. |                 zero.  The port-parameter may have a value of 1 to 4,
  1217. |                 indicating COM1: to COM4:.  COM1 and COM2 are pretty
  1218. |                 standard, but COM3 and COM4 aren't.  The following list
  1219. |                 shows my implementation of these ports.
  1220.  
  1221.  
  1222. |         mklport   base address    IRQ    INT vector addr
  1223. |         --------   ------------   -----   ---------------
  1224. | COM1:       1          3F8          4          0030
  1225. | COM2:       2          2F8          3          002C
  1226. | COM3:       3          338          4          0030
  1227. | COM4:       4          238          3          002C
  1228.  
  1229.  
  1230. |                 Warning: ports 3 and 4 may conflict with other  hardware
  1231. |                 and/or software. Use of these ports is is your
  1232. |                 responsibility, not that of the author of this package!
  1233.  
  1234. |                 Any port will always be initialised with 8-bit, no-parity,
  1235. |                 2 stop-bits.  The speed parameter should specify 2400,
  1236. |                 since it is the only speed supported by the
  1237. |                 Märklin-Interface.  Maybe later other values?
  1238.  
  1239. |                 The mklopen routine will initialise the communications task
  1240. |                 and the timer.
  1241.  
  1242. |                 Disabling is performed by mklclose().
  1243.  
  1244. | Return value    Nothing
  1245.  
  1246. | Related functions "mklclose" on page 12, "mklstats" on page 23
  1247.  
  1248.  
  1249.  
  1250. | MKLPOLL
  1251.  
  1252. | Name            mklpoll - start periodic reading of Märklin S88 encoder.
  1253.  
  1254. | C-language
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.   ───────────────────────────────────────────────────────────────────────────
  1261.                                                            Specifications  18
  1262.  
  1263.   Märklin-Interface driver
  1264.   ───────────────────────────────────────────────────────────────────────────
  1265.  
  1266.  
  1267. |   #include "marklin.h"
  1268. |   void mklpoll(unsigned int maxsensor);
  1269.  
  1270. | QuickBASIC
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.   ───────────────────────────────────────────────────────────────────────────
  1322.                                                            Specifications  19
  1323.  
  1324.   Märklin-Interface driver
  1325.   ───────────────────────────────────────────────────────────────────────────
  1326.  
  1327.  
  1328. |   ' $INCLUDE: 'MARKLIN.INC'
  1329. |   DECLARE SUB MKLPOLL CDECL (BYVAL MAXSENSOR%)
  1330.  
  1331. | Description     Märklin S88 encoderboxes 1..MAXSENSOR will be read by a
  1332. |                 'background' process.
  1333.  
  1334. |                 When starting the polling process a 'read with reset' is
  1335. |                 issued.  This means that the switches are supposed to be of
  1336. |                 the 'permanent' type, not of the 'moment' type.  This will
  1337. |                 be usable for example if you use them for sensing
  1338. |                 train-positions with isolated rail-sections.
  1339.  
  1340. |                 The responses of the read-operation are stored in a
  1341. |                 sensor-array.  Each word of the array can be read
  1342. |                 individually at any time with mklgetsn().
  1343.  
  1344. |                 Polling can be started and stopped any moment.  And even if
  1345. |                 started, it can be re-started (for example with a different
  1346. |                 maximum sensor value).
  1347.  
  1348. | Return value    Nothing
  1349.  
  1350. | Related functions "mklgo" on page 15 and "mklgetsn" on page 14
  1351.  
  1352.  
  1353.  
  1354. | MKLPURGE
  1355.  
  1356. | Name            mklpurge - purge output buffer
  1357.  
  1358. | C-language
  1359.  
  1360. |   #include "marklin.h"
  1361. |   void mklpurge(void);
  1362.  
  1363. | QuickBASIC
  1364.  
  1365. |   ' $INCLUDE: 'MARKLIN.INC'
  1366. |   DECLARE SUB MKLPURGE CDECL ()
  1367.  
  1368. | Description     Discard current contents of output buffer.  If the output
  1369. |                 buffer does contain any characters, these are not sent tot
  1370. |                 the Interface.  After purging the current contents, control
  1371. |                 is immediately returned.  See also "mklflush" on page 13.
  1372.  
  1373. |                 Note: This function is currently available in the driver
  1374. |                 for DOS.
  1375.  
  1376. | Return value    Nothing.
  1377.  
  1378. | Related functions "mklflush" on page 13
  1379.  
  1380.  
  1381.  
  1382.   ───────────────────────────────────────────────────────────────────────────
  1383.                                                            Specifications  20
  1384.  
  1385.   Märklin-Interface driver
  1386.   ───────────────────────────────────────────────────────────────────────────
  1387.  
  1388.  
  1389. | MKLPUTC
  1390.  
  1391. | Name            mklputc - send 1 or 2 characters to the interface
  1392.  
  1393. | C-language
  1394.  
  1395. |   #include "marklin.h"
  1396. |   int mklputc(unsigned int word);
  1397.  
  1398. | QuickBASIC
  1399.  
  1400. |   ' $INCLUDE: 'MARKLIN.INC'
  1401. |   DECLARE FUNCTION MKLPUTC% CDECL (BYVAL WORD%)
  1402.  
  1403. | Description     Send 1 or 2 characters to the Märklin-Interface.  The
  1404. |                 'word' is interpreted as two contiguous characters.  The
  1405. |                 low order byte of the word is sent first, followed by the
  1406. |                 high-order byte.  If the high is not sent when zero.  The
  1407. |                 exception to this rule is: if the first byte is a
  1408. |                 switch-command (ASCII 33 or 34), then the second byte will
  1409. |                 be sent, even when zero.
  1410.  
  1411. |                 This function returns immediately, and does not wait for
  1412. |                 the bytes to be actually transmitted to the interface.  The
  1413. |                 communications task will take care to send the buffered
  1414. |                 character(s) to the Märklin-Interface.
  1415.  
  1416. |                 Coding example to signal speed 8 to loc 27:
  1417.  
  1418. |     rc = mklputc( 27*256 + 8)
  1419.  
  1420. |                 For C-language programs it is highly recommended to use the
  1421. |                 provided macro's for sending 1 or 2 character commands (see
  1422. |                 "Macro Specifications" on page 29).
  1423.  
  1424. |                 Warning: When there is no room in the output buffer, then
  1425. |                 both  characters will be discarded.
  1426.  
  1427. | Return value     0   character(s) are accepted by the driver.
  1428.  
  1429. |                 -1   characters NOT accepted: output discarded.
  1430.  
  1431. | Note: If you use mklputc() while the driver is in 'stop-state' (see
  1432. | "mklstop" on page 25):
  1433.  
  1434. | ■  the OS/2-drivers issue a short high-pitch beep.  With OS/2 2.0 the data
  1435. |    might be buffered and transmitted after mklgo().  This depends on the
  1436. |    used device driver for the COM-port.  COM[xx].SYS does not buffer, but
  1437. |    SIO.SYS does (until its 4KB buffer is full).
  1438. | ■  the DOS-drivers do not generate a warning and will discard the data
  1439. |    until the stop-state is left via a call to mklgo().
  1440.  
  1441.  
  1442.  
  1443.   ───────────────────────────────────────────────────────────────────────────
  1444.                                                            Specifications  21
  1445.  
  1446.   Märklin-Interface driver
  1447.   ───────────────────────────────────────────────────────────────────────────
  1448.  
  1449.  
  1450. | MKLSLEEP
  1451.  
  1452. | Name            mklsleep - give up remainder of timeslice
  1453.  
  1454. | C-language
  1455.  
  1456.  
  1457.  
  1458.  
  1459.  
  1460.  
  1461.  
  1462.  
  1463.  
  1464.  
  1465.  
  1466.  
  1467.  
  1468.  
  1469.  
  1470.  
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.  
  1480.  
  1481.  
  1482.  
  1483.  
  1484.  
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502.  
  1503.  
  1504.   ───────────────────────────────────────────────────────────────────────────
  1505.                                                            Specifications  22
  1506.  
  1507.   Märklin-Interface driver
  1508.   ───────────────────────────────────────────────────────────────────────────
  1509.  
  1510.  
  1511. |   #include "marklin.h"
  1512. |   void mklsleep(void);
  1513.  
  1514. | QuickBASIC
  1515.  
  1516. |   ' $INCLUDE: 'MARKLIN.INC'
  1517. |   DECLARE SUB MKLSLEEP CDECL ()
  1518.  
  1519. | Description     When running a DOS-program in a multitasking environment
  1520. |                 (OS/2, Desqview, Windows, etc.), is is desirable to give
  1521. |                 control back to the multitasker, when the program does not
  1522. |                 need the processor for some time.  This function is
  1523. |                 experimental, it may not work with all multitaskers.
  1524.  
  1525. |                 The use of mklsleep is not absolutely needed with
  1526. |                 pre-emptive multitaskers (like OS/2), and is strongly
  1527. |                 recommended with Windows and DesqView.  In all cases it
  1528. |                 reduces CPU utilisation and leaves processor time for other
  1529. |                 tasks.
  1530.  
  1531. | Return value    Nothing.
  1532.  
  1533.  
  1534.  
  1535. | MKLSTATS
  1536.  
  1537. | Name            mklstats - obtain content of statistics counter.
  1538.  
  1539. | C-language
  1540.  
  1541. |   #include "marklin.h"
  1542. |   long int mklstats(int counter);
  1543.  
  1544. | QuickBASIC
  1545.  
  1546. |   ' $INCLUDE: 'MARKLIN.INC'
  1547. |   DECLARE FUNCTION MKLSTATS& CDECL (BYVAL counter%)
  1548.  
  1549. | Description     Obtain value of an internal counter in MKLAPI for
  1550. |                 statistical purposes.  All counters will be reset to zero
  1551. |                 with mklopen(), and can also be reset by a user program
  1552. |                 through specification of 0 (zero) as parameter.
  1553.  
  1554. |                 To read a counter specify a number in the range: 1 to 6.
  1555. |                 The counters (by number) have the following contents:
  1556.  
  1557. |                 1   Number of accepted commands, including polling-commands
  1558. |                     (commands to read S88's).  Since the we use a buffering
  1559. |                     mechanism, not all of these commands may have been
  1560. |                     transmitted actually!
  1561.  
  1562. |                 2   Number of internally generated commands to read S88's
  1563. |                     ('polls').
  1564.  
  1565.   ───────────────────────────────────────────────────────────────────────────
  1566.                                                            Specifications  23
  1567.  
  1568.   Märklin-Interface driver
  1569.   ───────────────────────────────────────────────────────────────────────────
  1570.  
  1571.  
  1572. |                 3   Number of commands that have been discarded.  Reasons
  1573. |                     may be:
  1574. |                     ■  system is in 'stop-state'
  1575. |                     ■  transmit buffer is full
  1576.  
  1577. |                 4   Number of bytes that were transmitted.  With the
  1578. |                     DOS-driver these bytes are actually transmitted to the
  1579. |                     COM-port, with OS/2 they were accepted by the device
  1580. |                     driver of the COM-port.
  1581.  
  1582. |                 5   Number of received bytes (most likely as result
  1583. |                     commands to read S88's).
  1584.  
  1585. |                 6   Number of bytes that were purged (discarded after first
  1586. |                     being accepted, but before actually being transmitted
  1587. |                     to the Märklin-Interface).  Reasons may be:
  1588. |                     ■  there were commands buffered while mklstop() was
  1589. |                        called
  1590. |                     ■  mklflush() could not complete (timeout)
  1591. |                     ■  commands were in the transmit buffer during a call
  1592. |                        to mklpurge()
  1593.  
  1594. |                     Discarded commands are not counted as 'purged'.
  1595.  
  1596. |                     Note: Purging is not supported in the OS/2-drivers, so
  1597. |                     this counter should remain zero with OS/2 programs.
  1598.  
  1599. |                 Counters in the range 1 to 6 can be considered as permanent
  1600. |                 feature of MKLAPI.  Counters in the range 7 to 15 are
  1601. |                 mainly for debugging purposes.  The description below is
  1602. |                 for information purposes only, do not use them in your
  1603. |                 program, as they may be incorrect, their meaning changed in
  1604. |                 a next version of MKLAPI, or may not be active at all in
  1605. |                 the distributed drivers.
  1606.  
  1607. |                 7   DOS: Number of calls to mklputc while the driver's
  1608. |                     transmit buffer was empty.
  1609.  
  1610. |                 8   DOS: Number of calls to mklputc while the CTS signal is
  1611. |                     'high'.
  1612.  
  1613. |                 9   DOS: Number of calls to mklputc while the hardware
  1614. |                     communications buffer was empty.
  1615.  
  1616. |                 10  DOS: Number of calls to mklputc whereby the first or
  1617. |                     only byte had to be put in the driver's communications
  1618. |                     buffer.
  1619.  
  1620. |                 11  Number of calls to mklputc with a request for 2 bytes
  1621. |                     (second character always buffered).
  1622.  
  1623. |                 12  DOS: Total number of interrupts processed by the
  1624. |                     interrupthandler for the asynchronous communications
  1625.  
  1626.   ───────────────────────────────────────────────────────────────────────────
  1627.                                                            Specifications  24
  1628.  
  1629.   Märklin-Interface driver
  1630.   ───────────────────────────────────────────────────────────────────────────
  1631.  
  1632.  
  1633. |                     port.
  1634.  
  1635. |                 13  DOS: Number of THRE interrupts.
  1636.  
  1637. |                 14  DOS: Number of MSR interrupts (number of CTS signal
  1638. |                     changes).
  1639.  
  1640. |                 15  DOS: Situations with a pending interrupt after a
  1641. |                     previous interrupt was processed.
  1642.  
  1643. |                 Specification of a counter number outside the indicated
  1644. |                 range will give unpredictable results.
  1645.  
  1646. | Return value    Contents of the specified counter (zero after reset).
  1647.  
  1648. | Related functions "mklopen" on page 17
  1649.  
  1650.  
  1651.  
  1652. | MKLSTOP
  1653.  
  1654. | Name            mklstop - send the 'stop' command.
  1655.  
  1656. | C-language
  1657.  
  1658.  
  1659.  
  1660.  
  1661.  
  1662.  
  1663.  
  1664.  
  1665.  
  1666.  
  1667.  
  1668.  
  1669.  
  1670.  
  1671.  
  1672.  
  1673.  
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.  
  1680.  
  1681.  
  1682.  
  1683.  
  1684.  
  1685.  
  1686.  
  1687.   ───────────────────────────────────────────────────────────────────────────
  1688.                                                            Specifications  25
  1689.  
  1690.   Märklin-Interface driver
  1691.   ───────────────────────────────────────────────────────────────────────────
  1692.  
  1693.  
  1694. |   #include "marklin.h"
  1695. |   int  mklstop(void);
  1696.  
  1697. | QuickBASIC
  1698.  
  1699. |   ' $INCLUDE: 'MARKLIN.INC'
  1700. |   DECLARE FUNCTION MKLSTOP% CDECL ()
  1701.  
  1702. | Description     Send the 'stop'-command (ASCII 97) to the Märklin-Interface
  1703. |                 immediately.  If polling was active at the time, it will be
  1704. |                 stopped.
  1705.  
  1706. |                 OS/2: The stop-command is sent via a DevIOCtl operation, so
  1707. |                 it will be sent ahead of data that might be in the transmit
  1708. |                 buffer.  If it could not be sent, for example the Interface
  1709. |                 is not ready, an errorcode is returned.  If OK, this is
  1710. |                 followed by a simulated XOFF command to indicate the
  1711. |                 COM-driver not to send yet buffered data to the
  1712. |                 Märklin-Interface.  The transmit buffer is NOT purged,
  1713. |                 pending output is preserved.  Transmission will can resumed
  1714. |                 after a simulated XON, which will be provided by mklgo().
  1715. |                 When the application continues to send commands, these will
  1716. |                 be discarded.
  1717.  
  1718. |                 DOS: The transmit buffer is purged and the stop-command is
  1719. |                 then sent as regular data.  New output is not accepted
  1720. |                 anymore (it is discarded), until a mklgo() is issued.
  1721.  
  1722. |                 Warning: The 'stop' command could be sent by the mainline
  1723. |                 directly,  but then would bypass the administrative
  1724. |                 functions of the driver.  Any following command received by
  1725. |                 the Märklin-Interface other than 'go' will cause a
  1726. |                 permanent drop of the CTS signal, making the control over
  1727. |                 the railroad from the computer permanently unavailable.
  1728. |                 The only possibility to resume control then is by manually
  1729. |                 hitting the 'go' key on the Märklin Central Unit.
  1730.  
  1731. |                 Note: The timer does not stop with a mklstop().  This may
  1732. |                 cause strange effects from time-dependent calculations in
  1733. |                 your mainline!
  1734.  
  1735. |                 The 'stop' command might interfere with a 2-byte command of
  1736. |                 which the first byte was already transmitted, but the
  1737. |                 second byte not!  In that case the 'stop' would not be
  1738. |                 recognised by the Märklin-Interface.  Two consecutive
  1739. |                 'stop'-commands will prevent the acceptation by the
  1740. |                 Märklin-Interface of any further commands from the
  1741. |                 computer.  To prevent this undesired situations and make
  1742. |                 sure that the 'stop' command will be processed by the
  1743. |                 Märklin-Interface, MKLAPI precedes the 'stop'-command with
  1744. |                 a 'go'-command:
  1745. |                 ■  If there was no command in transmission, then in won't
  1746. |                    harm.
  1747.  
  1748.   ───────────────────────────────────────────────────────────────────────────
  1749.                                                            Specifications  26
  1750.  
  1751.   Märklin-Interface driver
  1752.   ───────────────────────────────────────────────────────────────────────────
  1753.  
  1754.  
  1755. |                 ■  If a 'broken' 2-byte command was in progress, then the
  1756. |                    'go'-byte will be interpreted by the Märklin-Interface
  1757. |                    as the second byte.  This will probably have a different
  1758. |                    effect than was foreseen!
  1759.  
  1760. | Return value    Nothing.
  1761.  
  1762. | Related functions "mklgo" on page 15
  1763.  
  1764.  
  1765.  
  1766. | MKLTIME
  1767.  
  1768. | Name            mkltime - obtain time since program start in milliseconds.
  1769.  
  1770. | C-language
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783.  
  1784.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791.  
  1792.  
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.  
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.   ───────────────────────────────────────────────────────────────────────────
  1810.                                                            Specifications  27
  1811.  
  1812.   Märklin-Interface driver
  1813.   ───────────────────────────────────────────────────────────────────────────
  1814.  
  1815.  
  1816. |   #include "marklin.h"
  1817. |   unsigned long int mkltime(void);
  1818.  
  1819. | QuickBASIC
  1820.  
  1821. |   ' $INCLUDE: 'MARKLIN.INC'
  1822. |   DECLARE FUNCTION MKLTIME& CDECL ()
  1823.  
  1824. | Description     Returns the time in milliseconds after program start since
  1825. |                 it was updated with the last timer 'tick' (OS/2: 31.25
  1826. |                 msecs, DOS: 55 msecs).
  1827.  
  1828. |                 This is a little less accurate than mklmsecs, but consumes
  1829. |                 significantly less processor cycles.
  1830.  
  1831. | Return value    Time in milliseconds after program start.
  1832.  
  1833. | Related functions "mklmsecs" on page 16
  1834.  
  1835.  
  1836.  
  1837. | MKLTRACE
  1838.  
  1839. | Name            mkltrace - start or stop trace
  1840.  
  1841. | C-language
  1842.  
  1843. |   #include "marklin.h"
  1844. |   void mkltrace(short int signal);
  1845.  
  1846. | Description     Start or stop tracing of all data that is being sent to the
  1847. |                 Märklin-Interface and record the information, including a
  1848. |                 timestamp into the file MARKLIN.TRC.
  1849.  
  1850. |                 When signal is NOT zero, then tracing will be started, or
  1851. |                 restarted (old trace data will be discarded in that case).
  1852. |                 When signal is zero the trace is stopped and the trace file
  1853. |                 closed.
  1854.  
  1855. |                 It is my intention to replace this 'on/off' switch with a
  1856. |                 trace level facility (selection of events or data to be
  1857. |                 traced).
  1858.  
  1859. |                 Note: Since a buffered communications interface is used,
  1860. |                 the recording of trace data takes place at the moment the
  1861. |                 data is sent to the buffer.  So the timestamp does not
  1862. |                 reflect the exact transmission time.  Especially at moments
  1863. |                 when Märklin-Interface does not accept data (for example
  1864. |                 when it is transmitting Märklin S88 encoder-data), there
  1865. |                 may be a significant time difference!
  1866.  
  1867. |                 The utility MKLTRFMT.EXE can be used to produce a formatted
  1868. |                 trace report.  All commands are printed hexadecimal and
  1869.  
  1870.   ───────────────────────────────────────────────────────────────────────────
  1871.                                                            Specifications  28
  1872.  
  1873.   Märklin-Interface driver
  1874.   ───────────────────────────────────────────────────────────────────────────
  1875.  
  1876.  
  1877. |                 interpreted.
  1878.  
  1879. |                 See for details about the trace facility and a sample
  1880. |                 output: "Appendix D.  Trace facility" on page 47.
  1881.  
  1882. | Return value    Nothing.
  1883.  
  1884. | Note: Tracing is not provided by the DOS-drivers, but a dummy function is
  1885. | provided for combined OS/2 and OS/2 programs.
  1886.  
  1887.  
  1888.   MACRO SPECIFICATIONS
  1889.  
  1890.   A number of C-language only macro's is provided to make specification of
  1891.   some function-calls a little more simple, and to take care of possibly
  1892.   needed data conversion.
  1893.  
  1894.  
  1895.   MKLPUT1C
  1896.  
  1897.   Name            mklput1c - send a single character to the interface.
  1898.  
  1899.   Usage           #include "marklin.h"
  1900.  
  1901.                   void mklput1c(char);
  1902.  
  1903.   Prototype in    marklin.h
  1904.  
  1905.   Description     Macro to send a single character in the output buffer.  The
  1906.                   macro will expand into a mklputc().
  1907.  
  1908.   Return value    See "mklputc" on page 21.
  1909.  
  1910.  
  1911.  
  1912.   MKLPUT2C
  1913.  
  1914.   Name            mklput2c - send two characters to the interface.
  1915.  
  1916.   Usage           #include "marklin.h"
  1917.  
  1918.                   void mklput2c(char1,char2);
  1919.  
  1920.   Prototype in    marklin.h
  1921.  
  1922.   Description     Macro to send two consecutive character in the output
  1923.                   buffer.  The characters will guaranteed be sent in the
  1924.                   given order, without the risk of intervening characters by
  1925.                   the polling mechanism.  The macro will expand into a
  1926.                   mklputc().
  1927.  
  1928.   Return value    See "mklputc" on page 21.
  1929.  
  1930.  
  1931.   ───────────────────────────────────────────────────────────────────────────
  1932.                                                            Specifications  29
  1933.  
  1934.   Märklin-Interface driver
  1935.   ───────────────────────────────────────────────────────────────────────────
  1936.  
  1937.  
  1938. | USE OF TIMER
  1939.  
  1940. | At program start with mklopen(), the system time is taken as base for the
  1941. | functions mkltime and mklmsecs.  These functions return a value in
  1942. | milliseconds after mklopen().
  1943.  
  1944. | The OS/2-driver uses standard OS/2 facilities, which will allow a precision
  1945. | of about 16 msecs (the time is updated in OS/2 control blocks every 31.25
  1946. | msecs).
  1947.  
  1948. | The DOS-driver uses the system hardware to obtain the system time.  This
  1949. | allows a precision of 1 msec (with the function mklmsecs()).  The function
  1950. | mkltime() gives a precision of about 28 msecs, and takes less machine
  1951. | instructions, which might be sufficient for most purposes.
  1952.  
  1953. | The use of this timer facility provided by the MKLAPI-drivers has the
  1954. | following advantages:
  1955.  
  1956. | ■  It is independent of system (processor) speed and other tasks running in
  1957. |    your system.  Many sample programs use some kind of processing loop to
  1958. |    obtain a 'wait'-period, which might be dependent on processor speed and
  1959. |    'choke' the processor, during which time no other useful work is
  1960. |    possible, or at least it is pretty complicated.
  1961.  
  1962. | ■  It is available with very little processor cycles, so it is not needed
  1963. |    to call a 'universal' compiler-provided timer routine, which are
  1964. |    generally much more cycle consuming.
  1965.  
  1966. | The timer can be used for example for:
  1967.  
  1968. | ■  The application of an event-queue (for timed operations).
  1969. | ■  'Wait'-intervals during without programming a loop.
  1970. | ■  Simulation of train mass (inertia) through gradually increasing or
  1971. |    decreasing loc-speed.
  1972.  
  1973. | If you register this package, you'll receive a sample program which makes
  1974. | use of this feature.
  1975.  
  1976. | It is recommended to use mklsleep() in cyclic operations when running in a
  1977. | multitasking environment sucha as Windows, DesqView or in a DOS-session
  1978. | under OS/2.
  1979.  
  1980.  
  1981. | QUICKBASIC FUNCTION SPECIFICATIONS
  1982.  
  1983. | The functionality of the Märklin-driver for QuickBASIC is the same as for
  1984. | the drivers for C-language.  However the following should be noted:
  1985.  
  1986. | ■  BASIC does not allow the underscore-sign ("_") in names, as is very
  1987. |    common in C-language.  Therefore the FUNCTIONS and DATA fields in the
  1988. |    Märklin-driver for QuickBASIC have been adapted a little to BASIC
  1989. |    conventions since in 0.9 of these drivers.  All other differences are
  1990. |    'under the cover' (but see next item).
  1991.  
  1992.   ───────────────────────────────────────────────────────────────────────────
  1993.                                                            Specifications  30
  1994.  
  1995.   Märklin-Interface driver
  1996.   ───────────────────────────────────────────────────────────────────────────
  1997.  
  1998.  
  1999. | ■  C-language uses by default a different way of parameter passing than
  2000. |    BASIC, PASCAL and some other languages.  But MicroSoft QuickBASIC
  2001. |    compiler 4.5 allows the C-language convention to be used, and the
  2002. |    Märklin-driver for QuickBASIC expects this convention to be used.  This
  2003. |    is reflected in the function specifications in MARKLIN.INC.  If you use
  2004. |    the MARKLIN.INC file (strongly recommended!), then you won't have to
  2005. |    worry about these conventions.
  2006.  
  2007.  
  2008.  
  2009.   ERRORS AND SIGNALS
  2010.  
  2011.   The driver is designed not to disturb your screen with error-messages.
  2012.   Therefore audiable signals are used to indicate unexpected problems.  The
  2013.   following list is valid for the OS/2-driver only:
  2014.  
  2015.   very high pitch, long 4000 Hz, 300 msec: Märklin-Interface seems to be
  2016.               long-term blocked.  The transmit task (mklputc routine) is
  2017.               waiting for a previous request to finish, but for some reason
  2018.               it doesn't.  Check the 'stop'-light on the Märklin Central Unit
  2019.               if a stop-condition is the cause (manually set, or electrical
  2020.               problem).
  2021.  
  2022.   very high pitch, short 4000 Hz, 20 msec: Märklin-Interface  The driver is
  2023.               in stop-state, but some routine tries to send commands, which
  2024.               are discarded.
  2025.  
  2026.   high pitch, short 2000 Hz, 20 msec: A command-transmission did not finish
  2027.               within the normal time.  Too many commands may be queued, maybe
  2028.               because of a program loop.
  2029.  
  2030.   medium pitch, short 1000 Hz, 20 msec: a communications error occurred
  2031.               (OS/2).  Debugging information is sent to STDERR (which you
  2032.               might have redirected to a log-file to prevent disturbance of
  2033.               your screen).
  2034.  
  2035.   The DOS-drivers do not produce audiable signals.
  2036.  
  2037.  
  2038.  
  2039.  
  2040.  
  2041.  
  2042.  
  2043.  
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049.  
  2050.  
  2051.  
  2052.  
  2053.   ───────────────────────────────────────────────────────────────────────────
  2054.                                                            Specifications  31
  2055.  
  2056.   Märklin-Interface driver
  2057.   ───────────────────────────────────────────────────────────────────────────
  2058.  
  2059.  
  2060.   INSTALLATION
  2061.  
  2062.  
  2063.  
  2064.   APPLICATION DEVELOPMENT CONSIDERATIONS
  2065.  
  2066. | This MKLAPI is a program development tool with a C-language or QuickBASIC
  2067.   compiler.  You need MARKLIN.H (MARKLIN.INC for BASIC) at compile-time and
  2068.   one of the .OBJ files at LINK-time.  It is an addition to the compiler and
  2069.   possibly other toolkits you may have for other purposes.
  2070.  
  2071.  
  2072.   C-COMPILER CONSIDERATIONS
  2073.  
  2074.   The following compiler properties apply.
  2075.  
  2076.   ■  The file MARKLIN.H must be #included in the program that references the
  2077.      driver routines (you can use the same header-file for OS/2 and DOS).
  2078.  
  2079. | ■  Memory model: OS/2: LARGE; DOS: SMALL or LARGE (your choice)
  2080.  
  2081. | ■  Calling conventions: C
  2082.  
  2083. | ■  OS/2: The MT\INCLUDE's should be used with IBM C/2 compiler 1.1, since
  2084. |    the driver is multithreaded.  With MicroSoft C-compiler 6.00a the '/MT'
  2085. |    parameter is sufficient, and with IBM C SET/2 compiler '/Gm' should be
  2086. |    specified among other parameters.
  2087.  
  2088.   ■  Generate underbars: On (Turbo-C option).
  2089.  
  2090.   Other compiler options are (probably) not of influence on the use of the
  2091. | Märklin-driver.
  2092.  
  2093.  
  2094. | MICROSOFT QUICKBASIC COMPILER 4.5 CONSIDERATIONS
  2095.  
  2096. | The QuickBASIC compiler is needed to create an object deck of your BASIC
  2097. | program.  This OBJect file is combined with LMARKLIN.OBJ file as provided
  2098. | by this MKLAPI package to build an EXE-file with the LINK utility.
  2099.  
  2100. | ■  Calling conventions: C (DECLARE SUB|FUNCTION xxx CDECL ... etc)
  2101.  
  2102.  
  2103.  
  2104.   BUILDING AN EXE-FILE
  2105.  
  2106. | One of the OBJect files should be included in the link-step with your own
  2107. | OBJect file(s).  I prefer to Compile and LINK with the help of the (N)MAKE
  2108. | utility.
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.   ───────────────────────────────────────────────────────────────────────────
  2115.                                                              Installation  32
  2116.  
  2117.   Märklin-Interface driver
  2118.   ───────────────────────────────────────────────────────────────────────────
  2119.  
  2120.  
  2121. | C-LANGUAGE AND DOS
  2122.  
  2123. | For the DOS sample application ("TRAIN") I use the following MAKE-file:
  2124.  
  2125. | ┌─────────────────────────────────────────────────────────────────────────┐
  2126. | │                                                                         │
  2127. | │                                                                         │
  2128. | │ #                                                                       │
  2129. | │ # MAKE TRAIN: Marklin Digital Train Control program (DOS version)       │
  2130. | │ #             - SMARKLIN.OBJ and LMARKLIN.OBJ generated                 │
  2131. | │ #             - SMALL memory model version user for train.exe           │
  2132. | │ #                                                                       │
  2133. | │                                                                         │
  2134. | │ MDL=L                                                                   │
  2135. | │ CL=-c -Zl -Zp -G0 -W3 -AL -DDOS -Fotrain.obj -Ot                        │
  2136. | │ LK=/NOD /PACKC:65500 /ST:4000                                           │
  2137. | │                                                                         │
  2138. | │ train.exe: train.obj smarklin.obj lmarklin.obj                          │
  2139. | │ # LINK  train+$(MDL)marklin, train $(LK), nul, $(MDL)LIBCER;            │
  2140. | │   LINK  train+$(MDL)marklin, train $(LK), nul, $(MDL)LIBCER;            │
  2141. | │                                                                         │
  2142. | │ train.obj: train2.c train.h train.mak attrib.h attrib2.h common.h\      │
  2143. | │            matrix.h marklin.h                                           │
  2144. | │   CL $(CL) train2.c                                                     │
  2145. | │                                                                         │
  2146. | │ smarklin.obj: marklin.asm marklin.h train.mak                           │
  2147. | │   MASM -Dsmall marklin.asm,smarklin;                                    │
  2148. | │                                                                         │
  2149. | │ lmarklin.obj: marklin.asm marklin.h train.mak                           │
  2150. | │   MASM -Dlarge marklin.asm,lmarklin;                                    │
  2151. | │                                                                         │
  2152. | │                                                                         │
  2153. | └─────────────────────────────────────────────────────────────────────────┘
  2154.  
  2155. | Note: It contains switches to control the use of large or small memory
  2156. | models.
  2157.  
  2158.  
  2159. | C-LANGUAGE AND BASIC
  2160.  
  2161. | For a simple test-program in QuickBASIC I use the following batch-file:
  2162.  
  2163. | ┌─────────────────────────────────────────────────────────────────────────┐
  2164. | │                                                                         │
  2165. | │                                                                         │
  2166. | │ rem                                                                     │
  2167. | │ rem Build Marklin Digital Train Control program (DOS QuickBASIC version)│
  2168. | │ rem  - LMARKLIN.OBJ copied from \C2\MARKLIN subdirectory                │
  2169. | │ rem                                                                     │
  2170. | │ BC    train /A /C:1 /O /S;                                              │
  2171. | │ if errorlevel 0  LINK  train+\c2\marklin\lmarklin,/NOE,train;           │
  2172. | │                                                                         │
  2173. | └─────────────────────────────────────────────────────────────────────────┘
  2174.  
  2175.   ───────────────────────────────────────────────────────────────────────────
  2176.                                                              Installation  33
  2177.  
  2178.   Märklin-Interface driver
  2179.   ───────────────────────────────────────────────────────────────────────────
  2180.  
  2181.  
  2182. | Note: With MicroSoft QuickBASIC compiler 4.5 the LMARKLIN.OBJ need to be
  2183. | included in the link.  models.
  2184.  
  2185.  
  2186. | C-LANGUAGE AND OS2 1.3
  2187.  
  2188. | For the 16-bits OS/2-sample application ("TRAIN2") I use the following
  2189. | MAKE-file for MicroSoft C-compiler 6.00a and IBM OS/2 Program Development
  2190. | Toolkit 1.2/1.3:
  2191.  
  2192. | ┌─────────────────────────────────────────────────────────────────────────┐
  2193. | │                                                                         │
  2194. | │                                                                         │
  2195. | │ #                                                                       │
  2196. | │ # MAKE TREIN: Marklin Digital Train Control                             │
  2197. | │ #                                                                       │
  2198. | │ # To be used with MicroSoft C-compiler 6.00a                            │
  2199. | │ #                                                                       │
  2200. | │ # With IBM C/2 1.1 compiler specify '__IBMC2__' compiler option         │
  2201. | │ #                                                                       │
  2202. | │ # 'OS2' compiler variable needed for OS/2 object of TRAIN2!             │
  2203. | │ #                                                                       │
  2204. | │                                                                         │
  2205. | │ CL=-c -Zp -Zl -W3 -MT -DOS2                                             │
  2206. | │ LK=/A:16 /PACKC:65000 /NOI /NOD                                         │
  2207. | │ L1=LLIBCMT OS2                                                          │
  2208. | │                                                                         │
  2209. | │ train2.exe: train2.obj marklin2.obj train2.def                          │
  2210. | │    LINK train2+marklin2, $@ $(LK), NUL, $(L1), train2.def               │
  2211. | │                                                                         │
  2212. | │ train2.obj: train2.c train2.h attrib2.h marklin.h common.h matrix.h     │
  2213. | │    CL $(CL) train2.c                                                    │
  2214. | │                                                                         │
  2215. | │ marklin2.obj: marklin2.c                                                │
  2216. | │    CL $(CL) marklin2.c                                                  │
  2217. | │                                                                         │
  2218. | │                                                                         │
  2219. | └─────────────────────────────────────────────────────────────────────────┘
  2220.  
  2221. | The contents of the corresponding LINK .DEF-file are:
  2222.  
  2223. | ┌─────────────────────────────────────────────────────────────────────────┐
  2224. | │                                                                         │
  2225. | │                                                                         │
  2226. | │ ;                                                                       │
  2227. | │ ;******* Marklin Train Control Program  Definition File (.DEF) ******** │
  2228. | │ ;        For: 1)  16-bit version for OS/2 1.3 and MS C-compiler         │
  2229. | │ ;             2)  32-bit version for OS/2 2.0 and IBM C Set/2 compiler  │
  2230. | │                                                                         │
  2231. | │ NAME    TRAIN2  WINDOWCOMPAT                                            │
  2232. | │                                                                         │
  2233. | │ DESCRIPTION 'Marklin Train Control. Copyright (1991,93) Rob Hamerling'  │
  2234. | │ PROTMODE                                                                │
  2235.  
  2236.   ───────────────────────────────────────────────────────────────────────────
  2237.                                                              Installation  34
  2238.  
  2239.   Märklin-Interface driver
  2240.   ───────────────────────────────────────────────────────────────────────────
  2241.  
  2242.  
  2243. | │ HEAPSIZE   4096                                                         │
  2244. | │ STACKSIZE  8192                                                         │
  2245. | │                                                                         │
  2246. | └─────────────────────────────────────────────────────────────────────────┘
  2247.  
  2248.  
  2249.  
  2250. | C-LANGUAGE AND OS2 2.0+
  2251.  
  2252. | For the 32-bits OS/2-sample application ("TRAIN3"), the following MAKE-file
  2253. | is appropriate for IBM C SET/2 compiler and IBM OS/2 Program Development
  2254. | Toolkit 2.0:
  2255.  
  2256. | ┌─────────────────────────────────────────────────────────────────────────┐
  2257. | │                                                                         │
  2258. | │                                                                         │
  2259. | │ #                                                                       │
  2260. | │ # MAKE TREIN: Marklin Digital Train Control program                     │
  2261. | │ #                                                                       │
  2262. | │                                                                         │
  2263. | │ CL=/c /G3 /Gd+ /Gm+ /MS /Re /Se /Sm /Ss -DOS2                           │
  2264. | │ LK=/NOI /PACKC:65500 /ALIGN:4 /BASE:0x10000 /EXEPACK                    │
  2265. | │                                                                         │
  2266. | │ train3.exe: train3.obj marklin3.obj                                     │
  2267. | │    link386 $**, $@ $(LK), NUL, , train2.def                             │
  2268. | │                                                                         │
  2269. | │ train3.obj: train2.c                                                    │
  2270. | │    icc $(CL) /Fotrain3.obj train2.c                                     │
  2271. | │                                                                         │
  2272. | │ marklin3.obj: marklin2.c marklin.h                                      │
  2273. | │    icc $(CL) /Fomarklin3.obj marklin2.c                                 │
  2274. | │                                                                         │
  2275. | │                                                                         │
  2276. | └─────────────────────────────────────────────────────────────────────────┘
  2277.  
  2278. | Note: The same .DEF-file is used as for the 16-bit version.
  2279.  
  2280.  
  2281. | STORAGE AND PERFORMANCE
  2282.  
  2283. | There is yet not much to say about storage and performance of the driver.
  2284. | It is highly optimised code, and probably only a minor part of the 'real'
  2285. | railroad control program.
  2286.  
  2287.  
  2288.   MEMORY UTILISATION
  2289.  
  2290.   It is difficult to say how many storage is occupied by the OS/2-version of
  2291.   the Märklin-driver.
  2292.  
  2293.   The DOS-version requires about 4K bytes of storage.
  2294.  
  2295.  
  2296.  
  2297.   ───────────────────────────────────────────────────────────────────────────
  2298.                                                              Installation  35
  2299.  
  2300.   Märklin-Interface driver
  2301.   ───────────────────────────────────────────────────────────────────────────
  2302.  
  2303.  
  2304.   PROCESSOR UTILISATION
  2305.  
  2306.   You might be curious about the cycles that will be consumed by the polling
  2307.   task.  I've done some measurements under OS/2 version 1.3 with the sample
  2308.   program TRAIN2.  On an 8 Mhz AT (80286) the polling takes between 10% and
  2309.   12% of the processor time (difference in processor utilisation between
  2310.   polling ON and OFF).  This number is practically independent of the number
  2311.   of Märklin S88 encoder's that are specified for polling, but the polling
  2312.   frequency is also lower!
  2313.  
  2314.  
  2315.   COMMENTS, REMARKS, BUG-REPORTS
  2316.  
  2317.   If there are bugs, requirements or questions about this Märklin-driver, the
  2318.   documentation or the sample program (that you get when you register),
  2319.   please send me a message through the FIDO network.  You can find my name
  2320.   and node-(point)-number in the introduction of this document.
  2321.  
  2322.   Enjoy and good luck with your program development!  May this driver lead to
  2323.   a very attractive and succesful model railroad control program!
  2324.  
  2325.   Do not 'forget' to register!
  2326.  
  2327.  
  2328.  
  2329.  
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335.  
  2336.  
  2337.  
  2338.  
  2339.  
  2340.  
  2341.  
  2342.  
  2343.  
  2344.  
  2345.  
  2346.  
  2347.  
  2348.  
  2349.  
  2350.  
  2351.  
  2352.  
  2353.  
  2354.  
  2355.  
  2356.  
  2357.  
  2358.   ───────────────────────────────────────────────────────────────────────────
  2359.                                                              Installation  36
  2360.  
  2361.   Märklin-Interface driver
  2362.   ───────────────────────────────────────────────────────────────────────────
  2363.  
  2364.  
  2365.   APPENDIX A.  SUMMARY OF CHANGES
  2366.  
  2367.   0.7   First 'official' release: June 1992
  2368.  
  2369.   0.8   released: October 1992
  2370.         ■  The time-base value in mkltime has been changed from 55 msec to 1
  2371.            msec! (updating of mkltime still on timer-tick basis: once per 55
  2372.            msecs in DOS, once per 31.25 msecs in OS/2).
  2373.         ■  DOS: High precision timer routine added: mklmsecs().  This gives
  2374.            the period since line to opening of communication with
  2375.            Märklin-Interface  with 1 msec accuracy.
  2376.         ■  OS/2: Trace facility added (see also "Appendix D.  Trace facility"
  2377.            on page 47), start and stop of trace via procedure call
  2378.            mkltrace().  Output to and input from the Märklin-Interface is
  2379.            traced.  A trace-file formatting utility (MKLTRFMT.EXE) is added
  2380.            to package.  I have tried to add this trace facility also in the
  2381.            DOS driver, but I did not cucceed so far.  It is rather
  2382.            complicated to use DOS facilities during interrupt handling
  2383.            (tracing must be located in the com-port and timer interrupt
  2384.            routines).
  2385.         ■  A procedure 'mklsleep' added to make your DOS-program 'friendly'
  2386.            for some popular multitasking environments (such DOS-box of OS/2,
  2387.            Desqview, Windows).
  2388.         ■  DOS: mklflush times out after 3 seconds when transmit buffer could
  2389.            not be flushed.
  2390.         ■  Some bugs fixed:
  2391.            -  mklflush() of OS/2 version watched the INput in stead of OUTput
  2392.               queue.
  2393.            -  DOS: DTR and RTS now turned off before finishing program.
  2394.  
  2395.   0.9   released: March 1993
  2396.         ■  A 32-bits driver for OS/2 2.0+ (MARKLIN3.OBJ) has been added, with
  2397.            same functionality as MARKLIN2, including the new features below!
  2398.         ■  'MKLAPI' now also useable by programs translated with the
  2399.            MicroSoft QuickBASIC compiler 4.5.  Since QuickBASIC does not
  2400.            allow underscores in names, all externally used names have been
  2401.            changed, for example: mklopen() is now called mklopen().  The
  2402.            C-language calling convention must be specified in the source (see
  2403.            MARKLIN.INC), and the file LMARKLIN.OBJ should be used with LINK.
  2404.            All function specifications have been changed, and additions made
  2405.            for program development with MicroSoft QuickBASIC compiler 4.5.
  2406.         ■  mkltime() is not anymore an external variable, but a function
  2407.            returning the value of the time, expressed in milliseconds, but
  2408.            with the precision of the timer tick.
  2409.         ■  mklmsecs() now also a function returning the time, but in exact
  2410.            milliseconds (DOS only).
  2411.         ■  With the OS/2 drivers, the transmissions in STOP-state (after
  2412.            mklstop) may now be buffered in stead of discarded (until buffer
  2413.            full, then discarded).  This depends on the COM.SYS device
  2414.            drivers, or replacements thereof.
  2415.         ■  After the first mklstop subsequent calls of mklstop are ignored
  2416.            and nothing sent to the Märklin-Interface until mklgo has been
  2417.            called.
  2418.  
  2419.   ───────────────────────────────────────────────────────────────────────────
  2420.                                           Appendix A.  Summary of changes  37
  2421.  
  2422.   Märklin-Interface driver
  2423.   ───────────────────────────────────────────────────────────────────────────
  2424.  
  2425.  
  2426.         ■  mklstop() and mklgo() now give a returncode (0 = OK, otherwise a
  2427.            transmission problem exists).
  2428.         ■  Simple Switchpoint test program (incl c-source) added to MKLAPI
  2429.            package.
  2430.         ■  Added counters for and a function mklstats() for statistical
  2431.            purposes and debugging.
  2432.         ■  Polling optimised: a single 'reset after read S88' (192) is issued
  2433.            after mklpoll() and mklgo(), subsequently only 'read group of n
  2434.            S88s' (128+n) commands are sent periodically (previously both
  2435.            commands were sent after each interval).
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.  
  2444.  
  2445.  
  2446.  
  2447.  
  2448.  
  2449.  
  2450.  
  2451.  
  2452.  
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.  
  2460.  
  2461.  
  2462.  
  2463.  
  2464.  
  2465.  
  2466.  
  2467.  
  2468.  
  2469.  
  2470.  
  2471.  
  2472.  
  2473.  
  2474.  
  2475.  
  2476.  
  2477.  
  2478.  
  2479.  
  2480.   ───────────────────────────────────────────────────────────────────────────
  2481.                                           Appendix A.  Summary of changes  38
  2482.  
  2483.   Märklin-Interface driver
  2484.   ───────────────────────────────────────────────────────────────────────────
  2485.  
  2486.  
  2487.   APPENDIX B.  MKLAPI INTERNALS
  2488.  
  2489.   This appendix describes a number of design arguments for this driver and
  2490.   explains decisions where a choice had to be made.
  2491.  
  2492.  
  2493.   COMMUNICATIONS INTERFACE SPECIFICATION
  2494.  
  2495. | The Märklin-Interface contains a device driver level communication facility
  2496. | with between computer and Märklin-Interface, but with a rather high level
  2497. | interface for the application programmer.  It contains many basic
  2498. | functions, that otherwise have to be programmed yourself.  However, it
  2499. | enforces a specific organisation of your program and has some limitations.
  2500.  
  2501. | Some of the internals of the communications task are briefly explained to
  2502. | show why it works as it works now, and may prevent questions.  On the other
  2503. | hand, it may trigger suggestions for changes!  Feel free to go in
  2504. | discussion with me!
  2505.  
  2506. | Wiring          Only the Read (RD), write (TD) and Clear-to-Send (CTS) lead
  2507. |                 are connected.  Thus using DTR and RTS from the computer
  2508. |                 will have no effect of any kind and obviously DSR and DCD
  2509. |                 (sometimes also called CD or RLSD) will not be used by the
  2510. |                 Märklin-Interface  Nevertheless DTR and RTS are set by the
  2511. |                 driver with mklopen().  This allows for the use of a
  2512. |                 break-out box and/or another computer in stead of the
  2513. |                 Märklin-Interface for debugging of your program (since a PC
  2514. |                 commmunications program usually needs these leads to be
  2515. |                 active).  The driver itself works properly without the DSR
  2516. |                 and DCD leads.
  2517.  
  2518. | Speed           The Märklin-Interface allows only 2400 bps, and 8-bits
  2519. |                 data, NO parity, and 2 stop bits.  These are the built-in
  2520. |                 defaults of the driver, however a different speed can be
  2521. |                 specified at open-time (might be useful for test and
  2522. |                 debugging).
  2523.  
  2524. | FIFO            So called FIFO hardware buffering, provided by the newer
  2525. |                 UART-chips (such as 16550 AFN) on asynchronous
  2526. |                 communication ports is handled as follows by the drivers:
  2527. |                 ■  The DOS-driver does not actively support FIFO-mode, but
  2528. |                    FIFO-support is in plan.
  2529. |                 ■  The OS/2-MKLAPI uses the facilities of the device driver
  2530. |                    COM[xx].SYS for operation of the COM-port.  When FIFO is
  2531. |                    is active for the COM-port before opening, it is left
  2532. |                    active and uses this feature.  Use the MODE-command to
  2533. |                    control this feature.
  2534.  
  2535.                   FIFO-mode may not provide a considerable improvement:
  2536.                   ■  The Märklin-Interface operates strictly half-duplex, it
  2537. |                    is either in receive mode, or in transmit mode.  During
  2538. |                    data transfer (either way) CTS is dropped while
  2539. |                    transmitting each command-byte and may remain low for a
  2540.  
  2541.   ───────────────────────────────────────────────────────────────────────────
  2542.                                             Appendix B.  MKLAPI Internals  39
  2543.  
  2544.   Märklin-Interface driver
  2545.   ───────────────────────────────────────────────────────────────────────────
  2546.  
  2547.  
  2548. |                    'considerable' time while command interpretation is in
  2549. |                    progress and S88-positions are being sent back to the
  2550. |                    computer.  This does not suit very well with the FIFO
  2551. |                    for transmit buffering.  It might be useful for receive,
  2552. |                    since in many cases at least 2 bytes are received per
  2553. |                    S88. being read.  The support for this is in
  2554. |                    consideration.
  2555. |                 ■  Since the speed is 2400 bps, most systems can easily
  2556. |                    keep up with the non-buffered mode of operation.  The
  2557. |                    highly effective interrupt handler of the DOS-driver may
  2558. |                    make the netto effect of reduced CPU-cycles for
  2559. |                    interrupt handling only minimal.
  2560.  
  2561. |                 But FIFO-mode may be helpful in a multitasking environment.
  2562. |                 Use the MODE command with BUFFER=ON, to activate it, when
  2563. |                 desired.
  2564.  
  2565.   Output flow control The CTS signal is dropped by Märklin-Interface during
  2566.                   data transfer (during receive and transmit: the
  2567.                   Märklin-Interface is strictly half-duplex).  The CTS signal
  2568.                   is used for 'hardware output flow control' from the
  2569.                   computer.  So the transmit routines will not send data when
  2570.                   CTS is not high, but will automatically resume transmission
  2571.                   when CTS rises and the buffer contains any data to
  2572.                   transmit.
  2573.  
  2574.                   DOS Although not strictly needed, the DOS-version of the
  2575.                   Märklin-driver has the transmit interrupt (THRE) active to
  2576.                   be able to run the driver against a full-duplex interface
  2577.                   (with continuous CTS), such as another PC with a diagnostic
  2578.                   communications program.  The transmit interrupt uses the
  2579.                   same code as the MSR interrupt.
  2580.  
  2581.                   For initial testing of programs without actually running a
  2582.                   model railroad, you could use a 'wrap-plug' to partially
  2583.                   simulate the Märklin-Interface.  The RTS signal (raised by
  2584.                   the driver) is feeded back to CTS, so the driver is always
  2585. |                 able transmit.
  2586.  
  2587. |                 If also send and receive (genarlly pins 2 and 3) leads are
  2588. |                 wrapped back, then the transmitted data is treated as S88
  2589. |                 response.  This may cause
  2590.  
  2591.   Input flow control There is no form of input flow control allowed by the
  2592.                   Märklin-Interface: there is no way to signal the
  2593.                   Märklin-Interface to stop sending.  This will not be a
  2594.                   problem for the driver, since there is enough buffering and
  2595.                   CPU-power to process the low volume input in time.
  2596.  
  2597.   XON/XOFF flow control Not used.  This type of flow-control is not supported
  2598.                   by the Märklin-Interface, since the commands for the
  2599.                   Märklin-Interface may contain these characters!
  2600.  
  2601.  
  2602.   ───────────────────────────────────────────────────────────────────────────
  2603.                                             Appendix B.  MKLAPI Internals  40
  2604.  
  2605.   Märklin-Interface driver
  2606.   ───────────────────────────────────────────────────────────────────────────
  2607.  
  2608.  
  2609.                   OS/2: The standard COM[xx].SYS of OS/2 allows simulated
  2610.                   XON/XOFF.  A DosDevIOCtl-'XOFF' is issued to stop
  2611.                   transmitting buffered data when a 'stop'-command has to be
  2612.                   transmitted.  A DosDevIOCtl-'XON' is issued when a
  2613.                   subsequent 'go'-command is issued.
  2614.  
  2615.   Null stripping  The OS/2 COM[xx].SYS allows null stripping.  There are at
  2616.                   least 2 reasons for this feature not to be activated:
  2617.                   ■  Märklin S88 encoder's may respond with all bits zero
  2618.                   ■  Switch 256 is addressed as ASCII 0.
  2619.  
  2620.   Command parsing The driver does not interpret the data it sends to the
  2621.                   Märklin-Interface.  It means that it is completely the
  2622.                   responsibility of the mainline to ensure proper command
  2623.                   sequences.
  2624.  
  2625.                   Note: The driver does not send automatically a
  2626.                   switch-'relax' command (ASCII 32) after a switch command
  2627.                   (ASCII 33 or 34)!  You may write a shell for Märklin
  2628.                   command syntax checking.
  2629.  
  2630.  
  2631.  
  2632.   PROBLEMS WITH OS/2 COM[XX].SYS
  2633.  
  2634.   The Com-port driver of some versions of OS/2 for non-PS/2 machines
  2635.   (COM01.SYS) does have some known problems, such as:
  2636.  
  2637.   ■  READ and WRITE timout specifications cannot be changed from the built-in
  2638.      default of 1 minute.
  2639.  
  2640.   When encountering this kind of problems, I could recommend Gerry Rozema's
  2641.   replacement driver for AT-type machines (COM16540.SYS, or COM16550.SYS, as
  2642. | appropriate for your system's COM-port).  For OS/2 2.0 there is also a
  2643. | driver SIO.SYS by Ray Gwinn, that might be useful when having problems with
  2644. | the standard OS/2 2.0 drivers.
  2645.  
  2646.   These alternative drivers are available on Bulletin Boards such as
  2647.   PC-Square in The Netherlands (FIDO node 2:512/4, telephone 31.79.424107).
  2648.  
  2649.  
  2650.  
  2651.  
  2652.  
  2653.  
  2654.  
  2655.  
  2656.  
  2657.  
  2658.  
  2659.  
  2660.  
  2661.  
  2662.  
  2663.   ───────────────────────────────────────────────────────────────────────────
  2664.                                             Appendix B.  MKLAPI Internals  41
  2665.  
  2666.   Märklin-Interface driver
  2667.   ───────────────────────────────────────────────────────────────────────────
  2668.  
  2669.  
  2670.   APPENDIX C.  DESIGN NOTES AND TIPS
  2671.  
  2672.  
  2673.  
  2674.   POLLING FACILITY
  2675.  
  2676.  
  2677.  
  2678.   MULTITASKING
  2679.  
  2680.   There are many situations in real-time programming, where you want the
  2681.   system to do something for you, while in the meantime you would like to do
  2682.   something else in the mainline (before the first piece of program
  2683.   completes).
  2684.  
  2685.   An example of this is reading sensor boxes.  While you have to wait for the
  2686.   response of the Märklin S88 encoder, you might want to update your screen,
  2687.   read data from disk, or process keyboard input.  In many sample programs
  2688.   that I have seen, the wait is frequently done in the form of a short loop
  2689.   (a for- or while-statement).  This means that the processor is working, in
  2690.   fact consuming cycles, while you cannot do anything (unless you make a more
  2691.   'complicated' loop).  And in many cases you have to experiment with this
  2692.   loop to get the needed wait-interval (not too long and not too short).
  2693.   Running the same program on a machine with a different processor-speed,
  2694.   requires a change in the loop.
  2695.  
  2696.   A solution for this is to have multiple programs to run simultaneously.
  2697.   Executing multiple programs (tasks) in parallel is called multi-tasking.
  2698.   Since we are generally dealing with a single micro processor, the tasks are
  2699.   simultaneaously present in memory, but only 1 of them is actually
  2700.   processing.  There must be some mechanism to switch the processor between
  2701.   the tasks.
  2702.  
  2703.   Some operating environments have standard facilities for this (OS/2,
  2704.   Windows), but DOS doesn't.  Under DOS you have to do it yourself.  By
  2705.   intercepting hardware interupts, or the timer-tick interrupt it is possible
  2706.   to implement a kind of task-switching.
  2707.  
  2708.   The polling mechanism in the Märklin-driver is a form of multi-tasking.
  2709.   For OS/2 it uses the standard OS/2 facilities (called multi-threading), for
  2710.   DOS it uses the system timer to execute periodical actions independently
  2711.   from the main-program, and also the hardware interrupts of the asynchronous
  2712.   communications port to perform some communications work.  So in fact there
  2713.   are two 'extra' tasks in the polling mechanism:
  2714.  
  2715.   ■  Periodically send read-commands to the Märklin-Interface.
  2716.   ■  Receive the responses and put them in the appropriate place in the
  2717.      sensor-array.
  2718.  
  2719.   Although you don't have to bother about the polling mechanism, it does have
  2720.   some influence on the design of your railroad control program.  These
  2721.   practical aspects are explained below.
  2722.  
  2723.  
  2724.   ───────────────────────────────────────────────────────────────────────────
  2725.                                        Appendix C.  Design Notes and Tips  42
  2726.  
  2727.   Märklin-Interface driver
  2728.   ───────────────────────────────────────────────────────────────────────────
  2729.  
  2730.  
  2731.   BACKGROUND POLLING TASK
  2732.  
  2733.   The driver generates read-sensor commands in the following way:
  2734.  
  2735.   1. After polling is activated (with mklpoll(s)), periodically a sensor-read
  2736.      command is transmitted.
  2737.  
  2738.   2. The receive-part of the communications task is signalled that a response
  2739.      from the Märklin-Interface should be expected, and for which S88 the
  2740.      input is destined.  The receive continues (or a read is re-issued) as
  2741.      long as not all expected input is received, or an unexpected long time
  2742.      had to be waited.
  2743.  
  2744.   3. After processing the response, the system waits some time before issuing
  2745.      a new poll.
  2746.  
  2747.   4. Even if for some reason the previous poll did not finish within about
  2748.      one sec, a new poll-command is issued (poll timeout).
  2749.  
  2750.   5. If the transmit routine is in use by the mainline program (such as for
  2751.      sending train-commands), polling is suspended for a short while (shorter
  2752.      than the normal polling interval).  After such 'slow-poll' situation,
  2753.      normal polling intervals are respected again.
  2754.  
  2755.   The Märklin-Interface documentation indicates that the average time to read
  2756.   the last poll-response is between 45 and 300 milliseconds, depending on how
  2757.   many Märklin S88 encoder's are being read.  The polling task in the driver
  2758.   uses a poll interval (time between receiving the last data and sending the
  2759.   next poll-command) of about 100 msecs.
  2760.  
  2761.   From 'life'-tests I have concluded:
  2762.  
  2763.   ■  The poll implemented interval is short enough to signal occupied
  2764.      isolated sections of the railroad in time for most cases.
  2765.  
  2766.   ■  The poll interval is long enough to allow sending of many commands from
  2767.      the mainline between the polls.  To make this sure I also built a
  2768.      priority mechanism in the polling routine: it waits with generating a
  2769.      poll if another program uses mklputc() routine!
  2770.  
  2771.   ■  The frequency of the polls is low enough to ensure that not all CPU
  2772.      cycles are spent on polling, in stead of 'real' work.
  2773.  
  2774. | Polling is implemented as follows:
  2775.  
  2776. | 1. After calling mklpoll() of mklgo() with a non-zero parametervalue a
  2777. |    '192' byte is transmitted, meaning that the Interface will RESET the
  2778. |    bits with next read-sensor commands.
  2779.  
  2780. | 2. Periodically a '128 + MAXSENSOR' byte, meaning that the Interface will
  2781. |    report a group of sensors, up till the limit that was specified with the
  2782. |    (latest) mklpoll() of mklgo().
  2783.  
  2784.  
  2785.   ───────────────────────────────────────────────────────────────────────────
  2786.                                        Appendix C.  Design Notes and Tips  43
  2787.  
  2788.   Märklin-Interface driver
  2789.   ───────────────────────────────────────────────────────────────────────────
  2790.  
  2791.  
  2792.   Note: This mechanism is suitable for detection of occupied railroad
  2793.   sections, whereby the sensor-bit is set again by the train (after being
  2794.   read and reset by the Märklin-Interface) for example in the case of
  2795.   contact-rails or isolated sections.  As long as there is a pair of wheels
  2796.   making contact, the sensor-bit is reported as 'set' (1).
  2797.  
  2798.   You have to be careful with specifying more Märklin S88 encoder boxes in
  2799.   the mklpoll() than you really have in your model railroad yard.
  2800.  
  2801.   ■  It is not useful, since the Märklin-Interface will return all zeroes for
  2802.      not-connected Märklin S88 encoder's.
  2803.  
  2804.   ■  During the time the Märklin-Interface sends the responses to the
  2805.      computer, no commands are accepted by the Interface.
  2806.  
  2807.   So specifying more Märklin S88 encoders than really active will unnecessary
  2808.   downgrade the responsiveness of your program.  You might decide to stop
  2809.   polling during processor-intensive work, or not to use polling at all.
  2810.  
  2811.   Note:
  2812.  
  2813.   ■  This driver does not yet support physically reading of individual
  2814.      Märklin S88 encoders.
  2815.   ■  It is also not possible to use polling with no-reset (command 128 in
  2816.      stead of 192).
  2817.   ■  The driver will allow read-commands from the mainline, but will
  2818.      intercept the response and not return them to the mainline!  It
  2819.      interpretes all responses if were caused by its own polling activity.
  2820.      If polling is active the driver stores the input in the sensor array.
  2821.      If polling is not active the OS/2 driver leaves input data in the buffer
  2822.      of COM[xx].SYS, which will eventually fill-up!  In either case it will
  2823.      disturb the polling mechanism if is active or will be activated.  So do
  2824.      not send from your mainline commands that will cause the
  2825.      Märklin-Interface to send data!
  2826.  
  2827.  
  2828.  
  2829.   OS/2 AND DOS DIFFERENCES
  2830.  
  2831.   Although all versions of this Märklin-driver offer a consistent application
  2832.   programming interface for communication with the Märklin-Interface, it is
  2833.   most likely that there will be differences between the programs using
  2834.   either of them.  Some of these differences might be:
  2835.  
  2836.   ■  When running in a multitasking environment, the program should give
  2837.      other tasks the chance to run (yield the processor).
  2838.      -  With OS/2 other tasks will get some control automatically
  2839.         (pre-emptive multi-tasking), but nevertheless the program should use
  2840.         DosSleep() when it does not need the processor for some time.
  2841.      -  DOS: apart from the built-in multitasking of the Märklin-driver which
  2842.         controls itself, you probably won't run other programs.  In that case
  2843. |       you will not have to release the processor.
  2844. |    -  When running a DOS-program under another multitasker (Windows,
  2845.  
  2846.   ───────────────────────────────────────────────────────────────────────────
  2847.                                        Appendix C.  Design Notes and Tips  44
  2848.  
  2849.   Märklin-Interface driver
  2850.   ───────────────────────────────────────────────────────────────────────────
  2851.  
  2852.  
  2853. |       Desqview), periodic calls of mklsleep are recommended.
  2854.  
  2855.   ■  The OS/2 driver makes use of the standard multitasking (multithreading)
  2856.      facilities and therefore should specify /MT for MicroSoft C-compiler
  2857.      6.00a  or use include-files from the \INCLUDE\MT directory when using
  2858.      the IBM C/2 compiler 1.1, The different include-search might be
  2859.      indicated with a compiler option (-I for most C-compilers).
  2860.  
  2861.      The DOS driver should use the normal include directory.
  2862.  
  2863.   ■  The OS/2 driver requires the LARGE memory model, compiler options
  2864. |    (/Alfu), and use the LLIBCMT (multitasking!) library for LINK.  The
  2865. |    DOS-version is for the SMALL (/AS) or LARGE memory model (/AL), use the
  2866. |    resepctively the SLIBCE or LLIBCE library with LINK.
  2867.  
  2868. | ■  The standard OS/2-driver (COM[xx].SYS) will not accept new output data
  2869. |    in stop-state, but will transmit possibly retained data (from before
  2870. |    mklstop) after a call to 'mklgo'.  Some alternative drivers (such as
  2871. |    SIO.COM) do accept new data from mklputc, but keep it internally
  2872. |    buffered.  No more data is accepted when the buffer is full.  After
  2873. |    mklgo all buffered data, old and new, will be transmitted.
  2874.  
  2875. |    The DOS-drivers refuse all new output data in stop-state.
  2876.  
  2877.   ■  It is an absolute must, that the Märklin-driver under DOS is terminated
  2878.      with a call to mklclose() to de-activate the interrupts for com-port and
  2879.      timer.  Therefore it is recommended to use a routine to intercept Ctrl-C
  2880.      or Ctrl-Break actions from the keyboard.
  2881.  
  2882.      Under OS/2 this is not necessary: the system takes care of cleanup after
  2883.      terminating a program, regularly or not.
  2884.  
  2885.      In both cases it is recommended to direct the Ctrl-C signal to a
  2886.      controlled finish of your railroad control program: you probably do not
  2887.      want to terminate your program with uncontrolled running trains!
  2888.  
  2889.   ■  The display of information about the state of your railroad on the
  2890.      computer screen will probably use different techniques, such as the way
  2891.      cursor and color will be used:
  2892.      1. OS/2: Presentation Manager (graphics)
  2893.      2. DOS: Windows (graphics)
  2894.      3. ANSI escape-sequences (compatible between OS/2 and DOS)
  2895.  
  2896.      The sample program you'll receive after registration is a single source
  2897.      for environments 1 and 3.  My own programs are primarily for OS/2 and I
  2898.      prefer to use the OS/2 facilities and those of the Program Development
  2899.      Toolkit as good as possible.  For instance I use VIO-routines for color
  2900.      and cursor manipulation.
  2901.  
  2902.      To be able to run my sample program under DOS, I included some extra
  2903.      routines in the header-file.  These routines translate color and cursor
  2904.      manipulations with OS/2 VIO-calls into equivalent ANSI escape sequences.
  2905.      When ANSI is active under DOS (with DEVICE=[path]\ANSI.SYS in
  2906.  
  2907.   ───────────────────────────────────────────────────────────────────────────
  2908.                                        Appendix C.  Design Notes and Tips  45
  2909.  
  2910.   Märklin-Interface driver
  2911.   ───────────────────────────────────────────────────────────────────────────
  2912.  
  2913.  
  2914.      CONFIG.SYS), the visual effects are the same as with the OS/2 version.
  2915.  
  2916.   When there is no possibility to use the same code for OS/2 and DOS, you
  2917.   might consider using a compiler variable (with the -D compiler option) to
  2918.   distinguish which pieces of codes are OS/2 or DOS specific.  See for an
  2919.   example the MAKE-files in the MARKLIN package.
  2920.  
  2921.  
  2922.  
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928.  
  2929.  
  2930.  
  2931.  
  2932.  
  2933.  
  2934.  
  2935.  
  2936.  
  2937.  
  2938.  
  2939.  
  2940.  
  2941.  
  2942.  
  2943.  
  2944.  
  2945.  
  2946.  
  2947.  
  2948.  
  2949.  
  2950.  
  2951.  
  2952.  
  2953.  
  2954.  
  2955.  
  2956.  
  2957.  
  2958.  
  2959.  
  2960.  
  2961.  
  2962.  
  2963.  
  2964.  
  2965.  
  2966.  
  2967.  
  2968.   ───────────────────────────────────────────────────────────────────────────
  2969.                                        Appendix C.  Design Notes and Tips  46
  2970.  
  2971.   Märklin-Interface driver
  2972.   ───────────────────────────────────────────────────────────────────────────
  2973.  
  2974.  
  2975.   APPENDIX D.  TRACE FACILITY
  2976.  
  2977.  
  2978.  
  2979.   TRACE RECORDS
  2980.  
  2981.   The trace facility produces the following records (8 bytes each):
  2982.  
  2983.  
  2984.    long int timestamp;  /* value of mkltime */
  2985.    int  fl:1,           /* flag: 0=output, 1=input */
  2986.         nn:7,           /* (in start-of-trace record) trace source */
  2987.                         /* MKLAPI: DOS = 1; OS/2 1.x = 2; OS/2 2.x = 3 */
  2988.         sw:8;           /* S88 box number on input */
  2989.    char c1,             /* first character */
  2990.         c2;             /* second character */
  2991.  
  2992.  
  2993.   The first record after starting a trace contains 0xFF as first and second
  2994.   character.
  2995.  
  2996.  
  2997.   SAMPLE
  2998.  
  2999.   The output of the trace formatting program MKLTRFMT will look like:
  3000.  
  3001.  
  3002.         time    I/O  cmd  data  description
  3003.    ------------ ---  ---  ----  --------------------------------------
  3004.          45.050                 Start of trace (MKLAPI OS/2 1.x)
  3005.          +0.045  O    1A    13  Loc 19  speed 10  Funktion=ON
  3006.          +0.350  O    22    3F  switchpoint 63: branch off
  3007.          +0.760  O    20        switchpoint release
  3008.          +1.850  O    C0        read S88's with reset
  3009.          +4.850  O    82        read S88 1 t/m 2
  3010.          +4.881  I        1801  S88  1 ON=4,5,16
  3011.          +4.881  I        090E  S88  2 ON=,8,13,14,15
  3012.          +5.000  O    61        STOP
  3013.  
  3014.  
  3015.   This is not a complete trace, just some parts to show the essentials.
  3016.  
  3017.   MKLTRFMT.EXE is a 'family mode' application: it will run under OS/2 and
  3018.   DOS.  No parameters are required, but you may specify the input filename
  3019.   [including path] if your trace is in another directory or named other than
  3020.   MKLAPI.TRC, which is the default (output filename of MKLAPI).
  3021.  
  3022.   MKLTRFMT writes the output to 'stdout', which is normally the computer
  3023.   display.  But the output may be redirected to your printer or to a file.
  3024.   So you could use for example the command:
  3025.  
  3026.     MKLTRFMT >TRACE.FMT
  3027.  
  3028.  
  3029.   ───────────────────────────────────────────────────────────────────────────
  3030.                                               Appendix D.  Trace facility  47
  3031.  
  3032.   Märklin-Interface driver
  3033.   ───────────────────────────────────────────────────────────────────────────
  3034.  
  3035.  
  3036.   so that you could look afterwards with a text editor or file browse utility
  3037.   in TRACE.FMT for the formatted trace.
  3038.  
  3039.  
  3040.  
  3041.  
  3042.  
  3043.  
  3044.  
  3045.  
  3046.  
  3047.  
  3048.  
  3049.  
  3050.  
  3051.  
  3052.  
  3053.  
  3054.  
  3055.  
  3056.  
  3057.  
  3058.  
  3059.  
  3060.  
  3061.  
  3062.  
  3063.  
  3064.  
  3065.  
  3066.  
  3067.  
  3068.  
  3069.  
  3070.  
  3071.  
  3072.  
  3073.  
  3074.  
  3075.  
  3076.  
  3077.  
  3078.  
  3079.  
  3080.  
  3081.  
  3082.  
  3083.  
  3084.  
  3085.  
  3086.  
  3087.  
  3088.  
  3089.  
  3090.   ───────────────────────────────────────────────────────────────────────────
  3091.                                               Appendix D.  Trace facility  48
  3092.