Pill Timer
This box of tricks plays a tune three times a day to remind you to take your pills. My mum finds it most useful. The list of literals are the tune for the single tone beeper (note, rest, note, rest...). The three main routines are called in the main loop here. This was my first PIC project.
|
; Pill Timer (c) R Geleit November 2006
; Version 1.1
; Plays a tune 4 times a day to remind you to take your pills (mum)
; PIC16F84A
; Crystal frequency 3.2768MHz
list p=16F84A ; list directive to define processor
#include <p16F84A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
RADIX dec
;***** VARIABLE DEFINITIONS
mark32 equ 0x0C ; postscaler = 1/100 sec
hundths equ 0x0D
secs equ 0x0E
mins equ 0x0F
hours equ 0x10
flags equ 0x11
bpbar equ 0 ; new beep allowed? (bit)
nextinv equ 0x12 ; time of next note change
beepno equ 0x13 ; current beep in list
buztick equ 0x14 ; 1/100 sec postscaler for beep timing
;**********************************************************************
ORG 0x000 ; processor reset vector
goto start
init clrf PORTA ; reset in/out
clrf PORTB ;
bsf STATUS,5 ; select bank 1
movlw 1 ; RA0=button 0001
movwf TRISA
movlw 0 ; RB0=buzzer
movwf TRISB
movlw 7 ; external timer, max prescale 00000111
movwf OPTION_REG
bcf STATUS,5 ; select bank 0
clrf INTCON ; no interrupts
retlw 0
start call init
bcf PORTB,0 ; turn off buzzer
bwait btfss PORTA,0 ; wait 'till button pressed
goto bwait
movlw 30 ; set time (10.30am)
movwf mins
movlw 10
movwf hours
clrf secs
clrf hundths
; call turnon
mloop call time ; update file regs with current time
call beep ; maintain tune
call newbp ; start tune if time is right
goto mloop
time movfw mark32 ; update clock registers
subwf TMR0,W
btfss STATUS,Z ; 32 ticks of TMR0?
return
movlw 32 ; reset postscaler
addwf mark32,F
incf hundths,F
incf buztick,F
;return
movlw 100
subwf hundths,W
btfss STATUS,Z ; 100 hundredths of a second?
return
clrf hundths
incf secs,F ; then increase seconds
movlw 60
subwf secs,W
btfss STATUS,Z ; 60 seconds?
return
clrf secs
incf mins,F ; then increase minutes
movlw 60
subwf mins,W
btfss STATUS,Z ; 60 minutes?
return
clrf mins
incf hours,F ; then increase hours
movlw 24
subwf hours,W
btfss STATUS,Z ; 24 hours?
return
clrf hours ; then midnight
movlw 226 ; -30 seconds adjusts xtal default
movwf secs
return
beep movlw 0 ; maintain tune
subwf beepno,W
btfsc STATUS,Z ; beepno=0 => no tune playing so bomb
return
movfw nextinv
subwf buztick,W
btfss STATUS,Z ; time to stop/start a note?
return
comf PORTB,F ; stop/start note
incf beepno,F ; add next note duration to ticker
call nbl
movfw buztick ; tune is 0 terminated. if buztick=nextinv
subwf nextinv,W ; here then the note has no length
btfss STATUS,Z ; and the tune is ended
return
clrf beepno ; tune is ended
clrf PORTB
bcf flags,bpbar
return
nbl movfw beepno ; get next beep/rest length
call getinv
addwf buztick,W
movwf nextinv
return
getinv addwf PCL,F ; return note/rest length
retlw 0
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 240
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 240
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 6
retlw 9
retlw 15
retlw 6
retlw 9
retlw 30
retlw 0
newbp btfsc flags,bpbar
return
test1 movlw 0 ; check time first sec of min only
subwf secs,W
btfss STATUS,Z
return
movlw 30 ; 10:30?
subwf mins,W
btfss STATUS,Z
goto test2
movlw 10
subwf hours,W
btfsc STATUS,Z
goto turnon
test2 movlw 0 ; 15:00?
subwf mins,W
btfss STATUS,Z
goto test3
movlw 15
subwf hours,W
btfsc STATUS,Z
goto turnon
test3 movlw 0 ; 19:00?
subwf mins,W
btfss STATUS,Z
return
movlw 19
subwf hours,W
btfss STATUS,Z
return
turnon movlw 1 ; start tune!
movwf beepno
call nbl
bsf PORTB,0
bsf flags,bpbar
return
END