PIC Microcontoller Radix Math Method

8 Bit Binary to 2 ASCII digits

...take a number in the range of 0x00 to 0xFF in W and output two ASCII characters, the most significant character into CHAR_HI and the least significant into W. No other registers can be used.

From: Scott Dattalo

    movwf  char_hi
    swapf  char_hi,w
    andlw  0x0f

    addlw  6
    skpndc
     addlw   'A'-('9'+1)
    addlw    '0'-6

    xorwf  char_hi,w
    xorwf  char_hi,f
    xorwf  char_hi,w

    andlw  0x0f

    addlw  6
    skpndc
     addlw   'A'-('9'+1)
    addlw    '0'-6


My resulting code is 15 cycles, isochronous

Sean H. Breheny [shb7 at CORNELL.EDU] says:

movwf CHAR_HI           ; Place W in CHAR_HI to store
swapf CHAR_HI,W         ; Place CHAR_HI in W with most
                                 ; significant nibble in lower
                                 ; part of W
andlw 0x0F                      ; Clear upper part of W

addlw -10                       ; Same as single digit, do conversion
btfsc STATUS,C
addlw 'A'-'0'-10
addlw '0'+10
                                 ; Swap W and CHAR_HI
xorwf CHAR_HI,F         ; CHAR_HI = CHAR_HI xor W
xorwf CHAR_HI,W         ; W = W xor CHAR_HI xor W
                                 ; = (W xor W) xor CHAR_HI
                                 ; = 0 xor CHAR_HI = CHAR_HI
xorwf CHAR_HI,F         ; CHAR_HI = CHAR_HI xor W xor CHAR_HI
                                 ; = (CHAR_HI xor CHAR_HI) xor W
                                 ; = 0 xor W = W

andlw 0x0F              ; Now we have original W back in W
                         ; Clear upper part so we are left
                         ; with original least significant
                         ; nibble

addlw -10               ; Same as single digit, do conversion
btfsc STATUS,C
addlw 'A'-'0'-10
addlw '0'+10            ; We're done

Kübek Tony [tony.kubek at FLINTAB.COM] says:

another version: uses one stack-level more is not 'faster' but less code space :)
;
***********************************************************************
;
;  CONV_BYTE_HEX - Converts the byte in w to two ASCII hex digits ('0'-'9', 'A'-'F' )
;  Returns with top nibble ASCII digit in char_hi and the bottom one inW
;  NOTE uses TWO deep stack ( nested calls ) !! 
CONV_BYTE_HEX
        MOVWF   char_hi ; save byte temporarily
        SWAPF   char_hi,W       
        ; convert top nibble
        CALL    CONV_NIBBLE_HEX 
        ; top nibble in w, exchange char_hi with w
        XORWF   char_hi,F
        XORWF   char_hi,W
        XORWF   char_hi,F
        ; and convert low nibble
CONV_NIBBLE_HEX
        ANDLW   0x0F    ; mask out top nibble, preserv low nibble
        ADDLW   0xF6    ; add 246, to check if 0-9 or a-f, w=nibble+246
        BTFSC   STATUS,C ; if carry set then a-f
        ADDLW   0x07     ; carry set, then add 7, w=nibble+246+7 ( note nibble known to be a-f )
        ADDLW   0x3A     ; then finally add 58 to get 'proper' ascii 
                        ; 1) w = low(nibble+246+58) = 48+nibble ( if 0-9 )
                        ; 2) w = low(nibble+246+7+58) = 55+nibble ( if a-f )
        ; nibble converted to ASCII hex in w            
        RETURN



Comments:

Says:

A warning to users: This code is actually not usable for the range 0x00 to 0xFF, but only 0x00 to 0x99. Any nibbles of a value from 0xA to 0xF are converted to 0x3A through 0x3F, which is not correct ASCII. This code is only safe to use if your values will not go above 0x99.

Code: