home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / MKLAPI10.ZIP / MKLAPI.DOC < prev    next >
Encoding:
Text File  |  1993-05-04  |  112.9 KB  |  2,878 lines

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