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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [arm9/] [aaed2000/] [current/] [src/] [lcd_support.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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