|
|
View previous topic :: View next topic |
Author |
Message |
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
Help with LCD graphics |
Posted: Tue Nov 25, 2008 7:50 pm |
|
|
Hello,
I seem to have a nasty problem with a graphics driver I recently modified to drive a 128X64 graphical display, using the Sitronix ST7920 controller. I had originally found some code in the forum posted by javierviana for a similar controller (different display) I was able to easily modify this code to use with the Crystalfontz 144X32 graphical display by making some changes to the original code and it seems to work quite nicely. Since, I have acquired another module from Crystalfontz (CFAG12864JTMI) which is basically the same controller but the only difference is that it is a 128X64, the controller is really a 256X32 bitmap split into an upper screen which is 32 rows in the vertical space and 128 columns in the horizontal space. The ST7920 is not a very easy device to work, at least not their chinese translated data sheets. The way you get 128X64 pixels is by addressing the vertical from 0 to 31 and the horizontal from 0 to 127 when the horizontal address (16bit field) reaches 128 it automatically indexes the bottom half of the screen (Vert pos 32) and the vertical then steps from 0-31 or 32-64 while the horizontal goes from 128 to 256, in other words; to light up a pixel at location X=100 and Y=50 the real address would be X=227, Y=19. The problem I seem to have is most likely related to glcd_update() and the way the bitfield for the union/structure called gdram, it appears that I am missing the point with this bit field as I can only seem to address the upper half of the display, but not the lower, I am sure this is probably a simple problem, but I seem to be really bogged down with the way this pixel map is realized using the struct gdram, any hints or suggestions would be great help, specially if you have used this device.
Thank you
Code: | ************************************************************************************************************************************
/***************************************************************************
*
*
*
* This file contains drivers for using a CrystalFontz CFAG12864JTMI
* that uses a Sitronix ST7920 display controller. The CFAG12864JTMI is 128 by
* 64 pixels.
* The driver treats the upper left pixel as (0,0).
*
* This display maps out to a 32X256 bit map or two 32X128 screens stacked
*
* LCD Pin connections:
* 1: VSS is connected to GND
* 2: VDD is connected to +5V
* 3: V0 - LCD operating voltage (Constrast adjustment)
* 4: R/S - Data or Instruction is connected to C7
* 5: R/W - Read or Write is connected to C6
* 6: Enable is connected to C5
* 7-14: Data Bus 0 to 7 is connected to port D
* 15: Positive voltage for LED backlight is connected to +5V
* 16: Negavtive voltage for LED backlight is connected to GND
*
* This code was copied and modified from original source by javierviana
* http://www.ccsinfo.com/forum/viewtopic.php?t=32819&highlight=st7920
*
* glcd_init () Must be called before any other function.
*
* glcd_pixel (x,y,color) Sets the pixel to the given color.
* color can be ON or OFF
*
* glcd_fillScreen (color) Fills the entire LCD with the given color.
* color can be ON or OFF
*
*****************************************************************************/
#define GLCD_RS RC7 // Display Data / Control Data.
#define GLCD_RW RC6 // Read / Write
#define GLCD_E RC5 // Enable Signal.
#define GLCD_WIDTH 128
#define RS_FUNCTION 0
#define RS_DATA 1
#define RW_WRITE 0
#define RW_READ 1
#define TRIS_READ 0xFF
#define TRIS_WRITE 0x00
#define XVAL 16 // 16 X 16 or 256 for there is 8 word values for the upper and lower
#define YVAL 32
// Color Values
#define ON 1
#define OFF 0
typedef union
{
int16 word;
int8 byte[2];
} Dots;
typedef struct
{
int1 refresh;
Dots pix[YVAL][XVAL]; // Max dimensions for display (x,y) = (128,32)
} GD_RAM; // (0,0) corresponds to upper lefthand corner.
GD_RAM gdram;
/*----------------------------------------------------------------------------------------------
* glcd_readByte
*
* Reads a byte of data from the LCD.
*
* In/Out:
*
* Return: A byte of data read from the LCD.
*
*--------------------------------------------------------------------------------------------*/
unsigned int8 glcd_readByte (unsigned int8 address)
{
unsigned int8 data; // Stores the data read from the LCD
set_tris_b (TRIS_READ); // Set PORTB to input
delay_us(15);
GLCD_RS = address;
GLCD_RW = RW_READ; // Set for reading
delay_us(50);
GLCD_E = 1; // Pulse the enable pin
delay_us(50);
data = PORTB; // Get the data from the display's output register
GLCD_E = 0;
delay_us(15);
GLCD_RS = 1;
return (data);
}
/*----------------------------------------------------------------------------------------------
* Function Name: CheckBusyFlag()
*
* Function: Reads the status of bit 7 to test busy flag
*
* In/Out:
*
* Return: Flagdata
*
*
*
*--------------------------------------------------------------------------------------------*/
unsigned int8 CheckBusyFlag ()
{
unsigned int8 Flagdata; // flag data value
set_tris_d (TRIS_READ); // Set PORTB to input
delay_us(15);
GLCD_RS = 0;
GLCD_RW = RW_READ; // Set for reading
delay_us(5);
GLCD_E = 1; // Pulse the enable pin
delay_us(15);
Flagdata = (PORTD & 0x80); // mask bit 7 to test busy flag data from the display's output register
delay_us(15);
GLCD_E = 0;
delay_us(15);
GLCD_RS = 1;
return (Flagdata);
}
/*----------------------------------------------------------------------------------------------
* glcd_writeByte
*
* Write a byte of data to the LCD.
*
* - data (in): the byte of data to write.
*
*
*--------------------------------------------------------------------------------------------*/
void glcd_writeByte (unsigned int8 address, unsigned int8 data)
{
GLCD_RS = RS_FUNCTION;
GLCD_E = 0;
while ( CheckBusyFlag () ) ; // Whait Busy Flag = FALSE!
set_tris_d (TRIS_WRITE); // Set PORTB to output
delay_us(10);
GLCD_RS = address;
GLCD_RW = RW_WRITE; // Set for writing
delay_us(1);
GLCD_E = 1;
delay_us(5);
PORTD = data; // Put the data on the port
delay_us(10);
GLCD_E = 0; // Pulse the enable pin
delay_us(5);
GLCD_RW = RW_READ;
}
/*----------------------------------------------------------------------------------------------
glcd_fillScreen
*
* Fill the LCD screen with the passed in color.
*
* - color (in):
* ON - turn all the pixels on.
* OFF - turn all the pixels off.
*
*--------------------------------------------------------------------------------------------*/
void glcd_fillScreen (unsigned int1 color)
{
int8 v, h;
int16 d;
d = (color == ON ? 0xFFFFL : 0x0000L);
for (v=0; v < YVAL; v++)
{
for (h=0; h < XVAL; h++)
{
gdram.pix[v][h].word = d;
}
}
gdram.refresh = TRUE;
}
/*----------------------------------------------------------------------------------------------
* glcd_update
*
* Update the LCD with data from the display cache.
*
*--------------------------------------------------------------------------------------------*/
void glcd_update ()
{
int8 v, h,k;
if (gdram.refresh)
{
for (v=0; v <YVAL; v++)
{
glcd_writeByte (RS_FUNCTION, 0x80 | v); // Set Vertical Address.
glcd_writeByte (RS_FUNCTION, 0x80 | 0); // Set Horizontal Address.
for (h=0; h <XVAL; h++)
{
glcd_writeByte (RS_DATA, gdram.pix[v][h].byte[1]); // Write High Byte.
glcd_writeByte (RS_DATA, gdram.pix[v][h].byte[0]); // Write Low Byte.
}
}
gdram.refresh = FALSE;
}
} |
|
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Tue Nov 25, 2008 8:12 pm |
|
|
////Missing code from previous message (got accidentally left out)
Code: | /*----------------------------------------------------------------------------------------------
* glcd_init
*
* Initialize LCD.
*
* - mode (in): OFF/ON - Turns the LCD off/on.
*
* Call before using any other LCD function.
*
*--------------------------------------------------------------------------------------------*/
void glcd_init ()
{
set_tris_d (TRIS_WRITE); // PORTB as output.
GLCD_RS = RS_FUNCTION;
GLCD_RW = RW_WRITE;
GLCD_E = 0;
delay_ms (40);
glcd_writeByte (RS_FUNCTION, 0x30); // Specify 8 bit interface and basic instruction set.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x30); // Specify 8 bit interface and basic instruction set.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x0C); // Specify Display on, Cursor off and Blink off.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x01); // Display clear.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x06); // AC Increase (cursor move right), don't shift the display.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x34); // Select extended instruction set.
delay_ms (10);
glcd_writeByte (RS_FUNCTION, 0x36); // Graphic display ON.
delay_ms (10);
glcd_fillScreen (OFF);
glcd_update ();
}
/*----------------------------------------------------------------------------------------------
* Turn a pixel on a graphic LCD on or off.
*
*
* - x (in): the x coordinate of the pixel.
* - y (in): y - the y coordinate of the pixel.
* - color (in): ON or OFF.
*--------------------------------------------------------------------------------------------*/
void glcd_pixel(int8 x, int8 y, int1 color)
{
int8 v, h, b;
v = y;
h = x/16;
b = 15 - (x%16);
// if(v>31){h += 128; v-= 32;} //Although this works to some point the update does not
// Modify the actual word.
if (color == ON) bit_set (gdram.pix[v][h].word, b);
else bit_clear (gdram.pix[v][h].word, b);
gdram.refresh = TRUE;
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 25, 2008 9:51 pm |
|
|
Can you post the manufacturer and part number of the LCD (not the
chipset) that you are currently trying to make work ? If possible,
post a link to the webpage for the LCD. |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Wed Nov 26, 2008 11:47 am |
|
|
FOUND THE REAL PROBLEM!!!!!!!!!!!!!!!!
The reason why my graphics screen only works on only the upper half has nothing to do with the actual LCD driver code routines, the real isuue is that any calling routines to place pixels in the screen have to be translated as follows:
For line segments where (x1,y1,x2,y2) you must do the following:
if(y1>31){x1 += 128; y1 -= 32;}
if(y2>31){x2 += 128; y2 -= 32;}
For pixel positioning, where (x,y) you must do the following:
if(y>31){x += 128; y -= 32;}
The above have to be done in the graphic drawing routines (Graphics.c)
I will post a new driver and graphics.c once I get this going and it's tested, so others do not have to suffer like I did. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|