To download this file click here

/********************16 bit Binary to 5 decimal place conversion in Basic*******************************


** Heavily based on Peter Hemsley's High Speed Binary to Decimal For PICs article, published in EPE magazine, September 2004.
**
** The original ASM code and full explanations for this file can be downloaded from
www.epemag.wimbourne.co.uk.
**
** From the  download page look in Pic Tools folder
**Some similar ASM only code, and other maths algorithms are available for viewing at
** http://www.dattalo.com/technical/software/pic

**Assembler instructions such as rlf have been used as  XCSB  optimises the Carry register by automatically clearing it when code such as  temp = temp << 1 or temp = temp * 2 is used.
**

**The code comments assume that you have the original code and article available.
**
** This code uses 84 asm  instructions (including the ascii conversion) compared to the original 46 asm instructions (no ascii conversion) of the EPE article. 
**

**Code space used 108 words
**Code size 84 instructions
**Ram space 11 bytes


Compiler XCSB v1.8.1 Pro

 

This file may be used freely, however all text in this green colour must be included in any source code used for professional purposes


Copyright C D Barnard  DATE 9/01/2005
********************************************************************************************************************/

Variable declarations


int number
ubyte splitH
ubyte splitL
ubyte temp
ubyte tthou
ubyte thou
ubyte hund
ubyte tens
ubyte units
ubyte ASCII_flag

 

 

 

proc bin2dec_5(uint number, ubyte flag)

 


//Break 16 bit number into two byte size chunks
splitH = number >> 8
splitL = number


units = (splitH | 0xF0)               // Or'ing the byte with D'240 is the same as deducting 16 from the lower nibble

tens = units        
tens = tens + tens + tens  //
hund = units        

 

 

asm_start                                // It is necessary to use assembler here to prevent the compiler from clearing the carry
 

rlf hund,F


asm_end

 

 

splitH = splitH >>4                 // Swap the nibble around so as to work on what was the top nibble
splitH = splitH | 0xF0             // Again deduct D'16 from the nibble
  
hund = hund + splitH    
thou = splitH         
thou = thou + splitH       
units = units + (splitH + 52) 
   

temp = (splitL >>4)       // In basic we cannot use the W register directly (16F series) a temporary register has to be used
temp = temp | 0xF0           //Now working on the low byte, high nibble and deducting 16 from the contents. 
tens = tens + temp
units = units + temp


asm_start

//asm has to be used here partly for the reason stated above for rlf and because it seemed pointless to write the comf
// equivalent in basic. For those who are interested, 'comf'  in basic would be  units^0xFF

 

  rlf units,F
  comf units,F
  rlf units,F

 

asm_end

 

units = units + (splitL & 0x0F) //mask off the top nibble

 

 

asm_start

 

  rlf Tens,F

 

asm_end

 

tthou = 7

 

asm_start

        addlw 3
        rlf thou,F


asm_end


/**************************************************************************************************************************************
*************************************************************************************************************************************


** There are two choices of using the code below.

 

 

** The assembler version


** Which takes 8 instructions less than the basic version, can be uncommented if program space and speed is of             ** paramount importance.


** The basic version generates an extra two "goto's" per test of the STATUS register.


*************************************************************************************************************************************/

//Basic version. This is a sort of do...while or do.....until loop


while (1) do

 

 

asm_start

 

LSD                                    //Least Significant Digit


 addwf units,F
 decf tens,F

 

asm_end

 

    if (STATUS & (1<<C)) != 0 then   //If carry is set (=1) then we're finished with UNITS and ready for the TENS
 

  asm_start

 

  LMD

addwf tens,F
decf hund,F

 

  asm_end

       

 

     if (STATUS &(1<<C)) != 0 then   //Carry is set onto the HUNDreds

 

   asm_start

 

    MMD


        addwf hund,F
        decf thou,F

 

   asm_end

 

      if (STATUS & (1<<C)) != 0 then  //Done with the HUNDreds onto the THOUsands

 

    asm_start

 

     NSD

 

       addwf thou,F 
       decf tthou,F

 

     asm_end
        

        if (STATUS & (1<<C)) !=0 then  //THOUsands done, TenThousands take care of themselves, do..while loop finished

 

      break  //jump out of the loop to the done directive

 

        endif

 

        goto NSD

 

      endif

 

      goto MMD

 

     endif

 

      goto LMD

 

    endif

done

 

 

//Assembler version

/*
asm_start

 

LSD //Least Significant Digit

 

 addwf Units,F
 decf Tens,F
 btfss STATUS,C
 goto LSD


//Least Middle Digit
 

LMD

 

 addwf Tens,F
 decf Hund,F
 btfss STATUS,C
 goto LMD

 

//Middle Middle Digit

MMD

 

 addwf Hund,F
 decf Thou,F
 btfss STATUS,C
 goto MMD

 

//Next Significant Digit

NSD

 

 addwf Thou,F
 decf Tthou,F
 btfss STATUS,C
 goto NSD

 

asm_end
*/

 

// Convert the hex digit into ASCII format.

 

  if ASCII_flag !=0 then

 

    tthou = tthou + 0'0'  //This is equivalent to  tthou | 0x30
    thou = thou  + 0'0'
    hund = hund + 0'0'
    units = units + 0'0'

 

 endif


//return to calling program

 

endproc


endproc