;  This is "SONG" (Copyright 1983 Bob Abrahams, 3035 Berkeley Ave.,
;                    Los Angeles, CA 90026)
;  SONG plays a song on the Osborne Executive computer through
;        its speaker.
;  The data for the song must be inserted in the location and in
;        the format indicated below.
;  (There is also an extra sweep tone section that runs after
;        the song that can be deleted or bypassed for other songs
;        than the one below.)
;;
TONEB	MACRO	COUNT,TIMES
;; INLINE MACRO TO CREATE TONE BURST
;; IF EITHER PARAMETER IS MISSING, THE
;; CONTENTS OF THE RELATED REGISTER PAIR
;; WILL BE USED AS IS:
;;  BC = COUNT (NUMBER OF TIMES FOR EACH HALF-CYCLE)
;;  DE = TIMES (NUMBER OF HALF-CYCLES TO EXECUTE)
;;   REGISTERS ARE NOT SAVED
;; LOOP TIME = 24 CYCLES @ 4MHZ
;; OVERHEAD TIME = 74 CYCLES
;; FREQUENCY = 1/{2*[24*COUNT]+74} * 4
	LOCAL	PASTSUB,LOOP1
	JMP	PASTSUB
@TONEB:	PUSH	B	;;Subroutine loaded once and called from  	
			;; set-up portion of macro defined below
	IN	2	;; Invert speaker bit for each half-cycle
	XRI	8
	OUT	2
LOOP1:	DCX	B	;;Decrement half-cycle count BC
	MOV	A,B	;; Count down and check for zero
	ORA	C
	JNZ	LOOP1
	POP	B	;; Restore BC for next half-cycle
	DCX	D	;;Decrement duration count DE
	MOV	A,D	;; Count down and check for zero
	ORA	E	
	JNZ	@TONEB	;; Do this until all counts are down 
	RET
PASTSUB:
;; Redefinition of macro after first reference
TONEB	MACRO	CC,TT	
	IF	NOT NUL CC
	LXI	B,CC	;; Put Count in BC if given
	ENDIF
	IF	NOT NUL TT
	LXI	D,TT	;; Put Time in DE if given
	ENDIF
	CALL	@TONEB	;; go to subroutine
	ENDM
	TONEB	COUNT,TIMES	;; To set up new definition	
				;;TONEB
	ENDM
;;
WAIT	MACRO	SEC,TENTHS
;; GENERATES A WAIT OF THE TIME GIVEN UP TO 20 SECONDS
	LOCAL	AROUND
	JMP	AROUND
;; WAIT SUBROUTINE
@WAITT:	LXI	D,16665		;;		     10	>
	DCX	D		;;  6 >			>
	MOV	A,D		;;  4 >  X 16665 =	>
	ORA	E		;;  4 >		399,360	>
	JNZ	@WAITT+3	;; 10 >			> = 400,000
	INX	D		;;	(PAD)	      6	>
	INX	D		;;	(PAD)	      6	>
	NOP			;;	(PAD)	      4	>
	DCR	B		;;		      4	>
	JNZ	@WAITT		;;		     10	>
	RET
;; END OF WAIT SUBROUTINE
AROUND:
WAIT	MACRO	S?,T?
	DB	0D9H ;EXX	;;SAVE REGS
	IF	NUL T?
T??	SET	0
	ELSE
T??	SET	T?
	ENDIF
	IF	NUL S?
S??	SET	0
	ELSE
S??	SET	S?
	ENDIF
	 IF	S??*10+T?? GT 200
ERROR:	 "WAIT" TIME GREATER THAN 20 SECONDS
	 ELSE
	  IF	S??*10+T?? LE 0
	  MVI	B,20
	  ELSE
	  MVI	B,S??*10+T??
	  ENDIF
	 CALL	@WAITT
	 DB	0D9H ;EXX	;;RESTORE REGS
	 ENDIF
	ENDM
	WAIT	SEC,TENTHS
				;;WAIT
	ENDM
;; /*
MTIME	SET	20000	;Count time for one note-count (1/4 note??)
;			; Set for fast tempo (increase to slow down).
;	Definition table for note macros -- 
;         Letters with numbers:  Notes of the scale (number indicates
;		octave, F or S indicates Flat or Sharp)
;	  Letters without numbers are Osborne keyboard equivalents
;		from program PIANO
@@A2	SET	186
@@BF2	SET	175
@@B2	SET	165
@@C2	SET	156
@@A	SET	@@C2
@@CS2	SET	147
@@W	SET	@@CS2
@@D2	SET	138
@@S	SET	@@D2	
@@EF2	SET	130
@@E	SET	@@EF2
@@E2	SET	123
@@D	SET	@@E2
@@F2	SET	116
@@F	SET	@@F2
@@FS2	SET	109
@@T	SET	@@FS2
@@G2	SET	103
@@G	SET	@@G2
@@GS2	SET	97
@@Y	SET	@@GS2
@@A3	SET	91
@@H	SET	@@A3
@@BF3	SET	86
@@U	SET	@@BF3
@@B3	SET	81
@@J	SET	@@B3
@@C3	SET	76
@@K	SET	@@C3
@@CS3	SET	72
@@D3	SET	67
@@EF3	SET	63
@@E3	SET	60
@@F3	SET	57
NOTE	MACRO	STEP,LENGTH	;;Depending on how called, 
				;;
	DW	@@&STEP		;; First put in note code
	IF	NUL LENGTH
	DW	(MTIME/@@&STEP)  ;; With no LENGTH, just give one beat
	ELSE
	DW	(MTIME/@@&STEP)*LENGTH  ;; With LENGTH, provide more beats
	ENDM
	ORG	0100H
START:
	IN	2	;Force disk drives off
	ORI	6
	OUT	2
	DI		;Disable interrupts
	LXI	H,NOTAB	;Set to run through table
NOTELOOP:
	MOV	C,M	;Put low order  byte of Note in C
	INX	H	; Second half of entry
	MOV	B,M	;Put high order byte of Note in B
	MOV	A,B	; See if 0 
	ORA	C	
	JZ	EXIT2	;  If so, Exit
	INX	H	; Put length of note in DE
	MOV	E,M
	INX	H
	MOV	D,M	
	INX	H
	PUSH	H	; Save for next note
	TONEB		;  Macro TONEB -- Run note based on loop timing
			;  in BC for length of time in DE
	MVI	B,64	;  Provide small pause between each note
REST:	DCR	B	;    (So two of the same notes in a row
	JNZ	REST	;	play as two notes.)  (No real rests are
	POP	H	;      provided in this version.)
	JMP	NOTELOOP		
EXIT2:			;  Getting out
;
;   Added section to make tone sweep after regular song
;   (Delete or bypass this part for most songs.) 	
	WAIT	,3	
	LXI	B,4FH
SIRLOOP: LXI	D,2
	PUSH	B
	TONEB
	POP	B
	INX	B
	MOV	A,C
	CPI	3FH
	JNZ	SIRLOOP
SIRLOOM: LXI	D,2
	PUSH	B
	TONEB
	POP	B
	DCX	B
	MOV	A,C
	ORA	B
	JNZ	SIRLOOM
; *** End of special section
;
EXIT5:
	EI		;  To leave, turn interrupts back on
	JMP	0	;  Exit to CP/M
DATA2:
;
;  Table for Song to be played:
;  Format:  Each entry is two words (each word in low-high order).
;  	First Word:  Note ID word (length of each half-cycle for
;		Tone Burst Macro TONEB).  Get from equivalence
;		table at top of program. 
;	Second Word:  Length of each tone burst.  This must be
;		a compensated count.  (That is, higher frequency
;		notes have shorter half-cycle time, thus would
;		make a shorter burst if same number of cycles
;		were generated.  Lengths should be approximately
;		inversely proportional to half-cycle count.)  
;	Use NOTE macro (included here) to generate these two words.
;
;  Song included here is derived from "Baroque Hoedown" (Perrey-Kingsley)
;	Fennario Music (ASCAP)  (Used in Walt Disney World/Disneyland
;	"Electric Light Parade".)
;
NOTAB:		
	NOTE	A,2
	NOTE	F,2
	NOTE	H
	NOTE	U
	NOTE	K,2
	NOTE	F,2
	NOTE	S,2
	NOTE	G,2
	NOTE	D
	NOTE	S
	NOTE	D
	NOTE	A
;
	NOTE	F,2
	NOTE	F
	NOTE	G
	NOTE	H,2
	NOTE	F,2
	NOTE	S,2
	NOTE	G,2
	NOTE	D,4
;
	NOTE	F,2
	NOTE	H
	NOTE	U
	NOTE	K,2
	NOTE	F,2
	NOTE	S,2
	NOTE	G,2
	NOTE	D
	NOTE	S
	NOTE	D
	NOTE	A
;
	NOTE	F
	NOTE	G
	NOTE	H
	NOTE	F
	NOTE	G
	NOTE	H
	NOTE	G
	NOTE	F
	NOTE	D
	NOTE	S
	NOTE	D
	NOTE	A
	NOTE	F,4
;
	NOTE	F3,2
	NOTE	F3,2
	NOTE	E3,2
	NOTE	E3,2
	NOTE	D3,2
	NOTE	D3,2
	NOTE	C3,2
	NOTE	C3,2
	NOTE	F3,2
	NOTE	F3,2
	NOTE	E3,2
	NOTE	E3,2
	NOTE	D3,2
	NOTE	D3,2
	NOTE	C3,4
;
	NOTE	F3,2
	NOTE	F3,2
	NOTE	E3,2
	NOTE	E3,2
	NOTE	D3,2
	NOTE	D3,2
	NOTE	C3,2
	NOTE	C3,2
	NOTE	F3,2
	NOTE	F3,2
	NOTE	E3,2
	NOTE	E3,2
	NOTE	D3,2
	NOTE	D3,2
	NOTE	C3,4
;
	NOTE	F,2
	NOTE	H
	NOTE	U
	NOTE	K,2
	NOTE	F,2
	NOTE	S,2
	NOTE	G,2
	NOTE	D
	NOTE	S
	NOTE	D
	NOTE	A
;
	NOTE	F,2
	NOTE	H
	NOTE	U
	NOTE	K,2
	NOTE	F,2
	NOTE	G
	NOTE	H
	NOTE	G
	NOTE	F
	NOTE	D
	NOTE	S
	NOTE	D
	NOTE	A
;
	NOTE	F,2
	NOTE	H
	NOTE	U
	NOTE	K,2
	NOTE	F,2
	NOTE	S,2
	NOTE	G,2
	NOTE	D
	NOTE	S
	NOTE	D
	NOTE	A
;
	NOTE	F
	NOTE	G
	NOTE	H
	NOTE	F
	NOTE	G
	NOTE	H
	NOTE	G
	NOTE	F
	NOTE	D
	NOTE	S
	NOTE	D
	NOTE	A
	NOTE	F,4
	DW	0	; zero word to end song
;
;  
	NOTE	C2,2	; Test scale
	NOTE	D2,2
	NOTE	E2,2
	NOTE	F2,2
	NOTE	G2,2
	NOTE	A3,2
	NOTE	B3,2
	NOTE	C3,2
	DW	0	; 0 word to end song	
	END	START

