Author Topic: LCD LMG6640ULBC (circa '93)  (Read 2722 times)

Offline RDC

  • Administrator
  • Around the block
  • *
  • Posts: 2609
  • Post quality +90/-2
  • Gender: Male
  • The CGnome Project
LCD LMG6640ULBC (circa '93)
« on: May 14, 2014, 11:24:30 PM »
I've had this dinosaur sitting around here for awhile now. It's a 480 x 128 Dot Matrix display from an old Smith Corona word processor from 1993.

I always had the intention of using it for something, but for those of you other older farts around here, or any that are familiar with this kind of display, you'll know that it's far from being easy to use for anything at all without some type of driver as the LCD is just setup to take in 480 x 128bits of data, so it's not any kind of plug and play, or even simple to code for like newer LCDs are where the character/graphics driver is built into them. With this thing, it's almost all done manually, and anything you want displayed has to be done one bit at a time.





I still had the motherboard from it as well, so firing it up for a test was still possible.




Regardless of the PITA it was going to be, I decided to mess with it some and now that I have the pinout and such figured out, I wanted to get it all documented a bit as most info on this thing that's around is 10 years old and incomplete. No real shocker there.

The LCD uses 8 ICs..

6 x LC7941 - Segment Driver
2 x LC7942 - Common Driver
1 x LA6324N - Quad Op-Amp (for making the different voltages)
1 x 53003HEB-S (This is used at the least to generate the M signal)

The LCD has only one 10 pin connector. After tracing it out and comparing to DataSheets...

1 - SDI (for IC3, left side 240 x 128)
2 - SDI (for IC6, Right side 240 x 128)
3 - DIO1 (FRAME signal)
4 - Not Used
5 - LOAD_CP (LATCH clock)
6 - CP (DATA Shift Clock, 2MHz)
7 - VCC (5v)
8 - VSS (Ground for ICs)
9 - Ground for LA6324N, -13v
10 - Shielding (connect to pin 8)

It uses a fluorescent bulb and diffuser for the backlight, and the Inverter takes 5v.

Now since I still had the motherboard from the old Smithy, it was easy enough to wire most of it back up (minus the keyboard and disk drive as they're gone) and then put the Logic Analyzer on it just to see what was going on there.



That's only 2.5 seconds data, which is mostly just the start up splash screen.



In order to make the SMITH in the SMITH CORONA there at the top of the display, it takes this much data, and it needs to be repeated several times as the refresh rate of these types of display are not great, plus if just a single image is input and left on them too long it will burn in, but inputting the same image over and over causes the M signal to change and the voltages to change so the chance of burn in is reduced. It can still happen if the same image is going to be displayed on there for extended periods though.



To put it simply, and even then it's really not, to display any kind of data on this thing you have to tell every single one of the Dots what it needs to be, regardless of how many you want to use, and then repeat that data continuously or implement some type of moving screen saver so the crystals in there don't get stuck and cause burn in.

What is as simple as typing..

char message0[] = "SMITH";

..to display SMITH on a typical 16x2 LCD screen you can get now, takes lines upon lines upon lines of code to do on a Dot Matrix LCD like this as there is no character generation built into it like on the more common 16x2 LCDs have.

This is just the top line of the SMITH CORONA and logo. The SDIL (brown) is for the Left half of the screen so that data is input later so it's more in the middle of the screen, then the SDIR (red) is for the Right half of the screen and it's input first so it appears in the middle. The SDIR Dats is actually shown after the SDIL data on the screen, but it's input before it as the 480bits are split into two 240 x 128 layouts.



If all 480bits of that Data were looked at, which I can't type out here as there isn't enough width, there would be a mess of 1s (193 to be exact) then just looking at the ------------------------- SMITH part, it would look like this, again followed by another mess of 1s (222 this time)...

(193 1s) 00000000000000000000000001111111000001101111110100100000010011100 (222 more 1s) The first 24 0s there are part of the logo.

Now if you looked at the next 7 lines as well as that one, minus the first 24 spots as that's part of the logo, you can make out the SMITH in the 0s. Then on the LCD, the 1s are White, while the 0s are Blue.

Code: [Select]
1000001101111110100100000010011100 -  00000  0      0 00 000000 00   00
0000001100111100100100000010011100 - 000000  00    00 00 000000 00   00
0011110100011000100111001110011100 - 00    0 000  000 00   00   00   00
1000011100000000100111001110010000 -  0000   00000000 00   00   00 0000
1100001100100100100111001110010000 -   0000  00 00 00 00   00   00 0000
0111100100111100100111001110011100 - 0    00 00    00 00   00   00   00
0000000100111100100111001110011100 - 0000000 00    00 00   00   00   00
1000001100111100100111001110011100 -  00000  00    00 00   00   00   00

Just taking the left half of the screen, 240 x 128, to display a solid white screen, that is all dots 'on', you need to input 1, 30720 times. That is 30720 bits in 240bit serial data with a Latch Clock on the 240th bit, then the Frame signal after the 128th Latch, don't that sound fun?

So in code you have what boils down to..
Code: [Select]
SDI = 1; // Set the Data to 1
   
CP = 0; // Clock that in 239 times, falling edge triggered
CP = 1; // This is only one clock

LOAD_CP = 1; // Then on the 240th clock have the Latch Hi so it's clocked in to know that line is done with.
CP = 0;
CP = 1;
LOAD_CP = 0;

// And there you have 1 line of 240bits of the 128 lines done, then do that 127 more times.

DIO1 = 1; // Then after the 240th clock and the 128th Latch you have Frame and Latch Hi and clock those in together.
LOAD_CP = 1;
CP = 0;
CP = 1;
LOAD_CP = 0;
DIO1 = 0;

// There you have 1 Frame of Data, or all 1s on the screen, but that needs to be repeated over and over so the M signal can alternate and the screen doesn't burn in.

It's not possible to change data too quickly or it will not be seen or look faded out, as mentioned the refresh rate isn't incredible on this type of display.


Because of the massive amount of data involved here, you can't really do much at all with a PIC or the like on it's own. You'll need to get some type of RAM and EEP to use as a display buffer as well as some place to store the huge amounts of data it takes to just make up simple things like characters.

As mentioned earlier, with newer LCDs all that's really needed in code is just..

char message0[] = "ACIDMODS";

But on this thing, getting ACIDMODS on there means it needs something more like this..

Code: [Select]
/*******************************************************************************
PIC18F26K22 16MHz PLLx4 (64MHz)

LCD Dot Matrix Display LMG6640ULBC

RDC 2014
*******************************************************************************/

#define SDIL LATB0_bit
#define SDIR LATB1_bit
#define CP LATB3_bit
#define LOAD_CP LATB4_bit
#define DIO1 LATB5_bit

int counting = 0;
int i = 0;

char LINE_1_1 = 0b10011000;
char LINE_1_2 = 0b10100110;
char LINE_1_3 = 0b01001000;
char LINE_1_4 = 0b10011000;
char LINE_2_1 = 0b01101011;
char LINE_2_2 = 0b10101010;
char LINE_2_3 = 0b10101010;
char LINE_2_4 = 0b10101011;
char LINE_3_1 = 0b01101011;
char LINE_3_2 = 0b10101010;
char LINE_3_3 = 0b10101010;
char LINE_3_4 = 0b10101011;
char LINE_4_1 = 0b00001011;
char LINE_4_2 = 0b10101010;
char LINE_4_3 = 0b10101010;
char LINE_4_4 = 0b10101000;
char LINE_5_1 = 0b01101011;
char LINE_5_2 = 0b10101010;
char LINE_5_3 = 0b11101010;
char LINE_5_4 = 0b10101110;
char LINE_6_1 = 0b01101011;
char LINE_6_2 = 0b10101010;
char LINE_6_3 = 0b11101010;
char LINE_6_4 = 0b10101110;
char LINE_7_1 = 0b01101011;
char LINE_7_2 = 0b10101010;
char LINE_7_3 = 0b11101010;
char LINE_7_4 = 0b10101110;
char LINE_8_1 = 0b01101000;
char LINE_8_2 = 0b10100110;
char LINE_8_3 = 0b11101000;
char LINE_8_4 = 0b10011000;

// Initialize the PIC
void INIT() {
 CTMUCONH = 0b00000000;
 CTMUCONL = 0b00000000;
 CTMUICON = 0b00000000;
 PMD0 = 0b11111111;
 PMD1 = 0b11111111;
 PMD2 = 0b00001111;
 ANSELA = 0b00000000;                     // All AN are Digital
 ANSELB = 0b00000000;                     // All AN are Digital
 ANSELC = 0b00000000;                     // All AN are Digital
 TRISA = 0b00000000;                      // PORTA
 TRISB = 0b00000000;                      // PORTB, pins 6 and 7 also for ICSP
 TRISC = 0b00000000;                      // PORTC
 TRISE = 0b00001000;                      // PORTE, only 1 pin, RE3

 SDIL = 0;
 SDIR = 0;
 DIO1 = 0;
 LOAD_CP = 0;
 CP = 0;
}


void CLK(){
  CP = 0;
  CP = 1;
}

void LATCH(){
  LOAD_CP = 1;
  CLK();
  LOAD_CP = 0;
}

void FRAME(){
  DIO1 = 1;
  LOAD_CP = 1;
  CLK();
  LOAD_CP = 0;
  DIO1 = 0;
}

void main(){

 INIT();

  delay_ms(2);
  DIO1 = 1;
  delay_ms(2);
  DIO1 = 0;

  delay_ms(100);

   for (i = 0; i < 10; i++)
   {CLK();}

  LOAD_CP = 1;
  CLK();
  LOAD_CP = 0;

while (1){

  SDIR = 1;

  counting =  60;
  do{
 
   for (i = 0; i < 239; i++)
   {CLK();}

  LATCH();

  counting--;
  }while(counting != 0);

  SDIR = 1;

   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_1_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_1_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_1_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_1_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_1_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_1_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_1_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_1_4 <<= 1;
   }
   
   SDIR = 1;
 
   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();
   
   SDIR = 1;

   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_2_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_2_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_2_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_2_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_2_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_2_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_2_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_2_4 <<= 1;
   }
             
   SDIR = 1;
             
   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();
   
   SDIR = 1;

   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_3_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_3_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_3_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_3_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_3_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_3_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_3_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_3_4 <<= 1;
   }
             
   SDIR = 1;
   
   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();

   SDIR = 1;

   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_4_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_4_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_4_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_4_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_4_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_4_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_4_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_4_4 <<= 1;
   }
   
   SDIR = 1;
   
   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();

   SDIR = 1;

   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_5_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_5_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_5_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_5_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_5_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_5_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_5_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_5_4 <<= 1;
   }
   
   SDIR = 1;
           
   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();

   SDIR = 1;

   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_6_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_6_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_6_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_6_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_6_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_6_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_6_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_6_4 <<= 1;
   }
   
   SDIR = 1;

   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();
 
   SDIR = 1;

   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_7_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_7_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_7_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_7_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_7_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_7_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_7_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_7_4 <<= 1;
   }
   
   SDIR = 1;

   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();

   SDIR = 1;
 
   for (i = 0; i < 80; i++)
   {CLK();}

   for (i = 0; i < 8; i++)
   {
       if (LINE_8_1.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_8_1 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_8_2.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_8_2 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_8_3.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_8_3 <<= 1;
   }

   for (i = 0; i < 8; i++)
   {
       if (LINE_8_4.B7 == 1)
           SDIR = 1;
       else
           SDIR = 0;
       CLK();
       LINE_8_4 <<= 1;
   }
      SDIR = 1;
     
   for (i = 0; i < 127; i++)
   {CLK();}

   LATCH();

   SDIR = 1;

   counting =  60;
   do{

   for (i = 0; i < 239; i++)
   {CLK();}

   LATCH();

   counting--;
   }while(counting != 0);
 
   FRAME();
 
  LINE_1_1 = 0b10011000;
  LINE_1_2 = 0b10100110;
  LINE_1_3 = 0b01001000;
  LINE_1_4 = 0b10011000;
  LINE_2_1 = 0b01101011;
  LINE_2_2 = 0b10101010;
  LINE_2_3 = 0b10101010;
  LINE_2_4 = 0b10101011;
  LINE_3_1 = 0b01101011;
  LINE_3_2 = 0b10101010;
  LINE_3_3 = 0b10101010;
  LINE_3_4 = 0b10101011;
  LINE_4_1 = 0b00001011;
  LINE_4_2 = 0b10101010;
  LINE_4_3 = 0b10101010;
  LINE_4_4 = 0b10101000;
  LINE_5_1 = 0b01101011;
  LINE_5_2 = 0b10101010;
  LINE_5_3 = 0b11101010;
  LINE_5_4 = 0b10101110;
  LINE_6_1 = 0b01101011;
  LINE_6_2 = 0b10101010;
  LINE_6_3 = 0b11101010;
  LINE_6_4 = 0b10101110;
  LINE_7_1 = 0b01101011;
  LINE_7_2 = 0b10101010;
  LINE_7_3 = 0b11101010;
  LINE_7_4 = 0b10101110;
  LINE_8_1 = 0b01101000;
  LINE_8_2 = 0b10100110;
  LINE_8_3 = 0b11101000;
  LINE_8_4 = 0b10011000;

  }
}

..just to do 1 single Frame that gets repeated over and over to make this appear..




Now that I've got this out of my system I'm not sure what I may do with it, most likely box it up and forget about it again for years, as going any farther with it means getting into a display buffer and more hardware, but if any idea pops up I'll update this thread.

« Last Edit: December 12, 2023, 01:08:09 AM by RDC »
Screwing up is one of the best learning tools, so long as the only thing you're not learning is how to screw up.

 

SMF spam blocked by CleanTalk
SimplePortal 2.3.5 © 2008-2012, SimplePortal