Go Down

Topic: graphical lcd (nokia 3310) (Read 9512 times) previous topic - next topic

kuuk

i just wanted to tell everyone, that i got the display working. there is still much for me to do. cleaning up the code and doing the setup again with a proper voltage regulator as pointed out by massimo. the diode-method works, but i'm not satisfied with the contrast and dirtiness of this solution.

the main problem still is that the code to use the display is quite big. i managed to interface a joystick with the same board, to control a cursor. every further processing has to be done externally on another board or a computer. so goodbye DIY arduino gameboy :-)

if anyone is interested in the code or setup now, just PM me.

kuk



admin

cool

the best thing to do now is to write an article for the playground so that others can use it.

massimo

pclark

Has this been written up and posted anywhere yet?
Very interested in working with the Color LCD that SparkFun sells.

Thanks.


brainfart

http://www.display3000.com/html/screen-shots.html
http://www.shop-en.display3000.com/

sababa369

did anyone figure out a code that will work with arduino yet???

Bas-i

Hi,

there seem to be lots of pages describing how to hook one of these 3310 lcd's up but can anyone give me some pointers on how to go about to physically connect the darned thing? I followed the procedure on this page: http://www.microsyl.com/nokialcd/nokialcd.html , but simply couldn't get those wires soldered to the tiny connector! And made 2 of those little bits come off so now I need to look for another one :(

How do you guys wire the thing up?!?

kuuk

Hi Bas-l,

read the thread. it's basically all in there. the way i did it ( and how it worked for me) was basically like on the diagram and in the code. you just have to make sure that the voltage is around 3,3V max on the dipsplay.

i'd really like to help you more. But i gave away my prototype (it was a gift) and back then i didn't think it was necessary to document it... well.

i still have some displays around. i hope i'll find the time to do it again.

the code works though.

good luck,
kuk

Bas-i

Hi Kuk,

maybe I wasn't clear. My question is: how do you manage to physically connect wires to those teeny weeny small connectors on the display? I tried soldering wires directly on to them and I failed miserably, destroying 2 connectors (or rather 2 "pins", out of the 8 on the bottom/back of the display).

Are there connectors for sale somewhere that you can snap on that are easier to solder wires onto? If not, what's the trick to solder wires onto the display's connector?

I got 2 new 3310 lcd's off of ebay, for about 1$ each. Pretty cheap but would hate to ruin them as well ;)

Thanks,

Bas.

kuuk

oh i see,

i know that there are at least to versions of the same display around. one is designed to be placed with its contacts on some conducting rubber. the contacts on those are _not_ solderable, or at least not as far as i know. you can buy this "conductive rubber" and put it between the display and a custom pcb. it is not at all cheap but you only need half of a sq.centimetre. and i once saw someone offering these small pieces on ebay.

the displays i have all come from a 3310. its contacts are small copper springs. they're small but i had no problems soldering them since it's copper.

hope that helped you more.

//kuk

pclark

I still would like to know if the CODE has been posted anywhere?  Or if it would be possible for someone to send me a copy?

Thanks!

kuuk

ok, so here the working code.
part 1 because its to long for one reply...
Code: [Select]

#define LCD_X_RES                  84
#define LCD_Y_RES                  48



#define LCD_CACHE_SIZE             ((LCD_X_RES * LCD_Y_RES) / 8)

/*--------------------------------------------------------------------------------------------------
Type definitions
--------------------------------------------------------------------------------------------------*/



#define    LCD_CMD  0
#define    LCD_DATA  1

#define    PIXEL_OFF   0
#define    PIXEL_ON    1
#define    PIXEL_XOR   2

#define    FONT_1X  1
#define    FONT_2X  2


typedef unsigned int               word;
//  Mega8 port B pinout for LCD.
int CONTROL_LED=12;
int LCD_POWER_PIN      =       11;
int LCD_DC_PIN         =        2; //  PB0  4  Data Command
int LCD_CE_PIN         =        3; //  PB2  5  /CS   active low chip select ??
int SPI_MOSI_PIN       =        4; //  PB3  3  Serial   line
int LCD_RST_PIN        =        5; //  PB4  8   /RES RESET
int SPI_CLK_PIN        =        6; //  PB5  2  CLOCK

int voltometer        =         9;
// Public function prototypes

void LcdInit       ( void );
void LcdClear      ( void );
void LcdUpdate     ( void );
void LcdGotoXY     ( byte x, byte y );
void LcdChr        ( int size, byte ch );
void LcdStr        ( int size, byte *dataPtr );
void LcdPixel      ( byte x, byte y, int mode );
void LcdLine       ( byte x1, byte y1, byte x2, byte y2, int mode );
void LcdSendCmd ( byte data, int cd );


// This table defines the standard ASCII characters in a 5x7 dot format.


// Global Variables

byte  LcdCache [ LCD_CACHE_SIZE ];

int   LcdCacheIdx;
int   LoWaterMark;

int   HiWaterMark;
boolean  UpdateLcd;
char sign;
 byte ser= 0; //from serial port

// This table defines the standard ASCII characters in a 5x7 dot format.
static const byte FontLookup [][5] =
{
 {
   0x7E, 0x11, 0x11, 0x11, 0x7E     }
 ,   // A
 {
   0x7F, 0x49, 0x49, 0x49, 0x36     }
 ,   // B
 {
   0x3E, 0x41, 0x41, 0x41, 0x22     }
 ,   // C
 {
   0x7F, 0x41, 0x41, 0x22, 0x1C     }
 ,   // D
 {
   0x7F, 0x49, 0x49, 0x49, 0x41     }
 ,   // E
 {
   0x7F, 0x09, 0x09, 0x09, 0x01     }
 ,   // F
 {
   0x3E, 0x41, 0x49, 0x49, 0x7A     }
 ,   // G
 {
   0x7F, 0x08, 0x08, 0x08, 0x7F     }
 ,   // H
 {
   0x00, 0x41, 0x7F, 0x41, 0x00     }
 ,   // I
 {
   0x20, 0x40, 0x41, 0x3F, 0x01     }
 ,   // J
 {
   0x7F, 0x08, 0x14, 0x22, 0x41     }
 ,   // K
 {
   0x7F, 0x40, 0x40, 0x40, 0x40     }
 ,   // L
 {
   0x7F, 0x02, 0x0C, 0x02, 0x7F     }
 ,   // M
 {
   0x7F, 0x04, 0x08, 0x10, 0x7F     }
 ,   // N
 {
   0x3E, 0x41, 0x41, 0x41, 0x3E     }
    // O

 ,   // Y
 {
   0x61, 0x51, 0x49, 0x45, 0x43     }
   //Z
};
/*--------------------------------------------------------------------------------------------------

Name         :  LcdSendCmd

Description  :  Sends data to display controller.

Argument(s)  :  data -> Data to be sent
cd   -> Command or data (see/use enum)

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdSendCmd ( byte data, int cd )
{


 byte i = 8;

 byte mask;



 //

 if ( cd == LCD_DATA )
 {
   digitalWrite(LCD_DC_PIN,HIGH);
 }
 else
 {
   digitalWrite(LCD_DC_PIN,LOW) ;
 }




 while(0 < i) {

   mask = 0x01 << --i; // get bitmask and move to least significant bit
   // cause edge to fall
   digitalWrite(SPI_CLK_PIN,LOW); // tick
   delayMicroseconds(400);
   // set out byte
   if(data & mask){ // choose bit

     digitalWrite(SPI_MOSI_PIN,HIGH); // send 1

   }
   else{

     digitalWrite(SPI_MOSI_PIN,LOW); // send 0

   }

   // cause edge to rise

   digitalWrite(SPI_CLK_PIN,HIGH); // tock
   delayMicroseconds(400);





 }


}

/*--------------------------------------------------------------------------------------------------

Name         :  LcdInit

Description  :  Performs MCU SPI & LCD controller initialization.

Argument(s)  :  None.

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdInit ( void )
{

 int m;


 //  Toggle display reset pin.
 digitalWrite(LCD_RST_PIN,LOW);
 delay(40);
 digitalWrite(LCD_RST_PIN,HIGH);

 //  Enable SPI port: No interrupt, MSBit first, Master mode, CPOL->0, CPHA->0, Clk/4
 // SPCR = 0x50;



 LcdSendCmd( 0x21, LCD_CMD );  // LCD Extended Commands.
 LcdSendCmd( 0xB3, LCD_CMD );  // Set LCD Vop (Contrast). //B1
 LcdSendCmd( 0x04, LCD_CMD );  // Set Temp coefficent. //0x04

 LcdSendCmd( 0x13, LCD_CMD );  // LCD bias mode 1:48. //0x13
 LcdSendCmd( 0x20, LCD_CMD );  // LCD Standard Commands, Horizontal addressing mode.

 LcdSendCmd( 0x0C, LCD_CMD );  // LCD in normal mode. 0x0d for inverse
 // LcdSendCmd( 0x0D, LCD_CMD );

 //  Reset watermark pointers.
 LoWaterMark = LCD_CACHE_SIZE;
 HiWaterMark = 0;
 


 
   LcdClear();
 LcdUpdate();
}


kuuk

part 2:

Code: [Select]



/*--------------------------------------------------------------------------------------------------

Name         :  LcdContrast

Description  :  Set display contrast.

Argument(s)  :  contrast -> Contrast value from 0x00 to 0x7F.

Return value :  None.

Notes        :  No change visible at ambient temperature.

--------------------------------------------------------------------------------------------------*/
void LcdContrast ( byte contrast )
{
 //  LCD Extended Commands.
 LcdSendCmd( 0x21, LCD_CMD );

 // Set LCD Vop (Contrast).
 LcdSendCmd( 0x80 | contrast, LCD_CMD );

 //  LCD Standard Commands, horizontal addressing mode.
 LcdSendCmd( 0x20, LCD_CMD );
}

/*--------------------------------------------------------------------------------------------------

Name         :  LcdClear

Description  :  Clears the display. LcdUpdate must be called next.

Argument(s)  :  None.

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdClear ( void )
{
 int i;

 for ( i = 0; i < LCD_CACHE_SIZE; i++ )
 {
   LcdCache[i] = 0x00;
 }

 //  Reset watermark pointers.
 LoWaterMark = 0;
 HiWaterMark = LCD_CACHE_SIZE - 1;

 UpdateLcd = true;
}

/*--------------------------------------------------------------------------------------------------

Name         :  LcdGotoXY

Description  :  Sets cursor location to xy location corresponding to basic font size.

Argument(s)  :  x, y -> Coordinate for new cursor position. Range: 1,1 .. 14,6

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdGotoXY ( byte x, byte y )
{
 LcdCacheIdx = (x - 1) * 6 + (y - 1) * 84;
}

/*--------------------------------------------------------------------------------------------------

Name         :  LcdChr

Description  :  Displays a character at current cursor location and increment cursor location.

Argument(s)  :  size -> Font size. See enum.
ch   -> Character to write.

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdChr ( int size, byte ch )
{
 byte i, c;
 byte b1, b2;
 int  tmpIdx;

 if ( LcdCacheIdx < LoWaterMark )
 {
   //  Update low marker.
   LoWaterMark = LcdCacheIdx;
 }

 if ( (ch < 0x20) || (ch > 0x7b) )
 {
   //  Convert to a printable character.
   ch = 65;
 }

 if ( size == FONT_1X )
 {
   for ( i = 0; i < 5; i++ )
   {
     LcdCache[LcdCacheIdx++] = FontLookup[ch - 65][i] << 1;
   }
 }
 else if ( size == FONT_2X )
 {
   tmpIdx = LcdCacheIdx - 84;

   if ( tmpIdx < LoWaterMark )
   {
     LoWaterMark = tmpIdx;
   }

   if ( tmpIdx < 0 ) return;

   for ( i = 0; i < 5; i++ )
   {
     c = FontLookup[ch - 32][i] << 1;
     b1 =  (c & 0x01) * 3;
     b1 |= (c & 0x02) * 6;
     b1 |= (c & 0x04) * 12;
     b1 |= (c & 0x08) * 24;

     c >>= 4;
     b2 =  (c & 0x01) * 3;
     b2 |= (c & 0x02) * 6;
     b2 |= (c & 0x04) * 12;
     b2 |= (c & 0x08) * 24;

     LcdCache[tmpIdx++] = b1;
     LcdCache[tmpIdx++] = b1;
     LcdCache[tmpIdx + 82] = b2;
     LcdCache[tmpIdx + 83] = b2;
   }

   //  Update x cursor position.
   LcdCacheIdx += 11;
 }

 if ( LcdCacheIdx > HiWaterMark )
 {
   //  Update high marker.
   HiWaterMark = LcdCacheIdx;
 }

 //  Horizontal gap between characters.
 LcdCache[LcdCacheIdx++] = 0x00;
}

/*--------------------------------------------------------------------------------------------------

Name         :  LcdStr

Description  :  Displays a character at current cursor location and increment cursor location
according to font size.

Argument(s)  :  size    -> Font size. See enum.
dataPtr -> Pointer to null terminated ASCII string to display.

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdStr ( int size, byte *dataPtr )
{
 while ( *dataPtr )
 {
   LcdChr( size, *dataPtr++ );
 }
}


kuuk

part 3 and final:

Code: [Select]

/*--------------------------------------------------------------------------------------------------

Name         :  LcdPixel

Description  :  Displays a pixel at given absolute (x, y) location.

Argument(s)  :  x, y -> Absolute pixel coordinates
mode -> Off, On or Xor. See enum.

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdPixel ( byte x, byte y, int mode )
{
 word  index;
 byte  offset;
 byte  data;

 if ( x > LCD_X_RES ) return;
 if ( y > LCD_Y_RES ) return;

 index = ((y / 8) * 84) + x;
 offset  = y - ((y / 8) * 8);

 data = LcdCache[index];

 if ( mode == PIXEL_OFF )
 {
   data &= (~(0x01 << offset));
 }
 else if ( mode == PIXEL_ON )
 {
   data |= (0x01 << offset);
 }
 else if ( mode  == PIXEL_XOR )
 {
   data ^= (0x01 << offset);
 }

 LcdCache[index] = data;

 if ( index < LoWaterMark )
 {
   //  Update low marker.
   LoWaterMark = index;
 }

 if ( index > HiWaterMark )
 {
   //  Update high marker.
   HiWaterMark = index;
 }
}

/*--------------------------------------------------------------------------------------------------

Name         :  LcdLine

Description  :  Draws a line between two points on the display.

Argument(s)  :  x1, y1 -> Absolute pixel coordinates for line origin.
x2, y2 -> Absolute pixel coordinates for line end.
mode   -> Off, On or Xor. See enum.

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdLine ( byte x1, byte y1, byte x2, byte y2, int mode )
{
 int dx, dy, stepx, stepy, fraction;

 dy = y2 - y1;
 dx = x2 - x1;

 if ( dy < 0 )
 {
   dy    = -dy;
   stepy = -1;
 }
 else
 {
   stepy = 1;
 }

 if ( dx < 0 )
 {
   dx    = -dx;
   stepx = -1;
 }
 else
 {
   stepx = 1;
 }

 dx <<= 1;
 dy <<= 1;

 LcdPixel( x1, y1, mode );

 if ( dx > dy )
 {
   fraction = dy - (dx >> 1);
   while ( x1 != x2 )
   {
     if ( fraction >= 0 )
     {
       y1 += stepy;
       fraction -= dx;
     }
     x1 += stepx;
     fraction += dy;
     LcdPixel( x1, y1, mode );
   }
 }
 else
 {
   fraction = dx - (dy >> 1);
   while ( y1 != y2 )
   {
     if ( fraction >= 0 )
     {
       x1 += stepx;
       fraction -= dy;
     }
     y1 += stepy;
     fraction += dx;
     LcdPixel( x1, y1, mode );
   }
 }

 UpdateLcd = true;
}

/*--------------------------------------------------------------------------------------------------

Name         :  LcdUpdate

Description  :  Copies the LCD cache into the device RAM.

Argument(s)  :  None.

Return value :  None.

--------------------------------------------------------------------------------------------------*/
void LcdUpdate ( void )
{
 int i;
 
//always update everything for the moment
LoWaterMark = 0;
HiWaterMark = LCD_CACHE_SIZE - 1;


 if ( LoWaterMark < 0 ){
   LoWaterMark = 0;
 }
 else if ( LoWaterMark >= LCD_CACHE_SIZE ){
   LoWaterMark = LCD_CACHE_SIZE - 1;
 }

 if ( HiWaterMark < 0 ){
   HiWaterMark = 0;
 }
 else if ( HiWaterMark >= LCD_CACHE_SIZE ){
   HiWaterMark = LCD_CACHE_SIZE - 1;
 }

 //  Set base address according to LoWaterMark.
 LcdSendCmd( 0x80 | (LoWaterMark % LCD_X_RES), LCD_CMD );
 LcdSendCmd( 0x40 | (LoWaterMark / LCD_X_RES), LCD_CMD );

 //  Serialize the video buffer.
 for ( i = LoWaterMark; i <= HiWaterMark; i++ )
 {
   LcdSendCmd( LcdCache[i], LCD_DATA );
 }

 //  Reset watermark pointers.
 LoWaterMark = LCD_CACHE_SIZE - 1;
 HiWaterMark = 0;

 UpdateLcd = false;
}




void setup() {

 beginSerial(19200);
 //power the control led
 pinMode(CONTROL_LED,OUTPUT);


 pinMode(LCD_RST_PIN,OUTPUT);
 pinMode(LCD_DC_PIN ,OUTPUT);
 pinMode(LCD_CE_PIN ,OUTPUT);
 pinMode(SPI_MOSI_PIN ,OUTPUT);
 pinMode(SPI_CLK_PIN,OUTPUT);
pinMode(voltometer,OUTPUT);



 //power the display
 pinMode(LCD_POWER_PIN,OUTPUT);
 //start
 digitalWrite(CONTROL_LED, HIGH);
 analogWrite(voltometer, 150);
 LcdInit();
 




}

void loop() {

LcdClear();
delay(100);
LcdGotoXY ( 7, 3 );  
   
LcdStr(1, "OK");

LcdUpdate();

delay(500);




}



hope you can work with it.

alxblog

Thank you for the code
I have got a problem when I compile my sketch


In function 'void loop()':
error: invalid conversion from 'const char*' to 'byte*'


could you help me ?

Code: [Select]
#include <lcdnokia.h>
void setup()
{
 beginSerial(19200);
 //power the control led
 pinMode(CONTROL_LED,OUTPUT);


 pinMode(LCD_RST_PIN,OUTPUT);
 pinMode(LCD_DC_PIN ,OUTPUT);
 pinMode(LCD_CE_PIN ,OUTPUT);
 pinMode(SPI_MOSI_PIN ,OUTPUT);
 pinMode(SPI_CLK_PIN,OUTPUT);
pinMode(voltometer,OUTPUT);

 //power the display
 pinMode(LCD_POWER_PIN,OUTPUT);
 //start
 digitalWrite(CONTROL_LED, HIGH);
 analogWrite(voltometer, 150);
 LcdInit();

}

void loop()
 {
   LcdClear();
   delay(100);
   LcdGotoXY ( 7, 3 );
   LcdStr(1, "ok");
   LcdUpdate();
   delay(500);
}


I use Kuk header's file:
http://alx.alxblog.com/arduino/

Go Up