/* ======================================================================== * [PROJECT] SIR100 * [MODULE] Display * [TITLE] display source file * [FILE] display.c * [VSN] 1.0 * [CREATED] 26092003 * [LASTCHNGD] 06102006 * [COPYRIGHT] Copyright (C) STREAMIT BV * [PURPOSE] contains all interface- and low-level routines to * control the LCD and write characters or strings (menu-items) * ======================================================================== */ #define LOG_MODULE LOG_DISPLAY_MODULE #include #include #include #include #include #include #include #include "system.h" #include "portio.h" #include "display.h" #include "log.h" #include /*-------------------------------------------------------------------------*/ /* local defines */ /*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /* local variable definitions */ /*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /* local routines (prototyping) */ /*-------------------------------------------------------------------------*/ static void LcdWriteByte(u_char, u_char); static void LcdWriteNibble(u_char, u_char); static void LcdWaitBusy(void); void LcdBackLight(u_char Mode) { if (Mode==LCD_BACKLIGHT_ON) { sbi(LCD_BL_PORT, LCD_BL_BIT); // Turn on backlight } if (Mode==LCD_BACKLIGHT_OFF) { cbi(LCD_BL_PORT, LCD_BL_BIT); // Turn off backlight } } void LcdChar(char MyChar) { LcdWriteByte(WRITE_DATA, MyChar); } /* ����������������������������������������������������������������������� */ /*! * \brief Low-level initialisation function of the LCD-controller * * Initialise the controller and send the User-Defined Characters to CG-RAM * settings: 4-bit interface, cursor invisible and NOT blinking * 1 line dislay, 10 dots high characters * */ /* ����������������������������������������������������������������������� */ void LcdLowLevelInit() { u_char i; NutDelay(140); // wait for more than 140 ms after Vdd rises to 2.7 V for (i=0; i<3; ++i) { LcdWriteNibble(WRITE_COMMAND, 0x33); // function set: 8-bit mode; necessary to guarantee that NutDelay(4); // SIR starts up always in 5x10 dot mode } LcdWriteNibble(WRITE_COMMAND, 0x22); // function set: 4-bit mode; necessary because KS0070 doesn't NutDelay(1); // accept combined 4-bit mode & 5x10 dot mode programming //LcdWriteByte(WRITE_COMMAND, 0x24); // function set: 4-bit mode, 5x10 dot mode, 1-line LcdWriteByte(WRITE_COMMAND, 0x28); // function set: 4-bit mode, 5x7 dot mode, 2-lines NutDelay(5); LcdWriteByte(WRITE_COMMAND, 0x0C); // display ON/OFF: display ON, cursor OFF, blink OFF NutDelay(5); LcdWriteByte(WRITE_COMMAND, 0x01); // display clear NutDelay(5); LcdWriteByte(WRITE_COMMAND, 0x06); // entry mode set: increment mode, entire shift OFF LcdWriteByte(WRITE_COMMAND, 0x80); // DD-RAM address counter (cursor pos) to '0' } /* ����������������������������������������������������������������������� */ /*! * \brief Low-level routine to write a byte to LCD-controller * * Writes one byte to the LCD-controller (by calling LcdWriteNibble twice) * CtrlState determines if the byte is written to the instruction register * or to the data register. * * \param CtrlState destination: instruction or data * \param LcdByte byte to write * */ /* ����������������������������������������������������������������������� */ static void LcdWriteByte(u_char CtrlState, u_char LcdByte) { LcdWaitBusy(); // see if the controller is ready to receive next byte LcdWriteNibble(CtrlState, LcdByte & 0xF0); LcdWriteNibble(CtrlState, LcdByte << 4); } /* ����������������������������������������������������������������������� */ /*! * \brief Low-level routine to write a nibble to LCD-controller * * Writes a nibble to the LCD-controller (interface is a 4-bit databus, so * only 4 databits can be send at once). * The nibble to write is in the upper 4 bits of LcdNibble * * \param CtrlState destination: instruction or data * \param LcdNibble nibble to write (upper 4 bits in this byte * */ /* ����������������������������������������������������������������������� */ static void LcdWriteNibble(u_char CtrlState, u_char LcdNibble) { outp((inp(LCD_DATA_DDR) & 0x0F) | 0xF0, LCD_DATA_DDR); // set data-port to output again outp((inp(LCD_DATA_PORT) & 0x0F) | (LcdNibble & 0xF0), LCD_DATA_PORT); // prepare databus with nibble to write if (CtrlState == WRITE_COMMAND) { cbi(LCD_RS_PORT, LCD_RS); // command: RS low } else { sbi(LCD_RS_PORT, LCD_RS); // data: RS high } sbi(LCD_EN_PORT, LCD_EN); asm("nop\n\tnop"); // small delay cbi(LCD_EN_PORT, LCD_EN); cbi(LCD_RS_PORT, LCD_RS); outp((inp(LCD_DATA_DDR) & 0x0F), LCD_DATA_DDR); // set upper 4-bits of data-port to input outp((inp(LCD_DATA_PORT) & 0x0F) | 0xF0, LCD_DATA_PORT); // enable pull-ups in data-port } /* ����������������������������������������������������������������������� */ /*! * \brief Low-level routine to see if the controller is ready to receive * * This routine repeatetly reads the databus and checks if the highest bit (bit 7) * has become '0'. If a '0' is detected on bit 7 the function returns. * */ /* ����������������������������������������������������������������������� */ static void LcdWaitBusy() { u_char Busy = 1; u_char LcdStatus = 0; cbi (LCD_RS_PORT, LCD_RS); // select instruction register sbi (LCD_RW_PORT, LCD_RW); // we are going to read while (Busy) { sbi (LCD_EN_PORT, LCD_EN); // set 'enable' to catch 'Ready' asm("nop\n\tnop"); // small delay LcdStatus = inp(LCD_IN_PORT); // LcdStatus is used elsewhere in this module as well Busy = LcdStatus & 0x80; // break out of while-loop cause we are ready (b7='0') } cbi (LCD_EN_PORT, LCD_EN); // all ctrlpins low cbi (LCD_RS_PORT, LCD_RS); cbi (LCD_RW_PORT, LCD_RW); // we are going to write } //clears the Lcd screen void ClearLcd() { LcdWriteByte(WRITE_COMMAND, 0x01); } void LcdArrayLineOne(char *data, int size) { int i; LcdWriteByte(WRITE_COMMAND, 0x80); NutSleep(2); for(i = 0; i < size; i = i + 1){ LcdChar(data[i]); } } void LcdArrayLineTwo(char *data, int size){ int i; LcdWriteByte(WRITE_COMMAND, 0xC0); NutSleep(2); for(i = 0; i < size; i = i + 1){ LcdChar(data[i]); } } char getLoop(char *text,int offset) { return text[offset % strlen(text)]; } void setXCursorPos(int leftRight,int count) { int i; for ( i = 0; i