'******************************************************************************
'* 
'* PROGRAMMABLE INTERVAL TIMER i8253 v.1.0 (CHIP DEVICE)
'*
'* Supported platform/bus: X86
'* 
'* Version history:
'*  - 2004-2008 by WadiM (initial emulation and some changes)
'*
'****************************************************************************** 

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

'device interface support
public use object DEVICE

'internal implementation (direct)
public use internal "TIMER8253"

//device name
DeviceName="PIT i8253"
DebugName="PIT_I8253"

//timer channels (sub-devices)
dim ch(3) as object, i as integer
public use object "i8253\channel" as channel0 : ch(0)=channel0
public use object "i8253\channel" as channel1 : ch(1)=channel1
public use object "i8253\channel" as channel2 : ch(2)=channel2 
for i=0 to 2 : ch(i).Freq=1193180 
 ch(i).DeviceName=ch(i).DeviceName+Str(i)
 ch(i).DebugName=ch(i).DebugName+Str(i)
next
SetChannels(channel0.Object,channel1.Object,channel2.Object)
                   
//Interrupt requests event handler
function IRQEvent(freq as integer,eventid as dword) as boolean
 result=true 'need next event call
 channel0.UpdateState 
 channel1.UpdateState
 channel2.UpdateState
end direct IRQEvent

'-------------------------------- H/W Interface -------------------------------

//Write/Read channel data ports
public property CH0_DATA_PORT alias channel0.Data
public function CH0_DATA_PORT alias channel0.Data
public property CH1_DATA_PORT alias Channel1.Data
public function CH1_DATA_PORT alias Channel1.Data
public property CH2_DATA_PORT alias Channel2.Data
public function CH2_DATA_PORT alias Channel2.Data

//Write mode port
public property MODE_PORT(Value as byte)
 select case shr(Value and 0xC0,6)
 case 0 : channel0.Mode=Value
 case 1 : channel1.Mode=Value
 case 2 : channel2.Mode=Value
 case 3 //several channels
       if (Value and 2)<>0 then channel0.Mode=Value
       if (Value and 4)<>0 then channel1.Mode=Value
       if (Value and 8)<>0 then channel2.Mode=Value
 end select
 ?? DebugPrefix;">ModePort=";Hex(Value,2);"h"
end direct Mode

//Read mode port
public function MODE_PORT as byte
 result=0
 ?? DebugPrefix;"<ModePort=";Hex(result,2);"h"
end direct Mode

'---------------------------- 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)
 if EventFreq<2000 then EventFreq=2000

 'set initial data
 channel0.Input=true  : channel0.Output=true 
 channel1.Input=true  : channel2.Output=true
 channel2.Input=true  : channel2.Output=true

 //register interrupt requests event (at max available freq)
 pc.NewFreqEvent=IRQEvent 

 //success
 result=true

end 
