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. Min 16, Normal 256, Max 65534.

TBL
Sets the Transmit Buffer Length. Min 16, Normal 256, Max 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 Interupt 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 
Interupts 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 Interupt 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 Interupt 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, e.g. 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 
Interupt 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 Interupt 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 Interupt 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 initialision 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 Interupt 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 go '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
