[Back to KEYBOARD SWAG index] [Back to Main SWAG index] [Original]

    UNIT KeyIntr ;  { support for INT 09 16 routines } { Turbo Pascal 5.5+ }

    INTERFACE

    Type
       InterruptProcedure = Procedure ;

    Const
       BiosDataSegment = $40 ;

    Procedure DisableInterrupts ; Inline( $FA ) ;   { CLI }
    Procedure EnableInterrupts ;  Inline( $FB ) ;   { STI }
    Procedure CallInterrupt( P : Pointer ) ;

    Function AltPressed : Boolean ;
    Function ControlPressed : Boolean ;
    Function ShiftPressed : Boolean ;

    Procedure EOI ;                      { end of interrupt to 8259 }
    Function ReadScanCode : Byte ;       { read keyboard }
    Procedure ResetKeyboard ;            { prepare for next key }
                                         { put key in buffer for INT 16 }
    Function StoreKey( Scan, Key : Byte ) : Boolean ;

    IMPLEMENTATION

    Type
       TwoBytesPtr = ^TwoBytes ;
       TwoBytes =               { one key in the keyboard buffer }
       Record
          KeyCode,
          ScanCode : Byte ;
       End ;

    Var
       KeyState       : Word Absolute BiosDataSegment:$17 ;
       KeyBufferHead  : Word Absolute BiosDataSegment:$1A ;
       KeyBufferTail  : Word Absolute BiosDataSegment:$1C ;
       KeyBufferStart : Word Absolute BiosDataSegment:$80 ;
       KeyBufferEnd   : Word Absolute BiosDataSegment:$82 ;

    Procedure CallInterrupt( P : Pointer ) ;
    Begin
       Inline( $9C ) ;           { PUSHF }
       InterruptProcedure(P) ;
    End ;

    Function AltPressed : Boolean ;
    Begin
       AltPressed := (KeyState and 8) <> 0 ;
    End ;

    Function ControlPressed : Boolean ;
    Begin
       ControlPressed := (KeyState and 4) <> 0 ;
    End ;

    Function ShiftPressed : Boolean ;
    Begin
       ShiftPressed := (KeyState and 3) <> 0 ;
    End ;

    Procedure EOI ;  { end of interrupt to 8259 interrupt controller }
    Begin
       Port[$20] := $20 ;
    End ;

    Function ReadScanCode : Byte ;
    Var
       N : Byte ;
    Begin
       N := Port[$60] ;     { $FF means keyboard overrun }
       ReadScanCode := N ;
    End ;

    Procedure ResetKeyboard ;      { prepare for next key }
    Var
       N : Byte ;
    Begin
       N := Port[$61] ;
       Port[$61] := (N or $80) ;
       Port[$61] := N ;
    End ;

    Function StoreKey( Scan, Key : Byte ) : Boolean ;
    Var                { put key in buffer that INT 16 reads }
       P : TwoBytesPtr ;
       N : Word ;
    Begin
       DisableInterrupts ;

       N := KeyBufferTail ;
       P := Ptr( BiosDataSegment, N ) ;

       Inc( N, 2 ) ;
       If( N = KeyBufferEnd ) then        { end of the circular buffer }
          N := KeyBufferStart ;
       If( N = KeyBufferHead ) then       { buffer full }
       Begin
          EnableInterrupts ;
          StoreKey := False ;
       End
       Else
       Begin
          P^.KeyCode := Key ;
          P^.ScanCode := Scan ;             { store key in circular buffer }
          KeyBufferTail := N ;              { advance tail pointer }
          EnableInterrupts ;
          StoreKey := True ;
       End ;
    End ;

    END.

[Back to KEYBOARD SWAG index] [Back to Main SWAG index] [Original]