
;
;
;Check routine to use software loops and see if a high pulse on P2.0 is
;between two width limits.
;
;This code presumes that the input signal does not need de-bouncing
;or filtering. The nature of the edge detection will actually filter
;out a bouncing time that is shorter than 1 millisecond
;
;setup the legal limits of the pulse high time.
;
PULSE_HI_MIN    EQU     35          ;minimum valid high time
PULSE_HI_MAX    EQU     45          ;maximum valid high time
PULSE_TIMEOUT   EQU     2000        ;pulse wait timeout value (2 seconds)
;
;
      CSEG AT 0000H
RESET_VEC:
        JMP     INITIAL
;
      BSEG AT 020H
PREV_BIT:
        DBIT    1                   ;previous state of bit
WORK_BIT:
        DBIT    1                   ;work bit 

      DSEG AT 040H
WIDTH_CNT:
        DS      2                   ;16-bit width counter variable
STACK:
        DS      1                   ;starting place for the stack
;
;
      CSEG AT 0100H
INITIAL:
        MOV     SP,#STACK           ;put the stack out of the way
        SETB    P2.0                ;make sure p2.0 is an input
        MOV     A,#1
        CALL    DELAY_MS
        MOV     C,P2.0              ;initialize the previous bit
        MOV     PREV_BIT,C
        MOV     A,#0                ;clear the width counter
        MOV     WIDTH_COUNT+0,A
        M0V     WIDTH_COUNT+1,A
;
;
;wait here for pulse to go from low to high. If we have waited
;more than the timeout periof then something is wrong do branch to handle 
;the timeout.
;
WAIT_FIRST:                  
        MOV     A,#1
        CALL    DELAY_MS            ;wait another millisecond
        MOV     A,WIDTH_COUNT+1     ;increment the width counter
        ADD     A,#1
        MOV     WIDTH_COUNT+1,A
        MOV     A,WIDTH_COUNT+0
        ADC     A,#0
        MOV     WIDTH_COUNT+0,A     ;save the incremented width
;
        MOV     A,WIDTH_COUNT+0     ;check if timeout has come
        CJNE    A,#HIGH(PULSE_TIMEOUT),WF_1
        MOV     A,WIDTH_COUNT+1
        CJNE    A,#LOW(PULSE_TIMEOUT),WF_1
WF_1:
        JNC     TMO_FIRST           ;go deal with the timeout
;
        MOV     C,P2.0              ;check for change of input bit
        MOV     WORK_BIT,C          ;save a copy of the port bit
        ANL     C,/PREV_BIT         ;curr & /prev = change from o to 1
        JC      GOT_FIRST           ;got the leading edge of pulse
        MOV     C,WORK_BIT          ;save current value as now previous value
        MOV     PREV_BIT,C
        JMP     WAIT_FIRST          ;loop to wait more
;
;get here when the first edge has happened @ P2.0. Setup to measure the
;high period of the pulse and then wait for it to go back off. will deal
;with a timeout if it occurs
;
GOT_FIRST:
        MOV     A,#0                ;clear the width counter
        MOV     WIDTH_COUNT+0,A
        M0V     WIDTH_COUNT+1,A
WAIT_END:
        MOV     A,#1
        CALL    DELAY_MS            ;wait another millisecond
        MOV     A,WIDTH_COUNT+1     ;increment the width counter
        ADD     A,#1
        MOV     WIDTH_COUNT+1,A
        MOV     A,WIDTH_COUNT+0
        ADC     A,#0
        MOV     WIDTH_COUNT+0,A     ;save the incremented width
;
        MOV     A,WIDTH_COUNT+0     ;check if timeout has come
        CJNE    A,#HIGH(PULSE_TIMEOUT),WE_1
        MOV     A,WIDTH_COUNT+1
        CJNE    A,#LOW(PULSE_TIMEOUT),WE_1
WE_1:
        JNC     TMO_PULSE           ;go deal with timeout
;
        MOV     C,P2.0              ;check for change of input bit
        MOV     WORK_BIT,C          ;save a copy of the port bit
        MOV     C,PREV_BIT
        ANL     C,/WORK_BIT         ;/curr & prev = change from 1 to 0
        JC      END_FIRST           ;got the first pulse trailing edge
        MOV     C,WORK_BIT          ;save current value as now previous value
        MOV     PREV_BIT,C
        JMP     WAIT_END            ;loop to wait more
;
;get here when the pulse has ended and we check its width within legal limits
;                                                          
END_FIRST:
        MOV     A,WIDTH_COUNT+0     ;check if above the minimum width
        CJNE    A,#HIGH(PULSE_HI_MIN),EF_1
        MOV     A,WIDTH_COUNT+1
        CJNE    A,#LOW(PULSE_HI_MIN),EF_1
EF_1:
        JC      ILLEGAL_PULSE       ;go to show pulse was illegal
;       
        MOV     A,WIDTH_COUNT+0     ;check if over the maximum width
        CJNE    A,#HIGH(PULSE_HI_MAX),EF_2
        MOV     A,WIDTH_COUNT+1
        CJNE    A,#LOW(PULSE_HI_MAX),EF_2
EF_2:
        JNC     ILLEGAL_PULSE       ;go to show pulse was illegal       
;
;
;got here when the pulse is seen as a good width
;
GOOD_FIRST:
        NOP                         ;junk code here now
        JMP     GOOD_FIRST          ;replace
;
;
;get here when there was a timeout waiting for first rising edge
;
TMO_FIRST:
        ;code here to deal with legal high time of pulse.
        NOP                         ;junk code here now
        JMP     TMO_FIRST           ;replace
;
;
;get here when there was a timeout waiting for the pulse to complete
;
TMO_PULSE:
        ;code here to deal with timeout condition
        NOP                         ;junk code here now
        JMP     TMO_PULSE           ;replace
;
;
;get here when the width of the pulse was too short or too long
;
BAD_PULSE:
        ;code here to deal with situation
        NOP                         ;junk code here now
        JMP     BAD_PULSE           ;replace
;
;
;subroutine to delay count od A milliseconds (this was designed with 
;a standard type 80C51 in mind that has /12 clocking and is equipped 
;with an 11.0592 mHz crystal.
;
;entry A is the number of milliseconds to wait.
;
DELAY_MS:
        PUSH    ACC
        MOV     A,#228
DELAY_LP:
        NOP
        NOP
        DJNZ    ACC,DELAY_LP        ;wait out the millisecond
        POP     ACC
        DJNZ    ACC,DELAY_MS        ;need to do another millisecond?
        RET
;
;
        END
