I'm driving an ILI9230 LCD 320*240 16bit interface, with a framebuffer of 250*200 and I want to drive it as 4bit. so I built a loook up color table like that:

u16 LUT[16] = {
    //0      1      2     3    4    5    6    7    8       
    // 9      A    B      C    D     E   F

then my framebuffer is an array like that:

#define fbWidth      256
#define fbHeight     200
char frameBuffer[fbWidth*fbHeight/2]; // 256*200*4bit

I try to swap the double buffers like that:

for(i=0;i< fbWidth*fbHeight/2;i++)
         u16 color = LUT[frameBuffer[i]];
         *(__IO uint16_t *) (Bank1_LCD_D)= color;

and to write to the backbuffer:

    // color is 2
frameBuffer[fbWidth * y + x] = color;

The problem is I get less screen resolution due to truncating the frramebuffer width*height/2.. looks like I didn't implement the look up color table concept not correctly..

  • \$\begingroup\$ What are you running the code on? Try printing the value of fbWidth*fbHeight/2. Try getting a single framebuffer working, making the code as simple as practical. \$\endgroup\$
    – gbulmer
    Sep 7, 2014 at 22:00
  • \$\begingroup\$ ARM Cortex M3. I tried to substitute the result of fbWidth*fbHeight/2 to the equivalent value.. but still there is something that's not working and I can't figure it out. Unfortunately I don't have Jtag right now \$\endgroup\$ Sep 7, 2014 at 22:09
  • \$\begingroup\$ If you have no way to get data out, make the program simple. Initially use a framebuffer 1 scan-line long (320), and write the same line repeatedly. \$\endgroup\$
    – gbulmer
    Sep 7, 2014 at 22:14

1 Answer 1


Your problem here is you're working in bytes, but the framebuffer is conceptually in nibbles.

Say you have a screen 256x200, so you have a framebuffer of 256x200 nibbles, of 256x200/2 bytes. That is fine, and what you have.

You then need to translate your X/Y coordinates into a framebuffer byte location. For that you need to work with half the width, or half the height. For example, the location 10,20 would equate to half the value of 20 widths + 10 bytes. That would be (20 * 256 + 10) / 2 = 1285.

Now, you're half way there. You know where in the framebuffer your chosen pixel is, but not which half of the byte. For that you need to look at the full pixel location and see if it's odd or even. 20 * 156 + 10 = 2570. That is an even number (2570 & 1 = 0; the LSB is set to 0, so is even), so you want to only modify the lowest nibble of the value (if it were odd you'd modify the highest nibble - of course you could store them the other way around - see later).

So you would read the current value from the array, mask out the nibble you want to modify it so it's all 0, then overlay the new value.

Say the byte currently contains 0b10011100, you would AND it with 0b11110000 to result in 0b10010000. Then you OR that result with your new pixel value, say 2, to result in 0b10010010.

If you were modifying the upper nibble you would first need to shift your colour value 4 bits left to make it 0b00100000 instead of 0b00000010, then or it with the masked out upper nibble of the byte.

Then you write the byte back again.

Now, displaying the framebuffer to the screen is a similarly onerous task:

You need to take each byte of the framebuffer and split it into two nibbles. Right-shift the upper nibble 4 bits to make it a number between 0 and 15. Look up the colour for the lower nibble, and place it on the screen. Then do the same with the upper nibble placing in on the screen in the next pixel. Then you advance to the pixel following that, so you have moved on 2 pixels in total.

Note from earlier - if you stored the even in the upper nibble and the odd in the lower nibble you'd just output the pixels in the opposite order - upper then lower.

Clear as mud now?

  • \$\begingroup\$ amazing :) thanks so much.. from where did you get all that knowledge and the algorithms above :) ? books recommendation ? \$\endgroup\$ Sep 7, 2014 at 22:32
  • 1
    \$\begingroup\$ Self teaching and programming. Two years at college, three at university, then 15 years in software and hardware ;) Also I wrote my own TFT library for the PIC32 that does framebuffering and CLUT: github.com/majenkotech/TFT Feel free to take any code or ideas from that you like. \$\endgroup\$
    – Majenko
    Sep 8, 2014 at 0:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.