; This program activates the most commonly used interrupts
; of the MCS-51 controller.  These are:
;       serial interrupt
;       timer 0 interrupt
;       timer 1 interrupt
;       external interrupt 0
;       external interrupt 1

; This program services the above interrupts.

; the serial routine sends a byte out and receives it back.
;**********************************************************
;*      the user must jumper P3.0 and P3.1 together       *
;**********************************************************
; the stack is used in the serial interrupt to a depth of 5.

$debug
$mod51

ea_byte..equ.09fh.; all -51 interrupts enabled
tmod_val        equ     11h     ; timer0 in 16-bit mode
                                ; timer1 in 16-bit mode
t0_val          equ     00h     ; timer0 reload, LSB
t1_val          equ     80h     ; timer1 reload, LSB
t_val           equ     0ffh    ; timer MSB

end_it..equ.0ffh.; inc a up till this value
delay..equ.0ffh.; base for delay time
                                ; w/12 MHz clock, routine works
                                ; at delay=14h, not 0ah
scon_val.equ.098h.; 9 bit uart, ninth bit = 1
....; rcv enabled
pcon_val.equ.000h.; $80, 1/32*(clock), 19.2 kbaud
....; $00, 1/64*(clock), 9600 baud
stk_ptr         equ     31h     ; stack begins immediately
                                ; after 2 data bytes at 30h,31h
low_val         equ     01h     ; low byte of timer 0 reload
hi_val          equ     58h     ; hi byte of timer 0 reload

.dseg
        org     30h             ; scratchpad RAM
wait:..ds.1
rcv_data:.ds.1
;
.cseg
.org.0h
initz:.jmp.start

.org.3h
int_0:.jnb.p3.2,$..; wait till int0 goes high
        inc     r0              ; use r0 to count # of int0's
.reti

.org.0bh
t0_int:.clr     tr0              ; stop timer0
        jmp     t0_work

.org.13h
int_1:.jnb.p3.3,$..; wait till int1 goes high
        inc     r1              ; use r1 to count # of int0's
.reti

        org     1bh
t1_int: clr     tr1             ; stop timer1
        jmp     t1_work

        org     23h
s_int:  ljmp    ser_int

        org     60h
start:.mov     sp,#stk_ptr     ; set the stack pointer
        mov     scon,#scon_val
        mov     pcon,#pcon_val
        mov.ie,#ea_byte

.mov.tmod,#tmod_val
        mov     tl0,#t0_val
        mov     th0,#t_val
        mov     tl1,#t1_val
        mov     th1,#t_val

        mov     r0,#00h
        mov     r1,#00h

        setb    p3.0            ; alternate func. is RXD
        setb    p3.1            ; alternate func. is TXD

        mov     dpl,#00h
        clr     ti
        clr     ri

        setb    it0             ; int0 is edge sensitive
        setb    it1             ; int1 is edge sensitive

        setb    tr0             ; start timer0
        setb    tr1             ; start timer1

xmit:.mov.sbuf,dpl.; dpl inits to 0
set_wait:
        mov.wait,#delay     ; dead time: adjust this 
                                ; to tighten noose
;
loop2:.nop
.djnz.wait,loop2
        jmp     xmit
;
ser_int:
        push    acc
        push    dpl
        push    dph
        push    wait
        push    rcv_data
;
        mov     a,dpl                   ; manipulate data by acc
.mov.rcv_data,sbuf..; read the rcv'd byte
.cjne.a,rcv_data,bombout.; if different, bomb
.clr.ri...; clear the rcv interrupt
        clr     ti                      ; clear xmt interrupt too
.inc.a...; then inc a

; exit condition is commented out for this version
;.cjne.a,end_it,popm..; and compare to $ff
.....; go to top if not done
;.jmp.the_end...; go to the end if done

popm:   pop     rcv_data
        pop     wait
        pop     dph
        pop     dpl
        mov     dpl,a                   ; xmit byte will inc'd
        pop     acc

        reti

bombout:.jmp.$..; screwed up

the_end:.jmp.$..; ok

t0_work:        mov     tl0,#t0_val
                mov     th0,#t_val
                setb    tr0             ; start timer0 again
                reti

t1_work:        mov     tl1,#t1_val
                mov     th1,#t_val
                setb    tr1             ; start timer1 again
                reti
.end

