I want to directly modify a bit in a byte.
In GCC, you can do it as follow:
struct virtualByte {
unsigned char b0 : 1;
unsigned char b1 : 1;
unsigned char b2 : 1;
unsigned char b3 : 1;
unsigned char b4 : 1;
unsigned char b5 : 1;
unsigned char b6 : 1;
unsigned char b7 : 1;
} __attribute__((__packed__));
#define sbit(_byte, _pos) (((volatile struct virtualByte *)&_byte)->b ## _pos)
Usage:
unsigned char myByte = 0x00;
#define firstBit sbit(myByte, 0)
firstBit = 1; // Implicit myByte |= 0x01;
To make things neater I want to have class that does this for me. I came up with the following concept:
unsigned char myByteRef = 0x00;
Byte myByte(&myByteRef);
myByte[0] = 1; // Implicit myByteRef |= 0x01;
fprintf(stderr, "%2.2X\n", myByteRef);
But this does not work because in c++ you cannot return a reference to a single bit. Overloading the constructor does not work either.
Is there a possibility to implement such behaviour? The assignment operator should directly modify its underlying byte (not a set of bytes).
Finally came to a solution, many thanks to @doc!
My solution:
class Bit {
private:
volatile uint8_t *byte;
uint8_t bitPos;
public:
Bit(void)
{
}
void init(volatile uint8_t *const byte, uint8_t const bitPos)
{
this->byte = byte;
this->bitPos = (bitPos > 7u ? 7u : bitPos);
}
void setValue(bool const bitValue)
{
if (!this->byte) return;
if (bitValue) {
*this->byte |= (1u << this->bitPos);
} else {
*this->byte &= ~(1u << this->bitPos);
}
}
};
class BitReference {
private:
Bit &ref;
public:
BitReference(Bit &ref) : ref(ref)
{
}
void operator=(bool const bitValue)
{
this->ref.setValue(bitValue);
}
};
class Byte {
private:
Bit bits[8];
public:
Byte(volatile uint8_t *const byte)
{
for (unsigned i = 0; i < 8; ++i) {
this->bits[i].init(byte, i);
}
}
/* This did the trick :)! */
BitReference operator[](size_t index)
{
if (index > 7) index = 7;
return BitReference(this->bits[index]);
}
};
Usage:
uint8_t myPort = 0x00;
int main(int const argc, const char **const argv)
{
Byte abc(&myPort);
abc[0] = 1;
abc[1] = 1;
abc[2] = 1;
abc[3] = 1;
fprintf(stderr, "%2.2X\n", myPort);
return 0;
}