JuiceBox Code Lcd Main
(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; }