03B5			  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
03B5			  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;THE LOUDSPEAKER ROUTINES;;;;;;;;;;;;;;;;;;;;;;;;;;;;
03B5			  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
03B5			  ; THE TWO SUBROUTINES IN THIS SECTION ARE THE 'BEEPER' SUBROUTINE, THAT
03B5			  ; ACTUALLY CONTROLS THE LOUDSPEAKER, AND THE 'BEEP' COMMAND  ROUTINE.
03B5			  ; THE LOUDSPEAKER IS ACTIVATED BY HAVING 'D4' LOW DUING AN 'OUT' INSTRUCTION
03B5			  ; THAT IS USING PORT '254'.WHAN 'D4' IS HIGH IN A SIMILAR SITUATION THE
03B5			  ; LOUDSPEAKER IS DEACTIVATED. A 'BEEP' CAN THEREFORE BE PRODUCED BY
03B5			  ; RUGULARITY CHANGING THE LEVEL OF 'D4'.
03B5			  ; CONSIDER NOW THE NOTE 'MIDDLE C' WHICH NAS THE FREQUENCY 261.63 HZ. IN
03B5			  ; ORDER TO GET THIS NOTE THE LOUDSPEAKER WILL HAVE TO BE ALTERNATELY
03B5			  ; ACTIVATED AND DEACTIVATED EVERY 1/623.26 TH.OFF A SECOND. IN THE SPECTRUM
03B5			  ; THE SYSTEM CLOCK IS SET TO RUN AT 3.5 MHZ.AND THE NOTE 'MIDDLE C' WILL
03B5			  ; REQUARE THAT THE REQUISITE 'OUT' INSTRUCTION BE EXECUTED AS CLOSE AS
03B5			  ; POSSIBLE TO EVERY 6.689 T  STATES. THIS LAST VALUE,WHAN REDUCED SLIGHTY
03B5			  ; FOR UN????DABLE  OVERTRACK, REPRESENTS THE 'LENGTH OF THE TIMING LOOP'
03B5			  ; IN THE 'BEEPER' SUBROUTINE.
03B5			  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;THE  'BEEPER' SUBROUTINE;;;;;;;;;;;;;;;;;;;;;;;;;
03B5			  ; THIS  SUBROUTINE IS ENTERED WITH THE 'DE' REGISTER PAIR HOLDING THE VALUE
03B5			  ; 'F','T',WHERE A NOTE OF GIVEN FREQUENCY 'F' IS TO HAVE A DIRECTION OF 'T'
03B5			  ; SECONDS, AND THE 'HL' REGISTER PAIR HOLDING A VALUE EQUAL TO THE NUMBER
03B5			  ; OF 'T' STATES IN THE 'TIMING LOOP' DIVIDED BY '4'.
03B5			  ; I.E. FOR THE NOTE 'MIDDLE C' TO BE PRODUCED FOR ONE SECOND 'DE' HOLDS +0106
03B5			  ; (INT(281.63'1)) AND HL HOLDS +066A (DERIVED FROM 6.689/4-30.125).
03B5 F3 		  BEEPER:	DI			      ; DISABLE THE INTERRUPT FOR THE
03B6					;			      ; DURATION OF A 'BEEP'.
03B6 7D 				LD    A,L		      ; SAVE 'L' TEMPORARITY.
03B7 CB3D				SRL   L 		      ; EACH 'F' IN THE L REGISTER IS
03B9 CB3D				SRL   L 		      ; TO COUNT '4' T STATES,BUT TAKE
03BB					;			      ; INT(L/4) AND COUNT '16' T
03BB					;			      ; STATES INSTEAD.
03BB 2F 				CPL			      ; GO BACK TO THE ORIGINAL VALUE
03BC E603				AND   3 		      ; IN 'L' AND FIND HOW MANY WERE
03BE 4F 				LD    C,A		      ; LOST BY TOKING INT(L/4).
03BF 0600				LD    B,0		      ;
03C1 DD21D103				LD    IX,BE_IX3 	      ; THE BASE ADDRESS OF THE TIMING
03C5					;			      ; LOOP.
03C5 DD09				ADD   IX,BC		      ; ALTER THE LENGTH OF THE TIMING
03C7					;			      ; LOOP.USE AN EARLIER STARTING
03C7					;			      ; POINT FOR EACH 'F' LOST BY TOKING
03C7					;			      ; INT(L/4).
03C7 3A485C				LD    A,(BORDCR)	      ; FETCH THE PRESENT BORDER
03CA E638				AND   38H		      ; COLOUR AND MOVE IT TO BITS
03CC 0F 				RRCA			      ; 2,1 & 0 OF THE 'A' REGISTER.
03CD 0F 				RRCA			      ;
03CE 0F 				RRCA			      ;
03CF F608				OR    8 		      ; ENSURE THE 'MIC' OUTPUT IS 'OFF'.
03D1			  ; HOW ENTER THE SOUND GENERATION LOOP. 'DE' COMPLETE PRESSES ARE MADE,I.E.
03D1			  ; A PASS FOR EACH CYCLE OF THE NOTE.
03D1			  ; THE 'HL' REGISTER HOLDS THE 'LENGTH OOF TIMING LOOP' WITH '16' T STATES
03D1			  ; BEING USED FOR EACH 'F' IN THE 'L' REGISTER AND '1,024' T STATES FOR
03D1			  ; EACH '1' IN THE 'H' REGISTER.
03D1 00 		  BE_IX3:	NOP			      ; ADD '4' T STATES FOR EACH
03D2 00 		  BE_IX2:	NOP			      ; EARLIER ENTRY POINT
03D3 00 		  BE_IX1:	NOP			      ; THAT IS USED.
03D4 04 		  BE_IX0:	INC   B 		      ; THE VALUES IN THE B&C REGISTERS        ;
03D5 0C 				INC   C 		      ; WILL COME FROM 'HL'REGISTERS
03D6			  ;					 ; - SEE BELOW.
03D6 0D 		  BE_HL_LP:	DEC   C 		      ; THE 'TIMING LOOP'.
03D7 20FD				JR    NZ,BE_HL_LP	      ; I.E.,'BC' '4' T STATES
03D9 0E3F				LD    C,3FH		      ; (BUT NOTE THAT	AT THE HALF-CYCLE
03DB 05 				DEC   B 		      ; POINT - 'C' WILL BE EQUAL TO
03DC C2D603				JP    NZ,BE_HL_LP	      ; 'L+1').
03DF			  ; THE LOUDSPEAKER IS NOW ALTERNATELY ACTIVATED AND DEACTIVATED.
03DF EE10				XOR   010H		      ; FLIP BIT 4.
03E1 D3FE				OUT   (CSP1),A		      ; PERFORM THE 'OUT OPERATION;
03E3					;			      ; HAVING THE BORDER UNCHANGED
03E3 44 				LD    B,H		      ; RESET THE B REGISTER.
03E4 4F 				LD    C,A		      ; SAVE THE A REGISTER.
03E5 CB67				BIT   4,A		      ; JUMP IF THE HALF-CYCLE
03E7 2009				JR    NZ,BE_AGAIN	      ; POINT.
03E9			  ; AFTER A FULL CYCLE THE 'DE' REGISTER PAIR IS TASTED.
03E9 7A 				LD    A,D		      ; JUMP FORWARD IN THE LAST
03EA B3 				OR    E 		      ; COMPLETE PASS HAS BEEN
03EB 2809				JR    Z,BE_END		      ; MADE ALREADY.
03ED 79 				LD    A,C		      ; FETCH THE SAVED VALUE.
03EE 4D 				LD    C,L		      ; RESET THE 'C' REGISTER.
03EF 1B 				DEC   DE		      ; DECREASE THE PASS COUNTER.
03F0 DDE9				JP    (IX)		      ; JUMP BACK TO THE REQUIRED
03F2			  ;					 ; STARTING LOCATION OF THE LOOP.
03F2			  ; THE PARAMETERS FOR THE SECOND HALF-CYCLE ARE SET UP.
03F2 4D 		  BE_AGAIN:	LD    C,L		      ; RESET THE 'C' REGISTER.
03F3 0C 				INC   C 		      ; ADD '16' T STATES AS THIS PATH
03F4					;			      ; IS SHORTER.
03F4 DDE9				JP    (IX)		      ; JUMP BACK.
03F6			  ; UPON  COMPLETITION OF THE 'BEEP' THE MASKABLE INTERRUPT HAS TO BE ENABLED.
03F6 FB 		  BE_END:	EI			      ; ENABLE INTERRUPT.
03F7 C9 				RET			      ; FINALLY RETURN.
03F8			  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;THE  'BEEP' COMAND ROUTINE;;;;;;;;;;;;;;;;;;;;
03F8			  ; THIS SUBROUTINE IS ENTERED WITH TWO NUMBER ON THE CALCULATOR STACK. THE
03F8			  ; TOPMOST NUMBER REPRESENT THE 'PITCH' OF THE NOTE AND THE NUMBER UNDERNEATH
03F8			  ; IT REPRESENTS THE 'DURATION'.
03F8 EF 		  BEEP: 	RST   28H		      ; THE FLOATING-POINT CALCULATOR IS
03F9					;			      ; USED TO MANIPULATE THE TWO
03F9					;			      ; VALUES - T & P
03F9 31 				DEFB 031H		      ; DUPLICATE     ; T,P,P
03FA 27 				DEFB 027H		      ; INT	      ; T,P I (WHERE I - INT P)
03FB C0 				DEFB 0C0H		      ; ST.MEM-0      ; T,P,I (MEM-0 HOLDS I)
03FC 03 				DEFB 003H		      ; SUBTRACT      ; T,P (WHERE P IS THE FRACTIONAL
03FD					;			      ; PART OF P)
03FD 34 				DEFB 034H		      ; STK.DATA      ; STACK THE DECIMAL VALUE 'K',
03FE EC 				DEFB 0ECH		      ; EXPONENT +7C  ; 0.0577622606 (WHICH IS A
03FF 6C981FF5				DEFB 06CH,098H,01FH,0F5H      ; LITTLE BELOW 12*SQR(2)-1)
0403 04 				DEFB 004H		      ; MULTIPLY      ; T,PK
0404 A1 				DEFB 0A1H		      ; STK.ONE       ; T,PK,1
0405 0F 				DEFB 00FH		      ; ADDITION      ; T,PK+1
0406 38 				DEFB 038H		      ; END CALC.
0407			  ; NOW PERFORM SEVERAL TESTS ON 'I', THE INTEGER PART OF THE 'PITCH'.
0407 21925C				LD    HL,MEMBOT 	      ; THIS IS 'MEM-0-IST' (MEMBOT).
040A 7E 				LD    A,(HL)		      ; FETCH THE EXPONENT OF 'I'.
040B A7 				AND   A 		      ; GIVE AN ERROR IF 'I' IS NOT IN THE
040C 205E				JR    NZ,OF_RANG	      ; INTEGRAL (SHORT) FORM.
040E 23 				INC   HL		      ; COPY HE SING BYTE TO THE
040F 4E 				LD    C,(HL)		      ; 'C' REGISTER.
0410 23 				INC   HL		      ; COPY THE LOW-BYTE TO THE
0411 46 				LD    B,(HL)		      ; 'B' REGISTER; AND TO THE 'A'
0412 78 				LD    A,B		      ; REGISTER.
0413 17 				RLA			      ; AGAIN GIVE REPORT_B IF 'I' DOES NOT
0414 9F 				SBC   A,A		      ; SATISFY THE TEST:
0415 B9 				CP    C 		      ; -128<=I<=+127
0416 2054				JR    NZ,OF_RANG	      ;
0418 23 				INC   HL		      ;
0419 BE 				CP    (HL)		      ;
041A 2050				JR    NZ,OF_RANG	      ;
041C 78 				LD    A,B		      ; FETCH THE LOW-BYTE AND TEST
041D					;			      ; IT FURTHER.
041D C63C				ADD   A,3CH		      ;
041F F22504				JP    P,BE_I_OK 	      ; ACCEPT -60<=I<=67.
0422 E26C04				JP    PO,OF_RANG	      ; REJECT -128 TO -61.
0425			  ; NOTE: THE RANGE +70 TO +127 WILL BE REJECTED LATER ON.
0425			  ; THE CORRECT FREQUENCY FOR THE 'PITCH' I CAN NOW BE FOUND.
0425 06FA		  BE_I_OK:	LD    B,-6		      ; START '6' OCTAVES BELOW MIDDLE C.
0427 04 		  BE_OCTAVE:	INC   B 		      ; REPEATEDLY REDUCE 'I' IN ORDER TO
0428 D60C				SUB   12		      ; FIND TTHE CORRECT OCTAVE.
042A 30FB				JR    NC,BE_OCTAVE	      ;
042C C60C				ADD   A,12		      ; ADD BACK THE LAST SUBTRACTION.
042E C5 				PUSH  BC		      ; SAVE THE OCTAVE NUMBER.
042F 216E04				LD    HL,S18		      ; THE BASE ADDRESS OF THE 'SEMITONE
0432					;			      ; TABLE'.
0432 CD0634				CALL  LOC_MEM		      ; CONSIDER THE TABLE AND PASS THE
0435 CDB433				CALL  STACK_NUM 	      ; 'A TH.' VALUE T THE CALCULATOR
0438					;			      ; STACK .(CALL IS 'C').
0438			  ; NOW THE FRACTIONAL PART OF THE 'PITCH' CAN BE TAKEN INTO CONSIDERATION.
0438 EF 				RST   28H		      ; T,PK+1,C
0439 04 				DEFB 004H		      ; MULTIPLY	 ; T,C(PK+1)
043A 38 				DEFB 038H		      ; END CALC.
043B			  ; THE FIND FREQUENCY F IS FOUND BY MODIFYING THE "LAST VALUE" ACCORDING TO THE
043B			  ; OCTAVE NUMBER
043B F1 				POP   AF		      ; FETCH THE OCTAVE NUMBER
043C 86 				ADD   A,(HL)		      ; MULTIPLY THE "LAST VALUE" BY
043D 77 				LD    (HL),A		      ; 2 TO THE POWER OF THE OCTAVE NUMBER
043E EF 				RST   28H		      ; T,F
043F C0 				DEFB 0C0H		      ; ST_MEM0:	   THE FREQUENCY IS PUT ASIDE FOR
0440 02 				DEFB 002H		      ; DELETE: 	   MOMENT IN MEM_0
0441			  ; ATTENTION IS NOW TURNED TO THE "DURATION"
0441 31 				DEFB 031H		      ; DUPLICATE:	   T,T
0442 38 				DEFB 038H		      ; END_CALC
0443 CD941E				CALL  FIND_INT1 	      ; THE VALUE "INT T" MUST BE IN
0446 FE0B				CP    00BH		      ; THE RANGE 00 TO 0A
0448 3022				JR    NC,OF_RANG
044A			  ; THE NUMBER OF COMPLETE CICLES IN THE "BEEP" IS GIVEN BY "F*T" SO THIS VALUE
044A			  ; IS NOW FOUND
044A EF 				RST   28H		      ; T
044B E0 				DEFB 0E0H		      ; GET_MEM_0:	   T,F
044C 04 				DEFB 004H		      ; MULTIPLY:	   T*F
044D			  ; THE RESULT IS LEFT IN THE CALCULATOR STACK WHILST THE LENGTH OF THE
044D			  ; "TIMING LOOP" REQUIRED FOR THE "BEEP" TO COMPLETE.
044D E0 				DEFB 0E0H		      ; GET_MEM_0:	  T*F,F
044E 34 				DEFB 034H		      ; STK_DATA:	  THE VALUE "3.5*10**6/8"
044F 80 				DEFB 080H		      ; FOUR BYTES	  IN FORMED ON THE TOP OF
0450 43 				DEFB 043H		      ; EXPONENT +93	  THE CALCULATOR STACK
0451 559F80				DEFB 055H, 09FH, 080H	      ; T*F,F,437.500 (DEC.)
0454 01 				DEFB 001H		      ; EXCHANGE:	  T*F,437.500,F
0455 05 				DEFB 005H		      ; DIVISION:	  T*F,437.500/F
0456 34 				DEFB 034H		      ; STK_DATA
0457 35 				DEFB 035H		      ; EXPONENT +65
0458 71 				DEFB 071H		      ; (00,00,00)	  T*F,437.500/F,30.125 (DEC.)
0459 03 				DEFB 003H		      ; SUBTRACT:	  T*F,437.500/F-30.125
045A 38 				DEFB 038H		      ; END_CALC
045B			  ; NOTE: THE VALUE 437.500/F GIVES THE "HALF-CYCLE" LENGTH OF THE NOTE AND
045B			  ; REDUCING IT BY 30.125 ALLOWS FOR 120,5 T STATES IN WHICH TO ACTUALLY PRODUCE
045B			  ; THE NOTE END ADJUST THE COUNTERS ETC.
045B			  ;   THE VALUES CAN NOW BE TRANSFERED TO THE REQUIRED REGISTERS
045B CD991E				CALL  FIND_INT2 	      ; THE "TIMING LOOP" VALUE IS
045E					;			      ; COMPRESSED INTO THE BC
045E C5 				PUSH  BC		      ; REGSITER PAIR; AND SAVED
045F			  ; NOTE: IF THE TIMING LOOP VALUE IS TOO LARGE THEN AN ERROR WILL OCCUR
045F			  ; (RETURNING VIA ERROR_1); THEREBY EXCLUDING "PITCH" VALUES OF +70 TO +127.
045F CD991E				CALL  FIND_INT2 	      ; THE "T*F" VALUE IS COMPRESSED
0462					;			      ; INTO THE BC REGISTER PAIR
0462 E1 				POP   HL		      ; MOVE THE "TIMING LOOP" VALUE TO
0463					;			      ; THE HL REGISTER PAIR
0463 50 				LD    D,B		      ; MOVE THE "T*F" VALUE TO THE
0464 59 				LD    E,C		      ; DE REGISTER PAIR
0465			  ; HOWEVER BEFORE MAKING THE "BEEP" TEST THE VALUE "T*F"
0465 7A 				LD    A,D		      ; RETURN IF "T*F" HAS GIVEN THE
0466 B3 				OR    E 		      ; RESULT OF "NO CYCLES"
0467 C8 				RET   Z 		      ; REQUIRED
0468 1B 				DEC   DE		      ; DECREASE THE CYCLE NUMBER AND
0469 C3B503				JP    BEEPER		      ; JUMP TO THE BEEPER SUBROUTINE
046C					;			      ; (MAKING, AT LEAST ONE PASS).
046C			  ; REPORT B - INTEGER OUT OF RANGE
046C CF 		  OF_RANG:	RST   8 		      ; CALL THE ERROR HANDLING
046D 0A 				DEFB  0AH		      ; ROUTINE
046E			  ;
046E			  ; THE "SEMI-TONE" TABLE
046E			  ; THE TABLE HOLDS THE FREQUENCES OF THE TWELVE SEMI-TONES IN AN OCTAVE.
046E			  ;					      FREQUENSY HZ	  NOTE
046E 8902D01286 	  S18:		DEFB  89H,02H,0D0H, 12H, 86H  ;   261.63	      C
0473
0473 890A976075 			DEFB  89H,0AH,97H, 60H, 75H   ;   277.18	      C#
0478
0478 8912D5171F 			DEFB  89H,12H,0D5H,17H, 1FH   ;   293.65	      D
047D
047D 891B904102 			DEFB  89H,1BH,90H, 41H, 02H   ;   311.13	      D#
0482
0482 8924D053CA 			DEFB  89H,24H,0D0H,53H, 0CAH  ;   329.63	      E
0487
0487 892E9D36B1 			DEFB  89H,2EH,9DH, 36H, 0B1H  ;   349.23	      F
048C
048C 8938FF493E 			DEFB  89H,38H,0FFH,49H, 3EH   ;   369.99	      F#
0491
0491 8943FF6A73 			DEFB  89H,43H,0FFH,6AH, 73H   ;   392		      G
0496
0496 894FA70054 			DEFB  89H,4FH,0A7H,0,	54H   ;   415.30	      G#
049B
049B 895C000000 			DEFB  89H,5CH,0,   0,	0     ;   440		      A
04A0
04A0 896914F624 			DEFB  89H,69H,14H, 0F6H,24H   ;   466.10	      A#
04A5
04A5 8976F11005 			DEFB  89H,76H,0F1H,10H, 05H   ;   496.68	      B
04AA
04AA			  ;
04AA			  ; !!!???!!!
04AA			  ; THE "PROGRAM NAME" SUBROUTINE (ZX81)
04AA			  ; THE FOLLOWING SUBROUTINE APPLIES TO THE ZX81 AND WAS NOT REMOVED WHEN THE
04AA			  ; PROGRAM WAS REWRITTEN FOR THE SPECTRUM.
04AA 010039		  S_RUS:	LD BC,TRSYMB-100H	;   CALL   SCANNING
04AD ED43365C				LD (CHARS),BC		;   LD	   A,(FLAGS)
04B1 C9 				RET			;   ADD    A,A
04B2			  ;					;   JP	   M,REPORT_C
04B2 01003C		  S_LAT:	LD BC,TSYMB-100H	;   POP    HL
04B5 ED43365C				LD (CHARS),BC		;   RET    NC
04B9 C9 				RET			;
04BA			  ;
04C2			  ORG		04C2H			;   PUSH   HL
04C2								;   CALL   STK_FETCH
04C2								;   LD	   H,D
04C2								;   LD	   L,E
04C2								;   DEC    C
04C2								;   RET    M
04C2								;   ADD    HL,BC
04C2								;   SET    7,(HL)
04C2								;   RET
04C2			  ;

                                                                                                                                                                                                    