home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-05-04 | 112.9 KB | 2,878 lines |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- MKLAPI
-
- Märklin-Interface driver and
- High Level Language
- Application Programming Interface
- for C-language and BASIC
- Version 1.0
-
-
-
-
- Document Number RH-MKLAPI 1.0
-
- May 4, 1993
-
-
- Rob Hamerling
-
- Vianen-ZH
- The Netherlands
- Phone: 31-3473-72136 (voice)
- FIDO: 2:512/4.1098
-
- MKLAPI
-
-
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- CONTENTS
-
-
- Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
- What is MKLAPI? . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
- Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
- Realisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
- Registration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
-
- Functional description . . . . . . . . . . . . . . . . . . . . . . . . 3
- Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
- Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
- Functional Requirements . . . . . . . . . . . . . . . . . . . . . . . 3
- Provided Facilities . . . . . . . . . . . . . . . . . . . . . . . . . 4
- Deliverables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
- Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
- Restrictions and Limitations . . . . . . . . . . . . . . . . . . . . . 5
- Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
- C-language framework . . . . . . . . . . . . . . . . . . . . . . . . . 7
- QuickBASIC framework . . . . . . . . . . . . . . . . . . . . . . . . . 8
- Sample programs . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
- OS/2 and DOS differences . . . . . . . . . . . . . . . . . . . . . . 10
-
- Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
- Available Functions . . . . . . . . . . . . . . . . . . . . . . . . . 11
- mklclose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
- mklflush . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
- mklgetsn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
- mklgo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
- mklmsecs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
- mklopen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
- mklpoll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
- mklpurge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
- mklputc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
- mklsleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
- mklsound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
- mklstats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
- mklstop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
- mkltime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
- mkltrace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
- Macro Specifications . . . . . . . . . . . . . . . . . . . . . . . . 23
- mklput1c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
- mklput2c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
- Use of timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
- QuickBASIC Function Specifications . . . . . . . . . . . . . . . . . 25
- Errors and Signals . . . . . . . . . . . . . . . . . . . . . . . . . 25
-
- Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
- Application development considerations . . . . . . . . . . . . . . . 27
- C-Compiler considerations . . . . . . . . . . . . . . . . . . . . . . 27
- MicroSoft QuickBASIC compiler 4.5 Considerations . . . . . . . . . . 27
- Building an EXE-file . . . . . . . . . . . . . . . . . . . . . . . . 27
- C-language and DOS . . . . . . . . . . . . . . . . . . . . . . . . 28
- C-language and BASIC . . . . . . . . . . . . . . . . . . . . . . . 28
- C-language and OS2 1.3 . . . . . . . . . . . . . . . . . . . . . . 29
-
- ───────────────────────────────────────────────────────────────────────────
- Contents ii
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- C-language and OS2 2.0+ . . . . . . . . . . . . . . . . . . . . . . 30
- Storage and performance . . . . . . . . . . . . . . . . . . . . . . . 30
- Memory Utilisation . . . . . . . . . . . . . . . . . . . . . . . . 30
- Processor utilisation . . . . . . . . . . . . . . . . . . . . . . . 30
- Comments, Remarks, Bug-reports . . . . . . . . . . . . . . . . . . . 31
-
- Appendix A. MKLAPI Internals . . . . . . . . . . . . . . . . . . . . 32
- Multitasking . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
- Reading Märklin S88 encoders . . . . . . . . . . . . . . . . . . . . 33
- Communications Interface Specification . . . . . . . . . . . . . . . 35
- Problems with OS/2 COM[xx].SYS . . . . . . . . . . . . . . . . . . . 37
- OS/2 and DOS differences . . . . . . . . . . . . . . . . . . . . . . 38
-
- Appendix B. Trace facility . . . . . . . . . . . . . . . . . . . . . 40
- Trace records . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
- Sample . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
-
- | Appendix C. Märklin-Interface peculiarities . . . . . . . . . . . . 41
-
- Appendix D. Summary of changes . . . . . . . . . . . . . . . . . . . 42
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ────────────────────
- (1) This document is processed: on May 4, 1993 at 9:52 p.m.
-
- ───────────────────────────────────────────────────────────────────────────
- Contents iii
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- INTRODUCTION
-
- Copyright (C) R. Hamerling, 1991, 1993
- All Rights Reserved.
-
-
-
-
- WHAT IS MKLAPI?
-
- MKLAPI is a combination of:
-
- ■ a driver for buffered communications, automatic reading of Märklin S88
- encoder-boxes, timer- and some other services.
-
- ■ a number of user callable routines for common elementary functions, with
- a comfortable high-level programming interface.
-
- So MKLAPI reliefs a programmer from 'low-level' tasks such as controlling
- the communication with the Märklin-Interface, so that he can concentrate on
- the railroad-control logic. This simplifies programming for
- model-railroads which are controlled via a Märklin-Interface. Internally
- it performs a kind of multi-tasking, which is highly desirable for this
- realtime environment ('proces control').
-
-
- PURPOSE
-
- The driver and API has been developed for the following purposes:
-
- ■ have an application programming interface (API) which is independent of
- the operating system (i.c. OS/2 or DOS).
-
- ■ provide a simple interface for a number of frequently used basic control
- functions such as sending commands to trains and switch points, and
- reading sensors.
-
- ■ allow the mainline to be written completely in high-level programming
- language (i.c. C-language or QuickBASIC).
-
- ■ obtain a buffered communications facility to the Märklin-Interface,
- including automatic flow control as required by the Märklin-Interface.
-
- ■ have 'background' tasks for a number of functions that should or could
- be performed independently and asynchronously from the mainline.
-
- ■ provide an accurate and efficient timer facility for time-dependent
- operations, events and interval-calculations.
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Introduction 1
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- REALISATION
-
- This package offers a set of drivers with all the functionality of listed
- "Purpose" on page 1. Although the OS/2-drivers and DOS-drivers are
- completely different implementations, due to the rather extreme differences
- in functionality provided by OS/2 and DOS for this type of environment, the
- mainline of your railroad control program may be unaware of the underlying
- operating system: the application programming interface is identical.
-
- You may read a number of minor differences in "OS/2 and DOS differences" on
- page 10.
-
-
- REGISTRATION
-
- This package is of the 'SHAREWARE' type: You may try it for a reasonably
- short time (max 3 months). If you decide to use it for your own railroad
- control program, you may show your appreciation and become a 'registered
- user'. After registration, I'll send you by mail:
-
- ■ A diskette (3-1/2", 720KB), with the following contents:
- ∙ The most recent version of all the drivers.
- ∙ Source-files (C-language) of a couple of sample programs provided as
- executables in the base package.
-
- ■ Complete and up-to-date printed documentation, as well as 2
- documentation files on the diskette:
- ∙ A print-file, formatted for IBM Pro-Printer III.
- ∙ A file in OS/2 INF format (VIEW-able as online documentation like the
- inline OS/2 Command Reference Manual).
-
- After registration you are allowed to distribute the driver as integral
- part of your own railroad control application programs. The package (not
- the material you get after registration) may be distributed freely with
- under the following conditions:
-
- ■ it remains a separate and complete package
- ■ you do not apply changes of any kind
- ■ you do not make profit with it
-
- The registration fee is 45 Dutch Guilders or equivalent of 25 US-Dollars.
- Bare money is accepted as well, but foreign money only in the form of
- US-Dollar banknotes.
-
- Please send your comments and registration fee to:
-
- R. Hamerling
- Vianen-ZH,
- The Netherlands
- Postbank acct#: 2087285
- PC-Square: FIDOnet 2:512/4.1098
-
- Mention the purpose of your payment ("MKLAPI"), and the destination
- address! MKLAPI-source is not included.
-
-
- ───────────────────────────────────────────────────────────────────────────
- Introduction 2
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- FUNCTIONAL DESCRIPTION
-
- This chapter describes a possible use of this package.
-
-
- OVERVIEW
-
- The Märklin-Interface-driver package is a set of functions to enable direct
- communications support in a program written in C-language or BASIC for the
- MicroSoft QuickBASIC compiler 4.5((2)) for the family of IBM Personal
- System/2 and compatibles.
- Please report problems with the driver as soon as you can. and accompany
- your report with as much details as might be relevant.
-
-
- TERMINOLOGY
-
- In this document I use a number of terms which should probably be clarified
- first.
-
- Interface The Märklin-Interface. (Märklin partnumber 6050)
-
- Sensor The Märklin S88 encoder. (Märklin partnumber 6088). Sometimes
- also called sensor-box or encoder.
-
- Switch The railroad facility, Märklin K83 decoder (Märklin partnumber
- 6083) is used to control these switch points.
-
-
-
- FUNCTIONAL REQUIREMENTS
-
- The Märklin-Interface-driver must provide the following functionality:
-
- ■ Possibility to send commands to the Märklin-Interface in any sequence
- and mix.
-
- ■ Builtin buffered communication with the Märklin-Interface.
-
- ■ Automatic flow control between PC and Märklin-Interface.
-
- ■ Time-base (clock) for for time-dependent control, independent of
- hardware (processor) speed.
-
- ■ Automatic readout of sensor-boxes (Märklin S88 encoder): the mainline
- must be able to obtain sensor positions instantaneously (without
- waittime).
-
-
- ────────────────────
- (2) Please note that this driver is delivered in the form of
- .OBJ-files, and therefore can be used only with compiled programs
- (other .OBJ-files). QBASIC that comes with DOS 5.0 is not capable
- of producing an .OBJ file, you'll need the MicroSoft QuickBASIC
- compiler 4.5 to use this driver with BASIC programs.
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 3
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- ■ Priority mechanism: mainline activities must be handled with higher
- priority than 'background' service processes.
-
- ■ Ability for emergency stops, regardless of the state of the program or
- the model railroad.
-
-
-
- PROVIDED FACILITIES
-
- To fulfil the functional requirements, a 'driver' has been built. It
- contains a number of service-routines (and for DOS also hardware interrupt
- routines), and provides the following facilities:
-
- ■ Functions to send train and switch commands to the interface.
-
- Two macro's for output of resp. 1 or 2 consecutive characters (the so
- called 1-byte or 2-byte commands). With the 2-byte form the subroutines
- ensure that the 2 characters are sent as 2 consecutive characters (not
- interrupted by a 'background' task).
-
- ■ Functions to read sensors (S88-boxes).
-
- This can either be done by immediate reading the status of the last
- polling operation (if polling started). "Reading Märklin S88 encoders"
- on page 33 contains details about this mechanism.
-
- If the mainline is sending a command to the Märklin-Interface, polling
- is automatically suspended (the command is treated with higher
- priority).
-
- ■ A 'shadow' of the system timer, but expressed in milliseconds since
- program start. This timer has with the OS/2-driver of MKLAPI a
- precision of 31.25 msecs, using standard OS/2 facilities (the timer
- tick). With the DOS-driver of MKLAPI the posibilities of the hardware
- PC timer are explored, giving a precision of 1 millisecond.
-
- ■ A trace facility is built in for easy program debugging. All output to
- the interface can [optionally] be traced (OS/2 only) and formatted
- later.
-
-
-
- DELIVERABLES
-
- The shareware components of the Märklin-Interface-driver package are:
-
- | ■ This documentation file: MKLAPI.DOC.
- | ■ Header file for C-language: MKLAPI.H with function prototypes, data- and
- | macro- definitions.
- | ■ Include file for QuickBASIC: MKLAPI.INC with function prototypes.
- | ■ 2 OS/2-object decks, MKLAPI2.OBJ (16-bits OS/2 version) and MKLAPI3.OBJ
- | (32-bits OS/2 version), with a buffered multitasking communication
- | interface, polling, timer-support and trace facility.
- | ■ 2 DOS-object decks for C-language programs, SMKLAPI.OBJ and LMKLAPI.OBJ,
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 4
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- | with the same functionality as the OS/2 drivers, (but without a trace
- | facility). SMKLAPI is the object deck to be linked with your SMALL
- | memory model program, LMKLAPI.OBJ is for LARGE memory model C-language
- | programs. LMKLAPI.OBJ is also used for QuickBASIC programs.
- ■ TRAIN.EXE and TRAIN2.EXE, which are ready to run sample programs for a
- DOS and OS/2 environment respectively. See "Sample programs" on page 8
- for some characteristics of these programs.
- ■ MKLTRFMT.EXE, utility to interpret (format) the recorded trace file.
-
- The registration package consists of:
-
- ■ Sources (in C-language) of a sample train control program that makes use
- of the Märklin driver, usable for OS/2 and DOS ('fullscreen'
- application)
- ■ All include and header files
- ■ All MAKE and DEF files, used for compilation with MicroSoft C-compiler
- 6.00a or equivalent, IBM C SET/2 compiler for 32-bits programs and
- MicroSoft QuickBASIC compiler 4.5 for QuickBASIC programs.
-
-
-
- PREREQUISITES
-
- The package has been built with the following assumptions:
-
- ■ Your PC-hardware is 100% compatible with the productline of IBM Personal
- Computers (PC, PC/XT, PC/AT, and all current models of the Personal
- System/2 family), in particular the asynchronous communication adapters,
- their port addresses, etc. and the hardware timer.
-
- ■ The operating system is either OS/2 1.2 or higher, or PC-DOS 2.1 or
- MS-DOS 2.1 or higher. The package has been tested only with IBM PC/DOS
- version 4.0 and 5.0, and with OS/2 version 1.3 and 2.0 (in OS/2
- session).
-
- ■ Your (16-bits) C-programs (OS/2 and DOS) will be compiled with MicroSoft
- C-compiler 6.00a. For 32-bits C-programs IBM C SET/2 compiler is
- assumed. There may be some specific requirements on system hardware and
- software for these. Maybe Borland Turbo C compiler will work as well,
- but this has not been tested.
-
- ■ Your BASIC programs will be compiled with the MicroSoft QuickBASIC
- compiler 4.5.
-
-
-
- RESTRICTIONS AND LIMITATIONS
-
- The following restrictions apply:
-
- ■ One single port can be used between open and close of the COM-port to
- the Märklin-Interface, all other functions apply to the port chosen at
- open-time.
-
- ■ The transmit buffer of the DOS-driver is 2048 bytes long, for OS/2 it
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 5
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- depends on COM[xx].SYS, or substitute.
-
- ■ Received data is transferred immediately to the sensor-array (64 bytes).
-
- ■ When the mainline is sending data to the Märklin-Interface and a
- buffer-full situation arises, the data will be discarded. However it is
- very unlikely that this will happen in real life.
-
- ■ If you read a sensor-box outside the polling-range, the response is
- undefined.
-
-
-
- TESTS
-
- The drivers have been tested by the author with combinations of the
- following hardware and software:
-
- ■ model railroad equipment:
- ∙ Märklin Combined Control
- ∙ 3 Märklin Digital locs
- ∙ 3 Märklin K83 decoders, each connected to 4 switch points
- ∙ 1 Märklin S88 encoder, with railroad-section sensoring
-
- ■ computer hardware:
- ∙ IBM PC/AT-3 (80286/8) with IBM serial-parallel adapter
- ∙ IBM PS/2 model 80 (80386/16) with standard serial port
- ∙ IBM PS/2 notebook N51SLC (80386SLC/16) with standard serial port and
- second serial port
- ∙ IBM compatible 80486/33 with multi-I/O card
-
- Note: The DOS-drivers are written in 8086/8 Assembler and should also
- work on XT-type systems.
-
- ■ Operation Systems:
- | ∙ IBM OS/2 2.0: 32-bits mode with MKLAPI3.OBJ, 16-bits mode with
- | MKLAPI2.OBJ, DOS-session with LMKLAPI.OBJ
- | ∙ IBM OS/2 1.3: MKLAPI2.OBJ
- | ∙ IBM PC/DOS 5.0: LMKLAPI.OBJ with QuickBASIC and C-language
-
- Note: Not all combinations of hardware and software have been tested, but
- it is not likely that any viable combination will not work.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 6
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- C-LANGUAGE FRAMEWORK
-
- A typical model railroad control program with this driver may look like:
-
-
- #include "mklapi.h"
-
- mklopen(1,2400); /* open COM1: */
- mklpoll(5); /* 5 S88 boxes in yard */
- while (key != ESC) { /* end program from keyboard */
- if (kbhit()) { /* keyboard input */
- if (key = getch()) { /* normal key (incl alt-numpad) */
- switch(key) {
- case '?': - - - - - /* your key, your function */
- break;
- case ESC: break; /* nothing now, exit program */
- default: fprintf(stdout,"%c",BEL);
- break; /* unsupported normal key */
- }
- }
- else { /* 'special' key */
- switch(key = getch()) { /* extended character */
- case PgDn: - - - - - /* your 'extended' key function */
- break;
- default: fprintf(stdout,"%c",BEL);
- break; /* unsupported 'extended' key */
- }
- }
- }
- for (i=0; i<MAXTRAIN; i++) { /* scan train matrix */
- - - - - - /* train control function */
- }
- for (i=1; i<5, ++i) { /* scan S88 boxes */
- mklgetsn(i); /* read sensor bits */
- - - - - - - /* process changes */
- }
- if (!(mkltime()%5000)) { /* every 5 seconds */
- - - - - - /* anything else */
- }
- mklsleep(25); /* give up remainder of timeslice */
- }
- mklflush(); /* wait until output sent */
- mklclose(); /* terminate */
-
- Note: Above code is just a framework to show the general setup of a model
- railroad control program using the Märklin-Interface.
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 7
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- QUICKBASIC FRAMEWORK
-
- An equivalent framework in QuickBASIC might look like:
-
-
- ' $INCLUDE: 'MRKAPI.INC'
-
- rc = mklopen(1,2400);
- mklpoll(5);
- key$ = INKEY$
- while key$ <> ESC$
- select case key$
- case '?'
- - - - - -
- case ESC
- - - - - -
- case else
- print "error key"
- end select
- for i=0 to MAXTRAIN
- - - - - -
- next i
- for i=1 to 5
- mklgetsn(i)
- - - - - - -
- next i
- if MOD(mkltime,5000) < 50 then
- - - - - -
- end if
- mklsleep(25)
- key$ = INKEY$
- wend
- mklflush;
- mklclose;
-
- Note: This code may not be true and workable QuickBASIC!
-
- The file MKLAPI.INC contains the DECLARE lines for all functions contained
- in LMKLAPI.OBJ. It should be included in a QuickBASIC program to obtain
- the correct calling conventions and activates syntax checking by the
- MicroSoft QuickBASIC compiler 4.5. Subsequently the file LMKLAPI.OBJ
- should be linked with your QuickBASIC program to include the MKLAPI
- functions and subroutines.
-
-
- SAMPLE PROGRAMS
-
- After registration you will receive the sources a sample (C-language)
- program:
-
- ■ Control of 8 trains and several other possibilities, with the following
- details:
- ∙ Speed is controlled from the computer keyboard with arrow (cursor)
- keys: right-key is faster, left-key is slower, up-key is maximum for
- this train, down is maximum backward for this train.
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 8
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- ∙ The train for which the command is meant is selected with a
- number-key (program provides control for trains 1 through 8). The
- corresponding loc-address and other train properties are in a matrix
- (with individual entries for each train), such as minimum and maximum
- speed in Märklin Central Control values. The train addresses that
- are programmed are 10 for train 1, 20 for train 2, etc until 80 for
- train 8.
- ∙ The speed-control is indirect: you tell the system the program
- loc-speed, the program does mass-simulation ('slow' increase and
- decrease of speed). The parameters for enertia simulation are part
- of the train definitions.
- ∙ For each train its address, desired and actual train speed are
- displayed (in color). Direction changes are buffered and automatic.
- ∙ The display also indicates direction and whether the extra function
- is 'on' or 'off'.
-
- ■ Control of 4 Märklin K83 decoder for 16 railroad switch points. For
- each switch the position ('normal' or 'bound' in color) and its address
- is displayed. The keys are A-P for adresses 253-256, and 1-12
- respectively.
-
- ■ Polling of Märklin S88 encoder each with 16 sensors (or isolated
- railroad sections). The position is displayed real time, nothing but
- displaying is done with the information. 2 Märklin S88 encoder-boxes
- are being polled.
-
- ■ Sensor 16 of Märklin S88 encoder-box 1 is designated for speed
- measurement. The display shows the time (in milliseconds) between 2
- successive 'OFF-ON' transitions. If there is 1 train running and moving
- along the same road, this facility can be used for calibrating speed
- calculations for each speed-command-value.
-
- ■ Other keys:
- Insert Set Function 'on'
- Delete Set Function 'off'
- End Stop polling
- Home Restart polling
- F3 Stop the program (has to be entered twice consecutively)
- Esc Emergency Stop (issues the Märklin Central Control STOP
- command)
- Enter Resume (issues the Märklin Central Control GO command)
-
- The program may be started with 2 numeric parameters:
-
- 1. the first parameter indicates the COM-port to be used (1 for COM1, 2 for
- COM2, etc.), The default is COM1.
- 2. The second parameter indicates the number of Märklin S88 encoder-boxes
- to include in the polling mechanism. The default is 2.
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 9
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- OS/2 AND DOS DIFFERENCES
-
- The OS/2-drivers differ from the DOS drivers:
-
- ■ The OS/2-drivers are written in C-language, the DOS drivers in
- Assembler.
-
- ■ The OS/2-driver makes use of the services provided by the standard OS/2
- communications driver COM02.SYS (for PS/2) or COM01.SYS for others under
- OS/2 version 1.3, and COM.SYS for OS/2 version 2.0. The DOS driver
- interfaces directly with the PC hardware.
-
- ■ The OS/2-driver makes use of the standard OS/2 facilities for
- multithreading (task signalling is done with semaphores). The DOS
- driver performs a form of multi-tasking, driven by interrupts (the
- COM-port hardware and the standard DOS timer tick).
-
- ■ The DOS-drivers explore the possibilities of the hardware timer of the
- PC to obtain a accurate time values when needed. With the DOS
- timer-tick of 55 msec the average deviation would be about 28 msec.
- OS/2 does not allow access to the hardware by 'normal' applications,
- therefore the OS/2-drivers use standard OS/2 function calls. Since the
- OS/2 timer tick is 31.25 msec, the average deviation will be about 16
- msecs.
-
- The sample program under DOS chokes the processor (takes all the cycles
- that are available). This is OK in a typical single-task environment, but
- not very suitable for a multitasking system. Under OS/2 a very simple
- solution for this problem is to insert for example a DosSleep(30L) at the
- end of the infinite (keyboard-) loop. There may be better solutions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Functional description 10
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- SPECIFICATIONS
-
- This chapter describes the use of the provided facilities.
-
-
- AVAILABLE FUNCTIONS
-
- The following user callable functions are provided:
-
- mklopen Start communication with the Märklin-Interface and the
- background tasks.
- mklclose Stop background tasks and shutdown the communication with
- the Märklin-Interface.
- mklputc Transmit 1 or 2 character-commands to the
- Märklin-Interface.
- mklflush Wait until all data transmitted.
- mklpurge Discard remaining data in output buffer.
- mklpoll Start or stop polling of Märklin S88 encoder boxes.
- mklgetsn Obtain the status of 1 Märklin S88 encoder (when polling
- active).
- mklstop Set Märklin-Interface in 'stop'-state and stop polling
- mklgo Set Märklin-Interface in 'go'-state and (optionally) resume
- polling.
- mklmsecs Give accurate time in milliseconds since program start
- (only in DOS-drivers).
- mkltime Give time of last timer tick in milliseconds since program
- start.
- | mklstats Provide statistics (activity counters).
- | mklsleep Pause for a certain time (and give up the remainder of a
- | time slice when running in a multitasking environment).
- | mklsound Sound generator like BASIC sound or OS/2 DosBeep()
- mkltrace Start or stop recording data that is being sent to
- Märklin-Interface (only in OS/2-drivers).
-
- The next sections contain the specifications of available functions of the
- Märklin-driver, in alphabetical sequence.
-
- Note: The descriptions for C-language and QuickBASIC are given both, but in
- the text mainly the C-language notations are used.
-
-
- MKLCLOSE
-
- Name mklclose - close communications with the Märklin-Interface.
-
- C-language
-
- #include "mklapi.h"
- void mklclose(void);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE SUB MKLCLOSE CDECL ()
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 11
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- Description The close-routine disables the communications task of the
- driver. It should be called before termination your
- program. Transmits and receives that were in progress will
- be terinated, data might be lost.
-
- Return value Nothing.
-
- Related functions "mklopen" on page 15
-
- Warning: mklclose() is not a trivial function! It must be used when
- mklopen() has been called succesfully (under DOS). Otherwise your system
- may enter a hang-up situation when for no matter what reason your
- communications port gives an interrupt. So terminate your program always
- 'neatly' (so intercept Ctrl-Break in your program to prevent uncontrolled
- program termination)!
-
-
-
- MKLFLUSH
-
- Name mklflush - flush all buffered output.
-
- C-language
-
- #include "mklapi.h"
- int mklflush(void);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION FLUSH% CDECL ()
-
- Description Wait until all output is sent to the Märklin-Interface. In
- other words: wait for empty transmit buffer before
- | returning to caller.
-
- | When buffered data is apparently not transmitted anymore,
- | the remaining bytes in the transmit buffer will be purged
- | and the purge statistics are updated accordingly.
-
- | Return value Depending on success:
- | ■ 0 when no more bytes to transmit (buffer empty)
- | ■ >0 number of bytes not transmitted (purged) buffer.
- ■ -1 (DOS) last byte in hardware buffer was not
- transmitted
-
- Related functions "mklpurge" on page 16
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 12
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- MKLGETSN
-
- Name mklgetsn - get bit-pattern of a single Märklin S88 encoder.
-
- C-language
-
- #include "mklapi.h"
- unsigned short int mklgetsn(short int sensor);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION MKLGETSN% CDECL (BYVAL SENSOR%)
-
- Description Get a single sensor-box word (16 bits) from the sensor
- array.
-
- This function does not generate any action to the
- Märklin-Interface and returns the bitsetting immediately.
- Polling will have to be started first, with mklpoll(),
- before the reading of sensors will give meaningful results.
- Reading outside the range 1..31, or higher than the value
- as specified with the latest mklpoll(maxsensor) or
- | mklgo(maxsensor), will give unpredictable results.
-
- | The Märklin-Interface is always read with 'reset'. The
- | resulting 1-bits ('on'-switches) are cumulated until a
- | mklgetsn() is called for a specific S88. The caller
- | obtains the cumulative bit-setting, but the sensor word is
- | refreshed immediately with the results of the last read
- | command. Depending on the type of switche used on the
- | model railroad, and the frequency in which mklgetsn() is
- | issued by the mainline, it may be necessary to issue
- | mklgetsn() twice. See for a further explanation: "Reading
- | Märklin S88 encoders" on page 33.
-
- Return value A 16-bit word containing the current switch positions.
-
-
-
- MKLGO
-
- Name mklgo - send the 'go' command.
-
- C-language
-
- #include "mklapi.h"
- int mklgo(short int maxsensor);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION MKLGO% CDECL (BYVAL MAXSENSOR%)
-
- Description Send the 'go'-command (ASCII 96) to the Märklin-Interface
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 13
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- immediately.
-
- The value of MAXSENSOR has the same meaning and effect as
- in mklpoll (see "mklpoll" on page 16). Polling will be
- resumed if a non-zero parameter is specified.
-
- OS/2: The go-command is sent via a DevIOCtl operation (send
- immediate), and will be followed by a simulated XON. If
- there was buffered output (before the stop-state or after
- entering stop-state under OS/2 2.0), it will be transmitted
- | now.
-
- | OS/2: If the 'go'-command could not be sent, for example if
- | the Interface is not ready to accept data, a permanent low
- | beep will be heard until the 'go'-button on Märklin Central
- | Control is pressed. If an other error occured, mklgo will
- | return an error code.
-
- DOS: The go-command is send just as regular data. The
- returncode is always zero.
-
- Return value Nothing.
-
- Related functions "mklstop" on page 21, "mklpoll" on page 16
-
-
-
- MKLMSECS
-
- Name mklmsecs - obtain time since program start in milliseconds.
-
- C-language
-
- #include "mklapi.h"
- unsigned long int void mklmsecs(void);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION MKLMSECS& CDECL ()
-
- Description (DOS only!) Returns the exact time in milliseconds after
- program start without waiting for the next timer tick.
- This might be useful for more accurate timing for special
- purposes. Of course it takes some time to execute the
- necessary instructions to read the timer and format the
- information. On faster systems mklmsecs() gives the time a
- little more precise than on slower systems, but even on
- relatively slow systems it is much more precise than
- probably needed for the purpose of mode railroad control!
- If this very high precision is not needed, then use the
- function mkltime().
-
- (OS/2) This function is 100% equivalent to mkltime().
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 14
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- Return value Time in milliseconds after program start.
-
- Related functions "mkltime" on page 22
-
-
-
- MKLOPEN
-
- Name mklopen - open communications line
-
- C-language
-
- #include "mklapi.h"
- | int mklopen(short int port, short int speed);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- | DECLARE FUNCTION MKLOPEN CDECL (BYVAL PORT%, BYVAL SPEED%)
-
- Description Open and initialise communications port driver, high
- resolution timer (DOS only), and set all statistics
- counters to zero. The port-parameter may have a value of 1
- | to 4, indicating COM1: to COM4:. With DOS the port
- | addresses are obtained from BIOS, with OS/2 the COM[xx].SYS
- | device driver has them. The interrupt levels are IRQ4 for
- | COM1 and COM3, IRQ4 for COM2 and COM4. As you see COM3 may
- | conflict with COM1 (and COM2 with COM4). You cannot use
- | conflicting interrupt levels at the same time in most
- | computers.
-
- Any port will always be initialised with 8-bit, no-parity,
- 2 stop-bits. The speed parameter should specify 2400,
- since it is the only speed supported by the
- Märklin-Interface. Maybe later other values?
-
- The counterpart of mklopen() is mklclose(), which should be
- called before finishing your (DOS-) program.
-
- | Return value Depending on success:
- | ■ 0 - port opened succesfully
- | ■ 32 - port probably occupied by another device
- | ■ 110 - port not available
- | ■ other - see OS/2 or DOS documentation
-
- | With OS/2 the port is opened by a separate thread. When
- | the port could not be opened, the whole process will be
- | terminated.
-
- Related functions "mklclose" on page 11, "mklstats" on page 19
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 15
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- MKLPOLL
-
- Name mklpoll - start periodic reading of Märklin S88 encoder.
-
- C-language
-
- #include "mklapi.h"
- void mklpoll(unsigned int maxsensor);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE SUB MKLPOLL CDECL (BYVAL MAXSENSOR%)
-
- Description Märklin S88 encoderboxes 1..MAXSENSOR will be read by a
- 'background' process.
-
- When starting the polling process a 'read with reset' is
- issued. The responses of the read-operation are stored in
- sensor-arrays. Each word of the array can be read
- individually at any time with mklgetsn(). See for details
- "Reading Märklin S88 encoders" on page 33.
-
- Return value Nothing
-
- Related functions "mklgo" on page 13 and "mklgetsn" on page 13
-
-
-
- MKLPURGE
-
- Name mklpurge - purge output buffer
-
- C-language
-
- #include "mklapi.h"
- void mklpurge(void);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE SUB MKLPURGE CDECL ()
-
- Description Discard current contents of output buffer. If the output
- buffer does contain any characters, these are not sent tot
- the Interface. After purging the current contents, control
- is immediately returned. See also "mklflush" on page 12.
-
- Note: This function is currently available in the driver
- for DOS.
-
- Return value Nothing.
-
- Related functions "mklflush" on page 12
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 16
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- MKLPUTC
-
- Name mklputc - send 1 or 2 characters to the interface
-
- C-language
-
- #include "mklapi.h"
- int mklputc(unsigned int word);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION MKLPUTC% CDECL (BYVAL WORD%)
-
- Description Send 1 or 2 characters to the Märklin-Interface. The
- 'word' is interpreted as two contiguous characters. The
- low order byte of the word is sent first, followed by the
- high-order byte. If the high is not sent when zero. The
- exception to this rule is: if the first byte is a
- switch-command (ASCII 33 or 34), then the second byte will
- be sent, even when zero.
-
- This function returns immediately, and does not wait for
- the bytes to be actually transmitted to the interface. The
- communications task will take care to send the buffered
- character(s) to the Märklin-Interface.
-
- Coding example to signal speed 8 to loc 27:
-
- rc = mklputc( 27*256 + 8)
-
- For C-language programs it is highly recommended to use the
- provided macro's for sending 1 or 2 character commands (see
- "Macro Specifications" on page 23).
-
- Warning: When there is no room in the output buffer, then
- both characters will be discarded.
-
- Return value 0 character(s) are accepted by the driver.
-
- -1 characters NOT accepted: output discarded.
-
- Note: If you use mklputc() while the driver is in 'stop-state' (see
- "mklstop" on page 21):
-
- ■ the OS/2-drivers issue a short high-pitch beep. With OS/2 2.0 the data
- might be buffered and transmitted after mklgo(). This depends on the
- used device driver for the COM-port. COM[xx].SYS does not buffer, but
- SIO.SYS does (until its 4KB buffer is full).
- ■ the DOS-drivers do not generate a warning and will discard the data
- until the stop-state is left via a call to mklgo().
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 17
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- MKLSLEEP
-
- | Name mklsleep - pause some time and yield processor
-
- | C-language
-
- | #include "mklapi.h"
- | void mklsleep(short int pause);
-
- | QuickBASIC
-
- | ' $INCLUDE: 'MKLAPI.INC'
- | DECLARE SUB MKLSLEEP CDECL (BYVAL PAUSE%)
-
- | Description This function provides two facilities:
- | ■ It does not return to the caller before the indicated
- | pause-interval (im milliseconds) has expired.
- | ■ In a multitasking environment (OS/2, DesqView, Windows)
- | it releases the processor for this task.
-
- | In the OS/2-driver this function is equivalent to
- | DosSleep(). In the DOS-driver it is implemented as a loop
- | with an imbedded test for multitasking, in the OS/2-driver
- | as DosSleep().
-
- | The pause should be specified in milliseconds, and thus
- | cannot exceed about 32 seconds! The specified
- | pause-interval is rounded to the next timer tick, but may
- | be even larger when the multitasker decides not to give
- | control yet to this task after expiration of the interval!
-
- When running a DOS-program in a multitasking environment
- (OS/2, Desqview, Windows, etc.), it is desirable to give
- control back to the multitasker, when the program does not
- need the processor for some time. This part of mklsleep()
- is experimental, it may not work with all multitaskers.
- The use of mklsleep is not absolutely needed with
- pre-emptive multitaskers (like OS/2), but is strongly
- recommended. In all cases it reduces CPU utilisation and
- leaves processor time for other tasks.
-
- Return value Nothing.
-
-
-
- MKLSOUND
-
- Name mklsound - give a 'beep'
-
- C-language
-
- #include "mklapi.h"
- void mklsound(short int freq, short int time)
-
- QuickBASIC
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 18
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE SUB MKLSOUND CDECL (BYVAL FREQ%, BYVAL TIME%)
-
- Description Produces a beep-tone with frequency 'freq' expressed in
- Hertz, during a period 'time' expressed in milliseconds.
- The tone is played in background, all processing continues
- without delays or slowdown of the system.
-
- DOS: A beep can be stopped prematurely by calling
- mklsound() with a zero frequency, or by mklclose(). A beep
- can be changed by mklsound() with a different frequency.
- | This will stop any previous beep.
-
- | OS/2: mklsound is implemented as DosBeep and thus behaves
- | exactly like it. It is included in the OS/2 driver only
- | for source compatibility between OS/2 and DOS programs
- | using MKLAPI.
-
- Return value Nothing.
-
-
-
- MKLSTATS
-
- Name mklstats - obtain content of statistics counter.
-
- C-language
-
- #include "mklapi.h"
- long int mklstats(int counter);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION MKLSTATS& CDECL (BYVAL COUNTER%)
-
- Description Obtain value of an internal counter in MKLAPI for
- statistical purposes. All counters will be reset to zero
- with mklopen(), and can also be reset by a user program
- through specification of 0 (zero) as parameter.
-
- To read a counter specify a number in the range: 1 to 6.
- The counters (by number) have the following contents:
- 1 Number of accepted commands, including polling-commands
- (commands to read S88's). Since the we use a buffering
- mechanism, not all of these commands may have been
- transmitted actually!
- 2 Number of internally generated commands to read S88's
- ('polls').
- 3 Number of commands that have been discarded. Reasons
- may be:
- ■ system is in 'stop-state'
- ■ transmit buffer is full
- 4 Number of bytes that were transmitted. With the
- DOS-driver these bytes are actually transmitted to the
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 19
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- COM-port, with OS/2 they were accepted by the device
- driver of the COM-port.
- 5 Number of received bytes (most likely as result
- commands to read S88's).
- 6 Number of bytes that were purged (discarded after first
- being accepted, but before actually being transmitted
- to the Märklin-Interface). Reasons may be:
- ■ there were commands buffered while mklstop() was
- called
- ■ mklflush() could not complete (timeout)
- ■ commands were in the transmit buffer during a call
- to mklpurge()
-
- Discarded commands are not counted as 'purged', since
- they were not accepted and never put into the transmit
- system!
-
- Note: Purging is not supported in the OS/2-drivers, so
- this counter should remain zero with OS/2 programs.
-
- Counters in the range 1 to 6 can be considered as permanent
- feature of MKLAPI. Counters in the range 7 to 15 are
- mainly for debugging purposes. The description below is
- for information purposes only, do not use them in your
- program, as they may be incorrect, their meaning be changed
- in a next version of MKLAPI, or may not be active at all in
- the distributed drivers (for performance reasons).
- 7 DOS: Number of calls to mklputc while the driver's
- transmit buffer was empty.
- 8 DOS: Number of calls to mklputc while the CTS signal is
- 'high'.
- 9 DOS: Number of calls to mklputc while the
- hardware communications buffer was empty.
- 10 DOS: Number of calls to mklputc whereby the first or
- only byte had to be put in the driver's communications
- buffer.
- 11 Number of calls to mklputc with a request for 2 bytes
- (second character always buffered).
- 12 DOS: Total number of interrupts processed by the
- interrupthandler for the asynchronous communications
- port.
- 13 DOS: Number of THRE interrupts.
- 14 DOS: Number of MSR interrupts (number of CTS signal
- changes).
- 15 DOS: Situations with a pending interrupt after a
- previous interrupt was processed.
-
- Specification of a counter number outside the indicated
- range will give unpredictable results.
-
- Return value Contents of the specified counter (zero after reset).
-
- Related functions "mklopen" on page 15
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 20
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- MKLSTOP
-
- Name mklstop - send the 'stop' command.
-
- C-language
-
- #include "mklapi.h"
- int mklstop(void);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION MKLSTOP% CDECL ()
-
- Description Send the 'stop'-command (ASCII 97) to the Märklin-Interface
- immediately. If polling was active at the time, it will be
- | stopped.
-
- | ■ OS/2: A simulated XOFF command is used to indicate the
- | COM-driver to hold yet buffered data. The stop-command
- | is then sent via a 'send-immediate' operation, ahead of
- | data that might be in the transmit buffer. The transmit
- | buffer is NOT purged, held data is preserved and sent
- | after a 'go'-command.
-
- | You may hear a low beep while the mklstop operation is
- | waiting to get access to the Märklin-Interface. If an
- | other error occured, mklstop will return an error code.
-
- | ■ DOS: The transmit buffer is purged and the stop-command
- | is then sent as regular data. New output is not
- | accepted anymore (it will be discarded).
-
- Warning: The 'stop' command could be sent by the mainline
- directly, but then would bypass the administrative
- functions of the driver. Any train or switchpoint control
- command received by the Märklin-Interface will cause a
- permanent drop of the CTS signal, making the control over
- the railroad from the computer permanently
- unavailable. The only possibility to resume control then
- is by manually hitting the 'go' key on the Märklin Central
- Control.
-
- Note: The timer does not stop with a mklstop(). This may
- cause strange effects from time-dependent calculations in
- your mainline!
-
- The 'stop' command might interfere with a 2-byte command of
- which the first byte was already transmitted, but the
- second byte not! In that case the 'stop' would not be
- recognised by the Märklin-Interface. Two consecutive
- 'stop'-commands will prevent the acceptation by the
- Märklin-Interface of any further commands from the
- computer. To make sure that the 'stop' command will be
- processed by the Märklin-Interface, with with the least
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 21
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- inconvenience, MKLAPI precedes the 'stop'-command with a
- 'go'-command:
- ■ If there was no command in transmission, then it won't
- harm.
- ■ If a 'broken' 2-byte command was in progress, then the
- 'go'-byte will be interpreted by the Märklin-Interface
- as the second byte. This will probably have a different
- effect than was foreseen, but since a 'stop' will
- follow, this will be of minor importance.
-
- A secundary effect of this setup is that it allows the
- mainline to call mklstop() more than once. The
- intermediate 'go' ensures that the Märklin-Interface
- doesn't block permanently.
-
- Return value Error code
-
- Related functions "mklgo" on page 13
-
-
-
- MKLTIME
-
- Name mkltime - obtain time since program start in milliseconds.
-
- C-language
-
- #include "mklapi.h"
- unsigned long int mkltime(void);
-
- QuickBASIC
-
- ' $INCLUDE: 'MKLAPI.INC'
- DECLARE FUNCTION MKLTIME& CDECL ()
-
- Description Returns the time in milliseconds after program start since
- it was updated with the last timer 'tick' (OS/2: 31.25
- msecs, DOS: 55 msecs).
-
- This is a little less accurate than mklmsecs, but consumes
- also less processor cycles.
-
- Return value Time in milliseconds after program start.
-
- Related functions "mklmsecs" on page 14
-
-
-
- MKLTRACE
-
- Name mkltrace - start or stop trace
-
- C-language
-
- #include "mklapi.h"
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 22
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- void mkltrace(short int signal);
-
- QuickBASIC trace facility not provided in DOS drivers
-
- Description Start or stop tracing of all data that is being sent to the
- Märklin-Interface and record the information, including a
- timestamp into the file MKLAPI.TRC.
-
- When signal is NOT zero, then tracing will be started, or
- restarted (old trace data will be discarded in that case).
- When signal is zero the trace is stopped and the trace file
- closed.
-
- It is my intention to replace this 'on/off' switch with a
- trace level facility (selection of events or data to be
- traced).
-
- Note: Since a buffered communications interface is used,
- the recording of trace data takes place at the moment the
- data is sent to the buffer. So the timestamp does not
- reflect the exact transmission time. Especially at moments
- when Märklin-Interface does not accept data (for example
- when it is transmitting Märklin S88 encoder-data), there
- may be a significant time difference!
-
- The utility MKLTRFMT.EXE can be used to produce a formatted
- trace report. All commands are printed hexadecimal and
- interpreted.
-
- See for details about the trace facility and a sample
- output: "Appendix B. Trace facility" on page 40.
-
- Return value Nothing.
-
- Note: Tracing is not provided by the DOS-drivers, but a dummy function is
- provided for combined OS/2 and OS/2 programs.
-
-
- MACRO SPECIFICATIONS
-
- A number of C-language only macro's is provided to make specification of
- some function-calls a little more simple, and to take care of possibly
- needed data conversion.
-
-
- MKLPUT1C
-
- Name mklput1c - send a single character to the interface.
-
- Usage #include "mklapi.h"
-
- void mklput1c(char);
-
- Prototype in mklapi.h
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 23
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- Description Macro to send a single character in the output buffer. The
- macro will expand into a mklputc().
-
- Return value See "mklputc" on page 17.
-
-
-
- MKLPUT2C
-
- Name mklput2c - send two characters to the interface.
-
- Usage #include "mklapi.h"
-
- void mklput2c(char1,char2);
-
- Prototype in mklapi.h
-
- Description Macro to send two consecutive character in the output
- buffer. The characters will guaranteed be sent in the
- given order, without the risk of intervening characters by
- the polling mechanism. The macro will expand into a
- mklputc().
-
- Return value See "mklputc" on page 17.
-
-
-
- USE OF TIMER
-
- At program start with mklopen(), the system time is taken as base for the
- functions mkltime and mklmsecs. These functions return a value in
- milliseconds after mklopen().
-
- The OS/2-driver uses standard OS/2 facilities, which will allow a precision
- of about 16 msecs (the time is updated in OS/2 control blocks every 31.25
- msecs).
-
- The DOS-driver uses the system hardware to obtain the system time. This
- allows a precision of 1 msec (with the function mklmsecs()). The function
- mkltime() gives a precision of about 28 msecs, and takes less machine
- instructions, which might be sufficient for most purposes.
-
- The use of this timer facility provided by the MKLAPI-drivers has the
- following advantages:
-
- ■ It is independent of system (processor) speed and other tasks running in
- your system. Many sample programs use some kind of processing loop to
- obtain a 'wait'-period, which might be dependent on processor speed and
- 'choke' the processor, during which time no other useful work is
- possible, or at least it is pretty complicated.
-
- ■ It is available with very little processor cycles, so it is not needed
- to call a 'universal' compiler-provided timer routine, which are
- generally much more cycle consuming.
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 24
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- The timer can be used for example for:
-
- ■ The application of an event-queue (for timed operations).
- ■ 'Wait'-intervals during without programming a loop.
- ■ Simulation of train mass (inertia) through gradually increasing or
- decreasing loc-speed.
-
- If you register this package, you'll receive a sample program which makes
- use of this feature.
-
- It is recommended to use mklsleep() in cyclic operations when running in a
- multitasking environment sucha as Windows, DesqView or in a DOS-session
- under OS/2.
-
-
- QUICKBASIC FUNCTION SPECIFICATIONS
-
- The functionality of the Märklin-driver for QuickBASIC is the same as for
- the drivers for C-language. However the following should be noted:
-
- ■ BASIC does not allow the underscore-sign ("_") in names, as is very
- common in C-language. Therefore the FUNCTIONS and DATA fields in the
- Märklin-driver for QuickBASIC have been adapted a little to BASIC
- conventions since in 0.9 of these drivers. All other differences are
- 'under the cover' (but see next item).
-
- ■ C-language uses by default a different way of parameter passing than
- BASIC, PASCAL and some other languages. But MicroSoft QuickBASIC
- compiler 4.5 allows the C-language convention to be used, and the
- Märklin-driver for QuickBASIC expects this convention to be used. This
- is reflected in the function specifications in MKLAPI.INC. If you use
- the MKLAPI.INC file (strongly recommended!), then you won't have to
- worry about these conventions.
-
-
-
- ERRORS AND SIGNALS
-
- The driver is designed not to disturb your screen with error-messages.
- | Therefore audiable signals are used to indicate unexpected problems.
-
- | The OS/2 and DOS-drivers produce the same warning-signals:
-
- | very high pitch, short 3000 Hz, 20 msec: Märklin-Interface The driver is
- | in stop-state, but some routine tries to send commands, which
- | are discarded.
-
- | medium high pitch, long 2000 Hz, 300 msec: Märklin-Interface seems to be
- | long-term blocked. The transmit task could not deliver its
- | data. Most likely the transmit buffer is full. Check the
- | 'stop'-light on the Märklin Central Control if a stop-condition
- | is the cause (manually set, or electrical problem).
-
- | high pitch, short 1000 Hz, 20 msec: A command-transmission did not finish
- | within the normal time. Too many commands may be queued, maybe
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 25
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- | because of a program loop.
-
- | medium pitch, short 440 Hz, 100 msec: Flushing of the buffer could not take
- | place in the expected time. Either transmission of buffered
- | data doesn't take place, or the buffer is being filled during
- | flushing faster than can be transmitted.
-
- | low pitch, short 200 Hz, 100 msec: a communications error occurred (OS/2).
- | Debugging information might be sent to STDERR (which you might
- | have redirected to a log-file to prevent disturbance of your
- | screen).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Specifications 26
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- INSTALLATION
-
-
-
- APPLICATION DEVELOPMENT CONSIDERATIONS
-
- This MKLAPI is a program development tool with a C-language or QuickBASIC
- compiler. You need MKLAPI.H (MKLAPI.INC for BASIC) at compile-time and one
- of the .OBJ files at LINK-time. It is an addition to the compiler and
- possibly other toolkits you may have for other purposes.
-
-
- C-COMPILER CONSIDERATIONS
-
- The following compiler properties apply.
-
- ■ The file MKLAPI.H must be #included in the program that references the
- driver routines (you can use the same header-file for OS/2 and DOS).
-
- ■ Memory model: OS/2: LARGE; DOS: SMALL or LARGE (your choice)
-
- ■ Calling conventions: C
-
- ■ OS/2: The '/MT' parameter should be specified with MicroSoft C-compiler
- 6.00a With IBM C SET/2 compiler '/Gm' should be specified among other
- parameters.
-
- ■ Generate underbars: On (Turbo-C option).
-
- Other compiler options are (probably) not of influence on the use of the
- Märklin-driver.
-
-
- MICROSOFT QUICKBASIC COMPILER 4.5 CONSIDERATIONS
-
- The QuickBASIC compiler is needed to create an object deck of your BASIC
- program. This OBJect file is combined with LMKLAPI.OBJ file as provided by
- this MKLAPI package to build an EXE-file with the LINK utility.
-
- ■ Calling conventions: C (DECLARE SUB|FUNCTION xxx CDECL ... etc)
-
-
-
- BUILDING AN EXE-FILE
-
- One of the OBJect files should be included in the link-step with your own
- OBJect file(s). I prefer to Compile and LINK with the help of the (N)MAKE
- utility.
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Installation 27
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- C-LANGUAGE AND DOS
-
- For the DOS sample application ("TRAIN") I use the following MAKE-file:
-
- ┌─────────────────────────────────────────────────────────────────────────┐
- │ │
- │ # │
- │ # MAKE TRAIN: Marklin Digital Train Control program (DOS version) │
- │ # - both SMARKLIN.OBJ and LMARKLIN.OBJ generated │
- │ # - LARGE memory model version used for TRAIN.EXE │
- │ # - With the compiler variable __DOS__ specified, certain │
- │ # #include-file selections are made in train2.c. When │
- │ # __DOS__ not specified the OS/2-inlcudes are selected. │
- │ # │
- │ │
- │ MDL=L │
- │ CL=-c -Zl -Zp -G0 -W3 -A$(MDL) -D__DOS__ -Fotrain.obj -Ot │
- │ LK=/NOD /PACKC:65500 /ST:4000 │
- │ │
- │ train.exe: train.obj smklapi.obj lmklapi.obj │
- │ LINK train+$(MDL)mklapi, train $(LK), nul, $(MDL)LIBCER; │
- │ │
- │ train.obj: train2.c train.h train.mak attrib.h attrib2.h common.h\ │
- │ matrix.h mklapi.h │
- │ CL $(CL) train2.c │
- │ │
- │ smklapi.obj: mklapi.asm mklapi.h train.mak │
- │ MASM -Dsmall mklapi.asm,smklapi; │
- │ │
- │ lmklapi.obj: mklapi.asm mklapi.h train.mak │
- │ MASM -Dlarge mklapi.asm,lmklapi; │
- │ │
- │ │
- └─────────────────────────────────────────────────────────────────────────┘
-
- Note: It contains switches to control the use of large or small memory
- models.
-
-
- C-LANGUAGE AND BASIC
-
- For a simple test-program in QuickBASIC I use the following batch-file:
-
- ┌─────────────────────────────────────────────────────────────────────────┐
- │ │
- │ @echo off │
- │ rem │
- │ rem Build Marklin Digital Test program for DOS QuickBASIC │
- │ rem Note: LMKLAPI.OBJ fetched from \C2\MARKLIN subdirectory │
- │ rem │
- │ BC test /S; │
- │ if errorlevel 0 LINK test+\c2\marklin\lmklapi; │
- │ │
- └─────────────────────────────────────────────────────────────────────────┘
-
-
- ───────────────────────────────────────────────────────────────────────────
- Installation 28
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- Note: With MicroSoft QuickBASIC compiler 4.5 the LMKLAPI.OBJ need to be
- included in the link. models.
-
-
- C-LANGUAGE AND OS2 1.3
-
- For the 16-bits OS/2-sample application ("TRAIN2") I use the following
- MAKE-file for MicroSoft C-compiler 6.00a and IBM OS/2 Program Development
- Toolkit 1.2/1.3:
-
- ┌─────────────────────────────────────────────────────────────────────────┐
- │ │
- │ # │
- │ # MAKE TREIN: Marklin Digital Train Control │
- │ # │
- │ # To be used with MicroSoft C-compiler 6.00a │
- │ # │
- │ # With IBM C/2 1.1 compiler specify '__IBMC2__' compiler option │
- │ # │
- │ # 'OS2' compiler variable needed for OS/2 object of TRAIN2! │
- │ # │
- │ │
- │ CL=-c -Zp -Zl -W3 -MT │
- │ LK=/A:16 /PACKC:65000 /NOI /NOD │
- │ L1=LLIBCMT OS2 │
- │ │
- │ train2.exe: train2.obj mklapi2.obj train2.def │
- │ LINK train2+mklapi2, $@ $(LK), NUL, $(L1), train2.def │
- │ │
- │ train2.obj: train2.c train2.h attrib2.h mklapi.h common.h matrix.h │
- │ CL $(CL) train2.c │
- │ │
- │ mklapi2.obj: mklapi2.c │
- │ CL $(CL) mklapi2.c │
- │ │
- │ │
- └─────────────────────────────────────────────────────────────────────────┘
-
- The contents of the corresponding LINK .DEF-file are:
-
- ┌─────────────────────────────────────────────────────────────────────────┐
- │ │
- │ ; │
- │ ;******* Marklin Train Control Program Definition File (.DEF) ******** │
- │ ; For: 1) 16-bit version for OS/2 1.3 and MS C-compiler │
- │ ; 2) 32-bit version for OS/2 2.0 and IBM C Set/2 compiler │
- │ │
- │ NAME TRAIN2 WINDOWCOMPAT │
- │ │
- │ DESCRIPTION 'Marklin Train Control. Copyright (1991,93) Rob Hamerling' │
- │ PROTMODE │
- │ HEAPSIZE 4096 │
- │ STACKSIZE 8192 │
- │ │
- └─────────────────────────────────────────────────────────────────────────┘
-
- ───────────────────────────────────────────────────────────────────────────
- Installation 29
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- C-LANGUAGE AND OS2 2.0+
-
- For the 32-bits OS/2-sample application ("TRAIN3"), the following MAKE-file
- is appropriate for IBM C SET/2 compiler and IBM OS/2 Program Development
- Toolkit 2.0:
-
- ┌─────────────────────────────────────────────────────────────────────────┐
- │ │
- │ # │
- │ # MAKE TREIN: Marklin Digital Train Control program │
- │ # │
- │ │
- │ CL=/c /G3 /Gd+ /Gm+ /Re /Se /Sm /Ss │
- │ LK=/NOI /PACKC:65500 /ALIGN:4 /BASE:0x10000 /EXEPACK │
- │ │
- │ train3.exe: train3.obj mklapi3.obj │
- │ link386 $**, $@ $(LK), NUL, , train2.def │
- │ │
- │ train3.obj: train2.c │
- │ icc $(CL) /Fotrain3.obj train2.c │
- │ │
- │ mklapi3.obj: mklapi2.c mklapi.h │
- │ icc $(CL) /Fomklapi3.obj mklapi2.c │
- │ │
- │ │
- └─────────────────────────────────────────────────────────────────────────┘
-
- Note: The same .DEF-file is used as for the 16-bit version.
-
-
- STORAGE AND PERFORMANCE
-
- There is yet not much to say about storage and performance of the driver.
- It is highly optimised code, and probably only a minor part of the 'real'
- railroad control program.
-
-
- MEMORY UTILISATION
-
- It is difficult to say how many storage is occupied by the OS/2-version of
- the Märklin-driver.
-
- The DOS-version requires about 4K bytes of storage.
-
-
- PROCESSOR UTILISATION
-
- You might be curious about the cycles that will be consumed by the polling
- task. I've done some measurements under OS/2 version 1.3 with the sample
- program TRAIN2. On an 8 Mhz AT (80286) the polling takes between 10% and
- 12% of the processor time (difference in processor utilisation between
- polling ON and OFF). This number is practically independent of the number
- of Märklin S88 encoder's that are specified for polling, but the polling
- frequency is also lower!
-
-
- ───────────────────────────────────────────────────────────────────────────
- Installation 30
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- COMMENTS, REMARKS, BUG-REPORTS
-
- If there are bugs, requirements or questions about this Märklin-driver, the
- documentation or the sample program (that you get when you register),
- please send me a message through the FIDO network. You can find my name
- and node-(point)-number in the introduction of this document.
-
- Enjoy and good luck with your program development! May this driver lead to
- a very attractive and succesful model railroad control program!
-
- Do not 'forget' to register!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Installation 31
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- APPENDIX A. MKLAPI INTERNALS
-
- This appendix describes a number of design arguments for this driver and
- explains decisions where a choice had to be made.
-
-
- MULTITASKING
-
- There are many situations in real-time programming, where you want the
- system to do something for you, while in the meantime you would like to do
- something else in the mainline (before the first piece of program
- completes).
-
- An example of this is reading sensor boxes. While you have to wait for the
- response of the Märklin S88 encoder, you might want to update your screen,
- read data from disk, or process keyboard input. In many sample programs
- that I have seen, the wait is frequently done in the form of a short loop
- (a for- or while-statement). This means that the processor is working, in
- fact consuming cycles, while you cannot do anything (unless you make a more
- 'complicated' loop). And in many cases you have to experiment with this
- loop to get the needed wait-interval (not too long and not too short).
- Running the same program on a machine with a different processor-speed,
- requires a change in the loop.
-
- A solution for this is to have multiple programs to run simultaneously.
- Executing multiple programs (tasks) in parallel is called multi-tasking.
- Since we are generally dealing with a single micro processor, the tasks are
- simultaneaously present in memory, but only 1 of them is actually
- processing. There must be some mechanism to switch the processor between
- the tasks.
-
- Some operating environments have standard facilities for this (OS/2,
- Windows), but DOS doesn't. Under DOS you have to do it yourself. By
- intercepting hardware interupts, or the timer-tick interrupt it is possible
- to implement a kind of task-switching.
-
- The polling mechanism in the Märklin-driver is a form of multi-tasking.
- For OS/2 it uses the standard OS/2 facilities (called multi-threading), for
- DOS it uses the system timer to execute periodical actions independently
- from the main-program, and also the hardware interrupts of the asynchronous
- communications port to perform some communications work. So in fact there
- are two 'extra' tasks in the polling mechanism:
-
- ■ Periodically send read-commands to the Märklin-Interface.
- ■ Receive the responses and put them in the appropriate place in the
- sensor-array.
-
- Although you don't have to bother about the polling mechanism, it does have
- some influence on the design of your railroad control program. These
- practical aspects are explained below.
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 32
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- READING MäRKLIN S88 ENCODERS
-
- The driver generates read-sensor commands in the following way:
-
- 1. After polling is activated periodically a sensor-read command is
- transmitted to read multiple Märklin S88 encoders.
-
- 2. The receive-part of the communications task is signalled that a response
- from the Märklin-Interface should be expected. The receive continues as
- long as not all expected input is received, or an unexpected long time
- had to be waited.
-
- 3. After processing the response, the system waits some time before issuing
- a new read command (typically 100 msec).
-
- 4. Even if for some reason the previous poll did not finish within
- reasonable time (typically 500 msec), a new read-command is issued.
-
- 5. If the transmit routine is in use by the mainline program (such as
- sending train-commands), polling is suspended for a short while (shorter
- than the normal polling interval).
-
- The Märklin-Interface documentation indicates that the average time to read
- the last poll-response is between 45 and 300 milliseconds, depending on how
- many Märklin S88 encoder's are being read. From 'life'-tests I have
- concluded:
-
- ■ The total polling cycle (the time between two consecutive read commands)
- is so short that the delay between the change of a switch and making the
- change represented in the sensor-array is short enough for most
- practical situation.
- ■ The poll wait interval is long enough to allow sending of many commands
- from the mainline between read commands. To make this sure there is a
- built-in priority mechanism in the polling routine: it waits with
- generating a poll when another program uses mklputc() routine!
- ■ The frequency of the polls is low enough to ensure that not all CPU
- cycles are spent on polling, in stead of 'real' work.
-
- Polling is programmed as follows:
-
- 1. After calling mklpoll() of mklgo() with a non-zero parametervalue a
- '192'-byte is transmitted, meaning that the Interface will RESET the
- bits with next read-sensor commands.
- 2. Periodically a '128 + MAXSENSOR' byte, meaning that the Interface will
- report a group of sensors, up till the limit that was specified with the
- latest mklpoll() or mklgo().
-
-
- | The received data is collected in 2 sensor-arrays:
-
- | 1. Collection of 'raw' data from the Märklin-Interface. Array-1 always
- | represents the current switch positions of all polled S88's, apart from
- | a slight delay between consecutive reads.
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 33
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
-
- | ╔═══════════════════╗
- | ║ ║
- | ║ Marklin Interface ║
- | ║ ║
- | ╚═════════════════╝
- | ║ ║
- | ║ ║
- | ╔══════════════════════║══║═════════════════════════════════════╗
- | ║ READ S88 1...6 ═══╝ ║ Computer ║
- | ║ (by polling task) ║ ║
- | ║ ║ ║
- | ║ ║ ║
- | ║ ╔═════╦═════╦══╩══╦═════╦═════╗ ║
- | ║ 'move' ║ ║ ║ ║ ║ ║ ║
- | ║ ║ ║ ║ ║ ║ ║ ║
- | ║ ╔════╦════╦════╦════╦════╦════╦══ ═ ║
- | ║ ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ array-1 ║
- | ║ ╚══╦══╩══╦══╩══╦╦═╩══╦══╩══╦══╩══╦══╩══ ═ ║
- | ║ ║ ║
- | ║ 'or' ║ ║ ║║(2) ║ ║ ║ ║
- | ║ ║ ║
- | ║ ╔════╦════╦═══╦════╦════╦════╦══ ═ ║
- | ║ ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║ 6 ║ array-2 ║
- | ║ ╚═════╩═════╩══╦══╩═════╩═════╩═════╩══ ═ ║
- | ║ ║ ║
- | ║ ║(1) actions by: mklgetsn(3) ║
- | ║ ║ 1. return word 3 of array-2 ║
- | ║ 2. copy word 3 array-1 to array-2 ║
- | ║ ║
- | ╚═══════════════════════════════════════════════════════════════╝
-
-
- | Figure 1. Organisation of reading S88's (polling): In this sample a
- | group-read of 6 S88-boxes is used.
-
- | 2. Cumulative 'on'-bits since most recent mklgetsn() for each specific S88
- | in Array-2.
-
- | The incoming data of the 'read group' is stored in array-1, and all 1-bits
- | are copied immediately to array 2 with an 'or'-operation. So array-2 is a
- | cumulation of 'on' switch positions during a certain period.
-
- | When mklgetsn(x) is executed, the contents of word-x in array-2 are
- | returned to the caller. At the same time word-x in array-2 is refreshed
- | with the then current contents of array-1. So a second mklgetsn()
- | immediately after the first gives the actual status ((3)).
- | A second call is required if you want to know for sure if the switch is
- | currently in the 'off'-position after it has been 'on' since the most
- | recent mklgetsn().
-
-
- ────────────────────
- (3) Function mklgetsn might be changed later to be able to specify that
- you need data from the first or from the second array.
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 34
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- | This mechanism is suitable for all types of switches that are applied in
- | model-railroads, and ensures that you won't miss any 'switch-on' condition,
- | even if it is 'on' during a very short period. This organisation is
- | illustrated in Reading Märklin S88 encoders on page 33.
-
- You have to be careful with specifying more Märklin S88 encoder boxes in
- mklpoll() or mklgo() than you really have in your model railroad yard.
-
- ■ It is not useful, since the Märklin-Interface will return all zeroes for
- not-connected Märklin S88 encoder's.
- ■ During the time the Märklin-Interface sends the responses to the
- computer, no commands are accepted by the Interface.
-
- So specifying more Märklin S88 encoders than really active will unnecessary
- downgrade the responsiveness of your program. You might decide to stop
- | polling during processor-intensive work, or not to use polling at all.
-
- | Note: The following consequences of this mechanism:
-
- | ■ If you use this driver, you should not issue read-commands from the
- | mainline. The driver does not intercept read-commands from the
- | mainline, but it will intercept all data from the Interface and not
- | return it to the mainline! This will disturb the administration of the
- | internal sensor numbering, which is depending entirely on the number of
- | incoming bytes.
- | ■ This driver does not yet support physically reading of individual
- | Märklin S88 encoders, and it is not possible to use polling with
- | no-reset (command 128 in stead of 192). This may look like a
- | limitation, especially with the use of reed-switches or contact-rails.
- | But once you are familiar with the convenience of the polling mechanism
- | and the functionality of mklgetsn(), this should not be a practical
- | limitation.
-
-
-
- COMMUNICATIONS INTERFACE SPECIFICATION
-
- The Märklin-Interface contains a device driver level communication facility
- with between computer and Märklin-Interface, but with a rather high level
- interface for the application programmer. It contains many basic
- functions, that otherwise have to be programmed yourself. However, it
- enforces a specific organisation of your program and has some limitations.
-
- Some of the internals of the communications task are briefly explained to
- show why it works as it works now, and may prevent questions. On the other
- hand, it may trigger suggestions for changes! Feel free to go in
- discussion with me!
-
- Wiring Only the Read (RD), write (TD) and Clear-to-Send (CTS) lead
- are connected. Thus using DTR and RTS from the computer
- will have no effect of any kind and obviously DSR and DCD
- (sometimes also called CD or RLSD) will not be used by the
- Märklin-Interface Nevertheless DTR and RTS are set by the
- driver with mklopen(). This allows for the use of a
- break-out box and/or another computer in stead of the
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 35
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- Märklin-Interface for debugging of your program (since a PC
- commmunications program usually needs these leads to be
- active). The driver itself works properly without the DSR
- and DCD leads.
-
- Speed The Märklin-Interface allows only 2400 bps, and 8-bits
- data, NO parity, and 2 stop bits. These are the built-in
- defaults of the driver, however a different speed can be
- specified at open-time (might be useful for test and
- debugging).
-
- FIFO So called FIFO hardware buffering, provided by the newer
- UART-chips (such as 16550 AFN) on asynchronous
- communication ports is handled as follows by the drivers:
- ■ The DOS-driver does not actively support FIFO-mode, but
- FIFO-support is in plan.
- ■ The OS/2-MKLAPI uses the facilities of the device driver
- COM[xx].SYS for operation of the COM-port. When FIFO is
- is active for the COM-port before opening, it is left
- active and uses this feature. Use the MODE-command to
- control this feature.
-
- FIFO-mode may not provide a considerable improvement:
- ■ The Märklin-Interface operates strictly half-duplex, it
- is either in receive mode, or in transmit mode. During
- data transfer (either way) CTS is dropped while
- transmitting each command-byte and may remain low for a
- 'considerable' time while command interpretation is in
- progress and S88-positions are being sent back to the
- computer. This does not suit very well with the FIFO
- for transmitbuffering. It might be useful for receive,
- since in many cases at least 2 bytes are received per
- S88. being read. The support for this is in
- consideration.
- ■ Since the speed is 2400 bps, most systems can easily
- keep up with the non-buffered mode of operation. The
- highly effective interrupt handler of the DOS-driver may
- make the netto effect of reduced CPU-cycles for
- interrupt handling only minimal.
-
- But FIFO-mode may be helpful in a multitasking environment.
- Use the MODE command with BUFFER=ON, to activate it, when
- desired.
-
- Output flow control The CTS signal is dropped by Märklin-Interface during
- data transfer (during receive and transmit: the
- Märklin-Interface is strictly half-duplex). The CTS signal
- is used for 'hardware output flow control' from the
- computer. So the transmit routines will not send data when
- CTS is not high, but will automatically resume transmission
- when CTS rises and the buffer contains any data to
- transmit.
-
- DOS Although not strictly needed, the DOS-version of the
- Märklin-driver has the transmit interrupt (THRE) active to
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 36
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- be able to run the driver against a full-duplex interface
- (with continuous CTS), such as another PC with a diagnostic
- communications program. The transmit interrupt uses the
- same code as the MSR interrupt.
-
- For initial testing of programs without actually running a
- model railroad, you could use a 'wrap-plug' to partially
- simulate the Märklin-Interface. The RTS signal (raised by
- the driver) is feeded back to CTS, so the driver is always
- able transmit.
-
- If also send and receive (generally pins 2 and 3) leads are
- wrapped back, then the transmitted data is treated as S88
- response. This may cause
-
- Input flow control There is no form of input flow control allowed by the
- Märklin-Interface: there is no way to signal the
- Märklin-Interface to stop sending. This will not be a
- problem for the driver, since there is enough buffering and
- CPU-power to process the low volume input in time.
-
- XON/XOFF flow control Not used. This type of flow-control is not supported
- by the Märklin-Interface, since the commands for the
- Märklin-Interface may contain these characters!
-
- OS/2: The standard COM[xx].SYS of OS/2 allows simulated
- XON/XOFF. A DosDevIOCtl-'XOFF' is issued to stop
- transmitting buffered data when a 'stop'-command has to be
- transmitted. A DosDevIOCtl-'XON' is issued when a
- subsequent 'go'-command is issued.
-
- Null stripping The OS/2 COM[xx].SYS allows null stripping. There are at
- least 2 reasons for this feature not to be activated:
- ■ Märklin S88 encoder's may respond with all bits zero
- ■ Switch 256 is addressed as ASCII 0.
-
- Command parsing The driver does not interpret the data it sends to the
- Märklin-Interface. It means that it is completely the
- responsibility of the mainline to ensure proper command
- sequences.
-
- Note: The driver does not send automatically a
- switch-'relax' command (ASCII 32) after a switch command
- (ASCII 33 or 34)! You may write a shell for Märklin
- command syntax checking.
-
-
-
- PROBLEMS WITH OS/2 COM[XX].SYS
-
- The Com-port driver of some versions of OS/2 for non-PS/2 machines
- (COM01.SYS) does have some known problems, such as:
-
- ■ READ and WRITE timout specifications cannot be changed from the built-in
- default of 1 minute.
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 37
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- When encountering this kind of problems, I could recommend Gerry Rozema's
- replacement driver for AT-type machines (COM16540.SYS, or COM16550.SYS, as
- appropriate for your system's COM-port). For OS/2 2.0 there is also a
- driver SIO.SYS by Ray Gwinn, that might be useful when having problems with
- the standard OS/2 2.0 drivers.
-
- These alternative drivers are available on Bulletin Boards such as
- PC-Square in The Netherlands (FIDO node 2:512/4, telephone 31.79.424107).
-
-
- OS/2 AND DOS DIFFERENCES
-
- Although all versions of this Märklin-driver offer a consistent application
- programming interface for communication with the Märklin-Interface, it is
- most likely that there will be differences between the programs using
- either of them. Some of these differences might be:
-
- ■ When running in a multitasking environment, the program should give
- other tasks the chance to run (yield the processor).
- ∙ With OS/2 other tasks will get some control automatically
- (pre-emptive multi-tasking), but nevertheless the program should at
- least use DosSleep(0) when it does not need the processor for some
- time.
- ∙ DOS: apart from the built-in multitasking of the Märklin-driver which
- controls itself, you probably won't run other programs. In that case
- you will not have to release the processor.
- ∙ When running a DOS-program under another multitasker (Windows,
- Desqview), periodic calls of mklsleep() are recommended.
-
- ■ The OS/2 driver makes use of the standard multitasking (multithreading)
- facilities. Therefore any program using this driver should specify /MT
- for MicroSoft C-compiler 6.00a. The different include-search might be
- indicated with a compiler option (-I for most C-compilers).
-
- The DOS driver should use the normal include directory.
-
- ■ The OS/2 driver requires the LARGE memory model compiler options and use
- the LLIBCMT library for LINK (automatic with /MT). The DOS-version is
- for either the SMALL (/AS) or LARGE memory model (/AL), use the
- respectively the SLIBCE or LLIBCE library with LINK.
-
- ■ The standard OS/2-driver (COM[xx].SYS) will not accept new output data
- in stop-state, but will transmit possibly retained data (from before
- mklstop) after a call to 'mklgo'. Some alternative drivers (such as
- SIO.COM) do accept new data from mklputc, but keep it internally
- buffered. No more data is accepted when the buffer is full. After
- mklgo() all buffered data, old and new, will be transmitted.
-
- The DOS-drivers refuse all new output data in stop-state.
-
- ■ It is an absolute must, that the Märklin-driver under DOS is terminated
- with a call to mklclose() to de-activate the interrupts for com-port and
- timer. Therefore it is recommended to use a routine to intercept Ctrl-C
- or Ctrl-Break actions from the keyboard.
-
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 38
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- Under OS/2 this attitude is recommended, but not an absolute must.
-
- In both cases it is recommended to direct the Ctrl-C signal to a
- controlled finish of your railroad control program: you probably do not
- want to terminate your program with uncontrolled running trains!
-
- ■ The display of information about the state of your railroad on the
- computer screen will probably use different techniques, such as the way
- cursor and color will be used:
- 1. OS/2: Presentation Manager (graphics) or VIO routines.
- 2. DOS: Windows (graphics)
- 3. ANSI escape-sequences (compatible between OS/2 and DOS)
-
- The sample program you'll receive after registration is a single source
- for environments 1 and 3. My own programs are primarily for OS/2 and I
- prefer to use the OS/2 facilities and those of the Program Development
- Toolkit as good as possible. For instance I use VIO-routines for color
- and cursor manipulation.
-
- To be able to run my sample program under DOS, I included some extra
- routines in the header-file. These routines translate color and cursor
- manipulations with OS/2 VIO-calls into equivalent ANSI escape sequences.
- When ANSI is active under DOS (with DEVICE=[path]\ANSI.SYS in
- CONFIG.SYS), the visual effects are the same as with the OS/2 version.
-
- When there is no possibility to use the same code for OS/2 and DOS, you
- might consider using a compiler variable (with the -D compiler option) to
- distinguish which pieces of codes are OS/2 or DOS specific. See for an
- example the MAKE-files in the MKLAPI package.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix A. MKLAPI Internals 39
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- APPENDIX B. TRACE FACILITY
-
-
-
- TRACE RECORDS
-
- The trace facility produces the following records (8 bytes each):
-
-
- long int timestamp; /* value of mkltime */
- int fl:1, /* flag: 0=output, 1=input */
- nn:7, /* (in start-of-trace record) trace source */
- /* MKLAPI: DOS = 1; OS/2 1.x = 2; OS/2 2.x = 3 */
- sw:8; /* S88 box number on input */
- char c1, /* first character */
- c2; /* second character */
-
- The first record after starting a trace contains 0xFF as first and second
- character.
-
-
- SAMPLE
-
- The output of the trace formatting program MKLTRFMT will look like:
-
-
- time I/O cmd data description
- ------------ --- --- ---- --------------------------------------
- 45.050 Start of trace (MKLAPI OS/2 1.x)
- +0.045 O 1A 13 Loc 19 speed 10 Funktion=ON
- +0.350 O 22 3F switchpoint 63: branch
- +0.760 O 20 switchpoint release
- +1.850 O C0 read S88's with reset
- +4.850 O 82 read S88 1 t/m 2
- +4.881 I 1801 S88 1 ON=4,5,16
- +4.881 I 090E S88 2 ON=,8,13,14,15
- +5.000 O 61 STOP
-
- This is not a complete trace, just some parts to show the essentials.
-
- MKLTRFMT.EXE is a 'family mode' application: it will run under OS/2 and
- DOS. No parameters are required, but you may specify the input filename
- [including path] if your trace is in another directory or named other than
- MKLAPI.TRC, which is the default (output filename of MKLAPI).
-
- MKLTRFMT writes the output to 'stdout', which is normally the computer
- display. But the output may be redirected to your printer or to a file.
- So you could use for example the command:
-
- MKLTRFMT >TRACE.FMT
-
- so that you could look afterwards with a text editor or file browse utility
- | in TRACE.FMT for the formatted trace.
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix B. Trace facility 40
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- | APPENDIX C. MäRKLIN-INTERFACE PECULIARITIES
-
- | When writing a model railroad control program (with or without this
- | driver), you should be aware of some peculiarities, which are not very well
- | (or not at all) documented by Märklin. With experiments during development
- | of MKLAPI I have found for example:
-
- | ■ Sending 2 consecutive change-direction commands to the same loc does not
- | put the loc back in the original direction. A zero-speed command
- | between them is a good circumvention.
-
- | ■ When the Märklin-Interface is in 'stop'-state:
- | ∙ Permanent blocking (having to push the 'go'-button on the Märklin
- | Central Control) does occur only with commands to train-decoders and
- | switch-point or light decoders (K83 or K84).
- | ∙ Reading Märklin S88 encoders (polling) may continue. But since the
- | changes are not sent from the control-box to the Märklin-Interface,
- | it is not very useful.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix C. Märklin-Interface peculiarities 41
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- APPENDIX D. SUMMARY OF CHANGES
-
- 0.7 First beta release: June 1992
-
- 0.8 released: October 1992
- ■ The time-base value in mkltime has been changed from 55 msec to 1
- msec!(updating of mkltime still on timer-tick basis: once per 55
- msecs in DOS, once per 31.25 msecs in OS/2).
- ■ DOS: High precision timer routine added: mklmsecs(). This gives
- the period since line to opening of communication with
- Märklin-Interface with 1 msec accuracy.
- ■ OS/2: Trace facility added (see also "Appendix B. Trace facility"
- on page 40), start and stop of trace via procedure call
- mkltrace(). Output to and input from the Märklin-Interface is
- traced. A trace-file formatting utility (MKLTRFMT.EXE) is added
- to package. I have tried to add this trace facility also in the
- DOS driver, but I did not cucceed so far. It is rather
- complicated to use DOS facilities during interrupt handling
- (tracing must be located in the com-port and timer interrupt
- routines).
- ■ A procedure 'mklsleep' added to make your DOS-program 'friendly'
- for some popular multitasking environments (such DOS-box of OS/2,
- Desqview, Windows).
- ■ DOS: mklflush times out after 3 seconds when transmit buffer could
- not be flushed.
- ■ Some bugs fixed:
- ∙ mklflush() of OS/2 version watched the INput in stead of OUTput
- queue.
- ∙ DOS: DTR and RTS now turned off before finishing program.
-
- 0.9 released: March 1993
- ■ A 32-bits driver for OS/2 2.0+ (MKLAPI3.OBJ) has been added, with
- same functionality as MKLAPI2, including the new features below!
- ■ 'MKLAPI' now also useable by programs translated with the
- MicroSoft QuickBASIC compiler 4.5. Since QuickBASIC does not
- allow underscores in names, all externally used names have been
- changed, for example: mklopen() is now called mklopen(). The
- C-language calling convention must be specified in the source (see
- MKLAPI.INC), and the file LMKLAPI.OBJ should be used with LINK.
- All function specifications have been changed, and additions made
- for program development with MicroSoft QuickBASIC compiler 4.5.
- ■ mkltime() is not anymore an external variable, but a function
- returning the value of the time, expressed in milliseconds, but
- with the precision of the timer tick.
- ■ mklmsecs() now also a function returning the time, but in exact
- milliseconds (DOS only).
- ■ With the OS/2 drivers, the transmissions in STOP-state (after
- mklstop) may now be buffered in stead of discarded (until buffer
- full, then discarded). This depends on the COM.SYS device
- drivers, or replacements thereof.
- ■ After the first mklstop subsequent calls of mklstop are ignored
- and nothing sent to the Märklin-Interface until mklgo has been
- called.
- ■ mklstop() and mklgo() now give a returncode (0 = OK, otherwise a
- transmission problem exists).
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix D. Summary of changes 42
-
- MKLAPI
- ───────────────────────────────────────────────────────────────────────────
-
-
- ■ Simple Switchpoint test program (incl c-source) added to MKLAPI
- package.
- ■ Added counters for and a function mklstats() for statistical
- purposes and debugging.
- ■ Polling optimised: a single 'reset after read S88' (192) is issued
- after mklpoll() and mklgo(), subsequently only 'read group of n
- S88s' (128+n) commands are sent periodically (previously both
- commands were sent after each interval).
-
- 1.0 released: May 1993
- ■ Names and references to 'MARKLIN' renamed to MKLAPI, where the
- driver is meant (and not Märklin-components). Include-files and
- sources that include header files should be changed.
- ■ DOS-drivers now take RS232 port addresses from the BIOS data-area,
- and performs a simple check if the port is not already in use.
- ■ Sound support added to DOS-drivers, and the function made callable
- by mainline. Warning signals of OS/2- and DOS-drivers
- 'harmonised'.
- ■ Polling and storage of S88 bit-settings changed to get better
- operation for all types of switches.
- ■ mklstop() and mklgo() made more reliable.
- ■ mklsleep() accepts now specification of an interval (pause) time
- ■ mklmsecs(), mklsound() and mklsleep() functions now present in
- both OS/2 and DOS versions for more compatibility between OS/2 and
- DOS versions of programs that make use of the MKLAPI-driver.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────
- Appendix D. Summary of changes 43