pmaggi
Joined: 05 Jun 2013 Posts: 10
|
Nokia 5110 driver |
Posted: Sat Aug 22, 2015 4:32 pm |
|
|
Hi, I found a couple of drivers in this forum for nokia 5110 lcd but all of them were mainly txt drivers. So I wrote this one that implements graphical functions like drawing pixels, lines, boxes, circles, bars...
It uses a video memory map, so you can have txt and graphics at the same time. First you "draw" everything you want to show in that memory and then dump it to the lcd.
I hope you enjoy it!.
I uploaded a video of it to youtube: https://www.youtube.com/watch?v=x6TdIBKR3N4&feature=youtu.be
Here is the code:
Code: |
///////////////////////////////////////////////////////////////////////////////
// Driver for Nokia 5110 lcd //
// Pablo Maggi - 2015 //
//Conventions about coords. //
// (x,y) means x=0..83 y=0..47 //
// [x,y] means x=0..83 y=0..5 //
// //
//Funtions provided by this driver: //
// //
//nokia_init() initializes the lcd //
//nokia_refresh() dump video memory map to lcd //
//nokia_write_command(c) Sends command c to lcd //
//nokia_write_data(c) Sends data c to lcd //
//nokia_write_dorc(c) Sends data/command to lcd //
//nokia_clean_buffer() initialize video memory map //
//nokia_contrast(contrast) sets lcd contrast (0..127) //
//nokia_gotoxy(x,y) sets cursor [x,y] position on video memory //
// map //
//nokia_printchar(c) draws character c at cursor position on video//
// memory map //
//nokia_printstr(char* m) draws a string of characters at cursor //
// position on memory map. If the string is //
// longer than the lcd width, it continues in //
// next row //
//nokia_plot(x,y,color) Draws a pixel in video memory map at coords. //
// (x,y). It draws it on or off depending on //
// the value of color, 1 or 0 //
//nokia_line(x1,y1,x2,y2,color) Draws a line between (x1,y1) and (x2,y2), on //
// or off depending on color //
//nokia_box(x1,y1,x2,y2,fill,c) Draws a box of corners (x1,y1) and (x2,y2) //
// Fill o empty depending on fill and on or off //
// depending on c //
//nokia_bar(x1,y1,x2,y2,w,c) Draws a bar from (x1,y1) to (x2,y2) with a //
// width of w and on or off depending on c //
//nokia_circle(x,y,r,f,c) Draws a cirle with center on (x,y) and radius//
// r and filled depending on f. On or off //
// depending on c //
///////////////////////////////////////////////////////////////////////////////
//Defino los pines de comunicación entre PIC y LCD
#define nok_sclk PIN_C0 // nokia lcd sclk pin 2
#define nok_sda PIN_C1 // nokia lcd sda pin 3
#define nok_dc PIN_C2 // nokia lcd d/c pin 4
#define nok_cs PIN_C3 // nokia lcd cs pin 5
#define nok_res PIN_C4 // nokia lcd res pin 8
static int8 buffer[84][6]; //defino mapa de memoria de 504 bytes, 84x6
static int8 idx=0,idy=0; //indices del mapa de memoria
char CONST TABLA1 [240] = { // tabla ASCII para LCD NOKIA: 96 filas * 5 bytes= 480 bytes
0x00,0x00,0x00,0x00,0x00, // 20 space
0x00,0x00,0x5f,0x00,0x00, // 21 !
0x00,0x07,0x00,0x07,0x00, // 22 "
0x14,0x7f,0x14,0x7f,0x14, // 23 #
0x24,0x2a,0x7f,0x2a,0x12, // 24 $
0x23,0x13,0x08,0x64,0x62, // 25 %
0x36,0x49,0x55,0x22,0x50, // 26 &
0x00,0x05,0x03,0x00,0x00, // 27 '
0x00,0x1c,0x22,0x41,0x00, // 28 (
0x00,0x41,0x22,0x1c,0x00, // 29 )
0x14,0x08,0x3e,0x08,0x14, // 2a *
0x08,0x08,0x3e,0x08,0x08, // 2b +
0x00,0x50,0x30,0x00,0x00, // 2c ,
0x08,0x08,0x08,0x08,0x08, // 2d -
0x00,0x60,0x60,0x00,0x00, // 2e .
0x20,0x10,0x08,0x04,0x02, // 2f /
0x3e,0x51,0x49,0x45,0x3e, // 30 0
0x00,0x42,0x7f,0x40,0x00, // 31 1
0x42,0x61,0x51,0x49,0x46, // 32 2
0x21,0x41,0x45,0x4b,0x31, // 33 3
0x18,0x14,0x12,0x7f,0x10, // 34 4
0x27,0x45,0x45,0x45,0x39, // 35 5
0x3c,0x4a,0x49,0x49,0x30, // 36 6
0x01,0x71,0x09,0x05,0x03, // 37 7
0x36,0x49,0x49,0x49,0x36, // 38 8
0x06,0x49,0x49,0x29,0x1e, // 39 9
0x00,0x36,0x36,0x00,0x00, // 3a :
0x00,0x56,0x36,0x00,0x00, // 3b ;
0x08,0x14,0x22,0x41,0x00, // 3c <
0x14,0x14,0x14,0x14,0x14, // 3d =
0x00,0x41,0x22,0x14,0x08, // 3e >
0x02,0x01,0x51,0x09,0x06, // 3f ?
0x32,0x49,0x79,0x41,0x3e, // 40 @
0x7e,0x11,0x11,0x11,0x7e, // 41 A
0x7f,0x49,0x49,0x49,0x36, // 42 B
0x3e,0x41,0x41,0x41,0x22, // 43 C
0x7f,0x41,0x41,0x22,0x1c, // 44 D
0x7f,0x49,0x49,0x49,0x41, // 45 E
0x7f,0x09,0x09,0x09,0x01, // 46 F
0x3e,0x41,0x49,0x49,0x7a, // 47 G
0x7f,0x08,0x08,0x08,0x7f, // 48 H
0x00,0x41,0x7f,0x41,0x00, // 49 I
0x20,0x40,0x41,0x3f,0x01, // 4a J
0x7f,0x08,0x14,0x22,0x41, // 4b K
0x7f,0x40,0x40,0x40,0x40, // 4c L
0x7f,0x02,0x0c,0x02,0x7f, // 4d M
0x7f,0x04,0x08,0x10,0x7f, // 4e N
0x3e,0x41,0x41,0x41,0x3e}; // 4f O
char CONST TABLA2 [240] = {
0x7f,0x09,0x09,0x09,0x06, // 50 P
0x3e,0x41,0x51,0x21,0x5e, // 51 Q
0x7f,0x09,0x19,0x29,0x46, // 52 R
0x46,0x49,0x49,0x49,0x31, // 53 S
0x01,0x01,0x7f,0x01,0x01, // 54 T
0x3f,0x40,0x40,0x40,0x3f, // 55 U
0x1f,0x20,0x40,0x20,0x1f, // 56 V
0x3f,0x40,0x38,0x40,0x3f, // 57 W
0x63,0x14,0x08,0x14,0x63, // 58 X
0x07,0x08,0x70,0x08,0x07, // 59 Y
0x61,0x51,0x49,0x45,0x43, // 5a Z
0x00,0x7f,0x41,0x41,0x00, // 5b [
0x02,0x04,0x08,0x10,0x20, // 5c \
0x00,0x41,0x41,0x7f,0x00, // 5d ñ
0x04,0x02,0x01,0x02,0x04, // 5e ^
0x40,0x40,0x40,0x40,0x40, // 5f _
0x00,0x01,0x02,0x04,0x00, // 60 `
0x20,0x54,0x54,0x54,0x78, // 61 a
0x7f,0x48,0x44,0x44,0x38, // 62 b
0x38,0x44,0x44,0x44,0x20, // 63 c
0x38,0x44,0x44,0x48,0x7f, // 64 d
0x38,0x54,0x54,0x54,0x18, // 65 e
0x08,0x7e,0x09,0x01,0x02, // 66 f
0x0c,0x52,0x52,0x52,0x3e, // 67 g
0x7f,0x08,0x04,0x04,0x78, // 68 h
0x00,0x44,0x7d,0x40,0x00, // 69 i
0x20,0x40,0x44,0x3d,0x00, // 6a j
0x7f,0x10,0x28,0x44,0x00, // 6b k
0x00,0x41,0x7f,0x40,0x00, // 6c l
0x7c,0x04,0x18,0x04,0x78, // 6d m
0x7c,0x08,0x04,0x04,0x78, // 6e n
0x38,0x44,0x44,0x44,0x38, // 6f o
0x7c,0x14,0x14,0x14,0x08, // 70 p
0x08,0x14,0x14,0x18,0x7c, // 71 q
0x7c,0x08,0x04,0x04,0x08, // 72 r
0x48,0x54,0x54,0x54,0x20, // 73 s
0x04,0x3f,0x44,0x40,0x20, // 74 t
0x3c,0x40,0x40,0x20,0x7c, // 75 u
0x1c,0x20,0x40,0x20,0x1c, // 76 v
0x3c,0x40,0x30,0x40,0x3c, // 77 w
0x44,0x28,0x10,0x28,0x44, // 78 x
0x0c,0x50,0x50,0x50,0x3c, // 79 y
0x44,0x64,0x54,0x4c,0x44, // 7a z
0x00,0x08,0x36,0x41,0x00, // 7b {
0x00,0x00,0x7f,0x00,0x00, // 7c |
0x00,0x41,0x36,0x08,0x00, // 7d }
0x10,0x08,0x08,0x10,0x08, // 7e ~
0x78,0x46,0x41,0x46,0x78}; // 7f ¦
//Funciones implementadas
void nokia_init(void); //inicialización del LCD
void nokia_refresh(void); //vuelco el mapa de memoria en el LCD
void nokia_write_command(int8 c); //Escribo comando
void nokia_write_data(int8 c); //escribo dato
void nokia_write_dorc(int8 c); //escritura de dato o comando
void nokia_clean_buffer(void); //inicializado del mapa de memoria
void nokia_contrast(int8 contraste); //seteo contraste del LCD
void nokia_gotoxy(int8 x,int8 y); //posiciono cursor en columna x, fila y (84,6) en el mapa de memoria
void nokia_printchar(int8 c); //dibujo caracter en la posición actual
void nokia_printstr(char* message); //dibujo una cadena en la posición actual
void nokia_plot(int8 x,int8 y,int8 color); //prende o apaga un pixel segun color (84,48 pixeles)
void nokia_line(unsigned int8 x1, unsigned int8 y1, unsigned int8 x2, unsigned int8 y2, int1 color);
void nokia_box(unsigned int8 x1, unsigned int8 y1, unsigned int8 x2, unsigned int8 y2, int1 fill, int1 color);
void nokia_bar(unsigned int8 x1, unsigned int8 y1, unsigned int8 x2, unsigned int8 y2, unsigned int8 width, int1 color);
void nokia_circle(unsigned int8 x, unsigned int8 y, unsigned int8 radius, int1 fill, int1 color);
/////////////////////////////////////////////////////////////////////////////////////////////////
//Inicialización
void nokia_init() {
nokia_clean_buffer(); //limpio mapa de memoria
output_high(nok_dc); // bytes are stored in the display data ram, address counter, incremented automatically
output_high(nok_cs); // chip disabled
delay_us(200);
output_low(nok_res);
delay_ms(250);
output_high(nok_res);
nokia_write_command(0x21); //elijo conjunto de instrucciones extendidas
nokia_write_command(0xc2); //Vop
nokia_write_command(0x13); //bias
nokia_write_command(0x20); //modo horizontal de izq. a der., eje X se incrementa automaticamente,
//0x22 para direccionamiento vertical, también de nuevo en conjunto de instrucciones normales
nokia_write_command(0x09); //todo ON
delay_ms(50);
nokia_refresh(); //actualizo display
delay_ms(10);
nokia_write_command(0x08); //todo off
delay_ms(10);
nokia_write_command(0x0c); //modo normal
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//limpio el mapa de memoria
void nokia_clean_buffer() {
int8 i,j;
for(j=0;j<6;j++){ //borro el mapa de memoria
for(i=0;i<84;i++){
buffer[i][j]=0x00;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//vuelco mapa de memoria al LCD
void nokia_refresh() {
int8 i,j;
nokia_write_command(0x40);
nokia_write_command(0x80);
for(j=0;j<6;j++){ //mando mapa de memoria al LCD
for(i=0;i<84;i++){
nokia_write_data(buffer[i][j]);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//escribo comando
void nokia_write_command(int8 comando)
{
output_low(nok_dc); //es un comando
output_low(nok_cs); //habilito el chip
nokia_write_dorc(comando);
output_high(nok_cs); //deshabilito el chip
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//escribo dato
void nokia_write_data(int8 dato)
{
output_high(nok_dc); //es un dato
output_low(nok_cs); //habilito el chip
nokia_write_dorc(dato);
output_high(nok_cs); //deshabilito el chip
}
////////////////////////////////////////////////////////////////////////////////////////////////
//mando el dato o comando en forma serial
void nokia_write_dorc(int8 n_dato)
{
int8 caa;
for (caa=8;caa>0;caa--){ //mando MSB primero
output_low(nok_sclk);
delay_us(2);
if ((n_dato&0x80)==0)
output_low(nok_sda);
else
output_high(nok_sda);
output_high(nok_sclk);
delay_us(2);
n_dato = n_dato << 1;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
//posiciono cursor en el byte correspondiente al mapa de memoria para [x,y]
void nokia_gotoxy(int8 x, int8 y)
{
if(x>83)
x=83;
if(y>5)
y=5;
idx=x;
idy=y;
}
///////////////////////////////////////////////////////////////////////////////////////////////
//fijo contraste
void nokia_contrast(int8 contraste)
{
nokia_write_command(0x21); //comandos extendidos del LCD
nokia_write_command(0x80 | contraste); //fijo el Vop del Vop (contraste)
nokia_write_command(0x20); //vuelvo a comandos estandares de LCD y direccionamiento horizontal
}
///////////////////////////////////////////////////////////////////////////////////////////////
//cargo un caracter en posición actual del mapa de memoria
void nokia_printchar(int8 c)
{
char char_row,char_pos,char_data;
if (c<0x20) return; //verifico que el caracter sea "mostrable"
if (c>0x7f) return;
for (char_row=0;char_row<5;char_row++)
{
if (idx>83){
idx=0;
idy++;
if (idy>5)
idy=0;
}
if (c<0x50){
char_pos=((c-0x20)*5); //uso TABLA1
char_data=TABLA1[(char_pos+char_row)];
}
if (c>0x4f){
char_pos=((c-0x50)*5); //uso TABLA2
char_data=TABLA2[(char_pos+char_row)];
}
buffer[idx][idy]=char_data;
idx++;
}
buffer[idx][idy]=0x00; //dejo 1 byte en blanco para separar caracteres
idx++;
}
///////////////////////////////////////////////////////////////////////////////////////////////
//dibujo un pixel
//(x,y) - coordenadas del pixel
//color - on/off
void nokia_plot(int8 x, int8 y, int1 color) {
int16 offset;
byte data;
if (x > 83) return; //x debe ser menor de 83
if (y > 47) return; //y debe ser menor de 47
offset = y - ((y / 8) * 8);
if (color)
data = (0x01 << offset);
else
data = (0xfe << offset);
nokia_gotoxy(x, (y/8));
if (color)
buffer[idx][idy]=buffer[idx][idy]|data; //hago el OR de lo que hay en la posición del buffer y el pixel nuevo
else
buffer[idx][idy]=buffer[idx][idy]&data; //hago el AND de lo que hay en la posición del buffer y el pixe nuevo
}
/////////////////////////////////////////////////////////////////////////
// Dibuja una linea
// (x1, y1) - coordenada de comienzo
// (x2, y2) - coordenada de fin
// color - ON o OFF
void nokia_line(unsigned int8 x1, unsigned int8 y1, unsigned int8 x2, unsigned int8 y2, int1 color)
{
unsigned int16 dy, dx;
signed int8 addx=1, addy=1;
signed int16 P, diff;
unsigned int8 i=0;
dx = abs((signed int8)(x2 - x1));
dy = abs((signed int8)(y2 - y1));
if(x1 > x2)
addx = -1;
if(y1 > y2)
addy = -1;
if(dx >= dy)
{
dy *= 2;
P = dy - dx;
diff = P - dx;
for(; i<=dx; ++i)
{
nokia_plot(x1, y1, color);
if(P < 0)
{
P += dy;
x1 += addx;
}
else
{
P += diff;
x1 += addx;
y1 += addy;
}
}
}
else
{
dx *= 2;
P = dx - dy;
diff = P - dy;
for(; i<=dy; ++i)
{
nokia_plot(x1, y1, color);
if(P < 0)
{
P += dx;
y1 += addy;
}
else
{
P += diff;
x1 += addx;
y1 += addy;
}
}
}
}
/////////////////////////////////////////////////////////////////////////
// Dibuja un rectangulo
// (x1, y1) - coordenada de inicio
// (x2, y2) - coordenada de fin
// fill - YES/NO
// color - ON/OFF
void nokia_box(unsigned int8 x1, unsigned int8 y1, unsigned int8 x2, unsigned int8 y2, int1 fill, int1 color)
{
if(fill)
{
unsigned int8 i, xmin, xmax, ymin, ymax;
if(x1 < x2) // Encuentra x min y max
{
xmin = x1;
xmax = x2;
}
else
{
xmin = x2;
xmax = x1;
}
if(y1 < y2) // Encuentra y min y max
{
ymin = y1;
ymax = y2;
}
else
{
ymin = y2;
ymax = y1;
}
for(; xmin <= xmax; ++xmin)
{
for(i=ymin; i<=ymax; ++i)
{
nokia_plot(xmin, i, color);
}
}
}
else
{
nokia_line(x1, y1, x2, y1, color); // Dibuja los 4 lados
nokia_line(x1, y2, x2, y2, color);
nokia_line(x1, y1, x1, y2, color);
nokia_line(x2, y1, x2, y2, color);
}
}
/////////////////////////////////////////////////////////////////////////
// Dibuja una barra
// (x1, y1) - coordenada de inicio
// (x2, y2) - coordenada de fin
// width - El número de pixels de ancho
// color - ON o OFF
void nokia_bar(unsigned int8 x1, unsigned int8 y1, unsigned int8 x2, unsigned int8 y2, unsigned int8 width, int1 color)
{
unsigned int8 half_width;
signed int16 dy, dx;
signed int8 addx=1, addy=1, j;
signed int16 P, diff, c1, c2;
unsigned int8 i=0;
dx = abs((signed int8)(x2 - x1));
dy = abs((signed int8)(y2 - y1));
half_width = width/2;
c1 = -(dx*x1 + dy*y1);
c2 = -(dx*x2 + dy*y2);
if(x1 > x2)
{
signed int16 temp;
temp = c1;
c1 = c2;
c2 = temp;
addx = -1;
}
if(y1 > y2)
{
signed int16 temp;
temp = c1;
c1 = c2;
c2 = temp;
addy = -1;
}
if(dx >= dy)
{
P = 2*dy - dx;
diff = P - dx;
for(i=0; i<=dx; ++i)
{
for(j=-half_width; j<half_width+width%2; ++j)
{
nokia_plot(x1, y1+j, color);
}
if(P < 0)
{
P += 2*dy;
x1 += addx;
}
else
{
P += diff;
x1 += addx;
y1 += addy;
}
}
}
else
{
P = 2*dx - dy;
diff = P - dy;
for(i=0; i<=dy; ++i)
{
if(P < 0)
{
P += 2*dx;
y1 += addy;
}
else
{
P += diff;
x1 += addx;
y1 += addy;
}
for(j=-half_width; j<half_width+width%2; ++j)
{
nokia_plot(x1+j, y1, color);
}
}
}
}
/////////////////////////////////////////////////////////////////////////
// Dibuja un circulo
// (x,y) - centro del circulo
// radius - radio del circulo
// fill - YES/NO
// color - ON/OFF
void nokia_circle(unsigned int8 x, unsigned int8 y, unsigned int8 radius, int1 fill, int1 color)
{
signed int8 a, b, P;
a = 0;
b = radius;
P = 1 - radius;
do
{
if(fill)
{
nokia_line(x-a, y+b, x+a, y+b, color);
nokia_line(x-a, y-b, x+a, y-b, color);
nokia_line(x-b, y+a, x+b, y+a, color);
nokia_line(x-b, y-a, x+b, y-a, color);
}
else
{
nokia_plot(a+x, b+y, color);
nokia_plot(b+x, a+y, color);
nokia_plot(x-a, b+y, color);
nokia_plot(x-b, a+y, color);
nokia_plot(b+x, y-a, color);
nokia_plot(a+x, y-b, color);
nokia_plot(x-a, y-b, color);
nokia_plot(x-b, y-a, color);
}
if(P < 0)
P += 3 + 2 * a++;
else
P += 5 + 2 * (a++ - b--);
} while(a <= b);
}
///////////////////////////////////////////////////////////////////////////////
//Muestra cadena de caracteres en coordenada [x,y]
void nokia_printstr(char* message)
{
for(; *message != '\0';message++){
nokia_printchar(*message);
}
}
|
And here how to use it:
Code: |
nokia_init();
nokia_gotoxy(0,0);
texto="Hi! a txt line";
nokia_printstr(texto);
nokia_refresh();
delay_ms(1000);
nokia_clean_buffer();
nokia_gotoxy(0,0);
texto="a circle...";
nokia_circle(42,23,15,0,1);
nokia_refresh();
|
Soon, I'll be adding the possibility of showing bitmaps. |
|