sumotoy / RA8875

A library for RAiO RA8875 display driver for Teensy3.x or LC/Arduino's/Energia/Spark
GNU General Public License v3.0
79 stars 55 forks source link

drawPixel can't draw adjacent pixels when layers are enabled, but works OK without layers (V0.70b10) #66

Closed GJakobsche closed 8 years ago

GJakobsche commented 9 years ago

When I turn on layers and use drawPixel to draw a row of adjacent pixels, i.e., I increment the x coordinate by 1, as drawPixel draws each pixel, it seems to also draw on top of the previous pixel with a different color, often black. The net effect is as each pixel is drawn, the previous pixel is erased, at least when the pixel being drawn is red, green or blue. However, if I increment the x coordinate by 2, i.e., I skip a pixel between each drawn pixel, no pixels are erased or overwritten.

If I turn off layers, this problem does not occur, i.e., I can increment the x coordinate by 1 and drawPixel draws adjacent pixels as expected.

I wrote a small program to demonstrate this problem on a 7-inch EastRising display.

I understand that when layers are turned on, the color space is cut in half, so colors need to be 8 bits, rather than 16 bits. However, that does not explain why skipping a pixel causes a different result than drawing adjacent pixels, while layers are turned on. Am I doing something wrong?

-George

/*
                Test_drawPixel

George Jakobsche, 8/2/2015

Test program: Proves that "drawPixel()" cannot draw adjacent pixels in a row when using layers. 
As "drawPixel" draws each pixel, it seems to erase the pixel it previously drew, i.e., the adjacent pixel.

See text displayed by "displayLegend" for an explanation of what the program does. It seems when 
"drawPixel" draws adjacent pixels in a row, as it displays one pixel it erases the previous pixel.
However, if the x coordinate increments by two, i.e., we skip a pixel between each drawn pixel, "drawPixel"
works correctly. This problem occurs only if layers are enabled. 

Compiled with RA8875 library V0.70b10 Preview 2, by Sumotoy.

*/

// *************************************************************************************************

#include <SPI.h>
#include <Wire.h>
#include <RA8875.h>

#define RA8875_CS           10                  // Chip Select
#define RA8875_RESET        9                   // Reset

RA8875 tft = RA8875 (RA8875_CS, RA8875_RESET); // Instantiate the display "tft"

// *************************************************************************************************

void displayLegend() {

        tft.setCursor (100, 275);
        tft.setTextColor (RA8875_WHITE, RA8875_BLACK);

        tft.println ("Demonstration of problem with 'drawPixel' when used with layers.");
        tft.println ("Print a series of column pairs. In each column pair, display a horizontal row of 50 pixels.");
        tft.println ("Use 'drawPixel' in a loop to draw each row of pixels. The loop increments the x coordinate");
        tft.println ("of each pixel. In the left column, x increments by 1, i.e., the pixels are positioned right");
        tft.println ("next to each other. In the right column, x increments by 2, i.e., there is one pixel between");
        tft.println ("each drawn pixel. Go through all the colors, incrementing the color by one for each row");
        tft.println ("of pixels in a column pair. Although the SAME color value is passed to 'drawPixel' for both");
        tft.println ("the left and right columns, DIFFERENT colored pixels are displayed in the two columns!"); 
        tft.println ("");
        tft.println ("Comment out the two lines of code that turn on layers, and the problem does not occur!");       
}

// *************************************************************************************************

void setup() {

        unsigned int color;
        int startx;
        int x;
        int y;

        Wire.begin();                                  // Join I2C bus (address optional for master)

        tft.begin(RA8875_800x480);

        tft.displayOn(true);                           // Turn on display panel, in case it's off
        tft.backlight(true);
        tft.brightness(255);                           // Set backlight to max.    
        tft.clearScreen(RA8875_BLACK);

/*

After running the program to demonstrate the problem, comment out the following two lines of code,
so layers are not used. Then, run the program again. The problem will not occur. This proves the
problem is a result of a bad interaction between 'drawPixel' and layers.

*/                                                     
        tft.writeTo(L2);                               // Everything is written on Layer2.
        tft.layerEffect(LAYER2);                       // Display only Layer2

        displayLegend();

        startx = 0;                                    // Begin at left side of display
        y = 0;                                         // Begin at top of display

        color = 0x00;                                  // Step through the colors

        while (1 == 1) {

                if (y >= 0x100) {                      // Every 0x100 rows, start a new column

                        startx = startx + 100;         // Move to next column
                        y=0;                           // And start at top of the column
                }

                if (startx >= 800) {                    // After the screen is full

                        delay (1000);
                        tft.clearScreen(RA8875_BLACK);  // Erase the screen and
                        startx = 0;                     // start at left side of screen 
                        displayLegend();                       
                }

                tft.setCursor (0, 450);
                tft.setTextColor (RA8875_WHITE, RA8875_BLACK);
                tft.print ("Color: 0x");
                tft.print (color, HEX);
                                                        // Draw a column pair, i.e., two rows of pixels:

                for (x = startx; x < (startx + 50); x++) { // First row: draw 50 pixels, one next to the other

                        tft.drawPixel(x, y, color);
                }

                for (x = (startx + 50); x < (startx + 100); x = x + 2) { // Second row: skip every other pixel

                        tft.drawPixel(x, y, color);
                }

                y++;                                    // Advance to next line

                color++;                                // Advance to next color

//              color = color + 0x0010;                 // To go through the colors faster (skipping colors),
                                                        // comment out "color++" and uncomment this line.
        }
}

// *************************************************************************************************

void loop() {

}
sumotoy commented 9 years ago

Looks like another RA8875 hardware bug, I have solved many during develop. The code affected with or without layers it's the same, I will try to solve this for the b11.

sumotoy commented 8 years ago

Ok, started to look sort this issue, with 480x272 this not happenen for 16bit (at this resolution it's possible have 2 layers) but as soon I run at 8 bit the problem comes out. Looks like a RA8875 bug in 8pixel mode. I can confirm it's an 8bit bug, even comment out the two lines mentioned and initializing screen at 8 bit by using tft.begin(RA8875_800x480,8); the color bug happen again. The datasheet it's not illuminating but I've tried an undocumented attempt and now colors looks almost same. Since you are working in 8bit mode when switch layers at 800x480 I have tried to send a 8bit color to RA. Please download the 0.70b11p2 and try.

sumotoy commented 8 years ago

Definetively it's isolated to drawPixel, RA8875 has hardware routine that convert internally 16bit colors in 8 Bit but it try to simulate 16 bit, this works for setColor function but drawPixel write directly in RA8875 DRAM so it expect an 8 bit color when you are in 8 bit color mode! So it's not a real bug, it's an hardware limitation. I'm writed a seamless workaround to fix this, it's not optimized but compact 16bit color data into a single 8bit as requested by RAiO datasheet pg.75 and write a single byte instead a word, this just in 8bit mode. The code it's in 0.70b11p2

sumotoy commented 8 years ago

Looks ok to me now. Just one note about your example, you don't really need displayOn, backlight, brightness and clearScreen just after begin since the library performs all these commands inside begin (and also set the cursor at 0,0 and lot's more), in brief, just after begin the library it's fully initialized.

GJakobsche commented 8 years ago

Great! Thanks for compensating for the hardware limitation! I will try the new library in the coming days.

Thanks for your comments on no need call to "displayOn," etc. I may streamline my code. Best regards, George