aboutsummaryrefslogtreecommitdiffstats
path: root/board/cogent/lcd.c
blob: 76f5ad103fa1b6f24742cf5866291ef6a02da7c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/* 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[CONFIG_SYS_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;
}

#ifdef CONFIG_SHOW_ACTIVITY
void board_show_activity (ulong timestamp)
{
#ifdef CONFIG_STATUS_LED
	if ((timestamp % (CONFIG_SYS_HZ / 2) == 0)
		lcd_heartbeat ();
#endif
}

void show_activity(int arg)
{
}
#endif