; BIN_ASC 16-bit value ; This routine converts a 16-bit number into a counted string of ; ASCII characters compatible with Serout. It suppresses ; leading zeros so that numbers like 17 are sent as "17" not "00017". buffer = 31 ; String buffer at end of memory. ASC_0 = '0' ; ASCII numbers: 30h thru 39h. ASC_dp = '.' ; ASCII char for decimal point (period). fix = 3 ; Position for fixed decimal point. org 8 dec_no Res 1 ; Decade (1,10,100...) to work on. tempH Res 1 ; 16-bit temporary variable used by tempL Res 1 ; the BIN_ASC routine. hiB Res 1 ; MSB of number to convert. lowB Res 1 ; LSB of number to convert. flags ds 1 zs = flags.0 ; Leading-zero suppression flag. P = pic16c55 ; device pic16c55,xt_osc,wdt_off,protect_off reset start org 0 ; Table consisting of values 10,000, 1000, 100, 10, and 1. decade add 02, W retw #39 retw #16 retw #3 retw #232 retw #0 retw #100 retw #0 retw #10 retw #0 retw #1 start mov W, #$FF ; To see routines output, either mov hiB, W mov W, #$FF ; use the PSIM PIC simulator, or mov lowB, W call BIN_ASC ; merge with Serout. jmp $ ; Endless loop ; This routine accepts a 16-bit number in hiB, lowB and converts it into ; a counted ASCII text string located at the address "buffer." The buffer ; grows downward in memory. The first (0th) item in buffer is the number ; of characters in the string. The routine destroys the contents of ; hiB, lowB. If this value is required elsewhere, make a copy. BIN_ASC clr buffer ; Clear char count (item 0 in buf). clr flags ; Clear zs flag. clr dec_no ; Clear decade no. mov W, #buffer-1 ; Reserve 0th byte of buffer for count. mov fsr, W BIN_ASC_loop test dec_no call decade ; from the lookup table. mov tempH, W inc dec_no ; Get 2nd digit of decade no. test dec_no call decade mov tempL, W call d_point ; Insert decimal point. call sub_it ; Divide hiB,lowB by tempH,tempL test indirect snb flags.0 ; If zs = 0 AND digit = 0 then jmp BIN_ASC_no_zs snb 3.2 ; digit is a leading zero to be jmp BIN_ASC_no_zed BIN_ASC_no_zs mov indirect, W ADD indirect,#ASC_0 ; an included zero (as in 7501) inc buffer ; or a non-zero digit. dec fsr ; Point to next memory location. setb flags.0 ; First non-zero digit sets zs bit. BIN_ASC_no_zed inc dec_no ; Next decade. mov W, #8 ; If dec_no = 8, we're down to ones. sub dec_no, W sb 3.2 jmp BIN_ASC ; Otherwise, do next decade. inc dec_no ; Update decade number for d_point. call d_point ; Decimal point here? test lowB mov indirect, W ADD indirect,#ASC_0 ; Add offset for conversion to ASCII. inc buffer ; Add 1 to character count. retw #0h ; This routine performs division by iterated subtraction. It is efficient ; in this application because the dividend and divisor keep getting smaller ; as BIN_ASC runs, so the quotient is never larger than nine. A general- ; purpose division routine would be slower (and longer). sub_it clr indirect ; Clear to track no. of subtractions. sub_it_loop test tempL ; Subtract LSB. sub lowB, W snb 3.0 ; If no borrow, continue w/MSB. jmp sub_it_skip mov W, #1 ; Otherwise borrow from MSB. sub hiB, W snb 3.0 ; If borrow causes a carry, then jmp sub_it_skip inc hiB ; add numbers back and return. test tempL add lowB, W retw #0h sub_it_skip test tempH ; Subtract MSB. sub hiB, W snb 3.0 ; If no borrow, subtract again. jmp sub_it_skip2 ADD lowB,tempL ; Otherwise, undo the subtraction snb 3.0 ; by adding entire 16-bit no. inc hiB ; back together and return. ADD hiB,tempH retw #0 sub_it_skip2 inc indirect ; No borrow, so do it again. jmp sub_it_loop ; This routine adds a decimal point in the location set by "fix" in the ; equates at the beginning of the program. The location of the decimal point ; is in front of the "fix"ed digit, numbered starting with 0. If you fix the ; point at 0, the first (0th) character in the string produced by BIN_ASC ; will be a decimal point. If you don't want a decimal point, either move ; it out of range (fix = 6), or delete this routine and the "call d_point" ; in the body of BIN_ASC above. d_point mov W, #fix*2+1 sub dec_no, W sb 3.2 retw #0h setb flags.0 mov W, #ASC_dp mov indirect, W inc buffer dec fsr retw #0h