8bit BCD functions from my new libraries (with source).

General discussion on mikroC PRO for PIC.
Post Reply
Author
Message
IstvanK
Posts: 166
Joined: 22 Feb 2013 12:28

8bit BCD functions from my new libraries (with source).

#1 Post by IstvanK » 25 Nov 2013 19:19

I'm using a bit another algorithms as the 'official' Conversions library, but - for example - my "Dec_Bcd" is appr. quarter in size and more than twice as fast compared to the original "Dec2Bcd" function while gives same results:

Code: Select all

char Dec_Bcd(char c) {
     //R0 is a 'freely usable' (char type) working register in mikroC.

     for ( R0 = 0 ; c > 9 ; R0 += 16, c -= 10 );
     return R0 + c; 
}
I wrote also the opposite function (instead of the "Bcd2Dec").
First here is the pure C version "bcd2dec2", only to demonstrate a fast mul_10 algorithm for all 8bit non-p18 chips:
10*c = c+c+(c<<3)

Code: Select all

char bcd2dec2(char c) {

#ifdef P18 //hw mult will be used
     return Swap(c & 0xF0) * 10 + (c & 15); // 10*NoT + number of ones;
#else
     char NoT; //Number of Tens
     char tens;//'tens' digit

     NoT = Swap(c & 0xF0);
     //calculate NoT*10 using 'add' and 'rotate' (NoT < 16)
     NoT = NoT + NoT;         //2*
     tens = NoT + (NoT << 2); // 2* + 8* = (2+8)* = 10*
     //calculate the return value
     return tens + (c & 15);  // 10*NoT + number of ones
#endif
}
However, instead the above I recommend to use the asm optimized "Bcd_Dec" version (see attached, I do not write it here because many people rightly(?) averse to use of inline asm. Among others this is why I do not publishing the source of my own libraries).

The following comparison table contains the asm optimized version too. The table is based on the original functions with the same parameters (the 100% size and speed):
Bcd2Dec(0x99); //result = 99
Dec2Bcd(99); //result = 153 = 0x99

Code: Select all

          Dec_Bcd       bcd2dec2      Bcd_Dec     
        size  speed   size  speed   size  speed	
       
p16:     27%  231%     65%  275%     37%  463% 
p16e:    28%  208%     65%  290%     40%  457%
p18:     23%  253%     90%  100%     55%  156%

A PIC16F887 example (measured in the mikroC IDE Debugger):
 
the new Dec_Bcd(99) is    15 bytes long and 'eats' 106 cycles ( 1/speed )
  while Dec2Bcd(99) is 39+17 bytes long and 'eats' 246 cycles
Try and use it!
IstvanK
Attachments
Bcd_Dec.zip
(560 Bytes) Downloaded 210 times

User avatar
filip
mikroElektronika team
Posts: 11874
Joined: 25 Jan 2008 09:56

Re: 8bit BCD functions from my new libraries (with source).

#2 Post by filip » 26 Nov 2013 09:10

Hi,

Thank you for posting this, I'm sure our users will benefit from it.

Regards,
Filip.

IstvanK
Posts: 166
Joined: 22 Feb 2013 12:28

Re: 8bit BCD functions from my new libraries (with source).

#3 Post by IstvanK » 29 Nov 2013 17:06

More (self-explanatory) functions from my new libraries, here in pure C. Useful - for example - to display the RTC registers (eg min, hour) having BCD numbers.
The libraries contain the asm optimized (of course :-)), smaller and faster versions, using also my simplified multi LCD/SwUart functions.
After finished and well tested I will publish them in MCL form - now already separated for the three 8bit PIC family: p12/16, p12e/16e and p18 - as my time allows it.

Code: Select all

void BcdOut2Uart1(char ch) {   // ch is a valid bcd, max 0x99
  UART1_Write(Swap(ch & 0xF0) + '0');
  UART1_Write((ch & 0x0F) + '0');
}

void Dec2Out2Uart1(char ch) {  // ch = 0...99
  for ( R0 = '0' ; ch > 9 ; ++R0, ch -= 10 );
  UART1_Write(R0);
  UART1_Write(ch + '0');
}

void BcdOut2Lcd_CP(char ch) {
  Lcd_Chr_CP(Swap(ch & 0xF0) + '0');
  Lcd_Chr_CP((ch & 0x0F) + '0');
}

void Dec2Out2Lcd_CP(char ch) {
  for ( R0 = '0' ; ch > 9 ; ++R0, ch -= 10 );
  Lcd_Chr_CP(R0);
  Lcd_Chr_CP(ch + '0');
}

#define _d_ 
//if defined then the following positioned LCD outs are splitted (smaller code!):

void SetLcdPos(char row, char column) {
  --row; --column;     // *** if the first row/column is equal to 1 (convention)
  column.B7 = 1;       // add 0x80 (cursor set command)
  if (row.B0)          // row 1 or 3 (original 2 or 4)
     column.B6 = 1;    // add 0x40
  if (row.B1)          // row 2 or 3
 #ifndef LCD_16x4
     column += 0x14;   // usual (commonly used) offset
 #else
     column.B4 = 1;    // column += 0x10; different offset !!
 #endif
  Lcd_Cmd(column);
}
//or ... here is a shorter(?) solution for any non-16x4 LCD:
void SetLcdPos_(char row, char column) {
  char zero = 0; //treated as empty string ("")
  Lcd_Out(row, column, &zero); //only set position
}

#ifdef _d_
  #define BcdOut2Lcd(row,column,ch)  SetLcdPos((row),(column)); BcdOut2Lcd_CP(ch)
  #define Dec2Out2Lcd(row,column,ch) SetLcdPos((row),(column)); Dec2Out2Lcd_CP(ch)
#else // longer code
  void BcdOut2Lcd(char row, char column, char ch) {
     SetLcdPos(row, column);
     BcdOut2Lcd_CP(ch);
  }
  void Dec2Out2Lcd(char row, char column, char ch) {
     SetLcdPos(row, column);
     Dec2Out2Lcd_CP(ch);
  }
#endif
Try and use it!
IstvanK

User avatar
filip
mikroElektronika team
Posts: 11874
Joined: 25 Jan 2008 09:56

Re: 8bit BCD functions from my new libraries (with source).

#4 Post by filip » 03 Dec 2013 09:56

Hi,

Thanks again! :)

Regards,
Filip.

PaulC
Posts: 100
Joined: 03 Oct 2007 15:15
Location: Ireland

Re: 8bit BCD functions from my new libraries (with source).

#5 Post by PaulC » 23 Dec 2013 13:00

excellent thank you for this
Read it - Figure it - Share it

mick61
Posts: 4
Joined: 19 Aug 2016 17:40

Re: 8bit BCD functions from my new libraries (with source).

#6 Post by mick61 » 22 Apr 2017 16:16

IstvanK

Nice work

Thank you

Post Reply

Return to “mikroC PRO for PIC General”