unsigned difference

Hello all. I just came across some code involving a time difference, and also involving 'unsigned long' values ---- and I notice an 'AND' operation --- namely : & 0XFFFFL

It has a comment next to it, that says //get unsigned difference.

The line of code is: unsigned long difference = (now - previous) & 0xFFFFL ;

Can somebody help explain the importance (significance) of the "& 0xFFFFL" ? Just trying to understand and learn only.

Thanks very much in advance!

https://forum.arduino.cc/index.php?topic=229667.0

 // then update the long counter
unsigned long difference = (now - previous) & 0xFFFFL ;  // get unsigned difference

Full code:

unsigned long prev_accurate_time = 0L ;
unsigned long total_count = 0L ;
unsigned long prev_count = 0L ;
unsigned long previous_tick = 0L ;

unsigned int previous = 0 ;

void loop ()
{
  // first perform observation
  unsigned int now = TCNT1 ;
  unsigned long accurate_time = micros () ;

  // then update the long counter
  unsigned long difference = (now - previous) & 0xFFFFL ;  // get unsigned difference
  previous = now ;
  total_count += difference ;

  // check for time passing
  if (millis () - previous_tick >= 1000L)
  {
    previous_tick += 1000L ; // setup for next second.

    // calculate accurate values for the approximate 1s interval, pass to be displayed
    display (total_count - prev_count,
                 accurate_time - prev_accurate_time) ;

    prev_accurate_time = accurate_time ;  // update for next second
    prev_count = total_count ;


  }
}

It is throwing away all but the lowest 16 bits of the difference.

Regards,
Ray L.

now and previous are 16 bit variables on a standard Arduino.

RayL and Jrem ........ thanks very much! Genuinely appreciated!

You might try removing the &0xFFFFL to see if it makes a difference.

I don't know exactly how the compiler handles the promotion of 16 bit to 32 bit integers, and it might be that the extra operation prevents the sign bit (if set, for a negative difference) from being propagated and filling bits 16-31 of the long integer.

Edit: Scratch that idea.

void setup() {
Serial.begin(9600);
unsigned int a=0;
unsigned int b=1;
unsigned long c=0;
c = (a-b)&0xFFFFL;
Serial.println(c);  //prints 65535
c = (a-b);  
Serial.println(c); //prints 65535
}

void loop() {}
unsigned long difference = (now - previous) & 0xFFFFL ;  // get unsigned difference

1. Given the following declarations:

unsigned int now;     //variable 'now' can hold a value from 0 to 65535 (0x0000 to 0xFFFF); 16-bit positive
unsigned int previous = 0;  //same as variable 'now'

unsigned long difference; //'difference' will hold 32-bit data (always positive) from 0 to 4294967295
//(0x00000000 to 0xFFFFFFFF); 0x refers to hexadecimal base

2. The value of the variable 'now' comes from TCNT1 which can hold an unsigned (always positive) number from 0 to 65535 (0x0000 to 0xFFFF). Let us assume that the current content of TCNT1 is 0x8765 (34681) and previous = 0 (0x0000).

3. Let us compute the difference between 'now' and 'previous'.

unsigned int y = now - previous
==> y = 0x8765 - 0x0000
==> y = 0x8765 (decimal 34681)
==> y = 0b1000011101100101   (0b refers to binary base)

4. Let us retain all the bits of y of Step-3 by making bit-wise AND (&) with 1111111111111111 (0xFFFF)

==> y = y & 0xFFFF
==> y = 0b1000 0111 0110 0101 & 0b1111 1111 1111 1111 
==> y = 0b1000 0111 0110 0101  (unsigned int)
==> y = 0x8765

5. Let us keep the 'unsigned 16-bit' value of y of Step-4 in an 'unsigned 32-bit' variable named difference. How do we do it?
(1) Enlarge the storage size of y from 16-bit to 32-bit by placing this text '(unsigned long)' before y. This is known as casting. (2) And then store this: '(unsigned long)y' into the variable 'difference'.

unsigned long difference = (unsigned long)y;
==>unsigned long difference = (unsigned long)y & 0xFFFF; //going backward
==>unsigned long difference = (unsigned long)(now-previous) & 0xFFFF;  //going backward
==>unsigned long difference = (now-previous) & 0xFFFFUL;    //UL (not L) is a casting and replaces (unsigned long)