📄 lcd_support.c
字号:
pen_down = false;
waiting_for_pen_down = true;
#ifdef KBD_DEBUG
if (dump_info) {
int cur = start_console(0);
diag_printf("going idle\n");
end_console(cur);
}
#endif
}
return false;
}
#ifdef KBD_DEBUG
if (dump_info) {
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);
}
#endif
if (total_events == MIN_KBD_EVENTS) {
// If pen just went up then see if this was a valid
// character (inside the keyboard picture, etc)
int x = totalX/total_events;
int y = totalY/total_events;
int row, col;
int char_width, char_height;
unsigned char kbd_ch;
#ifdef KBD_DEBUG
if (dump_info) {
int cur = start_console(0);
diag_printf("Pen[%d] at %d/%d\n", total_events, x, y);
end_console(cur);
}
#endif
// Try and determine row/col in our keyboard matrix
if (inside(x, minX, maxX) && inside(y, minY, maxY)) {
// Point seems to be with the matrix
char_width = abs(minX - maxX) / 11;
char_height = abs(minY - maxY) / 4;
col = abs(x-maxX) / char_width;
row = abs(y-minY) / char_height;
kbd_ch = (*cur_kbd_map)[row][col];
#ifdef KBD_DEBUG
if (dump_info) {
int cur = start_console(0);
diag_printf("Row/Col = %d/%d = %x\n", row, col, kbd_ch);
end_console(cur);
}
#endif
switch (kbd_ch) {
case CODE_SHIFT:
if (cur_kbd_map == &kbd_shift_map) {
cur_kbd_map = &kbd_norm_map;
lcd_kbd(LCD_KBD_NORM);
} else {
cur_kbd_map = &kbd_shift_map;
lcd_kbd(LCD_KBD_SHIFT);
}
break;
case CODE_CTRL:
if (cur_kbd_map == &kbd_ctrl_map) {
cur_kbd_map = &kbd_norm_map;
lcd_kbd(LCD_KBD_NORM);
} else {
cur_kbd_map = &kbd_ctrl_map;
lcd_kbd(LCD_KBD_CTRL);
}
break;
case CODE_NUM:
if (cur_kbd_map == &kbd_num_map) {
cur_kbd_map = &kbd_norm_map;
lcd_kbd(LCD_KBD_NORM);
} else {
cur_kbd_map = &kbd_num_map;
lcd_kbd(LCD_KBD_NUM);
}
break;
case CODE_NONE:
break;
default:
*ch = kbd_ch;
return true;
}
}
}
return false;
}
static cyg_uint8
lcd_comm_getc(void* __ch_data)
{
cyg_uint8 ch;
while (!lcd_comm_getc_nonblock(__ch_data, &ch)) ;
return ch;
}
static void
lcd_comm_putc(void* __ch_data, cyg_uint8 c)
{
lcd_putc(c);
}
static void
lcd_comm_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
{
#if 0
CYGARC_HAL_SAVE_GP();
while(__len-- > 0)
lcd_comm_putc(__ch_data, *__buf++);
CYGARC_HAL_RESTORE_GP();
#endif
}
static void
lcd_comm_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
{
#if 0
CYGARC_HAL_SAVE_GP();
while(__len-- > 0)
*__buf++ = lcd_comm_getc(__ch_data);
CYGARC_HAL_RESTORE_GP();
#endif
}
static cyg_bool
lcd_comm_getc_timeout(void* __ch_data, cyg_uint8* ch)
{
int delay_count;
cyg_bool res;
delay_count = _timeout * 10; // delay in .1 ms steps
for(;;) {
res = lcd_comm_getc_nonblock(__ch_data, ch);
if (res || 0 == delay_count--)
break;
CYGACC_CALL_IF_DELAY_US(100);
}
return res;
}
static int
lcd_comm_control(void *__ch_data, __comm_control_cmd_t __func, ...)
{
static int vector = 0;
int ret = -1;
static int irq_state = 0;
CYGARC_HAL_SAVE_GP();
switch (__func) {
case __COMMCTL_IRQ_ENABLE:
ret = irq_state;
irq_state = 1;
#if 0
if (vector == 0) {
vector = eth_drv_int_vector();
}
HAL_INTERRUPT_UNMASK(vector);
#endif
break;
case __COMMCTL_IRQ_DISABLE:
ret = irq_state;
irq_state = 0;
#if 0
HAL_INTERRUPT_MASK(vector);
#endif
break;
case __COMMCTL_DBG_ISR_VECTOR:
ret = vector;
break;
case __COMMCTL_SET_TIMEOUT:
{
va_list ap;
va_start(ap, __func);
ret = _timeout;
_timeout = va_arg(ap, cyg_uint32);
va_end(ap);
break;
}
case __COMMCTL_FLUSH_OUTPUT:
case __COMMCTL_GETBAUD:
case __COMMCTL_SETBAUD:
ret = 0;
break;
default:
break;
}
CYGARC_HAL_RESTORE_GP();
return ret;
}
static int
lcd_comm_isr(void *__ch_data, int* __ctrlc,
CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
{
#if 0
char ch;
cyg_drv_interrupt_acknowledge(__vector);
*__ctrlc = 0;
if (lcd_comm_getc_nonblock(__ch_data, &ch)) {
if (ch == 0x03) {
*__ctrlc = 1;
}
}
return CYG_ISR_HANDLED;
#endif
return 0;
}
static bool
init_kbd_coord(int indx, char *prompt_char)
{
char prompt[] = "Press %s on kbd graphic";
int off = ((VISIBLE_SCREEN_WIDTH-sizeof(prompt))/2)-1;
int off2 = ((VISIBLE_SCREEN_WIDTH-20)/2)-1;
struct ts_event tse;
struct key_event ke;
bool pen_down;
int i, down_timer, total_events;
int timeout = 100000;
unsigned long totalX, totalY;
lcd_moveto(off, screen_height/2);
lcd_printf(prompt, prompt_char);
lcd_moveto(off2, (screen_height/2)+2);
lcd_printf("Keep pen down until");
lcd_moveto(off2, (screen_height/2)+3);
lcd_printf("message disappears");
pen_down = false;
down_timer = 0;
total_events = 0;
totalX = totalY = 0;
// Wait for a pen-down event
while (!pen_down) {
if (ts_get_event(&tse)) {
if (!tse.up) {
pen_down = true;
}
}
if (key_get_event(&ke)) {
if (ke.button_info == (ATMEL_BUTTON_STATE_UP|ATMEL_BUTTON_RETURN)) {
return true;
}
}
if (--timeout == 0) {
// Give up if the guy hasn't pressed anything
return true;
}
}
// Now accumulate data
// Assumption: the Atmel can send at most 3 position reports
// per millisecond. We should wait for 50ms before moving on
while (total_events < 100) {
if (ts_get_event(&tse)) {
if (tse.up) {
pen_down = false;
continue;
} else {
#ifdef PORTRAIT_MODE
totalX += tse.y;
totalY += tse.x;
#else
totalX += tse.x;
totalY += tse.y;
#endif
total_events++;
pen_down = true;
}
}
if (key_get_event(&ke)) {
if (ke.button_info == (ATMEL_BUTTON_STATE_UP|ATMEL_BUTTON_RETURN)) {
return true;
}
}
}
// Tell the guy we have enough data
lcd_moveto(off, screen_height/2);
for (i = 0; i < screen_width; i++) {
lcd_putc(' ');
}
// Now wait for the pen to go back up
while (pen_down) {
if (ts_get_event(&tse)) {
if (tse.up) {
pen_down = false;
}
}
if (key_get_event(&ke)) {
if (ke.button_info == (ATMEL_BUTTON_STATE_UP|ATMEL_BUTTON_RETURN)) {
return true;
}
}
}
kbd_limits[indx].x = totalX / total_events;
kbd_limits[indx].y = totalY / total_events;
return false;
}
static bool
close(int c1, int c2)
{
int diff = c1 - c2;
if (diff < 0) diff = -diff;
return (diff < 50);
}
#define LCD_COMM_CHANNEL 1 // Logical I/O channel used for LCD/TS console
void
lcd_comm_init(void)
{
static int init = 0;
bool need_params = true;
unsigned short cksum, param;
int i;
if (!init) {
hal_virtual_comm_table_t* comm;
int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
// Setup procs in the vector table
CYGACC_CALL_IF_SET_CONSOLE_COMM(LCD_COMM_CHANNEL);
comm = CYGACC_CALL_IF_CONSOLE_PROCS();
//CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
CYGACC_COMM_IF_WRITE_SET(*comm, lcd_comm_write);
CYGACC_COMM_IF_READ_SET(*comm, lcd_comm_read);
CYGACC_COMM_IF_PUTC_SET(*comm, lcd_comm_putc);
CYGACC_COMM_IF_GETC_SET(*comm, lcd_comm_getc);
CYGACC_COMM_IF_CONTROL_SET(*comm, lcd_comm_control);
CYGACC_COMM_IF_DBG_ISR_SET(*comm, lcd_comm_isr);
CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, lcd_comm_getc_timeout);
// Restore original console
CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
init = 1;
// Pick up parameters for virtual keyboard from RAM
cksum = (unsigned short)&_ipaq_LCD_params[0];
for (i = 0; i < 4; i++) {
param = _ipaq_LCD_params[i*2];
kbd_limits[i].x = param;
cksum ^= param;
param = _ipaq_LCD_params[(i*2)+1];
kbd_limits[i].y = param;
cksum ^= param;
}
need_params = cksum != _ipaq_LCD_params[(4*2)+1];
// If the data are currently bad, set up some defaults
if (need_params) {
kbd_limits[CS_UL].x = 994;
kbd_limits[CS_UL].y = 710;
kbd_limits[CS_UR].x = 413;
kbd_limits[CS_UR].y = 710;
kbd_limits[CS_LL].x = 989;
kbd_limits[CS_LL].y = 839;
kbd_limits[CS_LR].x = 411;
kbd_limits[CS_LR].y = 836;
}
if (!need_params) {
// See if the guy wants to force new parameters
lcd_clear();
lcd_moveto(5, screen_height/2);
lcd_printf("Calibrate touch screen?\n");
lcd_moveto(5, (screen_height/2)+1);
for (i = 0; i < 10; i++) {
struct key_event ke;
if (key_get_event(&ke) && ((ke.button_info & ATMEL_BUTTON_STATE) == ATMEL_BUTTON_STATE_UP)) {
need_params = (ke.button_info & ATMEL_BUTTON_VALUE) != ATMEL_BUTTON_RETURN;
break;
}
CYGACC_CALL_IF_DELAY_US(50000);
lcd_putc('.');
}
}
while (need_params) {
cursor_enable = false;
lcd_clear();
lcd_kbd(LCD_KBD_NORM);
if (init_kbd_coord(CS_UL, "'q'")) {
goto no_kbd;
}
if (init_kbd_coord(CS_UR, "BS ")) {
goto no_kbd;
}
if (init_kbd_coord(CS_LL, "SHIFT")) {
goto no_kbd;
}
if (init_kbd_coord(CS_LR, "'/' ")) {
goto no_kbd;
}
cursor_enable = true;
if (close(kbd_limits[CS_UL].x, kbd_limits[CS_LL].x) &&
close(kbd_limits[CS_UR].x, kbd_limits[CS_LR].x) &&
close(kbd_limits[CS_UL].y, kbd_limits[CS_UR].y) &&
close(kbd_limits[CS_LL].y, kbd_limits[CS_LR].y)) {
// Save values so we don't need to repeat this
cksum = (unsigned short)&_ipaq_LCD_params[0];
for (i = 0; i < 4; i++) {
param = kbd_limits[i].x;
cksum ^= param;
_ipaq_LCD_params[i*2] = param;
param = kbd_limits[i].y;
cksum ^= param;
_ipaq_LCD_params[(i*2)+1] = param;
}
_ipaq_LCD_params[(4*2)+1] = cksum;
break;
}
}
no_kbd:
// Munge the limits to allow for some slop
if (kbd_limits[CS_UL].x < kbd_limits[CS_UR].x) {
minX = min(kbd_limits[CS_UL].x, kbd_limits[CS_LL].x) - KBD_FUZZ;
maxX = max(kbd_limits[CS_UR].x, kbd_limits[CS_LR].x) + KBD_FUZZ;
} else {
minX = min(kbd_limits[CS_UR].x, kbd_limits[CS_LR].x) - KBD_FUZZ;
maxX = max(kbd_limits[CS_UL].x, kbd_limits[CS_LL].x) + KBD_FUZZ;
}
if (kbd_limits[CS_UL].y < kbd_limits[CS_LL].y) {
minY = min(kbd_limits[CS_UL].y, kbd_limits[CS_UR].y) - KBD_FUZZ;
maxY = max(kbd_limits[CS_LL].y, kbd_limits[CS_LR].y) + KBD_FUZZ;
} else {
minY = min(kbd_limits[CS_LR].y, kbd_limits[CS_LL].y) - KBD_FUZZ;
maxY = max(kbd_limits[CS_UL].y, kbd_limits[CS_UR].y) + KBD_FUZZ;
}
cursor_enable = true;
lcd_clear();
if (kbd_active) {
lcd_kbd(LCD_KBD_NORM);
}
#if 0
diag_printf("KBD Limits[] = %d/%d, %d/%d, %d/%d, %d/%d\n",
kbd_limits[CS_UL].x, kbd_limits[CS_UL].y,
kbd_limits[CS_UR].x, kbd_limits[CS_UR].y,
kbd_limits[CS_LL].x, kbd_limits[CS_LL].y,
kbd_limits[CS_LR].x, kbd_limits[CS_LR].y);
diag_printf("KBD in %d/%d .. %d/%d\n", minX, minY, maxX, maxY);
diag_printf("screen %d x %d\n", screen_height, screen_width);
#endif
}
}
// Control state of LCD display - only called by logical I/O layers
void
lcd_on(bool enable)
{
static bool enabled = true;
int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
if (cur != LCD_COMM_CHANNEL)
enable = false; // Only enable display if LCD is the active "console"
if (enable) {
if (!enabled) {
ipaq_EGPIO(SA1110_EIO_LCD_3V3|SA1110_EIO_LCD_CTRL|SA1110_EIO_LCD_5V|SA1110_EIO_LCD_VDD,
SA1110_EIO_LCD_3V3_ON|SA1110_EIO_LCD_CTRL_ON|SA1110_EIO_LCD_5V_ON|SA1110_EIO_LCD_VDD_ON);
lcd_brightness(_lcd_brightness);
}
enabled = true;
} else {
if (enabled) {
lcd_brightness(0);
ipaq_EGPIO(SA1110_EIO_LCD_3V3|SA1110_EIO_LCD_CTRL|SA1110_EIO_LCD_5V|SA1110_EIO_LCD_VDD,
SA1110_EIO_LCD_3V3_OFF|SA1110_EIO_LCD_CTRL_OFF|SA1110_EIO_LCD_5V_OFF|SA1110_EIO_LCD_VDD_OFF);
}
enabled = false;
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -