#define SIM 0 #define USE_16F628 0 #define USE_16F630 1 ; turn off TEST_VCOMPARE or run out of mem #define USE_16F84A 0 ; NOT SUPPORTED!! #define DO_VCHECK 1 #define TEST_VCOMPARE 0 #define CHECK_SYNC 1 #define NO_SLEEP_IF_HELD 0 #if USE_16F630 LIST P=16F630 include <p16f630.inc> __CONFIG 0x24 #endif #if USE_16F628 LIST P=16F628 ;f=inhx8m include <p16f628.inc> __CONFIG 0x3f38 #endif #if USE_16F84A ; ; 16F84 IS NO LONGER SUPPORTED!! ; LIST P=16F84A ;f=inhx8m include <p16f84a.inc> __CONFIG 0x3ff1 #endif RADIX DEC ;################################# ; SETUP FOR DIFFERENT PROCESSORS ;################################# ; ; PIC 16F630 ; #if USE_16F630 #define RED_LEDS PORTC #define b_led_red0 PORTC,0 #define b_led_red1 PORTC,1 #define b_led_red2 PORTC,2 #define b_led_red4 PORTC,3 #define b_led_red3 PORTC,4 #define RED0 0x01 #define RED1 0x02 #define RED2 0x04 #define RED3 0x10 #define RED4 0x08 #define RED_END 0x80 #define END_BIT 7 #define b_led_green0 PORTA,4 #define b_led_green1 PORTA,5 #define b_gravity PORTA,2 TRISVAL_A equ 0x06 ; Port tristate and initial values TRISVAL_C equ 0x00 FB equ 0x20 ; first free byte #define b_por PCON,NOT_POR #define b_rp0 STATUS,RP0 #define b_rapu OPTION_REG,NOT_GPPU #define b_intedg OPTION_REG,INTEDG #define b_int0if INTCON,INTF #define b_int0ie INTCON,INTE #define b_gie INTCON,GIE #define b_c1out CMCON,COUT #define b_wpua2 WPUA,2 #endif ; ; PIC 16F628 ; #if USE_16F628 #define RED_LEDS PORTB #define b_led_red4 PORTB,1 #define b_led_red3 PORTB,2 #define b_led_red2 PORTB,3 #define b_led_red1 PORTB,4 #define b_led_red0 PORTB,5 #define RED4 0x02 #define RED3 0x04 #define RED2 0x08 #define RED1 0x10 #define RED0 0x20 #define RED_END 0x80 ; end bit #define END_BIT 7 #define b_led_green0 PORTA,7 #define b_led_green1 PORTA,6 #define b_gravity PORTB,0 TRISVAL_A equ 0x01 ; Port tristate and initial values TRISVAL_B equ 0x01 FB equ 0x20 ; first free byte #define b_por PCON,NOT_POR #define b_oscf PCON,OSCF #define b_rp0 STATUS,RP0 #define b_rp1 STATUS,RP1 #define b_irp STATUS,IRP #define b_rbpu OPTION_REG,NOT_RBPU #define b_intedg OPTION_REG,INTEDG #define b_int0if INTCON,INTF #define b_int0ie INTCON,INTE #define b_gie INTCON,GIE #define b_c1out CMCON,C1OUT #endif ;################################# ; CONSTANTS ;################################# WAIT_100 equ 65 ; delay 100ms = 65*1540 GRAV_LOOPS equ 10 ; spins before sleeping START_LOOPS equ 100 ; initial loops before sleeping SYNC_LOOK_CNT equ 3 ; # times to look for sync none found VOLT_MIN equ 4 ; start at this range VOLT_CNT equ 4 ; check this many ranges ;################################# ; VARIABLES ;################################# ; ; bit variables ; #define b_check_sync v_bits0,0 #define b_got_intr v_bits0,1 #define b_check_v v_bits0,2 #define b_test_vcmp v_bits0,3 ; ; byte variables ; v_bits0 equ FB+0 ; bits v_current_msg equ FB+1 ; message currently being v_cnt1 equ FB+2 ; wait counter ls digit v_cnt2 equ FB+3 ; wait counter ms digit v_volt equ FB+5 v_volt_cnt equ FB+6 v_loops equ FB+7 ; spins before we sleep v_cptr equ FB+8 ; column pointer v_curval equ FB+9 ; value of current column (input) v_redval equ FB+10 ; value of current column (output) v_sync_cnt equ FB+11 ; times to check sync ;################################# ; BEGIN CODE ;################################# ;################################# ; VECTORS ;################################# ; ; reset vector ; org 0 goto init ; ; interrupt vector ; org 4 bsf b_got_intr ; indicate interrupt occurred bcf b_int0if retfie ;################################# ; red/green function jump tables ;################################# red: clrf PCLATH movf v_volt,w addwf PCL,f goto red14 goto red14 goto red12 goto red12 goto red1 ; ; w contains duration (w * 960usec) ; green: movwf v_cnt2 clrf PCLATH movf v_volt,w addwf PCL,f ; jump to green func based on voltage goto green50 goto green50 goto green35 goto green35 goto green1 ;################################# ; autogenerated subroutines ;################################# include <swords.inc> ;################################# ; off mode - turn off after last msg ;################################# turn_off: clrf v_current_msg decf v_current_msg,f off_loop: clrf INTCON ; interrupts off sleep ;################################# ; init routine ;################################# init: clrf STATUS clrf INTCON ; interrupts off #if USE_16F630 clrf PORTA clrf PORTC ; ; BANK 1 ; bsf b_rp0 movlw TRISVAL_A movwf TRISA movlw TRISVAL_C movwf TRISC bcf b_rapu ; turn on pullup for PORTA ;bsf b_wpua2 ; turn on pullup for A2 (on by default) bcf b_intedg ; interrupt on falling edge movf OSCCAL,w call 0x3ff ; get osc calibration value in w movwf OSCCAL ; calibrate the oscillator bcf b_rp0 ; ; BANK 0 ; #endif #if USE_16F628 clrf PORTA clrf PORTB ; ; BANK 1 ; bsf b_rp0 movlw TRISVAL_A movwf TRISA movlw TRISVAL_B movwf TRISB bcf b_rbpu ; turn on pullup for PORTB bcf b_intedg ; interrupt on falling edge bcf b_rp0 ; ; BANK 0 ; #endif clrf v_bits0 ; clear bit variables clrf v_sync_cnt ; do not check for sync (until sync is seen) bcf b_int0if ; clear sync bsf b_check_v ; check voltage next dot #if TEST_VCOMPARE btfss b_gravity bsf b_test_vcmp ; test voltage compare if gravity switch ; pressed during reset #endif ;################################# ; Debounce wait ;################################# ; ; wait a bit for MCLR switch debouncing ; (if bouncing, reset will occur here again) ; debounce: call wait_100 ;################################# ; NEXT MESSAGE ;################################# next_message: ; ; increment to next message ; incf v_current_msg,f movf v_current_msg,w addlw LOW -PHRASE_CNT btfsc STATUS,C goto turn_off ; ; initial loop count value ; movlw START_LOOPS movwf v_loops ; ; display current message ; movf v_current_msg,w ; ; go to phrase jump table in swords.inc ; goto jump ;################################# ; WAIT_500 - wait for 500 ms (1/2 sec) ;################################# wait_500: call wait_100 call wait_200 ; fall thru to wait_200 ;################################# ; WAIT_200 - wait for 100 ms (1/10 sec) ;################################# wait_200: call wait_100 ; fall thru to wait_100 ;################################# ; WAIT_100 - wait for 100 ms (1/10 sec) ;################################# wait_100: movlw WAIT_100 ; fall thru to wait ;################################# ; WAIT - wait for a short time ;################################# ; ; wait loop. Wait for: ; W * 772 cycles = W * 772 usec ; ; if b_check_sync is 1 then exit when b_int0if is set ; ; w contains time to wait: ; if b_check_sync == 0 ; cycles = usec = w * 1540 ; ; if b_check_sync == 1 ; cycles = usec = w * 1796 ; wait: movwf v_cnt2 #if !SIM wait_loop2: clrf v_cnt1 wait_loop1: btfss b_check_sync ; check sync? goto wait_cont btfsc b_int0if ; exit if sync occurred return wait_cont: decfsz v_cnt1,f goto wait_loop1 decfsz v_cnt2,f goto wait_loop2 #endif return ;################################# ; go to sleep ;################################# ; ; setup to wake up if interrupt occurs ; if b_int0if is set then sleep will not occur ; do_sleep: bcf b_got_intr ; this gets set if interrupt occurs bsf b_int0ie ; enable gravity interrupt bsf b_gie ; enable interrupts btfss b_got_intr sleep ; ; wakeup by interrupt goes here ; clrf INTCON ; disable interrupts return ; continue displaying message ;################################# ; DRAW GREEN DOT & OPTIONALLY CHECK VOLTAGE ;################################# dot: #if DO_VCHECK ; ; turn on both green LEDs ; bsf b_led_green0 bsf b_led_green1 ; ; need to check voltage? ; btfss b_check_v goto dot_wait ; ; next time do not check voltage ; bcf b_check_v ; ; check voltage ; #if USE_16F630 movlw 0x04 ; set up voltage compare movwf CMCON #endif #if USE_16F628 movlw 0x02 ; set up voltage compare movwf CMCON #endif movlw VOLT_CNT movwf v_volt_cnt ; check this many levels movlw VOLT_MIN movwf v_volt ; starting with this level #if TEST_VCOMPARE btfss b_test_vcmp goto tvc_skip1 movlw 16 ; try all 16 levels movwf v_volt_cnt clrf v_volt ; starting with 0 movlw 0x80 ; enable voltage reference iorwf v_volt,w bsf b_rp0 movwf VRCON bcf b_rp0 ; allow user to measure voltage with meter call wait_500 call wait_500 call wait_500 call wait_500 call wait_500 call wait_500 call wait_500 call wait_500 tvc_skip1: #endif vtst_loop1: movlw 0x80 ; enable voltage reference iorwf v_volt,w ; check this voltage bsf b_rp0 movwf VRCON bcf b_rp0 movlw 2 call wait ; wait for it to settle btfsc b_c1out ; exit loop if Vref > Vled goto vtst_done incf v_volt,f decfsz v_volt_cnt,f goto vtst_loop1 vtst_done: bsf b_rp0 clrf VRCON ; turn off voltage reference bcf b_rp0 #if TEST_VCOMPARE btfss b_test_vcmp goto tvc_skip2 bcf b_led_green0 ; green off bcf b_led_green1 #if USE_16F630 movf v_volt,w ; indicate voltage reading on red LEDs #endif #if USE_16F628 rlf v_volt,w ; indicate voltage reading on red LEDs #endif movwf RED_LEDS call wait_500 ; display for 1sec call wait_500 clrf RED_LEDS ; red off ; ; clamp to min=VOLT_MIN ; movf v_volt,w addlw LOW -VOLT_MIN movlw VOLT_MIN btfss STATUS,C movwf v_volt ; ; clamp to max=VOLT_MIN+VOLT_CNT-1 ; movf v_volt,w addlw LOW -(VOLT_MIN+VOLT_CNT) movlw VOLT_MIN+VOLT_CNT btfsc STATUS,C movwf v_volt tvc_skip2: #endif movlw LOW -VOLT_MIN addwf v_volt,f ; range from 0 to VOLT_CNT-1 #else ; DO_VCHECK clrf v_volt #endif ; DO_VCHECK dot_wait: movlw 208 ; 208 * 960usec = 200ms call green ; about 200ms of green per dot call wait_100 ; about 300ms blank between dots goto wait_200 ;################################# ; DRAW CHARACTER (incl gap) ;################################# ; ; pointer to start of char in W ; putc: movwf v_cptr putc_loop: call jump ; get dot values movwf v_curval ; save to check if last column movwf v_redval ; save to specify which LEDs to light call red incf v_cptr,f movf v_cptr,w btfss v_curval,END_BIT goto putc_loop goto gap ;################################# ; DRAW SPACE BETWEEN WORDS ;################################# lspace: call gap call gap ; fall thru to gap function ;################################# ; DRAW GAP BETWEEN CHARACTERS ;################################# gap: clrf v_redval ; all LED off call red ; draw with no leds set goto red ; and again (2 columns per gap) ;################################# ; DRAW SPIN MODE COLUMN OF RED LEDs ;################################# ; ; v_redval should hold red LED values ; ; time = 933 usec ; ; ; 25% duty cycle ; #define RED14_TIME 154 red14: movlw RED14_TIME movwf v_cnt1 movf v_redval,w red14_loop: movwf RED_LEDS nop clrf RED_LEDS #if !SIM decfsz v_cnt1,f goto red14_loop #endif goto red_end ; ; 50% duty cycle ; #define RED12_TIME 116 red12: movlw RED12_TIME movwf v_cnt1 movf v_redval,w red12_loop: movwf RED_LEDS nop nop nop clrf RED_LEDS #if !SIM decfsz v_cnt1,f goto red12_loop #endif goto red_end ; ; 100% duty cycle (always on) ; #define RED1_TIME 186 red1: movlw RED1_TIME movwf v_cnt1 red1_loop: movf v_redval,w movwf RED_LEDS #if !SIM decfsz v_cnt1,f goto red1_loop #endif red_end: clrf RED_LEDS movlw 0x00 ; zero w for next character return ;################################# ; DRAW LAST RED COLUMN IN CHARACTER ;################################# ; ; w should hold red LED values ; red_last: call red ; last column in character goto gap ; gap following character ;################################# ; DRAW GREEN LINE ;################################# ; ; time = v_cnt2 * 935usec ; ; ; 3/5 duty cycle ; #define GREEN35_TIME 116 green35: green35_loop2 movlw GREEN35_TIME movwf v_cnt1 green35_loop1: bsf b_led_green0 bsf b_led_green1 nop bcf b_led_green0 bcf b_led_green1 #if !SIM decfsz v_cnt1,f goto green35_loop1 decfsz v_cnt2,f goto green35_loop2 #endif return ; ; 50% duty cycle ; #define GREEN12_TIME 93 green12: green12_loop2 movlw GREEN12_TIME movwf v_cnt1 green12_loop1: bsf b_led_green0 bsf b_led_green1 nop nop nop bcf b_led_green0 bcf b_led_green1 #if !SIM decfsz v_cnt1,f goto green12_loop1 decfsz v_cnt2,f goto green12_loop2 #endif return ; ; 100% duty cycle (always on) ; #define GREEN1_TIME 187 green1: green1_loop2 movlw GREEN1_TIME movwf v_cnt1 green1_loop1: bsf b_led_green0 bsf b_led_green1 #if !SIM decfsz v_cnt1,f goto green12_loop1 decfsz v_cnt2,f goto green12_loop2 #endif bcf b_led_green0 bcf b_led_green1 return ;################################# ; START LOOP ;################################# ; ; Call this at start of phrase. ; ; - draw green line ; - check for timeout (sleep) ; start_loop: ;################################# ; Check for sync (gravity switch) ;################################# check_switch: #if NO_SLEEP_IF_HELD ; ; check for switch being held in - never sleep while that is ; true ; movlw GRAV_LOOPS btfss b_gravity ; gravity switch held in? movwf v_loops ; yes - do not sleep for a while #endif ; ; whenever we see a sync, check for sync the next N loops ; (N = SYNC_LOOK_CNT) ; ; ; check for switch toggling - if it toggles then look for sync ; movlw SYNC_LOOK_CNT btfsc b_int0if ; got sync? movwf v_sync_cnt ; check sync next N times ; ; looking for sync? ; movf v_sync_cnt,f btfsc STATUS,Z goto sync_skip ; skip looking for sync - we dont see it decf v_sync_cnt,f ; if no sync for a while then skip it movlw GRAV_LOOPS ; do not sleep while looking for sync movwf v_loops ; ; wait until we get a sync pulse ; sync_wait: bcf b_int0if ; clear sync #if CHECK_SYNC bsf b_check_sync call wait_500 ; wait 1/2 sec or until sync occurs bcf b_check_sync ; ; NOTE: we do not clear sync (b_int0if) - next loop it will ; be seen and will cause v_sync_cnt to be set again. ; So as long as we keep getting sync, we will keep looking ; for sync ; #endif ; CHECK_SYNC sync_skip: ;################################# ; Draw green line ;################################# movlw 50 ; 50 * 920usec = 46msec call green ;################################# ; Check for timeout ;################################# dec_time: decf v_loops,f btfsc STATUS,Z call do_sleep start_loop_done: movlw 0x00 ; zero W for character functions return org 0x3ff return ;################################# ; END ;################################# END |
This file Copyright (C) 2004 by Nathan (Acorn) Pooley
Go to Bat Blinker Development page
Go to Bat Blinker page
Go to JU Gadgets page
Go to Justice Unlimited homepage
Go to Acorn's personal webpage
Contact Acorn
See comments from others
Post your own comments
File created by do_doc at Wed Aug 4 20:16:01 2004