/* _ _ ___ _ __ ___ _ _ _ ___ ___ _ ____ ____ | \ | | / _ \ | |/ / |_ _| / \ / | / | / _ \ / _ \ | | / ___| | _ \ | \| | | | | | | ' / | | / _ \ | | | | | | | | | | | | | | | | | | | | | |\ | | |_| | | . \ | | / ___ \ | | | | | |_| | | |_| | | |___ | |___ | |_| | |_| \_| \___/ |_|\_\ |___| /_/ \_\ |_| |_| \___/ \___/ |_____| \____| |____/ PIC 18f1320 to Nokia 1100 LCD Interface http://sunbizhosting.com/~spiral/ File: lcd1100.c */ #include "lcd1100.h" //#include #include //#define NO_PUNCTUATION #ifndef _XTAL_FREQ // Unless already defined assume 4MHz system frequency // This definition is required to calibrate __delay_us() and __delay_ms() #define _XTAL_FREQ 8000000 #endif #define LCD_NOP 0xE3 #define LCD_MODE 0xA0 #define LCD_VOB_MSB 0x20 #define LCD_VOB_LSB 0x80 #define LCD_CHARGE_PUMP_ON 0x2F #define LCD_RAM_ADDR_MODE 0xAA #define LCD_CHANGE_ROW_LSB 0x00 #define LCD_CHANGE_ROW_MSB 0x10 #define LCD_CHANGE_COL 0xB0 #define LCD_MIRROR_Y 0xC0 #define LCD_MIRROR_X 0xA0 #define LCD_EXT_OSC 0x3A #define LCD_SOFT_RESET 0xE2 char bitaddr; // lookup table, here you can modify the font static const unsigned char FontLookup[][5] = { {0x00, 0x00, 0x00, 0x00, 0x00},// (space) #ifndef NO_PUNCTUATION {0x00, 0x00, 0x5F, 0x00, 0x00},// ! {0x00, 0x07, 0x00, 0x07, 0x00},// " {0x14, 0x7F, 0x14, 0x7F, 0x14},// # {0x24, 0x2A, 0x7F, 0x2A, 0x12},// $ {0x23, 0x13, 0x08, 0x64, 0x62},// % {0x36, 0x49, 0x55, 0x22, 0x50},// & {0x00, 0x05, 0x03, 0x00, 0x00},// ' {0x00, 0x1C, 0x22, 0x41, 0x00},// ( {0x00, 0x41, 0x22, 0x1C, 0x00},// ) {0x08, 0x2A, 0x1C, 0x2A, 0x08},// * {0x08, 0x08, 0x3E, 0x08, 0x08},// + {0x00, 0x50, 0x30, 0x00, 0x00},// , {0x08, 0x08, 0x08, 0x08, 0x08},// - {0x00, 0x30, 0x30, 0x00, 0x00},// . {0x20, 0x10, 0x08, 0x04, 0x02},// / #endif {0x3E, 0x51, 0x49, 0x45, 0x3E},// 0 {0x00, 0x42, 0x7F, 0x40, 0x00},// 1 {0x42, 0x61, 0x51, 0x49, 0x46},// 2 {0x21, 0x41, 0x45, 0x4B, 0x31},// 3 {0x18, 0x14, 0x12, 0x7F, 0x10},// 4 {0x27, 0x45, 0x45, 0x45, 0x39},// 5 {0x3C, 0x4A, 0x49, 0x49, 0x30},// 6 {0x01, 0x71, 0x09, 0x05, 0x03},// 7 {0x36, 0x49, 0x49, 0x49, 0x36},// 8 {0x06, 0x49, 0x49, 0x29, 0x1E},// 9 {0x00, 0x36, 0x36, 0x00, 0x00},// : {0x00, 0x56, 0x36, 0x00, 0x00},// ; {0x00, 0x08, 0x14, 0x22, 0x41},// < {0x14, 0x14, 0x14, 0x14, 0x14},// = {0x41, 0x22, 0x14, 0x08, 0x00},// > {0x02, 0x01, 0x51, 0x09, 0x06},// ? {0x32, 0x49, 0x79, 0x41, 0x3E},// @ {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, 0x01, 0x01},// F {0x3E, 0x41, 0x41, 0x51, 0x32},// 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, 0x04, 0x02, 0x7F},// M {0x7F, 0x04, 0x08, 0x10, 0x7F},// N {0x3E, 0x41, 0x41, 0x41, 0x3E},// O {0x7F, 0x09, 0x09, 0x09, 0x06},// P {0x3E, 0x41, 0x51, 0x21, 0x5E},// Q {0x7F, 0x09, 0x19, 0x29, 0x46},// R {0x46, 0x49, 0x49, 0x49, 0x31},// S {0x01, 0x01, 0x7F, 0x01, 0x01},// T {0x3F, 0x40, 0x40, 0x40, 0x3F},// U {0x1F, 0x20, 0x40, 0x20, 0x1F},// V {0x7F, 0x20, 0x18, 0x20, 0x7F},// W {0x63, 0x14, 0x08, 0x14, 0x63},// X {0x03, 0x04, 0x78, 0x04, 0x03},// Y {0x61, 0x51, 0x49, 0x45, 0x43},// Z {0x00, 0x00, 0x7F, 0x41, 0x41},// [ {0x02, 0x04, 0x08, 0x10, 0x20},// "\" {0x41, 0x41, 0x7F, 0x00, 0x00},// ] {0x04, 0x02, 0x01, 0x02, 0x04},// ^ {0x40, 0x40, 0x40, 0x40, 0x40},// _ {0x00, 0x01, 0x02, 0x04, 0x00},// ` {0x20, 0x54, 0x54, 0x54, 0x78},// a {0x7F, 0x48, 0x44, 0x44, 0x38},// b {0x38, 0x44, 0x44, 0x44, 0x20},// c {0x38, 0x44, 0x44, 0x48, 0x7F},// d {0x38, 0x54, 0x54, 0x54, 0x18},// e {0x08, 0x7E, 0x09, 0x01, 0x02},// f {0x08, 0x14, 0x54, 0x54, 0x3C},// g {0x7F, 0x08, 0x04, 0x04, 0x78},// h {0x00, 0x44, 0x7D, 0x40, 0x00},// i {0x20, 0x40, 0x44, 0x3D, 0x00},// j {0x00, 0x7F, 0x10, 0x28, 0x44},// k {0x00, 0x41, 0x7F, 0x40, 0x00},// l {0x7C, 0x04, 0x18, 0x04, 0x78},// m {0x7C, 0x08, 0x04, 0x04, 0x78},// n {0x38, 0x44, 0x44, 0x44, 0x38},// o {0x7C, 0x14, 0x14, 0x14, 0x08},// p {0x08, 0x14, 0x14, 0x18, 0x7C},// q {0x7C, 0x08, 0x04, 0x04, 0x08},// r {0x48, 0x54, 0x54, 0x54, 0x20},// s {0x04, 0x3F, 0x44, 0x40, 0x20},// t {0x3C, 0x40, 0x40, 0x20, 0x7C},// u {0x1C, 0x20, 0x40, 0x20, 0x1C},// v {0x3C, 0x40, 0x30, 0x40, 0x3C},// w {0x44, 0x28, 0x10, 0x28, 0x44},// x {0x0C, 0x50, 0x50, 0x50, 0x3C},// y {0x44, 0x64, 0x54, 0x4C, 0x44},// z {0x00, 0x08, 0x36, 0x41, 0x00},// { {0x00, 0x00, 0x7F, 0x00, 0x00},// | {0x00, 0x41, 0x36, 0x08, 0x00},// } {0x08, 0x08, 0x2A, 0x1C, 0x08},// -> {0x08, 0x1C, 0x2A, 0x08, 0x08} // <- }; // clear LCD void lcdClear(void){ unsigned int i; lcdWrite(CMD,0x40); // Y = 0 lcdWrite(CMD,0xb0); lcdWrite(CMD,0x10); // X = 0 lcdWrite(CMD,0x0); lcdWrite(CMD,0xae); // disable display; for(i=0;i<864;i++) lcdWrite(DATA,0x00); lcdWrite(CMD,0xaf); // enable display; } // init LCD void lcdInit(void){ cs = 0; rst = 0; __delay_ms(5); //Delay100TCYx(100); // 5mS so says the stop watch(less than 5ms will not work) rst = 1; lcdWrite(CMD,0x20); // write VOP register lcdWrite(CMD,0x90); lcdWrite(CMD,0xA4); // all on/normal display lcdWrite(CMD,0x2F); // Power control set(charge pump on/off) lcdWrite(CMD,0x40); // set start row address = 0 lcdWrite(CMD,0xb0); // set Y-address = 0 lcdWrite(CMD,0x10); // set X-address, upper 3 bits lcdWrite(CMD,0x0); // set X-address, lower 4 bits // comment out next two lines to flip display! //lcdWrite(CMD,0xC8); // mirror Y axis (about X axis) MY=1 (C8) or MY=0 (C0) //lcdWrite(CMD,0xa1); // Invert screen in horizontal axis lcdWrite(CMD,0xac); // set initial row (R0) of the display lcdWrite(CMD,0x07); //lcdWrite(CMD,0xF9); // lcdWrite(CMD,0xaf); // display ON/OFF lcdClear(); // clear LCD // lcdWrite(CMD,0xa7); // invert display __delay_ms(100); // Delay10KTCYx(100); // 1/2 Sec delay lcdWrite(CMD,0xa6); // normal display (non inverted) __delay_ms(200); //Delay10KTCYx(100); // 1 Sec delay } void lcdWrite(char cd, unsigned char c){ char i; cs = 0; sclk = 0; sda = cd; sclk = 1; for(i=0;i<8;i++){ sclk = 0; if(c & 0x80) sda = 1; else sda = 0; sclk = 1; c <<= 1; // use 100 for delay - originally used 20 for 8mhz but we're using 4mhz // 20 / (8 / 4) = 10 - and remember it's x10 _delay(10); // Delay10TCYx(20); } cs = 1; } /* change contrast of lcd trick: LINE 1: contrast value are feed into Vob register , only 5 LSB bits are send so AND'd with 0x1F to remove 3 MSB's see datasheet for more */ void lcdSetContrast(unsigned char value){ lcdWrite(CMD, LCD_VOB_MSB|0x04); lcdWrite(CMD, LCD_VOB_LSB|(value & 0x1F)); } //void lcdMirrorY(void){ // lcdWrite(CMD,0xC8); // mirror Y axis (about X axis) //} void lcdSetX(char x){ lcdWrite(CMD,0x10 | ((x>>4)&0x7)); lcdWrite(CMD,x & 0x0f); } void lcdSetY(char y){ char aux = 0; while(y>7){ y -=8; aux ++; } bitaddr = y-1; lcdWrite(CMD,0xB0 | (aux & 0x0f)); } void lcdGotoxy(char x,char y){ lcdWrite(CMD,(0xB0|(y&0x0F))); // Y axis initialisation: 0100 yyyy lcdWrite(CMD,(0x00|(x&0x0F))); // X axis initialisation: 0000 xxxx ( x3 x2 x1 x0) lcdWrite(CMD,(0x10|((x>>4)&0x07))); // X axis initialisation: 0010 0xxx ( x6 x5 x4) } //x dir > y dir from last line to ^ void lcdVLine(char x,char y,char on){ char aux[8]; char i; for(i=0;i<8;i++) aux[i] = 0; i = 7; while(y > 9){ aux[i] = 0xff; y -= 8; i--; } while(y > 0){ aux[i] >>= 1; aux[i] |= 0x80; y --; } for(y=0;y<8;y++){ lcdWrite(CMD,0xB0 | y); lcdSetX(x); lcdWrite(DATA,aux[y]); } } // xdir is > y is always < than y2 can be used for graphs void lcdLine(unsigned char x,unsigned char y,unsigned char y2,unsigned char on){ char aux[8]; char i,o; char c=1; char index; for(i=0;i<8;i++) aux[i] = 0; index = 0; for(i=0;i<64;i++){ if(i >= y && i <= y2){ aux[index] |= c << o; } o ++; if(o == 8){ o = 0; index ++; } } for(i=0;i<8;i++){ lcdWrite(CMD,0xB0 | i); lcdSetX(x); lcdWrite(DATA,aux[i]); } } void lcdPrintChar(char c){ lcdPrintCharInv(c, 0); } void lcdPrintCharInv(char c, char invert){ int i; char val; char space = 0x00; for ( i = 0; i < 5; i++ ){ #ifndef NO_PUNCTUATION // use punctuation chars val = FontLookup[c - 32][i] << 1; #else // no chars between ' ' and '0' char offset = 47; if (c == 32) offset = 32; val = FontLookup[c - offset][i] << 1; #endif if (invert == 1){ val = ~val; space = 0xff; } lcdWrite(DATA, val); } lcdWrite(DATA,space); } void lcdPrintMessage(const char * message){ // Write message to LCD (C string type) lcdWrite(CMD,0xae); // disable display; while (*message){ // Look for end of string lcdPrintChar(*message++); } lcdWrite(CMD,0xaf); // enable display; } void lcdPrintString(char * message){ // Write message to LCD (C string type) lcdWrite(CMD,0xae); // disable display; while (*message){ // Look for end of string lcdPrintChar(*message++); } lcdWrite(CMD,0xaf); // enable display; }