
		***************************************************
		***						***
		***		    ToggleDTR 1.0		***
		***						***
		***************************************************
		***	     © 13 Oct 1993 by Marc Heuler	***
		***************************************************

NAME		MACRO
		dc.b	"ToggleDTR"
		ENDM

VERSION		MACRO
		dc.b	"1.0"
		ENDM

DATE		MACRO
		dc.b	"17.10.93"
		ENDM

FACTOR		= 1000

		INCDIR	"Include:"

		INCLUDE	"exec/libraries.i"
		INCLUDE	"exec/memory.i"
		INCLUDE	"dos/dosextens.i"

		INCLUDE	"_LVOExec.i"
		INCLUDE	"_LVODos.i"
		INCLUDE	"_LVOIntuition.i"
		INCLUDE	"_LVOTimer.i"

		IFND	DEVICES_TIMER_I
		INCLUDE	"devices/timer.i"
		ENDC

_SysBase	= 4

CALLEXE		MACRO
		move.l	_SysBase,a6
		jsr	_LVO\1(a6)
		ENDM

CALLDOS		MACRO
		move.l	_DosBase,a6
		jsr	_LVO\1(a6)
		ENDM

CALLINT		MACRO
		move.l	_IntuitionBase,a6
		jsr	_LVO\1(a6)
		ENDM

CALLTIM		MACRO
		move.l	.TimerRequest(pc),a6
		move.l	IO_DEVICE(a6),a6
		jsr	_LVO\1(a6)
		ENDM


		***************************************************
		***						***
		***		       Start			***
		***						***
		***************************************************

Startup		movem.l	d1-d7/a0-a6,-(a7)	; preserve registers

		sub.l	a1,a1			; get workbench message
		CALLEXE	FindTask
		move.l	d0,a4
		moveq	#0,d0

		tst.l	$ac(a4)
		bne.s	.FromCLI
		lea	$5c(a4),a0
		CALLEXE	WaitPort
		lea	$5c(a4),a0
		CALLEXE	GetMsg
		move.l	d0,.WBMsg
.FromCLI	move.l	#20,-(a7)		; returncode

		moveq	#33,d0			; open dos.library v33+
		lea	.DosName(pc),a1
		CALLEXE	OpenLibrary
		move.l	d0,_DosBase
		beq	.Exit
		bra.s	.TestKick
.DosName	dc.b	"dos.library",0
		even

.TestKick	move.l	_SysBase,a0		; test kickstart version
		cmp.w	#37,LIB_VERSION(a0)
		blt	.NoKick20

		addq.l	#4,a7			; trash returncode

		tst.l	.WBMsg
		bne	.Error_WB

		moveq	#37,d0
		lea	.IntName(pc),a1
		CALLEXE	OpenLibrary
		move.l	d0,_IntuitionBase
		beq	.NoKick20

		bsr	Main			; call program

		move.l	d0,-(a7)		; preserve returncode

.Exit		move.l	_IntuitionBase(pc),d0	; close intuition.library
		beq.s	.NoInt
		move.l	d0,a1
		CALLEXE	CloseLibrary
.NoInt		move.l	_DosBase(pc),d0		; close dos.library
		beq.s	.NoDos
		move.l	d0,a1
		CALLEXE	CloseLibrary
.NoDos		move.l	.WBMsg(pc),d0		; reply workbench message
		beq.s	.NoWB
		CALLEXE	Forbid
		move.l	.WBMsg(pc),a1
		CALLEXE	ReplyMsg
.NoWB		move.l	(a7)+,d0

		movem.l	(a7)+,d1-d7/a0-a6	; exit
		rts

.NoKick20	lea	.txt_NoKick20(pc),a0
		bsr	Print
		bra.s	.Exit

.Error_WB	lea	.txt_NoWB(pc),a0
		bsr	Print
		bra.s	.Exit

.WBMsg		dc.l	0

.IntName	dc.b	"intuition.library",0
		even

.txt_NoKick20	NAME
		dc.b	": You need at least Kickstart v37 (2.04)!",$a,0
		even
.txt_NoWB	NAME
		dc.b	": You can't run this program via Workbench!",$a,0
		even

		***************************************************
		***						***
		***		   Version string		***
		***						***
		***************************************************

		dc.b	"$VER: "
		NAME
		dc.b	" "
		VERSION
		dc.b	" ("
		DATE
		dc.b	") © 1993 by Marc Heuler (Data Design)",0
		even

		***************************************************
		***						***
		***		   Main program			***
		***						***
		***************************************************

Main		move.l	#Template,d1			; Get arguments
		move.l	#ARGS,d2
		moveq	#0,d3
		CALLDOS	ReadArgs
		move.l	d0,Args
		beq	.Error

		move.l	ARG_Duration,d0			; Get duration
		beq.s	.Default
		move.l	d0,a0
		move.l	(a0),d2
		bra.s	.Dur
.Default	move.l	#1000,d2
.Dur		beq	.Error_Args
		cmp.l	#60000,d2
		bge	.Error_Args
		mulu	#FACTOR,d2

		CALLEXE	CreateMsgPort			; Create timer IORequest
		move.l	d0,.TimerPort
		beq	.Error_NoMem
		move.l	d0,a0
		moveq	#IOTV_SIZE,d0
		CALLEXE	CreateIORequest
		move.l	d0,.TimerRequest
		beq	.Error_NoMem

		moveq	#UNIT_MICROHZ,d0		; Open timer device
		moveq	#0,d1
		lea	.TimerName(pc),a0
		move.l	.TimerRequest(pc),a1
		CALLEXE	OpenDevice
		tst.l	d0
		seq	.TimerOpen
		bne	.Error_Timer


		***************************************************
		***						***
		***		   Do the magic			***
		***						***
		***************************************************

		CALLEXE	Forbid
		st	.Forbid

		btst	#7,$bfd000			; Check DTR
		bne	.Error_DTR

		lea	.Time_End(pc),a0		; Get start time
		CALLTIM	GetSysTime

		bset	#7,$bfd000			; Toggle DTR

		movem.l	.Time_End(pc),d0-d1		; Calculate end time
		add.l	d2,d1
.Set		cmp.l	#FACTOR*1000,d1
		blt.s	.Set_Okay
		sub.l	#FACTOR*1000,d1
		addq.l	#1,d0
		bra.s	.Set
.Set_Okay	movem.l	d0-d1,.Time_End

.Loop		lea	.Time_Current(pc),a0		; Read current time
	btst	#6,$bfe001
	bne.s	.Goon
	btst	#2,$dff016
	beq.s	.eee

.Goon		CALLTIM	GetSysTime
		lea	.Time_End(pc),a0
		lea	.Time_Current(pc),a1
		CALLTIM	CmpTime
		tst.l	d0
		bmi	.Loop

.eee		bclr	#7,$bfd000			; Toggle DTR

		CALLEXE	Permit
		sf	.Forbid

		moveq	#0,d0

		***************************************************
		***						***
		***		 Cleanup and exit		***
		***						***
		***************************************************

.Cleanup	move.l	d0,-(a7)

		tst.b	.Forbid				; Permit
		beq.s	.NoForbid
		CALLEXE	Permit
.NoForbid	tst.b	.TimerOpen			; Close timer device
		beq.s	.NoTimOpen
		move.l	.TimerRequest(pc),a1
		CALLEXE	CloseDevice
.NoTimOpen	move.l	.TimerRequest(pc),d0		; Free timer request
		beq.s	.NoTimReq
		move.l	d0,a0
		CALLEXE	DeleteIORequest
.NoTimReq	move.l	.TimerPort(pc),d0		; Free timer port
		beq.s	.NoTimPort
		move.l	d0,a0
		CALLEXE	DeleteMsgPort
.NoTimPort	move.l	Args(pc),d1			; Free Args
		beq.s	.NoArgs
		CALLDOS	FreeArgs
.NoArgs		move.l	(a7)+,d0
		rts


.Time_Current	dc.l	0,0
.Time_End	dc.l	0,0

.TimerPort	dc.l	0
.TimerRequest	dc.l	0

.Forbid		dc.b	0
.TimerOpen	dc.b	0
.TimerName	dc.b	"timer.device",0
		even


		***************************************************
		***						***
		***		  Error handling		***
		***						***
		***************************************************

.Error_DTR	lea	.tx_DTR(pc),a0
		bra	.Error_Print
.Error_NoMem	lea	.tx_NoMem(pc),a0
		bra	.Error_Print
.Error_Timer	lea	.tx_Timer(pc),a0
		bra	.Error_Print
.Error_Args	lea	.tx_Args(pc),a0
.Error_Print	bsr	Print
		bra.s	.Error_Exit

.Error		CALLDOS	IoErr				; DOS error
		move.l	d0,d1
		move.l	#.Error_Name,d2
		CALLDOS	PrintFault

.Error_Exit	moveq	#20,d0
		bra	.Cleanup

.Error_Name	NAME
		dc.b	0

.tx_Args	NAME
		dc.b	": Duration out of range (1-60000)",$a,0
.tx_DTR		NAME
		dc.b	": Internal serial interface not active",$a,0
.tx_NoMem	NAME
		dc.b	": Not enough memory",$a,0
.tx_Timer	NAME
		dc.b	": Couln't get ahold of a UNIT_MICROHZ timer",$a,0
		even


		***************************************************
		***						***
		***		Print To StdOutput		***
		***						***
		***************************************************
		*** >>> A0	*char (0-terminated)		***
		*** <<< FLAGS	BNE ERROR			***
		***************************************************

Print		movem.l	d1-d3/a0-a1,-(a7)
		move.l	_DosBase,d0
		beq.s	.Print_Skip
		move.l	a0,-(a7)
		CALLDOS	Output
		move.l	d0,d1
		move.l	(a7)+,a0
		move.l	a0,d2
.Print_Loop	tst.b	(a0)+
		bne.s	.Print_Loop
		move.l	a0,d3
		subq.l	#1,d3
		sub.l	d2,d3
		beq.s	.Print_Skip
		move.l	d3,-(a7)
		CALLDOS	Write
		sub.l	(a7)+,d0
.Print_Skip	movem.l	(a7)+,d1-d3/a0-a1
		rts


		***************************************************
		***						***
		***		     Variables			***
		***						***
		***************************************************

_DosBase	dc.l	0
_IntuitionBase	dc.l	0

Args		dc.l	0

ARGS
ARG_Duration	dc.l	0

Template	dc.b	"DURATION/N",0
		even

		END

