
$XREF
$PL(78) PW(119)
$DEBUG
$SYMBOLS
$NOMOD51

#define CYGNAL_DEBUG  1             // set non-zero for enable of code mode for
                                    // cygnal debug platform.

#if CYGNAL_DEBUG
$include(c8051f200.inc)             ; register definitions compatible
                                    ; with Cygnal C8051F200
#else
$include(REG51FX.INC)               ; register definitions compatible 
                                    ; with standard Intel architecture FX cpu
#endif

;***************************************************
; SETUP THE NAMES OF THE SEGMENTS
;---------------------------------------------------

BITS_SEG    SEGMENT     BIT
DATA_SEG    SEGMENT     DATA
BUFF_SEG    SEGMENT     IDATA
CODE_SEG    SEGMENT     CODE

;***************************************************
; DATA ALLOCATIONS AND BUFFER SPACES
;---------------------------------------------------
;
;
; Variables and buffers
;
        RSEG    BITS_SEG        
TEST_BIT:
        DBIT    1                   ; sample bit declaration
;
        RSEG    DATA_SEG
PREV_LO:
        DS      1                   ; previously sampled port 2
PREV_HI:
        DS      1                   ; previously sampled port 3
COUNTERS:
        DS      32                  ; array of counter values - a total
                                    ; of 16 counters of 16-bits each stored
                                    ; in low / high byte order 
;
;
; stack support
;
        RSEG    BUFF_SEG
STACK:
        DS      10                  ; reserve 10 bytes of space

;***************************************************
; INTERRUPT VECTOR DEFINITIONS
;---------------------------------------------------

CSEG    AT      0000H               ; reset vector
        JMP     POWER_UP            ; power-on entry point

CSEG    AT      0003H               ; intr 0 vector
        CLR     EX0                 ; external int 0
        RETI                        ; not used

CSEG    AT      000BH               ; timer 0 vector
        RETI                        ; not used

CSEG    AT      0013H               ; intr 1 vector
        CLR     EX1                 ; external int 1
        RETI                        ; not used

CSEG    AT      001BH               ; timer 1 vector
        RETI                        ; not used

CSEG    AT      0023H               ; UART vector
        RETI                        ; not used

;***************************************************
; BASE OF CODE AREA
;---------------------------------------------------

        RSEG    CODE_SEG    

        USING   0                   ; use register block 0

;***************************************************
; MAIN PROGRAM INITIALIZATION
;---------------------------------------------------

POWER_UP:
        MOV     SP, #STACK          ; set stack pointer

#if CYGNAL_DEBUG
        ; disable watch dog timer
        MOV     WDTCN, #0DEh        ; Disable the WDT. 
        MOV     WDTCN, #0ADh        ; 2nd move to WDTCN must be within 
                                    ; 4 clocks of first so watch IRQs
        ; Configure the PRTnMX Registers
        MOV     PRT0MX, #005h       ; PRT0MX: Initial Reset Value
                                    ; bit 2="1" enables /INT0 pin
                                    ; bit 0="1" enables TxD and RxD pins
        MOV     PRT1MX, #000h       ; PRT1MX: Initial Reset Value
        MOV     PRT2MX, #000h       ; PRT2MX: Initial Reset Value

        ; Select Pin I/0
        ; Port configuration (1 = Push Pull Output)
        MOV     PRT0CF, #001h       ; Output configuration for P0
                                    ; bit 0="1" enables TxD pin as push pull output
        MOV     PRT1CF, #000h       ; Output configuration for P1 
        MOV     PRT2CF, #000h       ; Output configuration for P2 
        MOV     PRT3CF, #000h       ; Output configuration for P3 

        MOV     P0MODE, #0FFh       ; Input Configuration for P0
        MOV     P1MODE, #0FFh       ; Input Configuration for P1
        MOV     P2MODE, #0FFh       ; Input Configuration for P2
        MOV     P3MODE, #0FFh       ; Input Configuration for P3

        ; enable the external oscillator
        MOV     OSCXCN, #067h       ; External Oscillator Control Register  
        CLR     A
        DJNZ    ACC, $              ; wait for
        DJNZ    ACC, $              ; at least 1ms

OX_WAIT:
        MOV     A, OSCXCN
        JNB     ACC.7, OX_WAIT      ; poll XTLVLD
;
        MOV     A, OSCICN           ; Internal Oscillator Control Register
        SETB    ACC.3               ; set for external clock to be used
        MOV     OSCICN, A

        CLR     A
        MOV     CKCON, A            ; ensure timers T0, T1 & T2 run with /12 clocks

#endif
;
;
; main loop to poll 16 inputs from a port (P3::P2) and increment counters for
; inputs that have a change in the input state. The counters are stored as an
; array of 16-bit low/high counters at the COUNTERS local RAM buffer.
;
; The main loop uses the B register to hold the edge detect and carry bits
; during the computational algorithm.
;
        MOV     A, P2               ; initialize the initial NOT prev_lo
        CPL     A
        MOV     PREV_LO, A      
        MOV     A, P3               ; initialize the initial NOT prev_hi
        CPL     A
        MOV     PREV_HI, A      
MAIN_LOOP:                          ; main processing task
        ; setup pointer to the counters
        MOV     R0, #COUNTERS

        ; edge detect logic for port 2 bits
        MOV     B, P2               ; get the port value
        MOV     A, PREV_LO
        ANL     A, B                ; edge bits
        XCH     A, B                ; save edge bits to B and get port_val to A
        CPL     A                   ; save NOT port bits to prev_lo
        MOV     PREV_LO, A
;
        ; increment low counters with pulse detects
        MOV     R1, #8              ; counter for low counters loop
BUMP_0_7:
        MOV     A, B
        RRC     A                   ; get increment bit for a counter
        MOV     B, A
        CLR     A
        ADDC    A, @R0              ; bump low byte of counter
        MOV     @R0, A
        INC     R0
        CLR     A
        ADDC    A, @R0              ; bump high byte of counter
        MOV     @R0, A
        INC     R0
        DJNZ    R1, BUMP_0_7
;
        ; edge detect logic for port 3 bits
        MOV     B, P3               ; get the port value
        MOV     A, PREV_LO
        ANL     A, B                ; edge bits
        XCH     A, B                ; save edge bits to B and get port_val to A
        CPL     A                   ; save NOT port bits to prev_lo
        MOV     PREV_LO, A
;
        ; increment high counters with pulse detects
        MOV     R1, #8              ; counter for high counters loop
BUMP_8_15:
        MOV     A, B
        RRC     A                   ; get increment bit for a counter
        MOV     B, A
        CLR     A
        ADDC    A, @R0              ; bump low byte of counter
        MOV     @R0, A
        INC     R0
        CLR     A
        ADDC    A, @R0              ; bump high byte of counter
        MOV     @R0, A
        INC     R0
        DJNZ    R1, BUMP_8_15
;
        SJMP    MAIN_LOOP

;***************************************************
;NAME: GET_CNT
;   Used to extract a count value from the counter
;   byte array.
;   Entry A is the 0-15 counter number
;   Exit B::A is the counter 16-bit value
;---------------------------------------------------

GET_CNT:
        ANL     A, #0FH             ; make nibble index to array of counter data
        RL      A                   ; *2 because the counters are 2 bytes each
        ADD     A, #COUNTERS+1
        MOV     R0, A               ; R0 is index to requested counters high byte
        MOV     A, @R0              ; get the low byte of the counter
        MOV     B, A
        DEC     R0                  ; bump pointer to high byte
        MOV     A, @R0
        RET                 
;
        END
