SFBMacros.h File Reference

Various utility macro definitions. More...

#include "SFBTypes.h"

Include dependency graph for SFBMacros.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define REGISTER_OFFSET(baseAddress, byteOffset)   (*((uv32 *) (((u32)(baseAddress))+(byteOffset))))
 Access a 32 bit H/W register.
#define B36_1(a)   B36_CONST_##a
 A length 1 base 36 constant.
#define B36_2(a, b)   (B36_1(a)*36u+B36_1(b))
 A length 2 base 36 constant.
#define B36_3(a, b, c)   (B36_2(a,b)*36u+B36_1(c))
 A length 3 base 36 constant.
#define B36_4(a, b, c, d)   (B36_3(a,b,c)*36u+B36_1(d))
 A length 4 base 36 constant.
#define B36_5(a, b, c, d, e)   (B36_4(a,b,c,d)*36u+B36_1(e))
 A length 5 base 36 constant.
#define B36_6(a, b, c, d, e, f)   (B36_5(a,b,c,d,e)*36u+B36_1(f))
 A length 6 base 36 constant.
#define B36_7(a, b, c, d, e, f, g)   (B36_6(a,b,c,d,e,f)*36u+B36_1(g))
 A length 7 base 36 constant.
#define IN_BODYRAM   __attribute__((section (".bodyram")))
#define IN_TALKRAM   __attribute__((section (".talkram")))
#define IN_FASTRAM   __attribute__((section (".fastram")))
#define IN_BODYRAM_BSS   __attribute__((section (".bss.bodyram")))
#define IN_TALKRAM_BSS   __attribute__((section (".bss.talkram")))
#define IN_FASTRAM_BSS   __attribute__((section (".bss.fastram")))
Bit Operations
These macros generally expect u32 operands, though some may work on smaller types

#define SET_BIT(value, bitNum)   ((value) |= (1<<(bitNum)))
 Set bit bitNum in value.
#define CLEAR_BIT(value, bitNum)   ((value) &= ~(1<<(bitNum)))
 Clear bit bitNum in value.
#define GET_BIT(value, bitNum)   (((value)>>(bitNum))&1)
 Access bit bitNum in value.
#define TEST_BIT(value, bitNum)   ((value)&(1<<(bitNum)))
 Check if bit bitNum in value is set.
#define BIT_PAIR_AT_POSITION(bits, newValue, position)   ((bits) = ((bits)&(~(3<<(position))))|((newValue)<<(position)))
 Set a consecutive pair of bits in bits, located at position, to value newValue.
Small Constant Array Maps
#define MAP4BY2(a, b, c, d)   ((((((((u8) d)<<2)|(c))<<2)|(b))<<2)|(a))
 Encode 4 numbers each 2 bits long, see MAP3BY3 for background.
#define GET_MAP4BY2(map, idx)   (((map)>>((idx)<<1))&0x3)
 Access the values encoded by MAP4BY2.
#define MAP4BY4(a, b, c, d)   ((((((((u16) d)<<4)|(c))<<4)|(b))<<4)|(a))
 Encode 4 numbers each 4 bits long, see MAP3BY3 for background.
#define GET_MAP4BY4(map, idx)   (((map)>>((idx)<<2))&0xf)
 Access the values encoded by MAP4BY4.
#define MAP4BY8(a, b, c, d)   ((((((((u32) d)<<8)|(c))<<8)|(b))<<8)|(a))
 Encode 4 numbers each 8 bits long, see MAP3BY3 for background.
#define GET_MAP4BY8(map, idx)   (((map)>>((idx)<<3))&0xff)
 Access the values encoded by MAP4BY8.
#define MAP3BY3(a, b, c)   ((((((u16) c)<<3)|(b))<<3)|(a))
 Encode 3 numbers each 3 bits long.
#define GET_MAP3BY3(map, idx)   (((map)>>((idx)*3))&0x7)
 Access the values encoded by MAP3BY3.
#define BLINK_MAP(red, green, blue)   MAP3BY3(blue,green,red)
 Use a MAP3BY3 to encode a 'blink code' of red, green, and blue flash counts.
#define GET_BLINK_MAP_COLOR(code, color)   GET_MAP3BY3(code,2-(color))
 Access the color flash counts encoded by BLINK_MAP.
Fast u32 Comparisons Handling Rollover
#define IS_EARLIER(a, b)   ((((u32)(a))-((u32)(b))) > 0x80000000UL)
 Functions like millis() and micros() can be tricky to use robustly.
#define IS_LATER_OR_EQUAL(a, b)   ((((u32)(a))-((u32)(b))) < 0x80000000UL)
 a after or same as b, with wraparound; see IS_EARLIER.
#define IS_LATER(a, b)   ((((u32)(b))-((u32)(a))) > 0x80000000UL)
 a after b, with wraparound; see IS_EARLIER.
#define IS_EARLIER_OR_EQUAL(a, b)   ((((u32)(b))-((u32)(a))) < 0x80000000UL)
 a before or same as b, with wraparound; see IS_EARLIER.
#define IS_EARLIER16(a, b)   ((u16)(((u16)(a))-((u16)(b))) > 0x8000UL)
 a before b, with wraparound, for u16 values; see IS_EARLIER
#define IS_LATER_OR_EQUAL16(a, b)   ((u16)(((u16)(a))-((u16)(b))) < 0x8000UL)
 a after or same as b, with wraparound, for u16 values; see IS_EARLIER.
#define IS_LATER16(a, b)   ((u16)(((u16)(b))-((u16)(a))) > 0x8000UL)
 a after b, with wraparound, for u16 values; see IS_EARLIER.
#define IS_EARLIER_OR_EQUAL16(a, b)   ((u16)(((u16)(b))-((u16)(a))) < 0x8000UL)
 a before or same as b, with wraparound, for u16 values; see IS_EARLIER.
#define IS_EARLIER8(a, b)   ((u8)(((u8)(a))-((u8)(b))) > 0x80UL)
 a before b, with wraparound, for u8 values; see IS_EARLIER
#define IS_LATER_OR_EQUAL8(a, b)   ((u8)(((u8)(a))-((u8)(b))) < 0x80UL)
 a after or same as b, with wraparound, for u8 values; see IS_EARLIER.
#define IS_LATER8(a, b)   ((u8)(((u8)(b))-((u8)(a))) > 0x80UL)
 a after b, with wraparound, for u8 values; see IS_EARLIER.
#define IS_EARLIER_OR_EQUAL8(a, b)   ((u8)(((u8)(b))-((u8)(a))) < 0x80UL)
 a before or same as b, with wraparound, for u8 values; see IS_EARLIER.
Miscellaneous macro hackery
#define STRUCT_MEMBER_OFFSET(structure, member)   ((uptr) &(((structure *) 0)->member))
 Find the offset of a particular member within some structure.
#define XSTR(arg)   STR(arg)
 The (now) traditional, but still disgusting, two-level stringification song and dance to stringify an expansion result, using XSTR and STR.
#define STR(arg)   #arg
 The (now) traditional, but still disgusting, two-level stringification song and dance to stringify an expansion result, using XSTR and STR.
#define MIN(a, b)   (((a)<(b))?(a):(b))
 The traditional minimum value macro.
#define MAX(a, b)   (((a)>(b))?(a):(b))
 The traditional maximum value macro.
#define FILEPOS   __FILE__ ":" XSTR(__LINE__)
 FILEPOS yields the current position in the source code as a "SFBMacros.h:63"-style string.

Operations on SFB face codes.

These macros are generally only valid for the "physical faces" like NORTH - WEST

#define CLOCKWISE_FACE(dir)   GET_MAP4BY2(MAP4BY2(EAST,WEST,SOUTH,NORTH),dir)
 Maps N->E, S->W, E->S, W->N.
#define COUNTERCLOCKWISE_FACE(dir)   GET_MAP4BY2(MAP4BY2(WEST,EAST,NORTH,SOUTH),dir)
 Maps N->W, S->E, E->N, W->S.
#define ANTICLOCKWISE_FACE(dir)   COUNTERCLOCKWISE_FACE(dir)
#define OPPOSITE_FACE(dir)   GET_MAP4BY2(MAP4BY2(SOUTH,NORTH,WEST,EAST),dir)
 Maps N->S, S->N, E->W, W->E.
#define FACE_NAME(face)   (faceNames[face])
 Maps N,S,E,W -> "North","South","East","West".
#define FACE_CODE(face)   GET_MAP4BY8(MAP4BY8('N','S','E','W'),face)
 Maps N,S,E,W -> 'N','S','E','W'.
#define FACE_NUMBER_FROM_CODE(code)   (((((code)&~0x20)^(((code)&~0x20)>>1))-1)&0x3)
 Maps 'N','n'->NORTH, 'S','s'->SOUTH, 'E','e'->EAST, 'W','w'->WEST.
#define IS_FACE_CODE(code)
 'N','n','S','s','E','e','W','w'->1,everything else-> 0
const char *const faceNames []


Detailed Description

Various utility macro definitions.

Author:
David H. Ackley.
Date:
(C) 2008 All rights reserved.
Code License:
The GNU Lesser General Public License
License Note:
All code samples shown in documentation are placed into the public domain.

Define Documentation

#define B36_6 ( a,
b,
c,
d,
e,
 )     (B36_5(a,b,c,d,e)*36u+B36_1(f))

A length 6 base 36 constant.

(Note: Some argument combinations are invalid)

#define B36_7 ( a,
b,
c,
d,
e,
f,
 )     (B36_6(a,b,c,d,e,f)*36u+B36_1(g))

A length 7 base 36 constant.

(Note: Argument 'a' must be 0 to have even a chance of this producing a valid constant. Why does this macro exist?)

#define BIT_PAIR_AT_POSITION ( bits,
newValue,
position   )     ((bits) = ((bits)&(~(3<<(position))))|((newValue)<<(position)))

Set a consecutive pair of bits in bits, located at position, to value newValue.

newValue must be in the range of 0 to 3 for correct operation.

Returns:
the modified value of bits.
Example:
    ...
     u32 num = 0;                    // num: ...000000 binary
     BIT_PAIR_AT_POSITION(num,3,1);  // num: ...000110 binary
     println(num);                   // prints 6
     BIT_PAIR_AT_POSITION(num,2,2);  // num: ...001010 binary
     println(num);                   // prints 10
   ...

#define BLINK_MAP ( red,
green,
blue   )     MAP3BY3(blue,green,red)

Use a MAP3BY3 to encode a 'blink code' of red, green, and blue flash counts.

BLINK_MAP puts red at the left of the map, so that any BLINK_MAP with red less than 4 will yield a constant that fits in 8 bits -- which the compiler will be able to generate in one instruction via an immediate operand, avoiding a memory reference.

Parameters:
red number of red flashes, 0 to 7
green number of green flashes, 0 to 7
blue number of blue flashes, 0 to 7
Example:
    ...
     API_ASSERT(foo<bar,BLINK_MAP(0,2,1));  // Die blinking 0,2,1 (a sketch custom code), unless foo < bar
   ...

#define CLEAR_BIT ( value,
bitNum   )     ((value) &= ~(1<<(bitNum)))

Clear bit bitNum in value.

Example:
    ...
     u32 num = 3;      // I.e., 11 in binary
     CLEAR_BIT(num,0); // Num is now 10 in binary
     println(num);     // Prints 2
   ...

#define GET_BIT ( value,
bitNum   )     (((value)>>(bitNum))&1)

Access bit bitNum in value.

Returns:
1 if the specified bit is set, else 0
Example:
    ...
     u32 num = 2;      // I.e., 11 in binary
     println(GET_BIT(num,1));     // Prints 1 since bit 1 of binary 10 is set
     println(GET_BIT(num,3));     // Prints 0 since bit 3 of binary 10 is clear
   ...

#define GET_BLINK_MAP_COLOR ( code,
color   )     GET_MAP3BY3(code,2-(color))

Access the color flash counts encoded by BLINK_MAP.

Parameters:
code The value created by BLINK_MAP
color The color to access, either 0==RED, 1==GREEN, or 2==BLUE
Example:
    ...
     u32 map = BLINK_MAP(2,0,4);   // Create a blink map
     println(GET_BLINK_MAP_COLOR(map,0));    // prints 2
     println(GET_BLINK_MAP_COLOR(map,1));    // prints 0
     println(GET_BLINK_MAP_COLOR(map,2));    // prints 4
   ...

#define GET_MAP3BY3 ( map,
idx   )     (((map)>>((idx)*3))&0x7)

Access the values encoded by MAP3BY3.

Parameters:
map The value created by MAP3BY3
idx The array index to access, from 0 to 2
Example:
    ...
     u32 num = MAP3BY3(2,0,4);   // Create a 3 by 3 SCAM
     println(GET_MAP3BY3(num,0));    // prints 2
     println(GET_MAP3BY3(num,1));    // prints 0
     println(GET_MAP3BY3(num,2));    // prints 4
   ...

#define GET_MAP4BY2 ( map,
idx   )     (((map)>>((idx)<<1))&0x3)

Access the values encoded by MAP4BY2.

Parameters:
map The value created by MAP4BY2
idx The array index to access, from 0 to 3
Example:
    ...
     u32 num = MAP4BY2(1,2,3,3);     // Create a 4 by 2 SCAM
     println(GET_MAP4BY2(num,0));    // prints 1
     println(GET_MAP4BY2(num,1));    // prints 2
     println(GET_MAP4BY2(num,2));    // prints 3
     println(GET_MAP4BY2(num,3));    // prints 3
   ...

#define GET_MAP4BY4 ( map,
idx   )     (((map)>>((idx)<<2))&0xf)

Access the values encoded by MAP4BY4.

Parameters:
map The value created by MAP4BY4
idx The array index to access, from 0 to 3
Example:
    ...
     u32 num = MAP4BY4(9,7,2,0xf);   // Create a 4 by 4 SCAM
     println(GET_MAP4BY4(num,0));    // prints 9
     println(GET_MAP4BY2(num,1));    // prints 7
     println(GET_MAP4BY2(num,2));    // prints 2
     println(GET_MAP4BY2(num,3));    // prints 15
   ...

#define GET_MAP4BY8 ( map,
idx   )     (((map)>>((idx)<<3))&0xff)

Access the values encoded by MAP4BY8.

Parameters:
map The value created by MAP4BY8
idx The array index to access, from 0 to 3
Example:
    ...
     u32 num = MAP4BY8(0x12,' ',99,127);   // Create a 4 by 8 SCAM
     println(GET_MAP4BY8(num,0));    // prints 18
     println(GET_MAP4BY8(num,1));    // prints 32 (ASCII value of the space ' ' char)
     println(GET_MAP4BY8(num,2));    // prints 99
     println(GET_MAP4BY8(num,3));    // prints 127
   ...

#define IS_EARLIER ( a,
 )     ((((u32)(a))-((u32)(b))) > 0x80000000UL)

Functions like millis() and micros() can be tricky to use robustly.

It's not too hard to write code like:

      u32 end = millis()+1000; // Compute the value of millis() 1 second from now
      ..prepare..              // Take some time preparing to work..
      while (millis() < end) { // ..then while there's still time in this second [[WARNING!  CONTAINS ERROR!]]
        ..work..               // ..do some low-priority work
      }

which seems very safe, and will indeed work correctly most of the time. But suppose the prepare step might sometimes take more than one second? You might answer "So what? Then the while loop will just quit immediately, because millis() is already later than end so there's no time left to work."

Indeed. But, just suppose your sketch has already been running for a long long time. After about 49 days, the total number of elapsed milliseconds exceeds the maximum possible value of a u32! When that happens, millis() "rolls over" back to zero! So a terrible possibility arises. Suppose:

  1. As the code is entered, millis() happens to be very large, but millis()+1000 doesn't quite roll over, so end gets a very large value, and
  2. the prepare step runs overtime by enough that millis() then does roll over, and so begins returning very small values. That means
  3. the while loop will then perform its low-priority work, not for less than a second, but for the next 49 days!

(If you can't even dream of your sketch running for six weeks solid, well, you be the judge. Still, one might consider dreaming bigger -- or consider micros(), which rolls over about every 70 minutes. And either way, the fix is sweet; read on.)

The fundamental problem, given that counters will eventually roll over, is that '<' doesn't quite capture the most useful notion of 'earlier' or 'before'. In the above example, if end is very large and millis() is very small, the most sensible interpretation is that millis() has wrapped and is therefore 'later' than or 'after' end, even though in that case millis() is numerically less than end.

And we could try to fix our code along those lines, saying that "< means earlier" unless some added special-case code decides that a wraparound has occurred. But, it turns out, there's a better, faster, and cleaner way to do it.

With two values a and b referenced to the same rollover counter, what we'd really like to know is: Would the counter count from a to b quicker than b to a, considering rollovers? If counting from a to b is shorter, then we're better off saying a is earlier than b.

And that's exactly the comparison the IS_EARLIER macro makes.

And, it does it wicked fast: The comparison itself is typically just three ARM assembly language instructions. If IS_EARLIER(a,b) is true, then it takes less counting-ups-with-possible-wrapping to go from a to b than b to a, so we assume a is earlier than b. Now, in general that assumption could be wrong, but in any particular case if we know our millis() operands are less than about 24 days apart (or micros() operands are less than about a half hour apart), then we are golden.

Our resulting code, hardly changed but now satisfyingly robust, looks like this:

      u32 end = millis()+1000; // Compute the value of millis() 1 second from now
      ..prepare..              // Take some time preparing to work..
      while (IS_EARLIER(millis(),end)) { // ..then while there's still time in this second
        ..work..               // ..do some low-priority work
      }
and it will work as desired so long as the prepare step definitely finishes in less than about 24 days.
Examples:
sdcard2.cpp, and speed4.cpp.

#define IS_EARLIER_OR_EQUAL ( a,
 )     ((((u32)(b))-((u32)(a))) < 0x80000000UL)

a before or same as b, with wraparound; see IS_EARLIER.

#define IS_EARLIER_OR_EQUAL16 ( a,
 )     ((u16)(((u16)(b))-((u16)(a))) < 0x8000UL)

a before or same as b, with wraparound, for u16 values; see IS_EARLIER.

#define IS_EARLIER_OR_EQUAL8 ( a,
 )     ((u8)(((u8)(b))-((u8)(a))) < 0x80UL)

a before or same as b, with wraparound, for u8 values; see IS_EARLIER.

#define IS_FACE_CODE ( code   ) 

Value:

(((code)&~0x20)=='N'||   \
   ((code)&~0x20)=='S'||   \
   ((code)&~0x20)=='E'||   \
   ((code)&~0x20)=='W')
'N','n','S','s','E','e','W','w'->1,everything else-> 0

#define IS_LATER ( a,
 )     ((((u32)(b))-((u32)(a))) > 0x80000000UL)

a after b, with wraparound; see IS_EARLIER.

#define IS_LATER16 ( a,
 )     ((u16)(((u16)(b))-((u16)(a))) > 0x8000UL)

a after b, with wraparound, for u16 values; see IS_EARLIER.

#define IS_LATER8 ( a,
 )     ((u8)(((u8)(b))-((u8)(a))) > 0x80UL)

a after b, with wraparound, for u8 values; see IS_EARLIER.

#define IS_LATER_OR_EQUAL ( a,
 )     ((((u32)(a))-((u32)(b))) < 0x80000000UL)

a after or same as b, with wraparound; see IS_EARLIER.

#define IS_LATER_OR_EQUAL16 ( a,
 )     ((u16)(((u16)(a))-((u16)(b))) < 0x8000UL)

a after or same as b, with wraparound, for u16 values; see IS_EARLIER.

#define IS_LATER_OR_EQUAL8 ( a,
 )     ((u8)(((u8)(a))-((u8)(b))) < 0x80UL)

a after or same as b, with wraparound, for u8 values; see IS_EARLIER.

#define MAP3BY3 ( a,
b,
 )     ((((((u16) c)<<3)|(b))<<3)|(a))

Encode 3 numbers each 3 bits long.

The primary use of such 3 by 3 maps is for efficiently storing and accessing the 'blink codes' displayed when errors occur; see BLINK_MAP and SFBErrors.h .

These macros (MAP3BY3, MAP4BY2, MAP4BY4, MAP4BY8) encode a small array of small numbers into a single constant value -- a Small Constant Array Map (SCAM) -- which can be accessed and stored with relatively little code and memory. They come in matched pairs -- a MAPxBYy to make a SCAM, and a GET_MAPxBYy to access it. In such pairings, the x is the number of associations in the map, and the y is number of bits in each mapped value.

In all cases it is the programmer's responsibility to ensure that all arguments passed to these macros are in range for the sizes involved; the macros do no error checking. Note also that if any of the arguments to a MAPxBYy macro are not compile-time constants, there are likely no efficiency gains, and it is probably not worth using these macros, in that context, at all.

Parameters:
a first argument becomes index 0 in the map
b second argument becomes index 1 in the map
c third argument becomes index 2 in the map
Example:
    ...
     u32 num = MAP3BY3(2,0,4);   // Create a 3 by 3 SCAM
     println(GET_MAP3BY3(num,0));    // prints 2
     println(GET_MAP3BY3(num,1));    // prints 0
     println(GET_MAP3BY3(num,2));    // prints 4
   ...

#define MAP4BY2 ( a,
b,
c,
 )     ((((((((u8) d)<<2)|(c))<<2)|(b))<<2)|(a))

Encode 4 numbers each 2 bits long, see MAP3BY3 for background.

Parameters:
a first argument becomes index 0 in the map
b second argument becomes index 1 in the map
c third argument becomes index 2 in the map
d fourth argument becomes index 3 in the map
Example:
    ...
     u32 num = MAP4BY2(1,2,3,3);     // Create a 4 by 2 SCAM
     println(GET_MAP4BY2(num,0));    // prints 1
     println(GET_MAP4BY2(num,1));    // prints 2
     println(GET_MAP4BY2(num,2));    // prints 3
     println(GET_MAP4BY2(num,3));    // prints 3
   ...

#define MAP4BY4 ( a,
b,
c,
 )     ((((((((u16) d)<<4)|(c))<<4)|(b))<<4)|(a))

Encode 4 numbers each 4 bits long, see MAP3BY3 for background.

Parameters:
a first argument becomes index 0 in the map
b second argument becomes index 1 in the map
c third argument becomes index 2 in the map
d fourth argument becomes index 3 in the map
Example:
    ...
     u32 num = MAP4BY4(9,7,2,0xf);   // Create a 4 by 4 SCAM
     println(GET_MAP4BY4(num,0));    // prints 9
     println(GET_MAP4BY2(num,1));    // prints 7
     println(GET_MAP4BY2(num,2));    // prints 2
     println(GET_MAP4BY2(num,3));    // prints 15
   ...

#define MAP4BY8 ( a,
b,
c,
 )     ((((((((u32) d)<<8)|(c))<<8)|(b))<<8)|(a))

Encode 4 numbers each 8 bits long, see MAP3BY3 for background.

Parameters:
a first argument becomes index 0 in the map
b second argument becomes index 1 in the map
c third argument becomes index 2 in the map
d fourth argument becomes index 3 in the map
Example:
    ...
     u32 num = MAP4BY8(0x12,' ',99,127);   // Create a 4 by 8 SCAM
     println(GET_MAP4BY8(num,0));    // prints 18
     println(GET_MAP4BY8(num,1));    // prints 32 (ASCII value of the space ' ' char)
     println(GET_MAP4BY8(num,2));    // prints 99
     println(GET_MAP4BY8(num,3));    // prints 127
   ...

#define MAX ( a,
 )     (((a)>(b))?(a):(b))

The traditional maximum value macro.

This is unsafe because it evaluates one of its arguments twice, so it must not be used with arguments that have side-effects.

Returns:
the larger of its two arguments

#define MIN ( a,
 )     (((a)<(b))?(a):(b))

The traditional minimum value macro.

This is unsafe because it evaluates one of its arguments twice, so it must not be used with arguments that have side-effects.

Returns:
the smaller of its two arguments

#define REGISTER_OFFSET ( baseAddress,
byteOffset   )     (*((uv32 *) (((u32)(baseAddress))+(byteOffset))))

Access a 32 bit H/W register.

Access given a base address and a BYTE COUNT offset, (which must be a multiple of four or you'll be making an unaligned access).

#define SET_BIT ( value,
bitNum   )     ((value) |= (1<<(bitNum)))

Set bit bitNum in value.

Example:
    ...
     u32 num = 0;
     SET_BIT(num,3);
     println(num);     // Prints 8 (since that's 1000 in binary)
   ...

#define STRUCT_MEMBER_OFFSET ( structure,
member   )     ((uptr) &(((structure *) 0)->member))

Find the offset of a particular member within some structure.

Sometimes it is necessary or helpful to know how for 'into' a given struct or class some particular member is located. STRUCT_MEMBER_OFFSET produces a non-negative u32 giving the offset to that member from the beginning of the structure, in bytes.

Example:
   struct Foo {                                // Some random struct..
     u8 title[17];
     u8 type;
     u32 value;
   };
   ...
     println(STRUCT_MEMBER_OFFSET(Foo,type));  // Prints 17.  'title' takes 17 bytes, which land at 
                                               // offsets 0..16, and then 'type' immediately follows.

#define TEST_BIT ( value,
bitNum   )     ((value)&(1<<(bitNum)))

Check if bit bitNum in value is set.

Typically produces slightly faster code, compared to GET_BIT, when bitNum is a constant.

Returns:
0 if the specified bit is clear, else a non-zero value (not necessarily 1)
Example:
    ...
     u32 num = 2;      // I.e., 10 in binary
     if (TEST_BIT(num,1)) println("Yes"); else println("No"); // prints Yes
   ...


Generated on Fri Apr 22 06:55:54 2011 for SFB by doxygen 1.5.9