OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [arm9/] [aaed2000/] [v2_0/] [src/] [lcd_support.c] - Blame information for rev 565

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//        Lcd_support.c
4
//
5
//        Agilent AAED2000 - LCD support routines
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):     gthomas
44
// Contributors:  gthomas
45
// Date:          2001-11-03
46
// Description:   Simple LCD support
47
//####DESCRIPTIONEND####
48
 
49
#include <pkgconf/hal.h>
50
 
51
#include <cyg/infra/diag.h>
52
#include <cyg/hal/hal_io.h>       // IO macros
53
#include <cyg/hal/hal_if.h>       // Virtual vector support
54
#include <cyg/hal/hal_arch.h>     // Register state info
55
#include <cyg/hal/hal_intr.h>     // HAL interrupt macros
56
 
57
#include <cyg/hal/aaed2000.h>  // Board definitions
58
#include <cyg/hal/lcd_support.h>
59
#include <cyg/hal/hal_cache.h>
60
 
61
#include <string.h>
62
 
63
#ifdef CYGPKG_ISOINFRA
64
# include <pkgconf/isoinfra.h>
65
# ifdef CYGINT_ISO_STDIO_FORMATTED_IO
66
#  include <stdio.h>  // sscanf
67
# endif
68
#endif
69
 
70
#include CYGHWR_MEMORY_LAYOUT_H
71
#define LCD_FRAMEBUFFER CYGMEM_REGION_lcd
72
static cyg_uint32 lcd_framebuffer;
73
 
74
#ifndef FALSE
75
#define FALSE 0
76
#define TRUE  1
77
#endif
78
 
79
// Physical dimensions of LCD display
80
#define DISPLAY_WIDTH  640
81
#define DISPLAY_HEIGHT 480
82
 
83
// Logical layout
84
#ifdef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
85
#define LCD_WIDTH  DISPLAY_HEIGHT
86
#define LCD_HEIGHT DISPLAY_WIDTH
87
#else
88
#define LCD_WIDTH  DISPLAY_WIDTH
89
#define LCD_HEIGHT DISPLAY_HEIGHT
90
#endif
91
#define LCD_DEPTH   16
92
 
93
#define RGB_RED(x)   (((x)&0x1F)<<0)
94
#define RGB_GREEN(x) (((x)&0x1F)<<5)
95
#define RGB_BLUE(x)  (((x)&0x1F)<<10)
96
 
97
// Physical screen info
98
//static int lcd_depth  = LCD_DEPTH;  // Should be 1, 2, or 4
99
static int lcd_bpp;
100
#ifdef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
101
static int lcd_width  = LCD_WIDTH;
102
#endif
103
static int lcd_height = LCD_HEIGHT;
104
 
105
// Black on light blue
106
static int bg = RGB_RED(0x17) | RGB_GREEN(0x17) | RGB_BLUE(0x1F);
107
#ifdef CYGSEM_AAED2000_LCD_COMM
108
static int fg = RGB_RED(0) | RGB_GREEN(0) | RGB_BLUE(0);
109
#endif
110
 
111
// Compute the location for a pixel within the framebuffer
112
static cyg_uint32 *
113
lcd_fb(int row, int col)
114
{
115
    return (cyg_uint32 *)(lcd_framebuffer+(((row*DISPLAY_WIDTH)+col)*2));
116
}
117
 
118
void
119
lcd_on(bool enable)
120
{
121
    cyg_uint32 ctl;
122
 
123
    if (!enable) return;  // FIXME - need a way to [safely] blank screen
124
 
125
    // Turn on PWM [pulse wave modulated] voltage pump
126
    HAL_WRITE_UINT32(AAEC_PUMP_CONTROL,    0x800);  // Magic FIXME
127
    HAL_WRITE_UINT32(AAEC_PUMP_FREQUENCY, 0x3733);  // Magic FIXME
128
    // Turn on Power
129
    HAL_READ_UINT32(AAED_EXT_GPIO, ctl);
130
    ctl |= AAED_EXT_GPIO_LCD_PWR_EN;
131
    HAL_WRITE_UINT32(AAED_EXT_GPIO, ctl);
132
    // Power must be on for 0..20ms before enabling signals
133
    CYGACC_CALL_IF_DELAY_US(500);  // 500us should be long enough
134
    HAL_READ_UINT32(AAEC_LCD_CONTROL, ctl);
135
    ctl |= AAEC_LCD_CONTROL_ENAB | AAEC_LCD_CONTROL_PWR_ENAB;
136
    HAL_WRITE_UINT32(AAEC_LCD_CONTROL, ctl);
137
}
138
 
139
// Initialize LCD hardware
140
 
141
void
142
lcd_init(int depth)
143
{
144
    cyg_uint32 ctl;
145
 
146
    HAL_VIRT_TO_PHYS_ADDRESS(LCD_FRAMEBUFFER, lcd_framebuffer);
147
    lcd_clear();
148
    HAL_READ_UINT32(AAEC_LCD_CONTROL, ctl);
149
    if (ctl & (AAEC_LCD_CONTROL_ENAB | AAEC_LCD_CONTROL_PWR_ENAB)) {
150
        // LCD currently on - turn it off carefully
151
        ctl &= ~(AAEC_LCD_CONTROL_ENAB | AAEC_LCD_CONTROL_PWR_ENAB);
152
        HAL_WRITE_UINT32(AAEC_LCD_CONTROL, ctl);
153
        // Now wait a little
154
        CYGACC_CALL_IF_DELAY_US(500);
155
        // Turn off Power
156
        HAL_READ_UINT32(AAED_EXT_GPIO, ctl);
157
        ctl &= ~AAED_EXT_GPIO_LCD_PWR_EN;
158
        HAL_WRITE_UINT32(AAED_EXT_GPIO, ctl);
159
        // Now wait for 1.0 second
160
        CYGACC_CALL_IF_DELAY_US(1000*1000);
161
    }
162
    HAL_WRITE_UINT32(AAEC_LCD_CONTROL, 0x00010028);   // Magic FIXME
163
    HAL_WRITE_UINT32(AAEC_LCD_TIMING0, 0x2B135F9C);   // Magic FIXME
164
    HAL_WRITE_UINT32(AAEC_LCD_TIMING1, 0x211401DF);   // Magic FIXME
165
    HAL_WRITE_UINT32(AAEC_LCD_TIMING2, 0x067F1820);   // Magic FIXME
166
    HAL_WRITE_UINT32(AAEC_LCD_TIMING3, 0x00000000);   // Magic FIXME
167
    HAL_WRITE_UINT32(AAEC_LCD_UPBASE,  lcd_framebuffer);
168
    HAL_WRITE_UINT32(AAEC_LCD_LPBASE,  lcd_framebuffer);
169
#if 0 // For some reason, this crashes miserably
170
    lcd_framebuffer = LCD_FRAMEBUFFER;  // Logical operations use cached space
171
#endif
172
    lcd_on(true);
173
    lcd_bpp = 16;
174
}
175
 
176
// Get information about the frame buffer
177
int
178
lcd_getinfo(struct lcd_info *info)
179
{
180
    if (lcd_bpp == 0) {
181
        return 0;  // LCD not initialized
182
    }
183
    info->width = DISPLAY_WIDTH;
184
    info->height = DISPLAY_HEIGHT;
185
    info->bpp = lcd_bpp;
186
    info->fb = (void*)LCD_FRAMEBUFFER;
187
    info->rlen = DISPLAY_WIDTH * 2;
188
    info->type = FB_TRUE_RGB555;
189
    return 1; // Information valid
190
}
191
 
192
// Clear screen
193
void
194
lcd_clear(void)
195
{
196
#ifndef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
197
    cyg_uint32 *fb_row0, *fb_rown;
198
    cyg_uint32 _bg = (bg<<16)|bg;
199
 
200
    fb_row0 = lcd_fb(0, 0);
201
    fb_rown = lcd_fb(lcd_height, 0);
202
    while (fb_row0 != fb_rown) {
203
        *fb_row0++ = _bg;
204
    }
205
#else
206
    int row, col;
207
    for (row = 0;  row < lcd_height;  row++) {
208
        for (col = 0;  col < lcd_width;  col++) {
209
            set_pixel(row, col, bg);
210
        }
211
    }
212
#endif
213
}
214
 
215
#ifdef CYGSEM_AAED2000_LCD_COMM
216
 
217
//
218
// Additional support for LCD/Keyboard as 'console' device
219
//
220
 
221
#ifdef CYGOPT_AAED2000_LCD_COMM_LOGO
222
#include "banner.xpm"
223
#endif
224
#include "font.h"
225
 
226
// Virtual screen info
227
static int curX = 0;  // Last used position
228
static int curY = 0;
229
//static int width = LCD_WIDTH / (FONT_WIDTH*NIBBLES_PER_PIXEL);
230
//static int height = LCD_HEIGHT / (FONT_HEIGHT*SCREEN_SCALE);
231
 
232
#define SCREEN_PAN            20
233
#define SCREEN_WIDTH          80
234
#define SCREEN_HEIGHT         (LCD_HEIGHT/FONT_HEIGHT)
235
#define VISIBLE_SCREEN_WIDTH  (LCD_WIDTH/FONT_WIDTH)
236
#define VISIBLE_SCREEN_HEIGHT (LCD_HEIGHT/FONT_HEIGHT)
237
static char screen[SCREEN_HEIGHT][SCREEN_WIDTH];
238
static int screen_height = SCREEN_HEIGHT;
239
static int screen_width = SCREEN_WIDTH;
240
static int screen_pan = 0;
241
 
242
// Usable area on screen [logical pixel rows]
243
static int screen_start = 0;
244
static int screen_end = LCD_HEIGHT/FONT_HEIGHT;
245
 
246
static bool cursor_enable = true;
247
 
248
// Functions
249
static void lcd_drawc(cyg_int8 c, int x, int y);
250
 
251
// Note: val is a 16 bit, RGB555 value which must be mapped
252
// onto a 12 bit value.
253
#define RED(v)   ((v>>12) & 0x0F)
254
#define GREEN(v) ((v>>7) & 0x0F)
255
#define BLUE(v)  ((v>>1) & 0x0F)
256
#ifdef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
257
#error PORTRAIT MODE NOT IMPLEMENTED
258
// Translate coordinates, rotating clockwise 90 degrees
259
static void
260
set_pixel(int row, int col, unsigned short val)
261
{
262
//    fp->pixels[col][(DISPLAY_WIDTH-1)-row] = val;
263
    int _row = (240-1) - col;
264
    int _col = row;
265
    unsigned char *pxptr = (unsigned char *)(0xC0000000 + (_row * 480) + ((_col * 3) / 2));
266
 
267
    diag_printf("%s\n", __FUNCTION__);  return;
268
    if ((row >= LCD_HEIGHT) || (col >= LCD_WIDTH)) return;
269
    if (0)
270
    {
271
        int old = start_console();
272
        diag_printf("row=%d/%d, col=%d/%d, pxptr = %p\n", row, _row, col, _col, pxptr);
273
        end_console(old);
274
    }
275
    if ((row % 2) == 0) {
276
        // Even row
277
        *pxptr++ = RED(val) | (GREEN(val) << 4);
278
        *pxptr = (*pxptr & 0xF0) | BLUE(val);
279
    } else {
280
        // Odd row
281
        *pxptr = (*pxptr & 0x0F) | (RED(val) << 4);
282
        *++pxptr = GREEN(val) | (BLUE(val) << 4);
283
    }
284
}
285
#else
286
 
287
static void
288
set_pixel(int row, int col, unsigned short val)
289
{
290
    unsigned short *pix = (unsigned short *)lcd_fb(row, col);
291
    *pix = val;
292
}
293
#endif
294
 
295
static int
296
_hexdigit(char c)
297
{
298
    if ((c >= '0') && (c <= '9')) {
299
        return c - '0';
300
    } else
301
    if ((c >= 'A') && (c <= 'F')) {
302
        return (c - 'A') + 0x0A;
303
    } else
304
    if ((c >= 'a') && (c <= 'f')) {
305
        return (c - 'a') + 0x0a;
306
    }
307
 
308
    return 0;
309
}
310
 
311
static int
312
_hex(char *cp)
313
{
314
    return (_hexdigit(*cp)<<4) | _hexdigit(*(cp+1));
315
}
316
 
317
static unsigned short
318
parse_color(char *cp)
319
{
320
    int red, green, blue;
321
 
322
    while (*cp && (*cp != 'c')) cp++;
323
    if (cp) {
324
        cp += 2;
325
        if (*cp == '#') {
326
            red = _hex(cp+1);
327
            green = _hex(cp+3);
328
            blue = _hex(cp+5);
329
#ifdef USE_RGB565
330
            return RGB_RED(red>>3) | RGB_GREEN(green>>2) | RGB_BLUE(blue>>3);
331
#else
332
            return RGB_RED(red>>3) | RGB_GREEN(green>>3) | RGB_BLUE(blue>>3);
333
#endif
334
        } else {
335
            // Should be "None"
336
            return 0xFFFF;
337
        }
338
    } else {
339
        return 0xFFFF;
340
    }
341
}
342
 
343
#ifndef CYGINT_ISO_STDIO_FORMATTED_IO
344
static int
345
get_int(char **_cp)
346
{
347
    char *cp = *_cp;
348
    char c;
349
    int val = 0;
350
 
351
    while ((c = *cp++) && (c != ' ')) {
352
        if ((c >= '0') && (c <= '9')) {
353
            val = val * 10 + (c - '0');
354
        } else {
355
            return -1;
356
        }
357
    }
358
    *_cp = cp;
359
    return val;
360
}
361
#endif
362
 
363
#ifdef CYGOPT_AAED2000_LCD_COMM_LOGO
364
int
365
show_xpm(char *xpm[], int screen_pos)
366
{
367
    int i, row, col, offset;
368
    char *cp;
369
    int nrows, ncols, nclrs;
370
    unsigned short colors[256];  // Mapped by character index
371
 
372
    cp = xpm[0];
373
#ifdef CYGINT_ISO_STDIO_FORMATTED_IO
374
    if (sscanf(cp, "%d %d %d", &ncols, &nrows, &nclrs) != 3) {
375
#else
376
    if (((ncols = get_int(&cp)) < 0) ||
377
        ((nrows = get_int(&cp)) < 0) ||
378
        ((nclrs = get_int(&cp)) < 0)) {
379
 
380
#endif
381
        diag_printf("Can't parse XPM data, sorry\n");
382
        return 0;
383
    }
384
    // printf("%d rows, %d cols, %d colors\n", nrows, ncols, nclrs);
385
 
386
    for (i = 0;  i < 256;  i++) {
387
        colors[i] = 0x0000;
388
    }
389
    for (i = 0;  i < nclrs;  i++) {
390
        cp = xpm[i+1];
391
        colors[(unsigned int)*cp] = parse_color(&cp[1]);
392
        // printf("Color[%c] = %x\n", *cp, colors[(unsigned int)*cp]);
393
    }
394
 
395
#ifdef CYGOPT_AAED2000_LCD_COMM_LOGO_TOP
396
    offset = screen_pos;
397
#else
398
    offset = screen_pos-nrows;
399
#endif
400
    for (row = 0;  row < nrows;  row++) {
401
        cp = xpm[nclrs+1+row];
402
        for (col = 0;  col < ncols;  col++) {
403
            set_pixel(row+offset, col, colors[(unsigned int)*cp++]);
404
        }
405
    }
406
#ifdef CYGOPT_AAED2000_LCD_COMM_LOGO_TOP
407
    screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT;
408
    screen_end = LCD_HEIGHT/FONT_HEIGHT;
409
    return offset+nrows;
410
#else    
411
    screen_start = 0;
412
    screen_height = offset / FONT_HEIGHT;
413
    screen_end = screen_height;
414
    return offset;
415
#endif
416
}
417
#endif
418
 
419
void
420
lcd_screen_clear(void)
421
{
422
    int row, col, pos;
423
    for (row = 0;  row < screen_height;  row++) {
424
        for (col = 0;  col < screen_width;  col++) {
425
            screen[row][col] = ' ';
426
        }
427
    }
428
#ifdef CYGOPT_AAED2000_LCD_COMM_LOGO
429
    // Note: Row 0 seems to wrap incorrectly
430
#ifdef CYGOPT_AAED2000_LCD_COMM_LOGO_TOP
431
    pos = 0;
432
#else
433
    pos = (LCD_HEIGHT-1);
434
#endif
435
    show_xpm(banner_xpm, pos);
436
#endif // CYGOPT_AAED2000_LCD_COMM_LOGO
437
    curX = 0;  curY = screen_start;
438
    if (cursor_enable) {
439
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
440
    }
441
}
442
 
443
// Position cursor
444
void
445
lcd_moveto(int X, int Y)
446
{
447
    if (cursor_enable) {
448
        lcd_drawc(screen[curY][curX], curX-screen_pan, curY);
449
    }
450
    if (X < 0) X = 0;
451
    if (X >= screen_width) X = screen_width-1;
452
    curX = X;
453
    if (Y < screen_start) Y = screen_start;
454
    if (Y >= screen_height) Y = screen_height-1;
455
    curY = Y;
456
    if (cursor_enable) {
457
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
458
    }
459
}
460
 
461
// Render a character at position (X,Y) with current background/foreground
462
static void
463
lcd_drawc(cyg_int8 c, int x, int y)
464
{
465
    cyg_uint8 bits;
466
    int l, p;
467
    int xoff, yoff;
468
#ifndef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
469
    cyg_uint32 *fb;
470
#endif
471
 
472
 
473
    if ((x < 0) || (x >= VISIBLE_SCREEN_WIDTH) ||
474
        (y < 0) || (y >= screen_height)) return;
475
    for (l = 0;  l < FONT_HEIGHT;  l++) {
476
        bits = font_table[c-FIRST_CHAR][l];
477
        yoff = y*FONT_HEIGHT + l;
478
        xoff = x*FONT_HEIGHT;
479
#ifndef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
480
        // Caution - only works for little-endian & font sizes multiple of 2
481
        fb = lcd_fb(yoff, xoff);
482
        for (p = 0;  p < FONT_WIDTH;  p += 2) {
483
            switch (bits & 0x03) {
484
            case 0:
485
                *fb++ = (bg << 16) | bg;
486
                break;
487
            case 1:
488
                *fb++ = (bg << 16) | fg;
489
                break;
490
            case 2:
491
                *fb++ = (fg << 16) | bg;
492
                break;
493
            case 3:
494
                *fb++ = (fg << 16) | fg;
495
                break;
496
            }
497
            bits >>= 2;
498
        }
499
#else
500
        for (p = 0;  p < FONT_WIDTH;  p++) {
501
            set_pixel(yoff, xoff + p, (bits & 0x01) ? fg : bg);
502
            bits >>= 1;
503
        }
504
#endif
505
    }
506
}
507
 
508
static void
509
lcd_refresh(void)
510
{
511
    int row, col;
512
 
513
    for (row = screen_start;  row < screen_height;  row++) {
514
        for (col = 0;  col < VISIBLE_SCREEN_WIDTH;  col++) {
515
            if ((col+screen_pan) < screen_width) {
516
                lcd_drawc(screen[row][col+screen_pan], col, row);
517
            } else {
518
                lcd_drawc(' ', col, row);
519
            }
520
        }
521
    }
522
    if (cursor_enable) {
523
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
524
    }
525
}
526
 
527
static void
528
lcd_scroll(void)
529
{
530
    int col;
531
    cyg_uint8 *c1;
532
    cyg_uint32 *lc0, *lc1, *lcn;
533
#ifndef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
534
    cyg_uint32 *fb_row0, *fb_row1, *fb_rown;
535
#endif
536
 
537
    // First scroll up the virtual screen
538
#if ((SCREEN_WIDTH%4) != 0)
539
#error Scroll code optimized for screen with multiple of 4 columns
540
#endif
541
    lc0 = (cyg_uint32 *)&screen[0][0];
542
    lc1 = (cyg_uint32 *)&screen[1][0];
543
    lcn = (cyg_uint32 *)&screen[screen_height][0];
544
    while (lc1 != lcn) {
545
        *lc0++ = *lc1++;
546
    }
547
    c1 = &screen[screen_height-1][0];
548
    for (col = 0;  col < screen_width;  col++) {
549
        *c1++ = 0x20;
550
    }
551
#ifdef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
552
    // Redrawing the screen in this mode is hard :-)
553
    lcd_refresh();
554
#else
555
    fb_row0 = lcd_fb(screen_start*FONT_HEIGHT, 0);
556
    fb_row1 = lcd_fb((screen_start+1)*FONT_HEIGHT, 0);
557
    fb_rown = lcd_fb(screen_end*FONT_HEIGHT, 0);
558
#if 1
559
    while (fb_row1 != fb_rown) {
560
        *fb_row0++ = *fb_row1++;
561
    }
562
#else
563
    // Optimized ARM assembly "move" code
564
    asm __volatile(
565
        "mov r0,%0;"
566
        "mov r1,%1;"
567
        "mov r2,%2;"
568
        "10: ldmia r1!,{r3-r10};"
569
        "stmia r0!,{r3-r10};"
570
        "cmp r1,r2;"
571
        "bne 10b"
572
        :
573
        : "r"(fb_row0), "r"(fb_row1), "r"(fb_rown)
574
        : "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10"
575
        );
576
#endif
577
    // Erase bottom line
578
    for (col = 0;  col < screen_width;  col++) {
579
        lcd_drawc(' ', col, screen_end-1);
580
    }
581
#endif
582
}
583
 
584
// Draw one character at the current position
585
void
586
lcd_putc(cyg_int8 c)
587
{
588
    if (cursor_enable) {
589
        lcd_drawc(screen[curY][curX], curX-screen_pan, curY);
590
    }
591
    switch (c) {
592
    case '\r':
593
        curX = 0;
594
        break;
595
    case '\n':
596
        curY++;
597
        break;
598
    case '\b':
599
        curX--;
600
        if (curX < 0) {
601
            curY--;
602
            if (curY < 0) curY = 0;
603
            curX = screen_width-1;
604
        }
605
        break;
606
    default:
607
        if (((cyg_uint8)c < FIRST_CHAR) || ((cyg_uint8)c > LAST_CHAR)) c = '.';
608
        screen[curY][curX] = c;
609
        lcd_drawc(c, curX-screen_pan, curY);
610
        curX++;
611
        if (curX == screen_width) {
612
            curY++;
613
            curX = 0;
614
        }
615
    }
616
    if (curY >= screen_height) {
617
        lcd_scroll();
618
        curY = (screen_height-1);
619
    }
620
    if (cursor_enable) {
621
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
622
    }
623
}
624
 
625
// Basic LCD 'printf()' support
626
 
627
#include <stdarg.h>
628
 
629
#define is_digit(c) ((c >= '0') && (c <= '9'))
630
 
631
static int
632
_cvt(unsigned long val, char *buf, long radix, char *digits)
633
{
634
    char temp[80];
635
    char *cp = temp;
636
    int length = 0;
637
    if (val == 0) {
638
        /* Special case */
639
        *cp++ = '0';
640
    } else {
641
        while (val) {
642
            *cp++ = digits[val % radix];
643
            val /= radix;
644
        }
645
    }
646
    while (cp != temp) {
647
        *buf++ = *--cp;
648
        length++;
649
    }
650
    *buf = '\0';
651
    return (length);
652
}
653
 
654
static int
655
lcd_vprintf(void (*putc)(cyg_int8), const char *fmt0, va_list ap)
656
{
657
    char c, sign, *cp;
658
    int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
659
    char buf[32];
660
    long val;
661
    while ((c = *fmt0++)) {
662
        cp = buf;
663
        length = 0;
664
        if (c == '%') {
665
            c = *fmt0++;
666
            left_prec = right_prec = pad_on_right = 0;
667
            if (c == '-') {
668
                c = *fmt0++;
669
                pad_on_right++;
670
            }
671
            if (c == '0') {
672
                zero_fill = TRUE;
673
                c = *fmt0++;
674
            } else {
675
                zero_fill = FALSE;
676
            }
677
            while (is_digit(c)) {
678
                left_prec = (left_prec * 10) + (c - '0');
679
                c = *fmt0++;
680
            }
681
            if (c == '.') {
682
                c = *fmt0++;
683
                zero_fill++;
684
                while (is_digit(c)) {
685
                    right_prec = (right_prec * 10) + (c - '0');
686
                    c = *fmt0++;
687
                }
688
            } else {
689
                right_prec = left_prec;
690
            }
691
            sign = '\0';
692
            switch (c) {
693
            case 'd':
694
            case 'x':
695
            case 'X':
696
                val = va_arg(ap, long);
697
                switch (c) {
698
                case 'd':
699
                    if (val < 0) {
700
                        sign = '-';
701
                        val = -val;
702
                    }
703
                    length = _cvt(val, buf, 10, "0123456789");
704
                    break;
705
                case 'x':
706
                    length = _cvt(val, buf, 16, "0123456789abcdef");
707
                    break;
708
                case 'X':
709
                    length = _cvt(val, buf, 16, "0123456789ABCDEF");
710
                    break;
711
                }
712
                break;
713
            case 's':
714
                cp = va_arg(ap, char *);
715
                length = strlen(cp);
716
                break;
717
            case 'c':
718
                c = va_arg(ap, long /*char*/);
719
                (*putc)(c);
720
                continue;
721
            default:
722
                (*putc)('?');
723
            }
724
            pad = left_prec - length;
725
            if (sign != '\0') {
726
                pad--;
727
            }
728
            if (zero_fill) {
729
                c = '0';
730
                if (sign != '\0') {
731
                    (*putc)(sign);
732
                    sign = '\0';
733
                }
734
            } else {
735
                c = ' ';
736
            }
737
            if (!pad_on_right) {
738
                while (pad-- > 0) {
739
                    (*putc)(c);
740
                }
741
            }
742
            if (sign != '\0') {
743
                (*putc)(sign);
744
            }
745
            while (length-- > 0) {
746
                (*putc)(c = *cp++);
747
                if (c == '\n') {
748
                    (*putc)('\r');
749
                }
750
            }
751
            if (pad_on_right) {
752
                while (pad-- > 0) {
753
                    (*putc)(' ');
754
                }
755
            }
756
        } else {
757
            (*putc)(c);
758
            if (c == '\n') {
759
                (*putc)('\r');
760
            }
761
        }
762
    }
763
 
764
    // FIXME
765
    return 0;
766
}
767
 
768
int
769
_lcd_printf(char const *fmt, ...)
770
{
771
    int ret;
772
    va_list ap;
773
 
774
    va_start(ap, fmt);
775
    ret = lcd_vprintf(lcd_putc, fmt, ap);
776
    va_end(ap);
777
    return (ret);
778
}
779
 
780
void
781
lcd_setbg(int red, int green, int blue)
782
{
783
    bg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
784
}
785
 
786
void
787
lcd_setfg(int red, int green, int blue)
788
{
789
    fg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
790
}
791
 
792
//
793
// Support LCD/keyboard (PS2) as a virtual I/O channel
794
//   Adapted from i386/pcmb_screen.c
795
//
796
 
797
static int  _timeout = 500;
798
 
799
static cyg_bool
800
lcd_comm_getc_nonblock(void* __ch_data, cyg_uint8* ch)
801
{
802
    if( !aaed2000_KeyboardTest() )
803
        return false;
804
    *ch = aaed2000_KeyboardGetc();
805
    return true;
806
}
807
 
808
static cyg_uint8
809
lcd_comm_getc(void* __ch_data)
810
{
811
    cyg_uint8 ch;
812
 
813
    while (!lcd_comm_getc_nonblock(__ch_data, &ch)) ;
814
    return ch;
815
}
816
 
817
static void
818
lcd_comm_putc(void* __ch_data, cyg_uint8 c)
819
{
820
    lcd_putc(c);
821
}
822
 
823
static void
824
lcd_comm_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
825
{
826
#if 0
827
    CYGARC_HAL_SAVE_GP();
828
 
829
    while(__len-- > 0)
830
        lcd_comm_putc(__ch_data, *__buf++);
831
 
832
    CYGARC_HAL_RESTORE_GP();
833
#endif
834
}
835
 
836
static void
837
lcd_comm_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
838
{
839
#if 0
840
    CYGARC_HAL_SAVE_GP();
841
 
842
    while(__len-- > 0)
843
        *__buf++ = lcd_comm_getc(__ch_data);
844
 
845
    CYGARC_HAL_RESTORE_GP();
846
#endif
847
}
848
 
849
static cyg_bool
850
lcd_comm_getc_timeout(void* __ch_data, cyg_uint8* ch)
851
{
852
    int delay_count;
853
    cyg_bool res;
854
 
855
    delay_count = _timeout * 2; // delay in .5 ms steps
856
    for(;;) {
857
        res = lcd_comm_getc_nonblock(__ch_data, ch);
858
        if (res || 0 == delay_count--)
859
            break;
860
        CYGACC_CALL_IF_DELAY_US(500);
861
    }
862
    return res;
863
}
864
 
865
static int
866
lcd_comm_control(void *__ch_data, __comm_control_cmd_t __func, ...)
867
{
868
    static int vector = 0;
869
    int ret = -1;
870
    static int irq_state = 0;
871
 
872
    CYGARC_HAL_SAVE_GP();
873
 
874
    switch (__func) {
875
    case __COMMCTL_IRQ_ENABLE:
876
        ret = irq_state;
877
        irq_state = 1;
878
        break;
879
    case __COMMCTL_IRQ_DISABLE:
880
        ret = irq_state;
881
        irq_state = 0;
882
        break;
883
    case __COMMCTL_DBG_ISR_VECTOR:
884
        ret = vector;
885
        break;
886
    case __COMMCTL_SET_TIMEOUT:
887
    {
888
        va_list ap;
889
 
890
        va_start(ap, __func);
891
 
892
        ret = _timeout;
893
        _timeout = va_arg(ap, cyg_uint32);
894
 
895
        va_end(ap);
896
        break;
897
    }
898
    case __COMMCTL_FLUSH_OUTPUT:
899
        ret = 0;
900
        break;
901
    default:
902
        break;
903
    }
904
    CYGARC_HAL_RESTORE_GP();
905
    return ret;
906
}
907
 
908
static int
909
lcd_comm_isr(void *__ch_data, int* __ctrlc,
910
           CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
911
{
912
#if 0
913
    char ch;
914
 
915
    cyg_drv_interrupt_acknowledge(__vector);
916
    *__ctrlc = 0;
917
    if (lcd_comm_getc_nonblock(__ch_data, &ch)) {
918
        if (ch == 0x03) {
919
            *__ctrlc = 1;
920
        }
921
    }
922
    return CYG_ISR_HANDLED;
923
#else
924
    return 0;
925
#endif
926
}
927
 
928
void
929
lcd_comm_init(void)
930
{
931
    static int init = 0;
932
 
933
    if (!init) {
934
        hal_virtual_comm_table_t* comm;
935
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
936
 
937
        init = 1;
938
        lcd_on(false);
939
        if (!aaed2000_KeyboardInit()) {
940
            // No keyboard - no LCD display
941
            return;
942
        }
943
        // Initialize screen
944
        cursor_enable = true;
945
        lcd_init(16);
946
        lcd_screen_clear();
947
 
948
        // Setup procs in the vector table
949
        CYGACC_CALL_IF_SET_CONSOLE_COMM(1);  // FIXME - should be controlled by CDL
950
        comm = CYGACC_CALL_IF_CONSOLE_PROCS();
951
        //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
952
        CYGACC_COMM_IF_WRITE_SET(*comm, lcd_comm_write);
953
        CYGACC_COMM_IF_READ_SET(*comm, lcd_comm_read);
954
        CYGACC_COMM_IF_PUTC_SET(*comm, lcd_comm_putc);
955
        CYGACC_COMM_IF_GETC_SET(*comm, lcd_comm_getc);
956
        CYGACC_COMM_IF_CONTROL_SET(*comm, lcd_comm_control);
957
        CYGACC_COMM_IF_DBG_ISR_SET(*comm, lcd_comm_isr);
958
        CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, lcd_comm_getc_timeout);
959
 
960
        // Restore original console
961
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
962
    }
963
}
964
 
965
#ifdef CYGPKG_REDBOOT
966
#include <redboot.h>
967
 
968
// Get here when RedBoot is idle.  If it's been long enough, then
969
// dim the LCD.  The problem is - how to determine other activities
970
// so at this doesn't get in the way.  In the default case, this will
971
// be called from RedBoot every 10ms (CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT)
972
 
973
#define MAX_IDLE_TIME (30*100)
974
 
975
static void
976
idle(bool is_idle)
977
{
978
    static int idle_time = 0;
979
    static bool was_idled = false;
980
 
981
    if (is_idle) {
982
        if (!was_idled) {
983
            if (++idle_time == MAX_IDLE_TIME) {
984
                was_idled = true;
985
                lcd_on(false);
986
            }
987
        }
988
    } else {
989
        idle_time = 0;
990
        if (was_idled) {
991
            was_idled = false;
992
                lcd_on(true);
993
        }
994
    }
995
}
996
 
997
RedBoot_idle(idle, RedBoot_AFTER_NETIO);
998
#endif
999
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.