CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

shift left right
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kmp84



Joined: 02 Feb 2010
Posts: 357

View user's profile Send private message

shift left right
PostPosted: Wed Aug 01, 2018 6:11 am     Reply with quote

Hello All,

I want to implement ccs shift_left( ), shift_right( ) functions in standard "C" language. Can you help me with some efficient C code?

Best Regards!
temtronic



Joined: 01 Jul 2010
Posts: 9249
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 7:25 am     Reply with quote

Have to ask WHY don't you use the CCS functions ??
As for converting to 'C'...well which 'C', which PIC ?? It's questionable that you can get better than what CCS has done and it brings up the next question
What do you term 'efficient' ? You have to decide on either speed, code space or compromise on a bit of both.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19555

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 7:40 am     Reply with quote

The C equivalent is to shift left one bit with <<, and then OR with the input value. You can though only do this with standard sized variables (so typically one byte, two bytes and four bytes). Shift right you do similarly with >> and then OR in the top bit (make sure the declared value is unsigned).
Many C's will have a similar shift right or shift left in their library. Efficiency depends totally on the capabilities of the processor involved.
kmp84



Joined: 02 Feb 2010
Posts: 357

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 8:27 am     Reply with quote

Okay, for now let's forget "efficient" code. I have working code that want to be portable to other compilers.
Ttelmah



Joined: 11 Mar 2010
Posts: 19555

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 8:47 am     Reply with quote

As I said, standard shift and OR. This is how shifting a bit in from a pin for example is done in most C's.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 8:59 am     Reply with quote

Quote:
I have working code that want to be portable to other compilers.

Post a few of your shift_left() lines from your program.
Post the variable declarations too.
temtronic



Joined: 01 Jul 2010
Posts: 9249
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 9:12 am     Reply with quote

re:
I have working code that want to be portable to other compilers.

It's highly unlikely that your CCS program can be 'ported' to other compilers , unlike COBOL, C doesn't have a 'setup section' for various processors and environments. At least not that I've seen. COBOL was great that way, just change ONE small section of code and your program would compile and execute on any machine running COBOL.
Those that grew up with 'C' should know, but I rather doubt it can be made 'portable'.

Jay
kmp84



Joined: 02 Feb 2010
Posts: 357

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 9:20 am     Reply with quote

PCM programmer wrote:
Quote:
I have working code that want to be portable to other compilers.

Post a few of your shift_left() lines from your program.
Post the variable declarations too.


Code:

void BinToBCD(unsigned int32 val, int8 *OutBcdBuff){
   //converts U32bit value, to BCD digits.
   int1 temp_bit;
   int8 size = 32;
   int8 i;
   int8 buff[] = {0,0,0,0,0};    // For optimization. The PIC processor can address a local array much more efficient than a parameterized address.
   do {
      if ((buff[0] & 0xF)>=5) buff[0]+=3;
      if ((buff[0] & 0xF0)>=0x50) buff[0]+=0x30;
      if ((buff[1] & 0xF)>=5) buff[1]+=3;
      if ((buff[1] & 0xF0)>=0x50) buff[1]+=0x30;
      if ((buff[2] & 0xF)>=5) buff[2]+=3;
      if ((buff[2] & 0xF0)>=0x50) buff[2]+=0x30;
      if ((buff[3] & 0xF)>=5) buff[3]+=3;
      if ((buff[3] & 0xF0)>=0x50) buff[3]+=0x30;           
     
      temp_bit=shift_left(&val,4,0);
      shift_left(buff,4,temp_bit);
     
   } while (--size);
 
   memcpy(OutBcdBuff, buff, 4);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19555

View user's profile Send private message

PostPosted: Wed Aug 01, 2018 12:39 pm     Reply with quote

Don't get me wrong, but on 90%+ of processors you will have hardware division available. On these just use %, and then divide the number by ten. Don't waste time performing the rotations.
There is also severe problem. A 32bit binary value, can generate a BCD number involving over 9 digits. Your code is only able to code with just over a 16bit value, not 32bit.
Generically the most portable way to code it is to simply sprintf to a string and subtract '0' from each digit.
kmp84



Joined: 02 Feb 2010
Posts: 357

View user's profile Send private message

PostPosted: Thu Aug 02, 2018 2:12 am     Reply with quote

I changed "BinToBCD()" function with Ttelmah's suggestion.

Code:
void BinToBCD(unsigned int32 val, unsigned int8 *OutBcdBuff){
   //converts 32bit value, to ten BCD digits.
   U8 i,k;
   U8 buff[] = {0,0,0,0,0,0,0,0,0,0};
   
   k = sprintf(buff,"%Lu", val);
   
   for(i=0; i<k; i++){   
      buff[i] -='0';      
  }
   
   for(i=0; i<5; i++){
      buff[i] = (buff[i*2]<<4) | (buff[i*2+1]);
   }   
   
   memcpy(OutBcdBuff, buff, 5);
}


But I'm not ready yet with shifting bits in array of bytes!

Best Regards,
Ttelmah



Joined: 11 Mar 2010
Posts: 19555

View user's profile Send private message

PostPosted: Thu Aug 02, 2018 2:19 am     Reply with quote

There is a problem with the version you have generated. Think about it the number contains (say) 100, so you get a string "100". Only three digits. You need to be justifying the number to a fixed length output. Remember also strings need one extra character for the terminator.
kmp84



Joined: 02 Feb 2010
Posts: 357

View user's profile Send private message

PostPosted: Thu Aug 02, 2018 3:38 am     Reply with quote

Ttelmah wrote:
There is a problem with the version you have generated. Think about it the number contains (say) 100, so you get a string "100". Only three digits. You need to be justifying the number to a fixed length output. Remember also strings need one extra character for the terminator.


Yes , just add one more 0\ to U8 buff[] for null terminate string, but there is no problem with 100. I have tested it. Calculation "-=0x30" applies only to ascii data!
kmp84



Joined: 02 Feb 2010
Posts: 357

View user's profile Send private message

PostPosted: Thu Aug 02, 2018 6:03 am     Reply with quote

Hi mr.TT,

Sorry, I saw the problem!

Confused
kmp84



Joined: 02 Feb 2010
Posts: 357

View user's profile Send private message

PostPosted: Thu Aug 02, 2018 6:40 am     Reply with quote

This is working code for 32bit bin to bcd:
Code:

void BinToBCD(unsigned int32 val, int8 *OutBcdBuff){
   //converts U32bit value, to BCD digits.
   int1 temp_bit;
   int8 size = 32;
   
   int8 buff[] = {0,0,0,0,0}; 
   do {
      if ((buff[0] & 0xF)>=5) buff[0]+=3;
      if ((buff[0] & 0xF0)>=0x50) buff[0]+=0x30;
      if ((buff[1] & 0xF)>=5) buff[1]+=3;
      if ((buff[1] & 0xF0)>=0x50) buff[1]+=0x30;
      if ((buff[2] & 0xF)>=5) buff[2]+=3;
      if ((buff[2] & 0xF0)>=0x50) buff[2]+=0x30;
      if ((buff[3] & 0xF)>=5) buff[3]+=3;
      if ((buff[3] & 0xF0)>=0x50) buff[3]+=0x30;           
      if ((buff[4] & 0xF)>=5) buff[4]+=3;
      if ((buff[4] & 0xF0)>=0x50) buff[4]+=0x30;     
     
      temp_bit=shift_left(&val,4,0);
      shift_left(buff,5,temp_bit);
     
   } while (--size);
 
   memcpy(OutBcdBuff, buff, 5);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19555

View user's profile Send private message

PostPosted: Thu Aug 02, 2018 6:54 am     Reply with quote

You had that code at the start. It has one fault, it wastes time doing all the tests before the rotation. If you read the algorithm for the shift and test conversion it does not do this.
However I don't see where you are going. You asked about doing the conversion in 'standard C'. The ASCII and subtract solution is one to do this. Or divison and remainder. Or just implement the shift by repetitive standard word << shifts ang generating the shifted bit yourself. Funnily one of the old standard methods is just to do subtractions. Have a table of all the values corresponding to BCD digits 1000, 100, 10, and starting with the largest just perform repeated subtractions, if the value tests as bigger than the digiit. This can actually be suprisingly small and quick.
These are the 'generic' solutions, but none are going to be particularly efficient.
So where are you 'going'?. You have a CCS solution. If you want an efficient solution on any other compiler it is going to need to be coded for that compiler. There are inefficient generic solutions.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group