static inline void lcd_write_byte(char data) { // Ensure ENABLE is off LCD_EN_CLR(); PORT_WR(LCD_DATA_P, data << LCD_DATA_OFFSET); // Flash ENABLE to issue command. Requires at least 450ns, which is a bit less than this will take LCD_EN_SET(); //task_delay(LCD_VERY_SHORT_DELAY); _nop(); LCD_EN_CLR(); }
/*! * \brief Send half byte to LCD controller. * * \param nib The four least significant bits are sent. */ static void LcdWriteNibble(unsigned int nib) { #ifdef LCD_DATA_LSB nib <<= LCD_DATA_LSB; #else { unsigned int val = 0; if (nib & 0x01) { val |= LCD_D0; } if (nib & 0x02) { val |= LCD_D1; } if (nib & 0x04) { val |= LCD_D2; } if (nib & 0x08) { val |= LCD_D3; } nib = val; } #endif LcdSetBits(nib & LCD_DATA); LcdClrBits(~nib & LCD_DATA); /* Create Enable Pulse: * For HD44780 Displays we need: * Vcc = 5.0V -> PWeh >= 230ns * Vcc = 3.3V -> PWeh >= 500ns */ LCD_EN_SET(); NutMicroDelay(LCD_SHORT_DELAY); LCD_EN_CLR(); }
static unsigned int LcdReadNibble(void) { unsigned int rc; LCD_EN_SET(); LcdDelay(LCD_SHORT_DELAY); rc = inr(LCD_DATA_PIO_ID+PIO_PDSR_OFF) & LCD_DATA; LCD_EN_CLR(); LcdDelay(LCD_SHORT_DELAY); #ifdef LCD_DATA_LSB rc >>= LCD_DATA_LSB #else { unsigned int val = 0; if (rc & LCD_D0) { val |= 0x01; } if (rc & LCD_D1) { val |= 0x02; } if (rc & LCD_D2) { val |= 0x04; } if (rc & LCD_D3) { val |= 0x08; } rc = val; } #endif return rc; }
static int LcdInit(NUTDEVICE * dev) { LCD_RS_CLR(); LCD_RW_CLR(); LcdClrBits(LCD_DATA); NutMicroDelay(30); LCD_EN_CLR(); NutMicroDelay(30); NutSleep(18); /* This initialization will make sure, that the LCD is switched * to 8-bit mode, no matter which mode we start from or we finally * need. */ LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)); NutSleep(16); LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)); NutSleep(4); LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)); NutSleep(2); LcdWriteInstruction((_BV(LCD_FUNCTION)) | (_BV(LCD_FUNCTION_8BIT)) | (_BV(LCD_EXT)) , LCD_SHORT_DELAY); /* Switch display and cursor off. */ LcdWriteNibble(_BV(LCD_ON_CTRL) >> 4); LcdWriteNibble(_BV(LCD_ON_CTRL)); NutSleep(2); /* Clear display. */ LcdClear(); /* Set entry mode. */ LcdWriteCmd(_BV(LCD_ENTRY_MODE) | _BV(LCD_ENTRY_INC)); /* Switch display on. */ LcdWriteCmd(_BV(LCD_ON_CTRL) | _BV(LCD_ON_DISPLAY)); /* Move cursor home. */ LcdCursorHome(); /* Set data address to zero. */ LcdWriteCmd(_BV(LCD_DDRAM)); return 0; }
static int LcdInit(NUTDEVICE * dev) { #if defined(PMC_PCER) outr(PMC_PCER, _BV(LCD_RS_PIO_ID) | _BV(LCD_EN_PIO_ID)); #endif /* Initialize GPIO lines. */ #ifdef LCD_RW_BIT outr(PMC_PCER, _BV(LCD_RW_PIO_ID)); LCD_RW_CLR(); #endif #ifdef LCD_EN2_BIT outr(PMC_PCER, _BV(LCD_EN2_PIO_ID)); LCD_EN2_CLR(); #endif #ifdef LCD_RST_BIT outr(PMC_PCER, _BV(LCD_RST_PIO_ID)); LCD_RST_CLR(); #endif LCD_RS_CLR(); LCD_RW_CLR(); LcdClrBits(LCD_DATA); NutMicroDelay(30); LCD_EN_CLR(); NutMicroDelay(30); /* Initial delay. Actually only required after power on. */ NutSleep(16); /* This initialization will make sure, that the LCD is switched * to 8-bit mode, no matter which mode we start from or we finally * need. */ LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4); NutSleep(15); LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4); NutSleep(4); LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)) >> 4); NutSleep(2); #ifdef LCD_IF_4BIT /* We now switch to 4-bit mode */ LcdWriteNibble(_BV(LCD_FUNCTION) >> 4); NutSleep(2); // TODO: Add support for large font in single line displays /* Set number of lines and font. Can't be changed later. */ #if (LCD_ROWS == 2) || (LCD_ROWS==4) LcdWriteNibble((_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES)) >> 4); LcdWriteNibble(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_2LINES)); #else LcdWriteNibble(_BV(LCD_FUNCTION) >> 4); LcdWriteNibble(_BV(LCD_FUNCTION) ); #endif #else /* LCD_IF_4BIT */ LcdWriteCmd(_BV(LCD_FUNCTION) | _BV(LCD_FUNCTION_8BIT)); #endif /* LCD_IF_4BIT */ NutSleep(2); /* Switch display and cursor off. */ LcdWriteNibble(_BV(LCD_ON_CTRL) >> 4); LcdWriteNibble(_BV(LCD_ON_CTRL)); NutSleep(2); /* Clear display. */ LcdClear(); /* Set entry mode. */ LcdWriteCmd(_BV(LCD_ENTRY_MODE) | _BV(LCD_ENTRY_INC)); /* Switch display on. */ LcdWriteCmd(_BV(LCD_ON_CTRL) | _BV(LCD_ON_DISPLAY)); /* Move cursor home. */ LcdCursorHome(); /* Set data address to zero. */ LcdWriteCmd(_BV(LCD_DDRAM)); return 0; }
static void lcd_setup(void) { //mPORTDSetPinsDigitalOut(BIT_3); //mPORTDClearBits(BIT_3); mPORTDSetPinsDigitalOut( BIT_2 ); //Set backlight to open drain mPORTDOpenDrainOpen( BIT_2 ); //Enable contrast control OpenTimer2(T2_ON, LCD_PWMPERIOD); OpenOC4( OC_ON | OC_TIMER_MODE16 | OC_TIMER2_SRC | OC_CONTINUE_PULSE | OC_LOW_HIGH , LCD_PWMPERIOD, 0x0458 ); //Start the timer for contrast/brightness PWM //OpenTimer3(T3_ON | T3_PS_1_1 | T3_SOURCE_INT, LCD_PWMPERIOD); //PR3 = LCD_PWMPERIOD - 1; //OC3R = 0; //mT3SetIntPriority(4); //mT3ClearIntFlag(); //mT3IntEnable(1); //SetDCOC3PWM(LCD_PWMPERIOD >> 2); //SetDCOC3PWM(1); //Enable brightness control OpenOC3( OC_ON | OC_TIMER_MODE16 | OC_TIMER2_SRC | OC_CONTINUE_PULSE | OC_LOW_HIGH , LCD_PWMPERIOD, 0x500 ); // Open ENABLE line as output LCD_EN_CLR(); PORT_DIR_OUT(LCD_EN_P, LCD_EN); LCD_EN_CLR(); // Open RW and RS lines as output LCD_RS_CLR(); PORT_CLR(LCD_RW_P, LCD_RW); PORT_DIR_OUT(LCD_RS_P, LCD_RS); PORT_DIR_OUT(LCD_RW_P, LCD_RW); LCD_RS_CLR(); PORT_CLR(LCD_RW_P, LCD_RW); // Set data lines as output PORT_CLR(LCD_DATA_P, LCD_DATA_MASK); PORT_DIR_OUT(LCD_DATA_P, LCD_DATA_MASK); PORT_CLR(LCD_DATA_P, LCD_DATA_MASK); // Wait for proper power up task_delay(LCD_LONG_DELAY); task_delay(LCD_LONG_DELAY); task_delay(LCD_LONG_DELAY); task_delay(LCD_LONG_DELAY); // Wait for the LCD to power up correctly lcd_command(LCD_FUNCTION_SET_CMD | LCD_FUNCTION_SET_8_BITS); task_delay(LCD_SHORT_DELAY); lcd_command(LCD_FUNCTION_SET_CMD | LCD_FUNCTION_SET_8_BITS); task_delay(LCD_VERY_SHORT_DELAY); lcd_command(LCD_FUNCTION_SET_CMD | LCD_FUNCTION_SET_8_BITS); task_delay(LCD_VERY_SHORT_DELAY); // Set up the LCD function lcd_command(LCD_FUNCTION_SET_CMD | LCD_FUNCTION_SET_8_BITS | LCD_FUNCTION_SET_2_LINES); task_delay(LCD_VERY_SHORT_DELAY); // Turn the display on lcd_command(LCD_DISPLAY_CTRL_CMD | LCD_DISPLAY_CTRL_CURSOR_ON | LCD_DISPLAY_CTRL_BLINK_ON); task_delay(LCD_VERY_SHORT_DELAY); // Clear the display lcd_command(LCD_CLEAR_DISPLAY_CMD); task_delay(LCD_SHORT_DELAY); // Increase the cursor lcd_command(LCD_ENTRY_MODE_CMD | LCD_ENTRY_MODE_INCREASE); task_delay(LCD_SHORT_DELAY); lcd_command(LCD_DISPLAY_CTRL_CMD | LCD_DISPLAY_CTRL_DISPLAY_ON); task_delay(LCD_SHORT_DELAY); }