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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [hal/] [arm/] [sa11x0/] [ipaq/] [v2_0/] [src/] [lcd_support.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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