1
0
Fork 0
forked from len0rd/rockbox

Rewritten based on lcd-player.c.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2715 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Mats Lidell 2002-10-18 09:20:48 +00:00
parent a99c565d72
commit 786d2c3cb3

View file

@ -17,6 +17,7 @@
*
****************************************************************************/
#include "config.h"
#include "hwcompat.h"
#include "lcd.h"
#include "kernel.h"
@ -30,244 +31,19 @@
/*** definitions ***/
#define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00)
#define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10)
#define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20)
#define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28)
#define LCD_SET_DISPLAY_START_LINE ((char)0x40)
#define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81)
#define LCD_SET_SEGMENT_REMAP ((char)0xA0)
#define LCD_SET_LCD_BIAS ((char)0xA2)
#define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4)
#define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5)
#define LCD_SET_NORMAL_DISPLAY ((char)0xA6)
#define LCD_SET_REVERSE_DISPLAY ((char)0xA7)
#define LCD_SET_INDICATOR_OFF ((char)0xAC)
#define LCD_SET_INDICATOR_ON ((char)0xAD)
#define LCD_SET_DISPLAY_OFF ((char)0xAE)
#define LCD_SET_DISPLAY_ON ((char)0xAF)
#define LCD_SET_PAGE_ADDRESS ((char)0xB0)
#define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0)
#define LCD_SET_DISPLAY_OFFSET ((char)0xD3)
#define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0)
#define LCD_SOFTWARE_RESET ((char)0xE2)
#define LCD_NOP ((char)0xE3)
#define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE)
#define CHAR_WIDTH 6
#define CHAR_HEIGHT 8
#define ICON_HEIGHT 8
/* LCD command codes */
#define LCD_CNTL_RESET 0xe2 // Software reset
#define LCD_CNTL_POWER 0x2f // Power control
#define LCD_CNTL_CONTRAST 0x81 // Contrast
#define LCD_CNTL_OUTSCAN 0xc8 // Output scan direction
#define LCD_CNTL_SEGREMAP 0xa1 // Segment remap
#define LCD_CNTL_DISPON 0xaf // Display on
#define LCD_CNTL_PAGE 0xb0 // Page address
#define LCD_CNTL_HIGHCOL 0x10 // Upper column address
#define LCD_CNTL_LOWCOL 0x00 // Lower column address
#define SCROLL_SPACING 3
struct scrollinfo {
char line[MAX_PATH + LCD_WIDTH/2 + SCROLL_SPACING + 2];
int len; /* length of line in chars */
int width; /* length of line in pixels */
int offset;
int startx;
int starty;
};
static void scroll_thread(void);
static char scroll_stack[DEFAULT_STACK_SIZE];
static char scroll_name[] = "scroll";
static char scroll_speed = 8; /* updates per second */
static char scroll_step = 6; /* pixels per scroll step */
static struct scrollinfo scroll; /* only one scroll line at the moment */
static int scroll_count = 0;
static int xmargin = 0;
static int ymargin = 0;
static int curfont = FONT_SYSFIXED;
#ifdef SIMULATOR
unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
#else
static unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
#endif
/* All zeros and ones bitmaps for area filling */
static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff};
void lcd_init(void)
{
create_thread(scroll_thread, scroll_stack,
sizeof(scroll_stack), scroll_name);
}
void lcd_clear_display (void)
{
memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
}
static int double_height=1;
void lcd_setmargins(int x, int y)
{
xmargin = x;
ymargin = y;
}
int lcd_getxmargin(void)
{
return xmargin;
}
int lcd_getymargin(void)
{
return ymargin;
}
void lcd_setfont(int newfont)
{
curfont = newfont;
}
int lcd_getstringsize(unsigned char *str, int *w, int *h)
{
struct font* pf = font_get(curfont);
int ch;
int width = 0;
while((ch = *str++)) {
/* check input range*/
if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
ch = pf->defaultchar;
ch -= pf->firstchar;
/* get proportional width and glyph bits*/
width += pf->width? pf->width[ch]: pf->maxwidth;
}
if ( w )
*w = width;
if ( h )
*h = pf->height;
return width;
}
/* put a string at a given char position */
void lcd_puts(int x, int y, unsigned char *str)
{
int xpos,ypos,w,h;
#if defined(HAVE_LCD_CHARCELLS)
/* We make the simulator truncate the string if it reaches the right edge,
as otherwise it'll wrap. The real target doesn't wrap. */
char buffer[12];
if(strlen(str)+x > 11 ) {
strncpy(buffer, str, sizeof buffer);
buffer[11-x]=0;
str = buffer;
}
xmargin = 0;
ymargin = 8;
#endif
if(!str || !str[0])
return;
lcd_getstringsize(str, &w, &h);
xpos = xmargin + x*w / strlen(str);
ypos = ymargin + y*h;
lcd_putsxy(xpos, ypos, str);
/* lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); */
#if defined(HAVE_LCD_CHARCELLS)
/* this function is being used when simulating a charcell LCD and
then we update immediately */
lcd_update();
#endif
}
extern char* get_lcd_pattern(int width);
/* put a string at a given pixel position, skipping first ofs pixel columns */
static void lcd_putsxyofs(int x, int y, int ofs, unsigned char *str)
{
int ch;
struct font* pf = font_get(curfont);
while ((ch = *str++) != '\0' && x < LCD_WIDTH)
{
int width;
/* check input range */
if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
#ifndef SIMULATOR
ch = pf->defaultchar;
#else
{
if (ch > 8)
ch = pf->defaultchar;
else
{
char* bm = get_lcd_pattern(ch);
width = 6;
lcd_bitmap(bm, x, y, width, 8, true);
x += width;
continue;
}
}
#endif
ch -= pf->firstchar;
/* no partial-height drawing for now... */
if (y + pf->height > LCD_HEIGHT)
break;
/* get proportional width and glyph bits */
width = pf->width ? pf->width[ch] : pf->maxwidth;
width = MIN (width, LCD_WIDTH - x);
if (ofs != 0)
{
if (ofs > width)
{
ofs -= width;
continue;
}
width -= ofs;
}
if (width > 0)
{
int rows = (pf->height + 7) / 8;
bitmap_t* bits = pf->bits +
(pf->offset ? pf->offset[ch] : (pf->height * ch));
lcd_bitmap (((unsigned char*) bits) + ofs*rows, x, y,
width, pf->height, true);
x += width;
}
ofs = 0;
}
}
/* put a string at a given pixel position */
void lcd_putsxy(int x, int y, unsigned char *str)
{
lcd_putsxyofs(x, y, 0, str);
}
/*
* All bitmaps have this format:
* Bits within a byte are arranged veritcally, LSB at top.
* Bytes are stored in column-major format, with byte 0 at top left,
* byte 1 is 2nd from top, etc. Bytes following left-most column
* starts 2nd left column, etc.
*
* Note: The HW takes bitmap bytes in row-major order.
*
* Memory copy of display bitmap
*/
/*
* Draw a bitmap at (x, y), size (nx, ny)
@ -575,106 +351,146 @@ void lcd_invertpixel(int x, int y)
INVERT_PIXEL(x,y);
}
void lcd_puts_scroll(int x, int y, unsigned char* string )
void lcd_clear_display(void)
{
struct scrollinfo* s = &scroll;
int w, h;
memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
}
lcd_puts(x,y,string);
lcd_getstringsize(string, &w, &h);
/* put a string at a given pixel position, skipping first ofs pixel columns */
static void lcd_putsxyofs(int x, int y, int ofs, unsigned char *str)
{
int ch;
struct font* pf = font_get(2);
if ((LCD_WIDTH - x*6 - xmargin) < w)
while ((ch = *str++) != '\0' && x < LCD_WIDTH)
{
/* prepare scroll line */
char *end;
int width;
memset(s->line, 0, sizeof s->line);
strcpy(s->line, string);
strcat(s->line, " ");
/* get new width incl. spaces */
s->width = lcd_getstringsize(s->line, &w, &h);
/* check input range */
if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
ch = pf->defaultchar;
ch -= pf->firstchar;
for (end = s->line; *end; end++);
strncpy(end, string, LCD_WIDTH/2);
/* no partial-height drawing for now... */
if (y + pf->height > LCD_HEIGHT)
break;
s->len = strlen(string);
s->offset = 0;
s->startx = x;
s->starty = y;
scroll_count = 1;
}
}
/* get proportional width and glyph bits */
width = pf->width ? pf->width[ch] : pf->maxwidth;
width = MIN (width, LCD_WIDTH - x);
void lcd_stop_scroll(void)
{
if ( scroll_count ) {
int w,h;
struct scrollinfo* s = &scroll;
scroll_count = 0;
lcd_getstringsize(s->line, &w, &h);
lcd_clearrect(xmargin + s->startx*w/s->len,
ymargin + s->starty*h,
LCD_WIDTH - xmargin,
h);
/* restore scrolled row */
lcd_puts(s->startx,s->starty,s->line);
lcd_update();
}
}
void lcd_scroll_pause(void)
{
scroll_count = 0;
}
void lcd_scroll_resume(void)
{
scroll_count = 1;
}
void lcd_scroll_speed(int speed)
{
scroll_step = speed;
}
static void scroll_thread(void)
{
struct scrollinfo* s = &scroll;
while ( 1 ) {
if ( !scroll_count ) {
yield();
continue;
if (ofs != 0)
{
if (ofs > width)
{
ofs -= width;
continue;
}
width -= ofs;
}
/* wait 0.5s before starting scroll */
if ( scroll_count < scroll_speed/2 )
scroll_count++;
else {
int w, h;
int xpos, ypos;
s->offset += scroll_step;
if (s->offset >= s->width)
s->offset %= s->width;
lcd_getstringsize(s->line, &w, &h);
xpos = xmargin + s->startx * s->width / s->len;
ypos = ymargin + s->starty * h;
lcd_clearrect(xpos, ypos, LCD_WIDTH - xmargin, h);
lcd_putsxyofs(xpos, ypos, s->offset, s->line);
lcd_update();
if (width > 0)
{
int rows = (pf->height + 7) / 8;
bitmap_t* bits = pf->bits +
(pf->offset ? pf->offset[ch] : (pf->height * ch));
lcd_bitmap (((unsigned char*) bits) + ofs*rows, x, y,
width, pf->height, true);
x += width;
}
sleep(HZ/scroll_speed);
ofs = 0;
}
}
/* -----------------------------------------------------------------
* local variables:
* eval: (load-file "../rockbox-mode.el")
* end:
*/
/* put a string at a given pixel position */
void lcd_putsxy(int x, int y, unsigned char *str)
{
lcd_putsxyofs(x, y, 0, str);
}
void lcd_puts(int x, int y, unsigned char *str)
{
int xpos,ypos;
/* We make the simulator truncate the string if it reaches the right edge,
as otherwise it'll wrap. The real target doesn't wrap. */
char buffer[12];
if(strlen(str)+x > 11 ) {
strncpy(buffer, str, sizeof buffer);
buffer[11-x]=0;
str = buffer;
}
xpos = CHAR_WIDTH * x;
ypos = ICON_HEIGHT + CHAR_HEIGHT * y;
lcd_clearrect(xpos, ypos, LCD_WIDTH - xpos, CHAR_HEIGHT * double_height);
lcd_putsxy(xpos, ypos, str);
/* this function is being used when simulating a charcell LCD and
then we update immediately */
lcd_update();
}
void lcd_double_height(bool on)
{
double_height = 1;
if (on)
double_height = 2;
}
static char patterns[8][7];
void lcd_define_pattern(int which, char *pattern, int length)
{
int i, j;
int pat = which / 8;
char icon[8];
memset(icon, 0, sizeof icon);
DEBUGF("Defining pattern %d\n", pat);
for (j = 0; j <= 5; j++) {
for (i = 0; i < length; i++) {
if ((pattern[i])&(1<<(j)))
icon[5-j] |= (1<<(i));
}
}
for (i = 0; i <= 5; i++)
{
patterns[pat][i] = icon[i];
}
}
char* get_lcd_pattern(int which)
{
DEBUGF("Get pattern %d\n", which);
return patterns[which];
}
extern void lcd_puts(int x, int y, unsigned char *str);
void lcd_putc(int x, int y, unsigned char ch)
{
char str[2];
int xpos = x * CHAR_WIDTH;
int ypos = ICON_HEIGHT + y * CHAR_HEIGHT;
if (ch <= 8)
{
char* bm = get_lcd_pattern(ch);
lcd_bitmap(bm, xpos, ypos, CHAR_WIDTH, CHAR_HEIGHT, true);
return;
}
if (ch == 137) {
/* Have no good font yet. Simulate the cursor character. */
ch = '>';
}
str[0] = ch;
str[1] = 0;
lcd_clearrect(xpos, ypos, CHAR_WIDTH, CHAR_HEIGHT * double_height);
lcd_putsxy(xpos, ypos, str);
/* this function is being used when simulating a charcell LCD and
then we update immediately */
lcd_update();
}