Routines 
Prev: 03B5  Up: Map 
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  03F8  RST $28  The floatingpoint calculator is used to manipulate the two values: t, P.  
03F9  DEFB $31  duplicate: t, P, P  
03FA  DEFB $27  int: t, P, i (where i=INT P)  
03FB  DEFB $C0  st_mem_0: t, P, i (mem0 holds i)  
03FC  DEFB $03  subtract: t, p (where p is the fractional part of P)  
03FD  DEFB $34  stk_data: Stack the decimal value K=0.0577622606 (which is a little below 12*(2↑0.5)1)  
03FE  DEFB $EC,$6C,$98,$1F,$F5  
0403  DEFB $04  multiply: t, pK  
0404  DEFB $A1  stk_one: t, pK, 1  
0405  DEFB $0F  addition: t, pK+1  
0406  DEFB $38  end_calc  
Now perform several tests on i, the integer part of the 'pitch'.


0407  LD HL,$5C92  This is 'mem01st' (MEMBOT).  
040A  LD A,(HL)  Fetch the exponent of i.  
040B  AND A  Give an error if i is not in the integral (short) form.  
040C  JR NZ,REPORT_B  
040E  INC HL  Copy the sign byte to the C register.  
040F  LD C,(HL)  
0410  INC HL  Copy the lowbyte to the B register, and to the A register.  
0411  LD B,(HL)  
0412  LD A,B  
0413  RLA  Again give report B if i does not satisfy the test: 128<=i<=+127.  
0414  SBC A,A  
0415  CP C  
0416  JR NZ,REPORT_B  
0418  INC HL  
0419  CP (HL)  
041A  JR NZ,REPORT_B  
041C  LD A,B  Fetch the lowbyte and test it further.  
041D  ADD A,$3C  
041F  JP P,BE_i_OK  Accept 60<=i<=67.  
0422  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  0425  LD B,$FA  Start '6' octaves below middle C.  
BE_OCTAVE  0427  INC B  Repeatedly reduce i in order to find the correct octave.  
0428  SUB $0C  
042A  JR NC,BE_OCTAVE  
042C  ADD A,$0C  Add back the last subtraction.  
042E  PUSH BC  Save the octave number.  
042F  LD HL,$046E  The base address of the 'semitone table'.  
0432  CALL LOC_MEM  Consider the table and pass the 'A th.' value to the calculator stack. (Call it C.)  
0435  CALL STACK_NUM  
Now the fractional part of the 'pitch' can be taken into consideration.


0438  RST $28  t, pK+1, C  
0439  DEFB $04  multiply: t, C(pK+1)  
043A  DEFB $38  end_calc  
The final frequency f is found by modifying the 'last value' according to the octave number.


043B  POP AF  Fetch the octave number.  
043C  ADD A,(HL)  Multiply the 'last value' by 2 to the power of the octave number.  
043D  LD (HL),A  
043E  RST $28  t, f  
043F  DEFB $C0  st_mem_0: Copy the frequency (f) to mem0  
0440  DEFB $02  delete: t  
Attention is now turned to the 'duration'.


0441  DEFB $31  duplicate: t, t  
0442  DEFB $38  end_calc  
0443  CALL FIND_INT1  The value 'INT t' must be in the range +00 to +0A.  
0446  CP $0B  
0448  JR NC,REPORT_B  
The number of complete cycles in the 'beep' is given by f*t so this value is now found.


044A  RST $28  t  
044B  DEFB $E0  get_mem_0: t, f  
044C  DEFB $04  multiply: f*t  
The result is left on the calculator stack whilst the length of the 'timing loop' required for the 'beep' is computed.


044D  DEFB $E0  get_mem_0: f*t, f  
044E  DEFB $34  stk_data: Stack the value (3.5*10↑6)/8=437500  
044F  DEFB $80,$43,$55,$9F,$80  
0454  DEFB $01  exchange: f*t, 437500, f  
0455  DEFB $05  division: f*t, 437500/f  
0456  DEFB $34  stk_data: f*t, 437500/f, 30.125  
0457  DEFB $35,$71  
0459  DEFB $03  subtract: f*t, 437500/f30.125  
045A  DEFB $38  end_calc  
Note: the value 437500/f gives the 'halfcycle' 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.


045B  CALL FIND_INT2  The 'timing loop' value is compressed into the BC register pair and saved.  
045E  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.


045F  CALL FIND_INT2  The f*t value is compressed into the BC register pair.  
0462  POP HL  Move the 'timing loop' value to the HL register pair.  
0463  LD D,B  Move the f*t value to the DE register pair.  
0464  LD E,C  
However before making the 'beep' test the value f*t.


0465  LD A,D  Return if f*t has given the result of 'no cycles' required.  
0466  OR E  
0467  RET Z  
0468  DEC DE  Decrease the cycle number and jump to BEEPER (making at least one pass).  
0469  JP BEEPER  
Report B  integer out of range.


REPORT_B  046C  RST $08  Call the error handling routine.  
046D  DEFB $0A 
Prev: 03B5  Up: Map 