Routines |
Prev: 00949 | Up: Map | Next: 01134 |
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 |