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 "config.h"
|
||||||
|
#include "hwcompat.h"
|
||||||
|
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
@ -30,244 +31,19 @@
|
||||||
|
|
||||||
/*** definitions ***/
|
/*** definitions ***/
|
||||||
|
|
||||||
#define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00)
|
#define CHAR_WIDTH 6
|
||||||
#define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10)
|
#define CHAR_HEIGHT 8
|
||||||
#define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20)
|
#define ICON_HEIGHT 8
|
||||||
#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)
|
|
||||||
|
|
||||||
/* 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];
|
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 */
|
/* All zeros and ones bitmaps for area filling */
|
||||||
static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff,
|
static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff};
|
0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
void lcd_init(void)
|
static int double_height=1;
|
||||||
{
|
|
||||||
create_thread(scroll_thread, scroll_stack,
|
|
||||||
sizeof(scroll_stack), scroll_name);
|
|
||||||
}
|
|
||||||
void lcd_clear_display (void)
|
|
||||||
{
|
|
||||||
memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
* Draw a bitmap at (x, y), size (nx, ny)
|
||||||
|
|
@ -575,106 +351,146 @@ void lcd_invertpixel(int x, int y)
|
||||||
INVERT_PIXEL(x,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;
|
memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
|
||||||
int w, h;
|
}
|
||||||
|
|
||||||
lcd_puts(x,y,string);
|
/* put a string at a given pixel position, skipping first ofs pixel columns */
|
||||||
lcd_getstringsize(string, &w, &h);
|
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 */
|
int width;
|
||||||
char *end;
|
|
||||||
|
|
||||||
memset(s->line, 0, sizeof s->line);
|
/* check input range */
|
||||||
strcpy(s->line, string);
|
if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
|
||||||
strcat(s->line, " ");
|
ch = pf->defaultchar;
|
||||||
/* get new width incl. spaces */
|
ch -= pf->firstchar;
|
||||||
s->width = lcd_getstringsize(s->line, &w, &h);
|
|
||||||
|
|
||||||
for (end = s->line; *end; end++);
|
/* no partial-height drawing for now... */
|
||||||
strncpy(end, string, LCD_WIDTH/2);
|
if (y + pf->height > LCD_HEIGHT)
|
||||||
|
break;
|
||||||
|
|
||||||
s->len = strlen(string);
|
/* get proportional width and glyph bits */
|
||||||
s->offset = 0;
|
width = pf->width ? pf->width[ch] : pf->maxwidth;
|
||||||
s->startx = x;
|
width = MIN (width, LCD_WIDTH - x);
|
||||||
s->starty = y;
|
|
||||||
scroll_count = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (ofs != 0)
|
||||||
void lcd_stop_scroll(void)
|
{
|
||||||
{
|
if (ofs > width)
|
||||||
if ( scroll_count ) {
|
{
|
||||||
int w,h;
|
ofs -= width;
|
||||||
struct scrollinfo* s = &scroll;
|
continue;
|
||||||
scroll_count = 0;
|
}
|
||||||
|
width -= ofs;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
/* 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 (width > 0)
|
||||||
|
{
|
||||||
if (s->offset >= s->width)
|
int rows = (pf->height + 7) / 8;
|
||||||
s->offset %= s->width;
|
bitmap_t* bits = pf->bits +
|
||||||
|
(pf->offset ? pf->offset[ch] : (pf->height * ch));
|
||||||
lcd_getstringsize(s->line, &w, &h);
|
lcd_bitmap (((unsigned char*) bits) + ofs*rows, x, y,
|
||||||
xpos = xmargin + s->startx * s->width / s->len;
|
width, pf->height, true);
|
||||||
ypos = ymargin + s->starty * h;
|
x += width;
|
||||||
|
|
||||||
lcd_clearrect(xpos, ypos, LCD_WIDTH - xmargin, h);
|
|
||||||
lcd_putsxyofs(xpos, ypos, s->offset, s->line);
|
|
||||||
lcd_update();
|
|
||||||
}
|
}
|
||||||
sleep(HZ/scroll_speed);
|
ofs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------
|
/* put a string at a given pixel position */
|
||||||
* local variables:
|
void lcd_putsxy(int x, int y, unsigned char *str)
|
||||||
* eval: (load-file "../rockbox-mode.el")
|
{
|
||||||
* end:
|
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