	org 	8000h
        jmp     810Ah
	
	$MOD51GB


;        org     803bh
;        jmp     A2D_ISR

        org     8100h
        db      21h,2dh,3bh,48h,56h,62h

        org     810Ah
main:   mov     P1,#0FFh        ;initialize port 1
        mov     R0,#015h        ;turn sonar to 90 right
        mov     CCAP0h,R0      ;load PWM register with PW value
        call    PCA_INIT        ;initialize the PWM

        mov     ACON,#010h      ;enable A2D operation
;        mov     IEA,#080h      ;enable the A2D interrupt
;        setB    EA             ;enable all interrupts
        call    lngDelay
        call    lngDelay
        call    lngDelay
        call    lngDelay

        mov     DPTR,#8100h
        mov     R1, #06h

son_cyc:
        call    son_out
        movx    A,@DPTR
        mov     CCAP0h,A

        call    snd_ASCII_A
        
        call    PRINT
        db      '**\n',0,
        inc     DPTR

        call    print
        db      '\n     Press the g key for next reading\n',0,

start:  call    cin
        cjne    A,#'g',start

        djnz    R1, son_cyc

        call    son_out

        call    print
        db      '\n     Press the g key for next reading\n',0,

start2:  call    cin
        cjne    A,#'g',start2


        jmp     main


son_out:
        call    lngDelay
        mov     A,AD0
        call    snd_ASCII_A
        call    PRINT
        db      '\n',0,

        ret


wait:   jmp     wait


;A2D_ISR:
;        push    ACC
;        push    00h
;        push    PSW

;        mov     A,#020h
;        xrl     ACON,A          ;clear A2D interrupt flag
;        mov     A,AD0           ;load A with contents of AD0

;        mov     R0,#04h

;sr4:    clr     C               ;load a zero into carry
;        rrc     A               ;roll A right
;        djnz    R0,sr4          ;repeat 4 times

;        call    UTIL_BINTOASC   ;convert most sig nibble to ascii
;        call    SEND_BYTE       ;send it to the monitor
;        mov     A,AD0           ;get the value in AD0

;        call    UTIL_BINTOASC
;        call    SEND_BYTE
;        call    print
;        db      '\n',0,
;        pop     PSW
;        pop     00h
;        pop     ACC 

;        reti

PCA_INIT:
        mov     CMOD,#006h      ;PCA frequency external input
                                ;40kHz
        mov     CCAPM0,#042h    ;Put PCA mod 0 into PWM mode
        mov     CCAP0H,R0       ;Initialize the duty cycle
        setb    CR              ;Start the PCA clock
        ret

delay10: mov    R3,#025h
delay:  mov     R4,#0FFh
delay1: djnz    R4, delay1              ;wait >10 msec
        djnz    R3, delay
	ret

lngDelay: mov   R3,#00Ah
delay2: mov     R4,#035h
delay3: mov     R5,#0FFh
delay4: djnz    R5, delay4              ;wait >500msec
        djnz    R4, delay3
        djnz    R3, delay2
	ret

cin:    JNB     RI,$             ; WAIT FOR THE RI FLAG TO SET
        CLR     RI               ; CLEAR THE RECEIVE FLAG ONCE RECIEVED
        MOV     A,SBUF           ; PLACE RECEIVED BYTE IN REGISTER A
        RET



cout:   JNB     TI,$            ;Wait until transmission completed.
        CLR     TI              ;Clear interrupt flag.
	MOV     SBUF,A          ;Write out character.
        RET


snd_ASCII_A:
        mov     R0,#04h
sr4:    clr     C               ;load a zero into carry
        rrc     A               ;roll A right
        djnz    R0,sr4          ;repeat 4 times

        call    UTIL_BINTOASC   ;convert most sig nibble to ascii
        call    cout            ;send it to the monitor
        mov     A,CCAP0h
        call    UTIL_BINTOASC
        call    cout
        ret

PRINT:  PUSH    ACC      ; push the A and DPTR registers so their contents  
        PUSH    DPH      ; don't get lost in case they are being used
        PUSH    DPL      ; before calling this function. 

; move the stack pointer down low in order to pop the first string's byte
; address
        MOV     A,SP     
        ADD     A,#0FDH
        MOV     SP,A
        POP     DPH
        POP     DPL

; send (PRINT) the string back to the PC computer
READ_TX:
        CLR     A
        MOVC    A,@A+DPTR
        INC     DPTR             

        CJNE    A,#'\',SND

        CLR     A
        MOVC    A,@A+DPTR
        INC     DPTR             

        CJNE    A,#'n',SND

        MOV     A,#0DH
        ACALL   cout
        MOV     A,#0AH

SND:    ACALL   cout
        CJNE    A,#0,READ_TX

; place the new return addres in stack
        PUSH    DPL
        PUSH    DPH

; move the stack pointer up high in order to pop the A and DPTR registers 
        MOV     A,SP
        ADD     A,#3
        MOV     SP,A
        POP     DPL
        POP     DPH
        POP     ACC
        RET


UTIL_BINTOASC:
        anl     a,#00fh                 ; Keep Only Low Bits
        add     a,#090h                 ; Add 144
        da      a                       ; Decimal Adjust
        addc    a,#040h                 ; Add 64
        da      a                       ; Decimal Adjust
        ret                             ; Return To Caller
              

	;print 16 bit unsigned integer in DPTR, using base 10.
pint16u:	;warning, destroys r2, r3, r4, r5, psw.5
	push	acc
	mov	a, r0
	push	acc
	clr	psw.5
	mov	r2, dpl
	mov	r3, dph

pint16a:mov	r4, #16	;ten-thousands digit
	mov	r5, #39
	acall	pint16x
	jz	pint16b
	add	a, #'0'
	lcall	cout
	setb	psw.5

pint16b:mov	r4, #232	;thousands digit
	mov	r5, #3
	acall	pint16x
	jnz	pint16c
	jnb	psw.5, pint16d
pint16c:add	a, #'0'
	lcall	cout
	setb	psw.5

pint16d:mov	r4, #100	;hundreds digit
	mov	r5, #0
	acall	pint16x
	jnz	pint16e
	jnb	psw.5, pint16f
pint16e:add	a, #'0'
	lcall	cout
	setb	psw.5

pint16f:mov	a, r2		;tens digit
	mov	r3, b
	mov	b, #10
	div	ab
	jnz	pint16g
	jnb	psw.5, pint16h
pint16g:add	a, #'0'
	lcall	cout

pint16h:mov	a, b		;and finally the ones digit
	mov	b, r3
	add	a, #'0'
	lcall	cout

	pop	acc
	mov	r0, a
	pop	acc
	ret

;ok, it's a cpu hog and a nasty way to divide, but this code
;requires only 21 bytes!  Divides r2-r3 by r4-r5 and leaves
;quotient in r2-r3 and returns remainder in acc.  If Intel
;had made a proper divide, then this would be much easier.

pint16x:mov	r0, #0
pint16y:inc	r0
	clr	c
	mov	a, r2
	subb	a, r4
	mov	r2, a
	mov	a, r3
	subb	a, r5
	mov	r3, a
	jnc	pint16y
	dec	r0
	mov	a, r2
	add	a, r4
	mov	r2, a
	mov	a, r3
	addc	a, r5
	mov	r3, a
	mov	a, r0
	ret

        end
