{"id":3135,"date":"2026-07-28T02:35:36","date_gmt":"2026-07-28T02:35:36","guid":{"rendered":"https:\/\/cml-a.com\/content\/?p=3135"},"modified":"2026-07-28T04:56:20","modified_gmt":"2026-07-28T04:56:20","slug":"the-colors-are-wrong-but-how","status":"publish","type":"post","link":"https:\/\/cml-a.com\/content\/2026\/07\/28\/the-colors-are-wrong-but-how\/","title":{"rendered":"The colors are wrong, but how?"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Recently I got this <a href=\"https:\/\/www.raspberrypi.com\/products\/raspberry-pi-pico-2\/\" data-type=\"link\" data-id=\"https:\/\/www.raspberrypi.com\/products\/raspberry-pi-pico-2\/\">Raspberry Pi Pico 2W<\/a> as a toy:<\/p>\n\n\n\n<figure class=\"wp-block-image size-medium\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"224\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image-300x224.png\" alt=\"\" class=\"wp-image-3136\" srcset=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image-300x224.png 300w, https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image-1024x763.png 1024w, https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image-768x572.png 768w, https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image.png 1060w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">It does come with a single blinking LED, you know, so you can check that basic things are working. So that's good. Since it's nice to actually display things, I got a small, simple display- a <a href=\"https:\/\/www.waveshare.com\/1.69inch-lcd-module.htm?srsltid=AfmBOopaM8UsmS2aVqCh4uNnwGM0gq03ipVr3soALCsIscLkQ_j47TA9\" data-type=\"link\" data-id=\"https:\/\/www.waveshare.com\/1.69inch-lcd-module.htm?srsltid=AfmBOopaM8UsmS2aVqCh4uNnwGM0gq03ipVr3soALCsIscLkQ_j47TA9\">WaveShare 1.69\" LCD display<\/a> and hooked it up as follows: <\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>WaveShare LCD pin<\/th><th>Raspberry Pi Pico 2W semantic pin<\/th><th>Raspberry Pi Pico 2W global pin<\/th><\/tr><\/thead><tbody><tr><td>VCC<\/td><td>3v3<\/td><td>Pin 39<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><td>Pin 38<\/td><\/tr><tr><td>DIN<\/td><td>GP19, SPI0 TX<\/td><td>Pin 25<\/td><\/tr><tr><td>CLK<\/td><td>GP18, SPI0 SCK<\/td><td>Pin 24<\/td><\/tr><tr><td>CS<\/td><td>GP17, SPI0 CSn<\/td><td>Pin 22<\/td><\/tr><tr><td>DC<\/td><td>GP22<\/td><td>Pin 29<\/td><\/tr><tr><td>RST<\/td><td>GP13 (also SPI1CSn)<\/td><td>Pin 17<\/td><\/tr><tr><td>BL<\/td><td>GP21<\/td><td>Pin 27<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The initial functions like powering it on, turning on the backlight and clearing the screen to white and black seemed to work. The only thing is, the colors were wrong. For example, if I tried to clear to RED, well, the sample code has<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define RED           0xF800<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Except when I try it, it looks like blue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Not a big deal, figure the red\/blue channels are swapped. Very common problem. The documentation, regarding color formats, says <\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">This LCD supports input color formats of 12-bit, 16-bit, and 18-bit per pixel, which are<br>RGB444, RGB565, and RGB666. This demo example uses the RGB565 color format,<br>which is also a commonly used RGB format.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">That makes it sound like channel swapping is unlikely, and the demo is supposed to be RGB565, but who knows. Or it might be RGB444 with unused bits. I haven't worked with this device before and I couldn't find any clarifying documentation on the mode selection so I don't know.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So as another test, I try<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define GREEN         0x07E0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">since that should work, irrespective of red-blue channel swapping. Right? <\/p>\n\n\n\n<figure class=\"wp-block-image size-medium\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"265\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image-1-300x265.png\" alt=\"\" class=\"wp-image-3137\" srcset=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image-1-300x265.png 300w, https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/image-1.png 600w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Wrong. Instead of being green, it looks red now. I guess it's good to know that the different color channels are capable of displaying, But what kind of absolute madman would put red <em>in the middle<\/em> of the format? It doesn't match any of the formats it listed support for, and seems like a very strange decision. Clearly something weird is going on.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As a mini investigation, I did a test where I turned each of the 16 bits of the image data on in turn, to see the effects. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>At this point, I don't 100% know how many bits are in each channel or how the channels are ordered. <\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But, I was looking for<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The highest-order red<\/li>\n\n\n\n<li>The highest-order green<\/li>\n\n\n\n<li>The highest-order blue<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Since those probably have to exist somewhere, and if that 1 bit is turned on, you'll be able to see the effects. E.g., a dark red, a dark green, a dark blue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sure enough, I found them and marked them down:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ &#91;0] - \n\/\/ &#91;1] - \n\/\/ &#91;2] - \n\/\/ &#91;3] - blue (high)\n\/\/ &#91;4] - \n\/\/ &#91;5] - \n\/\/ &#91;6] - \n\/\/ &#91;7] - \n\/\/ &#91;8] - red (high)\n\/\/ &#91;9] - \n\/\/ &#91;10]- \n\/\/ &#91;11]- \n\/\/ &#91;12]- \n\/\/ &#91;13]- green (high)\n\/\/ &#91;14]- \n\/\/ &#91;15]- <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The high-order blue was at bit 3, high-order red was at bit 8, and high-order green was at bit 13. This comports with the experiment earlier where setting the middle of the data would make it red. It all seems a bit weird but at least it's true and I checked it's reproducible.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you notice, the blue is 5 bits away from the red, the red is 5 bits away from the green, and green appears to wrap around.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you fill it all in, you get<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ &#91;0] - green \n\/\/ &#91;1] - green \n\/\/ &#91;2] - green (low)\n\/\/ &#91;3] - blue (high)\n\/\/ &#91;4] - blue\n\/\/ &#91;5] - blue\n\/\/ &#91;6] - blue \n\/\/ &#91;7] - blue(low)\n\/\/ &#91;8] - red (high)\n\/\/ &#91;9] - red\n\/\/ &#91;10]- red\n\/\/ &#91;11]- red\n\/\/ &#91;12]- red(low)\n\/\/ &#91;13]- green (high)\n\/\/ &#91;14]- green \n\/\/ &#91;15]- green <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Which <em>is<\/em> R5G6B5. Just... Shifted by 8 bits. Or with the bytes swapped around, if you prefer to look at it that way. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sure enough, if I swap the bytes of the colors whenever I import them, you get the right result:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"326\" height=\"250\" src=\"https:\/\/cml-a.com\/content\/wp-content\/uploads\/2026\/07\/rpball_multicolor.gif\" alt=\"\" class=\"wp-image-3138\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Looks like an endianness type of problem, since <em>some<\/em> codepaths for the demo do swap the bytes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> void LCD_WriteData_Word(UWORD da)\n{\n    UBYTE i=(da&gt;&gt;8)&amp;0xff;\n    DEV_Digital_Write(DEV_CS_PIN,0);\n    DEV_Digital_Write(DEV_DC_PIN,1);\n    DEV_SPI_WRITE(i);\n    DEV_SPI_WRITE(da);\n    DEV_Digital_Write(DEV_CS_PIN,1);\n}   <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Just, not the one I was using. Oops! <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I think it would make the most sense to store all your colors pre-swapped, so that you can simply copy them. Oh well.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fixed this easily by swapping the bytes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to try out this demo, the code is available here: <a href=\"https:\/\/github.com\/clandrew\/rpball\">https:\/\/github.com\/clandrew\/rpball<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently I got this Raspberry Pi Pico 2W as a toy: It does come with a single blinking LED, you know, so you can check that basic things are working. So that&#8217;s good. Since it&#8217;s nice to actually display things, I got a small, simple display- a WaveShare 1.69&#8243; LCD display and hooked it up [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3135","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts\/3135","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/comments?post=3135"}],"version-history":[{"count":17,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts\/3135\/revisions"}],"predecessor-version":[{"id":3158,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts\/3135\/revisions\/3158"}],"wp:attachment":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/media?parent=3135"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/categories?post=3135"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/tags?post=3135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}