DRUID Development Docs: gmain.inc

Gadget Sourcecode: gmain.inc

; Justice Unlimited Gadget Microcode
; (C) 2004 Nathan (Acorn) Pooley 
;
; gmain.inc
;
;@DOC@ main loop and sleep/wake/on/off code
;

;############################################
;############### WAKE UP ####################
;############################################

    ; wake up and stay in same mode we were in before sleep
wake_up:
    ENABLE_SPINNER
    
    bsf     b_rbif              ; force PORTB interrupt
    bsf     b_rbie              ; enable PORTB interrupt
    bra     main_start          ; continue into main

;############################################
;############### BUTTON WAIT ################
;############################################

    ;
    ; wait until button has been unpressed for a while (debounce)
    ;
turn_onoff_but_wait:
    movlw   TURN_ON_WAIT_TIME
    movwf   v_tmp2
turn_onoff_but_loop:
    call    time
    movlw   TURN_ON_WAIT_TIME
    btfss   PORTB,7
    movwf   v_tmp2              ; reset tmp2 if button is held in
    decfsz  v_tmp2,f            ; loop until tmp2 empties
    bra     turn_onoff_but_loop

    return


;############################################
;############### INIT_OFF ###################
;############################################

    ;
    ; turn off spinner, checking for movement
    ;   INPUT CONDITIONS:
    ;      b_turn_off = 0: sleep
    ;                   1: turn off immediately
    ;
    ;
turn_off:
    DISABLE_IR
    ENABLE_SPINNER

    nop                     ; wait for spinner to turn on
    nop


    movf    PORTB,w         ; get PORTB current val
    bcf     b_rbie          ; disable portb interrupt

    ;
    ; save PORTB value
    ;
    movwf   v_off_bval

    DISABLE_SPINNER

    ;
    ; sleep or turn off?
    ;
    btfsc   b_turn_off
    bra     turn_off_now

    btfsc   b_showing_time
    bra     wake_up

    ;
    ; abort sleep if timer2 is on - a button must have been pressed
    ;
    btfsc   b_tmr2on
    bra     wake_up

    ;
    ; abort sleep if we got a spinner change just before disabling
    ; interrupts
    ;
    btfsc   b_got_input
    bra     wake_up

    ;
    ; abort sleep if buttons pressed
    ;
    btfss   v_off_bval,7
    bra     wake_up

    ;
    ; fall thru to sleep
    ;

;############################################
;############### SLEEP ######################
;############################################

    ;
    ; THIS SHOULD ONLY BE CALLED FROM turn_off (above)
    ;

    ;
    ; "SLEEP" looks just like "ON", but spinner is disabled
    ;
    ;   at this point:
    ;     spinner is turned off
    ;     v_off_bval = last PORTB value
    ;
fall_asleep:
    ;
    ; Set sleep-off timer (time until we turn off)
    ;
    movlw   SLEEP_OFF_TIME          ; turn off after this long
    btfss   disab_light
    movlw   SLEEP_OFF_TIME_LIGHT    ; faster if light is on

    call    set_sleep_time

sleep_main_loop:
    movlw   SLEEP_NOSPIN_TIME   ; keep spinner off this long
    movwf   v_tmp2

    call    time            ; call time every 1/10 sec (only needed
                            ; about once per sec)

sleep_loop1:
    movf    PORTB,w
    xorwf   v_off_bval,w
    andlw   0x9f            ; ignore spinner
    bnz     wake_up         ; wake up if button was pressed
    decfsz  v_tmp2,f        ; loop until time to check spinner
    bra     sleep_loop1     ; loop until PORTB changes

    ;
    ; time to check spinner
    ;
    ENABLE_SPINNER
    nop                 ; allow time for spinner to turn on
    nop
    movf    PORTB,w     ; get spinner value
    DISABLE_SPINNER

    xorwf   v_off_bval,w
    andlw   0x60            ; only look at spinner bits
    bnz     wake_up

    ;
    ; is it time to turn off completely?
    ;
    btfss   b_sleep
    bra     sleep_main_loop ; keep sleeping

    ;
    ; fall thru to turn_off
    ;

;############################################
;############### TURN OFF ###################
;############################################

    ;
    ; THIS SHOULD ONLY BE CALLED FROM turn_off (above)
    ;
    ;
    ; "OFF" means display is off
    ;    click = reset to welcome screen
    ;    spin  = wake up to where we were
    ;
    ;   at this point:
    ;     spinner is turned off
    ;     v_off_bval = last PORTB value
    ;
turn_off_now:
    ;
    ; turn stuff off
    ;
    bcf     b_light
    rcall   output_disable

    ;
    ; wait until button is unpressed (and debounced)
    ; (but only if turnoff was caused by button click)
    ;
    btfsc   b_turn_off
    rcall   turn_onoff_but_wait

    bsf     v_off_bval,7    ; turn off button bit (1=unpressed)

off_main_loop:
    bcf     b_turn_off


#if QUICK_TURNON
    ;
    ; set v_tmp2 as counter until time to check spinner
    ;
    movlw   OFF_NOSPIN_QTIME    ; keep spinner off this long
    movwf   v_tmp2

#else ; QUICK_TURNON
    ;
    ; Set sleep-off timer (used to check spinner)
    ;
    movlw   OFF_NOSPIN_TIME ; keep spinner off this long
    rcall   set_sleep_time
#endif ; QUICK_TURNON

off_loop1:
    call    time            ; call time repeatedly
    btfss   PORTB,7         ; button pressed?
    bra     turn_on_click   ;   yes - turn on!

#if SIMULATE_INPUT
    movf    PORTB,w
    xorwf   v_off_bval,w
    andlw   0x88
    bnz     turn_on_click
    movf    PORTB,w
    xorwf   v_off_bval,w
    andlw   0x66
    bnz     turn_on_spin
#endif


#if QUICK_TURNON

    decfsz  v_tmp2,f        ; loop until time to check spinner
    bra     off_loop1

#else ; QUICK_TURNON

    btfss   b_sleep         ; time to check spinner?
    bra     off_loop1       ;   no  - keep waiting

#endif ; QUICK_TURNON


    ;
    ; time to check spinner
    ;
    ENABLE_SPINNER
    nop                 ; allow time for spinner to turn on
    nop
    movf    PORTB,w     ; get spinner value
    DISABLE_SPINNER

    xorwf   v_off_bval,w
    andlw   0x60            ; only look at spinner bits
    bz      off_main_loop   ; same - stay off

    btfsc   PORTB,7             ; any buttons pressed?
    bra     turn_on_spin        ; turned on by spinner

    ;
    ; when spinner moved fall thru to turn_on_click
    ;   

;############################################
;############### TURN ON ####################
;############################################

turn_on_click:
    rcall   init_mode           ; reset to welcome screen

    ;
    ; wait until button is unpressed (and debounced)
    ;
    rcall   turn_onoff_but_wait

turn_on_spin:
#if REPORT_ERRORS
    incf    v_cnt_turnon,f
#endif

    ;
    ; enable output
    ;
    clrf    v_en_cnt
    rcall   output_enable

    ;
    ; setup the current mode
    ;
    ; (NOTE: This calls input enable)
    ;
    rcall   load_mode

    ;
    ; fall through to main loop
    ;

;############################################
;############### MAIN LOOP ##################
;############################################

main_start:
    ;
    ; reset auto-off timer & turn-off bit
    ;
    bcf     b_turn_off
    call    reset_sleep_time    ; set time until sleep

main:

#if SIMULATE_NOTIMEOUT
    call    reset_sleep_time    ; never fall asleep
#endif

    rcall   main_func
    btfss   b_sleep
    bra     main

    bra     turn_off

;############################################
;############### MAIN FUNCTION ##############
;############################################

    ;
    ; called repeatedly from the main loop
    ;

main_func:
#if SIMULATE_INPUT
sim_input:
    movf        PORTB,w
    xorwf       v_si_oldb,w
    andlw       0x0e
    btfsc       STATUS,Z
    bra         sim_input_end

    xorwf       v_si_oldb,f
    movwf       v_tmp

    call        reset_sleep_time

    btfss       v_tmp,3
    bra         sim_input_1

    ;
    ; RB0 = button press
    ;
    movf    v_func_btn0_click,w ; button clicked?
    goto    main_jump

sim_input_1:
    btfss       v_tmp,1
    bra         sim_input_2

    ;
    ; RB1 = dec
    ;
    bsf         b_spinchange
    decfsz      v_spinval,f
    bra         sim_input_2

    incf        v_spinval,f
    btfsc       b_spinwrap
    movff       v_spinmax,v_spinval

sim_input_2:
    btfss       v_tmp,2
    bra         sim_input_3

    ;
    ; RB2 = inc
    ;
    bsf         b_spinchange
    incf        v_spinval,f
    decf        v_spinval,w
    subwf       v_spinmax,w
    bnz         sim_input_3

    decf        v_spinval,w
    btfsc       b_spinwrap
    movlw       0x01
    movwf       v_spinval

sim_input_3:
sim_input_end:
#endif
#if TEST_INPUT
    btfss   v_bheld,7
    bra     ti_2

    nop     ; HELD
    bcf     v_bheld,7
    return


ti_2:
    btfss   b_got_input
    bra     ti_3

    nop     ; INPUT
    bra     input
    return

ti_3:
    btfss   b_spinchange
    bra     ti_4

    nop     ; SPINCHANGE
    bcf     b_spinchange
    return

ti_4:
    return

ti_button_released:
    nop     ; BUTTON RELEASED
    return

#endif

    movf    v_func_event1,w     ; any events occurred?
    bnz     main_bit_check
    movf    v_func_event2,w
    bnz     main_bit_check
    movf    v_func_event3,w
    bnz     main_bit_check

    movf    v_func_default,w    ; default function

    movf    v_time_addsec,f     ; need to update time?
    btfss   STATUS,Z
    movlw   func_time

main_bit_check:
    btfsc   b_spinchange
    movf    v_func_spinchange,w ; spinner changed?

    btfsc   b_got_input         ; inbuf not empty?
    movlw   func_input

                                ; TODO: to support mulit-button decode v_bheld
    btfsc   v_bheld,7           ; button0 was held in?
    bra     light_toggle_held   ; hold in to toggle light

    goto    main_jump


This file Copyright (C) 2004 by Nathan (Acorn) Pooley
Go to DRUID Development page
Go to DRUID 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 17:53:58 2004