/* This work was developed as a part of following course work Subject: Embedded Systems Design Instructor: Mr. Devesh Samaiya(devesh.samaiya@pilani.bits-pilani.ac.in) College: Birla Institute of Technology and Science, Pilani Campus Year: 2017 Odd Semester. */ /* Author : Gaurav Sharma h2016075@pilani.bits-pilani.ac.in Himanshu Shekhar h2016071@pilani.bits-pilani.ac.in. This is a graphics defined library for KS0108 based GLCD. We have tested in on our CNK-JHD12864E LCD. However it should work on any GLCD based on KS0108 controller.*/ #ifndef __GLCD_GRAPHICS_H #define __GLCD_GRAPHICS_H #include #include #include #include /*Both these files should be in same folder as glcd_graphics.h*/ #include "timer.h" //For _delay_us and _delay_ms functions #include "character_map.h" //For TAHOMA Font character maps #define m_delay 2 //HOLD TIME ENABLE SIGNAL. INCREASE IT IF GLCD NOT WORKING #define DISP_WIDTH 128 #define DISP_HEIGHT 64 uint8_t NIGHT_MODE = 1; //If 1 then white image on dark background. If 0 then black image on green background.* /*CONTROL PORT MAPPING. */ /*Assuming that PORT1 of LPC2148 is used as control port. */ /*Following is the connections between GLCD control pins(on the left) and LPC2148 pins(on the right) . */ #define RS (1<<16) //it means that P1.16 pin of LPC2148 is connected to RS pin of GLCD #define RW (1<<17) //..............P1.17 pin of LPC2148 is connected to RW pin of GLCD #define E (1<<18) //................................................................. #define CS1 (1<<19) //................................................................. #define CS2 (1<<20) #define RST (1<<21) /*****************************************************/ /*DATA PIN MAPPING.*/ /*Assuming following mapping between GLCD data pins and LPC2148. */ /* DB0 is connected to P0.0 of LPC2148 */ /* DB1 P0.1 of LPC2148 */ /* DB2..................P0.2............*/ /* DB7..................P0.7............*/ /******************************************************/ /********************************************************/ /*Low level GLCD interfacing routines. Users are adviced not to use these directly, except for init_glcd() , which should be called before any drawing.*/ void rs_high(void); void rs_low(void); void rw_high(void); void rw_low(void); void e_high(void); void e_low(void); void cs1_high(void); void cs1_low(void); void cs2_high(void); void cs2_low(void); void rst_high(void); void rst_low(void); void write_data_on_bus(uint8_t); void send_data(uint8_t); uint8_t read_data(void); void select_glcd1(void); void select_glcd2(void); void select_glcd12(void); void display_on(void); void display_off(void); void init_glcd(void); /*This should be called before starting to draw on GLCD.*/ /******************************************************/ /******************************************************/ /*Low level graphics display routines. User should not use these*/ void set_vertical_address(uint8_t); /*Set x addr. */ void set_horizontal_address(uint8_t); /*Set y addr */ void set_pixel(uint8_t, uint8_t); void clear_screen(void); /*This is pixel by pixel. Use clear frame instead.*/ /*******************************************************/ /*******************************************************/ /*High Level graphics display routines. Users should use these functions instead of low level graphics routines above. All these functions update the back buffer. To actually draw on GLCD, call draw_frame.*/ void set_night_mode(void); void set_day_mode(void); void set_pixel_in_buffer(uint8_t, uint8_t); void clear_pixel_in_buffer(uint8_t, uint8_t); void fill_screen(uint8_t*); /*Draw a 128*64 bit map on the back buffer.*/ void draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); void draw_circle(uint8_t x_center, uint8_t y_center, uint8_t radius); void reflect_circle(uint8_t xc, uint8_t yx, uint8_t x, uint8_t y); void play_buzzer(unsigned long buzzer_time); void fill_rect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); void draw_string(uint8_t line_no, char *string); /*******************************************************************/ /*Draw frame is called to flush the current back buffer to the glcd. Once drawing the current scene is done, draw frame should be called. */ void draw_frame(void); void clear_frame(void); /*Used to clear the back buffer*/ /*******************************************************************/ uint8_t buffer1[128 * 64 /8]; //Back buffer for back buffering uint8_t *back_buffer = buffer1; //pointer to back buffer static uint8_t x1, y1, x2, y2; void rs_high() { IO1DIR |= RS; IO1SET |= RS; } void rs_low() { IO1DIR |= RS; IO1CLR |= RS; } void rw_high() { IO1DIR |= RW; IO1SET |= RW; } void rw_low() { IO1DIR |= RW; IO1CLR |= RW; } void e_low() { IO1DIR |= E; IO1CLR |= E; } void e_high() { IO1DIR |= E; IO1SET |= E; } void cs1_low() { IO1DIR |= CS1; IO1CLR |= CS1; } void cs1_high() { IO1DIR |= CS1; IO1SET |= CS1; } void cs2_low() { IO1DIR |= CS2; IO1CLR |= CS2; } void cs2_high() { IO1DIR |= CS2; IO1SET |= CS2; } void rst_low() { IO1DIR |= RST; IO1CLR |= RST; } void rst_high() { IO1DIR |= RST; IO1SET |= RST; } void write_data_on_bus(uint8_t command) { IO0DIR |= 0xFF; IO0SET |= command; IO0CLR |= ~command; } void send_data(uint8_t data) { //assuming correct half of lcd is activated e_low(); rs_high(); rw_low(); write_data_on_bus(data); e_high(); _delay_us(m_delay); e_low(); _delay_us(m_delay); } uint8_t read_data() { uint8_t data = 0; IO0DIR |= 0x00; //read mode for port0 rw_high(); rs_high(); e_high(); _delay_us(m_delay); e_low(); _delay_us(m_delay); e_high(); data = IO0PIN; _delay_us(m_delay); e_low(); return data; } void select_glcd1() { cs1_high(); cs2_low(); } void select_glcd2() { cs1_low(); cs2_high(); } void select_glcd12() { cs1_high(); cs2_high(); } void display_on() { e_low(); rs_low(); rw_low(); select_glcd12(); uint8_t temp = 0x3F; write_data_on_bus(temp); e_high(); _delay_us(m_delay); e_low(); _delay_us(m_delay); } void display_off() { e_low(); rs_low(); rw_low(); select_glcd12(); uint8_t temp = 0x3E; write_data_on_bus(temp); e_high(); _delay_us(m_delay); e_low(); _delay_us(m_delay); } void init_glcd() { //wait for vdd to stabilize initClocks(); initTimer0(); _delay_ms(100); rst_low(); _delay_ms(10); rst_high(); _delay_ms(10); select_glcd12(); display_on(); //display_on(); } /*Set x addr */ void set_vertical_address(uint8_t v_addr) { e_low(); rs_low(); rw_low(); uint8_t temp = 0xB8 | (v_addr & 0x07); write_data_on_bus(temp); e_high(); _delay_us(m_delay); e_low(); _delay_us(m_delay); } /*Set y addr */ void set_horizontal_address(uint8_t h_addr) { e_low(); rs_low(); rw_low(); uint8_t temp = 0x40 | (h_addr & 0x3F); write_data_on_bus(temp); e_high(); _delay_us(m_delay); e_low(); _delay_us(m_delay); } void clear_frame() { uint8_t i,j; for(i = 0; i<128; i++) for(j=0; j<64; j++) clear_pixel_in_buffer(i,j); } void _set_pixel_in_buffer(uint8_t x, uint8_t y) { uint8_t *ptr = &back_buffer[(y/8 * 128) + x]; *ptr = *ptr | (1<<(y%8)); } void _clear_pixel_in_buffer(uint8_t x, uint8_t y) { uint8_t *ptr = &back_buffer[(y/8 * 128) + x]; *ptr = *ptr & ~(1<<(y%8)); } void set_pixel_in_buffer(uint8_t x, uint8_t y) { if(NIGHT_MODE) _clear_pixel_in_buffer(x,y); else _set_pixel_in_buffer(x,y); } void clear_pixel_in_buffer(uint8_t x, uint8_t y) { if(NIGHT_MODE) _set_pixel_in_buffer(x,y); else _clear_pixel_in_buffer(x,y); } void draw_frame() { fill_screen(back_buffer); } void fill_screen(uint8_t *back_buffer) { int i,j; select_glcd1(); set_horizontal_address(0); for(i = 0; i<8; i++) { set_vertical_address(i); for(j=0; j<64; j++) send_data(back_buffer[i*128 + j]); //send_data(0xFF); } select_glcd2(); set_horizontal_address(0); for(i = 0; i<8; i++) { set_vertical_address(i); for(j=64; j<128; j++) send_data(back_buffer[i*128 + j]); } } void draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { signed int x, y, addx, addy, dx, dy; signed long P; int i; dx = abs((signed int)(x2 - x1)); dy = abs((signed int)(y2 - y1)); x = x1; y = y1; if(x1 > x2) addx = -1; else addx = 1; if(y1 > y2) addy = -1; else addy = 1; if(dx >= dy) { P = 2*dy - dx; for(i=0; i<=dx; ++i) { set_pixel_in_buffer(x, y); if(P < 0) { P += 2*dy; x += addx; } else { P += 2*dy - 2*dx; x += addx; y += addy; } } } else { P = 2*dx - dy; for(i=0; i<=dy; ++i) { set_pixel_in_buffer(x, y); if(P < 0) { P += 2*dx; y += addy; } else { P += 2*dx - 2*dy; x += addx; y += addy; } } } } void reflect_circle(uint8_t xc, uint8_t yc, uint8_t x, uint8_t y) { draw_line(xc+x, yc+y, xc-x, yc+y); draw_line(xc+x, yc-y, xc-x, yc-y); draw_line(xc+y, yc+x, xc-y, yc+x); draw_line(xc+y, yc-x, xc-y, yc-x); /* */ } /*TODO make the circle more circular......*/ void draw_circle(uint8_t x_center, uint8_t y_center, uint8_t r) { uint8_t x = 0, y = r; uint8_t d = 3 - 2 * r; while(y >= x) { reflect_circle(x_center, y_center, x, y); x++; if(d > 0) { y--; d = d + 4 *(x-y) + 10; } else d = d + 4 * x + 6; reflect_circle(x_center, y_center, x, y); } } void fill_rect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { int i; for(i=y1; i