Adding / Bitwise or

Hello,

I can't seem to get my head around this.

//Let's say we have a stored byte but it can only have a value between 0-15 by default
uint8_t storedByte = 0;

//we have another variable which is intended to be stored on the upper bits of storedByte  with reduced precision
uint8_t variable = 0;

//first limit previously stored value to be sure
//if (storedByte > 15)
//{
//  storedByte = 15;
//}
storedByte &= 0x0F;

//also limit variable for the available bits
if (variable > 150)
{
  variable = 150;
}

storedByte += (uint8_t)((float)variable * 0.1f) << 4;

//Bitwise Or results the same value in every case??

storedByte |= (uint8_t)((float)variable * 0.1f) << 4;

Thanks in advance.

No. Addition has carry:

0b00001010 (10 decimal)
0b00000110 (6 decimal)
0b00001010 + 0b00000110 = 0b00010000 (16 decimal)
0b00001010 | 0b00000110 = 0b00001110 (14 decimal)

If "storredByte" is ALWAYS zero before the operation, addition and 'or' will produce the same result.

using the floating point math is absolutely nonsense in case of bitwise operations and must be avoided.

It should be writen as

storedByte |= ((variable /10) << 4) & 0xF0;

bitwise & with 0xF0 will clear the result from all bits except the upper half of the byte

If "storredByte" is ALWAYS zero before the operation, addition and 'or' will produce the same result.

Got it. But what if it was made sure that "storedByte" has 0 on the upper 4 bits?
(Sorry I added that later)

I used float because rounding was on my mind, but forgot to add it.
storedByte |= (round(variable * 0.1f) << 4) & 0xF0;

bitwise & with 0xF0 will clear the result from all bits except the upper half of the byte
That's a good hint.

Also

if (storedByte > 15)
{
  storedByte = 15;
}

could become

storedByte &= 0x0F;

Float binary structure is

590px-Float_example.svg

When you round result you still have float. What happens when you shift it left 4 position, what exactly do you expect to happen?

It should be long, if I understand correctly from Arduino.h file:

#define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

consider

 c '1' 0x31, b 0x01, storedByte 0x10
 c '2' 0x32, b 0x02, storedByte 0x21
 c 'a' 0x61, b 0x0a, storedByte 0xa2
 c 'b' 0x62, b 0x0b, storedByte 0xba
 c 'c' 0x63, b 0x0c, storedByte 0xcb
 c 'g' 0x67, b 0x00, storedByte 0x0c
 c 'h' 0x68, b 0x01, storedByte 0x10
 c 'j' 0x6a, b 0x03, storedByte 0x31
unsigned int storedByte;
byte b;
char s [80];

void loop () {
    if (Serial.available ())  {
        char c = Serial.read ();

        if ('a' <= c)
            b = 10 + c - 'a';
        else if ('0' <= c)
            b = c - '0';

        if (b > 0x0F)
            b &= 0x0F;

        storedByte >>= 4;
        storedByte  |= b << 4;

        sprintf (s, " c '%c' 0x%02x, b 0x%02x, storedByte 0x%02x",
                            c, c, b, storedByte);
        Serial.println (s);
    }
}

// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);
}

That is only true if 'storedByte' is either <=15 or ==16. If 'storredByte' is 33 (0x21) then the first one would set 'storedByte' to 15 (0x0F) and the second would set 'storedByte' to 1 (0x01). Not the same.

if would set it to 0 not 15 as 16 is 0b10000

You're right. My mistake.

Oof, a non-standard Arduino-only definition of round. The standard C++ round function returns the same type that was passed in (e.g., float -> float or double -> double, though float and double are treated the same on the 8-bit Arduini).