Prev: 00949 Up: Map Next: 01134
01016: THE 'BEEP' COMMAND ROUTINE
The address of this routine is found in the parameter table.
The subroutine is entered with two numbers on the calculator stack. The topmost number (P) represents the 'pitch' of the note and the number underneath it (t) represents the 'duration'.
BEEP 01016 RST 40 The floating-point calculator is used to manipulate the two values: t, P.
01017 DEFB 49 duplicate: t, P, P
01018 DEFB 39 int: t, P, i (where i=INT P)
01019 DEFB 192 st_mem_0: t, P, i (mem-0 holds i)
01020 DEFB 3 subtract: t, p (where p is the fractional part of P)
01021 DEFB 52 stk_data: Stack the decimal value K=0.0577622606 (which is a little below 12*(2↑0.5)-1)
01022 DEFB 236,108,152,31,245
01027 DEFB 4 multiply: t, pK
01028 DEFB 161 stk_one: t, pK, 1
01029 DEFB 15 addition: t, pK+1
01030 DEFB 56 end_calc
Now perform several tests on i, the integer part of the 'pitch'.
01031 LD HL,23698 This is 'mem-0-1st' (MEMBOT).
01034 LD A,(HL) Fetch the exponent of i.
01035 AND A Give an error if i is not in the integral (short) form.
01036 JR NZ,REPORT_B
01038 INC HL Copy the sign byte to the C register.
01039 LD C,(HL)
01040 INC HL Copy the low-byte to the B register, and to the A register.
01041 LD B,(HL)
01042 LD A,B
01043 RLA Again give report B if i does not satisfy the test: -128<=i<=+127.
01044 SBC A,A
01045 CP C
01046 JR NZ,REPORT_B
01048 INC HL
01049 CP (HL)
01050 JR NZ,REPORT_B
01052 LD A,B Fetch the low-byte and test it further.
01053 ADD A,60
01055 JP P,BE_i_OK Accept -60<=i<=67.
01058 JP PO,REPORT_B Reject -128 to -61.
Note: the range 70 to 127 will be rejected later on.
The correct frequency for the 'pitch' i can now be found.
BE_i_OK 01061 LD B,250 Start '6' octaves below middle C.
BE_OCTAVE 01063 INC B Repeatedly reduce i in order to find the correct octave.
01064 SUB 12
01066 JR NC,BE_OCTAVE
01068 ADD A,12 Add back the last subtraction.
01070 PUSH BC Save the octave number.
01071 LD HL,1134 The base address of the 'semitone table'.
01074 CALL LOC_MEM Consider the table and pass the 'A th.' value to the calculator stack. (Call it C.)
01077 CALL STACK_NUM
Now the fractional part of the 'pitch' can be taken into consideration.
01080 RST 40 t, pK+1, C
01081 DEFB 4 multiply: t, C(pK+1)
01082 DEFB 56 end_calc
The final frequency f is found by modifying the 'last value' according to the octave number.
01083 POP AF Fetch the octave number.
01084 ADD A,(HL) Multiply the 'last value' by 2 to the power of the octave number.
01085 LD (HL),A
01086 RST 40 t, f
01087 DEFB 192 st_mem_0: Copy the frequency (f) to mem-0
01088 DEFB 2 delete: t
Attention is now turned to the 'duration'.
01089 DEFB 49 duplicate: t, t
01090 DEFB 56 end_calc
01091 CALL FIND_INT1 The value 'INT t' must be in the range 0 to 10.
01094 CP 11
01096 JR NC,REPORT_B
The number of complete cycles in the 'beep' is given by f*t so this value is now found.
01098 RST 40 t
01099 DEFB 224 get_mem_0: t, f
01100 DEFB 4 multiply: f*t
The result is left on the calculator stack whilst the length of the 'timing loop' required for the 'beep' is computed.
01101 DEFB 224 get_mem_0: f*t, f
01102 DEFB 52 stk_data: Stack the value (3.5*10↑6)/8=437500
01103 DEFB 128,67,85,159,128
01108 DEFB 1 exchange: f*t, 437500, f
01109 DEFB 5 division: f*t, 437500/f
01110 DEFB 52 stk_data: f*t, 437500/f, 30.125
01111 DEFB 53,113
01113 DEFB 3 subtract: f*t, 437500/f-30.125
01114 DEFB 56 end_calc
Note: the value 437500/f gives the 'half-cycle' length of the note and reducing it by 30.125 allows for 120.5 T states in which to actually produce the note and adjust the counters etc.
The values can now be transferred to the required registers.
01115 CALL FIND_INT2 The 'timing loop' value is compressed into the BC register pair and saved.
01118 PUSH BC
Note: if the timing loop value is too large then an error will occur (returning via ERROR_1), thereby excluding 'pitch' values of 70 to 127.
01119 CALL FIND_INT2 The f*t value is compressed into the BC register pair.
01122 POP HL Move the 'timing loop' value to the HL register pair.
01123 LD D,B Move the f*t value to the DE register pair.
01124 LD E,C
However before making the 'beep' test the value f*t.
01125 LD A,D Return if f*t has given the result of 'no cycles' required.
01126 OR E
01127 RET Z
01128 DEC DE Decrease the cycle number and jump to BEEPER (making at least one pass).
01129 JP BEEPER
Report B - integer out of range.
REPORT_B 01132 RST 8 Call the error handling routine.
01133 DEFB 10
Prev: 00949 Up: Map Next: 01134