English translation by Mick Lock verified by Peter West 1996,1997
-----------------------------------------------------------------


MIDI.PRG
********

This is a driver for using the MIDI interface with the file functions that 
are defined in SERSOFT.TXT.

General
-------
############# Currently still an Experimental version #################

This driver belongs to the HSMODA package. Be aware that it is for 
'normal' data transmission and not for music software, which is the usual 
purpose of the MIDI interface. Those who do not need to use the MIDI 
interface for 'normal' data transmission, will not require this driver.


Communication parameters
------------------------
It will support all that the ACIA and RxD/TxD interface can handle.

Baud rate: 31250, 7812
Handshake: 'None', 'XON/XOFF'
Character format: 7e2, 7o2, 7e1, 7o1, 8n2, 8n1, 8e1, 8o1


Configuration
-------------
Configuration is achieved using the SETTER.TTP program. For operating 
details see SETTER.TXT.

RBL
Sets the Receive Buffer Length. Minimum 16, Normal 256, Maximum 65534.

TBL
Sets the Transmit Buffer Length. Minimum 16, Normal 256, Maximum 65534.

OMIX
The driver can hook into the XBIOS call to intercept and handle the Iorec 
and Midiws for the original MIDI interface. If you answer 'No' this driver 
will not hook into the XBIOS, with 'Yes' it will. 'Yes' should only be 
required if your software wants to use the MIDI original routines and not 
the new GEMDOS interface or the new BIOS numbers.

MISY
The driver can install itself into one of two places for interrupt 
handling. The fastest MIDI variant is the  MFP-I4 Interupt, whose vector 
is at address $118. Using it, you must set MISY= 'No'. As an alternative 
the driver can hook into the midisys vector of the KBDVECS structure if 
you set MISY= 'Yes'.


Compatibility
-------------
When TOS 1.02 and upwards is being used the original BIOS interface for 
MIDI (BIOS number 3, number 4 for Bcostat) will be accepted by this 
driver, by registering itself in the xco*-vectors. This causes no 
additional overhead.

With the configuration point 'OMIX' you can also activate the functions 
Midiws and Iorec for the original MIDI. To do this, however, the driver 
must hook itself into the XBIOS Trap.

In contrast to the original routines, transmission via Bconout or Midiws 
is always Interrupt controlled. In the original response Midiws only 
returned after all characters were transmitted, now it returns as soon as 
all characters are in the transmit buffer. This could possibly irritate 
music software.

'MISY'='Yes' is more compatible than 'No', but somewhat slower.


Screen savers
-------------
There may be problems with screen savers that hook into some ACIA 
Interrupts and similar. You can partly remove these problems if the screen 
saver is loaded after the MIDI.PRG. This generally means, but not always, 
that the MIDI Interrupt handling will be slower.


(Internal:) Implemention variants
---------------------------------
Transmission is also Interrupt-controlled. If one polls Bit1 of the extra 
Status register again in the transmit Interrupt (though one doesn't need 
to, for when transmitting with polling the transmit buffer will be empty 
by definition (otherwise there would be chaos anyway), and therefore one 
cannot write anything to the ACIA in any case), there is no need to 
intercept Midiws and Bconout-MIDI calls as these are transmitting with 
polling and not disturbing the structures of this driver. Although they 
could interfere with an Interrupt-controlled transmission, that should not 
happen because either old programs use these non-Interrupt calls (where 
polling Midiws may be necessary for the sake of compatibility), or new 
programs operate via GEMDOS or the higher BIOS number. Because MIDI is not 
always #3 in the BIOS, one has to enter the number of a hooked-in driver 
into the RSVF anyway, and only support the old #3 for the sake of 
compatibility.

You have to decide how far you wish to take the optimisation (swapping 
storage space and clarity for speed). 31250Bd on Receive means an Interupt 
frequency of 3125Hz with 8N1 and an Interrupt response time of less than 
320us. The 68000/8MHZ needs 0.5us for a WORD memory-access. The saving of 
8 registers by TOS (as a LONG) will therefore already take 8uS, to which 
must be added the reaction time of the CPU. After processing one needs 
another 8uS in the Interrupt for restoring. The IKBD-ACIA at 7812.5Bd is 
slow in comparison.

'MISY'='No': MIDI.PRG is directly in the MFP-I4-Interupt (vector $118), 
the fastest possiblity, all MIDI vectors in KBDVECS are dead. Some music 
software could be incompatible with this, but the driver is not intended 
for this. On installation it throws out everything from the MFP-I4-Int, 
eg. Templmon. So start Templmon first after MIDI.PRG or use 'MISY'='No'.

'MISY'='Yes': MIDI.PRG is only in the KBDVECS.Midisys vector. Slower, but 
more compatible. Only KBDVECS.midivec and KBDVECS.vmiderr are dead.


Other variants, which may be realised in alternative ways:

As midisys(), slowest, midivec() and vmiderr() are used, remaining 
Interrupt conditions are handled by midisys() itself.



(For the programmer:) The software side of the MIDI interface
=============================================================

Under TOS, MIDI data is always sent directly. There is no transmit IOREC. 
Only receive data is handled by Interrupts, a receive IOREC exists (XBIOS 
14 Iorec (device 2)). XBIOS 15 Rsconf does not exist. In addition, XBIOS 
12 Midiwis exists for transmitting byte sequences. This function works as 
polling. In BIOS, MIDI is normally device 3, except with BIOS 8 Bcostat 
where it is 4.

XBIOS 34 Kbdvbase supplies a data block,that contains a pointer to some 
routines that are associated with MIDI and IKBD. Unfortunately these 
routines are often falsely described, even the 'Profibuch' book has errors 
in it.

The MIDI-ACIA and IKBD-ACIA report their Interrupt active with a 'OR' 
combined message (their L-active open collector outputs are connected to 
each other) over the same input (I4) of the MFP (ST-MFP) that points to 
the MFP Interrupt-vector at address $0118.

Here lurks the first trap: The MFP only generates an Interrupt when a H/L 
transition occurs at the I4 port. This transition only occurs when there's 
a change from 'Both ACIA with no Interrupt requests' to 'at least one ACIA 
Interrupt request'. If you now reset the Interrupt request only in the MFP 
and do not interrogate either ACIA until I4 is once again H, then I4 will 
remain L and the MFP will report no further ACIA-Interrupts. This may 
occur, for instance, if in a very early phase of the system initialisation 
there is data incoming to the MIDI-port.


Kbdvbase (XBIOS 34)
-------------------
This function supplies a pointer to a data block with pointers to 
different routines for connection with MIDI and IKBD.

Typedef struct {
 void (*midivec)();   /* Midi input */
 void (*vkbderr)();   /* Keyboard error (default: RTS only) */
 void (*vmiderr)();   /* MIDI error (default: RTS only) */
 void (*statvec)();   /* Status of IKBD read (default: RTS only) */
 void (*mousevec)();  /* Interrograte mouse */
 void (*clockvec)();  /* Interrograte time */
 void (*joyvec)();    /* Interrograte joystick (default: RTS only) */
 void (*midisys)();   /* MIDI system vector */
 void (*ikbdsys)();   /* IKBD system vector */
 WORD drvstat;        /* IKBD Driver status (used as two bytes) */
} KBDVECS;

If I4 of the MFP generates an Interrupt, then the service routine calls 
midisys() and ikbdsys() in turn. If I4 now still remains L (so is active), 
then these routines will be repeatedly called until processing of 
ikbdsys() I4 at last goes H. Then the Interrupt in the MFP will be marked 
as dealt with and the service routine ends. The XXXXsys() must themselves 
establish from the status register of their ACIA whether they should 
operate or return. Before the routines were called the registers 
A0-A3/D0-D3 were saved, so that one can use them. For safety's sake 
however one should only use A0-A2/D0-D2, as the conventions of most 
C-compilers on the Atari permit. The whole operation runs with an 
Interrupt priority level of 6, so that no further Interrupts can 
intervene. When one reduces the IPL (temporarily in the XXXsys routine), 
then at least the higher priority Interrupts from the MFP, such as that 
for MODEM1, can intervene.

Vmiderr() and vkbderr() are called by midisys() or ikbdsys() respectively 
when a receive-buffer overflow occurs. The received characters will 
nevertheless be passed to D0.b. The error condition has already been reset 
in the ACIA. Other error conditions are ignored and do not cause vXXXerr() 
calls. So if one incorporates one's own XXXXsys() routines, vXXXerr() will 
be called only if this is done by that XXXXsys() routine. The vXXXerr() 
calls may use A0-A2/D0-D2 and in TOS consist only of a RTS.

Midivec() will be called by midisys() when an error-free character is 
received from MIDI_ACIA. The character will be passed in D0.b. The routine 
may use A0-A2/D0-D2 and in TOS writes the character to the MIDI receive 
buffer.

All other routines are called by ikbdsys() after ikbdsys has received all 
bytes that belong to the corresponding packet. These bytes are collected 
in a buffer and the routine will be passed a pointer to this buffer in the 
register A0 and in the Stack. The routines may use A0-A2/D0-D2. They 
should be as short as possible, since a run-time of 1mS (as quoted by the 
Profibuch) already limits the error-free reception data rate via MODEM1 to 
only 9600Bd (the data from MIDI at 31250Bd goes 'bang' a lot earlier). An 
alternative is offered by re-entrant routines (so copy the buffer contents 
first) that set the IPL to less than 6 while they are running and so 
permit at least reception via MODEM1 (which has a higher priority in the 
MFP).

If one looks at these 4 other routines, one finds they miss a routine to 
handle normal key presses (Byte $00-$F5). The pointer to this routine in 
our experience (which is not documented) is placed exactly before the 
KBDVECS-structure. This routine will be passed the character in D0.b, and 
it may use A0-A2/D0-D2. It handles the characters and writes the 
corresponding data to the receive buffer, which can then be read by 
Bconin-keyboard, for instance. With TOS 2.06 all receive buffer inputs 
will be a LONG.

Mousevec() is not only called from ikbdsys(), but also by the undocumented 
key routine and the key repeat routine when the keyboard is used to 
emulate a mouse (with Alt+cursor-keys).

Drvstat is always non-zero when ibkdsys() is in the process of collating a 
packet. An undocumented feature of TOS2.06 is the use of the high-byte for 
saving the internal routine number (derived from the received header) and 
of the low-byte as a down-counter for the number of bytes yet to be 
received.

If one wants to pass self-generated packets to one of the 4 routines, one 
has to ensure that these (in TOS) non-re-entrant routines are not also 
accidentally called from within the Interrupt. So either set the IPL to 6 
or 7, or install a dummy routine temporarily in KBDVECS (that, if 
possible, only stores the packet somewhere) in place of the original 
routine that one is currently calling.


Versions
--------
(Date in the form year-month-day)
1994-08-27	Should function correctly for the first time
1994-10-24     TIOCM_RER (overrun, frame, parity) ascertainable with 
               TIOCCTLGET
1994-12-30     Fast Bconout parameter passing changed (and 
               MAPT_APP/MAPT_OVE function number)
1995-01-15     Now runs with TOS versions prior to 2.00
1995-03-19     Covers from TOS1.02 also the original MIDI BIOS numbers and 
               can also make available the original MIDI Iorec as well as 
               Midiws.
1995-04-08     Added ACIA-reset during installation (necessary under 
               MagiCMac)
1995-04-28     New configuration point MISY

Harun Scheutzow, Berlin 27.08.1994 and later
