|
|
View previous topic :: View next topic |
Author |
Message |
georgei Guest
|
shift right and left |
Posted: Mon Aug 17, 2009 11:54 pm |
|
|
hello.
I am trying to shift a byte right and left.
I know 2 commands for that:
1. a<<2
2. shift_left(a,1,0)
The final bit is lost in both of them, but I need a function that move right and left in cycle-which mean that the msb is coming back to the right, and I am not losing any bit. Someone know a function for that?
Anyway, why this code is not working?
Code: |
a=0b00000101;
WHILE(1)
{
output_c(a);
delay_ms(2000);
a<<1;
}
|
I get the word in port C, but it doesn't move right\left.
How can I move it without losing the msb\lsb ?
thanks. |
|
|
Ttelmah Guest
|
|
Posted: Tue Aug 18, 2009 2:15 am |
|
|
What you want is to use the _rotate_ function.
It is fairly obvious if you think about it.
01000111
Shift it left
10001110
and again
00011100
Shift, is like a 'slider', moving the byte. Anything going out the 'top' os lost, and you get new '0' values (or optionally '1'), introduced at the bottom. So on the last shift, you lose the top '1'.
Now, start with the same byte
Rotate it left
10001110
and again
00011101
With rotate, the bits are treated like a 'wheel', with the stuff going off one end, and arriving back at the other. So on the last rotation, the MSb, gets rotated back to the start.
If you look at rotate_right, and rotate_left n the manual, you should find what you want.
Best Wishes |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Aug 18, 2009 2:18 am |
|
|
You mean rotate.
It strange realy because the assembler has rotate instructions but C (as far as I know) doesn't have a direct map to an operator.
One way to do it in C is
Code: |
// Rotate right by 1
int rotateRight(int val)
{
int flag;
flag = (val & 0x01) << 8;
val = (val >> 1) | flag;
return(val);
}
// Rotate left by 1
int rotateLeft(int val)
{
int flag;
flag = (val & 0x80) >> 8;
val = (val << 1) | flag;
return(val);
}
|
This can be done better and quicker using a bit of asm
#asm
RLFC val, F
RRCF val, F
#endasm
Or using CCS code
rotate_left(&val, 1);
rotate_right(&val, 1); |
|
|
Ttelmah Guest
|
|
Posted: Tue Aug 18, 2009 2:49 am |
|
|
Er. Wayne, look at 'rotate_right', and 'rotate_left' in the manual....
Best Wishes |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Aug 18, 2009 4:11 am |
|
|
Ttelmah wrote: | Er. Wayne, look at 'rotate_right', and 'rotate_left' in the manual....
Best Wishes |
Er. look at the end of my post
I posted all 3 methods |
|
|
Ttelmah Guest
|
|
Posted: Tue Aug 18, 2009 8:13 am |
|
|
What I don't understand, is why you think 'C' (as opposed to CCS C), should have a function....
You say 'assembler' has this function, but this is simply not true, for quite a few processors. If you look at some of the mini computers dating from the date when C was written, a lot don't have rotate functions in their assembler. It had to be done by masking off the extra bit, shifting, then masking the bit back in. You can write this quite easily in C, using something like (for a byte, shifting left):
(val & 0x80)?(val<<1)+1:(val<<1);
Or test the bottom bit when going the other way.
Because the PIC, does have an assembler instruction for this, CCS have added the directives to access this.
Rotate functions are actually quite rare in early assembler, and weren't considered that useful. What is annoying in the CCS _shift_ functions, is that they don't allow direct access to the bit shifted out.
Best Wishes |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Aug 18, 2009 8:44 am |
|
|
First of all this is very off topic.
Secondly I never said C should have a function I said it is strange that it didn't when many, I never said ALL, processors have a built in function, in fact I only specified that the PIC did.
I know many that do, I don't personally know of any that don't without looking but I am sure there are some, and i have programmed a few processors in my time as I am sure you have.
It would have been very easy to map a C function to a rotation function in asm even if the processor didn't have one! I just stated that it was strange that it was left out when they developed C.
Yes you can easily write code in C to do the job as I posted, so why did you have to go and show an obfuscated version, and before you say it, it is only obfuscated if you don't understand it!
So, CCS have decided to include a function to do rotation, I assume that this is directly mapped to the pic opcode ?
Sorry if I sound a bit off it just seems like you are arguing for the sake of arguing!
All I did was correct you for missing off the fact that I DID read the CCS manual to see if there was a function to do it, and I actually posted the fact that it did.
I couldn't understand why you told me to look in the manual when I obviously did
Enjoy |
|
|
Ttelmah Guest
|
|
Posted: Tue Aug 18, 2009 8:57 am |
|
|
Because they were tucked away at the bottom of the post, when to answer the original question, they should have been the first choices....
It does really come down to them not being considered useful functions. Shifting data in and out, is common, rotating relatively rare.
Best Wishes |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Aug 18, 2009 9:09 am |
|
|
Ttelmah wrote: | Because they were tucked away at the bottom of the post, when to answer the original question, they should have been the first choices....
|
Should they when they make the code CCS specific and harder to port!
Just a thought
It's like using make8, make16, shift_left and shift_right. Why use those when it is just as easy to use standard C to do the same thng ?
OK, in the case of rotate_left and rotate_right there is a good reason, and that is because CCS maps it to a single opcode for an 8 bit value, hopefully, I havn't checked
You could do the same with inline assembler, or even write your own function / macro to do it.
But it does annoy me when people have to resort to non standard functions to do something that is easier to do in C anyway, only because they either don't know C or someone has told them to use the function, instead of showing the C code to do it! |
|
|
georgie Guest
|
so.. |
Posted: Tue Aug 18, 2009 10:47 am |
|
|
you saying too much but at the end i dont know how to rotate
lets say i have 0b01010101 and i need to rotate it to left,without loosing bit.
what is the exact line for that ??
thanks a lot.. |
|
|
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Tue Aug 18, 2009 10:55 am |
|
|
Page 200-201 of the manual the example is:
x = 0x86; //0b 1000 0110
rotate_left (&x, 1);
//x is now 0x0d //0b 0000 1101
The thing to remember I suppose is that the rotate functions expect a pointer as the first argument. |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Tue Aug 18, 2009 4:18 pm |
|
|
This does it pretty economically:
Code: |
i <<= 1;
if (bit_test(status, 0))
bit_set(i, 0);
|
This works because when the shift operation takes place, the top bit is shifted out into the carry bit, i.e. bit 0 of the status register, and the bottom bit is cleared. So you can test the carry bit, and if it contains a 1, set the bottom bit of the register which was shifted. |
|
|
georgie Guest
|
THANKS |
Posted: Wed Aug 19, 2009 1:14 am |
|
|
thanks a lot. it helped me so much.
but if i need to rotate only the 4 low bits ?
lets say i have : 00001010
i need to rotate left only the 4 right bits.. so i wanna get: 00000101
how i do that with rotate ? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Aug 19, 2009 5:55 am |
|
|
It starts to look like a school assignment where we are doing your work. Post an attempt on solving the problem yourself and if you don't succeed we'll be happy to help you improve on it. |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Wed Aug 19, 2009 6:24 am |
|
|
Quote: | thanks a lot. it helped me so much.
but if i need to rotate only the 4 low bits ?
lets say i have : 00001010
i need to rotate left only the 4 right bits.. so i wanna get: 00000101
how i do that with rotate ? |
John P's code should give you a hint on how to do this - then check out bitwise & and | operators! (Ok extra hint - you need to get the low 4 bits out (& with 0x0F) rotate that, and OR (|) back in.) |
|
|
|
|
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
|