📄 lcd_support.c
字号:
unsigned long _fp;
// Frame buffer must be aligned on a 16 byte boundary
_fp = (((unsigned long)&lcd_frame_buffer) + 15) & ~15;
fp = (struct lcd_frame *)(_fp + SA11X0_RAM_BANK0_BASE);
// Enable LCD in 320x240 16bpp
*SA1110_DBAR1 = (unsigned long)&(fp->palette);
*SA1110_LCCR1 = 0x1D1D0930;
*SA1110_LCCR2 = 0xEF;
*SA1110_LCCR3 = 0x0c;
fp->palette[0] = 0x2000; // Tell controller 16 bits
// *SA1110_LCCR0 = 0xBB; // B&W
*SA1110_LCCR0 = 0xB9; // Color
// assabet_BCR(SA1110_BCR_LCD_BPP, SA1110_BCR_LCD_12BPP);
assabet_BCR(SA1110_BCR_LCD_BPP, SA1110_BCR_LCD_16BPP);
assabet_BCR(SA1110_BCR_LCD, SA1110_BCR_LCD_ON);
assabet_BCR(SA1110_BCR_BACKLIGHT, SA1110_BCR_BACKLIGHT);
}
// Clear screen
void
lcd_clear(void)
{
int row, col;
for (row = 0; row < lcd_height; row++) {
for (col = 0; col < lcd_width; col++) {
fp->pixels[row][col] = bg;
}
}
for (row = 0; row < SCREEN_HEIGHT; row++) {
for (col = 0; col < SCREEN_WIDTH; col++) {
screen[row][col] = ' ';
}
}
// Note: Row 0 seems to wrap incorrectly
curX = 0; curY = SCREEN_START;
lcd_drawc(CURSOR_ON, curX, curY);
show_xpm(banner_xpm);
}
// Position cursor
void
lcd_moveto(int X, int Y)
{
lcd_drawc(CURSOR_OFF, curX, curY);
if (X < 0) X = 0;
if (X >= SCREEN_WIDTH) X = SCREEN_WIDTH-1;
curX = X;
if (Y < SCREEN_START) Y = SCREEN_START;
if (Y >= SCREEN_HEIGHT) Y = SCREEN_HEIGHT-1;
curY = Y;
lcd_drawc(CURSOR_ON, curX, curY);
}
// Render a character at position (X,Y) with current background/foreground
static void
lcd_drawc(cyg_int8 c, int x, int y)
{
// Currently hard-coded for 16bpp
cyg_uint8 bits;
cyg_uint16 *pixels;
int l, p;
screen[curY][curX] = c;
for (l = 0; l < FONT_HEIGHT; l++) {
bits = font_table[c-FIRST_CHAR][l];
pixels = &fp->pixels[curY*FONT_HEIGHT+l][curX*FONT_WIDTH];
for (p = 0; p < 8; p++) {
if (bits & 0x01) {
*pixels++ = fg;
} else {
*pixels++ = bg;
}
bits >>= 1;
}
}
}
static void
lcd_scroll(void)
{
int row, col;
cyg_uint8 *c1, *c2;
cyg_uint16 *p1, *p2;
// First scroll up the virtual screen
for (row = SCREEN_START; 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;
}
// Now the physical screen
for (row = FONT_HEIGHT*(SCREEN_START+1); row < LCD_HEIGHT; row++) {
p1 = &fp->pixels[row-FONT_HEIGHT][0];
p2 = &fp->pixels[row][0];
for (col = 0; col < LCD_WIDTH; col++) {
*p1++ = *p2++;
}
}
for (row = LCD_HEIGHT-FONT_HEIGHT; row < LCD_HEIGHT; row++) {
p1 = &fp->pixels[row][0];
for (col = 0; col < LCD_WIDTH; col++) {
*p1++ = bg;
}
}
}
// Draw one character at the current position
void
lcd_putc(cyg_int8 c)
{
lcd_drawc(CURSOR_OFF, curX, curY);
switch (c) {
case '\r':
curX = 0;
break;
case '\n':
curY++;
if (curY == SCREEN_HEIGHT) {
lcd_scroll();
curY--;
}
break;
case '\b':
curX--;
if (curX < 0) {
curY--;
if (curY < 0) curY = 0;
curX = SCREEN_WIDTH-1;
}
break;
default:
lcd_drawc(c, curX, curY);
curX++;
if (curX == SCREEN_WIDTH) {
curY++;
curX = 0;
}
}
lcd_drawc(CURSOR_ON, curX, 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);
}
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');
}
}
}
}
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
set_bg(int red, int green, int blue)
{
bg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
}
void
set_fg(int red, int green, int blue)
{
fg = RGB_RED(red) | RGB_GREEN(green) | RGB_BLUE(blue);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -