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.

