|
|
View previous topic :: View next topic |
Author |
Message |
stewart
Joined: 28 Nov 2005 Posts: 12
|
Calling all CASTers |
Posted: Fri Jul 18, 2008 12:49 am |
|
|
Welcome to CAST LAND
Thanks to the forum for many previous questions answered!!!!
The trouble with CAN went smooth with the help of you all.
I have a need for a "barrel shift".
Using CCS PCH C Compiler, Version 4.050, 40210
Looking for the best generated code, based on the data type, I tried
several examples to see which was the fastest.
What do you all think is wrong with the commented out lines??
Is this just a matter of CASTing??
Thanks,
Stewart
Code: |
#include "18f4423.h"
typedef struct {
int8 D0:1;
int8 D1:1;
int8 D2:1;
int8 D3:1;
int8 D4:1;
int8 D5:1;
int8 D6:1;
int8 D7:1;
} BYTEBITS;
void main() {
int8 a, b[2];
BYTEBITS c, d[1], e[2], f[4];
int16 g;
int32 h;
if ( ! ( a >>= 1) ) a = 0x80;
// if ( ! ( (int16) b[0] >>= 1) ) b = 0x8000;
if ( ! ( (int8) c >>= 1) ) c.D7 = 1;
if ( ! ( (int8) d[0] >>= 1) ) d[0].D7 = 1;
if ( ! ( (int16) e[0] >>= 1) ) e[1].D7 = 1;
// if ( ! ( (int32) f[0] >>= 1) ) f[3].D7 = 1;
if ( ! ( g >>= 1) ) g = 0x8000;
if ( ! ( h >>= 1) ) h = 0x80000000;
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Fri Jul 18, 2008 2:37 am |
|
|
Major fault with the first. 'b' is the _address_ of the array, not an element...
There are similar fault in most of your lines. It is just 'luck' that in some cases they work. How (for instance), can '0x8000', be put into an integer?. int's in CCS C (unless you are on a DSPIC), are only 8bits wide.
You are misunderstanding what happens with a 'cast'. It doesn't allow you to access a byte variable as if it is (for example) an int16. It _extracts_ the byte value, and turns this into an int16. It then performs the operation on the int16 value, and if you then write this back to the same variable, the result is automatically converted _back_ to int8.
The command that allows you to access the same memory area in various ways, is the _union_.
You talk about wanting a 'barrel shift'. This can't be done in code. A 'barrel shifter', is a hardware circuit that produces a defined number of bits of shift in one clock cycle. Software is never going to do this...
All you seem to be trying to implement, is a simple rotation, rather than a shift. So, in the first case, if as a result of the shift, the value becomes '0', you put a bit back into the top of the byte. Why not just use the processor's hardware instructions, that already do this, available to you, using the 'rotate_right' instruction?.
So, your entire 'f' rotation, just becomes:
rotate_right(&f[0],);
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Fri Jul 18, 2008 4:03 am |
|
|
Add a number after the comma according to how many bytes of the array you want to rotate. So '4' to do the whole 4 byte array.
Best Wishes |
|
|
stewart
Joined: 28 Nov 2005 Posts: 12
|
|
Posted: Sat Jul 19, 2008 2:01 am |
|
|
Ttelmah,
A well written and informative reply, Thanks !!
I missed the rotate_right/left() functions Thanks !
I should have looked things over a bit more before posting. My "bit setting" was a secondary error.
You also brought up that a "cast" is a extraction of a value.. I thought it was a "treatment" or pro-motion/de-motion.
The shift of various types was the question.
If you would, please explain
The difference in how 'b' and 'e' are seen by the compiler in terms of the shift.
Why does a reference to 'b' not indicate that it's sizeof(b).
Why did the use of a struct change things??
You are an asset to the learning.
Thanks,
Stewart |
|
|
Ttelmah Guest
|
|
Posted: Sat Jul 19, 2008 4:01 am |
|
|
It doesn't change the actual 'value'. It changes how the value is treated in an operation. Hence extraction is implicit. The point is that you can't write 'into' a cast (so if you store 0x8000, into a type cast 'up' to an int16, the basic storage type is still an int8, and only the low byte will be saved). This is why the cast is not suitable for putting data 'back' as you show.
There are ways of doing this with a cast. For instance, if you take the address of an int8 array, and cast this to be the address of an int16 array, then you can access the int16 elements using this address.
In C, the 'name' of an array, is shorthand for it's location in memory. Some operations (such as sizeof), will still extract the sizeof the array, rather than of the location.
However the union is the 'key' simple operator for mixed access like this. So:
Code: |
typedef struct {
int8 D0:1;
int8 D1:1;
int8 D2:1;
int8 D3:1;
int8 D4:1;
int8 D5:1;
int8 D6:1;
int8 D7:1;
} BYTEBITS;
union {
BYTEBITS bi[4];
byte b[4];
int16 w16[2]
int32 val32;
} val;
//Puts a four byte array, a four byte array of 8 bits, a two word
//array of int16 values,and a single int32 value, _all_ accessing the
//same part of memory.
val.val32=0x80000000;
//writes a 32bit value into the entire area.
if (val.bi[3].D7 == 1) {
//will access the top bit of the top byte
}
val.w16[1] = 0x4000;
//Will write an int16, into the top two bytes of the area
val.b[3] = 0x80;
//Will write an int8 into the top byte
|
This allow 'interchangeable' access to the same memory area, for both read, and write, using whatever form you want!...
Best Wishes |
|
|
|
|
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
|