📄 lcd_support.c
字号:
}
for (row = LCD_HEIGHT-FONT_HEIGHT; row < LCD_HEIGHT; row++) {
p1 = &fp->pixels[row][0];
for (col = 0; col < LCD_WIDTH; col++) {
*p1++ = bg;
}
}
#endif
if (cursor_enable) {
lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
}
}
static void
lcd_scroll(void)
{
int row, col;
cyg_uint8 *c1, *c2;
// First scroll up the virtual screen
for (row = (screen_start+1); row < screen_height; row++) {
c1 = &screen[row-1][0];
c2 = &screen[row][0];
for (col = 0; col < screen_width; col++) {
*c1++ = *c2++;
}
}
c1 = &screen[screen_height-1][0];
for (col = 0; col < screen_width; col++) {
*c1++ = 0x20;
}
lcd_refresh();
}
// Draw one character at the current position
void
lcd_putc(cyg_int8 c)
{
if (cursor_enable) {
lcd_drawc(screen[curY][curX], curX-screen_pan, curY);
}
switch (c) {
case '\r':
curX = 0;
break;
case '\n':
curY++;
break;
case '\b':
curX--;
if (curX < 0) {
curY--;
if (curY < 0) curY = 0;
curX = screen_width-1;
}
break;
default:
if (((cyg_uint8)c < FIRST_CHAR) || ((cyg_uint8)c > LAST_CHAR)) c = '.';
screen[curY][curX] = c;
lcd_drawc(c, curX-screen_pan, curY);
curX++;
if (curX == screen_width) {
curY++;
curX = 0;
}
}
if (curY >= screen_height) {
lcd_scroll();
curY = (screen_height-1);
}
if (cursor_enable) {
lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
}
}
// Basic LCD 'printf()' support
#include <stdarg.h>
#include <string.h>
#define is_digit(c) ((c >= '0') && (c <= '9'))
static int
_cvt(unsigned long val, char *buf, long radix, char *digits)
{
char temp[80];
char *cp = temp;
int length = 0;
if (val == 0) {
/* Special case */
*cp++ = '0';
} else {
while (val) {
*cp++ = digits[val % radix];
val /= radix;
}
}
while (cp != temp) {
*buf++ = *--cp;
length++;
}
*buf = '\0';
return (length);
}
static int
lcd_vprintf(void (*putc)(cyg_int8), const char *fmt0, va_list ap)
{
char c, sign, *cp;
int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
char buf[32];
long val;
while ((c = *fmt0++)) {
cp = buf;
length = 0;
if (c == '%') {
c = *fmt0++;
left_prec = right_prec = pad_on_right = 0;
if (c == '-') {
c = *fmt0++;
pad_on_right++;
}
if (c == '0') {
zero_fill = TRUE;
c = *fmt0++;
} else {
zero_fill = FALSE;
}
while (is_digit(c)) {
left_prec = (left_prec * 10) + (c - '0');
c = *fmt0++;
}
if (c == '.') {
c = *fmt0++;
zero_fill++;
while (is_digit(c)) {
right_prec = (right_prec * 10) + (c - '0');
c = *fmt0++;
}
} else {
right_prec = left_prec;
}
sign = '\0';
switch (c) {
case 'd':
case 'x':
case 'X':
val = va_arg(ap, long);
switch (c) {
case 'd':
if (val < 0) {
sign = '-';
val = -val;
}
length = _cvt(val, buf, 10, "0123456789");
break;
case 'x':
length = _cvt(val, buf, 16, "0123456789abcdef");
break;
case 'X':
length = _cvt(val, buf, 16, "0123456789ABCDEF");
break;
}
break;
case 's':
cp = va_arg(ap, char *);
length = strlen(cp);
break;
case 'c':
c = va_arg(ap, long /*char*/);
(*putc)(c);
continue;
default:
(*putc)('?');
}
pad = left_prec - length;
if (sign != '\0') {
pad--;
}
if (zero_fill) {
c = '0';
if (sign != '\0') {
(*putc)(sign);
sign = '\0';
}
} else {
c = ' ';
}
if (!pad_on_right) {
while (pad-- > 0) {
(*putc)(c);
}
}
if (sign != '\0') {
(*putc)(sign);
}
while (length-- > 0) {
(*putc)(c = *cp++);
if (c == '\n') {
(*putc)('\r');
}
}
if (pad_on_right) {
while (pad-- > 0) {
(*putc)(' ');
}
}
} else {
(*putc)(c);
if (c == '\n') {
(*putc)('\r');
}
}
}
return 0; // Should be length of string written
}
int
lcd_printf(char const *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = lcd_vprintf(lcd_putc, fmt, ap);
va_end(ap);
return (ret);
}
void
lcd_setbg(int red, int green, int blue)
{
bg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
}
void
lcd_setfg(int red, int green, int blue)
{
fg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
}
#ifdef CYGSEM_IPAQ_LCD_COMM
//
// Support LCD/touchscreen as a virtual I/O channel
//
#include "kbd.xpm" // Contains 4 keyboard images
static int _timeout = 500;
struct coord {
short x,y;
};
#ifdef PORTRAIT_MODE
#define CS_UL 1
#define CS_UR 0
#define CS_LL 3
#define CS_LR 2
#else
#define CS_UL 0
#define CS_UR 1
#define CS_LL 2
#define CS_LR 3
#endif
#define KBD_FUZZ 50
static struct coord kbd_limits[4];
static short minX, maxX, minY, maxY; // Coordinates for the keyboard matrix
#define CODE_NONE 0x00
#define CODE_CTRL 0x81
#define CODE_SHIFT 0x82
#define CODE_NUM 0x83
#define CODE_BS 0x08
#define CODE_CR 0x0D
#define CODE_ESC 0x1B
#define CODE_DEL 0x7F
#define CTRL(x) (x&0x1F)
typedef unsigned char kbd_map[4][11];
static kbd_map kbd_norm_map = {
{ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', CODE_BS },
{ 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-', CODE_CR },
{ CODE_CTRL, 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', ';' },
{ CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, '\'', '=', '\\', '/'}
};
static kbd_map kbd_num_map = {
{ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', CODE_BS },
{ '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', CODE_CR },
{ CODE_CTRL, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '`', '~' },
{ CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, '[', ']', '{', '}'}
};
static kbd_map kbd_ctrl_map = {
{ CTRL('q'), CTRL('w'), CTRL('e'), CTRL('r'), CTRL('t'), CTRL('y'),
CTRL('u'), CTRL('i'), CTRL('o'), CTRL('p'), CODE_ESC },
{ CTRL('a'), CTRL('s'), CTRL('d'), CTRL('f'), CTRL('g'), CTRL('h'),
CTRL('j'), CTRL('k'), CTRL('l'), CTRL('_'), CODE_CR },
{ CODE_CTRL, CTRL('z'), CTRL('x'), CTRL('c'), CTRL('v'), CTRL('b'),
CTRL('n'), CTRL('m'), '\\', CTRL(']'), CTRL('^') },
{ CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, ' ', ' ', ' ', CODE_DEL}
};
static kbd_map kbd_shift_map = {
{ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', CODE_BS },
{ 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '_', CODE_CR },
{ CODE_CTRL, 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', ':' },
{ CODE_SHIFT, CODE_SHIFT, ' ', ' ', ' ', ' ', CODE_NUM, '"', '+', '|', '?'}
};
static kbd_map *cur_kbd_map = &kbd_norm_map;
static bool kbd_active = true;
// Pseudo-keyboard indicator
#define LCD_KBD_NORM 0
#define LCD_KBD_SHIFT 1
#define LCD_KBD_NUM 2
#define LCD_KBD_CTRL 3
// Display pseudo keyboard
static void
lcd_kbd(int which)
{
char **kbd_xpm;
switch (which) {
case LCD_KBD_NORM:
kbd_xpm = keynorm_xpm;
break;
case LCD_KBD_SHIFT:
kbd_xpm = keyshft_xpm;
break;
case LCD_KBD_CTRL:
kbd_xpm = keyctrl_xpm;
break;
case LCD_KBD_NUM:
kbd_xpm = keynum_xpm;
break;
default:
return;
}
show_xpm(kbd_xpm, kbd_pos);
}
static bool
inside(int pos, int lim1, int lim2)
{
if (lim1 <= lim2) {
return ((pos >= lim1) && (pos <= lim2));
} else {
return ((pos >= lim2) && (pos <= lim1));
}
}
static int
abs(int x)
{
if (x < 0) {
return -x;
} else {
return x;
}
}
static int
min(int x, int y)
{
if (x < y) {
return x;
} else {
return y;
}
}
static int
max(int x, int y)
{
if (x < y) {
return y;
} else {
return x;
}
}
static cyg_bool
lcd_comm_getc_nonblock(void* __ch_data, cyg_uint8* ch)
{
static bool pen_down = false;
static bool waiting_for_pen_down = true;
static int total_events = 0;
static int pen_idle;
static unsigned long totalX, totalY;
struct ts_event tse;
struct key_event ke;
//#define KBD_DEBUG
#ifdef KBD_DEBUG
static bool dump_info = false;
#endif
#define PEN_IDLE_TIMEOUT 50000
#define MIN_KBD_EVENTS 10
// See if any buttons have been pushed
if (key_get_event(&ke)) {
if ((ke.button_info & ATMEL_BUTTON_STATE) == ATMEL_BUTTON_STATE_UP) {
// diag_printf("Key = %x\n", ke.button_info);
lcd_on(true);
switch (ke.button_info & ATMEL_BUTTON_VALUE) {
case ATMEL_BUTTON_RETURN:
*ch = CTRL('C');
return true;
case ATMEL_BUTTON_JOY_DOWN:
case ATMEL_BUTTON_JOY_UP:
screen_pan = 0;
lcd_refresh();
break;
case ATMEL_BUTTON_JOY_LEFT:
screen_pan -= SCREEN_PAN;
if (screen_pan < 0) screen_pan = 0;
lcd_refresh();
break;
case ATMEL_BUTTON_JOY_RIGHT:
screen_pan += SCREEN_PAN;
if (screen_pan > (SCREEN_WIDTH-SCREEN_PAN)) screen_pan = SCREEN_WIDTH-SCREEN_PAN;
lcd_refresh();
break;
default:
#ifdef KBD_DEBUG
{
int cur = start_console(0);
diag_printf("pen: %d, waiting: %d, total: %d\n", pen_down, waiting_for_pen_down, total_events);
end_console(cur);
dump_info = !dump_info;
}
#endif
return false;
}
}
return false; // Ignore down presses
}
// If keyboard not active, always returns false
if (!kbd_active) {
return false;
}
// Wait for pen down
if (waiting_for_pen_down) {
if (ts_get_event(&tse)) {
lcd_on(true);
if (!tse.up) {
pen_down = true;
waiting_for_pen_down = false;
totalX = totalY = 0;
total_events = 0;
pen_idle = PEN_IDLE_TIMEOUT;
#ifdef KBD_DEBUG
if (dump_info) {
int cur = start_console(0);
diag_printf("start pen: %d, waiting: %d, total: %d\n", pen_down, waiting_for_pen_down, total_events);
end_console(cur);
}
#endif
}
}
return false;
}
// While the pen is down, accumulate some data
if (ts_get_event(&tse)) {
pen_idle = PEN_IDLE_TIMEOUT;
if (tse.up) {
pen_down = false;
waiting_for_pen_down = true;
} else {
total_events++;
pen_down = true;
#ifdef PORTRAIT_MODE
totalX += tse.y;
totalY += tse.x;
#else
totalX += tse.x;
totalY += tse.y;
#endif
}
} else {
if (--pen_idle == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -