;*************************************************************************** ; FILE: bee.asm * ; CONTENTS: Angry Bee * ; COPYRIGHT: MadLab Ltd. 2025 * ; AUTHOR: James Hutchby * ; UPDATED: 27/08/25 * ;*************************************************************************** processor 12F1840 include "p12f1840.inc" __config _CONFIG1, _FOSC_INTOSC&_WDTE_ON&_PWRTE_ON&_MCLRE_OFF&_CP_OFF&_CPD_OFF&_BOREN_OFF&_CLKOUTEN_OFF&_IESO_OFF&_FCMEN_ON&h'3fff' __config _CONFIG2, _WRT_ALL&_PLLEN_ON&_STVREN_ON&_BORV_19&_LVP_OFF&h'3fff' ; __idlocs h'' errorlevel -207,-302,-305,-311 ;*************************************************************************** ; * ; Specification * ; * ;*************************************************************************** ; power-up self-test - LEDs flash twice and double beeps ; flashes eyes and plays samples when motion sensed ; preset controls sensitivity ; switched off at extreme preset position ;*************************************************************************** ; * ; Port assignments * ; * ;*************************************************************************** PORTA_IO equ b'011101' ; PORTA status LEDS equ 1 ; LEDs (RA1) SPEAKER equ 5 ; speaker (RA5/P1A) PRESET equ 0 ; preset (RA0/AN0) LDR equ 2 ; LDR (RA2/AN2) leds_on macro movlb 2 bsf LATA,LEDS movlb 0 endm leds_off macro movlb 2 bcf LATA,LEDS movlb 0 endm ;*************************************************************************** ; * ; Constants and timings * ; * ;*************************************************************************** CLOCK_FREQ equ d'8000000'*4 ; processor clock frequency in Hz SAMPLE_RATE equ d'8000' ; sample rate in Hz RETRIGGER equ d'20' ; delay before retrigger in 1/100s ;*************************************************************************** ; * ; File register usage (big endian) * ; * ;*************************************************************************** cblock h'20' base:2 ; base light level sum:2 ; sum threshold ; motion threshold min, max ; minimum and maximum counts endc cblock h'70' flags ; various flags light:2 ; light level sample_end:2 ; sample end addr ; EEPROM address repeat ; repeat counter ticks:2 ; ticks counter work, work1, work2 ; work registers endc ; flags HI_LO equ 0 ; high/low word half ACTIVE equ 1 ; sample active ;*************************************************************************** ; * ; Macros * ; * ;*************************************************************************** routine macro label ; routine label endm table macro label ; lookup table label brw endm entry macro value ; table entry retlw value endm index macro label ; index table call label endm tstw macro ; test w iorlw 0 endm movff macro f1,f2 ; move file to file movfw f1 movwf f2 endm movlf macro n,reg ; move literal to file movlw n movwf reg endm negw macro ; negate w sublw 0 endm ;--------------------------------------------------------------------------- ; reset and interrupt vectors ;--------------------------------------------------------------------------- org 0 goto main_entry org 4 goto isr ;*************************************************************************** ; * ; Lookup tables * ; * ;*************************************************************************** table threshold_table entry d'0' ; sleep entry d'215' entry d'180' entry d'145' entry d'110' entry d'75' entry d'40' entry d'4' ;*************************************************************************** ; * ; Procedures * ; * ;*************************************************************************** ;--------------------------------------------------------------------------- ; interrupt service routine ;--------------------------------------------------------------------------- routine isr movlb 0 incf ticks+1 ; increment ticks skpnz incf ticks+0 btfss flags,ACTIVE ; sample active ? bra isr3 ; branch if not btfsc flags,HI_LO bra isr1 movlb 3 bsf EECON1,RD ; read program memory nop nop rlf EEDATL,w ; get sample (7 bits) rlf EEDATH,w andlw h'7f' movlb 5 ; duty cycle movwf CCPR1L bra isr2 isr1 movlb 3 movfw EEDATL ; get sample (7 bits) andlw h'7f' movlb 5 ; duty cycle movwf CCPR1L movlb 3 ; step pointer incf EEADRL skpnz incf EEADRH movfw sample_end+0 ; end of sample ? subwf EEADRH,w bnz isr2 movfw sample_end+1 subwf EEADRL,w bnz isr2 ; branch if not bcf flags,ACTIVE ; signal finished movlb 0 bra isr3 isr2 movlb 0 movlw 1< w return ;--------------------------------------------------------------------------- ; samples the LDR ;--------------------------------------------------------------------------- routine sample_ldr movlb 1 movlf (LDR<<2)|b'01',ADCON0 movlb 0 leds_off clrf sum+0 clrf sum+1 movlf d'4',repeat samp2 movlb 1 bsf ADCON0,GO samp3 clrwdt btfsc ADCON0,GO bra samp3 comf ADRESH,w ; greater = increasing light movwf light+0 comf ADRESL,w movwf light+1 movlb 0 movfw light+1 addwf sum+1 movfw light+0 addwfc sum+0 decfsz repeat goto samp2 lsrf sum+0 ; calculate average rrf sum+1 lsrf sum+0 rrf sum+1 movff sum+0,light+0 movff sum+1,light+1 return ;--------------------------------------------------------------------------- ; tests if light level above threshold, returns carry flag set if yes ;--------------------------------------------------------------------------- routine test_threshold call sample_ldr ; change in light level movfw light+1 subwf base+1,w movwf work1+1 movfw light+0 subwfb base+0,w movwf work1+0 btfss work1+0,7 ; absolute value bra test1 comf work1+0 comf work1+1 incf work1+1 skpnz incf work1+0 test1 tstf work1+0 ; saturate movlw h'ff' skpz movwf work1+1 movfw threshold ; above threshold ? subwf work1+1,w return ;--------------------------------------------------------------------------- ; main entry point ;--------------------------------------------------------------------------- routine main_entry clrwdt call init_hardware clrf flags leds_on ; double flash/beep call beep leds_off movlw d'25' call wait leds_on call beep leds_off movlw d'25' call wait movlf h'ff',min movlf h'00',max clrf flags clrf ticks+0 clrf ticks+1 clrf base+0 clrf base+1 bsf INTCON,PEIE ; enable interrupts bsf INTCON,GIE ;--------------------------------------------------------------------------- ; main loop ;--------------------------------------------------------------------------- routine main_loop clrwdt call sample_preset ; get sensitivity movwf threshold lsrf threshold lsrf threshold lsrf threshold lsrf threshold lsrf threshold,w ; divide by 32 => 0 to 7 index threshold_table movwf threshold tstw ; switched on ? bnz loop1 ; branch if yes leds_off clrf base+0 clrf base+1 movlb 1 ; watchdog timer - 4s movlf b'01100'<<1,WDTCON movlb 0 sleep ; standby mode nop bra main_loop loop1 movfw base+0 iorwf base+1,w bnz loop2 call sample_ldr ; get base light level movff light+0,base+0 movff light+1,base+1 loop2 call test_threshold ; above threshold ? bc loop3 ; branch if yes movlb 1 ; watchdog timer - 1/4s movlf b'01000'<<1,WDTCON movlb 0 sleep ; standby mode nop bra main_loop loop3 clrf ticks+0 clrf ticks+1 call play_sample1 ; play samples call play_sample2 leds_off call sample_ldr ; get base light level movff light+0,base+0 movff light+1,base+1 movlw RETRIGGER ; delay before retrigger call wait call test_threshold ; above threshold ? bc loop3 ; branch if yes bra main_loop ;*************************************************************************** ; * ; Audio samples * ; * ;*************************************************************************** fade_in macro dw h'0000',h'0208',h'0610',h'0a18',h'0e20',h'1228',h'1630',h'1a38',h'1e3f' endm fade_out macro dw h'203c',h'1c34',h'182c',h'1424',h'101c',h'0c14',h'080c',h'0404',h'0000' endm sample1 fade_in include "buzzoff.asm" fade_out sample1_ sample2 fade_in include "buzzing.asm" fade_out sample2_ end