GLCD source code COMPLETED!!

General discussion on mikroC.
Post Reply
Author
Message
Deepak
Posts: 55
Joined: 08 Jan 2009 06:00
Location: India

GLCD source code COMPLETED!!

#1 Post by Deepak » 03 Jun 2009 13:45

Hello all,

I'm using a PIC18F8520 MCU, MicroC IDE and a 128x64 GLCD. With the in-built library functions the GLCD is working fine, but I want to use code without using the library functions for portability reasons. Please help me with the source code to simply initialize the GLCD and display a character for now. Thank you in advance.
This is my code as of now and is not working:
#define GLCD_DI PORTJ.F2
#define GLCD_RW PORTJ.F3
#define GLCD_EN PORTJ.F4
#define GLCD_CS1 PORTJ.F0
#define GLCD_CS2 PORTJ.F1
#define GLCD_RST PORTJ.F5
#define GLCD_DATA PORTD

#define X_ADRESS 0xB8 // Adress base for Page 0
#define Y_ADRESS 0x40 // Adress base for Y0
#define START_LINE 0xC0 // Adress base for line 0
#define DISPLAY_ON 0x3F // Turn display on
#define DISPLAY_OFF 0x3E // Turn display off

#define RIGHT 0
#define LEFT 1
#define BUSY 0x80

typedef unsigned int U16;

void GLCDWaitBusy( )
{

GLCD_DATA= 0xFF; // Set LCD_DATA port in input mode
TRISD = 0xFF;
GLCD_DI = 0; // Instruction mode
GLCD_RW = 1; // Read mode
GLCD_EN = 0; // Strobe
Delay_ms( 10 );
GLCD_EN = 1;

//while( GLCD_DATA & 0x7F == BUSY ); // Mask the other status bits and test the BUSY bit
while( GLCD_DATA & 0x80 );

}

void GLCDInstructionWrite( U16 Instruction )
{

GLCDWaitBusy( ); // Wait until LCD not busy
GLCD_DI = 0; // Instruction mode
GLCD_RW = 0; // Write mode
GLCD_DATA = Instruction; // Outbyte
GLCD_EN = 1; // Strobe
Delay_ms( 10 );
GLCD_EN = 0;

}

void GLCDSelectSide( U16 Side )
{

if( Side == RIGHT )
{
// Switch to right
GLCD_EN = 0;
GLCD_DI = 0;
GLCD_RW = 1;
GLCD_CS1 = 0;
GLCD_CS2 = 1;

GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

}
else
{
// Switch to left
GLCD_EN = 0;
GLCD_DI = 0;
GLCD_RW = 1;
GLCD_CS1 = 1;
GLCD_CS2 = 0;

GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

}

}

void GLCDDataWrite( U16 Data )
{

GLCDWaitBusy( ); // Wait until LCD not busy
GLCD_DI = 1; // Data mode
GLCD_RW = 0; // Write mode
GLCD_DATA = Data; // Outbyte
GLCD_EN = 1; // Strobe
Delay_ms( 10 );
GLCD_EN = 0;

}

void GLCD_ClearScreen( )
{

U16 Page = 0;
U16 Column = 0;
// Process the 8 pages of the GLCD
for( Page = 0; Page < 8; Page++ )
{

GLCDSelectSide( LEFT ); // Select left side
GLCDInstructionWrite( X_ADRESS | Page ); // Set the page number
GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

// Process a page on both sides
for ( Column = 0; Column < 128; Column++ )
{

if( Column == 64 )
{

GLCDSelectSide( RIGHT ); // Select right side
GLCDInstructionWrite( X_ADRESS | Page ); // Set the page number
GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

}

GLCDDataWrite( 0x00 ); // Erase a column

}

}

}

void GLCDInt( )
{

GLCD_DATA = 0;
GLCD_DI = 0;
GLCD_RW = 0;
GLCD_EN = 0;
GLCD_CS1 = 0;
GLCD_CS2 = 0;

GLCD_RST = 1;
Delay_ms( 10 );
GLCD_RST=0;
Delay_ms( 10 );
GLCD_RST=1;

GLCDSelectSide( LEFT );
GLCDInstructionWrite( DISPLAY_OFF ); // Display OFF
GLCDInstructionWrite( START_LINE );
GLCDInstructionWrite( X_ADRESS );
GLCDInstructionWrite( Y_ADRESS );
GLCDInstructionWrite( DISPLAY_ON ); // Display ON

GLCDSelectSide( RIGHT );
GLCDInstructionWrite( DISPLAY_OFF ); // Display OFF
GLCDInstructionWrite( START_LINE );
GLCDInstructionWrite( X_ADRESS );
GLCDInstructionWrite( Y_ADRESS );
GLCDInstructionWrite( DISPLAY_ON ); // Display ON

GLCD_ClearScreen( );

}

U16 GLCDDataRead( )
{

GLCD_DATA = 0xFF; // Set LCD_DATA port in input mode

GLCD_RW = 1; // Read mode
GLCD_DI = 1; // Data mode

GLCD_EN = 0; // Strobe
Delay_ms( 10 );
GLCD_EN = 1;
Delay_ms( 10 );

return GLCD_DATA; // Return the data read

}
/*
void GLCDSetDot( U16 Xaxis, U16 Yaxis )
{

U16 DataRead = 0;

GLCDInstructionWrite( START_LINE ); // Set adress for line 0

// Left side
if( Xaxis < 64 )
{

GLCDSelectSide( LEFT ); // Select left side
GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis ); // Select column

DataRead = GLCDDataRead( ); // Read the current location
DataRead = GLCDDataRead( ); // on the LCD. dummy read

GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis ); // Select column
GLCDDataWrite( DataRead | ( 1 << ( Yaxis % 8 ) ) ); // Plot the dot

}
else
// Right side
{

GLCDSelectSide( RIGHT ); // Select left side
GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis - 64 ); // Select column

DataRead = GLCDDataRead( ); // Read the current location
DataRead = GLCDDataRead( ); // on the LCD. dummy read

GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis - 64 ); // Select column
GLCDDataWrite( DataRead | ( 1 << ( Yaxis % 8 ) ) ); // Plot the dot

}

GLCDInstructionWrite( START_LINE ); // Set adress for line 0

}

void GLCDRectangle( U16 Xaxis1, U16 Yaxis1, U16 Xaxis2, U16 Yaxis2 )
{

U16 CurrentValue = 0;

// Draw the two horizontal lines
for( CurrentValue = 0; CurrentValue < Xaxis2 - Xaxis1+ 1; CurrentValue++ )
{

GLCDSetDot( Xaxis1 + CurrentValue, Yaxis1 );
GLCDSetDot( Xaxis1 + CurrentValue, Yaxis2 );
}

// Draw the two vertical lines
for( CurrentValue = 0; CurrentValue < Yaxis2 - Yaxis1 + 1; CurrentValue++ )
{

GLCDSetDot( Xaxis1, Yaxis1 + CurrentValue );
GLCDSetDot( Xaxis2, Yaxis1 + CurrentValue );

}

}
*/
void main( )
{

CMCON |= 0x07; // Turn off comparators
ADCON1 |= 0x0F; // Turn off analog inputs
MEMCON.EBDIS = 1; // Disable external memory bus

TRISJ = 0;
TRISD = 0;

//GLCDInt( );
//GLCDDataWrite( 0x65 );
//GLCDRectangle( 1, 1, 1, 1 );
Glcd_Init( &PORTJ, 0, 1, 2, 3, 5, 4, &PORTD ); // Glcd_Init_BP5, see Autocomplete
Glcd_Fill( 0x00 );
GLCD_Write_Text( "RACE=DYNAMICS" , 25, 11, 2 );
//GLCDSetDot(0,0);
//GLCDRectangle( 0, 0, 10, 10 );

}
Regards,
Deepak.[/b]
Last edited by Deepak on 10 Jun 2009 10:03, edited 2 times in total.

icebox1701
Posts: 15
Joined: 20 Apr 2009 21:44

#2 Post by icebox1701 » 04 Jun 2009 18:16

as I'm working on something similar I found your code very interesting.

First thing I think it's a problem is that at GLCDWaitBusy you set TRISD as 0xFF (input mode) and never set it back - this way your data is never written to the display.

Second problem found: some of the RS, DI values are wrong - datasheet says something else than you used.

Third problem Delay_ms(10) milliseconds - you need - if I get the datasheet corectly - 25ns for the E strobe 10 ms = 10 000 000 nanoseconds = your code is way to slow - I replaced Delay_ms(10) with Delay_us(10) and I think it can go as low as Delay_ms(1)

It still doesn't work but I think it's a start. After corecting values from datasheet I can get the display to show consistent garbage :)

will keep working - your code is far more close to usable than the free library code I am trying to port

BTW if you figure it out, please share !
--
icebox

[url=http://www.sgvulcan.com/]http://www.sgvulcan.com/[/url]

icebox1701
Posts: 15
Joined: 20 Apr 2009 21:44

new update

#3 Post by icebox1701 » 04 Jun 2009 19:16

I have a PIC 16F887 on my board so the screen is wired to PORTB not PORTJ like yours

This is the code I got working - partially - I get dots to light up on the screen but in the wrong positions:

Any ideeas?

Thanks

Code: Select all


#define GLCD_DI PORTB.F2
#define GLCD_RW PORTB.F3
#define GLCD_EN PORTB.F4
#define GLCD_CS1 PORTB.F0
#define GLCD_CS2 PORTB.F1
#define GLCD_RST PORTB.F5
#define GLCD_DATA PORTD

#define X_ADRESS 0xB8 // Adress base for Page 0
#define Y_ADRESS 0x40 // Adress base for Y0
#define START_LINE 0xC0 // Adress base for line 0
#define DISPLAY_ON 0x3F // Turn display on
#define DISPLAY_OFF 0x3E // Turn display off

#define RIGHT 0
#define LEFT 1
#define BUSY 0x80

typedef unsigned int U16;

void GLCDWaitBusy( )
{

  TRISD = 0xFF; // Set LCD_DATA port in input mode
  GLCD_DATA= 0xFF;
  GLCD_DI = 1; // Instruction mode
  GLCD_RW = 0; // Read mode
  GLCD_EN = 0; // Strobe
  Delay_us(10);
  GLCD_EN = 1;
  Delay_us(10);
  GLCD_EN = 0;
  //while( GLCD_DATA & 0x7F == BUSY ); // Mask the other status bits and test the BUSY bit
  while( GLCD_DATA & 0x80);
  TRISD = 0x00;

}

void GLCDInstructionWrite( U16 Instruction )
{

GLCDWaitBusy( ); // Wait until LCD not busy
GLCD_DI = 0; // Instruction mode
GLCD_RW = 0; // Write mode
GLCD_DATA = Instruction; // Outbyte
GLCD_EN = 1; // Strobe
Delay_us(10);
GLCD_EN = 0;

}

void GLCDSelectSide( U16 Side )
{

if( Side == RIGHT )
{
// Switch to right
GLCD_EN = 0;
GLCD_DI = 0;
GLCD_RW = 1;
GLCD_CS1 = 0;
GLCD_CS2 = 1;

GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

}
else
{
// Switch to left
GLCD_EN = 0;
GLCD_DI = 0;
GLCD_RW = 1;
GLCD_CS1 = 1;
GLCD_CS2 = 0;

GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

}

}

void GLCDDataWrite( U16 Data )
{

GLCDWaitBusy( ); // Wait until LCD not busy
GLCD_DI = 1; // Data mode
GLCD_RW = 0; // Write mode
GLCD_DATA = Data; // Outbyte
GLCD_EN = 1; // Strobe
Delay_us(10);
GLCD_EN = 0;

}

void GLCD_ClearScreen( )
{

U16 Page = 0;
U16 Column = 0;
// Process the 8 pages of the GLCD
for( Page = 0; Page < 8; Page++ )
{

GLCDSelectSide( LEFT ); // Select left side
GLCDInstructionWrite( X_ADRESS | Page ); // Set the page number
GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

// Process a page on both sides
for ( Column = 0; Column < 128; Column++ )
{

if( Column == 64 )
{

GLCDSelectSide( RIGHT ); // Select right side
GLCDInstructionWrite( X_ADRESS | Page ); // Set the page number
GLCDInstructionWrite( Y_ADRESS ); // Set column to 0

}

GLCDDataWrite( 0x00 ); // Erase a column

}

}

}

void GLCDInt( )
{
PORTB = 0;
GLCD_DATA = 0;
GLCD_DI = 0;
GLCD_RW = 0;
GLCD_EN = 0;
GLCD_CS1 = 0;
GLCD_CS2 = 0;

GLCD_RST = 1;
Delay_us(10);
GLCD_RST = 0;
Delay_us(10);
GLCD_RST = 1;

GLCDSelectSide( LEFT );
GLCDInstructionWrite( DISPLAY_OFF ); // Display OFF
GLCDInstructionWrite( START_LINE );
GLCDInstructionWrite( X_ADRESS );
GLCDInstructionWrite( Y_ADRESS );
GLCDInstructionWrite( DISPLAY_ON ); // Display ON

GLCDSelectSide( RIGHT );
GLCDInstructionWrite( DISPLAY_OFF ); // Display OFF
GLCDInstructionWrite( START_LINE );
GLCDInstructionWrite( X_ADRESS );
GLCDInstructionWrite( Y_ADRESS );
GLCDInstructionWrite( DISPLAY_ON ); // Display ON

GLCD_ClearScreen( );

}

U16 GLCDDataRead( )
{

GLCD_DATA = 0xFF; // Set LCD_DATA port in input mode
TRISD = 0xFF;
GLCD_RW = 1; // Read mode
GLCD_DI = 1; // Data mode

GLCD_EN = 0; // Strobe
Delay_us(10);
GLCD_EN = 1;
Delay_us(10);

return GLCD_DATA; // Return the data read
TRISD = 0x00;
}

void GLCDSetDot( U16 Xaxis, U16 Yaxis )
{

U16 DataRead = 0;

GLCDInstructionWrite( START_LINE ); // Set adress for line 0

// Left side
if( Xaxis < 64 )
{

GLCDSelectSide( LEFT ); // Select left side
GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis ); // Select column

DataRead = GLCDDataRead( ); // Read the current location
DataRead = GLCDDataRead( ); // on the LCD. dummy read

GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis ); // Select column
GLCDDataWrite( DataRead | ( 1 << ( Yaxis % 8 ) ) ); // Plot the dot

}
else
// Right side
{

GLCDSelectSide( RIGHT ); // Select left side
GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis - 64 ); // Select column

DataRead = GLCDDataRead( ); // Read the current location
DataRead = GLCDDataRead( ); // on the LCD. dummy read

GLCDInstructionWrite( X_ADRESS + ( Yaxis / 8 ) ); // Select page number
GLCDInstructionWrite( Y_ADRESS + Xaxis - 64 ); // Select column
GLCDDataWrite( DataRead | ( 1 << ( Yaxis % 8 ) ) ); // Plot the dot

}

GLCDInstructionWrite( START_LINE ); // Set adress for line 0

}


void GLCDRectangle( U16 Xaxis1, U16 Yaxis1, U16 Xaxis2, U16 Yaxis2 )
{

U16 CurrentValue = 0;

// Draw the two horizontal lines
for( CurrentValue = 0; CurrentValue < Xaxis2 - Xaxis1+ 1; CurrentValue++ )
{

GLCDSetDot( Xaxis1 + CurrentValue, Yaxis1 );
GLCDSetDot( Xaxis1 + CurrentValue, Yaxis2 );
}

// Draw the two vertical lines
for( CurrentValue = 0; CurrentValue < Yaxis2 - Yaxis1 + 1; CurrentValue++ )
{

GLCDSetDot( Xaxis1, Yaxis1 + CurrentValue );
GLCDSetDot( Xaxis2, Yaxis1 + CurrentValue );

}

}

void main( )
{
ANSEL = 0;
ANSELH = 0;
C1ON_bit = 0; // Turn off comparators
C2ON_bit = 0;
 
TRISB = 0;
TRISD = 0;

GLCDInt( );
//GLCDDataWrite( 0x65 );
//GLCDRectangle( 1, 1, 1, 1 );

//GLCDSetDot(0,0);

GLCDSetDot(10,10);

//GLCDSetDot(105,2);

//GLCDRectangle( 0, 0, 10, 10 );

}

--
icebox

[url=http://www.sgvulcan.com/]http://www.sgvulcan.com/[/url]

Deepak
Posts: 55
Joined: 08 Jan 2009 06:00
Location: India

#4 Post by Deepak » 05 Jun 2009 06:25

Thanks a lot for the reply icebox1710. Good news: the code is working perfectly. Started working from start and a different code. As of now I'm able to initialize the GLCD and Fill it. Next I'm trying to write a line or atleast a dot. Here is my working new code:

Code: Select all

#define GLCD_CS1  PORTJ.F0
#define GLCD_CS2  PORTJ.F1
#define GLCD_DI   PORTJ.F2
#define GLCD_RW   PORTJ.F3
#define GLCD_EN	  PORTJ.F4
#define GLCD_RS   PORTJ.F5
#define GLCD_DATA PORTD
#define X_ADRESS	  0xB8	// Adress base for Page 0
#define Y_ADRESS	  0x40	// Adress base for Y0
#define START_LINE	0xC0	// Adress base for line 0
#define DISPLAY_ON	0x3F	// Turn display on
#define DISPLAY_OFF	0x3E	// Turn display off
#define RIGHT 0
#define LEFT	1
#define BUSY	0x80
#define ON  1
#define OFF 0
#define GLCD_LEFT 0
#define GLCD_RIGHT 1
typedef unsigned char U8;
/*********************GLCD Write Function*********************/
void GLCD_WriteByte(U8 chip,U8 data)
{
 if(chip==GLCD_LEFT) // Choose which chip to write to
     GLCD_CS1=1;
 else
     GLCD_CS2=1;

 GLCD_RW=0;      // Set for writing
 GLCD_DATA=data; // Put the data on the port
 GLCD_EN=1;      // Pulse the enable pin
 Delay_ms(10);
 GLCD_EN=0;

 GLCD_CS1=0;     // Reset the chip select lines
 GLCD_CS2=0;
}
/***********************GLCD Fill Screen**********************/
void GLCD_FillScreen(U8 color) // Color is 1 for ON and 0 for OFF
{
 U8 i,j;
 // Loop through the vertical pages
 for(i=0;i<8;++i)
 {
  //GLCD_CS1=1;
  GLCD_DI=0;                               // Set for instruction
  GLCD_WriteByte(GLCD_LEFT,0b01000000);     // Set horizontal address to 0
  GLCD_WriteByte(GLCD_RIGHT,0b01000000);
  GLCD_WriteByte(GLCD_LEFT,i | 0b10111000); // Set page address
  GLCD_WriteByte(GLCD_RIGHT,i | 0b10111000);
  GLCD_DI=1;                               // Set for data
  //Loop through the horizontal sections
  for(j=0;j<64;++j)
  {
   GLCD_WriteByte(GLCD_LEFT,0xFF*color);    // Turn pixels ON or OFF
   GLCD_WriteByte(GLCD_RIGHT,0xFF*color);    // Turn pixels ON or OFF
  }
 } 
}
/********************GLCD Initialization********************/
void GLCD_Int(U8 mode)
{
 GLCD_RS=1;
 delay_us(10);
 GLCD_EN =0;
 GLCD_CS1=0;
 GLCD_CS2=0;

 GLCD_DI = 0;                    // Set for instruction
 GLCD_WriteByte(GLCD_LEFT, 0xC0); // Specify first RAM line at the top of the screen
 GLCD_WriteByte(GLCD_RIGHT, 0xC0);
 GLCD_WriteByte(GLCD_LEFT, 0x40); // Set the column address to 0
 GLCD_WriteByte(GLCD_RIGHT, 0x40);
 GLCD_WriteByte(GLCD_LEFT, 0xB8); // Set the page address to 0
 GLCD_WriteByte(GLCD_RIGHT, 0xB8);
 if(mode==ON)
 {
  GLCD_WriteByte(GLCD_LEFT,0x3F); // Turn the display ON
  GLCD_WriteByte(GLCD_RIGHT,0x3F);
 }
 else
 {
  GLCD_WriteByte(GLCD_LEFT,0x3E); // Turn the display OFF
  GLCD_WriteByte(GLCD_RIGHT,0x3E);
 }
 //GLCD_FillScreen(OFF);           // Clear the display
}
/*************************Main Function**********************/
void main()
{
 TRISD=0;
 TRISJ=0;
 GLCD_Int(ON);
 for(;;){
 GLCD_FillScreen(ON);
 Delay_ms(1000);
 GLCD_FillScreen(OFF);}
}
All the best :)

Deepak
Posts: 55
Joined: 08 Jan 2009 06:00
Location: India

#5 Post by Deepak » 05 Jun 2009 12:16

Hello,

I'm now trying to access each pixel on the GLCD, but I can access 8 bits/pixels together but not individually. Please help me with that. Thank you.

Deepak
Posts: 55
Joined: 08 Jan 2009 06:00
Location: India

#6 Post by Deepak » 10 Jun 2009 10:22

finally have the perfect woking complete code for the GLCD. Will post it if anyone requires it.. Cheers :D

icebox1701
Posts: 15
Joined: 20 Apr 2009 21:44

#7 Post by icebox1701 » 10 Jun 2009 11:35

hey, great news.

I sure would like to see your code

I also managed to port the free ks0108 library from http://en.radzio.dxp.pl/ks0108/ but I still have problems with text and bitmaps. I intend to post-it when it's done
--
icebox

[url=http://www.sgvulcan.com/]http://www.sgvulcan.com/[/url]

Deepak
Posts: 55
Joined: 08 Jan 2009 06:00
Location: India

#8 Post by Deepak » 11 Jun 2009 06:08

Hi icebox1701, now I'm fine tuning the code, as in adding comments wherever required, using appropriate names for variables,etc.. to makes things easy to understand. Will post it latest by this evening :D

asanto
Posts: 5
Joined: 08 Nov 2009 04:52

#9 Post by asanto » 17 Nov 2009 04:24

Woa! A long time to see your code!

Deepak
Posts: 55
Joined: 08 Jan 2009 06:00
Location: India

Re:

#10 Post by Deepak » 29 Apr 2010 06:47

asanto wrote:Woa! A long time to see your code!
I said I'l send it to people who NEED it.. Not people who check this thread after FIVE months and go "Woa! A long time to see your code!"

Post Reply

Return to “mikroC General”