2718l1.txt ;************************************************************************************************* ; LISTING 1 - ASSEMBLY CODE FOR THE COP8 ; ; "Sonarlike method detects fluid level," EDN, July 19, 2001, pg 94 ;************************************************************************************************* ; An application to measure fluid level ; Hardware Design by Bob Leboeuf ; Written by Eric Masse for National Semiconductor ; Date 02-18-01 ; .incld cop8sac.inc ; .sect Register,REG count1:.dsb 1 count2:.dsb 1 count3:.dsb 1 innerloop:.dsb 1 ; For delay outerloop:.dsb 1 check:.dsb 1 ; check loops timelo:.dsb 1 ; movement value timehi:.dsb 1 digit_1:.dsb 1 digit_2:.dsb 1 digit_3:.dsb 1 .endsect ; .sect digit,RAM digitmem: .dsb 11 zero = digitmem one = digitmem+1 two = digitmem+2 three = digitmem+3 four = digitmem+4 five = digitmem+5 six = digitmem+6 seven = digitmem+7 eight = digitmem+8 nine = digitmem+10 decimal = digitmem+11 .endsect ; ; The main program. Call subroutines from this point .sect main, rom main: jsr init_send_pulses jsr init_listen jsr scale jsr send_digits ld innerloop,#0xFF ; A long delay between measurements ld outerloop,#0x64 jsr delay jp main ; Next measurement .endsect ; This routine will use the COP8's PWM to send a pulse train .sect tmr, rom init_send_pulses: ld PORTGC,#0xFB ; portg 3 as output others input ld PSW,#0x00 ; Initialize PSW ld ICNTRL,#0x00 ; initialize ICNTRL rbit 3,PORTGD ; initialize T1A sbit 2,PORTGD ; use weak pull-up resistor - This is for the listen ld TMR1LO,#0x0B ; initialize lower byte of timer ld TMR1HI,#0x00 ; initialize upper byte of timer ld T1RALO,#0x0B ; Set the lower "high" time ld T1RAHI,#0x00 ; Set the upper "high" time ld T1RBLO,#0x0B ; Set the lower "high" time ld T1RBHI,#0x00 ; Set the upper "high" time ld CNTRL,#0xA0 ; Set up PWM to toggle SBIT 4,CNTRL ; Start Timer T1 ; ld innerloop,#0x02 ; This should send out pulses during the delay ld outerloop,#0x03 ; jsr delay rbit 4,CNTRL ; Stop timer T1 rbit 3,PORTGD ; Reset the pulse to low ret ; ; This subroutine listens for the echo, echo, echo... init_listen: ; For debugging purposes ld PORTLC,#0xFF ; make portl all outputs ld PORTLD,#0x00 ; start them all low ; end of debugging setup rbit 2,PORTGC ; portg 2 as input rbit 3,PORTGC ; portg 3 as input rbit 3,PORTGD ; initialize T1A ld CNTRL,#0xA0 ; Set up PWM to so we can reset the counter rbit 4,CNTRL ; Reset the counter ld TMR1LO,#0xFF ; initialize lower byte of timer ld TMR1HI,#0xFF ; initialize upper byte of timer ld T1RALO,#0xFF ; Set the lower "high" time ld T1RAHI,#0xFF ; Set the upper "high" time ld T1RBLO,#0xE7 ; Set the lower "max" time ld T1RBHI,#0x03 ; Set the upper "max" time ld PSW,#0x11 ; Set up PSW to T1A interupt pending and enabled ld ICNTRL,#0x01 ; Set up ICNTRL to T1B interrupt pending and enabled ld innerloop,#0x14 ; Make sure we are out of the cross talk region 2.5mS ld outerloop,#0x11 ; jsr delay ; delay before we start measuring sbit 3,PORTLD ; Debug - port L3 should go high ld check,#0x01 ; Put some number into the accumulator ld CNTRL,#B'11100000 ; Set-up as input capture mode AND START TIMER rbit 3,PORTLD ; See where the timer starts ; listen: ifbit 0,check ; If this has changed to zero then we caught the pulse jp listen ret .endsect ; ; Subroutine for sending number through uWire. .sect uwire, rom send_digits: ld PORTGC,#0xBE ; Setup G0, G4 and G5 as outputs sbit 0,PORTGD ; Set OE high ld CNTRL,#B'00001000 ; Enable microWire ld count2,#0x03 ; send the three digits rotate_num: ld A,count2 ifne A,#0x03 ; if not the third digit jp _2nd_digit ; jump to second digit ld A,digit_1 jsr seg_asgn ; assign the binary data ld A,count3 jp send _2nd_digit: ifne A,#0x02 ; if not the second digit jp _3rd_digit ; jump to third digit ld A,digit_2 jsr seg_asgn ; assign the binary data ld A,count3 jp send _3rd_digit: ; ifne A,#0x01 ; if not the first digit ; jp send ; jump to send digit ld A,digit_3 jsr seg_asgn ; assign the binary data ld A,count3 send: ld A,count3 ; Load the Binary equiv. for 7 seg. ld B,#PSW x A,SIOR ; Put value in SIOR reg. sbit BUSY,[B] rotate: ifbit BUSY,[B] jp rotate sbit 1,PORTGD ; Send a strobe bit nop rbit 1,PORTGD drsz count2 jp rotate_num ret ; The binary data for the 7-segments LED's seg_asgn: ifeq A,#0x00 ld count3,#B'00111111 ifeq A,#0x01 ld count3,#B'00000110 ifeq A,#0x02 ld count3,#B'01011011 ifeq A,#0x03 ld count3,#B'01001111 ifeq A,#0x04 ld count3,#B'01100110 ifeq A,#0x05 ld count3,#B'01101101 ifeq A,#0x06 ld count3,#B'01111101 ifeq A,#0x07 ld count3,#B'00000111 ifeq A,#0x08 ld count3,#B'01111111 ifeq A,#0x09 ld count3,#B'01101111 ret ; ; Subroutine for changing binary number to decimal equivalent and putting it ; the digit_x registers. scale: ld digit_1,#0x00 ld digit_2,#0x00 ld digit_3,#0x00 sc ; Make sure the carry bit is set to 1 ld A,#0xFF ; Put the high byte in accu. subc A,timehi ; because it counted down not up X A,timehi ; timehi should have the new number ld A,#0xFF ; Put the byte in accu. subc A,timelo X A,timelo ld count3,#02 ; Prescalar - Divide by 4 again: ld A,timehi ; Read upper byte rbit 6,PSW ; Reset the carry bit rrc A ; divide by 2 X A,timehi ; Save value in TIMHI ld A,timelo rrc A ; divide by 2 X A,timelo ; Save value in TIMLO drsz count3 jp again lowerbyte: ifeq timelo,#0x00 ; if the lower byte = 0 jp test_hi inc_digit_1: ifeq digit_1,#0x09 ; Is the first digit = 9 jp inc_digit_2 ; Go to inc. next digit. ld A,digit_1 inc A X A,digit_1 ; Digit_1 has new number drsz timelo ; decrement timelo jp lowerbyte ; don't care if zero or not. jp lowerbyte inc_digit_2: ifeq digit_2,#0x09 ; Is the second digit = 9 jp inc_digit_3 ; Go to inc. next digit. ld digit_1,#0x00 ; bring digit_1 to 0 ld A,digit_2 inc A X A,digit_2 ; Digit_2 has new number drsz timelo ; decrement timelo jp lowerbyte ; don't care if zero or not. jp lowerbyte ; don't care if zero or not. inc_digit_3: ifeq digit_3,#0x09 ; Is the third digit = 9 jp check_2 ; If so check the others ld digit_1,#0x00 ; bring digit_1 to 0 ld digit_2,#0x00 ; bring digit_2 to 0 ld A,digit_3 inc A X A,digit_3 ; does digit_1 have new number drsz timelo ; decrement timelo jp lowerbyte ; don't care if zero or not. jp lowerbyte check_2: ifeq digit_2,#0x09 jp check_1 jp inc_digit_2 check_1: ifeq digit_1,#0x09 ret jp inc_digit_1 test_hi: ifeq timehi,#0x00 ; if the upperbyte = 0 ret ; if both are = 0 we are done ld A,timehi ; put timehi in A dec A X A,timehi ; put the decremented value back in timehi ld timelo,#0xff ; start again jp lowerbyte ; Subroutine for delay between measurements .sect delay,rom ; Delay Loop of approx. ?ms delay: ld A,outerloop X A,count2 ; load inner loop OUTER_LOOP: ld A,innerloop X A,count3 INNER_LOOP: DRSZ count3 JP INNER_LOOP DRSZ count2 JP OUTER_LOOP RET .endsect ;******Interrupt handler******* .sect intr,rom,abs=0xFF .=00FF Save: PUSH A LD A,B PUSH A LD A,X PUSH A VIS Restore: POP A X A,X POP A X A,B POP A RETI Timer1A_Service: ; The timer must have timed out ld CNTRL,#0xA0 ; Set up PWM to stop timer. rbit 4,CNTRL ; Stop the timer ld check,#0x00 ; get out of the loop (listen) RBIT T1PNDA,PSW ; Reset T1PNDA pending flag ld ICNTRL,#0x00 ld A,#0x09 X A,digit_1 ; Put a nine in the first digit ld A,#0x09 X A,digit_2 ; Put a nine in the second digit ld A,#0x09 X A,digit_3 ; Put a nine in the third digit jsr send_digits ; send the digits ld check,#0x00 ; get out of the loop (listen) jp Restore ; Timer1B_Service: ld CNTRL,#0xA0 ; Set up PWM to stop timer. rbit 4,CNTRL ; Stop the timer sbit 3,PORTLD ; Debug - port L3 should go high rbit 3,PORTLD ; Debug - port L3 should go low ld A,T1RBLO ; Read lower byte X A,timelo ; Save value in TIMLO ld A,T1RBHI ; Read upper byte X A,timehi ; Save value in TIMHI ld ICNTRL,#0x00 ld check,#0x00 ; get out of the loop (listen) JP Restore ; ; PortL_Wakeup_Service: jp Restore ; IDLE_Tmr_Service: JP Restore ; Inactive_Isr: JP Restore .endsect ;****************************** .sect Interrupt_Table,ROM,ABS=0x01E0 .addrw Inactive_Isr .addrw PortL_Wakeup_Service .addrw Inactive_Isr .addrw Inactive_Isr .addrw Inactive_Isr .addrw Inactive_Isr .addrw Inactive_Isr .addrw Inactive_Isr .addrw Inactive_Isr .addrw Inactive_Isr .addrw Timer1B_Service .addrw Timer1A_Service .addrw IDLE_Tmr_Service .addrw Inactive_Isr .addrw Inactive_Isr .addrw Inactive_Isr .endsect .END main