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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [sa11x0/] [ipaq/] [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
//        SA1110/iPAQ - 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
//                Richard Panton <richard.panton@3glab.com>
45
// Date:          2001-02-24
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/hal_sa11x0.h>   // Board definitions
58
#include <cyg/hal/ipaq.h>
59
#include <cyg/hal/lcd_support.h>
60
#include <cyg/hal/atmel_support.h>
61
#include <cyg/hal/hal_cache.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
// Gross hack to force use of simple internal functions.
71
// Using libc sscanf fails (as far as I could tell from a quick look)
72
// when assertions are enabled because some of the C++ contructors have
73
// not been run yet.   jskov
74
#undef CYGINT_ISO_STDIO_FORMATTED_IO
75
 
76
#ifndef FALSE
77
#define FALSE 0
78
#define TRUE  1
79
#endif
80
 
81
#define PORTRAIT_MODE
82
//#define LOGO_AT_TOP
83
#include "banner.xpm"
84
#include "font.h"
85
 
86
// Physical dimensions of LCD display
87
#define DISPLAY_WIDTH  320
88
#define DISPLAY_HEIGHT 240
89
 
90
// Logical layout
91
#ifdef PORTRAIT_MODE
92
#define LCD_WIDTH  240
93
#define LCD_HEIGHT 320
94
#else
95
#define LCD_WIDTH  320
96
#define LCD_HEIGHT 240
97
#endif
98
#define LCD_DEPTH   16
99
 
100
static struct lcd_frame {
101
    unsigned short palette[16];
102
    unsigned short pixels[DISPLAY_HEIGHT][DISPLAY_WIDTH];
103
    unsigned char  pad[256];
104
} *lcd_frame_buffer = (struct lcd_frame *)0x01FC0000;  // Actually just 0x26000 bytes, but...
105
 
106
#define USE_RGB565
107
#ifdef USE_RGB565
108
#define RGB_RED(x)   (((x)&0x1F)<<11)
109
#define RGB_GREEN(x) (((x)&0x3F)<<5)
110
#define RGB_BLUE(x)  ((x)&0x1F)
111
#else
112
#define RGB_RED(x)   (((x)&0x0F)<<12)
113
#define RGB_GREEN(x) (((x)&0x0F)<<7)
114
#define RGB_BLUE(x)  (((x)&0x0F)<<1)
115
#endif
116
 
117
static volatile struct lcd_frame *fp;
118
 
119
// Physical screen info
120
//static int lcd_depth  = LCD_DEPTH;  // Should be 1, 2, or 4
121
static int lcd_bpp;
122
static int lcd_width  = LCD_WIDTH;
123
static int lcd_height = LCD_HEIGHT;
124
 
125
// Virtual screen info
126
static int curX = 0;  // Last used position
127
static int curY = 0;
128
//static int width = LCD_WIDTH / (FONT_WIDTH*NIBBLES_PER_PIXEL);
129
//static int height = LCD_HEIGHT / (FONT_HEIGHT*SCREEN_SCALE);
130
 
131
static int fg = RGB_RED(15) | RGB_GREEN(63) | RGB_BLUE(8);
132
static int bg = RGB_RED(0) | RGB_GREEN(0) | RGB_BLUE(15/*31*/);
133
 
134
#define SCREEN_PAN            20
135
#define SCREEN_WIDTH          80
136
#define SCREEN_HEIGHT         (LCD_HEIGHT/FONT_HEIGHT)
137
#define VISIBLE_SCREEN_WIDTH  (LCD_WIDTH/FONT_WIDTH)
138
#define VISIBLE_SCREEN_HEIGHT (LCD_HEIGHT/FONT_HEIGHT)
139
static char screen[SCREEN_HEIGHT][SCREEN_WIDTH];
140
static int screen_start = 0;
141
static int screen_height = SCREEN_HEIGHT;
142
static int screen_width = SCREEN_WIDTH;
143
static int screen_pan = 0;
144
 
145
static bool cursor_enable = true;
146
 
147
static int kbd_pos;
148
 
149
// Functions
150
static void lcd_drawc(cyg_int8 c, int x, int y);
151
 
152
#ifdef PORTRAIT_MODE
153
// Translate coordinates, rotating clockwise 90 degrees
154
static void
155
set_pixel(int row, int col, unsigned short val)
156
{
157
    fp->pixels[col][(DISPLAY_WIDTH-1)-row] = val;
158
}
159
#else
160
static void
161
set_pixel(int row, int col, unsigned short val)
162
{
163
    fp->pixels[row][col] = val;
164
}
165
#endif
166
 
167
static int
168
_hexdigit(char c)
169
{
170
    if ((c >= '0') && (c <= '9')) {
171
        return c - '0';
172
    } else
173
    if ((c >= 'A') && (c <= 'F')) {
174
        return (c - 'A') + 0x0A;
175
    } else
176
    if ((c >= 'a') && (c <= 'f')) {
177
        return (c - 'a') + 0x0a;
178
    }
179
    return 0;
180
}
181
 
182
static int
183
_hex(char *cp)
184
{
185
    return (_hexdigit(*cp)<<4) | _hexdigit(*(cp+1));
186
}
187
 
188
static unsigned short
189
parse_color(char *cp)
190
{
191
    int red, green, blue;
192
 
193
    while (*cp && (*cp != 'c')) cp++;
194
    if (cp) {
195
        cp += 2;
196
        if (*cp == '#') {
197
            red = _hex(cp+1);
198
            green = _hex(cp+3);
199
            blue = _hex(cp+5);
200
#ifdef USE_RGB565
201
            return RGB_RED(red>>3) | RGB_GREEN(green>>2) | RGB_BLUE(blue>>3);
202
#else
203
            return RGB_RED(red>>3) | RGB_GREEN(green>>3) | RGB_BLUE(blue>>3);
204
#endif
205
        } else {
206
            // Should be "None"
207
            return 0xFFFF;
208
        }
209
    } else {
210
        return 0xFFFF;
211
    }
212
}
213
 
214
#ifndef CYGINT_ISO_STDIO_FORMATTED_IO
215
static int
216
get_int(char **_cp)
217
{
218
    char *cp = *_cp;
219
    char c;
220
    int val = 0;
221
 
222
    while ((c = *cp++) && (c != ' ')) {
223
        if ((c >= '0') && (c <= '9')) {
224
            val = val * 10 + (c - '0');
225
        } else {
226
            return -1;
227
        }
228
    }
229
    *_cp = cp;
230
    return val;
231
}
232
#endif
233
 
234
int
235
show_xpm(char *xpm[], int screen_pos)
236
{
237
    int i, row, col, offset;
238
    char *cp;
239
    int nrows, ncols, nclrs;
240
    unsigned short colors[256];  // Mapped by character index
241
 
242
    cp = xpm[0];
243
#ifdef CYGINT_ISO_STDIO_FORMATTED_IO
244
    if (sscanf(cp, "%d %d %d", &ncols, &nrows, &nclrs) != 3) {
245
#else
246
    if (((ncols = get_int(&cp)) < 0) ||
247
        ((nrows = get_int(&cp)) < 0) ||
248
        ((nclrs = get_int(&cp)) < 0)) {
249
 
250
#endif
251
        diag_printf("Can't parse XPM data, sorry\n");
252
        return 0;
253
    }
254
    // printf("%d rows, %d cols, %d colors\n", nrows, ncols, nclrs);
255
 
256
    for (i = 0;  i < 256;  i++) {
257
        colors[i] = 0x0000;
258
    }
259
    for (i = 0;  i < nclrs;  i++) {
260
        cp = xpm[i+1];
261
        colors[(unsigned int)*cp] = parse_color(&cp[1]);
262
        // printf("Color[%c] = %x\n", *cp, colors[(unsigned int)*cp]);
263
    }
264
 
265
#ifdef LOGO_AT_TOP
266
    offset = screen_pos;
267
#else
268
    offset = screen_pos-nrows;
269
#endif
270
    for (row = 0;  row < nrows;  row++) {
271
        cp = xpm[nclrs+1+row];
272
        for (col = 0;  col < ncols;  col++) {
273
            set_pixel(row+offset, col, colors[(unsigned int)*cp++]);
274
        }
275
    }
276
#ifdef LOGO_AT_TOP
277
    screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT;
278
    return offset+nrows;
279
#else    
280
    screen_height = offset / FONT_HEIGHT;
281
    return offset;
282
#endif
283
}
284
 
285
void
286
lcd_init(int depth)
287
{
288
    // Currently only color/16bpp supported
289
 
290
    if (depth != 16) {
291
        return;
292
    }
293
    lcd_bpp = depth;
294
    fp = (struct lcd_frame *)hal_virt_to_phys_address((cyg_uint32)lcd_frame_buffer);
295
    // Enable LCD in 320x240 16bpp
296
    *SA1110_DBAR1 = (unsigned long)&(fp->palette);
297
    *SA1110_LCCR1 = 0x0b100800 + DISPLAY_WIDTH - 16;
298
    *SA1110_LCCR2 = 0x0a010400 + DISPLAY_HEIGHT - 1;
299
    *SA1110_LCCR3 = 0x00300010;
300
    fp->palette[0] = 0x2000;  // Tell controller true color / 16 bits
301
    *SA1110_LCCR0 = 0xB9;     // Color
302
    ipaq_EGPIO(SA1110_EIO_LCD_3V3|SA1110_EIO_LCD_CTRL|SA1110_EIO_LCD_5V|SA1110_EIO_LCD_VDD,
303
            SA1110_EIO_LCD_3V3_ON|SA1110_EIO_LCD_CTRL_ON|SA1110_EIO_LCD_5V_ON|SA1110_EIO_LCD_VDD_ON);
304
    lcd_clear();
305
    lcd_brightness(31);
306
}
307
 
308
// Get information about the frame buffer
309
int
310
lcd_getinfo(struct lcd_info *info)
311
{
312
    if (lcd_bpp == 0) {
313
        return 0;  // LCD not initialized
314
    }
315
    info->width = DISPLAY_WIDTH;
316
    info->height = DISPLAY_HEIGHT;
317
    info->bpp = lcd_bpp;
318
    info->fb = (void *)lcd_frame_buffer->pixels;  // Note: this is cached
319
    info->rlen = DISPLAY_WIDTH * 2;
320
    info->type = FB_TRUE_RGB565;
321
    return 1; // Information valid
322
}
323
 
324
// Control screen light [brightness]
325
 
326
static void
327
lcd_brightness_ack(atmel_pkt *pkt)
328
{
329
}
330
 
331
static int _lcd_brightness;
332
 
333
void
334
lcd_brightness(int level)
335
{
336
    unsigned char cmd[3];
337
 
338
    atmel_register(ATMEL_CMD_LIGHT, lcd_brightness_ack);
339
    cmd[0] = 1;  // LCD magic
340
    cmd[1] = (level > 0) ? 1 : 0;  // Turn light on
341
    cmd[2] = level;
342
    if (level) _lcd_brightness = level;
343
    atmel_send(ATMEL_CMD_LIGHT, cmd, 3);
344
}
345
 
346
// Clear screen
347
void
348
lcd_clear(void)
349
{
350
    int row, col;
351
    int pos;
352
 
353
#ifndef USE_RGB565
354
    int val;
355
    for (row = 0;  row < lcd_height;  row++) {
356
        for (col = 0;  col < lcd_width;  col++) {
357
            set_pixel(row, col, RGB_RED(31));
358
        }
359
    }
360
    CYGACC_CALL_IF_DELAY_US(100000);
361
 
362
    for (row = 0;  row < lcd_height;  row++) {
363
        for (col = 0;  col < lcd_width;  col++) {
364
            set_pixel(row, col, RGB_GREEN(31));
365
        }
366
    }
367
    CYGACC_CALL_IF_DELAY_US(100000);
368
    val = 0;
369
    for (pos = 0;  pos < 16;  pos++) {
370
        val = (1<<pos);
371
        diag_printf("Set pixel to 0x%04x\n", val);
372
        for (row = 0;  row < lcd_height;  row++) {
373
            for (col = 0;  col < lcd_width;  col++) {
374
                set_pixel(row, col, val);
375
            }
376
        }
377
        CYGACC_CALL_IF_DELAY_US(100000);
378
    }
379
    val = 0;
380
    for (pos = 8;  pos < 16;  pos++) {
381
        val |= (1<<pos);
382
        diag_printf("Set pixel to 0x%04x\n", val);
383
        for (row = 0;  row < lcd_height;  row++) {
384
            for (col = 0;  col < lcd_width;  col++) {
385
                set_pixel(row, col, val);
386
            }
387
        }
388
        CYGACC_CALL_IF_DELAY_US(100000);
389
    }
390
 
391
    for (row = 0;  row < lcd_height;  row++) {
392
        for (col = 0;  col < lcd_width;  col++) {
393
            set_pixel(row, col, RGB_BLUE(31));
394
        }
395
    }
396
    CYGACC_CALL_IF_DELAY_US(100000);
397
#endif // RGB565
398
 
399
    for (row = 0;  row < lcd_height;  row++) {
400
        for (col = 0;  col < lcd_width;  col++) {
401
            set_pixel(row, col, bg);
402
        }
403
    }
404
    for (row = 0;  row < screen_height;  row++) {
405
        for (col = 0;  col < screen_width;  col++) {
406
            screen[row][col] = ' ';
407
        }
408
    }
409
    // Note: Row 0 seems to wrap incorrectly
410
#ifdef LOGO_AT_TOP
411
    pos = 0;
412
#else
413
    pos = (LCD_HEIGHT-1);
414
#endif
415
    kbd_pos = show_xpm(banner_xpm, pos);
416
    curX = 0;  curY = screen_start;
417
    if (cursor_enable) {
418
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
419
    }
420
}
421
 
422
// Position cursor
423
void
424
lcd_moveto(int X, int Y)
425
{
426
    if (cursor_enable) {
427
        lcd_drawc(screen[curY][curX], curX-screen_pan, curY);
428
    }
429
    if (X < 0) X = 0;
430
    if (X >= screen_width) X = screen_width-1;
431
    curX = X;
432
    if (Y < screen_start) Y = screen_start;
433
    if (Y >= screen_height) Y = screen_height-1;
434
    curY = Y;
435
    if (cursor_enable) {
436
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
437
    }
438
}
439
 
440
// Render a character at position (X,Y) with current background/foreground
441
static void
442
lcd_drawc(cyg_int8 c, int x, int y)
443
{
444
    cyg_uint8 bits;
445
    int l, p;
446
 
447
    if ((x < 0) || (x >= VISIBLE_SCREEN_WIDTH) ||
448
        (y < 0) || (y >= screen_height)) return;
449
    for (l = 0;  l < FONT_HEIGHT;  l++) {
450
        bits = font_table[c-FIRST_CHAR][l];
451
        for (p = 0;  p < FONT_WIDTH;  p++) {
452
            if (bits & 0x01) {
453
                set_pixel(y*FONT_HEIGHT+l, x*FONT_WIDTH + p, fg);
454
            } else {
455
                set_pixel(y*FONT_HEIGHT+l, x*FONT_WIDTH + p, bg);
456
            }
457
            bits >>= 1;
458
        }
459
    }
460
}
461
 
462
static void
463
lcd_refresh(void)
464
{
465
    int row, col;
466
#ifdef PORTRAIT_MODE
467
    for (row = screen_start;  row < screen_height;  row++) {
468
        for (col = 0;  col < VISIBLE_SCREEN_WIDTH;  col++) {
469
            if ((col+screen_pan) < screen_width) {
470
                lcd_drawc(screen[row][col+screen_pan], col, row);
471
            } else {
472
                lcd_drawc(' ', col, row);
473
            }
474
        }
475
    }
476
#else
477
    cyg_uint16 *p1, *p2;
478
    // Now the physical screen
479
    for (row = FONT_HEIGHT*(screen_start+1);  row < LCD_HEIGHT;  row++) {
480
        p1 = &fp->pixels[row-FONT_HEIGHT][0];
481
        p2 = &fp->pixels[row][0];
482
        for (col = 0;  col < LCD_WIDTH;  col++) {
483
            *p1++ = *p2++;
484
        }
485
    }
486
    for (row = LCD_HEIGHT-FONT_HEIGHT;  row < LCD_HEIGHT;  row++) {
487
        p1 = &fp->pixels[row][0];
488
        for (col = 0;  col < LCD_WIDTH;  col++) {
489
            *p1++ = bg;
490
        }
491
    }
492
#endif
493
    if (cursor_enable) {
494
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
495
    }
496
}
497
 
498
static void
499
lcd_scroll(void)
500
{
501
    int row, col;
502
    cyg_uint8 *c1, *c2;
503
 
504
    // First scroll up the virtual screen
505
    for (row = (screen_start+1);  row < screen_height;  row++) {
506
        c1 = &screen[row-1][0];
507
        c2 = &screen[row][0];
508
        for (col = 0;  col < screen_width;  col++) {
509
            *c1++ = *c2++;
510
        }
511
    }
512
    c1 = &screen[screen_height-1][0];
513
    for (col = 0;  col < screen_width;  col++) {
514
        *c1++ = 0x20;
515
    }
516
    lcd_refresh();
517
}
518
 
519
// Draw one character at the current position
520
void
521
lcd_putc(cyg_int8 c)
522
{
523
    if (cursor_enable) {
524
        lcd_drawc(screen[curY][curX], curX-screen_pan, curY);
525
    }
526
    switch (c) {
527
    case '\r':
528
        curX = 0;
529
        break;
530
    case '\n':
531
        curY++;
532
        break;
533
    case '\b':
534
        curX--;
535
        if (curX < 0) {
536
            curY--;
537
            if (curY < 0) curY = 0;
538
            curX = screen_width-1;
539
        }
540
        break;
541
    default:
542
        if (((cyg_uint8)c < FIRST_CHAR) || ((cyg_uint8)c > LAST_CHAR)) c = '.';
543
        screen[curY][curX] = c;
544
        lcd_drawc(c, curX-screen_pan, curY);
545
        curX++;
546
        if (curX == screen_width) {
547
            curY++;
548
            curX = 0;
549
        }
550
    }
551
    if (curY >= screen_height) {
552
        lcd_scroll();
553
        curY = (screen_height-1);
554
    }
555
    if (cursor_enable) {
556
        lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
557
    }
558
}
559
 
560
// Basic LCD 'printf()' support
561
 
562
#include <stdarg.h>
563
#include <string.h>
564
 
565
#define is_digit(c) ((c >= '0') && (c <= '9'))
566
 
567
static int
568
_cvt(unsigned long val, char *buf, long radix, char *digits)
569
{
570
    char temp[80];
571
    char *cp = temp;
572
    int length = 0;
573
    if (val == 0) {
574
        /* Special case */
575
        *cp++ = '0';
576
    } else {
577
        while (val) {
578
            *cp++ = digits[val % radix];
579
            val /= radix;
580
        }
581
    }
582
    while (cp != temp) {
583
        *buf++ = *--cp;
584
        length++;
585
    }
586
    *buf = '\0';
587
    return (length);
588
}
589
 
590
static int
591
lcd_vprintf(void (*putc)(cyg_int8), const char *fmt0, va_list ap)
592
{
593
    char c, sign, *cp;
594
    int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
595
    char buf[32];
596
    long val;
597
 
598
    while ((c = *fmt0++)) {
599
        cp = buf;
600
        length = 0;
601
        if (c == '%') {
602
            c = *fmt0++;
603
            left_prec = right_prec = pad_on_right = 0;
604
            if (c == '-') {
605
                c = *fmt0++;
606
                pad_on_right++;
607
            }
608
            if (c == '0') {
609
                zero_fill = TRUE;
610
                c = *fmt0++;
611
            } else {
612
                zero_fill = FALSE;
613
            }
614
            while (is_digit(c)) {
615
                left_prec = (left_prec * 10) + (c - '0');
616
                c = *fmt0++;
617
            }
618
            if (c == '.') {
619
                c = *fmt0++;
620
                zero_fill++;
621
                while (is_digit(c)) {
622
                    right_prec = (right_prec * 10) + (c - '0');
623
                    c = *fmt0++;
624
                }
625
            } else {
626
                right_prec = left_prec;
627
            }
628
            sign = '\0';
629
            switch (c) {
630
            case 'd':
631
            case 'x':
632
            case 'X':
633
                val = va_arg(ap, long);
634
                switch (c) {
635
                case 'd':
636
                    if (val < 0) {
637
                        sign = '-';
638
                        val = -val;
639
                    }
640
                    length = _cvt(val, buf, 10, "0123456789");
641
                    break;
642
                case 'x':
643
                    length = _cvt(val, buf, 16, "0123456789abcdef");
644
                    break;
645
                case 'X':
646
                    length = _cvt(val, buf, 16, "0123456789ABCDEF");
647
                    break;
648
                }
649
                break;
650
            case 's':
651
                cp = va_arg(ap, char *);
652
                length = strlen(cp);
653
                break;
654
            case 'c':
655
                c = va_arg(ap, long /*char*/);
656
                (*putc)(c);
657
                continue;
658
            default:
659
                (*putc)('?');
660
            }
661
            pad = left_prec - length;
662
            if (sign != '\0') {
663
                pad--;
664
            }
665
            if (zero_fill) {
666
                c = '0';
667
                if (sign != '\0') {
668
                    (*putc)(sign);
669
                    sign = '\0';
670
                }
671
            } else {
672
                c = ' ';
673
            }
674
            if (!pad_on_right) {
675
                while (pad-- > 0) {
676
                    (*putc)(c);
677
                }
678
            }
679
            if (sign != '\0') {
680
                (*putc)(sign);
681
            }
682
            while (length-- > 0) {
683
                (*putc)(c = *cp++);
684
                if (c == '\n') {
685
                    (*putc)('\r');
686
                }
687
            }
688
            if (pad_on_right) {
689
                while (pad-- > 0) {
690
                    (*putc)(' ');
691
                }
692
            }
693
        } else {
694
            (*putc)(c);
695
            if (c == '\n') {
696
                (*putc)('\r');
697
            }
698
        }
699
    }
700
    return 0;  // Should be length of string written
701
}
702
 
703
int
704
lcd_printf(char const *fmt, ...)
705
{
706
    int ret;
707
    va_list ap;
708
 
709
    va_start(ap, fmt);
710
    ret = lcd_vprintf(lcd_putc, fmt, ap);
711
    va_end(ap);
712
    return (ret);
713
}
714
 
715
void
716
lcd_setbg(int red, int green, int blue)
717
{
718
    bg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
719
}
720
 
721
void
722
lcd_setfg(int red, int green, int blue)
723
{
724
    fg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
725
}
726
 
727
#ifdef CYGSEM_IPAQ_LCD_COMM
728
 
729
//
730
// Support LCD/touchscreen as a virtual I/O channel
731
//
732
 
733
#include "kbd.xpm"     // Contains 4 keyboard images
734
 
735
static int  _timeout = 500;
736
 
737
struct coord {
738
    short x,y;
739
};
740
 
741
#ifdef PORTRAIT_MODE
742
#define CS_UL 1
743
#define CS_UR 0
744
#define CS_LL 3
745
#define CS_LR 2
746
#else
747
#define CS_UL 0
748
#define CS_UR 1
749
#define CS_LL 2
750
#define CS_LR 3
751
#endif
752
#define KBD_FUZZ 50
753
static struct coord kbd_limits[4];
754
static short minX, maxX, minY, maxY;  // Coordinates for the keyboard matrix
755
 
756
#define CODE_NONE   0x00
757
#define CODE_CTRL   0x81
758
#define CODE_SHIFT  0x82
759
#define CODE_NUM    0x83
760
#define CODE_BS     0x08
761
#define CODE_CR     0x0D
762
#define CODE_ESC    0x1B
763
#define CODE_DEL    0x7F
764
#define CTRL(x)     (x&0x1F)
765
 
766
typedef unsigned char kbd_map[4][11];
767
static kbd_map kbd_norm_map = {
768
    { 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', CODE_BS },
769
    { 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-', CODE_CR },
770
    { CODE_CTRL, 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', ';' },
771
    { CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, '\'', '=', '\\', '/'}
772
};
773
 
774
static kbd_map kbd_num_map = {
775
    { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', CODE_BS },
776
    { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', CODE_CR },
777
    { CODE_CTRL, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '`', '~' },
778
    { CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, '[', ']', '{', '}'}
779
};
780
 
781
static kbd_map kbd_ctrl_map = {
782
    { CTRL('q'), CTRL('w'), CTRL('e'), CTRL('r'), CTRL('t'), CTRL('y'),
783
      CTRL('u'), CTRL('i'), CTRL('o'), CTRL('p'), CODE_ESC  },
784
    { CTRL('a'), CTRL('s'), CTRL('d'), CTRL('f'), CTRL('g'), CTRL('h'),
785
      CTRL('j'), CTRL('k'), CTRL('l'), CTRL('_'), CODE_CR },
786
    { CODE_CTRL, CTRL('z'), CTRL('x'), CTRL('c'), CTRL('v'), CTRL('b'),
787
      CTRL('n'), CTRL('m'), '\\', CTRL(']'), CTRL('^') },
788
    { CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, ' ', ' ', ' ', CODE_DEL}
789
};
790
 
791
static kbd_map kbd_shift_map = {
792
    { 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', CODE_BS },
793
    { 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '_', CODE_CR },
794
    { CODE_CTRL, 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', ':' },
795
    { CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, '"', '+', '|', '?'}
796
};
797
 
798
static kbd_map *cur_kbd_map = &kbd_norm_map;
799
static bool kbd_active = true;
800
 
801
// Pseudo-keyboard indicator
802
#define LCD_KBD_NORM  0
803
#define LCD_KBD_SHIFT 1
804
#define LCD_KBD_NUM   2
805
#define LCD_KBD_CTRL  3
806
 
807
// Display pseudo keyboard
808
static void
809
lcd_kbd(int which)
810
{
811
    char **kbd_xpm;
812
 
813
    switch (which) {
814
    case LCD_KBD_NORM:
815
        kbd_xpm = keynorm_xpm;
816
        break;
817
    case LCD_KBD_SHIFT:
818
        kbd_xpm = keyshft_xpm;
819
        break;
820
    case LCD_KBD_CTRL:
821
        kbd_xpm = keyctrl_xpm;
822
        break;
823
    case LCD_KBD_NUM:
824
        kbd_xpm = keynum_xpm;
825
        break;
826
    default:
827
        return;
828
    }
829
    show_xpm(kbd_xpm, kbd_pos);
830
}
831
 
832
static bool
833
inside(int pos, int lim1, int lim2)
834
{
835
    if (lim1 <= lim2) {
836
        return ((pos >= lim1) && (pos <= lim2));
837
    } else {
838
        return ((pos >= lim2) && (pos <= lim1));
839
    }
840
}
841
 
842
static int
843
abs(int x)
844
{
845
    if (x < 0) {
846
        return -x;
847
    } else {
848
        return x;
849
    }
850
}
851
 
852
static int
853
min(int x, int y)
854
{
855
    if (x < y) {
856
        return x;
857
    } else {
858
        return y;
859
    }
860
}
861
 
862
static int
863
max(int x, int y)
864
{
865
    if (x < y) {
866
        return y;
867
    } else {
868
        return x;
869
    }
870
}
871
 
872
static cyg_bool
873
lcd_comm_getc_nonblock(void* __ch_data, cyg_uint8* ch)
874
{
875
    static bool pen_down = false;
876
    static bool waiting_for_pen_down = true;
877
    static int  total_events = 0;
878
    static int  pen_idle;
879
    static unsigned long totalX, totalY;
880
    struct ts_event tse;
881
    struct key_event ke;
882
//#define KBD_DEBUG
883
#ifdef KBD_DEBUG
884
    static bool dump_info = false;
885
#endif
886
#define PEN_IDLE_TIMEOUT 50000
887
#define MIN_KBD_EVENTS   10
888
 
889
    // See if any buttons have been pushed
890
    if (key_get_event(&ke)) {
891
        if ((ke.button_info & ATMEL_BUTTON_STATE) == ATMEL_BUTTON_STATE_UP) {
892
//            diag_printf("Key = %x\n", ke.button_info);
893
            lcd_on(true);
894
            switch (ke.button_info & ATMEL_BUTTON_VALUE) {
895
            case ATMEL_BUTTON_RETURN:
896
                *ch = CTRL('C');
897
                return true;
898
            case ATMEL_BUTTON_JOY_DOWN:
899
            case ATMEL_BUTTON_JOY_UP:
900
                screen_pan = 0;
901
                lcd_refresh();
902
                break;
903
            case ATMEL_BUTTON_JOY_LEFT:
904
                screen_pan -= SCREEN_PAN;
905
                if (screen_pan < 0) screen_pan = 0;
906
                lcd_refresh();
907
                break;
908
            case ATMEL_BUTTON_JOY_RIGHT:
909
                screen_pan += SCREEN_PAN;
910
                if (screen_pan > (SCREEN_WIDTH-SCREEN_PAN)) screen_pan = SCREEN_WIDTH-SCREEN_PAN;
911
                lcd_refresh();
912
                break;
913
            default:
914
#ifdef KBD_DEBUG
915
                {
916
                    int cur = start_console(0);
917
                    diag_printf("pen: %d, waiting: %d, total: %d\n", pen_down, waiting_for_pen_down, total_events);
918
                    end_console(cur);
919
                    dump_info = !dump_info;
920
                }
921
#endif
922
                return false;
923
            }
924
        }
925
        return false;  // Ignore down presses
926
    }
927
    // If keyboard not active, always returns false
928
    if (!kbd_active) {
929
        return false;
930
    }
931
    // Wait for pen down
932
    if (waiting_for_pen_down) {
933
        if (ts_get_event(&tse)) {
934
            lcd_on(true);
935
            if (!tse.up) {
936
                pen_down = true;
937
                waiting_for_pen_down = false;
938
                totalX = totalY = 0;
939
                total_events = 0;
940
                pen_idle = PEN_IDLE_TIMEOUT;
941
#ifdef KBD_DEBUG
942
                if (dump_info) {
943
                    int cur = start_console(0);
944
                    diag_printf("start pen: %d, waiting: %d, total: %d\n", pen_down, waiting_for_pen_down, total_events);
945
                    end_console(cur);
946
                }
947
#endif
948
            }
949
        }
950
        return false;
951
    }
952
    // While the pen is down, accumulate some data
953
    if (ts_get_event(&tse)) {
954
        pen_idle = PEN_IDLE_TIMEOUT;
955
        if (tse.up) {
956
            pen_down = false;
957
            waiting_for_pen_down = true;
958
        } else {
959
            total_events++;
960
            pen_down = true;
961
#ifdef PORTRAIT_MODE
962
            totalX += tse.y;
963
            totalY += tse.x;
964
#else
965
            totalX += tse.x;
966
            totalY += tse.y;
967
#endif
968
        }
969
    } else {
970
        if (--pen_idle == 0) {
971
            pen_down = false;
972
            waiting_for_pen_down = true;
973
#ifdef KBD_DEBUG
974
            if (dump_info) {
975
                int cur = start_console(0);
976
                diag_printf("going idle\n");
977
                end_console(cur);
978
            }
979
#endif
980
        }
981
        return false;
982
    }
983
#ifdef KBD_DEBUG
984
    if (dump_info) {
985
        int cur = start_console(0);
986
        diag_printf("pen: %d, waiting: %d, total: %d\n", pen_down, waiting_for_pen_down, total_events);
987
        end_console(cur);
988
    }
989
#endif
990
    if (total_events == MIN_KBD_EVENTS) {
991
        // If pen just went up then see if this was a valid
992
        // character (inside the keyboard picture, etc)
993
        int x = totalX/total_events;
994
        int y = totalY/total_events;
995
        int row, col;
996
        int char_width, char_height;
997
        unsigned char kbd_ch;
998
#ifdef KBD_DEBUG
999
        if (dump_info) {
1000
            int cur = start_console(0);
1001
            diag_printf("Pen[%d] at %d/%d\n", total_events, x, y);
1002
            end_console(cur);
1003
        }
1004
#endif
1005
        // Try and determine row/col in our keyboard matrix
1006
        if (inside(x, minX, maxX) && inside(y, minY, maxY)) {
1007
            // Point seems to be with the matrix
1008
            char_width = abs(minX - maxX) / 11;
1009
            char_height = abs(minY - maxY) / 4;
1010
            col = abs(x-maxX) / char_width;
1011
            row = abs(y-minY) / char_height;
1012
            kbd_ch = (*cur_kbd_map)[row][col];
1013
#ifdef KBD_DEBUG
1014
            if (dump_info) {
1015
                int cur = start_console(0);
1016
                diag_printf("Row/Col = %d/%d = %x\n", row, col, kbd_ch);
1017
                end_console(cur);
1018
            }
1019
#endif
1020
            switch (kbd_ch) {
1021
            case CODE_SHIFT:
1022
                if (cur_kbd_map == &kbd_shift_map) {
1023
                    cur_kbd_map = &kbd_norm_map;
1024
                    lcd_kbd(LCD_KBD_NORM);
1025
                } else {
1026
                    cur_kbd_map = &kbd_shift_map;
1027
                    lcd_kbd(LCD_KBD_SHIFT);
1028
                }
1029
                break;
1030
            case CODE_CTRL:
1031
                if (cur_kbd_map == &kbd_ctrl_map) {
1032
                    cur_kbd_map = &kbd_norm_map;
1033
                    lcd_kbd(LCD_KBD_NORM);
1034
                } else {
1035
                    cur_kbd_map = &kbd_ctrl_map;
1036
                    lcd_kbd(LCD_KBD_CTRL);
1037
                }
1038
                break;
1039
            case CODE_NUM:
1040
                if (cur_kbd_map == &kbd_num_map) {
1041
                    cur_kbd_map = &kbd_norm_map;
1042
                    lcd_kbd(LCD_KBD_NORM);
1043
                } else {
1044
                    cur_kbd_map = &kbd_num_map;
1045
                    lcd_kbd(LCD_KBD_NUM);
1046
                }
1047
                break;
1048
            case CODE_NONE:
1049
                break;
1050
            default:
1051
                *ch = kbd_ch;
1052
                return true;
1053
            }
1054
        }
1055
    }
1056
    return false;
1057
}
1058
 
1059
static cyg_uint8
1060
lcd_comm_getc(void* __ch_data)
1061
{
1062
    cyg_uint8 ch;
1063
 
1064
    while (!lcd_comm_getc_nonblock(__ch_data, &ch)) ;
1065
    return ch;
1066
}
1067
 
1068
static void
1069
lcd_comm_putc(void* __ch_data, cyg_uint8 c)
1070
{
1071
    lcd_putc(c);
1072
}
1073
 
1074
static void
1075
lcd_comm_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
1076
{
1077
#if 0
1078
    CYGARC_HAL_SAVE_GP();
1079
 
1080
    while(__len-- > 0)
1081
        lcd_comm_putc(__ch_data, *__buf++);
1082
 
1083
    CYGARC_HAL_RESTORE_GP();
1084
#endif
1085
}
1086
 
1087
static void
1088
lcd_comm_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
1089
{
1090
#if 0
1091
    CYGARC_HAL_SAVE_GP();
1092
 
1093
    while(__len-- > 0)
1094
        *__buf++ = lcd_comm_getc(__ch_data);
1095
 
1096
    CYGARC_HAL_RESTORE_GP();
1097
#endif
1098
}
1099
 
1100
static cyg_bool
1101
lcd_comm_getc_timeout(void* __ch_data, cyg_uint8* ch)
1102
{
1103
    int delay_count;
1104
    cyg_bool res;
1105
 
1106
    delay_count = _timeout * 10; // delay in .1 ms steps
1107
    for(;;) {
1108
        res = lcd_comm_getc_nonblock(__ch_data, ch);
1109
        if (res || 0 == delay_count--)
1110
            break;
1111
        CYGACC_CALL_IF_DELAY_US(100);
1112
    }
1113
    return res;
1114
}
1115
 
1116
static int
1117
lcd_comm_control(void *__ch_data, __comm_control_cmd_t __func, ...)
1118
{
1119
    static int vector = 0;
1120
    int ret = -1;
1121
    static int irq_state = 0;
1122
 
1123
    CYGARC_HAL_SAVE_GP();
1124
 
1125
    switch (__func) {
1126
    case __COMMCTL_IRQ_ENABLE:
1127
        ret = irq_state;
1128
        irq_state = 1;
1129
#if 0
1130
        if (vector == 0) {
1131
            vector = eth_drv_int_vector();
1132
        }
1133
        HAL_INTERRUPT_UNMASK(vector);
1134
#endif
1135
        break;
1136
    case __COMMCTL_IRQ_DISABLE:
1137
        ret = irq_state;
1138
        irq_state = 0;
1139
#if 0
1140
        HAL_INTERRUPT_MASK(vector);
1141
#endif
1142
        break;
1143
    case __COMMCTL_DBG_ISR_VECTOR:
1144
        ret = vector;
1145
        break;
1146
    case __COMMCTL_SET_TIMEOUT:
1147
    {
1148
        va_list ap;
1149
 
1150
        va_start(ap, __func);
1151
 
1152
        ret = _timeout;
1153
        _timeout = va_arg(ap, cyg_uint32);
1154
 
1155
        va_end(ap);
1156
        break;
1157
    }
1158
    case __COMMCTL_FLUSH_OUTPUT:
1159
    case __COMMCTL_GETBAUD:
1160
    case __COMMCTL_SETBAUD:
1161
        ret = 0;
1162
        break;
1163
    default:
1164
        break;
1165
    }
1166
    CYGARC_HAL_RESTORE_GP();
1167
    return ret;
1168
}
1169
 
1170
static int
1171
lcd_comm_isr(void *__ch_data, int* __ctrlc,
1172
           CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
1173
{
1174
#if 0
1175
    char ch;
1176
 
1177
    cyg_drv_interrupt_acknowledge(__vector);
1178
    *__ctrlc = 0;
1179
    if (lcd_comm_getc_nonblock(__ch_data, &ch)) {
1180
        if (ch == 0x03) {
1181
            *__ctrlc = 1;
1182
        }
1183
    }
1184
    return CYG_ISR_HANDLED;
1185
#endif
1186
    return 0;
1187
}
1188
 
1189
static bool
1190
init_kbd_coord(int indx, char *prompt_char)
1191
{
1192
    char prompt[] = "Press %s on kbd graphic";
1193
    int off = ((VISIBLE_SCREEN_WIDTH-sizeof(prompt))/2)-1;
1194
    int off2 = ((VISIBLE_SCREEN_WIDTH-20)/2)-1;
1195
    struct ts_event tse;
1196
    struct key_event ke;
1197
    bool pen_down;
1198
    int i, down_timer, total_events;
1199
    int timeout = 100000;
1200
    unsigned long totalX, totalY;
1201
 
1202
    lcd_moveto(off, screen_height/2);
1203
    lcd_printf(prompt, prompt_char);
1204
    lcd_moveto(off2, (screen_height/2)+2);
1205
    lcd_printf("Keep pen down until");
1206
    lcd_moveto(off2, (screen_height/2)+3);
1207
    lcd_printf("message disappears");
1208
    pen_down = false;
1209
    down_timer = 0;
1210
    total_events = 0;
1211
    totalX = totalY = 0;
1212
    // Wait for a pen-down event
1213
    while (!pen_down) {
1214
        if (ts_get_event(&tse)) {
1215
            if (!tse.up) {
1216
                pen_down = true;
1217
            }
1218
        }
1219
        if (key_get_event(&ke)) {
1220
            if (ke.button_info == (ATMEL_BUTTON_STATE_UP|ATMEL_BUTTON_RETURN)) {
1221
                return true;
1222
            }
1223
        }
1224
        if (--timeout == 0) {
1225
            // Give up if the guy hasn't pressed anything
1226
            return true;
1227
        }
1228
    }
1229
    // Now accumulate data 
1230
    // Assumption: the Atmel can send at most 3 position reports
1231
    // per millisecond.  We should wait for 50ms before moving on
1232
    while (total_events < 100) {
1233
        if (ts_get_event(&tse)) {
1234
            if (tse.up) {
1235
                pen_down = false;
1236
                continue;
1237
            } else {
1238
#ifdef PORTRAIT_MODE
1239
                totalX += tse.y;
1240
                totalY += tse.x;
1241
#else
1242
                totalX += tse.x;
1243
                totalY += tse.y;
1244
#endif
1245
                total_events++;
1246
                pen_down = true;
1247
            }
1248
        }
1249
        if (key_get_event(&ke)) {
1250
            if (ke.button_info == (ATMEL_BUTTON_STATE_UP|ATMEL_BUTTON_RETURN)) {
1251
                return true;
1252
            }
1253
        }
1254
    }
1255
    // Tell the guy we have enough data
1256
    lcd_moveto(off, screen_height/2);
1257
    for (i = 0;  i < screen_width;  i++) {
1258
        lcd_putc(' ');
1259
    }
1260
    // Now wait for the pen to go back up
1261
    while (pen_down) {
1262
        if (ts_get_event(&tse)) {
1263
            if (tse.up) {
1264
                pen_down = false;
1265
            }
1266
        }
1267
        if (key_get_event(&ke)) {
1268
            if (ke.button_info == (ATMEL_BUTTON_STATE_UP|ATMEL_BUTTON_RETURN)) {
1269
                return true;
1270
            }
1271
        }
1272
    }
1273
    kbd_limits[indx].x = totalX / total_events;
1274
    kbd_limits[indx].y = totalY / total_events;
1275
    return false;
1276
}
1277
 
1278
static bool
1279
close(int c1, int c2)
1280
{
1281
    int diff = c1 - c2;
1282
    if (diff < 0) diff = -diff;
1283
    return (diff < 50);
1284
}
1285
 
1286
#define LCD_COMM_CHANNEL 1  // Logical I/O channel used for LCD/TS console
1287
 
1288
void
1289
lcd_comm_init(void)
1290
{
1291
    static int init = 0;
1292
    bool need_params = true;
1293
    unsigned short cksum, param;
1294
    int i;
1295
 
1296
    if (!init) {
1297
        hal_virtual_comm_table_t* comm;
1298
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
1299
 
1300
        // Setup procs in the vector table
1301
        CYGACC_CALL_IF_SET_CONSOLE_COMM(LCD_COMM_CHANNEL);
1302
        comm = CYGACC_CALL_IF_CONSOLE_PROCS();
1303
        //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
1304
        CYGACC_COMM_IF_WRITE_SET(*comm, lcd_comm_write);
1305
        CYGACC_COMM_IF_READ_SET(*comm, lcd_comm_read);
1306
        CYGACC_COMM_IF_PUTC_SET(*comm, lcd_comm_putc);
1307
        CYGACC_COMM_IF_GETC_SET(*comm, lcd_comm_getc);
1308
        CYGACC_COMM_IF_CONTROL_SET(*comm, lcd_comm_control);
1309
        CYGACC_COMM_IF_DBG_ISR_SET(*comm, lcd_comm_isr);
1310
        CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, lcd_comm_getc_timeout);
1311
 
1312
        // Restore original console
1313
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
1314
 
1315
        init = 1;
1316
 
1317
        // Pick up parameters for virtual keyboard from RAM
1318
        cksum = (unsigned short)&_ipaq_LCD_params[0];
1319
        for (i = 0;  i < 4;  i++) {
1320
            param = _ipaq_LCD_params[i*2];
1321
            kbd_limits[i].x = param;
1322
            cksum ^= param;
1323
            param = _ipaq_LCD_params[(i*2)+1];
1324
            kbd_limits[i].y = param;
1325
            cksum ^= param;
1326
        }
1327
        need_params = cksum != _ipaq_LCD_params[(4*2)+1];
1328
 
1329
        // If the data are currently bad, set up some defaults
1330
        if (need_params) {
1331
            kbd_limits[CS_UL].x = 994;
1332
            kbd_limits[CS_UL].y = 710;
1333
            kbd_limits[CS_UR].x = 413;
1334
            kbd_limits[CS_UR].y = 710;
1335
            kbd_limits[CS_LL].x = 989;
1336
            kbd_limits[CS_LL].y = 839;
1337
            kbd_limits[CS_LR].x = 411;
1338
            kbd_limits[CS_LR].y = 836;
1339
        }
1340
 
1341
        if (!need_params) {
1342
            // See if the guy wants to force new parameters
1343
            lcd_clear();
1344
            lcd_moveto(5, screen_height/2);
1345
            lcd_printf("Calibrate touch screen?\n");
1346
            lcd_moveto(5, (screen_height/2)+1);
1347
            for (i = 0;  i < 10;  i++) {
1348
                struct key_event ke;
1349
                if (key_get_event(&ke) && ((ke.button_info & ATMEL_BUTTON_STATE) == ATMEL_BUTTON_STATE_UP)) {
1350
                    need_params = (ke.button_info & ATMEL_BUTTON_VALUE) != ATMEL_BUTTON_RETURN;
1351
                    break;
1352
                }
1353
                CYGACC_CALL_IF_DELAY_US(50000);
1354
                lcd_putc('.');
1355
            }
1356
        }
1357
 
1358
        while (need_params) {
1359
            cursor_enable = false;
1360
            lcd_clear();
1361
            lcd_kbd(LCD_KBD_NORM);
1362
            if (init_kbd_coord(CS_UL, "'q'")) {
1363
                goto no_kbd;
1364
            }
1365
            if (init_kbd_coord(CS_UR, "BS ")) {
1366
                goto no_kbd;
1367
            }
1368
            if (init_kbd_coord(CS_LL, "SHIFT")) {
1369
                goto no_kbd;
1370
            }
1371
            if (init_kbd_coord(CS_LR, "'/'  ")) {
1372
                goto no_kbd;
1373
            }
1374
            cursor_enable = true;
1375
            if (close(kbd_limits[CS_UL].x, kbd_limits[CS_LL].x) &&
1376
                close(kbd_limits[CS_UR].x, kbd_limits[CS_LR].x) &&
1377
                close(kbd_limits[CS_UL].y, kbd_limits[CS_UR].y) &&
1378
                close(kbd_limits[CS_LL].y, kbd_limits[CS_LR].y)) {
1379
                // Save values so we don't need to repeat this
1380
                cksum = (unsigned short)&_ipaq_LCD_params[0];
1381
                for (i = 0;  i < 4;  i++) {
1382
                    param = kbd_limits[i].x;
1383
                    cksum ^= param;
1384
                    _ipaq_LCD_params[i*2] = param;
1385
                    param = kbd_limits[i].y;
1386
                    cksum ^= param;
1387
                    _ipaq_LCD_params[(i*2)+1] = param;
1388
                }
1389
                _ipaq_LCD_params[(4*2)+1] = cksum;
1390
                break;
1391
            }
1392
        }
1393
 
1394
    no_kbd:
1395
        // Munge the limits to allow for some slop
1396
        if (kbd_limits[CS_UL].x < kbd_limits[CS_UR].x) {
1397
            minX = min(kbd_limits[CS_UL].x, kbd_limits[CS_LL].x) - KBD_FUZZ;
1398
            maxX = max(kbd_limits[CS_UR].x, kbd_limits[CS_LR].x) + KBD_FUZZ;
1399
        } else {
1400
            minX = min(kbd_limits[CS_UR].x, kbd_limits[CS_LR].x) - KBD_FUZZ;
1401
            maxX = max(kbd_limits[CS_UL].x, kbd_limits[CS_LL].x) + KBD_FUZZ;
1402
        }
1403
        if (kbd_limits[CS_UL].y < kbd_limits[CS_LL].y) {
1404
            minY = min(kbd_limits[CS_UL].y, kbd_limits[CS_UR].y) - KBD_FUZZ;
1405
            maxY = max(kbd_limits[CS_LL].y, kbd_limits[CS_LR].y) + KBD_FUZZ;
1406
        } else {
1407
            minY = min(kbd_limits[CS_LR].y, kbd_limits[CS_LL].y) - KBD_FUZZ;
1408
            maxY = max(kbd_limits[CS_UL].y, kbd_limits[CS_UR].y) + KBD_FUZZ;
1409
        }
1410
        cursor_enable = true;
1411
        lcd_clear();
1412
        if (kbd_active) {
1413
            lcd_kbd(LCD_KBD_NORM);
1414
        }
1415
#if 0
1416
        diag_printf("KBD Limits[] = %d/%d, %d/%d, %d/%d, %d/%d\n",
1417
                    kbd_limits[CS_UL].x, kbd_limits[CS_UL].y,
1418
                    kbd_limits[CS_UR].x, kbd_limits[CS_UR].y,
1419
                    kbd_limits[CS_LL].x, kbd_limits[CS_LL].y,
1420
                    kbd_limits[CS_LR].x, kbd_limits[CS_LR].y);
1421
        diag_printf("KBD in %d/%d .. %d/%d\n", minX, minY, maxX, maxY);
1422
        diag_printf("screen %d x %d\n", screen_height, screen_width);
1423
#endif
1424
    }
1425
}
1426
 
1427
// Control state of LCD display - only called by logical I/O layers
1428
 
1429
void
1430
lcd_on(bool enable)
1431
{
1432
    static bool enabled = true;
1433
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
1434
 
1435
    if (cur != LCD_COMM_CHANNEL)
1436
        enable = false;  // Only enable display if LCD is the active "console"
1437
    if (enable) {
1438
        if (!enabled) {
1439
            ipaq_EGPIO(SA1110_EIO_LCD_3V3|SA1110_EIO_LCD_CTRL|SA1110_EIO_LCD_5V|SA1110_EIO_LCD_VDD,
1440
                       SA1110_EIO_LCD_3V3_ON|SA1110_EIO_LCD_CTRL_ON|SA1110_EIO_LCD_5V_ON|SA1110_EIO_LCD_VDD_ON);
1441
            lcd_brightness(_lcd_brightness);
1442
        }
1443
        enabled = true;
1444
    } else {
1445
        if (enabled) {
1446
            lcd_brightness(0);
1447
            ipaq_EGPIO(SA1110_EIO_LCD_3V3|SA1110_EIO_LCD_CTRL|SA1110_EIO_LCD_5V|SA1110_EIO_LCD_VDD,
1448
                       SA1110_EIO_LCD_3V3_OFF|SA1110_EIO_LCD_CTRL_OFF|SA1110_EIO_LCD_5V_OFF|SA1110_EIO_LCD_VDD_OFF);
1449
        }
1450
        enabled = false;
1451
    }
1452
}
1453
#endif

powered by: WebSVN 2.1.0

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