Pill TimerThis 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