UNIT MIDI;


(* Original Source : Inside Turbo Pascal, May 1991, Vol 3 Number 5    *)
(* Modified by Sid (SJones@hort.cri.nz) 19th November 1993            *)
(* Removed the Originals object to allow compatibility with earlier   *)
(* versions of Turbo Pascal                                           *)

                                                     
{============================}  INTERFACE  {==========================}

USES Crt;

CONST
  UARTMode = $3F;

FUNCTION  GetMIDIData: INTEGER;

PROCEDURE SendMIDICommand (MIDICmd: BYTE);

PROCEDURE SendMIDIData (MIDIData: BYTE);

PROCEDURE ResetMIDIInterface;

{==========================} IMPLEMENTATION  {========================}

CONST
  DataPort = $330;  { MIDI messages IN/OUT  }
  StatPort = $331;  { Interface status port }
  DSR = $80;        { Interface ready to send message to CPU bit mask }
  DRR = $40;        { Interface ready to receive msg from CPU bit mask}
  ACK = $FE;        { Acknowledge msg sent from interface after cmd   }
  ResetSystem = $FF;    { System command                              }
  ActiveSensing = $FE;  { Msg sent by some keyboards, MIDIUnit ignores}

{=====================================================================}

FUNCTION GetMIDIData: INTEGER;

VAR
  MIDIData : INTEGER;                       { Data byte from INTERFACE}
  KeyFlag  : BOOLEAN;                       { Detect keypress flag to }
                                            {  short circuit input    }
BEGIN
  REPEAT
    KeyFlag := FALSE;
    REPEAT                                  { Loop till user presses a}
      KeyFlag := KeyPressed                 {  key or interface has a }
    UNTIL ((Port[StatPort] AND DSR) = 0) OR (KeyFlag); {byte available}
    IF KeyFlag THEN                         { Set temporary return    }
      MIDIData := -1                        {  for function           }
    ELSE
      MIDIData := Port[DataPort];
  UNTIL (MIDIData <> ActiveSensing);        { Exclude any active      }
  GetMIDIData := MIDIData                   {  sensing bytes          }
END;

{=====================================================================}

PROCEDURE SendMIDICommand (MIDICmd: BYTE);

BEGIN
  WHILE ((Port[StatPort] AND DRR) <> 0) DO ; { Wait till ok to send   }
  Port[StatPort] := MIDICmd;                 { Send cmd byte out port }
  WHILE Port[DataPort] <> ACK DO;            { Wait for Acknowledgment}
END;

{=====================================================================}

PROCEDURE SendMIDIData (MIDIData: BYTE);

VAR
  Status, ThrowAway : BYTE;
BEGIN
  REPEAT
    Status := Port[StatPort];
    IF (Status AND DSR) = 0 THEN             { If interface has a     }
      ThrowAway := Port[DataPort]            { throwaway byte get it  }
  UNTIL (Status AND DRR) = 0;                { Loop until interface   }
  Port[DataPort] := MIDIData                 {  is ready for data     }
END;

{=====================================================================}

PROCEDURE ResetMIDIInterface;

BEGIN
  REPEAT
    IF (Port[StatPort] AND DRR) = 0 THEN    { Wait till ok to send    }
      Port[StatPort] := ResetSystem         { Reset interface         }
  UNTIL Port[DataPort] = ACK                { Keep doing until you    }
END;                                        {   get ACK message       }

END.
