'******************************************************************************
'* 
'* TIMER i8253/54 CHANNEL IMPLEMENTATION (internal currently)
'*
'* Supported platform/bus: X86
'* 
'* Version history:
'*  2004-2008 - initial emulation (by WadiM)
'* 
'* List of internally supported fields and methods
'* - IRQIndex as integer - index of IRQ of the channel (<0 - no IRQ)
'* - IRQCount as dword - count of interrupt requests to process
'* - Freq as dword - input frequency of timer channel
'* - Input as boolean - is input allowed
'* - Output as boolean - is output allowed
'* - Mode as byte - mode port of channel
'* - Data as byte - data port of channel
'* - function Update as dword - update channel state and get IRQ count
'* - procedure UpdateState - update channel state and raise IRQs
'*
'****************************************************************************** 

//DEBUG.ON 'uncomment to enable debug messages (can be slow for hi-freq events)
//DIRECT.OFF 'uncomment to disable direct calls to internal implementation

'ISA device interface support
public use object DEVICE_ISA

'internal implementation
public use internal "TIMER8253CHANNEL"

//device name
DeviceName="PIT i8253 Channel"
DebugName="PIT_I8253_CH" 

//variable, used to show count of system timer interrupt/second (in debug mode)
dim ips as integer=0

//Update channel state and get count of IRQ for passed period of time 
public procedure UpdateState
 dim i as integer, j as integer=Update //internal Update
 if j=0 then exit
 for i=0 to j-1 
 if pc.SetIRQ(IRQIndex,true) then : IRQCount=IRQCount-1 
    ips=ips+1 'interrupts per second
    else : if IRQCount>1 then IRQCount=shr(IRQCount,1) 'better to discard unprocessed IRQs?
    exit for : end if 
 next i
end direct UpdateState

//Interrupts per second message event
function IPSEvent(freq as integer,eventid as dword) as boolean
 result=true : if ips>0 then : ?? DebugPrefix;"IPS=";ips : ips=0 : end if 
end

'---------------------------- DEVICE Interface --------------------------------

//Device initialization
public function DEV_INIT(stream as object,byref EventFreq as integer) as boolean

 'parent call
 if not DEV_INIT(stream,EventFreq) then exit(false)

 'configure internal implementation
 IRQIndex=DeviceIRQ 'pass configured IRQ index

 'interrupts per second counting
 pc.NewFreqEvent(1)=IPSEvent  //1Hz

 //success
 result=true

end 
