342 lines
6.5 KiB
NASM
342 lines
6.5 KiB
NASM
******************************************************************************
|
|
* Name: intervaltimer.s *
|
|
* Date: $Date: 2016-12-18 22:20:04 +0100 (So, 18. Dez 2016) $ *
|
|
* Authors: Henryk Richter *
|
|
******************************************************************************
|
|
|
|
;MACHINE MC68040
|
|
|
|
include exec/types.i
|
|
include lvo/exec_lib.i
|
|
include lvo/dos_lib.i
|
|
include lvo/timer_lib.i
|
|
include exec/exec.i
|
|
include dos/dos.i
|
|
include dos/dostags.i
|
|
include exec/io.i
|
|
include dos/dosextens.i
|
|
include exec/lists.i
|
|
|
|
DO_TEST EQU 0
|
|
|
|
ifne 1
|
|
include "intervaltimer.i"
|
|
else
|
|
STRUCTURE IVT_TimerStruct,0
|
|
ULONG IVT_Interval ;<1e6 in microseconds
|
|
LONG IVT_Signal ;Signal that is sent back to task from interrupt
|
|
ULONG IVT_SigMask
|
|
APTR IVT_SigTask ;Task that is signaled
|
|
APTR IVT_Port
|
|
APTR IVT_IORequest
|
|
APTR IVT_Device
|
|
STRUCT IVT_Int,IS_SIZE ;
|
|
BYTE IVT_Init ; !=0 - initialized
|
|
BYTE IVT_Runflag ; current status ( !=0 = running )
|
|
BYTE IVT_Stopflag ; stop request if != 0
|
|
BYTE IVT_Unused ;
|
|
ULONG IVT_Counter ; Counter (statistics)
|
|
LABEL IVT_Size
|
|
endc
|
|
|
|
xdef _InterruptIntervalTimer
|
|
xdef _InitIntervalTimer
|
|
xdef _ExitIntervalTimer
|
|
xdef _StartIntervalTimer
|
|
xdef _StopIntervalTimer
|
|
|
|
CALLEXEC macro
|
|
move.l 4.w,a6
|
|
jsr _LVO\1(a6)
|
|
endm
|
|
|
|
section code,text
|
|
|
|
ifne DO_TEST
|
|
|
|
TestTimer:
|
|
lea dos_name,a1 ;string base
|
|
moveq #0,d0
|
|
move.l 4.w,a6
|
|
jsr _LVOOpenLibrary(a6)
|
|
move.l d0,dosbase
|
|
beq .nodos
|
|
|
|
move.l dosbase,a6
|
|
jsr _LVOOutput(a6) ;get stdout
|
|
move.l d0,stdout
|
|
|
|
lea timerbase,a1
|
|
bsr _InitIntervalTimer
|
|
tst.l d0
|
|
bge .ok
|
|
|
|
move.l stdout,d0
|
|
move.l #failtimer,d1
|
|
move.l dosbase,16
|
|
jsr _LVOPutStr(a6)
|
|
bra .error
|
|
|
|
.ok
|
|
lea timerbase,a1
|
|
move.l #10000,d1
|
|
bsr _StartIntervalTimer
|
|
|
|
moveq #0,d3
|
|
.loop
|
|
cmp.l #10,d3
|
|
bgt.s .exitloop
|
|
|
|
move.l dosbase,A6
|
|
moveq #10,d1
|
|
jsr _LVODelay(a6)
|
|
|
|
addq.l #1,d3
|
|
lea timerbase,a1
|
|
cmp.l #100,IVT_Counter(a1)
|
|
blt.s .loop
|
|
.exitloop:
|
|
|
|
move.l #succname,d1
|
|
cmp.l #10,d3
|
|
ble.s .succ
|
|
move.l #failname,d1
|
|
.succ:
|
|
jsr _LVOVPrintf(a6)
|
|
|
|
|
|
lea timerbase,a1
|
|
bsr _StopIntervalTimer
|
|
.error
|
|
lea timerbase,a1
|
|
bsr _ExitIntervalTimer
|
|
|
|
move.l dosbase,d0
|
|
beq.s .nodos
|
|
move.l d0,a1
|
|
move.l 4.w,a6
|
|
jsr _LVOCloseLibrary(a6)
|
|
.nodos:
|
|
rts
|
|
|
|
ENDC ;DO_TEST
|
|
|
|
|
|
; A1 = IVT_TimerStruct
|
|
_InterruptIntervalTimer:
|
|
movem.l d1-a6,-(sp)
|
|
;<- basic Timer.device ops ->
|
|
move.l a1,a2
|
|
|
|
move.l IVT_Port(a2),a0
|
|
CALLEXEC GetMsg
|
|
tst.l d0
|
|
beq.s .error
|
|
|
|
move.l IVT_SigMask(a2),d0 ;move.l IVT_Signal(a2),d0
|
|
move.l IVT_SigTask(a2),a1
|
|
CALLEXEC Signal
|
|
|
|
tst.b IVT_Stopflag(a2)
|
|
bne.s .error ;not exactly an error but same consequence
|
|
|
|
move.l a2,a1
|
|
bsr _RestartIntervalTimer
|
|
|
|
;<- end basic Timer.device ops ->
|
|
|
|
;<- useful stuff ->
|
|
addq.l #1,IVT_Counter(a2)
|
|
|
|
;<- useful stuff ->
|
|
|
|
bra.s .endintroutine
|
|
.error:
|
|
clr.b IVT_Runflag(a2)
|
|
.endintroutine:
|
|
movem.l (sp)+,d1-a6
|
|
rts
|
|
|
|
|
|
_InitIntervalTimer: ;prepare timer.device for buffer swap interrupt
|
|
movem.l d1-a6,-(sp)
|
|
move.l a1,a2
|
|
move #IVT_Size-1,d0
|
|
.clr
|
|
clr.b (a1)+ ;
|
|
dbf d0,.clr
|
|
|
|
sf IVT_Init(a2)
|
|
sf IVT_Runflag(a2)
|
|
;signal to wait for from timer output if output queue full
|
|
moveq #-1,d0
|
|
CALLEXEC AllocSignal
|
|
move.l d0,IVT_Signal(a2) ; <0 ? error, valid are 0..31
|
|
blt .error ; error: have to go (shouldn't happen)
|
|
moveq #0,d1
|
|
bset d0,d1
|
|
move.l d1,IVT_SigMask(a2)
|
|
|
|
suba.l a1,a1
|
|
CALLEXEC FindTask
|
|
move.l d0,IVT_SigTask(a2)
|
|
|
|
CALLEXEC CreateMsgPort ;Create MsgPort for timing...
|
|
move.l d0,IVT_Port(a2)
|
|
beq .error ;0=error
|
|
|
|
move.l IVT_Port(a2),a0
|
|
move.l #IOTV_SIZE,d0
|
|
CALLEXEC CreateIORequest
|
|
move.l d0,IVT_IORequest(a2)
|
|
beq .error ;0=error
|
|
|
|
lea.l IVT_Int(a2),a0
|
|
lea _InterruptIntervalTimer(pc),a1
|
|
move.l a1,IS_CODE(a0)
|
|
move.l a2,IS_DATA(a0)
|
|
move.b #NT_INTERRUPT,LN_TYPE(a0)
|
|
move.b #0,LN_PRI(a0) ;-32,-16,0,16,32
|
|
|
|
move.l IVT_Port(a2),a1
|
|
;move.b #NT_MSGPORT,LN_TYPE(a1)
|
|
move.b #PA_SOFTINT,MP_FLAGS(a1)
|
|
move.l a0,MP_SIGTASK(a1) ;Softint eintragen
|
|
|
|
lea VBtimer_name,a0
|
|
moveq #UNIT_MICROHZ,d0
|
|
move.l IVT_IORequest(a2),a1
|
|
moveq #0,d1
|
|
CALLEXEC OpenDevice
|
|
tst.l d0
|
|
beq.s .ok
|
|
moveq #0,d0
|
|
bra.s .error
|
|
.ok ;OK, timer device is ready
|
|
st IVT_Init(a2)
|
|
moveq #1,d0 ;OK
|
|
.error
|
|
movem.l (sp)+,d1-a6
|
|
;ret 0 <= err, >0 = ok
|
|
rts
|
|
|
|
_ExitIntervalTimer:
|
|
;stop timer.device
|
|
movem.l d0-a6,-(sp)
|
|
move.l a1,a2
|
|
|
|
sf IVT_Init(a2)
|
|
|
|
move.l IVT_IORequest(a2),d5
|
|
beq.s .noIO
|
|
tst.b IVT_Runflag(a2)
|
|
beq.s .noAbort
|
|
st IVT_Stopflag(a2)
|
|
ifne 0
|
|
move.l d5,a1
|
|
CALLEXEC WaitIO
|
|
else
|
|
move.l d5,a1
|
|
move.l IO_DEVICE(a1),a6
|
|
jsr DEV_ABORTIO(A6) ;clear pending requests
|
|
endc
|
|
.noAbort:
|
|
move.l d5,a1
|
|
CALLEXEC CloseDevice
|
|
move.l d5,a0
|
|
CALLEXEC DeleteIORequest
|
|
clr.l IVT_IORequest(a2)
|
|
.noIO:
|
|
move.l IVT_Port(a2),d0
|
|
beq.s .noPort
|
|
move.l d0,a0
|
|
CALLEXEC DeleteMsgPort
|
|
clr.l IVT_Port(a2)
|
|
.noPort:
|
|
move.l IVT_Signal(a2),d0
|
|
not.l d0 ;if( d0 == -1 ) d0 = 0
|
|
beq.s .nosig
|
|
not.l d0 ; swap back
|
|
CALLEXEC FreeSignal
|
|
moveq #-1,d0
|
|
move.l d0,IVT_Signal(a2)
|
|
.nosig:
|
|
movem.l (sp)+,d0-a6
|
|
rts
|
|
|
|
|
|
; input:
|
|
; A1 = IVT Structure (after init)
|
|
; D1 = Number of Microseconds
|
|
_StartIntervalTimer:
|
|
movem.l d0/a1/a2/a6,-(Sp)
|
|
move.l a1,a2
|
|
move.l d1,IVT_Interval(A2)
|
|
sf IVT_Stopflag(a2)
|
|
|
|
tst.b IVT_Runflag(a2) ;running already ? -> keep it running
|
|
bne.s .notimer
|
|
move.l a2,a1
|
|
bsr _RestartIntervalTimer
|
|
.notimer
|
|
movem.l (sp)+,d0/a1/a2/a6
|
|
rts
|
|
|
|
; Non-Public
|
|
; A1 - IVT Structure
|
|
_RestartIntervalTimer:
|
|
movem.l d0/a1/a2/a6,-(sp)
|
|
move.l a1,a2
|
|
|
|
move.l IVT_IORequest(a2),d0
|
|
beq.s .notimer
|
|
|
|
move.l d0,a1
|
|
move.w #TR_ADDREQUEST,IO_COMMAND(a1)
|
|
clr.b IO_FLAGS(a1)
|
|
clr.l IOTV_TIME+EV_HI(a1)
|
|
move.l IVT_Interval(A2),IOTV_TIME+EV_LO(a1)
|
|
|
|
move.l IO_DEVICE(a1),a6
|
|
jsr DEV_BEGINIO(A6)
|
|
|
|
st IVT_Runflag(a2)
|
|
.notimer
|
|
movem.l (sp)+,d0/a1/a2/a6
|
|
rts
|
|
|
|
_StopIntervalTimer:
|
|
movem.l d0-a6,-(Sp)
|
|
move.l a1,a2
|
|
|
|
st IVT_Stopflag(a2)
|
|
|
|
tst.b IVT_Runflag(a2)
|
|
beq.s .noIO
|
|
move.l IVT_IORequest(a2),d5
|
|
beq.s .noIO
|
|
|
|
move.l d5,a1
|
|
move.l IO_DEVICE(a1),a6
|
|
jsr DEV_ABORTIO(A6) ;clear pending requests
|
|
sf IVT_Runflag(a2)
|
|
.noIO:
|
|
movem.l (sp)+,d0-a6
|
|
rts
|
|
|
|
|
|
section data,data
|
|
dosbase: dc.l 0
|
|
stdout: dc.l 0
|
|
timerbase: ds.b IVT_Size
|
|
|
|
VBtimer_name: dc.b "timer.device",0
|
|
ifne DO_TEST
|
|
dos_name: dc.b "dos.library",0
|
|
succname: dc.b "success: timer worked",10,0
|
|
failname: dc.b "failure: timer didn't work",10,0
|
|
failtimer: dc.b "timer open failure",10,0
|
|
ENDC ;DO_TEST
|
|
END
|
|
|