/****************************************************************************** * LC7981/HD61830 Graphics +Text LCD Driver * * Configured for the Samsung LJ41-00192B 160x80 monochrome graphics lcd. * * Written by Vanya A. Sergeev - * * February 16, 2007 * geändert Juni+Juli 2009 Wolfgang ***************************************************************************/ /* lc7981.c: Source code for the LC7981/HD61830 graphics lcd driver. * The hardware port defines can be found in lc7981.h. */ #define LCD_WIDTH 160 #define LCD_HEIGHT 80 /* Convenient macros to toggle RS, RW, and E control pins, bequeme Makros */ #define lcd_rs_high() P6OUT |= BIT6; #define lcd_rs_low() P6OUT &=~BIT6; #define lcd_rw_high() P6OUT |= BIT5; #define lcd_rw_low() P6OUT &=~BIT5; #define lcd_enable_high() P6OUT |= BIT3; #define lcd_enable_low() P6OUT &=~BIT3; /* All possible instructions for the LCD Instruction Register */ //alle möglichen Befehle des Befehlsregisters #define LCD_CMD_MODE 0x00 #define LCD_CMD_CHAR_PITCH 0x01 //Zeichenfeld #define LCD_CMD_NUM_CHARS 0x02 #define LCD_CMD_TIME_DIVISION 0x03 #define LCD_CMD_CURSOR_POS 0x04 #define LCD_CMD_DISPLAY_START_LA 0x08 #define LCD_CMD_DISPLAY_START_HA 0x09 #define LCD_CMD_CURSOR_LA 0x0A #define LCD_CMD_CURSOR_HA 0x0B #define LCD_CMD_WRITE_DATA 0x0C #define LCD_CMD_READ_DATA 0x0D #define LCD_CMD_CLEAR_BIT 0x0E #define LCD_CMD_SET_BIT 0x0F /* Bits of the LCD Mode Control Register (DB5-DB0) */ #define LCD_MODE_ON_OFF 32 #define LCD_MODE_MASTER_SLAVE 16 #define LCD_MODE_BLINK 8 //Zeichen blinkt Cursor AUS #define CURSOR_BLINKT 12 //Cursor EIN und blinkt #define LCD_MODE_CURSOR 4 //Cursor EIN #define LCD_MODE_MODE 2 //grafische Betriebsart #define LCD_MODE_EXTERNAL 1 /* Possible settings of the character pitch register */ #define LCD_CHAR_PITCH_HP_6 0x05 #define LCD_CHAR_PITCH_HP_7 0x06 #define LCD_CHAR_PITCH_HP_8 0x07 #define LCD_CHAR_PITCH_8x8 0x77 //Zeichenfeld: Bit 7-4 --> vertikal, Bit 3-0 --> horizontal #define LCD_CHAR_PITCH_8x6 0x75 //Zeichenfeld: Bit 7-4 --> vertikal, Bit 3-0 --> horizontal /* To indicate the state of a pixel */ #define PIXEL_ON 0xFF #define PIXEL_OFF 0x00 /* Low-level LCD interface functions */ void lcd_strobe_enable(void); void lcd_write_command(unsigned char command, unsigned char data); void lcd_wait_busy(void); /* LCD Graphics interface */ void lcd_graphics_init(void); void lcd_graphics_clear(void); void lcd_graphics_move(unsigned short x, unsigned short y); void lcd_graphics_draw_byte(unsigned char data); void lcd_graphics_plot_byte(unsigned short x, unsigned short y, unsigned char data); void lcd_graphics_plot_pixel(unsigned short x, unsigned short y, unsigned char state); void Pause1(void); void pausek(void); void text_init(void); void text_loeschen(void); /** * Strobes the Enable control line to trigger the lcd to process the * transmitted instruction. */ void lcd_strobe_enable(void) // H-Impuls an E = P6.3 { lcd_enable_high(); //__asm("nop;"); __asm("nop;");// __asm("nop;"); lcd_enable_low(); //__asm("nop;"); __asm("nop;");// __asm("nop;"); } /** * Waits for the busy flag to clear, which should take * around the maximum time for an instruction to complete. * Note, LCD operation is kind of sensitive to this configuration. If the delay * is too fast, the LCD will miss some pixels when it is really put through * a stress test. This dela time seems to work great. */ void lcd_wait_busy(void) { unsigned int d; for (d=0;d<200;d++); //_delay_us(3); } /** * Writes a raw instruction to the LCD. * @param command The 4-bit instruction code. * @param data The 8-bit paramater/data to the specified instruction. */ void lcd_write_command(unsigned char command, unsigned char data) //sendet zuerst Instruktionsart { /* Wait for the busy flag to clear */ lcd_wait_busy(); /* Set RW low, RS high to write the instruction command */ lcd_rw_low(); lcd_rs_high(); /* Instruction commands are a maximum of 4 bits long, so just mask off the rest. */ /* Anweisungsbefehle sind max 4 Bit lang, Rest abschneiden*/ P1OUT =(command&0x0F);// lcd_strobe_enable(); //H -impuls /* Set RW low, RW low to write the instruction data */ lcd_rw_low(); lcd_rs_low(); P1OUT = data; __asm("nop;");// __asm("nop;"); //__asm("nop;"); lcd_strobe_enable(); __asm("nop;");// __asm("nop;");// __asm("nop;"); } /** * Initializes the LCD in graphics mode. * Uses a character pitch of 8 (8 bits are plotted whenever a byte is drawn) */ void lcd_graphics_init(void) { unsigned char commandData; /* Set the data direction registers apprioriately */ P6DIR = 0x78; //P6= Steuerleitungen P1DIR = 0xFF; //P1= Datenleitungen /* Assert all control lines to low alle Steuerleitungen auf L */ lcd_rw_low(); lcd_rs_low(); //L= Daten H=Befehl lcd_enable_low(); /* Send mode configuration command with * Toggle Display On, Master, Mode Graphics bits set */ commandData = LCD_MODE_ON_OFF | LCD_MODE_MASTER_SLAVE | LCD_MODE_BLINK|LCD_MODE_MODE;//LCD_MODE_CURSOR; lcd_write_command(LCD_CMD_MODE, commandData); // schreibt die vorbereitete Instruktion /* Send the set character pitch command with horizontal * character pitch of 8 (so 8 pixels are painted when we draw) */ commandData = LCD_CHAR_PITCH_HP_8; lcd_write_command(LCD_CMD_CHAR_PITCH, commandData); /* Send the number of characters command with the total * number of graphics bytes that can be painted horizontally * (width/8) */ commandData = (LCD_WIDTH/8)-1; lcd_write_command(LCD_CMD_NUM_CHARS, commandData); /* Set the time division */ commandData = 128-1; lcd_write_command(LCD_CMD_TIME_DIVISION, commandData); /* Set the display low/high start address to 0x00 (left corner) */ commandData = 0x00; lcd_write_command(LCD_CMD_DISPLAY_START_LA, commandData); lcd_write_command(LCD_CMD_DISPLAY_START_HA, commandData); /* Reset the cursor to home 0x00 (left corner) */ commandData = 0x00; lcd_write_command(LCD_CMD_CURSOR_LA, commandData); lcd_write_command(LCD_CMD_CURSOR_HA, commandData); } void text_init(void) { unsigned char commandData; P6DIR = 0x78; //P6= Steuerleitungen P1DIR = 0xFF; //P1= Datenleitungen lcd_rw_low(); lcd_rs_low(); //L= Daten H=Befehl lcd_enable_low(); commandData = LCD_MODE_ON_OFF | LCD_MODE_MASTER_SLAVE | CURSOR_BLINKT ;// Zeichenmodus, Zeichen blinkt lcd_write_command(LCD_CMD_MODE, commandData); /* Send the set character pitch command with horizontal * character pitch of 8 (so 8 pixels are painted when we draw) */ commandData = LCD_CHAR_PITCH_8x6; lcd_write_command(LCD_CMD_CHAR_PITCH, commandData); //Zeichenfeld festlegen /* Send the number of characters command with the total * number of graphics bytes that can be painted horizontally * (width/8) */ commandData = (LCD_WIDTH/6)-1; //Zeichen pro Zeile 160/6=26,6)-1=25 lcd_write_command(LCD_CMD_NUM_CHARS, commandData); //Zeichen pro Zeile Befehl: 0x02 /* Set the time division */ commandData = 79; lcd_write_command(LCD_CMD_TIME_DIVISION, commandData); /* Set the display low/high start address to 0x00 (left corner) */ commandData = 0x00; lcd_write_command(LCD_CMD_DISPLAY_START_LA, commandData); lcd_write_command(LCD_CMD_DISPLAY_START_HA, commandData); /* Reset the cursor to home 0x00 (left corner) */ commandData = 0x00; lcd_write_command(LCD_CMD_CURSOR_LA, 0); lcd_write_command(LCD_CMD_CURSOR_HA, commandData); text_loeschen(); } /** * Moves the LCD cursor to the specified coordinates. * @param x The new x coordinante of the cursor. * @param y The new y coordinante of the cursor. */ void lcd_graphics_move(unsigned short x, unsigned short y) { unsigned short pos; /* Calculate the raw address in terms of bytes on the screen */ pos = ((y*LCD_WIDTH)+x)/8; /* Move the cursor to the new address */ lcd_write_command(LCD_CMD_CURSOR_LA, pos&0xFF); lcd_write_command(LCD_CMD_CURSOR_HA, pos>>8); } /** * Draws a byte to the LCD at the current LCD's cursor location. * @param data The byte to draw. The pixels are drawn MSB to LSB. */ void lcd_graphics_draw_byte(unsigned char data) { lcd_write_command(LCD_CMD_WRITE_DATA, data); } /** * Plots a byte at the specified coordinates. * @param x The x coordinante of the byte to be drawn. * @param y The y coordinante of the byte to be drawn. * @param data The byte to draw. The pixels are drawn MSB to LSB. */ void lcd_graphics_plot_byte(unsigned short x, unsigned short y, unsigned char data) { lcd_graphics_move(x, y); lcd_graphics_draw_byte(data); } /** * Plots a pixel at the specified coordinates. * @param x The x coordinante of the pixel. * @param y The y coordinante of the pixel. * @param state PIXEL_ON to set the pixel, otherwise pixel will be cleared. */ void lcd_graphics_plot_pixel(unsigned short x, unsigned short y, unsigned char state) { unsigned char pos; lcd_graphics_move(x, y); /* Since lcd_graphics_move() moves the cursor to a particular * byte, not bit, we need the relative distance to the specified * bit we are going to set/clear. */ pos = x%8; if (state == PIXEL_ON) lcd_write_command(LCD_CMD_SET_BIT, pos); else lcd_write_command(LCD_CMD_CLEAR_BIT, pos); } /** * Clears the LCD screen */ void lcd_graphics_clear(void) { unsigned short i; /* Move cursor to home (top left corner) */ lcd_graphics_move(0, 0); /* Draw empty bytes to ocucpy the entire screen */ for (i = 0; i < ((LCD_WIDTH*LCD_HEIGHT)/8); i++) lcd_graphics_draw_byte(0x00); } void text_loeschen(void) { unsigned int z; lcd_write_command(LCD_CMD_CURSOR_LA,0); lcd_write_command(LCD_CMD_CURSOR_HA,0); for (z=0; z<260;z++) // 25 Zeichen/Zeile x 10 Zeilen { lcd_write_command(LCD_CMD_WRITE_DATA,' '); //Leerzeichen schreiben } }