#include <delay.h>

#define lcd_dc_pin PORTB.0
#define lcd_ce_pin PORTB.2
#define lcd_rst_pin PORTB.4

#define lcd_comm 0
#define lcd_data 1
#define lcd_x_res 84
#define lcd_y_res 48

unsigned char font [][5] = {
	{ 0x00, 0x00, 0x00, 0x00, 0x00 },   // sp 0 
    { 0x00, 0x00, 0x2f, 0x00, 0x00 },   // ! 1
    { 0x00, 0x07, 0x00, 0x07, 0x00 },   // " 2
    { 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // # 3
    { 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $ 4
	{ 0x32, 0x34, 0x08, 0x16, 0x26 },   // % 5
    { 0x36, 0x49, 0x55, 0x22, 0x50 },   // & 6
    { 0x00, 0x05, 0x03, 0x00, 0x00 },   // ' 7
    { 0x00, 0x1c, 0x22, 0x41, 0x00 },   // ( 8
    { 0x00, 0x41, 0x22, 0x1c, 0x00 },   // ) 9
    { 0x14, 0x08, 0x3E, 0x08, 0x14 },   // * 10
    { 0x08, 0x08, 0x3E, 0x08, 0x08 },   // + 11
    { 0x00, 0x00, 0x50, 0x30, 0x00 },   // , 12
    { 0x10, 0x10, 0x10, 0x10, 0x10 },   // - 13
    { 0x00, 0x60, 0x60, 0x00, 0x00 },   // . 14
    { 0x20, 0x10, 0x08, 0x04, 0x02 },   // / 15
    { 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 },   // ;
    { 0x08, 0x14, 0x22, 0x41, 0x00 },   // <
    { 0x14, 0x14, 0x14, 0x14, 0x14 },   // =
    { 0x00, 0x41, 0x22, 0x14, 0x08 },   // >
    { 0x02, 0x01, 0x51, 0x09, 0x06 },   // ?
    { 0x32, 0x49, 0x59, 0x51, 0x3E },   // @
    { 0x7E, 0x11, 0x11, 0x11, 0x7E },   // A 33
    { 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B 34
    { 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C 35
    { 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D 36
    { 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E 37
    { 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F 38
    { 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G 39
    { 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H 40
    { 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I 41
    { 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J 42
    { 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K 43
    { 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L 44
    { 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M 45
    { 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N 46
    { 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O 47
    { 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P 48
    { 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q 49
    { 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R 50
    { 0x46, 0x49, 0x49, 0x49, 0x31 },   // S 51
    { 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T 52
    { 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U 53
    { 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V 54
    { 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W 55
    { 0x63, 0x14, 0x08, 0x14, 0x63 },   // X 56
    { 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y 57
    { 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z 58
    { 0x00, 0x7F, 0x41, 0x41, 0x00 },   // [ 59
    { 0x55, 0x2A, 0x55, 0x2A, 0x55 },   // 55 60
    { 0x00, 0x41, 0x41, 0x7F, 0x00 },   // ] 61
    { 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^ 62
    { 0x40, 0x40, 0x40, 0x40, 0x40 },   // _ 63
    { 0x00, 0x01, 0x02, 0x04, 0x00 },   // ' 64
    { 0x20, 0x54, 0x54, 0x54, 0x78 },   // a 65
    { 0x7F, 0x48, 0x44, 0x44, 0x38 },   // b 66
    { 0x38, 0x44, 0x44, 0x44, 0x20 },   // c 67
    { 0x38, 0x44, 0x44, 0x48, 0x7F },   // d 68
    { 0x38, 0x54, 0x54, 0x54, 0x18 },   // e 69
    { 0x08, 0x7E, 0x09, 0x01, 0x02 },   // f 70
    { 0x0C, 0x52, 0x52, 0x52, 0x3E },   // g 71
    { 0x7F, 0x08, 0x04, 0x04, 0x78 },   // h 72
    { 0x00, 0x44, 0x7D, 0x40, 0x00 },   // i 73
    { 0x20, 0x40, 0x44, 0x3D, 0x00 },   // j 74
    { 0x7F, 0x10, 0x28, 0x44, 0x00 },   // k 75
    { 0x00, 0x41, 0x7F, 0x40, 0x00 },   // l 76
    { 0x7C, 0x04, 0x18, 0x04, 0x78 },   // m 77
    { 0x7C, 0x08, 0x04, 0x04, 0x78 },   // n 78
    { 0x38, 0x44, 0x44, 0x44, 0x38 },   // o 79
    { 0x7C, 0x14, 0x14, 0x14, 0x08 },   // p 80
    { 0x08, 0x14, 0x14, 0x18, 0x7C },   // q 81
    { 0x7C, 0x08, 0x04, 0x04, 0x08 },   // r 82
    { 0x48, 0x54, 0x54, 0x54, 0x20 },   // s 83
    { 0x04, 0x3F, 0x44, 0x40, 0x20 },   // t 84
    { 0x3C, 0x40, 0x40, 0x20, 0x7C },   // u 85
    { 0x1C, 0x20, 0x40, 0x20, 0x1C },   // v 86
    { 0x3C, 0x40, 0x30, 0x40, 0x3C },   // w 87
    { 0x44, 0x28, 0x10, 0x28, 0x44 },   // x 88
    { 0x0C, 0x50, 0x50, 0x50, 0x3C },   // y 89
    { 0x44, 0x64, 0x54, 0x4C, 0x44 },   // z 90
    { 0x00, 0x7F, 0x3E, 0x1C, 0x08 },   // > Filled 91
	{ 0x08, 0x1C, 0x3E, 0x7F, 0x00 }, 	 // < Filled 92
	{ 0x08, 0x7C, 0x7E, 0x7C, 0x08 },   // Arrow up 93
	{ 0x10, 0x3E, 0x7E, 0x3E, 0x10 },   // Arrow down 94	
	{ 0x3E, 0x3E, 0x3E, 0x3E, 0x3E },   // Stop 95
	{ 0x00, 0x7F, 0x3E, 0x1C, 0x08 }    // Play 96
};

void lcd_delay (void)
{
	int i;
	for(i=-32000;i<32000;i++);
}

void lcd_send (unsigned char data, char cd)
{
    // Enable display controller (active low)
	lcd_ce_pin = 0;
    
	// Either command or data
    if (cd == lcd_data)
    {
        lcd_dc_pin = 1;
    }
    else
    {
        lcd_dc_pin = 0;
    }
    
    spi (data);
    
    // Wait until Tx register empty
    //while ( (SPSR & 0x80) != 0x80 );
    
	// Disable display controller
    lcd_ce_pin = 1;
    
}

void lcd_clear (void)
{
    int col, str;
    char my_page_addr;
    for (str = 0; str < lcd_y_res; str++)
    {
        my_page_addr = (str | 0x40);
        lcd_send (my_page_addr, lcd_comm);
        lcd_send (0x80, lcd_comm);
        for (col = 0; col < lcd_x_res; col++)
        {
            lcd_send (0x00, lcd_data);
        }          
    }
}

void lcd_init (void)
{
	// Pull-up on reset pin
	lcd_rst_pin = 1;
	delay_ms(10);
	lcd_rst_pin = 0;
	lcd_delay();
	lcd_rst_pin = 1;
	
	// Disable LCD controller
	lcd_ce_pin = 1;
	
    lcd_send (0x21, lcd_comm);
	lcd_send (0xC5, lcd_comm);
	lcd_send (0x06, lcd_comm);
	lcd_send (0x13, lcd_comm);
	lcd_send (0x20, lcd_comm);
	lcd_send (0x0C, lcd_comm);
	
	// Clear lcd
    lcd_clear();
}

