;      /*****************************************************************/
;      /*                                                               */
;      /*           Copyright (c) IBM Corporation  1987, 1992           */
;      /*                     All Rights Reserved                       */
;      /*                                                               */
;      /*****************************************************************/
;      /******************* START OF SPECIFICATIONS *********************/
;      /*                                                               */
;      /*  SOURCE FILE NAME: DISPLAY.ASM                                */
;      /*                                                               */
;      /*  DESCRIPTIVE NAME: Display handler                            */
;      /*                                                               */
;      /*  COPYRIGHT:  IBM Corp. 1992                                   */
;      /*                                                               */
;      /*  STATUS:  Version 1.0                                         */
;      /*                                                               */
;      /*  NOTES: This module contains routines to manage the display   */
;      /*         backlight. The device dependent module is called      */
;      /*         to turn the backlight on and off. The device dependent*/
;      /*         module must call Dsp_Engine to report change of       */
;      /*         backlight status.                                     */
;      /*                                                               */
;      /*  ENTRY POINTS:                                                */
;      /*      See public statements                                    */
;      /*  EXTERNAL REFERENCES:                                         */
;      /*      See extrn statements                                     */
;      /*                                                               */
;      /******************* END  OF  SPECIFICATIONS *********************/
.xlist
  include pensegs.inc
  include pen.inc
  include penidc.inc
  include penioctl.inc
  include penei.inc
  include struc.inc
.list

.286p

;------------------------------------------------------------------------------
; external data references
;------------------------------------------------------------------------------

extrn Device_Help  : dword

;------------------------------------------------------------------------------
; external routines
;------------------------------------------------------------------------------

extrn Idc_ReportEvent : near
extrn Idc_RequestCallback : near
extrn Idc_CancelCallback : near
extrn Idc_QueryActivity : near
extrn Idc_SuppressStroke : near
extrn Tim_Mill2Tick      : near

;------------------------------------------------------------------------------
; local equates
;------------------------------------------------------------------------------

ON  equ 1
OFF equ 0

; The following set the frequency of checking the activity
; note: CNT1,CNT2,CNT3 must be less than 64 * Tim_MsecPerTick (31)
;       for math in SetInactPeriod to work
LIMIT1 equ 60
CNT1   equ 1      ; less than LIMIT1 seconds, check this many seconds
LIMIT2 equ 300
CNT2   equ 10     ; less than LIMIT2 seconds, check every this many seconds
CNT3   equ 30     ; greater than LIMIT2 seconds, check every this many seconds

;------------------------------------------------------------------------------
; local data declarations
;------------------------------------------------------------------------------

DSEG   segment
displayDCB dw 0
DSEG   ends

CSEG SEGMENT
     ASSUME    CS:CGROUP, SS:nothing, ES:nothing, DS:DGROUP

;---- ROUTINES TO SET DISPLAY STATE -------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; Set the diplay state (turn it on or off)
;  al = command 1=turn on backlight 0=turn off backlight
;  bx = dcb
;------------------------------------------------------------------------------
public Dsp_SDS
Dsp_SDS proc
  CALL_NZ_ERR [bx].dcb_@backlight     ; turn on/off the backlight
  ret
Dsp_SDS endp

;---- ROUTINES TO MANAGE DISPLAY ENGINE ---------------------------------------
;
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Update display engine with backlight state info. Called by device dependent
; code to update display engine.
;  al = 1=backlight is on 0=backlight is off
;  bx = dcb
;------------------------------------------------------------------------------
public Dsp_Engine
Dsp_Engine    proc
  .if <nonzero al>
     jmp Dsp_StateOn
  .endif
  jmp Dsp_StateOff
Dsp_Engine endp

;------------------------------------------------------------------------------
; update state to on
; bx = dcb
;------------------------------------------------------------------------------
public Dsp_StateOn
Dsp_StateOn proc
  call Dsp_CancelAutoOn

  .if  <bit [bx].dcb_DspFlags z DSP_STATE_ON>
     or  [bx].dcb_DspFlags,DSP_STATE_ON
     mov  di,[bx].dcb_@EiEvent
     mov  [di].dev_state, ON
     call Idc_ReportEvent         ; report the event
  .endif

  call Dsp_StartAutoOff
  ret
Dsp_StateOn endp

;------------------------------------------------------------------------------
; update state to off
; bx = dcb
;------------------------------------------------------------------------------
public Dsp_StateOff
Dsp_StateOff proc
  call dsp_CancelAutoOff

  .if  <bit [bx].dcb_DspFlags nz DSP_STATE_ON>
     and [bx].dcb_DspFlags, not DSP_STATE_ON
     mov  di,[bx].dcb_@EiEvent
     mov  [di].dev_state, OFF
     call Idc_ReportEvent         ; report the event
  .endif

  call dsp_StartAutoOn
  ret
Dsp_StateOff endp

;---- AUTOMATIC BACKLIGHT CONTROL ---------------------------------------------
;
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Process requests to activate and disable automatic control. This should be
; called when ever the inactivity peroid changes or if the automatic enable
; changes.
;   bx = dcb
;------------------------------------------------------------------------------
public Dsp_SetInactPeriod
Dsp_SetInactPeriod proc

  .if <bit [bx].dcb_DspFlags z DSP_AUTO_ENABLED>
     call Dsp_CancelAutoOff
     call Dsp_CancelAutoOn
  .else
     call Dsp_Convert
     .if <bit [bx].dcb_DspFlags nz DSP_STATE_ON>
        call Dsp_StartAutoOff
     .else
        call Dsp_StartAutoOn
     .endif
  .endif
  ret
Dsp_SetInactPeriod endp

;------------------------------------------------------------------------------
; Convert inactivity peroid in seconds to number of ticks between checks and
; number of checks needed.
;   bx = dcb
;------------------------------------------------------------------------------
K2 equ dword ptr [bp-6]
K1 equ word ptr  [bp-2]

public Dsp_Convert
Dsp_Convert proc
  .386p
  enter 6,0
  mov ecx,[bx].dcb_InactPeriod
  .if <ecx be LIMIT1>
     mov  eax, CNT1
  .elseif <ecx be LIMIT2>
     mov  eax, CNT2
  .else
     mov  eax, CNT3
  .endif
  mov  [K2], eax   ; put on the stack for latter divide

; calculate number of ticks between activity checks

  mov  [K1], 1000
  imul [K1]            ;convert seconds to milliseconds
  call Tim_Mill2Tick   ;convert to tick count
  mov  [bx].dcb_TicksPerCheck, ax

; calculate number of checks needed

  mov  eax,ecx
  xor  edx,edx
  idiv [K2]
  .if  <nonzero edx>
     inc eax
  .endif
  mov  [bx].dcb_NumberChecks, eax

  leave
  .286p
  ret
Dsp_Convert endp

;------------------------------------------------------------------------------
; start an automatic on
; bx = dcb
;------------------------------------------------------------------------------
public Dsp_StartAutoOn
Dsp_StartAutoOn proc
  .if <bit [bx].dcb_DspFlags nz DSP_AUTO_ENABLED>
      call Idc_RequestCallback
      or   [bx].dcb_DspFlags,DSP_AUTO_ON
  .endif
  ret
Dsp_StartAutoOn endp

;------------------------------------------------------------------------------
; start an automatic off. Blindly restart the counter if it is already going
; bx = dcb
;------------------------------------------------------------------------------
public Dsp_StartAutoOff
Dsp_StartAutoOff proc
  .if <bit [bx].dcb_DspFlags nz DSP_AUTO_ENABLED>
      .386p
      mov  ax,[bx].dcb_TicksPerCheck
      mov  [bx].dcb_CountDown1, ax
      mov  eax,[bx].dcb_NumberChecks
      mov  [bx].dcb_CountDown2, eax
      .286p
      or   [bx].dcb_DspFlags,DSP_AUTO_OFF
  .endif
  ret
Dsp_StartAutoOff endp

;------------------------------------------------------------------------------
; canel an automatic on
; bx = dcb
;------------------------------------------------------------------------------
public Dsp_CancelAutoOn
Dsp_CancelAutoOn proc
  .if <bit [bx].dcb_DspFlags nz DSP_AUTO_ON>
     and  [bx].dcb_DspFlags,not DSP_AUTO_ON
     call Idc_CancelCallback
  .endif
  ret
Dsp_CancelAutoOn endp

;------------------------------------------------------------------------------
; canel an automatic off.
; bx = dcb
;------------------------------------------------------------------------------
public Dsp_CancelAutoOff
Dsp_CancelAutoOff proc
  .if <bit [bx].dcb_DspFlags nz DSP_AUTO_OFF>
      and  [bx].dcb_DspFlags,not DSP_AUTO_OFF
  .endif
  ret
Dsp_CancelAutoOff endp

;------------------------------------------------------------------------------
; process ticks to detect inactivity period
; bx = dcb
;------------------------------------------------------------------------------
public dsp_tick
dsp_tick    proc
  .if <bit [bx].dcb_DspFlags nz DSP_AUTO_OFF>
     sub [bx].dcb_CountDown1,1
     .if Z OR
     .if C
        mov  ax,[bx].dcb_TicksPerCheck
        mov  [bx].dcb_CountDown1, ax
        call Idc_QueryActivity
        .386p
        xchg edx,[bx].dcb_LastActivity
        .if <edx eq [bx].dcb_LastActivity>
           sub [bx].dcb_CountDown2,1
           .286p
           .if Z OR
           .if C
              and [bx].dcb_DspFlags, not DSP_AUTO_OFF
              mov  al,OFF
              jmp  Dsp_SDS
           .endif
        .else
           .386p
           mov  eax,[bx].dcb_NumberChecks
           mov  [bx].dcb_CountDown2, eax
           .286p
        .endif
     .endif
  .endif
  ret
dsp_tick    endp

;------------------------------------------------------------------------------
; process callback after system activity to automatically turn display on
; bx = dcb
;------------------------------------------------------------------------------
public Dsp_callback
Dsp_callback    proc
  mov  bx, displayDCB
  .if <bit [bx].dcb_DspFlags nz DSP_AUTO_ON>
     and [bx].dcb_DspFlags, not DSP_AUTO_ON
     .if <bit [bx].dcb_DspFlags nz DSP_SUPPRESS>
        call Idc_SuppressStroke
     .endif
     mov  al,ON
     call Dsp_SDS
  .endif
  ret
Dsp_callback    endp

;------------------------------------------------------------------------------
; Get control bits for suppressing activity while the backlight is off
; returns
;   dx = lev_cntrl and bev_cntrl bits
;------------------------------------------------------------------------------
public Dsp_GetSuppress
Dsp_GetSuppress proc
  push bx
  mov  bx,displayDCB
  .if  <nonzero bx> AND ; incase display not started
  .if  <bit [bx].dcb_DspFlags z DSP_STATE_ON+DSP_OPAQUE>
     mov dx,LOC_BKLT_OFF
  .else
     xor dx,dx
  .endif
  pop  bx
  ret
Dsp_GetSuppress endp

CSEG ends
;---- INITIALIZATION ROUTINES -------------------------------------------------
;
; note: this code is truncated from the driver after the INIT command returns
;       to OS/2
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; Initialize engine
;  bx = dcb
;------------------------------------------------------------------------------
CSEGI segment
public Dsp_Init
Dsp_Init proc
  mov  displayDCB,bx
  mov  [bx].dcb_@Dev_DTTick  ,offset dsp_tick
  call Dsp_SetInactPeriod
  ret
Dsp_Init endp
CSEGI ends
end
