; 2010.04.05 18:49 Public release ; 1996.05.19 19:35 Original ; Copyright 1996, 2010 Nicholas O. Lindan, rights reserved ; Released under terms of gnu general public software license GPLv3 ; For use with Paralax PIC assembler. This assembler uses a ; more 'user friendly' 8051-like syntax rather than the standard ; microchip pic assembly lanuage. DEVICE PIC16C54,XT_OSC,WDT_OFF,PROTECT_OFF RESET BEGIN ; Port definitions KEYSENSE_INPUT = RA.2 RELAY_OUTPUT = RA.3 LSD_LED_ENABLE = RA.0 MSD_LED_ENABLE = RA.1 SEGMENTS = RB KEY_STATE_IDLE = 0 KEY_STATE_HIT = 1 KEY_STATE_DEBOUNCE = 2 KEY_STATE_DWELL = 3 KEY_STATE_HELD = 4 KEY_DEBOUNCE_TIME = 25 KEY_DWELL_TIME = 100 KEY_RAMP_TIME = 25 UNPAUSE_TIME = 130 KEY_UP = 0100B KEY_DOWN = 1000B KEY_EXPOSE = 0001B KEY_FOCUS = 0010B MACHINE_STATE_IDLE = 0 MACHINE_STATE_RAMPING = 1 MACHINE_STATE_FOCUSING = 2 MACHINE_STATE_EXPOSING = 3 MACHINE_STATE_EXPOSE_PAUSED = 4 MACHINE_STATE_UNPAUSING = 5 ; RAM definitions ORG 8 ; Count values COUNT_LSD DS 1 COUNT_MSD DS 1 COUNT_LSD_SAVE DS 1 COUNT_MSD_SAVE DS 1 SCALE DS 1 PRESCALE_LSD DS 1 PRESCALE_MSD DS 1 BITS DS 1 SCRATCH DS 1 KEY_STATE DS 1 KEY_COUNTER DS 1 KEY DS 1 MACHINE_STATE DS 1 RAMP_COUNTER DS 1 UNPAUSING_TIMER DS 1 TICKS DS 1 MUX_TOGGLE = BITS.0 FLASH = BITS.1 FLASH_10S_LED = BITS.2 ;************************************************************* ;* ;* SEVEN_SEG_ENCODE ;* ;************************************************************* ORG 0 SEVEN_SEG_ENCODE JB MUX_TOGGLE, SEVEN_SEG_ENCODE_LSD ADD PC, W ; BAFGDECP GFEDCBA RETW 00010001B ; 1000000B ; 0 RETW 01111101B ; 1111001B RETW 00100011B ; 0100100B RETW 00100101B ; 0110000B RETW 01001101B ; 0011001B RETW 10000101B ; 0010010B RETW 10000001B ; 0000010B RETW 00111101B ; 1111000B RETW 00000001B ; 0000000B RETW 00001101B ; 0011000B ; 9 SEVEN_SEG_ENCODE_LSD ADD PC, W ; FAPBGCDE GFEDCBA RETW 00101000B ; 1000000B ; 0 RETW 11101011B ; 1111001B RETW 10100100B ; 0100100B RETW 10100001B ; 0110000B RETW 01100011B ; 0011001B RETW 00110001B ; 0010010B RETW 00110000B ; 0000010B RETW 10101011B ; 1111000B RETW 00100000B ; 0000000B RETW 00100011B ; 0011000B ; 9 ;************************************************************* ;* ;* DP_ENCODE ;* ;************************************************************* DP_ENCODE JB MUX_TOGGLE, DP_ENCODE_LSD ADD PC, W RETW 11111110B ; MSD, 1/10ths RETW 11111111B ; MSD, 1s RETW 11111111B ; MSD, 10s RETW 11111110B ; MSD, error DP_ENCODE_LSD ADD PC, W RETW 11111111B ; LSD, 1/10ths RETW 11111111B ; LSD, 1s SB FLASH_10S_LED RETW 11011111B ; LSD, error & 10s w/ no flashing SB TICKS.7 RETW 11011111B ; LSD, 10s RETW 11111111B ;************************************************************* ;* ;* IS_KEY_HIT ;* ;************************************************************* IS_KEY_HIT XOR W, KEY SZ RET MOV W, #KEY_STATE_HIT XOR W, KEY_STATE RET ;************************************************************* ;* ;* SET_PRESCALE_LSD ;* ;************************************************************* SET_PRESCALE_LSD CJE SCALE, #0, PRESCALE_10THS MOV PRESCALE_LSD, #250 RET PRESCALE_10THS MOV PRESCALE_LSD, #25 RET ;************************************************************* ;* ;* SET_PRESCALE_MSD ;* ;************************************************************* SET_PRESCALE_MSD CJE SCALE, #2, PRESCALE_10S MOV PRESCALE_MSD, #1 RET PRESCALE_10S MOV PRESCALE_MSD, #10 RET ;************************************************************* ;* ;* BEGIN ;* ;************************************************************* BEGIN ; Port A: RA.2 is the key sense input, all else are outputs MOV !5, #00000100b MOV RA, #0FFh ; Port B is all outputs MOV !6, #000h MOV RB, #0FFh ; Not using the WDT or RTC, Prescale is 1:8 MOV OPTION, #2 ; Initialize at 10. seconds MOV W, #000h MOV COUNT_LSD, W MOV KEY_STATE, W MOV MACHINE_STATE, W MOV BITS, W MOV W, #001h MOV COUNT_MSD, W MOV SCALE, W LOOP JMP WAIT_FOR_TICK WAIT_FOR_TICK_RET INC TICKS JMP DEBOUNCE DEBOUNCE_RET JMP MUX_DISPLAY MUX_DISPLAY_RET JMP ADJUST ADJUST_RET JMP FOCUS FOCUS_RET EXPOSE ; The jump table is here as all jump tables must be in the lower ; 256 bytes of a page MOV W, MACHINE_STATE ADD PC, W JMP EXPOSE_CHECK_HIT ; MACHINE_STATE_IDLE JMP EXPOSE_RET ; MACHINE_STATE_RAMPING JMP EXPOSE_RET ; MACHINE_STATE_FOCUSING JMP EXPOSE_EXPOSING ; MACHINE_STATE_EXPOSING JMP EXPOSE_PAUSED ; MACHINE_STATE_EXPOSE_PAUSED JMP EXPOSE_UNPAUSING ; MACHINE_STATE_UNPAUSING EXPOSE_RET JMP LOOP ;************************************************************* ;* ;* WAIT_FOR_TICK ;* ;************************************************************* WAIT_FOR_TICK MOV SCRATCH, #4 WFT_LOOP CJNE RTCC, #0, WFT_LOOP MOV RTCC, #131 DJNZ SCRATCH, WFT_LOOP JMP WAIT_FOR_TICK_RET ;************************************************************* ;* ;* DEBOUNCE ;* ;************************************************************* DEBOUNCE OR RA, #0011B ; Turn off both digits MOV SEGMENTS, KEY MOV W, KEY_STATE ADD PC, W JMP STATE_IDLE JMP STATE_HIT JMP STATE_DEBOUNCE JMP STATE_DWELL JMP STATE_HELD STATE_IDLE CLRB C ; Keyboard idle MOV KEY, #1 STATE_IDLE_LOOP MOV SEGMENTS, KEY MOV W, KEY MOV 6, W NOP JB KEYSENSE_INPUT, TO_STATE_HIT RL KEY JNB KEY.4, STATE_IDLE_LOOP JMP DEBOUNCE_RET TO_STATE_HIT MOV KEY_STATE, #KEY_STATE_HIT ; Hit detected JMP DEBOUNCE_RET STATE_HIT MOV KEY_STATE, #KEY_STATE_DEBOUNCE ; Transition from hit state MOV KEY_COUNTER, #KEY_DEBOUNCE_TIME ; Preset delay interval STATE_DEBOUNCE ; Waiting period, 100 msec. debounce DJNZ KEY_COUNTER, DEBOUNCE_RET MOV KEY_COUNTER, #KEY_DWELL_TIME ; Preset to 500 msec. MOV KEY_STATE, #KEY_STATE_DWELL JMP DEBOUNCE_RET STATE_DWELL ; Waiting 500 msec for held JNB KEYSENSE_INPUT, TO_STATE_IDLE DJNZ KEY_COUNTER, DEBOUNCE_RET MOV KEY_STATE, #KEY_STATE_HELD JMP DEBOUNCE_RET STATE_HELD JB KEYSENSE_INPUT, DEBOUNCE_RET TO_STATE_IDLE MOV KEY_STATE, #KEY_STATE_IDLE JMP DEBOUNCE_RET ;************************************************************* ;* ;* MUX_DISPLAY ;* ;************************************************************* MUX_DISPLAY JNB FLASH, NO_FLASHING JNB TICKS.6, NO_FLASHING MOV SEGMENTS, #0FFH JMP MUX_DISPLAY_RET NO_FLASHING MOV FSR, #COUNT_LSD SB MUX_TOGGLE ; Move the nibble into place INC FSR MOV W, INDIRECT ; Convert to seven seg. data CALL SEVEN_SEG_ENCODE MOV SEGMENTS, W MOV W, SCALE CALL DP_ENCODE AND SEGMENTS, W MOV W, #1110B ; Set the digit strobe SB MUX_TOGGLE MOV W, #1101B AND RA, W XOR BITS, #1B ; Complement MUX_TOGGLE JMP MUX_DISPLAY_RET ;************************************************************* ;* ;* ADJUST ;* ;************************************************************* ADJUST CJNE MACHINE_STATE, #MACHINE_STATE_IDLE, ADJUST_RET MOV W, KEY_STATE ADD PC, W JMP ADJUST_RET ; KEY_STATE_IDLE JMP UP_DOWN ; KEY_STATE_HIT JMP ADJUST_RET ; KEY_STATE_DEBOUNCE JMP ADJUST_RET ; KEY_STATE_DWELL DJNZ RAMP_COUNTER, ADJUST_RET ; KEY_STATE_HELD UP_DOWN MOV RAMP_COUNTER, #KEY_RAMP_TIME MOV W, #1100B AND W, KEY JZ ADJUST_RET JB KEY.3, DECREMENT INCREMENT CJE COUNT_LSD, #9, I_0 INC COUNT_LSD JMP ADJUST_RET I_0 CJE COUNT_MSD, #9, I_1 INC COUNT_MSD MOV COUNT_LSD, #0 JMP ADJUST_RET I_1 CJE SCALE, #2, ADJUST_RET INC SCALE MOV COUNT_MSD, #1 MOV COUNT_LSD, #0 JMP ADJUST_RET DECREMENT CJE COUNT_LSD, #0, D_0 DEC COUNT_LSD JMP ADJUST_RET D_0 CJE COUNT_MSD, #0, ADJUST_RET MOV COUNT_LSD, #9 CJE COUNT_MSD, #1, D_1 DEC COUNT_MSD JMP ADJUST_RET D_1 CJE SCALE, #0, D_2 MOV COUNT_MSD, #9 DEC SCALE JMP ADJUST_RET D_2 MOV COUNT_MSD, #0 JMP ADJUST_RET ;************************************************************* ;* ;* FOCUS ;* ;************************************************************* FOCUS CJAE MACHINE_STATE, #MACHINE_STATE_EXPOSING, FOCUS_RET MOV W, #KEY_FOCUS CALL IS_KEY_HIT JNZ FOCUS_RET XOR RA, #1000B JMP FOCUS_RET ;************************************************************* ;* ;* EXPOSE PROCEDURES ;* ;************************************************************* EXPOSE_CHECK_HIT MOV W, #KEY_EXPOSE CALL IS_KEY_HIT JNZ EXPOSE_RET ; Expose has been hit, check that there is an exposure ; value that has been set MOV W, COUNT_LSD OR W, COUNT_MSD JZ EXPOSE_RET ; Start exposing SETB FLASH_10S_LED MOV MACHINE_STATE, #MACHINE_STATE_EXPOSING CLRB RELAY_OUTPUT CALL SET_PRESCALE_LSD CALL SET_PRESCALE_MSD MOV COUNT_LSD_SAVE, COUNT_LSD MOV COUNT_MSD_SAVE, COUNT_MSD JMP EXPOSE_RET EXPOSE_EXPOSING ; If expose key has been hit again, then go to the paused state MOV W, #KEY_EXPOSE CALL IS_KEY_HIT JNZ EE_0 SETB RELAY_OUTPUT SETB FLASH CLRB FLASH_10S_LED MOV MACHINE_STATE, #MACHINE_STATE_EXPOSE_PAUSED JMP EXPOSE_RET ; Check if the exposure is complete EE_0 CJNE COUNT_LSD, #0, EE_1 CJE COUNT_MSD, #0, END_EXPOSURE ; Count down the exposure EE_1 DJNZ PRESCALE_LSD, EXPOSE_RET CALL SET_PRESCALE_LSD DJNZ PRESCALE_MSD, EXPOSE_RET CALL SET_PRESCALE_MSD DEC COUNT_LSD JNB COUNT_LSD.7, EXPOSE_RET DEC COUNT_MSD MOV COUNT_LSD, #9 JMP EXPOSE_RET EXPOSE_PAUSED MOV W, #KEY_EXPOSE CALL IS_KEY_HIT JNZ EXPOSE_RET MOV UNPAUSING_TIMER, #UNPAUSE_TIME MOV MACHINE_STATE, #MACHINE_STATE_UNPAUSING JMP EXPOSE_RET EXPOSE_UNPAUSING ; The lamp is off, and we have gotten a hit expose key in the paused ; mode. If the unpause timer expires we turn the lamp on and go ; back to exposing. If we get a held expose key then we cancel the ; exposure DJNZ UNPAUSING_TIMER, CHECK_EXPOSE_HELD JMP UNPAUSE CHECK_EXPOSE_HELD CJNE KEY, #KEY_EXPOSE, EXPOSE_RET CJNE KEY_STATE, #KEY_STATE_HELD, EXPOSE_RET END_EXPOSURE MOV MACHINE_STATE, #MACHINE_STATE_IDLE SETB RELAY_OUTPUT MOV COUNT_LSD, COUNT_LSD_SAVE MOV COUNT_MSD, COUNT_MSD_SAVE CLRB FLASH_10S_LED CLRB FLASH JMP EXPOSE_RET UNPAUSE CLRB RELAY_OUTPUT SETB FLASH_10S_LED CLRB FLASH MOV MACHINE_STATE, #MACHINE_STATE_EXPOSING JMP EXPOSE_RET