Dave's ****
; RA4------------------+
; |
; RA3----R1---+---R2---+---R3---C2---+----+---> TO AMPLIFIER
; | | |
; | | |
; C1 C3 R4
; | | |
; | | |
; GND GND GND
;Some component values, for the sake of an example:
; R1 = 470 ohms
; C1 = 10uF
; R2 = R3 = R4 = 10K ohms
; C2 = C3 = 10nF
; 1. Before initiating a "dong" procedure, RA3 and RA4 are both
; configured as outputs and both have been outputting a LOW.
; 2. To start the "dong", output a HIGH on both RA3 and RA4, and
; wait a period of time at least 5 * R1 * C1 to give C1 time to
; charge up (in this example, that would be about 25 milliseconds).
; 3. At the end of this period, change RA3 from an output to an input.
; 4. Then start outputting alternating 1's and 0's on RA4 at
; whatever frequency you want the tone to be, with roughly a 50%
; duty cycle. This generates the tone by "chopping" the DC voltage
; that's on the top end of C1, and it also causes C1 to start
; discharging through R2 during the half-cycles when port pin
; RA4 is low. Since the voltage on C1 decays exponentially,
; and since it's being chopped, you end up with a tone that decays
; in amplitude very realistically.
; 5. Once C1 is discharged, which takes about 10 * R2 * C1 seconds
; (about a second, in this example), stop toggling RA4 and leave
; it LOW; also make RA3 an output again and bring it LOW, too,
; until you want to emit another "dong".
;
; Dave Dilatush
;dong.asm - sound from 2 PIC pins
; 13th February 2002
;
list p=16F628
include "P16F628.inc"
bank0 macro
bcf status,rp0
bcf status,rp1
bcf status,irp
endm
bank1 macro
bsf status,rp0
bcf status,rp1
bcf status,irp
endm
#define button porta,0
#define audio1 porta,3
#define audio2 porta,4
cblock 0x20
count1 ;IRQ counter
limit ;number of IRQs @ 256us
stage ;progress flags byte
timelo ;1 second counter
timehi
shadow
endc
begin equ 0x00 ;progress flags bits
tone equ 0x01
finish equ 0x02
done equ 0x03
__config _intrc_osc_noclkout & _wdt_off & _pwrte_on & _lvp_off & _boden_off
org 0x00
goto init
org 0x04
goto isr
init clrf porta
movlw 0x07
movwf cmcon
bank1
movlw b'00000001' ;oooo oooi all o/p except button
movwf trisa
movlw b'00000000' ;oooo oooo, unused, set as o/p
movwf trisb
movlw b'10000000' ;pull-ups off, no timer pre-scaler
movwf option_reg
bank0
clrf porta
clrf portb
clrf count1
clrf stage
clrf timelo
movlw 0x0f ;set 1 second time limit
movwf timehi ;15 x 256 x 256 = 983,040 us
waitl btfsc button ;wait for button push-release to start
goto waitl
waith btfss button
goto waith
movlw 0x64 ;charge for ~25ms (100 x 256us)
movwf limit
bsf audio1
nop
bsf audio2
movlw b'00000001' ;set "begin" flag
movwf stage
bsf intcon,t0ie ;enable TMR0 IRQs
bsf intcon,gie
;==============================
loop1 nop ;loop here during "begin" IRQs
btfss stage,tone ;jump out if ready for stage2
goto loop1
;==============================
stage2 bank1
movlw b'00001000' ;set RA3 to i/p
movwf trisa
bank0 ;and tone freq on RA4
loop2 nop ;loop here during "tone" IRQs
btfss stage,finish ;jump out if ready for stage3
goto loop2
;==============================
loop3 nop ;loop here during "decay" IRQs
btfss stage,done ;jump out if at main timer limit
goto loop3
;==============================
stop bank1
movlw b'00000000' ;RA3 as o/p again
movwf trisa
bank0
bcf audio1
nop
bcf audio2
bcf intcon,t0ie
bcf intcon,gie
goto init ;restart
;==============================
isr bcf intcon,t0if
incfsz timelo ;1 second main timer
goto cont
decfsz timehi
goto cont ;if not 1 second, continue
rlf stage ;1 second, set "done" flag, end sound
retfie ;return to loop3
cont btfss stage,tone ;do not use "limit" for tone
goto inccnt
toggle movfw porta ;copy porta to RAM
movwf shadow
movlw b'00010000' ;toggle RA4 output
xorwf shadow,w
movwf porta
retfie ;return to loop2
inccnt incf count1 ;compare counter to limit (100)
movfw limit
xorwf count1,w
skpz ;if 25ms limit, set "tone" flag
retfie
clrc
rlf stage ;move flag through byte
retfie
end