*****************************************************************
*								*
*	maestix.library-Demo:	SineTone2			*
*								*
*****************************************************************
*
*	Programmed by		Richard Körber
*	Date			1995-01-30
*
*****************************************************************
*  This  demonstration shows the  basic transmit  functions of  *
*  the  maestix library.  It allocates the  Maestro soundcard,  *
*  prepares  a sine  wave buffer and outputs  it using the in-	*
*  coming rate, resulting a 1378 Hz sine wave (CD-Player).	*
*****************************************************************

		INCDIR	"include:"
		INCLUDE	exec.i			; Library call macros
		INCLUDE	intuition.i
		INCLUDE	graphics.i
		INCLUDE	dos.i
		INCLUDE	maestix.i
		INCLUDE	libraries/maestix.i	;Reference includes
		INCLUDE	intuition/intuition.i
		INCLUDE	dos/dostags.i
		INCLUDE	exec/ports.i

BUFSIZE		EQU	12*1024			;size of FIFO data block

		SECTION text,CODE

*---------------------------------------------------------------*
*	== START OF PROGRAM ==					*
*								*
start	;-- Open all libraries -----------------;
		lea	maestname(PC),a1	;maestix
		moveq	#35,d0			; V35+
		exec	OpenLibrary		; open
		move.l	d0,maestbase		; store base
		beq	error1			; not found!
		lea	intuiname(PC),a1	;intuition
		moveq	#36,d0			; V36+
		exec	OpenLibrary		; open
		move.l	d0,intuibase		; store base
		beq	error2
		lea	dosname(PC),a1		;dos
		moveq	#36,d0			; V36+
		exec	OpenLibrary		; open
		move.l	d0,dosbase		; store base
		beq	error3
	;-- Create buffer ----------------------;
		move.l	#BUFSIZE*2,d0		;size of two buffers
		moveq	#$1,d1			;PUBLIC
		exec	AllocMem
		move.l	d0,buffer
		beq	error4
	;-- Fill the buffer --------------------;
		lea	sintab(PC),a0		;^Sine tab
		move.l	buffer(PC),a1		;^Output puffer
		moveq	#0,d0			;sine tab index pointer
		move.l	#BUFSIZE*2/4,d1		;longword counter
.fillbuff	subq.l	#1,d1			;one lw less
		bcs.b	.filldone		; fill has been done
		move	(a0,d0.w),(a1)+		;left channel
		move	(a0,d0.w),(a1)+		;right channel
		addq	#2,d0			;index to next word
		and	#63,d0			;modulo 64
		bra.b	.fillbuff
	;-- Alloc signal bits ------------------;
.filldone	sub.l	a1,a1			;get task ptr
		exec	FindTask
		move.l	d0,maintask
		moveq	#-1,d0			;Allocate a signal bit
		exec	AllocSignal
		move.b	d0,donesigbit
		cmp.b	#-1,d0			;no signals free?
		beq.w	error5
	;-- Open a window ----------------------;
		sub.l	a0,a0			;no newwindow struct
		lea	windowtags(PC),a1	; but loads of tags
		intui	OpenWindowTagList
		move.l	d0,window
		beq	error6
	;-- Launch level task ------------------;
		move.l	#tasktags,d1		;Tags for new task
		dos	CreateNewProc		;create new process
		tst.l	d0			;got the task?
		beq	error7
		moveq	#0,d0			;wait 'till 2nd task setup'd
		move.b	donesigbit(PC),d1	; signal
		bset	d1,d0
		exec	Wait			;wait for this event
	;-- Wait for reply (main loop) ---------;
.mainloop	move.l	window(PC),a0		;window message?
		move.l	wd_UserPort(a0),a0	; ^message port
		exec	WaitPort
.nextmsg	move.l	window(PC),a0		;window message?
		move.l	wd_UserPort(a0),a0	; ^message port
		exec	GetMsg			; try to get it...
		tst.l	d0			; got one?
		beq.b	.mainloop		; nope: wait for next msg
	;---- got a window event ---------------;
		move.l	d0,a0			;^IDCMP-message -> a0
		cmp.l	#IDCMP_CLOSEWINDOW,im_Class(a0) ;close window?
		bne.b	.nextmsg		; no -> look for next msg
	;-- Exit program -----------------------;
exit		move.l	sinetask(PC),a1		;Shut sine task
		moveq	#0,d0
		move.b	sinesigbit(PC),d1
		bset	d1,d0
		exec	Signal			; signals the exit
		moveq	#0,d0			;wait 'till 2nd task exited
		move.b	donesigbit(PC),d1	; signal
		bset	d1,d0
		exec	Wait			;wait for this event
		moveq	#20,d1
		dos	Delay
error7		move.l	window(PC),a0		;Close output window
		intui	CloseWindow
error6		move.b	donesigbit(PC),d0
		exec	FreeSignal
error5		move.l	buffer(PC),a1		;^Buffer
		move.l	#BUFSIZE*2,d0
		exec	FreeMem
error4		move.l	dosbase(PC),a1		;close dos library
		exec	CloseLibrary
error3		move.l	intuibase(PC),a1	;close intuition library
		exec	CloseLibrary
error2		move.l	maestbase(PC),a1	;close maestix library
		exec	CloseLibrary
error1		moveq	#0,d0			;Reply 0
		rts				;back to CLI

*---------------------------------------------------------------*
*	== SINE PROCESS ==					*
*								*
SineProc
	;-- Get exiting signal -----------------;
		sub.l	a1,a1			;Get task structure
		exec	FindTask
		move.l	d0,sinetask
		moveq	#-1,d0			;get sig bit
		exec	AllocSignal
		move.b	d0,sinesigbit
		cmp.b	#-1,d0			;got no bit
		beq	.error1
		move.l	maintask(PC),a1		;task is done
		moveq	#0,d0
		move.b	donesigbit(PC),d1
		bset	d1,d0
		exec	Signal			; signals the exit
	;-- Allocate Maestro -------------------;
		sub.l	a0,a0			;no tags
		maest	AllocMaestro
		move.l	d0,maestro		;^Maestro base
		beq	.error2
	;-- Set Modus --------------------------;
		move.l	maestro(PC),a0		;^Maestro base
		lea	modustags(PC),a1	;^Modus tags
		maest	SetMaestro		;set it now
	;-- Create Transmit-Messageport --------;
		exec	CreateMsgPort		;create a messageport
		move.l	d0,tport		; as transmit port
		beq	.error4
	;-- Init messages ----------------------;
		move.l	tport(PC),d1		;^Receive Reply Port
		lea	msg1(PC),a0		;^1st Message
		lea	msg2(PC),a1
		move.l	buffer(PC),d0		;get buffer ptr
		move.l	d0,(dmn_BufPtr,a0)	; set buffer1
		add.l	#BUFSIZE,d0
		move.l	d0,(dmn_BufPtr,a1)	; set buffer2
		move.l	#BUFSIZE,(dmn_BufLen,a0) ;Set buffer length
		move.l	#BUFSIZE,(dmn_BufLen,a1)
		move.l	d1,(MN_REPLYPORT,a0)	;Set Reply-Port
		move.l	d1,(MN_REPLYPORT,a1)
		move	#dmn_SIZEOF,(MN_LENGTH,a0) ;Set msg length
		move	#dmn_SIZEOF,(MN_LENGTH,a1)
	;-- Start transmit process -------------;
		move.l	maestro(PC),a0		;transmit msg to library
		lea	msg1(PC),a1
		maest	TransmitData		; the 1st (starts transmitter!)
		move.l	maestro(PC),a0
		lea	msg2(PC),a1
		maest	TransmitData		; and the 2nd
	;-- wait for messages ------------------;
.mainloop	move.l	tport(PC),a0		;maestix message?
		exec	GetMsg			; try to get it...
		tst.l	d0			; got one?
		bne.b	.gotmaestro		; then evaluate it
		moveq	#0,d0			;create wait mask
		move.b	sinesigbit(PC),d1	; signal for exiting
		bset	d1,d0
		move.l	tport(PC),a0		; second, from receive port
		move.b	MP_SIGBIT(a0),d1	; sig bit
		bset	d1,d0			; set this bit
		exec	Wait			;wait for these events
		move.b	sinesigbit(PC),d1	; exit forced?
		btst	d1,d0			; test this bit
		beq.b	.mainloop		;not wanted -> main loop
		bra.b	.exit			; wanted -> leave
	;---- got a maestix event --------------;
.gotmaestro	move.l	maestro(PC),a0		;Re-send message
		move.l	d0,a1
		maest	TransmitData		; to maestix library
		bra.b	.mainloop
	;-- Leave task -------------------------;
.exit		move.l	maestro(PC),a0
		maest	FlushTransmit
		move.l	tport(PC),a0		;delete receive port
		exec	DeleteMsgPort
.error4		move.b	sinesigbit(PC),d0	;free signal bit
		exec	FreeSignal
.error3		move.l	maestro(PC),a0		;Set maestro free
		maest	FreeMaestro
.error2		move.l	maintask(PC),a1		;task is done
		moveq	#0,d0
		move.b	donesigbit(PC),d1
		bset	d1,d0
		exec	Signal			; signals the exit
.error1		rts				;done (freed by DOS)

*---------------------------------------------------------------*
*	== DATA SECTION ==					*
*								*
maintask	dc.l	0			;^Main task
sinetask	dc.l	0			;^Sine task
sinesigbit	dc.b	0			;Sine task signal bit
donesigbit	dc.b	0			;Main task done sigbit
		even
maestbase	dc.l	0			;^Maestix Lib Base
intuibase	dc.l	0			;^Intuition Lib Base
dosbase		dc.l	0			;^DOS Lib Base
maestro		dc.l	0			;^Maestro Base
tport		dc.l	0			;^Transmit MsgPort
buffer		dc.l	0			;^Data buffer
window		dc.l	0			;^Window structure
msg1		ds.b	dmn_SIZEOF		;^first message
msg2		ds.b	dmn_SIZEOF		;^second message

modustags	dc.l	MTAG_Output,OUTPUT_FIFO	;FIFO -> Output
		dc.l	MTAG_Input,INPUT_STD	;Custom input
		dc.l	MTAG_CopyProh,CPROH_OFF	;No copy protection
		dc.l	MTAG_Emphasis,EMPH_OFF	;No emphasis
		dc.l	MTAG_Source,SRC_INPUT	;Source see input
		dc.l	MTAG_Rate,RATE_INPUT	;Rate see input
		dc.l	TAG_DONE

tasktags	dc.l	NP_Entry,SineProc	;<- New process' tags
		dc.l	NP_Priority,25
		dc.l	NP_Name,.name
		dc.l	TAG_DONE
.name		dc.b	"Maestix output process",0
		even

windowtags	dc.l	WA_IDCMP,IDCMP_CLOSEWINDOW ;<- New window's tags
		dc.l	WA_Title,.title
		dc.l	WA_InnerWidth,100
		dc.l	WA_InnerHeight,0
		dc.l	WA_DragBar,-1
		dc.l	WA_DepthGadget,-1
		dc.l	WA_CloseGadget,-1
		dc.l	WA_Activate,-1
		dc.l	WA_RMBTrap,-1
		dc.l	TAG_DONE
.title		dc.b	"Sine Output",0
		even

maestname	dc.b	"maestix.library",0	;Maestix name
intuiname	dc.b	"intuition.library",0	;Intuition name
dosname		dc.b	"dos.library",0		;DOS name
		even

	;-- output sine table ------------------;
sintab		dc.w	00000,06393,12540,18205
		dc.w	23170,27246,30274,32138
		dc.w	32767,32138,30274,27246
		dc.w	23170,18205,12540,06393
		dc.w	000000,-06393,-12540,-18205
		dc.w	-23170,-27246,-30274,-32138
		dc.w	-32768,-32138,-30274,-27246
		dc.w	-23170,-18205,-12540,-06393

*---------------------------------------------------------------*
*	== END ==						*
*								*
		END
