eLinux.org - Embedded Linux Wiki
JuiceBox Code Lcd Main
From eLinux.org
(file: lcd_1.c)
#include "stdint.h"
#include "s3c44b0x.h"
const uint8_t lookup[]=
{ 0xff, /* white */
0xe0, /* red */
0x1c, /* green */
0x03, /* blue */
0xe0 | 0x1c, /* red + green */
0x1c | 0x03, /* green + blue */
0xe0 | 0x03, /* red + blue */
0, /* black */
};
void delay_ms(uint32_t delay)
{
/* Delay hand tuned for use with 66.428MHz clock
(PLLCON = 0x55051, PLL reference of 10MHz).
Assumes code is running from cached memory.
fixme: use a hardware timer instead.
*/
uint32_t ms;
uint32_t i;
for (ms=0; ms<delay; ms++)
for (i=0; i<13288; i++);
}
void tune_delay()
{
/* Swap TXD0 line to I/O and toggle it to tune delay_ms() */
*pcone&=~0x0c;
*pcone|=0x04;
/* Expect 50 Hz, or 10ms from edge to edge */
for (;;)
{
*pdate|=0x02;
delay_ms(10);
*pdate&=(~0x02);
delay_ms(10);
}
}
void uart_init()
{
/* Assign TX and RX pins to the UART */
*pcone&=~0x0c;
*pcone|=0x08;
/* 8 bits, 2 stop bits, no parity, non-IrDA mode */
*ulcon0=0x03;
/* Polled RX, polled TX, no break, no loopback, no error interrupts,
no RX fifo timeouts, TX level interrupts
*/
*ucon0=0x205;
/* Clear and enable FIFOs */
*ufcon0=7;
/* Disable automatic flow control on handshake lines */
*umcon0=0;
/* Set baud rate divisor
0x23 = 115.2k baud with 66.428MHz clock
(OK, it's really 115.327kbaud, or 0.11% fast).
*/
*ubrdiv0=0x23;
}
void cpu_init()
{
/* Set clock rate to 66.428MHz, just in case the JB has
it set wrong
*/
*pllcon=0x55051;
/* Be sure we're in cacheable memory
Can the framebuffer be in cache too?
*/
*ncachbe0=0x80002000;
*ncachbe1=0x0;
}
void uart_tx_string(const uint8_t* s)
{
while (*s)
{
/* Spin until fifo isn't full */
while ((*ufstat0 & 0x0200)) {};
*utxh0=*s;
s++;
}
}
void set_lcd_brightness(uint32_t brightness)
{
/* Set LCD backlight brightness
0 is dark, 0xa00 is full bright
*/
*tcmpb1=brightness;
}
uint32_t *framebuffer_start()
{
/* Return with starting address of LCD framebuffer */
return (uint32_t*)(((*lcdsaddr1) & 0x07ffffff) << 1);
}
void clear_lcd()
{
uint32_t i;
uint32_t *addr=framebuffer_start();
/* fill entire framebuffer, 32 bits at a whack */
for (i=0; i<240*160; i+=4)
{
*addr=0;
++addr;
}
}
void h_line(uint32_t y, uint8_t color)
{
uint32_t x;
uint32_t c=(color << 24) | (color << 16) | (color << 8) | color;
uint32_t *addr=framebuffer_start();
addr+=(240*y)/4;
/* Draw horizontal line, 4 bytes at a time */
for (x=0; x<240; x+=4)
{
*addr++=c;
}
}
void v_line(uint32_t x, uint8_t color)
{
uint32_t y;
uint8_t *addr=(uint8_t*)framebuffer_start();
addr+=x;
/* Assumes 240 pixels/line */
for (y=0; y<160; y++)
{
*addr=color;
addr+=240;
}
}
void h_loop()
{
/* Bounce a horizontal line up and down the screen. */
uint32_t i, color;
clear_lcd();
for (color=0; color<7; color++)
{
for (i=0; i<159; i++)
{
h_line(i+1, lookup[color]);
h_line(i, 0);
delay_ms(6);
}
for (i=160; i>0; i--)
{
h_line(i-1, lookup[color]);
h_line(i, 0);
delay_ms(6);
}
}
}
void v_loop()
{
/* Bounce a vertical line back and forth */
uint32_t x, color;
clear_lcd();
for (color=0; color<7; color++)
{
for (x=0; x<240; x++)
{
v_line(x+1, lookup[color]);
v_line(x, 0);
delay_ms(6);
}
for (x=240; x>0; x--)
{
v_line(x-1, lookup[color]);
v_line(x, 0);
delay_ms(6);
}
}
}
void v_fill_loop()
{
/* Vertical screen fill demo */
uint32_t x, color;
for (color=0; color<7;)
{
for (x=0; x<240; x++)
{
v_line(x+1, lookup[color]);
delay_ms(6);
}
color++;
for (x=240; x>0; x--)
{
v_line(x-1, lookup[color]);
delay_ms(6);
}
color++;
}
}
void h_fill_loop()
{
/* Horizontal screen fill demo */
uint32_t i, color;
for (color=0; color<7;)
{
for (i=0; i<160; i++)
{
h_line(i, lookup[color]);
delay_ms(6);
}
color++;
for (i=160; i>0; i--)
{
h_line(i-1, lookup[color]);
delay_ms(6);
}
color++;
}
}
void lcd_init()
{
/* Set ENVID (bit 0 of lcdcon1) to 0 to disable panel */
*lcdcon1=0x10C0DF40; /* LCDCON1 (LCD Control 1) */
/* Configure the LCD panel, using settings borrowed from
the built in self test code.
Looks like it's one byte/pixel, using the palette LUT registers.
*/
*lcdcon2=0x0141649F; /* LCDCON2 (LCD Control 2) */
*lcdcon3=0x00000000; /* LCDCON3 (LCD Control 3) */
*lcdsaddr1=0x1E0F288A; /* LCDSADDR1 (Frame Upper Buffer Start Address 1) */
*lcdsaddr2=0x21AF738A; /* LCDSADDR2 (Frame Lower Buffer Start Address 2) */
*lcdsaddr3=0x00000078; /* LCDSADDR3 (Virtual Screen Address) */
*redlut=0xFDB96420; /* REDLUT (RED Lookup Table) */
*greenlut=0xFDB96420; /* GREENLUT (GREEN Lookup Table) */
*bluelut=0x0000FB40; /* BLUELUT (BLUE Lookup Table) */
*dp1_2=0x0000A5A5; /* DP1_2 (Dithering Pattern duty 1/2) */
*dp4_7=0x0BA5DA65; /* DP4_7 (Dithering Pattern duty 4/7) */
*dp3_5=0x000A5A5F; /* DP3_5 (Dithering Pattern duty 3/5) */
*dp2_3=0x00000D6B; /* DP2_3 (Dithering Pattern duty 2/3) */
*dp5_7=0x0EB7B5ED; /* DP5_7 (Dithering Pattern duty 5/7) */
*dp3_4=0x00007DBE; /* DP3_4 (Dithering Pattern duty 3/4) */
*dp4_5=0x0007EBDF; /* DP4_5 (Dithering Pattern duty 4/5) */
*dp6_7=0x07FDFBFE; /* DP6_7 (Dithering Pattern duty 6/7) */
*dithmode=0x00000000; /* DITHMODE (Dithering Mode) */
/* Enable the panel now that the settings are in place */
*lcdcon1=0x10C0DF41; /* LCDCON1 (LCD Control 1) */
}
void solid_fill(uint8_t color)
{
/* Fill the entire framebuffer with a solid color */
uint32_t i, c;
uint32_t *addr=framebuffer_start();
c=(color << 24) | (color << 16) | (color << 8) | color;
for (i=0; i<240*160; i+=4)
{
*addr++=c;
}
}
void color_test()
{
/* Try to display all 256 potential color
I'm not at all sure this works, but I left it in.
*/
uint32_t x, y, c;
uint8_t *addr=(uint8_t*)framebuffer_start();
for (y=0; y<160; y++)
{
for (x=0; x<240; x++)
{
c=((x /15) << 4) + (y/10);
*addr++=c;
}
}
}
int main(void)
{
uint32_t i;
/* Init */
cpu_init();
uart_init();
lcd_init();
/* Hi */
uart_tx_string("\r\n\r\nJuicebox: Hello, world! ("
__FILE__ ", " __DATE__ ", " __TIME__ ")");
delay_ms(100);
/* Demo loop */
for (;;)
{
uart_tx_string("\r\n Vertical fill demo...");
v_fill_loop();
uart_tx_string("\r\n Horizontal fill demo...");
h_fill_loop();
uart_tx_string("\r\n Vertical line demo...");
v_loop();
uart_tx_string("\r\n Horizontal line demo...");
h_loop();
uart_tx_string("\r\n Color swatch demo...");
color_test();
delay_ms(2000);
uart_tx_string("\r\n Color flood demo...");
for (i=0; i<255; i++)
{
solid_fill(i);
delay_ms(50);
}
}
return 0;
}

