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:
parent
a99c565d72
commit
786d2c3cb3
1 changed files with 134 additions and 318 deletions
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue