📄 lcd_support.c
字号:
set_pixel(yoff, xoff + p, (bits & 0x01) ? fg : bg);
bits >>= 1;
}
#endif
}
}
static void
lcd_refresh(void)
{
int row, col;
for (row = screen_start; row < screen_height; row++) {
for (col = 0; col < VISIBLE_SCREEN_WIDTH; col++) {
if ((col+screen_pan) < screen_width) {
lcd_drawc(screen[row][col+screen_pan], col, row);
} else {
lcd_drawc(' ', col, row);
}
}
}
if (cursor_enable) {
lcd_drawc(CURSOR_ON, curX-screen_pan, curY);
}
}
static void
lcd_scroll(void)
{
int col;
cyg_uint8 *c1;
cyg_uint32 *lc0, *lc1, *lcn;
#ifndef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
cyg_uint32 *fb_row0, *fb_row1, *fb_rown;
#endif
// First scroll up the virtual screen
#if ((SCREEN_WIDTH%4) != 0)
#error Scroll code optimized for screen with multiple of 4 columns
#endif
lc0 = (cyg_uint32 *)&screen[0][0];
lc1 = (cyg_uint32 *)&screen[1][0];
lcn = (cyg_uint32 *)&screen[screen_height][0];
while (lc1 != lcn) {
*lc0++ = *lc1++;
}
c1 = &screen[screen_height-1][0];
for (col = 0; col < screen_width; col++) {
*c1++ = 0x20;
}
#ifdef CYGSEM_AAED2000_LCD_PORTRAIT_MODE
// Redrawing the screen in this mode is hard :-)
lcd_refresh();
#else
fb_row0 = lcd_fb(screen_start*FONT_HEIGHT, 0);
fb_row1 = lcd_fb((screen_start+1)*FONT_HEIGHT, 0);
fb_rown = lcd_fb(screen_end*FONT_HEIGHT, 0);
#if 1
while (fb_row1 != fb_rown) {
*fb_row0++ = *fb_row1++;
}
#else
// Optimized ARM assembly "move" code
asm __volatile(
"mov r0,%0;"
"mov r1,%1;"
"mov r2,%2;"
"10: ldmia r1!,{r3-r10};"
"stmia r0!,{r3-r10};"
"cmp r1,r2;"
"bne 10b"
:
: "r"(fb_row0), "r"(fb_row1), "r"(fb_rown)
: "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10"
);
#endif
// Erase bottom line
for (col = 0; col < screen_width; col++) {
lcd_drawc(' ', col, screen_end-1);
}
#endif
}
// 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>
#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');
}
}
}
// FIXME
return 0;
}
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);
}
//
// Support LCD/keyboard (PS2) as a virtual I/O channel
// Adapted from i386/pcmb_screen.c
//
static int _timeout = 500;
static cyg_bool
lcd_comm_getc_nonblock(void* __ch_data, cyg_uint8* ch)
{
if( !aaed2000_KeyboardTest() )
return false;
*ch = aaed2000_KeyboardGetc();
return true;
}
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 * 2; // delay in .5 ms steps
for(;;) {
res = lcd_comm_getc_nonblock(__ch_data, ch);
if (res || 0 == delay_count--)
break;
CYGACC_CALL_IF_DELAY_US(500);
}
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;
break;
case __COMMCTL_IRQ_DISABLE:
ret = irq_state;
irq_state = 0;
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:
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;
#else
return 0;
#endif
}
void
lcd_comm_init(void)
{
static int init = 0;
if (!init) {
hal_virtual_comm_table_t* comm;
int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
init = 1;
lcd_on(false);
if (!aaed2000_KeyboardInit()) {
// No keyboard - no LCD display
return;
}
// Initialize screen
cursor_enable = true;
lcd_init(16);
lcd_screen_clear();
// Setup procs in the vector table
CYGACC_CALL_IF_SET_CONSOLE_COMM(1); // FIXME - should be controlled by CDL
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);
}
}
#ifdef CYGPKG_REDBOOT
#include <redboot.h>
// Get here when RedBoot is idle. If it's been long enough, then
// dim the LCD. The problem is - how to determine other activities
// so at this doesn't get in the way. In the default case, this will
// be called from RedBoot every 10ms (CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT)
#define MAX_IDLE_TIME (30*100)
static void
idle(bool is_idle)
{
static int idle_time = 0;
static bool was_idled = false;
if (is_idle) {
if (!was_idled) {
if (++idle_time == MAX_IDLE_TIME) {
was_idled = true;
lcd_on(false);
}
}
} else {
idle_time = 0;
if (was_idled) {
was_idled = false;
lcd_on(true);
}
}
}
RedBoot_idle(idle, RedBoot_AFTER_NETIO);
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -