mUNISH,
This is exactly as was in my Display before the new code,
Actually the display chip drives 102x67 pixels, but only the top left 84x48 pixels are displayed.
This explains why the 11 rows are garbage, as they have not been cleared yet!
They are filled with undefined/random data after a reset.
The display driver wraps a row (8 pix) after 102 pixels and not 84 pixels. That is why the display is 'eating up' 3 characters (6*3=18 pixels).
The Driver chip has no documented command to shift the display down by some pixels, but still there is a workaround.
Remove bank 0 form the display by shifting the display 5 rows up using 0x45 command. It will now comprise of Banks 1-6. Use Banks 1-6 for displaying. Use a software address counter by storing the current x and y address and changing the row manually.
I have been able to make 3 such 'defective' displays work 'normally' using this code snippet written using SDCC for 89S52:
Unfortunately, I broke the LCD just after experimentation and don't have a photograph for it. But I can vouch that it will work 200% for sure.
Use NEW=1 for 'defective' display, NEW=0 for older displays.
Code:
#define NEW 1 // For new lcd, set it to 1, for old 0
unsigned char cx,cy;
#define clockSCL() SCLK=0; SCLK=1;
// Software SPI to LCD
void lcdOut(unsigned char dat)
{
CS=0;
SDIN=dat&0x80;
clockSCL();
SDIN=dat&0x40;
clockSCL();
SDIN=dat&0x20;
clockSCL();
SDIN=dat&0x10;
clockSCL();
SDIN=dat&0x08;
clockSCL();
SDIN=dat&0x04;
clockSCL();
SDIN=dat&0x02;
clockSCL();
SDIN=dat&0x01;
clockSCL();
CS=1;
}
// Write a command to LCD
void lcdCom(unsigned char dat) { DC=0; lcdOut(dat); }
// Write data to LCD
void lcdData(unsigned char dat)
{
DC=1; lcdOut(dat);
#if NEW
// Implementation of a software address counter
cx++;
if (cx > 83)
lcd_gotoxy(0,cy+1);
if (cy > 5)
lcd_gotoxy(cx,0);
#endif
}
// Initialize the LCD
void initLCD(void)
{
CS=1;
RST=1;
_delay_ms(200); // Software delay routine - change with your own
RST=0; // Hardware Reset Initiation
_delay_ms(200); // Software delay routine - change with your own
RST=1;
lcdCom(0x21); // Extended Instruction Set
#if NEW
lcdCom(0xE4); // A large VOP for new displays
lcdCom(0x45); // New LCD Correction (Y offset +5)
#else
lcdCom(0x90); // VOP values for older displays
#endif
lcdCom(0x06); // Temp. coefficient
lcdCom(0x13); // VBias
lcdCom(0x20); // Normal Instruction Set
lcdCom(0x09); // All on (display black)
_delay_ms(750); // Software delay routine - change with your own
clearLCD(); // Clear DDRAM
lcdCom(0x08); // Display Blank
_delay_ms(50); // Software delay routine - change with your own
lcdCom(0x0C); // Normal Mode
home(); //Home cursor
}
// Cursor positioning
void lcd_gotoxy(unsigned char x, unsigned char y)
{
lcdCom(0x80|(x&0x7F)); // X Address Set 1XXX XXXX
#if NEW
// Use bank 1-6 for new displays
lcdCom(0x40|((y+1)&0x07)); // Y Address Set 0100 0YYY+1
cx=x;cy=y;
#else
// Use bank 0-5 for old displays
lcdCom(0x40|(y&0x07)); // Y Address Set 0100 0YYY
#endif
}
// Clear DDRAM
void clearLCD()
{
int i;
home();
for (i=0;i<504;i++)
lcdData(0x00);
}
//cursor home
void home() { lcd_gotoxy(0,0); }
SCE, SDIN, RST and SCLK have their usual meanings.
And yes, regarding your other queries:
The controller is definitely different from the earlier PCD8544, but is compatible with its opcodes, and will certainly work 100% with the modifications proposed.
The Nokia 3310 displays will work fine from 3V to 5V VCC. The 7V Mentioned in the datasheet is about the LCD Driving voltage, which is internally generated from the supply voltage through a charge pump inside the IC, as a high potential is required to change the phase of liquid crystals inside the LCD.
For any code compilation errors or further display problems, do PM me with a proper screenshot of the LCD so that I may help you further.
With regards
Abhishek.