0

So I'm playing with a TFT screen and trying to understand the colourspace encoding. I wrote a quick for loop to show colours from 0 to FFFF and to print the value of colour being displayed:

for (int q=0; q<0xFFFF; q+=0x80) {
  tft.fillScreen(q);
  tft.setCursor(0, 0); tft.println(q, HEX);
  delay(2);
}

I was surprised to find values greater than FFFF being displayed - which suggest that int is more than 16 bits. It's running on a Uno.

What has happened?

(PS I now understand RGB565 encoding, so this is off-topic)

Socco
  • 1
  • 1
    Socco, Shall we close this question? Next time start by telling us which tft screen you have and that you are using the adafruit gfx library and if possible show a working sketch. The tft.fillScreen has a unsigned 16-bits parameter. A value above 0xFFFF rolls over and starts from 0x0000 again. – Jot Oct 11 '18 at 00:28

1 Answers1

1

I guess you're seeing some big numbers starting with FFFF...?

What you are seeing is not big numbers - it's misrepresented numbers.

You have an int. That's not a "16-bit number", it's a 15-bit number plus a sign bit.

When you print it the variable is promoted to a long and the sign bit is extended.

That long is then further mapped (cast) into an unsigned long to print it as hexadeximal (there is no negative in the hexadecimal representation on Arduino), and that extended sign bit is seen as a string of F.

For example, the value 0xABCD stored in an int is:

 1 010 1011 1100 1101

I broke off the first bit because that is the sign bit in a signed integer. The actual decimal value of that is -21555.

Now when that gets cast to a long the sign extension copies the leading sign bit to all the other 16 bits to the left of it, resulting in:

1 111 1111 1111 1111 1010 1011 1100 1101

Because of the way that twos complement works, that string of bits still represents -21555 in decimal.

However, cast it to unsigned long for printing as HEX and you can see how you would end up with some big numbers. It would give you:

FFFFABCD

So you can see that a 16 bit signed value can end up being printed as 8 hex digits, and all because of the way the print() function in the Arduino API works.

When working with unsigned values you really should be working with an unsigned variable - especially if those unsigned values (0 - 65535) fall outside the range of the signed variable type (-32768 - 32767). Switch to using uint16_t and you will be able to both store and represent the values correctly.


You might find it useful playing around with this site to learn how different variable types represent and store the data within them as binary.

Majenko
  • 105,095
  • 5
  • 79
  • 137
  • Thank you for your detailed explanation @Majenko - quite informative for me. (1) However the display does not show leading FFFFFs - for example it now shows 26C E000 . (2) I guess the for loop will never exit because 0xFFFF will always be greater than the evaluation of max signed int =0x7FFF - (3) But this still does not explain why the display is showing numbers greater than 16 bit capacity, which suggests the print command is being given a number greater than 16 bits. (4) The Uno is a Chinese clone received with other hardware - so maybe this is relevant? – Socco Oct 11 '18 at 02:03
  • It won't be because it's a chinese clone - it's still the same software running on the same processor - even if it is one from the rejects bin. You loop certainly will never end. You should change to an unsigned value that is larger than your maximum loop value. Use uint32_t instead for your loop, then cast it to uint16_t for your colour value. – Majenko Oct 11 '18 at 08:14