📄 phone_console.c
字号:
/* * (C) Copyright 2004 Intracom S.A. * Pantelis Antoniou <panto@intracom.gr> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//* * phone_console.c * * A phone based console * * Virtual display of 80x24 characters. * The actual display is much smaller and panned to show the virtual one. * Input is made by a numeric keypad utilizing the input method of * mobile phones. Sorry no T9 lexicons... * */#include <common.h>#include <version.h>#include <linux/types.h>#include <devices.h>#include <sed156x.h>/*************************************************************************************************/#define ROWS 24#define COLS 80#define REFRESH_HZ (CFG_HZ/50) /* refresh every 20ms */#define BLINK_HZ (CFG_HZ/2) /* cursor blink every 500ms *//*************************************************************************************************/#define DISPLAY_BACKLIT_PORT ((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat#define DISPLAY_BACKLIT_MASK 0x0010/*************************************************************************************************/#define KP_STABLE_HZ (CFG_HZ/100) /* stable for 10ms */#define KP_REPEAT_DELAY_HZ (CFG_HZ/4) /* delay before repeat 250ms */#define KP_REPEAT_HZ (CFG_HZ/20) /* repeat every 50ms */#define KP_FORCE_DELAY_HZ (CFG_HZ/2) /* key was force pressed */#define KP_IDLE_DELAY_HZ (CFG_HZ/2) /* key was released and idle */#if CONFIG_NETPHONE_VERSION == 1#define KP_SPI_RXD_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat)#define KP_SPI_RXD_MASK 0x0008#define KP_SPI_TXD_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat)#define KP_SPI_TXD_MASK 0x0004#define KP_SPI_CLK_PORT (((volatile immap_t *)CFG_IMMR)->im_ioport.iop_pcdat)#define KP_SPI_CLK_MASK 0x0001#elif CONFIG_NETPHONE_VERSION == 2#define KP_SPI_RXD_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat)#define KP_SPI_RXD_MASK 0x00000008#define KP_SPI_TXD_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat)#define KP_SPI_TXD_MASK 0x00000004#define KP_SPI_CLK_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat)#define KP_SPI_CLK_MASK 0x00000002#endif#define KP_CS_PORT (((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pedat)#define KP_CS_MASK 0x00000010#define KP_SPI_RXD() (KP_SPI_RXD_PORT & KP_SPI_RXD_MASK)#define KP_SPI_TXD(x) \ do { \ if (x) \ KP_SPI_TXD_PORT |= KP_SPI_TXD_MASK; \ else \ KP_SPI_TXD_PORT &= ~KP_SPI_TXD_MASK; \ } while(0)#define KP_SPI_CLK(x) \ do { \ if (x) \ KP_SPI_CLK_PORT |= KP_SPI_CLK_MASK; \ else \ KP_SPI_CLK_PORT &= ~KP_SPI_CLK_MASK; \ } while(0)#define KP_SPI_CLK_TOGGLE() (KP_SPI_CLK_PORT ^= KP_SPI_CLK_MASK)#define KP_SPI_BIT_DELAY() /* no delay */#define KP_CS(x) \ do { \ if (x) \ KP_CS_PORT |= KP_CS_MASK; \ else \ KP_CS_PORT &= ~KP_CS_MASK; \ } while(0)#define KP_ROWS 7#define KP_COLS 4#define KP_ROWS_MASK ((1 << KP_ROWS) - 1)#define KP_COLS_MASK ((1 << KP_COLS) - 1)#define SCAN 0#define SCAN_FILTER 1#define SCAN_COL 2#define SCAN_COL_FILTER 3#define PRESSED 4#define KP_F1 0 /* leftmost dot (tab) */#define KP_F2 1 /* middle left dot */#define KP_F3 2 /* up */#define KP_F4 3 /* middle right dot */#define KP_F5 4 /* rightmost dot */#define KP_F6 5 /* C */#define KP_F7 6 /* left */#define KP_F8 7 /* down */#define KP_F9 8 /* right */#define KP_F10 9 /* enter */#define KP_F11 10 /* R */#define KP_F12 11 /* save */#define KP_F13 12 /* redial */#define KP_F14 13 /* speaker */#define KP_F15 14 /* unused */#define KP_F16 15 /* unused */#define KP_RELEASE -1 /* key depressed */#define KP_FORCE -2 /* key was pressed for more than force hz */#define KP_IDLE -3 /* key was released and idle */#define KP_1 '1'#define KP_2 '2'#define KP_3 '3'#define KP_4 '4'#define KP_5 '5'#define KP_6 '6'#define KP_7 '7'#define KP_8 '8'#define KP_9 '9'#define KP_0 '0'#define KP_STAR '*'#define KP_HASH '#'/*************************************************************************************************/static int curs_disabled;static int curs_col, curs_row;static int disp_col, disp_row;static int width, height;/* the simulated vty buffer */static char vty_buf[ROWS * COLS];static char last_visible_buf[ROWS * COLS]; /* worst case */static char *last_visible_curs_ptr;static int last_visible_curs_rev;static int blinked_state;static int last_input_mode;static int refresh_time;static int blink_time;static char last_fast_punct;/*************************************************************************************************/#define IM_SMALL 0#define IM_CAPITAL 1#define IM_NUMBER 2static int input_mode;static char fast_punct;static int tab_indicator;static const char *fast_punct_list = ",.:;*";static const char *input_mode_txt[] = { "abc", "ABC", "123" };static const char *punct = ".,!;?'\"-()@/:_+&%*=<>$[]{}\\~^#|";static const char *whspace = " 0\n";/* per mode character select (for 2-9) */static const char *digits_sel[2][8] = { { /* small */ "abc2", /* 2 */ "def3", /* 3 */ "ghi4", /* 4 */ "jkl5", /* 5 */ "mno6", /* 6 */ "pqrs7", /* 7 */ "tuv8", /* 8 */ "wxyz9", /* 9 */ }, { /* capital */ "ABC2", /* 2 */ "DEF3", /* 3 */ "GHI4", /* 4 */ "JKL5", /* 5 */ "MNO6", /* 6 */ "PQRS7", /* 7 */ "TUV8", /* 8 */ "WXYZ9", /* 9 */ }};/*****************************************************************************/static void update(void);static void ensure_visible(int col, int row, int dx, int dy);static void console_init(void){ curs_disabled = 0; curs_col = 0; curs_row = 0; disp_col = 0; disp_row = 0; input_mode = IM_SMALL; fast_punct = ','; last_fast_punct = '\0'; refresh_time = REFRESH_HZ; blink_time = BLINK_HZ; memset(vty_buf, ' ', sizeof(vty_buf)); memset(last_visible_buf, ' ', sizeof(last_visible_buf)); last_visible_curs_ptr = NULL; last_input_mode = -1; last_visible_curs_rev = 0; blinked_state = 0; sed156x_init(); width = sed156x_text_width; height = sed156x_text_height - 1; tab_indicator = 0;}/*****************************************************************************/void phone_putc(const char c);/*****************************************************************************/static int queued_char = -1;static int enabled = 0;/*****************************************************************************//* flush buffers */int phone_start(void){ console_init(); update(); sed156x_sync(); enabled = 1; queued_char = 'U' - '@'; /* backlit on */ DISPLAY_BACKLIT_PORT &= ~DISPLAY_BACKLIT_MASK; return 0;}int phone_stop(void){ enabled = 0; sed156x_clear(); sed156x_sync(); /* backlit off */ DISPLAY_BACKLIT_PORT |= DISPLAY_BACKLIT_MASK; return 0;}void phone_puts(const char *s){ int count = strlen(s); while (count--) phone_putc(*s++);}int phone_tstc(void){ return queued_char >= 0 ? 1 : 0;}int phone_getc(void){ int r; if (queued_char < 0) return -1; r = queued_char; queued_char = -1; return r;}/*****************************************************************************/int drv_phone_init(void){ device_t console_dev; char *penv; /* * Force console i/o to serial ? */ if ((penv = getenv("console")) != NULL && strcmp(penv, "serial") == 0) return 0; console_init(); memset(&console_dev, 0, sizeof(console_dev)); strcpy(console_dev.name, "phone"); console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */ console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; console_dev.start = phone_start; console_dev.stop = phone_stop; console_dev.putc = phone_putc; /* 'putc' function */ console_dev.puts = phone_puts; /* 'puts' function */ console_dev.tstc = phone_tstc; /* 'tstc' function */ console_dev.getc = phone_getc; /* 'getc' function */ if (device_register(&console_dev) == 0) return 1; return 0;}static int use_me;int drv_phone_use_me(void){ return use_me;}static void kp_do_poll(void);void phone_console_do_poll(void){ int i, x, y; kp_do_poll(); if (enabled) { /* do the blink */ blink_time -= PHONE_CONSOLE_POLL_HZ; if (blink_time <= 0) { blink_time += BLINK_HZ; if (last_visible_curs_ptr) { i = last_visible_curs_ptr - last_visible_buf; x = i % width; y = i / width; sed156x_reverse_at(x, y, 1); last_visible_curs_rev ^= 1; } } /* do the refresh */ refresh_time -= PHONE_CONSOLE_POLL_HZ; if (refresh_time <= 0) { refresh_time += REFRESH_HZ; sed156x_sync(); } }}static int last_scancode = -1;static int forced_scancode = 0;static int input_state = -1;static int input_scancode = -1;static int input_selected_char = -1;static char input_covered_char;static void putchar_at_cursor(char c){ vty_buf[curs_row * COLS + curs_col] = c; ensure_visible(curs_col, curs_row, 1, 1);}static char getchar_at_cursor(void){ return vty_buf[curs_row * COLS + curs_col];}static void queue_input_char(char c){ if (c <= 0) return; queued_char = c;}static void terminate_input(void){ if (input_state < 0) return; if (input_selected_char >= 0) queue_input_char(input_selected_char); input_state = -1; input_selected_char = -1; putchar_at_cursor(input_covered_char); curs_disabled = 0; blink_time = BLINK_HZ; update();}static void handle_enabled_scancode(int scancode){ char c; int new_disp_col, new_disp_row; const char *sel; switch (scancode) { /* key was released */ case KP_RELEASE: forced_scancode = 0; break; /* key was forced */ case KP_FORCE: switch (last_scancode) { case '#': if (input_mode == IM_NUMBER) { input_mode = IM_CAPITAL; /* queue backspace to erase # */ queue_input_char('\b'); } else { input_mode = IM_NUMBER; fast_punct = '*'; } update(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (input_state < 0) break; input_selected_char = last_scancode; putchar_at_cursor((char)input_selected_char); terminate_input(); break; default: break; } break; /* release and idle */ case KP_IDLE: input_scancode = -1; if (input_state < 0) break; terminate_input(); break; /* change input mode */ case '#': if (last_scancode == '#') /* no repeat */ break; if (input_mode == IM_NUMBER) { input_scancode = scancode; input_state = 0; input_selected_char = scancode; input_covered_char = getchar_at_cursor(); putchar_at_cursor((char)input_selected_char); terminate_input(); break; } if (input_mode == IM_SMALL) input_mode = IM_CAPITAL; else input_mode = IM_SMALL; update(); break; case '*': /* no repeat */ if (last_scancode == scancode) break; if (input_state >= 0) terminate_input(); input_scancode = fast_punct; input_state = 0; input_selected_char = input_scancode; input_covered_char = getchar_at_cursor(); putchar_at_cursor((char)input_selected_char); terminate_input(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* no repeat */ if (last_scancode == scancode) break; if (input_mode == IM_NUMBER) { input_scancode = scancode; input_state = 0; input_selected_char = scancode; input_covered_char = getchar_at_cursor(); putchar_at_cursor((char)input_selected_char); terminate_input(); break; } if (input_state >= 0 && input_scancode != scancode) terminate_input(); if (input_state < 0) { curs_disabled = 1; input_scancode = scancode; input_state = 0; input_covered_char = getchar_at_cursor(); } else input_state++; if (scancode == '0') sel = whspace; else if (scancode == '1') sel = punct; else sel = digits_sel[input_mode][scancode - '2']; c = *(sel + input_state); if (c == '\0') { input_state = 0; c = *sel; } input_selected_char = (int)c; putchar_at_cursor((char)input_selected_char);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -