	;; -----------------------------------------------
	;; PShell - a runtime environment for    
	;; sharp pocket computers                 
	;; file     : sound.asm                   
	;; author   : puehringer edgar           
	;; date     : 09.05.2005                 
	;; version  : 1.0.0                      
	;; assembler: as61860                    
	;;                                       
	;; All sound output related funtions for pshell
	;; -----------------------------------------------

.area pshell (REL)
        
.include "pshell.h"
.include "internal.h"


	;; -----------------------------------------------
	;; Emits a short beep, but only if ps_sound_enbl
	;; is set (Otherwise the same time of silence
	;; appears).
	;; Used registers: A,B,I,K,DP, 1 stack pos.
	;; -----------------------------------------------

ps_beep::
	LIA  95
	LIB  2
	CALL ps_play_sound
	LIA  49
	LIB  1
	CALL ps_play_sound
	JP   ps_reset_sound	; JP instead of CALL,
				; to save one byte
	
	;; -----------------------------------------------
	;; Toggles the beeps on and off. Return value:
	;; If carry is set, beeps are enabled
	;; Used registers: A,B,DP
	;; label prefix 22
	;; -----------------------------------------------

ps_toggle_sound::
	LIDP ps_sound_enbl
	LDD
	CPIA 0
	JRZP lb2201
	RA
	STD
	RC
	RTN
lb2201:	LIA  0xff
	STD
	SC
	RTN
	
	
	;; -----------------------------------------------
	;; Sets the Xin/Xout ports to silence 
	;; Used registers: A
	;; -----------------------------------------------
	
ps_reset_sound::
	LIP  95
	ANIM PORT_C_DISPLAY
	OUTC
	RTN

	
	;; -----------------------------------------------
	;; Sets the Xin/Xout ports to 2/4kHz 
	;; If carry is set the beep has 4 kHz, 2 kHz
	;; otherwise
	;; Used registers: A,B  
	;; label prefix 24
	;; -----------------------------------------------
	
ps_set_sound::
	LIP  95	
	JRCP lb2401

	ORIM PORT_C_BEEP_CTRL
	JRP  lb2402
	
lb2401: ORIM PORT_C_BEEP_CTRL+PORT_C_BEEP_FREQ
	
lb2402:	LIDP ps_sound_enbl
	LDD
	CPIA 0
	JRZP lb2403
	
	OUTC
	
lb2403:	RTN

	
	;; -----------------------------------------------
	;; Play sound of variable frequency and duration,
	;; but only if ps_sound_enbl is set (Otherwise the
	;; same time of silence appears). Frequency is
	;; given in A, duration in B. Preserves the
	;; display on/off state
	;; 
	;; Timing calculation for 768k resonator
	;; f = 256000 / (4*A+55) ==>
	;;   f = 64000 / (A+13,75)
	;; 
	;; Timing calculation for 576k resonator
	;; f = 192000 / (3*A+41) ==>
	;;   f = 64000 / (A+13,67)
	;;
	;; As you can see, timing is the same (with a 
	;; small error) for e.g. PC-1402 and PC-1403.
	;; f max = 4655 Hz, f min = 238 Hz.
	;; There is more error for PCs with 800k
	;; resonator (plus 4%):
	;; f = 266667 / (4*A+55) ==>
	;;   f = 66667 / (A+13,75)
	;;
	;; Duratrion is B * 10ms
	;;
	;; For very low freqencies (starting with A>115)
	;; the duration gets longer (up to two times
	;; for A=255).
	;; 
	;; This is a more sophisticated version of the
	;; sample disassembled from Bernie's homepage:
	;;
	;;	LII   50	; Param. frequency
	;; lb1:	WAIT  50	; Param. duration
	;;	LIP   95
	;;	ORIM  16
	;;	OUTC
	;;	ANIM  239
	;;	OUTC
	;;	TEST  2
	;;	JRZM  lb1
	;;	DECI
	;;	JRNZM lb1
	;;	RTN
	;;
	;; Used registers: A,B,I,K,DP, 1 stack pos.
	;; label prefix 26
	;; -----------------------------------------------
	
ps_play_sound::
	LIDP lb2603+1		; set length of
	STD			;  wait intervals
.if (__PC_RESONATOR_768K__ + __PC_RESONATOR_800K__)
	LIDP lb2604+1
	STD
.endif
	LIDP lb2605+1
	STD
	LIDP lb2606+1
	STD
	
	EXAB			; K=B, B=A
	LP   REG_K
	EXAM

	LIDP ps_sound_enbl	; if snd enabled,
	LDD			; sleep an equal time
	CPIA 0
	JRNZP lb2601

	EXAB			; we don't need a RTN, bcause
	JP   ps_sleep		; ps_sleep has one
lb2601:

	LIA  0x04		; push 4
	PUSH
		
lb2602:	LP   REG_K		; I=K, P=95
	LDM
	LP   REG_I
	EXAM
	LIP  95
	
	;; ================================
	;; Start of timing loop
	
lb2603: WAIT 0x00		; 6 + B
.if (__PC_RESONATOR_768K__ + __PC_RESONATOR_800K__)
lb2604:	WAIT 0x00		; 6 + B
	WAIT 0x02		; 8
.endif
	ORIM PORT_C_BEEP_FREQ	; 4
	OUTC			; 2
lb2605:	WAIT 0x00		; 6 + B
lb2606:	WAIT 0x00		; 6 + B
        ANIM PORT_C_DISPLAY	; 4
	OUTC			; 2
        TEST TEST_CNT_2		; 4
	JRZM lb2603		; 7 (taken)
	
	;; ================================
	;;			  41+3*B (55+4*B)
	
	DECI
	JRNZM lb2603		; loop I (=param K) times

	LOOP lb2602		; loop 5 times
	
	RTN
