CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

t6963c graphical lcd drivers
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
newguy



Joined: 24 Jun 2004
Posts: 1504
Location: Edmonton, Alberta

View user's profile Send private message

t6963c graphical lcd drivers
PostPosted: Mon Jul 19, 2004 10:26 am     Reply with quote

Edit (update Feb 11 2005):

Just got this message from Treitmey:

Quote:
Found that in the read of data, some of my hardware requires that
that an #asm nop #endasm is needed before latching the data.
Some of the documentation also states wait 150nS. I figured 1 noop is enough.

Can you update you listing in the code library as such.
for read and readbyteauto.


Done. Thanks Treitmey!


Hi,

Here's some code that Treitmey originally posted some time ago - I modified it a bit. It's a complete set of drivers for a graphical lcd equipped with the toshiba T6963C controller.

The hookup is really easy - you only need 8 data lines, and an additional 4 control lines: /WR, /RD, C/D (command/data), and /RESET. There is a document regarding the 6963 chip somewhere on the 'net that says that you also need to hook up the /CE signal, but you don't. Just tie it to ground, along with the FS pin (font select), which will give you 8x8 sized spaces for characters (the characters are always 5x7, regardless of the state of the FS pin).

The only function of the display that I haven't implemented is the user-defined characters in the text mode.

Most of the 240x64 displays come with 8k RAM, which is enough for about 4 full unique displays. To quickly switch between these displays, just set the graphics home to the base address of the new screen/picture.

Anyway, here's some sample code (18F452 @ 4 MHz) that I cut & pasted from a project that I'm currently working on. That's the reason why the interrupts are enabled, but there are no interrupt routines.

Code:
#include <18F452.h>
#device *=16
#device adc=10
#use delay(clock=4000000,RESTART_WDT)
#fuses XT, BROWNOUT, BORV27, PUT, STVREN, NOLVP

/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// This file contains drivers for using a Tosiba T6963C controller ////
//// in parallel/8080(intel) mode.  The T6963C is 240 pixels across  ////
////  and 64 pixels down. The driver treats the upper left pixel 0,0 ////
////                                                                 ////
////  Connections are as follows:                                    ////
////  /WR - - C4                                                     ////
////  /RD - - C5                                                     ////
////  C//D- - C6                                                     ////
////  /RST- - C7                                                     ////
////  DATA0-7 PORTD0-7                                               ////
////  LCD's FS is tied low (FS = 0 is 8x8 font)                      ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////

// 240 x 64 in the 8x8 font mode means that 30 characters across by
// 8 rows of characters may be displayed

#define set_tris_lcd(x) set_tris_d(x)
//TRIS DataBus=x,  note:control bus (PORTC) always outputs
const int16 TextHome = 0x0780;
const int8  TextArea = 0x001E; // how many bytes before a new line
const int16 GraphicsHome = 0x0000;
const int8  GraphicsArea = 0x001E; // how many bytes before a new line

const int8 AutoModeWrite = 0xB0;
const int8 AutoModeRead  = 0xB1;
const int8 AutoModeReset = 0xB2;

const int8 LCDModeSet  = 0x80;   // send this OR'd with the following
const int8 LCDMode_OR  = 0b0000;
const int8 LCDMode_XOR = 0b0001;
const int8 LCDMode_AND = 0b0010;
const int8 LCDMode_TA  = 0b0100; // TEXT ATTRIBUTE mode.
const int8 LCDMode_RAM = 0b1000; // 1=CG RAM, 0=internal CG ROM

const int8 LCDSetCursorPtr  = 0x21;  // cursor address
const int8 LCDSetCursorSize = 0xA0;  // 1 line cursor

const int8 LCDDispMode = 0x90;   // send this OR'd with the following
const int8 LCDDisp_BLK = 0b0001;
const int8 LCDDisp_CUR = 0b0010;
const int8 LCDDisp_TXT = 0b0100;
const int8 LCDDisp_GRH = 0b1000;

struct lcd_pin_def
{
   BOOLEAN unused1;    // C0
   BOOLEAN unused2;    // C1
   BOOLEAN unused3;  // C2
   BOOLEAN unused4;  // C3
   BOOLEAN w_bar;  // C4 Write bar active low
   BOOLEAN r_bar;  // C5 Read bar active low
   BOOLEAN cd;         // C6 Command/Data BAR   1=command 0=data
   BOOLEAN reset_bar;  // C7 Reset active low
   int  data    :  8;  // PortD=Data bus
};
struct lcd_pin_def  LCD;

#byte LCD = 0xf82    // portC address on 18F452

int   glcd_ReadByte(void);
void  glcd_WriteByte(int1 cd, int data);
void  glcd_WriteByteAuto(int data);
void  glcd_WriteCmd2(int16 data, int cmd);
void  glcd_WriteCmd1(int data, int cmd);
void  glcd_gotoxy(int x, int y, int1 text);

void glcd_init(void) {
  int16 counter;
  set_tris_lcd(0xff);   //TRIS DATA bus,note:control bus always outputs

  LCD.w_bar = 1;      // INITIAL STATES OF CONTROL PINS
  LCD.r_bar = 1;      //
  LCD.cd = 1;         // command

  LCD.reset_bar = 0;  // perform a reset
  delay_us(10);      // delay for a reset
  LCD.reset_bar = 1;  // run

  // Set up the graphics and text areas
  glcd_WriteCmd2(TextHome, 0x40);
  glcd_WriteCmd2(TextArea, 0x41);
  glcd_WriteCmd2(GraphicsHome, 0x42);
  glcd_WriteCmd2(GraphicsArea, 0x43);

  // set address to 0
  glcd_WriteCmd2(0x0000, 0x24);
  glcd_WriteCmd2(0x0000, 0x24);

  // Clear all RAM of LCD (8k)
  glcd_WriteByte(1, AutoModeWrite);
  for (counter = 0; counter < 0x1fff; counter++)
  {
    glcd_WriteByteAuto(0);    // fill everything with zeros
  }
  glcd_WriteByte(1, AutoModeReset);
}

void glcd_WriteByte(int1 cd, int data)
{
    int status = 0, temp = 0;
    set_tris_lcd(0xff);
    LCD.w_bar = 1;
    LCD.r_bar= 1;
    LCD.cd = 1;//defaults

    while (status != 0x03) {  // is LCD busy?
       LCD.r_bar= 0;
       temp = LCD.data;
       LCD.r_bar = 1;
       status = temp & 0x03;
    }

    set_tris_lcd(0x00);    // All outputs
    LCD.cd = cd;           // Command/Data bar
    LCD.data = data;
    LCD.r_bar = 1;         // not read
    LCD.w_bar = 0;         // write
    LCD.w_bar = 1;         // release
}

void glcd_WriteByteAuto(int data)
{
   int status = 0, temp = 0; // status bits ARE DIFFERENT BITS THAN NORMAL
   set_tris_lcd(0xff);
   LCD.w_bar = 1;
   LCD.r_bar = 1;
   LCD.cd = 1; // defaults

   while (status != 0x08) {  // is LCD busy?
     LCD.r_bar = 0;
     temp = LCD.data;
     LCD.r_bar = 1;
     status = temp & 0x08;
   }

   set_tris_lcd(0x00);     // All outputs
   LCD.cd = 0;             // This is always data, cd=0
   LCD.data = data;        // Put data on data bus
   LCD.w_bar = 0;          // write
   LCD.w_bar = 1;          // release
}

void glcd_WriteCmd1(int data, int cmd)
{
  glcd_WriteByte(0, data);
  glcd_WriteByte(1, cmd);
}

void glcd_WriteCmd2(int16 data, int cmd)
{
  glcd_WriteByte(0, data & 0xff);
  glcd_WriteByte(0, data>>8);
  glcd_WriteByte(1, cmd);
}

int glcd_ReadByte(void)
{
  int data = 0, status = 0, temp = 0;
  set_tris_lcd(0xff);
  LCD.w_bar = 1;
  LCD.r_bar = 1;
  LCD.cd = 1;  // defaults

  #asm nop #endasm

  while (status != 0x03) {  // is LCD busy?
    LCD.r_bar = 0;
    temp = LCD.data;
    LCD.r_bar = 1;
    status = temp & 0x03;
  }

  LCD.cd = 0;          // Command/Data bar
  LCD.r_bar = 0;        // read
  /////////////////////////////////////////////////////////
  #asm nop #endasm    // THIS PAUSE IS VERY NESSESARY !!!//
  /////////////////////////////////////////////////////////
  data = LCD.data;
  LCD.r_bar = 1;
  LCD.cd = 1;
  return data;        // Return the read data
}

void glcd_putc(char c) {
   glcd_WriteCmd1(c - 0x20, 0xc0);
}

void glcd_gotoxy(int x, int y, int1 text) { // sets memory location to screen location x, y
   // location 1,1 is upper left corner;  text = 1 (text area), text = 0 (graphics area)
   int16 location, home;
   int line;

   if (!text) {
      home = GraphicsHome;
      line = GraphicsArea;
   }
   else {
      home = TextHome;
      line = TextArea;
   }

   location = home + (((int16)y - 1) * line) + x - 1;
   glcd_WriteCmd2(location, 0x24);
}

#use fast_io(D)

void main() {

   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_DIV_8);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_ON);
   setup_timer_0(RTCC_DIV_256|RTCC_8_bit);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_AD);
   enable_interrupts(INT_RB);
   enable_interrupts(global);

   set_tris_c(0x00);  // graphic lcd control lines all output
   glcd_init();
   glcd_WriteByte(1, (LCDModeSet|LCDMode_XOR));
   glcd_WriteByte(1, (LCDDispMode|LCDDisp_TXT|LCDDisp_GRH));
}


The above code will initialize the graphic lcd. If you wanted to display "Hi there" beginning at screen location column 4, row 3, then these two commands will do that:

Code:
glcd_gotoxy(4,3,1); // 1 = text area of memory; note that there are only
                             // 8 rows of text possible
glcd_putc("Hi there");


If you wanted to create an 8 pixel x 8 pixel black square with the upper left corner of the square located at 9 pixels in from the left, and 43 pixels down from the top, then this code will do that:

Code:
int n;
for (n = 0; n< 8; n++) {
   glcd_gotoxy(2,43+n,0);  // 0 = graphics memory area;  note that there
   // are still 30 columns (30 x 8 pixels = 240), but now there are now 64
   // rows so pixel location 9,43 translates into column 2, row 43.  A little
   // confusing, I know, but that's the way it works.
   glcd_WriteCmd1(0xff,0xc0);
}


Last edited by newguy on Mon Apr 25, 2005 9:24 am; edited 6 times in total
The Puma



Joined: 23 Apr 2004
Posts: 227
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Jul 20, 2004 10:58 am     Reply with quote

How can i convert this source to use it on a PIC16F877

The lcd i used is a 128x128LCD
http://www.lcdchina.com/LCDMODULES/im/GDM128128A.pdf

newguy,
please can you convert ( or help me ) to use this lcd with a pic16F877

Thanks
newguy



Joined: 24 Jun 2004
Posts: 1504
Location: Edmonton, Alberta

View user's profile Send private message

changes for 16f877
PostPosted: Tue Jul 20, 2004 11:46 am     Reply with quote

Assuming that your graphical lcd also uses the toshiba controller, there's really only 2 things you need to change:

1. Where it says
Code:
#byte LCD = 0xf82 // portC address on 18F452
, change the address from 0xf82 to 7. The place to find this is in Microchip's datasheet for the 16F877 - look for "Special Function Registers" in the datasheet's table of contents.

2. Where it says
Code:
const int8 TextArea = 0x001e; // how many bytes before a new line
, change this to 0x0010, which would be the number of bytes wide your screen is (0x0010 = 16 = 128 dots/8 dots/byte). Also change the GraphicsArea to 0x0010 as well.
William H. Conley III



Joined: 27 May 2004
Posts: 17
Location: Tucson, AZ

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Jul 29, 2004 2:47 pm     Reply with quote

do you need the "#device *=16" ?
newguy



Joined: 24 Jun 2004
Posts: 1504
Location: Edmonton, Alberta

View user's profile Send private message

PostPosted: Thu Jul 29, 2004 3:19 pm     Reply with quote

No, you don't need the #device *=16.
xmen



Joined: 30 Jul 2004
Posts: 2

View user's profile Send private message

PostPosted: Fri Jul 30, 2004 9:10 pm     Reply with quote

Hello newguy:

May you put some example to draw a box or a line, with your routines ?
I don't understand your example to draw a black square.

Also, if may you put some example to set ON and set OFF a specific pixel.

I don't see in your source code, function to clear screen.

Kind regards.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message

PostPosted: Mon Aug 02, 2004 10:51 am     Reply with quote

This is my clear screen routine
Code:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
// Purpose:       Clears LCD RAM
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
void glcd_clr(int16 location,int16 size)
{
  ////fprintf(DEBUG,"loc=%lu  size=%lu\n\r",location,size);
  // look very simular to the init,... doesn't it. : )
  glcd_WriteCmd2(location,LCDSetPtr);
  glcd_WriteCmd0(AutoModeWrite);
  for (;size;size--)
  {
    glcd_WriteByteAuto(0x00);//clear ram
  }
  glcd_WriteCmd0(AutoModeReset);
}


and get the location using a define
#define LCDTxtAdr(s,x,y) 0x780+(240*s)+(AreaSet_T*y)+x
//that is the screen,x position , y position

so the call looks like

glcd_clr(LCDTxtAdr(SCRN0,0,0),CharPerScn);


Hope this helps
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message

PostPosted: Mon Aug 02, 2004 10:54 am     Reply with quote

by the way,.. I use this define to print text all the time.

Code:

  glcd_WriteCmd2(LCDTxtAdr(SCRN0,2,2),LCDSetPtr);//(screen,x,y)
  printf(glcd_putc, "ADDRESS=%u",MyAddr);
ganeshbook



Joined: 09 Sep 2006
Posts: 1

View user's profile Send private message

GDM128128A
PostPosted: Sat Sep 09, 2006 4:09 am     Reply with quote

Hi,
This is ganesh. I am using 128 * 128 graphical display(t6963c) and it was succesfully initialised. But i cant able to change the font size from 5*8 to 8*8. What should i do.

Can U help me.
Thanking U.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message

PostPosted: Tue Sep 12, 2006 7:38 am     Reply with quote

On my board this is done with a jumper to the FS pin on the header.
From Hantronix AppNote.
A zero on FS will place a 5x7 pixel character in a 8x8 field.((30 char/line))
A one on FS will place a 5x7 pixel character in a 6x8 field.
((240/6=40 char /line))
NOTE THAT THE FONT IS STILL 5x7...It is just the field that changes
zhiling0229



Joined: 13 Sep 2006
Posts: 10

View user's profile Send private message

PostPosted: Thu Sep 14, 2006 9:52 am     Reply with quote

hi,

just want to know if I'm using Port A.0 as C/D, A.1 as read, A.2 as write, A3 as reset and Port B as data bus, what instruction should i change?

I'm using 16f877a

Thanks
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message

PostPosted: Thu Sep 14, 2006 1:26 pm     Reply with quote

Try the
struct lcd_pin_def LCD;
#byte LCD = 0xf82 // portC address on 18F452
and related tris.
Note also that port a is probably "open collector"
zhiling0229



Joined: 13 Sep 2006
Posts: 10

View user's profile Send private message

PostPosted: Sat Sep 16, 2006 9:06 am     Reply with quote

Hi guys,

I just tested the code and it works Very Happy

But I'm using a 240x120 display

I was wondering what value should I change for 1FFF to clear all the ram value on the screen :

// Clear all RAM of LCD (8k)
glcd_WriteByte(1, AutoModeWrite);
for (counter = 0; counter < 0x1fff; counter++)
{
glcd_WriteByteAuto(0); // fill everything with zeros
}
glcd_WriteByte(1, AutoModeReset);
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message

PostPosted: Mon Sep 18, 2006 8:13 am     Reply with quote

Just so you know. You should ask questions in main forum. NOT here in the code library.

1 bit of memory for every 1 bit on screen. so...
I think its just 240*120=0x7080=28800

Will that nuber fit in the variable size alloted?
newguy



Joined: 24 Jun 2004
Posts: 1504
Location: Edmonton, Alberta

View user's profile Send private message

PostPosted: Mon Sep 18, 2006 8:58 am     Reply with quote

zhiling0229 wrote:
Hi guys,

I just tested the code and it works Very Happy

But I'm using a 240x120 display

I was wondering what value should I change for 1FFF to clear all the ram value on the screen :

// Clear all RAM of LCD (8k)
glcd_WriteByte(1, AutoModeWrite);
for (counter = 0; counter < 0x1fff; counter++)
{
glcd_WriteByteAuto(0); // fill everything with zeros
}
glcd_WriteByte(1, AutoModeReset);


I'm a little confused. You say it works, yet you ask about clearing a 240x120 display.

The t6963c controller has 8k of RAM built-in. 8k is enough for 65,536 individual pixels (8,192 bytes x 8 pixels/byte), and a 240 x 120 display only has 28,800. The routine, as it stands, should clear the display without any modifications.

However, if you have a display with TWO t6963c controllers, it will not.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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