//------------------------------------------------------------------------------------------------------
//		Nokia 3310 (PCD8544) Hi-Tech C for PIC
//------------------------------------------------------------------------------------------------------

#include	<htc.h>
#include	"delay.h"
#include	"nokia_3310.h"

// !!!     SPI_INTERFACE   

//     PIC   LCD 
#ifndef	SPI_INTERFACE
	#define nok_sclk	RC3		// Clock				- pin 2
	#define nok_sda 	RC5 	// Data					-	pin 3
#endif
#define nok_dc 			RC1		// Data/Command	-	pin 4
#define nok_res 		RC4		// Reset				- pin 8



// Lcd Commands (normal Functionset)
#define GLCD_FUNCTIONSET	(0x20)
#define GLCD_SETXADDR		(0x80)
#define GLCD_SETYADDR		(0x40)
#define	GLCD_DISPLAYBLANK	(0x08)
#define	GLCD_DISPLAYFLUSH	(0x09)
#define	GLCD_DISPLAYNORMAL	(0x0C)
#define	GLCD_DISPLAYINVERT	(0x0D)

// Lcd Commands (extended Functionset)
#define GLCD_FUNCTIONSETEXT	(0x21)
#define GLCD_BIAS			(0x13)	// Bias 1:48
#define GLCD_TEMPCOEF		(0x06)	// TF = 2
#define GLCD_SETVOP			(0x80)




//              .
//         ,    -.
unsigned char bytefornokia;

//--------------------------------------------------------------------------------------------------------------------------
// ASCII   
static const unsigned char FontLookup[194][5] =
{
	{ 0x7F, 0x3E, 0x1C, 0x08, 0x00 }, // 
	{ 0x00, 0x7F, 0x3E, 0x1C, 0x08 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 

	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // (space)
	{ 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, 0x60, 0x60, 0x00, 0x00 }, // .
	{ 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
	{ 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 },  // <- (0x7f) index 95


	{ 0x7E, 0x11, 0x11, 0x11, 0x7E }, // A  0x80
	{ 0x7F, 0x49, 0x49, 0x49, 0x30 }, // 
	{ 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B
	{ 0x7F, 0x01, 0x01, 0x01, 0x01 }, // 
	{ 0x60, 0x3E, 0x21, 0x3F, 0x60 }, // 
	{ 0x7F, 0x49, 0x49, 0x49, 0x41 }, // 
	{ 0x67, 0x18, 0x7F, 0x18, 0x67 }, // 
	{ 0x22, 0x41, 0x49, 0x49, 0x36 }, // 3
	{ 0x7F, 0x10, 0x08, 0x04, 0x7F }, // 
	{ 0x7F, 0x10, 0x09, 0x04, 0x7F }, // 
	{ 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K
	{ 0x40, 0x3E, 0x01, 0x01, 0x7E }, // 
	{ 0x7F, 0x02, 0x04, 0x02, 0x7F }, // M
	{ 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H
	{ 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O
	{ 0x7F, 0x01, 0x01, 0x01, 0x7F }, // 
	{ 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P
	{ 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C
	{ 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T
	{ 0x27, 0x48, 0x48, 0x48, 0x3F }, // 
	{ 0x1E, 0x21, 0x7F, 0x21, 0x1E }, // 
	{ 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
	{ 0x3F, 0x20, 0x20, 0x3F, 0x40 }, // 
	{ 0x1F, 0x10, 0x10, 0x10, 0x7F }, // 
	{ 0x7F, 0x40, 0x7F, 0x40, 0x7F }, // 
	{ 0x3F, 0x20, 0x3F, 0x20, 0x7F }, // 
	{ 0x01, 0x7F, 0x44, 0x44, 0x38 }, // 
	{ 0x7F, 0x44, 0x7C, 0x00, 0x7F }, // 
	{ 0x7F, 0x44, 0x44, 0x44, 0x38 }, // 
	{ 0x22, 0x41, 0x49, 0x49, 0x3E }, // 
	{ 0x7F, 0x08, 0x7F, 0x41, 0x7F }, // 
	{ 0x46, 0x29, 0x19, 0x09, 0x7F }, // 

	{ 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
	{ 0x3C, 0x4A, 0x4A, 0x4B, 0x30 }, // 
	{ 0x7C, 0x54, 0x54, 0x58, 0x20 }, // 
	{ 0x7C, 0x04, 0x04, 0x04, 0x04 }, // 
	{ 0x60, 0x38, 0x24, 0x3C, 0x60 }, // 
	{ 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
	{ 0x74, 0x08, 0x7C, 0x08, 0x74 }, // 
	{ 0x28, 0x44, 0x54, 0x54, 0x28 }, // 
	{ 0x7C, 0x20, 0x10, 0x08, 0x7C }, // 
	{ 0x7C, 0x21, 0x12, 0x09, 0x7C }, // 
	{ 0x7C, 0x10, 0x10, 0x28, 0x44 }, // 
	{ 0x40, 0x78, 0x04, 0x04, 0x7C }, // 
	{ 0x7C, 0x08, 0x10, 0x08, 0x7C }, // 
	{ 0x7C, 0x10, 0x10, 0x10, 0x7C }, // 
	{ 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
	{ 0x7C, 0x04, 0x04, 0x04, 0x7C }, // 

	{ 0x7C, 0x14, 0x14, 0x14, 0x08 }, // p
	{ 0x38, 0x44, 0x44, 0x44, 0x28 }, // c
	{ 0x04, 0x04, 0x7C, 0x04, 0x04 }, // 
	{ 0x0C, 0x50, 0x50, 0x50, 0x3C }, // y
	{ 0x18, 0x24, 0x7C, 0x24, 0x18 }, // 
	{ 0x44, 0x28, 0x10, 0x28, 0x44 }, // 
	{ 0x3C, 0x20, 0x20, 0x3C, 0x40 }, // 
	{ 0x1C, 0x20, 0x20, 0x20, 0x7C }, // 
	{ 0x7C, 0x40, 0x7C, 0x40, 0x7C }, // 
	{ 0x3C, 0x20, 0x3C, 0x20, 0x7C }, // 
	{ 0x04, 0x7C, 0x48, 0x48, 0x30 }, // 
	{ 0x7C, 0x48, 0x48, 0x30, 0x7C }, // 
	{ 0x7C, 0x48, 0x48, 0x48, 0x30 }, // 
	{ 0x28, 0x44, 0x54, 0x54, 0x38 }, // 
	{ 0x7C, 0x38, 0x44, 0x44, 0x38 }, // 
	{ 0x48, 0x34, 0x14, 0x14, 0x7C }, // 

	{ 0x7E, 0x4B, 0x4A, 0x4B, 0x42 }, // 
	{ 0x38, 0x55, 0x54, 0x55, 0x18 }  // 

};






//--------------------------------------------------------------------------------------------------------------------------
#ifdef	SPI_INTERFACE
//       SPI 
unsigned char nokia_serial_write(void)			// LOW LEVEL serial write data or command subroutine
{
	SSPBUF = bytefornokia; 		//      
	while( !BF); 							//    
	return SSPBUF;	 					//    -       SPI 
}
#else
//         SPI  -   
void nokia_serial_write(void)			// LOW LEVEL serial write data or command subroutine
{
	unsigned char c;
	for(c=8; c!=0; c--){
		nok_sclk=0;
		if((bytefornokia&0x80)==0) nok_sda=0;
		else nok_sda=1;
		nok_sclk=1;
		bytefornokia<<=1;
	}
}
#endif

//--------------------------------------------------------------------------------------------------------------------------
void nokia_write_command(void)
{
	nok_dc = 0;							// byte is a command it is read with the eight SCLK pulse
	nokia_serial_write();
}
//--------------------------------------------------------------------------------------------------------------------------
void nokia_write_data(void)
{
	nok_dc = 1;
	nokia_serial_write();
}
//--------------------------------------------------------------------------------------------------------------------------
void init_nokia(void)
{
		nok_res=0;					// reset chip during 250ms
		DelayMs(10);				//   250  10 .      -  100  .
		nok_res=1;
					
		bytefornokia=0x21;		// set extins extended instruction set
		nokia_write_command();
		
		bytefornokia=0xc2;		// Vop  was 0xc2 // better is 0xa0     
		nokia_write_command();
		
		bytefornokia=0x13;		// bias 1:48
		nokia_write_command();
		
		bytefornokia=0x20;		// horizontal mode from left to right, X axe are incremented automatically , 0x22 for vertical addressing ,back on normal instruction set too 0x20 for horizontal
		nokia_write_command();

//  ALL_PIXEL_ON_TEST     -       -   
#ifdef	ALL_PIXEL_ON_TEST		
		bytefornokia=0x09;		// mode control - all pixels on - for test only
		nokia_write_command();
		DelayMs(250);			//       
		bytefornokia=0x08;		// mode control - blank change (all pixels off)
		nokia_write_command();
		DelayMs(10);
#endif		

		bytefornokia=0x0c;		// mode control normal change -        
		nokia_write_command();

		DelayMs(10);
 		nokia_clear_DDRAM();	// reset DDRAM,   
		nokia_gotoxy(0,0);		//    
}

//--------------------------------------------------------------------------------------------------------------------------
void nokia_clear_DDRAM(void)	// clear all DDRAM (set all bits to zero) 6 rows  84 columns  8 pixels
{
#ifdef	SPI_INTERFACE
	unsigned int i;
	unsigned char d;
	
	nok_dc=1;
	for(i=504; i!=0; i--){
		SSPBUF = 0; 				//      
		while( !BF); 				//     -   BF   1
		d = SSPBUF;	 				//   
	}	
#else
	unsigned int i;

	nok_sda=0;
	nok_dc=1;
	for(i=4032; i!=0; i--){
		nok_sclk=0;
		nok_sclk=1;
	}
#endif
}

//--------------------------------------------------------------------------------------------------------------------------
void nokia_gotoxy(unsigned char xnokia, unsigned char ynokia)	// Nokia LCD Position cursor
{
	bytefornokia=(0x40|(ynokia&0x07));		// Y axe initialisation: 0100 0yyy -     0  5
	nokia_write_command();
		
	bytefornokia=(0x80|(xnokia&0x7f));		// X axe initialisation: 1xxx xxxx
	nokia_write_command();
}
//--------------------------------------------------------------------------------------------------------------------------
void nokia_printmessage(const char * message)	// Write message to LCD (C string type)
{
	while(*message){							// Look for end of string
		nokia_printchar(*message);		//	
		message++;
	}
}
//--------------------------------------------------------------------------------------------------------------------------
void nokia_printchar(unsigned char c)					// Write 1 character to LCD 
{
	unsigned char i;

	//      .   -   
	if (c >= 192) c -= 64;
	for(i=0; i<5; i++)
	{
		bytefornokia=FontLookup[c][i];
		nokia_write_data();			// send data to nokia
	}
	bytefornokia=0x00;
	nokia_write_data();			// send data to nokia
}
//--------------------------------------------------------------------------------------------------------------------------



void nokia_set_contrast(unsigned char contrast)
{
	bytefornokia = GLCD_FUNCTIONSETEXT;
	nokia_write_command();
	bytefornokia = GLCD_SETVOP | contrast;
	nokia_write_command();
	bytefornokia = GLCD_FUNCTIONSET;
	nokia_write_command();
}


/*
void nokia_print_message_center(const char * message, unsigned char y)
{
	nokia_gotoxy(42-(strlen(message)*3),y);
	while(*message){							// Look for end of string
		nokia_printchar(*message);
		message++;
	}
}
//--------------------------------------------------------------------------------------------------------------------------


void nokia_set_inverse(unsigned char inv)
{
	if(inv){ bytefornokia = GLCD_DISPLAYINVERT;	nokia_write_command(); }
	else{    bytefornokia = GLCD_DISPLAYNORMAL;	nokia_write_command(); }
}
*/
