Open GoogleCodeExporter opened 8 years ago
I haven't had any success with reading pixels from GRAM. All I can read from
GRAM is 0x001F (equivalent to a blue pixel given RGB565 color coding) even
though there is no blue pixel on screen.
I am able to read other register values properly, however.
Has 'lcdGetPixel' worked for anyone else?
Original comment by alec.gre...@gmail.com
on 23 Nov 2012 at 4:56
Hmmh, it was ages ago, but here's some code I wrote years ago that worked for
me back then, although it was too slow for me. It's not clean or anything, but
have fun deciphering it. By the way, don't trust the comments in the code, they
might not be up to date.
This interface level function reads a rectangle from the screen:
/// LcdReadRectange should not be used. Reading from the display memory is
unsupported in many displays and very slow in others.
u_int16 LcdReadRectangle (u_int16 x1, u_int16 y1, u_int16 x2, u_int16 y2,
u_int16 *texture) {
u_int16 buff[2];
u_int32 n = (((u_int32)x2-x1)+1);
u_int16 x, y;
n *= (((u_int32)y2-y1)+1);
n *= 2; //pixels to bytes
if (!texture) {
return S_ERROR; //Caller must supply pointer to texture
}
for (y=y1; y<=y2; y++) {
TFTWriteRegister(DRAM_Horizontal_Address_Set,y);
for (x=x1; x<=x2; x++) {
TFTWriteRegister(DRAM_Vertical_Address_Set,(__LCD_LOGICAL_WIDTH-1)-x);
*texture++ = TFTReadRegister(Read_Data_from_DRAM);
}
}
}
It uses TFTWriteRegister and TFTReadRegister, which are written as:
// This function seems to work at at least 80 MHz.
void TFTWriteRegister(u_int16 reg, u_int16 data) {
PERIP(GPIO0_MODE) &= ~0x07ff; //Set GPIO0 pins [10:0] as GPIO pins
PERIP(GPIO0_DDR) |= 0x06ff; //Set GPIO0 pins [10:9,7:0] as outputs
WR_SET_HIGH();
RD_SET_HIGH();
A0_SET_LOW();
CS_SET_LOW();
A0_SET_LOW();
WRITE_BYTE(0);
WRITE_BYTE(reg);
A0_SET_HIGH();
WRITE_BYTE(data >> 8);
WRITE_BYTE(data);
CS_SET_HIGH();
PERIP(GPIO0_MODE) |= 0x07ff; //Set GPIO0 pins [10:0] as peripherals
}
/// This function is optimized for 60 MHz speed. It reads the register twice to
be able to read from display memory.
u_int16 TFTReadRegister(u_int16 reg) {
u_int16 result,result2;
PERIP(GPIO0_MODE) &= ~0x07ff; //Set GPIO0 pins [10:0] as GPIO pins
PERIP(GPIO0_DDR) |= 0x06ff; //Set GPIO0 pins [10:9,7:0] as outputs
WR_SET_HIGH();
A0_SET_LOW();
CS_SET_LOW();
A0_SET_LOW();
WRITE_BYTE(0);
WRITE_BYTE(reg);
A0_SET_HIGH();
PERIP(GPIO0_DDR) &= ~0x00ff; //Set GPIO0 pins [7:0] as inputs
READ_BYTE(result2);
READ_BYTE(result2);
READ_BYTE(result2);
READ_BYTE(result);
result = result2<<8 | result;
CS_SET_HIGH();
PERIP(GPIO0_DDR) |= 0x06ff; //Set GPIO0 pins [10:9,7:0] as outputs
PERIP(GPIO0_MODE) |= 0x07ff; //Set GPIO0 pins [10:0] as peripherals
return result;
}
Those finally use some hardware macros to manipulate GPIO pins. Note the
reduplication of some instructions just to introduce small delays into the
waveform.
// Hard macros to manipulate the interface pins.
#define A0_SET_HIGH(){PERIP(GPIO0_SET_MASK) = (1 << 0xe);}
#define A0_SET_LOW(){PERIP(GPIO0_CLEAR_MASK) = (1 << 0xe);}
#define CS_SET_HIGH(){PERIP(GPIO1_SET_MASK) = (1 << 0x0);}
#define CS_SET_LOW(){PERIP(GPIO1_CLEAR_MASK) = (1 << 0x0);}
#define RD_SET_HIGH(){PERIP(GPIO0_SET_MASK) = (1 << 0x9);}
#define RD_SET_LOW(){PERIP(GPIO0_CLEAR_MASK) = (1 << 0x9);}
#define WR_SET_HIGH(){PERIP(GPIO0_SET_MASK) = (1 << 0xa);}
#define WR_SET_LOW(){PERIP(GPIO0_CLEAR_MASK) = (1 << 0xa);}
#define WRITE_BYTE(a){PERIP(GPIO0_CLEAR_MASK)=0x00ff;
PERIP(GPIO0_SET_MASK)=((a)&0xff); PERIP(GPIO0_CLEAR_MASK)=0x0400;
WR_SET_LOW();WR_SET_LOW();PERIP(GPIO0_SET_MASK)=0x0600;}
#define
READ_BYTE(a){RD_SET_LOW();RD_SET_LOW();RD_SET_LOW();RD_SET_LOW();RD_SET_LOW();RD
_SET_LOW();RD_SET_LOW();RD_SET_LOW();a=PERIP(GPIO0_IDATA)&0xff;RD_SET_HIGH();}
Have loads of fun...!
-PP.
Original comment by ptechdes...@gmail.com
on 23 Nov 2012 at 8:22
Oh, btw that last code snippet from me is not for arm, and maybe not even
working, but it may help you to get some ideas for you to tweak your code.
Original comment by ptechdes...@gmail.com
on 23 Nov 2012 at 8:45
[deleted comment]
[deleted comment]
Okay, thanks for the comments on the code. It appears that in essence you are
still writing the GRAM reg value (0x0022), and then reading as indicated in the
attached diagram.
Datasheet says minimum low and high hold times for read operation are 150ns
each. I am performing both for 170ns each (perhaps not long enough?), with
oscilloscope readings exactly as depicted in the attached diagram. The strange
thing is that read works fine for non-GRAM registers.
I'll try with longer read hold times, and let you know.
*Also, the attached diagram makes it look like you can perform sequential pixel
reads (with auto-address increment) just like you can with writes. You asked
if it was possible in your initial post; did you ever succeed with sequential
reads?
Original comment by alec.gre...@gmail.com
on 24 Nov 2012 at 5:39
Attachments:
Hi!
No, I never got the autoincrement to work so it was just pixel-by-pixel
reading. But it was just one LCD module from China and who knows what the
controller in that module /really/ was..., I never tried it again with other
modules.
BTW, A0 is another traditional name for RS (Register Select), inherited from
naming conventions in old code and schematics...
> The strange thing is that read works fine for non-GRAM registers.
Hmmh, it's not strange at all, since the mechanism for reading the GRAM
registers is different: it takes 1-2 clock cycles for the RAM fetch, which
needs to trickle its way down to the register. Other registers don't need this
step, they are read directly, so they don't need the dummy cycles. How many
times do you clock in the register value? Try adding a few..
Original comment by ptechdes...@gmail.com
on 24 Nov 2012 at 5:47
Well, I had some luck in reading pixels (doesn't seem to auto-increment,
though).
However, weirdly enough there seem to be certain pixel values that I can't read
correctly. I can read green (0x07E0), magenta (0xF81F), cyan (0x07FF), and
others. However, when I try to read red (0xF800), I get blue (0x001F) AND vice
versa (read red when really blue pixel). I'm also having issues with other
colors (eg read 0xD7E6 when I really write 0x37FA).
I'm using the same read/write routines for all of it, just changing out the
pixel values with straight hex numbers, so wonder if it could be hardware issue?
Original comment by alec.gre...@gmail.com
on 25 Nov 2012 at 4:53
If you get blue when you read red and other such problems, then you have a RGB
vs BGR bit order problem. There's a bit in the register set which chooses which
bits are the leftmost, red (RGB) or blue (BGR).
It may also help to know that the display memory is always 18 bits wide. When
you write a pixel value, it's translated into a 18-bit value using some
colorscheme, such as 18-bit (RGB666), 16 bit (RGB565), 15-bit (RGB555), 8 bit
(BGR233, not supported in ILI9325) or some other translation. For each
colorscheme, there may be different translations for example to support
different orderings of the plastic RGB color filter on top of the LCD glass.
When you read back the pixel value, the 18-bit value in the display memory is
again translated into a 8-bit, 15-bit, 16-bit (or 18-bit) value. So if the
display's configuration changes between write and read, at least then you will
get different hex values than the ones you write in.
Original comment by ptechdes...@gmail.com
on 25 Nov 2012 at 4:55
This explains it; thank you so much. I assumed from the attached diagram that
I should be writing and reading in RGB.
My initialization of the 'entry mode register' (0x0003) was setting the 'BGR'
bit, which causes the RGB565 input pixels to be swapped (color inversion).
I was thrown off because some of the pixels I was reading were color inversions
of each other (eg YELLOW = 0xFFE0 and CYAN = 0x07FF) and some were palindromes
(eg MAGENTA = 0xF81F), thus making it seem that some pixels were being read
correctly while others were not. Very insidious!
However, for my display the 'BGR' bit apparently needs to be set in order to
map pixels written in RGB correctly. In other words, since I can't find
another register value that will color-invert the pixel upon read-out, I will
either have to write BGR (BGR bit = 0) and/or read BGR (BGR bit = 1), and
cannot both write and read in RGB. Is this what you experienced with the
display?
Original comment by alec.gre...@gmail.com
on 26 Nov 2012 at 2:05
Attachments:
Sounds right, and now that you mention it, the way it behaves on read does feel
familiar. I think my unit might have behaved just like yours. The conversion
might not be symmetrical or perhaps not all conversions are available for
reading. But as I said, I felt it was too slow and abandoned reading the very
same day I got it working, so I don't have much memories accumulated from that.
But hey, great to hear that it works!
Original comment by ptechdes...@gmail.com
on 6 Dec 2012 at 6:15
Original issue reported on code.google.com by
ptechdes...@gmail.com
on 2 Oct 2011 at 9:29