| /* most of this is taken from the file */ |
| /* hal/powerpc/cogent/current/src/hal_diag.c in the */ |
| /* Cygnus eCos source. Here is the copyright notice: */ |
| /* */ |
| /*============================================================================= */ |
| /* */ |
| /* hal_diag.c */ |
| /* */ |
| /* HAL diagnostic output code */ |
| /* */ |
| /*============================================================================= */ |
| /*####COPYRIGHTBEGIN#### */ |
| /* */ |
| /* ------------------------------------------- */ |
| /* The contents of this file are subject to the Cygnus eCos Public License */ |
| /* Version 1.0 (the "License"); you may not use this file except in */ |
| /* compliance with the License. You may obtain a copy of the License at */ |
| /* http://sourceware.cygnus.com/ecos */ |
| /* */ |
| /* Software distributed under the License is distributed on an "AS IS" */ |
| /* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the */ |
| /* License for the specific language governing rights and limitations under */ |
| /* the License. */ |
| /* */ |
| /* The Original Code is eCos - Embedded Cygnus Operating System, released */ |
| /* September 30, 1998. */ |
| /* */ |
| /* The Initial Developer of the Original Code is Cygnus. Portions created */ |
| /* by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. */ |
| /* ------------------------------------------- */ |
| /* */ |
| /*####COPYRIGHTEND#### */ |
| /*============================================================================= */ |
| /*#####DESCRIPTIONBEGIN#### */ |
| /* */ |
| /* Author(s): nickg, jskov */ |
| /* Contributors: nickg, jskov */ |
| /* Date: 1999-03-23 */ |
| /* Purpose: HAL diagnostic output */ |
| /* Description: Implementations of HAL diagnostic output support. */ |
| /* */ |
| /*####DESCRIPTIONEND#### */ |
| /* */ |
| /*============================================================================= */ |
| |
| /*----------------------------------------------------------------------------- */ |
| /* Cogent board specific LCD code */ |
| |
| #include <common.h> |
| #include <stdarg.h> |
| #include <board/cogent/lcd.h> |
| |
| static char lines[2][LCD_LINE_LENGTH+1]; |
| static int curline; |
| static int linepos; |
| static int heartbeat_active; |
| /* make the next two strings exactly LCD_LINE_LENGTH (16) chars long */ |
| /* pad to the right with spaces if necessary */ |
| static char init_line0[LCD_LINE_LENGTH+1] = "U-Boot Cogent "; |
| static char init_line1[LCD_LINE_LENGTH+1] = "mjj, 11 Aug 2000"; |
| |
| static inline unsigned char |
| lcd_read_status(cma_mb_lcd *clp) |
| { |
| /* read the Busy Status Register */ |
| return (cma_mb_reg_read(&clp->lcd_bsr)); |
| } |
| |
| static inline void |
| lcd_wait_not_busy(cma_mb_lcd *clp) |
| { |
| /* |
| * wait for not busy |
| * Note: It seems that the LCD isn't quite ready to process commands |
| * when it clears the BUSY flag. Reading the status address an extra |
| * time seems to give it enough breathing room. |
| */ |
| |
| while (lcd_read_status(clp) & LCD_STAT_BUSY) |
| ; |
| |
| (void)lcd_read_status(clp); |
| } |
| |
| static inline void |
| lcd_write_command(cma_mb_lcd *clp, unsigned char cmd) |
| { |
| lcd_wait_not_busy(clp); |
| |
| /* write the Command Register */ |
| cma_mb_reg_write(&clp->lcd_cmd, cmd); |
| } |
| |
| static inline void |
| lcd_write_data(cma_mb_lcd *clp, unsigned char data) |
| { |
| lcd_wait_not_busy(clp); |
| |
| /* write the Current Character Register */ |
| cma_mb_reg_write(&clp->lcd_ccr, data); |
| } |
| |
| static inline void |
| lcd_dis(int addr, char *string) |
| { |
| cma_mb_lcd *clp = (cma_mb_lcd *)CMA_MB_LCD_BASE; |
| int pos, linelen; |
| |
| linelen = LCD_LINE_LENGTH; |
| if (heartbeat_active && addr == LCD_LINE0) |
| linelen--; |
| |
| lcd_write_command(clp, LCD_CMD_ADD + addr); |
| for (pos = 0; *string != '\0' && pos < linelen; pos++) |
| lcd_write_data(clp, *string++); |
| } |
| |
| void |
| lcd_init(void) |
| { |
| cma_mb_lcd *clp = (cma_mb_lcd *)CMA_MB_LCD_BASE; |
| int i; |
| |
| /* configure the lcd for 8 bits/char, 2 lines and 5x7 dot matrix */ |
| lcd_write_command(clp, LCD_CMD_MODE); |
| |
| /* turn the LCD display on */ |
| lcd_write_command(clp, LCD_CMD_DON); |
| |
| curline = 0; |
| linepos = 0; |
| |
| for (i = 0; i < LCD_LINE_LENGTH; i++) { |
| lines[0][i] = init_line0[i]; |
| lines[1][i] = init_line1[i]; |
| } |
| |
| lines[0][LCD_LINE_LENGTH] = lines[1][LCD_LINE_LENGTH] = 0; |
| |
| lcd_dis(LCD_LINE0, lines[0]); |
| lcd_dis(LCD_LINE1, lines[1]); |
| |
| printf("HD44780 2 line x %d char display\n", LCD_LINE_LENGTH); |
| } |
| |
| void |
| lcd_write_char(const char c) |
| { |
| int i, linelen; |
| |
| /* ignore CR */ |
| if (c == '\r') |
| return; |
| |
| linelen = LCD_LINE_LENGTH; |
| if (heartbeat_active && curline == 0) |
| linelen--; |
| |
| if (c == '\n') { |
| lcd_dis(LCD_LINE0, &lines[curline^1][0]); |
| lcd_dis(LCD_LINE1, &lines[curline][0]); |
| |
| /* Do a line feed */ |
| curline ^= 1; |
| linelen = LCD_LINE_LENGTH; |
| if (heartbeat_active && curline == 0) |
| linelen--; |
| linepos = 0; |
| |
| for (i = 0; i < linelen; i++) |
| lines[curline][i] = ' '; |
| |
| return; |
| } |
| |
| /* Only allow to be output if there is room on the LCD line */ |
| if (linepos < linelen) |
| lines[curline][linepos++] = c; |
| } |
| |
| void |
| lcd_flush(void) |
| { |
| lcd_dis(LCD_LINE1, &lines[curline][0]); |
| } |
| |
| void |
| lcd_write_string(const char *s) |
| { |
| char *p; |
| |
| for (p = (char *)s; *p != '\0'; p++) |
| lcd_write_char(*p); |
| } |
| |
| void |
| lcd_printf(const char *fmt, ...) |
| { |
| va_list args; |
| char buf[CFG_PBSIZE]; |
| |
| va_start(args, fmt); |
| (void)vsprintf(buf, fmt, args); |
| va_end(args); |
| |
| lcd_write_string(buf); |
| } |
| |
| void |
| lcd_heartbeat(void) |
| { |
| cma_mb_lcd *clp = (cma_mb_lcd *)CMA_MB_LCD_BASE; |
| #if 0 |
| static char rotchars[] = { '|', '/', '-', '\\' }; |
| #else |
| /* HD44780 Rom Code A00 has no backslash */ |
| static char rotchars[] = { '|', '/', '-', '\315' }; |
| #endif |
| static int rotator_index = 0; |
| |
| heartbeat_active = 1; |
| |
| /* write the address */ |
| lcd_write_command(clp, LCD_CMD_ADD + LCD_LINE0 + (LCD_LINE_LENGTH - 1)); |
| |
| /* write the next char in the sequence */ |
| lcd_write_data(clp, rotchars[rotator_index]); |
| |
| if (++rotator_index >= (sizeof rotchars / sizeof rotchars[0])) |
| rotator_index = 0; |
| } |