C - How do I receive a bit from a bit field as a parameter in a function?

I have a bit field defined like that (it is from a microcontroller library, so it looks a bit different):

typedef union {
    byte Byte;
    struct {
        byte PTAD0       :1;
        byte PTAD1       :1;                                       
        byte PTAD2       :1;
        byte PTAD3       :1;
        byte PTAD4       :1;
        byte PTAD5       :1;
        byte             :1;
        byte             :1;
    } Bits;
} PTADSTR;
extern volatile PTADSTR _PTAD @0x00000000;
#define PTAD                            _PTAD.Byte
#define PTAD_PTAD0                      _PTAD.Bits.PTAD0
#define PTAD_PTAD1                      _PTAD.Bits.PTAD1
#define PTAD_PTAD2                      _PTAD.Bits.PTAD2
#define PTAD_PTAD3                      _PTAD.Bits.PTAD3
#define PTAD_PTAD4                      _PTAD.Bits.PTAD4
#define PTAD_PTAD5                      _PTAD.Bits.PTAD5

So. Let's say that i want a function that sets a bit, like that:

void setbit(bit Bit) {
     Bit = 1;
}

Of course, the "bit" declaration doesn't work. I would like a declaration that I could use

setbit(PTAD_PTAD5)

and it would set this bit. I could do

void setbit(byte Byte, byte number) {
     Byte |= 1<<(number);
}

and send

setbit(PTAD,5);

That works perfectly, but... that's not what I want, cause I want to do something like Arduino's libraries. Anyone has any idea how to do that in the way I prefered?

Upvotes: 3

Views: 3027

Answers (4)

Pelle
Pelle

Reputation: 1252

How about this? Using the static const qualifier should make sure the memory overhead is about zero

typedef struct
{
    uint8_t* reg;
    uint8_t bitnum;
}bit;

void setbit(bit b)
{
    *b.reg |= (1 << b.bitnum);
}

void clrbit(bit b)
{
    *b.reg &= ~(1 << b.bitnum);
}

static const bit PTAD_PTAD0 = {&PTAD, 0};
static const bit PTAD_PTAD1 = {&PTAD, 1};
static const bit PTAD_PTAD2 = {&PTAD, 2};
static const bit PTAD_PTAD3 = {&PTAD, 3};
static const bit PTAD_PTAD4 = {&PTAD, 4};
static const bit PTAD_PTAD5 = {&PTAD, 5};
static const bit PTAD_PTAD6 = {&PTAD, 6};
static const bit PTAD_PTAD7 = {&PTAD, 7};

int main()
{
    printf("PTAD: %02X\n", PTAD);
    setbit(PTAD_PTAD0);
    printf("PTAD: %02X\n", PTAD);
    clrbit(PTAD_PTAD0);
    printf("PTAD: %02X\n", PTAD);

}

Upvotes: 0

Kninnug
Kninnug

Reputation: 8053

Because you can access the bits in your bitfield individually setting a bit is very easy:

_PTAD_PTAD5 = 1;

which would, thanks to the #define _PTAD_PTAD5, evaluate to

_PTAD.Bits.PTAD5 = 1;

Note that due to C being a pass-by-value language,

void setBit(bit Bit){
    Bit = 1;
}

doen't do what you expect. Instead it sets the (function-)local variable Bit to one, leaving the variable you send to it unchanged.

Normally you'd use a pointer to a variable you want to change in a function, but because you can't take the address of a bit in a bitfield you can't do that in this case.

Upvotes: 2

Carl Norum
Carl Norum

Reputation: 225082

  1. C is a pass-by-value language, so even if you could do:

    void setbit(bit Bit) {
         Bit = 1;
    }
    

    it would be a no-op.

  2. You can do what you're trying with a function-like-macro:

    #define setbit(x) do { (x) = 1; } while(0)
    

    If you call this macro with PTAD_PTAD5, it should work like you expect.

Upvotes: 3

Michael Dorgan
Michael Dorgan

Reputation: 12515

In C, I do not believe it is possible to access a bitfield as an array. One idea would be to pass in a enumerated type or constant and switch off its value into 8 different set functions. Not the cleanest way, but I believe it would work.


#define PTAD5  5
...

void setbit(PTADSTR byte, int bit)
{
    switch(bit)
    {
        ...
        case PTAD5  : byte.PTAD5 = 1; break;
        default: ASSERT_ALWAYS(); break;
    }
}

Upvotes: 0

Related Questions