Hier entsteht eine kleine Bibliothek für Grafik-LCDs. Angefangen habe ich mit einem Nokia 3310 LCD (PCD8544 Controller). Eine kleine Demonstration kann man in dem Video sehen. Die Bibliothek wird in nächster Zeit noch ein paar Funktionen dazu bekommen (es fehlen noch viele Funktionen, wie z.B. Linien zeichnen, Rechtecke, Kreise etc.). Bei dem verwendeten Nokia 3310 LCD handelt sich um ein Ersatz-Display (kann auf Ebay bestellt werden). Der sichtbare Bereich des Displays beträgt 96×64 Pixel (der Display-Speicher ist aber etwas größer). WICHTIG: Das originale Nokia 3310 LCD hat eine Auflösung von 84×48 Pixel! Die Ansteuerung (besonders die Initialsierung) ist bei diesem Display ziemlich einfach, da es nicht viele Einstellmöglichkeiten gibt, beschränkt sich also auf ein paar Befehle. Angesteuert wird das LCD über einen MSP430G2553 (per SPI).
Video
Schaltplan
Source-Code
Der komplette Source-Code: DOWNLOAD SOURCE
Zwei Ausschnitte: main.c und lib_lcd.c
main.c
- /*******************************
- * __
- * /\ \
- * __ _ \_\ \ __ ___
- * /\ \/'\ /'_' \ /'__'\ /'___\
- * \/> <//\ \ \ \/\ __//\ \__/
- * /\_/\_\ \___,_\ \____\ \____\
- * \//\/_/\/__,_ /\/____/\/____/
- *
- * Author: declis (xdec.de)
- ********************************/
- #include <msp430g2553.h>
- #include "lib_lcd.h"
- #include "delay.h"
- #include "bitmaps.h"
- #include "data.h"
- void main(void)
- {
- signed int x=0,y=-184,num=0,x1=0,y1=0;
- WDTCTL=WDTPW+WDTHOLD;
- BCSCTL1=CALBC1_8MHZ; // SMCLK=~8MHz
- DCOCTL=CALDCO_8MHZ;
- init_USCI();
- init_LCD();
- // SCENE 00 - "Countdown" ----------------------------
- wait_ms(500);
- countdown('3');
- countdown('2');
- countdown('1');
- wait_ms(500);
- write_string(3,2,gogo,5);
- wait_ms(1000);
- fill_display(lcd_width,lcd_height,0);
- // ---------------------------------------------------
- // SCENE 01 - "Motoko Vertical-Scroller" -------------
- while(y!=16)
- {
- draw_bitmap(0,y++,ghost_w,ghost_h,ghost);
- wait_ms(80);
- }
- write_string(0,0,moto,1);
- wait_ms(2000);
- while(y!=-85)
- {
- draw_bitmap(0,y--,ghost_w,ghost_h,ghost);
- wait_ms(80);
- }
- wait_ms(2000);
- // ---------------------------------------------------
- // SCENE 02 - "Motoko Horizontal-Overlap-Scroller" ---
- y=0;
- while(x!=-lcd_width)
- {
- draw_bitmap(x--,-85,ghost_w,ghost_h,ghost);
- draw_bitmap(y++,-85,ghost_w,ghost_h,ghost);
- }
- while(x<=lcd_width)
- {
- draw_bitmap(x++,-85,ghost_w,ghost_h,ghost);
- draw_bitmap(y--,-85,ghost_w,ghost_h,ghost);
- }
- wait_ms(500);
- // ---------------------------------------------------
- // SCENE 03 - "String-Typer" -------------------------
- string_typer(3,0,powa0,0,typer_ms);
- string_typer(3,1,powa1,1,typer_ms);
- string_typer(3,3,powa2,0,typer_ms);
- wait_ms(typer_ms);
- draw_bitmap(0,29,boo_w,boo_h,boo);
- wait_ms(typer_ms);
- string_typer(3,4,powa3,3,typer_ms);
- string_typer(3,7,powa4,0,typer_ms);
- wait_ms(4000);
- fill_display(lcd_width,lcd_height,0);
- // ---------------------------------------------------
- // SCENE 04 - "Bitmap-FadeIn-Destruction -------------
- x=0;
- while(x<=29)
- {
- draw_bitmap(0,0,x++,ichi_h,ichi);
- wait_ms(300);
- }
- wait_ms(1000);
- // ---------------------------------------------------
- // SCENE 05 - "Classic-Scrolling" --------------------
- x=lcd_width;
- y=lcd_width;
- y1=sizeof(sine)-1;
- x1=sizeof(sine)-21;
- num=6*sizeof(scroll0);
- while(x!=-num)
- {
- if(!y1) y1=sizeof(sine)-1;
- if(!x1) x1=sizeof(sine)-1;
- f_scroller_normal(x--,0,scroll1);
- if(y!=-num)
- {
- f_scroller_normal(y,56,scroll0);
- y-=2;
- }
- else y=lcd_width;
- draw_bitmap(0,0,ichi_w,ichi_h-8,ichi);
- draw_bitmap(35,sine[y1--]/2+8,boo_w,boo_h,boo);
- draw_bitmap(70,sine[x1--]/2+8,boo_w,boo_h,boo);
- wait_ms(50);
- }
- // ---------------------------------------------------
- // SCENE 06 - "FadeOut Scene 05" ---------------------
- wait_ms(500);
- x=0;
- y=8;
- while(y<=lcd_height)
- {
- if(x>=-ichi_w)
- draw_bitmap(x--,0,ichi_w,ichi_h,ichi);
- draw_bitmap(35,sine[y1]/2+y,boo_w,boo_h,boo);
- draw_bitmap(70,sine[x1]/2+y++,boo_w,boo_h,boo);
- wait_ms(70);
- }
- // ---------------------------------------------------
- // SCENE 07 - "Sine-Scroller" / "END" ----------------
- x=lcd_width;
- num=6*sizeof(scroll3);
- write_string(3,6,end,2);
- while(x!=-num)
- {
- f_scroller_func(x--,0,scroll3,sine,sizeof(sine)-1);
- write_h_string(0,0,powa3,1);
- write_h_string(15,0,powa3,1);
- wait_ms(70);
- fill_display(lcd_width,32,0);
- }
- // ---------------------------------------------------
- fill_display(lcd_width,lcd_height,0);
- while(1);
- }
/******************************* * __ * /\ \ * __ _ \_\ \ __ ___ * /\ \/'\ /'_' \ /'__'\ /'___\ * \/> <//\ \ \ \/\ __//\ \__/ * /\_/\_\ \___,_\ \____\ \____\ * \//\/_/\/__,_ /\/____/\/____/ * * Author: declis (xdec.de) ********************************/ #include <msp430g2553.h> #include "lib_lcd.h" #include "delay.h" #include "bitmaps.h" #include "data.h" void main(void) { signed int x=0,y=-184,num=0,x1=0,y1=0; WDTCTL=WDTPW+WDTHOLD; BCSCTL1=CALBC1_8MHZ; // SMCLK=~8MHz DCOCTL=CALDCO_8MHZ; init_USCI(); init_LCD(); // SCENE 00 - "Countdown" ---------------------------- wait_ms(500); countdown('3'); countdown('2'); countdown('1'); wait_ms(500); write_string(3,2,gogo,5); wait_ms(1000); fill_display(lcd_width,lcd_height,0); // --------------------------------------------------- // SCENE 01 - "Motoko Vertical-Scroller" ------------- while(y!=16) { draw_bitmap(0,y++,ghost_w,ghost_h,ghost); wait_ms(80); } write_string(0,0,moto,1); wait_ms(2000); while(y!=-85) { draw_bitmap(0,y--,ghost_w,ghost_h,ghost); wait_ms(80); } wait_ms(2000); // --------------------------------------------------- // SCENE 02 - "Motoko Horizontal-Overlap-Scroller" --- y=0; while(x!=-lcd_width) { draw_bitmap(x--,-85,ghost_w,ghost_h,ghost); draw_bitmap(y++,-85,ghost_w,ghost_h,ghost); } while(x<=lcd_width) { draw_bitmap(x++,-85,ghost_w,ghost_h,ghost); draw_bitmap(y--,-85,ghost_w,ghost_h,ghost); } wait_ms(500); // --------------------------------------------------- // SCENE 03 - "String-Typer" ------------------------- string_typer(3,0,powa0,0,typer_ms); string_typer(3,1,powa1,1,typer_ms); string_typer(3,3,powa2,0,typer_ms); wait_ms(typer_ms); draw_bitmap(0,29,boo_w,boo_h,boo); wait_ms(typer_ms); string_typer(3,4,powa3,3,typer_ms); string_typer(3,7,powa4,0,typer_ms); wait_ms(4000); fill_display(lcd_width,lcd_height,0); // --------------------------------------------------- // SCENE 04 - "Bitmap-FadeIn-Destruction ------------- x=0; while(x<=29) { draw_bitmap(0,0,x++,ichi_h,ichi); wait_ms(300); } wait_ms(1000); // --------------------------------------------------- // SCENE 05 - "Classic-Scrolling" -------------------- x=lcd_width; y=lcd_width; y1=sizeof(sine)-1; x1=sizeof(sine)-21; num=6*sizeof(scroll0); while(x!=-num) { if(!y1) y1=sizeof(sine)-1; if(!x1) x1=sizeof(sine)-1; f_scroller_normal(x--,0,scroll1); if(y!=-num) { f_scroller_normal(y,56,scroll0); y-=2; } else y=lcd_width; draw_bitmap(0,0,ichi_w,ichi_h-8,ichi); draw_bitmap(35,sine[y1--]/2+8,boo_w,boo_h,boo); draw_bitmap(70,sine[x1--]/2+8,boo_w,boo_h,boo); wait_ms(50); } // --------------------------------------------------- // SCENE 06 - "FadeOut Scene 05" --------------------- wait_ms(500); x=0; y=8; while(y<=lcd_height) { if(x>=-ichi_w) draw_bitmap(x--,0,ichi_w,ichi_h,ichi); draw_bitmap(35,sine[y1]/2+y,boo_w,boo_h,boo); draw_bitmap(70,sine[x1]/2+y++,boo_w,boo_h,boo); wait_ms(70); } // --------------------------------------------------- // SCENE 07 - "Sine-Scroller" / "END" ---------------- x=lcd_width; num=6*sizeof(scroll3); write_string(3,6,end,2); while(x!=-num) { f_scroller_func(x--,0,scroll3,sine,sizeof(sine)-1); write_h_string(0,0,powa3,1); write_h_string(15,0,powa3,1); wait_ms(70); fill_display(lcd_width,32,0); } // --------------------------------------------------- fill_display(lcd_width,lcd_height,0); while(1); }
lib_lcd.c
- #include <msp430g2553.h>
- #include "ascii_char.h"
- #include "lib_lcd.h"
- #include "delay.h"
- #define max_f_size 8 // cache size for "font resize function"
- unsigned char byte,bit_num;
- void write_h_string(unsigned char x, unsigned char y, const char *string, unsigned char f_size)
- {
- while(*string!=0)
- {
- write_char(x,y,*string++,f_size);
- if(f_size==1) y+=f_size+1;
- else if(f_size>1) y+=f_size;
- else y++;
- }
- }
- void string_typer(unsigned char x, unsigned char y, const char *string, unsigned char f_size, unsigned int ms)
- {
- while(*string!=0)
- {
- write_char(x,y,*string++,f_size);
- if(f_size>1) x+=f_size;
- else x++;
- wait_ms(ms);
- }
- }
- void f_scroller_func(signed int x, signed int y, const char *string, const char *func, unsigned char func_size)
- {
- byte=0;
- while(*string!=0&&x<lcd_width)
- {
- if(x>func_size) byte=x-func_size; // use abs() here
- else byte=x;
- draw_bitmap(x,y+func[byte],f_width,8,ascii_table[*string++]);
- set_instruction(1,0); // clear byte before
- x+=f_width+space_char;
- byte++;
- }
- }
- void f_scroller_normal(signed int x, signed int y, const char *string)
- {
- while(*string!=0&&x<lcd_width)
- {
- draw_bitmap(x,y,f_width,8,ascii_table[*string++]);
- set_instruction(1,0); // clear byte before
- x+=f_width+space_char;
- }
- }
- void countdown(unsigned char num)
- {
- signed char size=8;
- while(size!=-1)
- {
- write_char(4,0,num,size--);
- wait_ms(111);
- fill_display(96,64,0);
- }
- }
- void draw_bitmap(signed int x, signed int y, unsigned int b_width, unsigned int b_height, const char *bmap)
- {
- unsigned int h_index=0,w_index=0,width_max=0,x_off=0,y_off=0;
- byte=0;
- if(y+(signed int)b_height<0) return; // outside display
- if(x+(signed int)b_width<0) return;
- if(y>=lcd_height) return;
- if(x>=lcd_width) return;
- if(x<0)
- {
- w_index=x*-1; // set bmap x-offset
- x_off=w_index;
- x=0; // start at display position x=0 with x-offset
- }
- if(b_height%8) b_height+=8;
- b_height/=8;
- if(x+(signed int)b_width>=lcd_width) // width overflow check
- width_max=lcd_width-x;
- else width_max=b_width;
- if(y<0)
- {
- y*=-1;
- y_off=y/8;
- b_height-=y_off;
- while(h_index<b_height)
- {
- set_cursor(x,h_index);
- while(w_index<width_max)
- {
- byte=bmap[w_index+((h_index+y_off)*b_width)]>>(y%8);
- if(h_index+1!=b_height)
- byte|=bmap[w_index+((h_index+y_off+1)*b_width)]<<(8-(y%8));
- set_instruction(1,byte);
- w_index++;
- byte=0;
- }
- h_index++;
- w_index=x_off;
- if(h_index>=lcd_height_b) return;
- }
- }
- else
- {
- y_off=y/8;
- while(h_index<=b_height)
- {
- set_cursor(x,y_off+h_index);
- while(w_index<width_max)
- {
- if(h_index!=b_height)
- byte=bmap[w_index+(h_index*b_width)]<<(y%8);
- if(h_index)
- byte|=(bmap[w_index+((h_index-1)*b_width)]>>(8-(y%8))); // byte before
- set_instruction(1,byte);
- w_index++;
- byte=0;
- }
- h_index++;
- w_index=x_off;
- if(h_index+y_off>=lcd_height_b) return;
- if(h_index==b_height&&!(y%8)) return;
- }
- }
- }
- void convert_font_size(unsigned char x, unsigned char y, unsigned char character, unsigned char f_size)
- {
- unsigned char x_char=0,bit_num_b=0,size=0,px_size=0,y_pos_new=0,x_pos_new=0;
- unsigned char cache[max_f_size],i=0;
- byte=0;
- bit_num=0;
- if (f_size==1) size=2;
- else size=f_size;
- while(x_char<f_width) // test byte, starting at 0 to f_width (font width)
- {
- while(bit_num<8) // test bit 0..7 of current byte
- {
- if(ascii_table[character][x_char]&(1<<bit_num)) // if bit=1 in byte...
- {
- while(px_size<size) // duplicate bits (f_size*f_size)
- {
- if(bit_num_b>7&&px_size>0) // byte overflow, new byte
- {
- set_cursor(x+x_pos_new,y+y_pos_new++); // set cursor to next y-address
- set_instruction(1,byte); // send byte
- bit_num_b=0; // reset bit counter
- cache[i++]=byte; // save byte in cache
- byte=0; // reset byte
- }
- byte|=(1<<bit_num_b); // set bit in byte
- px_size++; // increment pixel duplicate counter
- bit_num_b++; // calculate new bit position
- }
- px_size=0; // reset pixel duplicate counter
- }
- else bit_num_b+=size; // bit=0, calculate new bit position in byte
- if(bit_num_b>7) // byte overflow, new byte
- {
- set_cursor(x+x_pos_new,y+y_pos_new++);
- set_instruction(1,byte);
- bit_num_b-=8;
- cache[i++]=byte;
- byte=0;
- }
- bit_num++; // test next byte in array
- }
- y_pos_new=0; // reset y-offset
- x_pos_new++; // increment x-position
- i=0; // reset cache counter
- if(f_size==1) size=0; // double height font (only for f_size=1)
- else size--; // first row is ready, only size-1
- while(size--)
- {
- while(i<f_size)
- {
- set_cursor(x+x_pos_new,y+y_pos_new++);
- set_instruction(1,cache[i++]);
- }
- i=0;
- y_pos_new=0;
- x_pos_new++;
- }
- x_char++;
- if(f_size==1) size=2;
- else size=f_size;
- i=0;
- bit_num=0;
- }
- }
- void write_string(unsigned char x, unsigned char y, const char *string, unsigned char f_size)
- {
- x*=(f_width+space_char);
- set_cursor(x,y);
- while(*string!=0)
- {
- if(f_size)
- {
- convert_font_size(x,y,*string++,f_size);
- x+=(f_size*f_width+space_char);
- }
- else
- {
- send_data_array(ascii_table[*string++],f_width);
- y=space_char;
- while(y--)
- set_instruction(1,0);
- }
- }
- }
- void write_char(unsigned char x, unsigned char y, unsigned char character, unsigned char f_size)
- {
- x*=(f_width+space_char);
- set_cursor(x,y);
- if(f_size)
- convert_font_size(x,y,character,f_size);
- else
- send_data_array(ascii_table[character],f_width);
- }
- void send_data_array(const char *d_array, unsigned char size)
- {
- while(size--)
- set_instruction(1,*d_array++);
- }
- void set_cursor(unsigned char x, unsigned char y)
- {
- set_instruction(0,0x80+x);
- set_instruction(0,0x40+y);
- }
- void fill_display(unsigned char width, unsigned char height, unsigned char byte)
- {
- height/=8;
- while(height--)
- {
- set_cursor(0,height);
- while(width--)
- set_instruction(1,byte);
- width=lcd_width;
- }
- }
- void set_instruction(unsigned char register_sel, unsigned char number)
- {
- if(register_sel)
- P1OUT|=DC;
- else P1OUT&=~DC;
- P1OUT&=~CS; // start condition
- while(IFG2&UCB0TXIFG); // TX buffer ready?
- UCB0TXBUF=number; // start transmission
- }
- void init_LCD(void)
- {
- wait_ms(100);
- P1OUT|=RES;
- set_instruction(0,0x21); // function set, extended instruction set (h=1)
- set_instruction(0,0xCF); // set Vop, contrast
- set_instruction(0,0x04); // temperature control, set coefficient
- set_instruction(0,0x17); // set bias system
- set_instruction(0,0x20); // function set, basic instruction set (h=0)
- set_instruction(0,0x0C); // display control, normal mode
- fill_display(lcd_width,lcd_height_real,0); // display RAM is undefined after reset, clean dat shit
- }
- void init_USCI(void)
- {
- P1DIR|=RES+DC+CS;
- P1OUT&=~RES+DC;
- P1OUT&=~CS;
- P1SEL|=SDIN+SCLK;
- P1SEL2|=SDIN+SCLK;
- UCB0CTL1|=UCSWRST; // USCI in reset state
- // SPI Master, 8bit, MSB first, synchronous mode
- UCB0CTL0|=UCMST+UCSYNC+UCCKPH+UCMSB;
- UCB0CTL1|=UCSSEL_2; // USCI CLK-SRC=SMCLK=~8MHz
- UCB0CTL1&=~UCSWRST; // USCI released for operation
- IE2|=UCB0TXIE; // enable TX interrupt
- IFG2&=~UCB0TXIFG;
- _EINT(); // enable interrupts
- }
- #pragma INTERRUPT (USCI)
- #pragma vector=USCIAB0TX_VECTOR
- void USCI(void)
- {
- P1OUT|=CS; // transmission done
- IFG2&=~UCB0TXIFG; // clear TXIFG
- }
#include <msp430g2553.h> #include "ascii_char.h" #include "lib_lcd.h" #include "delay.h" #define max_f_size 8 // cache size for "font resize function" unsigned char byte,bit_num; void write_h_string(unsigned char x, unsigned char y, const char *string, unsigned char f_size) { while(*string!=0) { write_char(x,y,*string++,f_size); if(f_size==1) y+=f_size+1; else if(f_size>1) y+=f_size; else y++; } } void string_typer(unsigned char x, unsigned char y, const char *string, unsigned char f_size, unsigned int ms) { while(*string!=0) { write_char(x,y,*string++,f_size); if(f_size>1) x+=f_size; else x++; wait_ms(ms); } } void f_scroller_func(signed int x, signed int y, const char *string, const char *func, unsigned char func_size) { byte=0; while(*string!=0&&x<lcd_width) { if(x>func_size) byte=x-func_size; // use abs() here else byte=x; draw_bitmap(x,y+func[byte],f_width,8,ascii_table[*string++]); set_instruction(1,0); // clear byte before x+=f_width+space_char; byte++; } } void f_scroller_normal(signed int x, signed int y, const char *string) { while(*string!=0&&x<lcd_width) { draw_bitmap(x,y,f_width,8,ascii_table[*string++]); set_instruction(1,0); // clear byte before x+=f_width+space_char; } } void countdown(unsigned char num) { signed char size=8; while(size!=-1) { write_char(4,0,num,size--); wait_ms(111); fill_display(96,64,0); } } void draw_bitmap(signed int x, signed int y, unsigned int b_width, unsigned int b_height, const char *bmap) { unsigned int h_index=0,w_index=0,width_max=0,x_off=0,y_off=0; byte=0; if(y+(signed int)b_height<0) return; // outside display if(x+(signed int)b_width<0) return; if(y>=lcd_height) return; if(x>=lcd_width) return; if(x<0) { w_index=x*-1; // set bmap x-offset x_off=w_index; x=0; // start at display position x=0 with x-offset } if(b_height%8) b_height+=8; b_height/=8; if(x+(signed int)b_width>=lcd_width) // width overflow check width_max=lcd_width-x; else width_max=b_width; if(y<0) { y*=-1; y_off=y/8; b_height-=y_off; while(h_index<b_height) { set_cursor(x,h_index); while(w_index<width_max) { byte=bmap[w_index+((h_index+y_off)*b_width)]>>(y%8); if(h_index+1!=b_height) byte|=bmap[w_index+((h_index+y_off+1)*b_width)]<<(8-(y%8)); set_instruction(1,byte); w_index++; byte=0; } h_index++; w_index=x_off; if(h_index>=lcd_height_b) return; } } else { y_off=y/8; while(h_index<=b_height) { set_cursor(x,y_off+h_index); while(w_index<width_max) { if(h_index!=b_height) byte=bmap[w_index+(h_index*b_width)]<<(y%8); if(h_index) byte|=(bmap[w_index+((h_index-1)*b_width)]>>(8-(y%8))); // byte before set_instruction(1,byte); w_index++; byte=0; } h_index++; w_index=x_off; if(h_index+y_off>=lcd_height_b) return; if(h_index==b_height&&!(y%8)) return; } } } void convert_font_size(unsigned char x, unsigned char y, unsigned char character, unsigned char f_size) { unsigned char x_char=0,bit_num_b=0,size=0,px_size=0,y_pos_new=0,x_pos_new=0; unsigned char cache[max_f_size],i=0; byte=0; bit_num=0; if (f_size==1) size=2; else size=f_size; while(x_char<f_width) // test byte, starting at 0 to f_width (font width) { while(bit_num<8) // test bit 0..7 of current byte { if(ascii_table[character][x_char]&(1<<bit_num)) // if bit=1 in byte... { while(px_size<size) // duplicate bits (f_size*f_size) { if(bit_num_b>7&&px_size>0) // byte overflow, new byte { set_cursor(x+x_pos_new,y+y_pos_new++); // set cursor to next y-address set_instruction(1,byte); // send byte bit_num_b=0; // reset bit counter cache[i++]=byte; // save byte in cache byte=0; // reset byte } byte|=(1<<bit_num_b); // set bit in byte px_size++; // increment pixel duplicate counter bit_num_b++; // calculate new bit position } px_size=0; // reset pixel duplicate counter } else bit_num_b+=size; // bit=0, calculate new bit position in byte if(bit_num_b>7) // byte overflow, new byte { set_cursor(x+x_pos_new,y+y_pos_new++); set_instruction(1,byte); bit_num_b-=8; cache[i++]=byte; byte=0; } bit_num++; // test next byte in array } y_pos_new=0; // reset y-offset x_pos_new++; // increment x-position i=0; // reset cache counter if(f_size==1) size=0; // double height font (only for f_size=1) else size--; // first row is ready, only size-1 while(size--) { while(i<f_size) { set_cursor(x+x_pos_new,y+y_pos_new++); set_instruction(1,cache[i++]); } i=0; y_pos_new=0; x_pos_new++; } x_char++; if(f_size==1) size=2; else size=f_size; i=0; bit_num=0; } } void write_string(unsigned char x, unsigned char y, const char *string, unsigned char f_size) { x*=(f_width+space_char); set_cursor(x,y); while(*string!=0) { if(f_size) { convert_font_size(x,y,*string++,f_size); x+=(f_size*f_width+space_char); } else { send_data_array(ascii_table[*string++],f_width); y=space_char; while(y--) set_instruction(1,0); } } } void write_char(unsigned char x, unsigned char y, unsigned char character, unsigned char f_size) { x*=(f_width+space_char); set_cursor(x,y); if(f_size) convert_font_size(x,y,character,f_size); else send_data_array(ascii_table[character],f_width); } void send_data_array(const char *d_array, unsigned char size) { while(size--) set_instruction(1,*d_array++); } void set_cursor(unsigned char x, unsigned char y) { set_instruction(0,0x80+x); set_instruction(0,0x40+y); } void fill_display(unsigned char width, unsigned char height, unsigned char byte) { height/=8; while(height--) { set_cursor(0,height); while(width--) set_instruction(1,byte); width=lcd_width; } } void set_instruction(unsigned char register_sel, unsigned char number) { if(register_sel) P1OUT|=DC; else P1OUT&=~DC; P1OUT&=~CS; // start condition while(IFG2&UCB0TXIFG); // TX buffer ready? UCB0TXBUF=number; // start transmission } void init_LCD(void) { wait_ms(100); P1OUT|=RES; set_instruction(0,0x21); // function set, extended instruction set (h=1) set_instruction(0,0xCF); // set Vop, contrast set_instruction(0,0x04); // temperature control, set coefficient set_instruction(0,0x17); // set bias system set_instruction(0,0x20); // function set, basic instruction set (h=0) set_instruction(0,0x0C); // display control, normal mode fill_display(lcd_width,lcd_height_real,0); // display RAM is undefined after reset, clean dat shit } void init_USCI(void) { P1DIR|=RES+DC+CS; P1OUT&=~RES+DC; P1OUT&=~CS; P1SEL|=SDIN+SCLK; P1SEL2|=SDIN+SCLK; UCB0CTL1|=UCSWRST; // USCI in reset state // SPI Master, 8bit, MSB first, synchronous mode UCB0CTL0|=UCMST+UCSYNC+UCCKPH+UCMSB; UCB0CTL1|=UCSSEL_2; // USCI CLK-SRC=SMCLK=~8MHz UCB0CTL1&=~UCSWRST; // USCI released for operation IE2|=UCB0TXIE; // enable TX interrupt IFG2&=~UCB0TXIFG; _EINT(); // enable interrupts } #pragma INTERRUPT (USCI) #pragma vector=USCIAB0TX_VECTOR void USCI(void) { P1OUT|=CS; // transmission done IFG2&=~UCB0TXIFG; // clear TXIFG }
Good work dude. It works fine for nokia 2100 lcd(96×64) with little modification. Thanks..
Hi,
Excellent design.
Do you know what changes are needed to make the Nokia 2100 work?
Thanks.