; ***************************************************************
; * Copyright (c) 2001, Embed Inc (http://www.embedinc.com) *
; * *
; * Permission to copy this file is granted as long as this *
; * copyright notice is included in its entirety at the *
; * beginning of the file, whether the file is copied in whole *
; * or in part and regardless of whether other information is *
; * added to the copy. *
; * *
; * The contents of this file may be used in any way, *
; * commercial or otherwise. This file is provided "as is", *
; * and Embed Inc makes no claims of suitability for a *
; * particular purpose nor assumes any liability resulting from *
; * its use. *
; ***************************************************************
;
; Module that manages the output sounds.
;
include "hal.inc"
extern rand_max ;set REG0 to random number in range 0 thru REG1
extern sound ;start new sound at REG3,REG2 with REG1,REG0 samples
extern lookflas ;prog memory word at REG3,REG2 into REG1,REG0, inc adr
extern_flags ;declare global flag bits EXTERN
;
;***********************************************************************
;
; Configuration constants.
;
lbank equ 0 ;register bank for the local state of this module
delmin equ 50 ;min delay between sounds, 100mS units
delmax equ 100 ;max delay between sounds, 100mS units
;
; Derived constants.
;
lbankadr equ bankadr(lbank) ;address within local state register bank
;
;***********************************************************************
;
; Global state. All this state is assumed to be in the GBANK register
; bank by other modules.
;
.bank#v(gbank) udata
;
;***********************************************************************
;
; Local state.
;
if lbank != gbank
.bank#v(lbank) udata
endif
cntdel res 1 ;100mS ticks until start next sound
.soun code
;
;***********************************************************************
;
; Table SOUNDS
;
; This table lists all the available sounds. Each table entry contains
; the 14 bit starting address of the sound.
;
; A sound starts with the 14 bit number of samples in the sound, followed
; by the samples. Two sound samples are stored per 14 bit program memory
; word, with the low 7 bits being the first sample and the high 7 bits
; the second. The number of samples may be odd, in which case the high
; 7 bits of the last program memory location of the sound will be ignored.
;
n_sounds set 0 ;init number of entries in SOUNDS table
;
;*****
;
; Macro SOUND_ENT <start adr>
;
; This macro creates one SOUNDS table entry. The argument is the sound
; start address. The sound is assumed to be stored in a separate module,
; so the start address symbol will be declared external, and a table
; entry of the proper format will be created. The assembly variable
; N_SOUNDS will be incremented. This will indicate the number of
; table entries to code located after this table.
;
sound_ent macro startadr
extern startadr ;declare the sound start symbol external
data startadr ;write the table entry
n_sounds set n_sounds + 1 ;count one more SOUNDS table entry
endm
;
;*****
;
sounds ;start of table listing the available sounds
sound_ent owl
sound_ent howl
sound_ent pop
sound_ent pop2
;
;***********************************************************************
;
; Subroutine SOUN_INIT
;
; Initialize the hardware and software state managed by this module.
;
glbsub soun_init, noregs
dbankif lbankadr
movlw (delmin + delmax) / 2 ;init 100mS ticks until next sound start
movwf cntdel
leaverest
;
;***********************************************************************
;
; Subroutine SOUN_OFF
;
; OFF mode was just entered. Update the sound handling accordingly.
;
glbsub soun_off, noregs
dbankif gbankadr
bcf flag_audon ;make sure audio output is off
leaverest
;
;***********************************************************************
;
; Subroutine SOUN_100MS
;
; This subroutine is called once every 100mS.
;
; A new randomly chosen sound is started occasionally. The local variable
; CNTDEL is the number of 100mS ticks until it is time to start a new
; sound. It is reloaded with a random value from DELMIN to DELMAX for
; each sound. CNTDEL is not decremented while a sound is being played,
; so DELMIN and DELMAX represent the min/max time of the silence between
; sounds.
;
glbsub soun_100ms, regf0 | regf1 | regf2 | regf3
;
; Check for OFF mode, in which case there is nothing to do.
;
dbankif gbankadr
btfsc flag_off ;not in OFF mode ?
goto done_newsound ;in OFF mode, sound output is disabled
;
; Check for a sound is currently playing. If so, there is nothing to do.
;
dbankif gbankadr
btfsc flag_audon ;the audio output is currently off (no sound playing) ?
goto done_newsound ;a sound is in progress, do nothing until it's done
; ;***** START DEBUG CODE *****
; ;
; ; Don't start a sound if the external SNDON input is low.
; ;
; dbankif sndon_reg
; btfss sndon_reg, sndon_bit ;sounds are enabled ?
; goto done_newsound ;sounds are disabled
; ;
; ;***** END DEBUG CODE *****
;
; No sound is currently playing.
;
dbankif lbankadr
decfsz cntdel ;count one less 100mS tick until start new sound
goto done_newsound ;not time yet to start a new sound
;
; The delay counter just expired. This means it is time to start a new sound.
;
; Reset the delay counter with a random value from DELMIN to DELMAX. This
; will be the length of the silence after this new sound.
;
movlw delmax - delmin ;make number of valid delays in the range
movwf reg1 ;pass random number max limit
gcall rand_max ;get random number in REG0 that is at or below REG1
movf reg0, w ;get the 0 - N random number into W
addlw delmin ;make randomly chosen delay time within the range
dbankif lbankadr
movwf cntdel ;set length of quiet time after the new sound
;
; Chose a random sound from the SOUNDS table.
;
movlw n_sounds - 1 ;pass max random number value
movwf reg1
gcall rand_max ;pick a random 0-N SOUNDS table entry in REG0
movlw high sounds ;init high byte of table entry address
movwf reg3
movlw low sounds ;get low byte of table start address
addwf reg0, w ;make low byte of table entry address
movwf reg2 ;pass it
skip_ncarr ;no carry into address high byte ?
incf reg3 ;propagate the carry to the high address byte
gcall lookflas ;lookup entry at REG3,REG2 into REG1,REG0, inc address
;
; REG1,REG0 contains the starting address of the randomly chosen sound.
; Now read the sound length word, and pass the starting data address and
; data length to SOUND to start the sound playing.
;
movf reg0, w ;pass program memory read address in REG3,REG2
movwf reg2
movf reg1, w
movwf reg3
gcall lookflas ;read num samples into REG1,REG0, inc adr in REG3,REG2
gcall sound ;start sound at REG3,REG2 with REG2,REG0 num of samples
done_newsound unbank ;done dealing with starting new sound issues
leaverest
end