void lcd_begin_frame() { uint8_t flags = vram.flags; uint8_t mode = vram.mode; lcd_window_x = 0; lcd_window_y = vram.first_line; /* * Wake up the LCD controller, if necessary. */ if (!lcd_is_awake) { lcd_is_awake = 1; // First, we take the LCD controller out of reset. // Then we fully initialize it. We turn on the backlight // after both initialization is complete and the first // frame has finished rendering. CTRL_PORT = CTRL_IDLE & ~CTRL_LCD_DCX; CTRL_PORT = (CTRL_IDLE & ~CTRL_LCD_DCX) | CTRL_FLASH_LAT2; // Enter reset lcd_reset_delay(); CTRL_PORT = CTRL_IDLE; CTRL_PORT = CTRL_IDLE | CTRL_FLASH_LAT2; // Exit reset // Controller initialization lcd_cmd_table(lcd_setup_table); #ifdef LCD_MODEL_TIANMA_HX8353 lcd_lut_init(); #endif } LCD_WRITE_BEGIN(); // Set addressing mode LCD_CMD_MODE(); LCD_BYTE(LCD_CMD_MADCTR); LCD_DATA_MODE(); LCD_BYTE(LCD_MADCTR_NORMAL ^ (flags & LCD_MADCTR_VRAM)); // Set row/column addressing, and start RAMWR. lcd_address_and_write(); LCD_WRITE_END(); // Vertical sync #ifdef HAVE_LCD_TE if (flags & _SYS_VF_SYNC) while (!CTRL_LCD_TE); #endif }
void lcd_lut_init() { /* * The HX8353 seems to boot up with a totally bogus color LUT. * So, we need to set it ourselves. */ LCD_WRITE_BEGIN(); LCD_CMD_MODE(); LCD_BYTE(LCD_CMD_COLOR_LUT); LCD_DATA_MODE(); lcd_lut_32(); // Red lcd_lut_64(); // Green lcd_lut_32(); // Blue // It's okay to return in write mode. }
/* ** ** low level routine to send a byte value ** to the LCD controller data register. entry argument ** is the data to output and the controller-number ** */ void lcd_out_dat(const unsigned char dat, const unsigned char ncontr) { LCD_DATA_MODE(); LCDDATAPORT = dat; lcd_strobe_e(ncontr); }
void lcd_address_and_write(void) { /* * Change the row/column address, and start a RAMWR command. * * Assumes we're already set up for writing to the LCD. * Leaves with the bus in data mode. * * In the case that HAVE_GRAM_PANEL_MISMATCH is defined, * we must calculate the appropriate values for CASET and RASET * based on the current VRAM flags configuration as follows: * * x_offset = (flags & LCD_MADCTR_MX) ? LCD_X_RIGHT_MARGIN : LCD_X_LEFT_MARGIN * y_offset = (flags & LCD_MADCTR_MY) ? LCD_Y_BOTTOM_MARGIN : LCD_Y_TOP_MARGIN * if (flags & LCD_MADCTR_MV) { * col_offset = y_offset * row_offset = x_offset * } else { * col_offset = x_offset * row_offset = y_offset * } * * Some graphics modes constrain the registers we can use * to implement this - we can only touch b, r0 and r1, * because of the requirements in vm_stamp_pixel(), * by way of vm_fb32_pixel(). Otherwise, we'd be happy * to implement this in C. */ #ifdef HAVE_GRAM_PANEL_MISMATCH __asm push acc push dpl push dph ; vram.flags in a mov dptr, #_SYS_VA_FLAGS movx a, @dptr ; select y_margin based on LCD_MADCTR_MY and save in b jnb acc.7, 1$ ; flags & LCD_MADCTR_MY mov b, #LCD_Y_BOTTOM_MARGIN sjmp 2$ 1$: mov b, #LCD_Y_TOP_MARGIN 2$: ; col_offset in r1 and row_offset in r0, based on LCD_MADCTR_MV. ; XXX: because the X margins are both the same for the Santek, ; we shortcut the test of LCD_MADCTR_MX, since currently ; more code space is required to enable this test. jnb acc.5, 3$ ; flags & LCD_MADCTR_MV mov r1, b mov r0, #LCD_X_RIGHT_MARGIN sjmp 4$ 3$: mov r1, #LCD_X_LEFT_MARGIN mov r0, b 4$: ASM_LCD_CMD_MODE(); ASM_LCD_BYTE(#LCD_CMD_CASET); ASM_LCD_DATA_MODE(); ASM_LCD_BYTE(#0x0); mov a, _lcd_window_x add a, r1 ASM_LCD_BYTE(a); ASM_LCD_BYTE(#0x0); mov a, #(LCD_WIDTH - 1) add a, r1 ASM_LCD_BYTE(a); ASM_LCD_CMD_MODE(); ASM_LCD_BYTE(#LCD_CMD_RASET); ASM_LCD_DATA_MODE(); ASM_LCD_BYTE(#0x0); mov a, _lcd_window_y add a, r0 ASM_LCD_BYTE(a); ASM_LCD_BYTE(#0x0); mov a, #(LCD_HEIGHT - 1) add a, r0 ASM_LCD_BYTE(a); ; assumption: dptr and a are not touched below pop dph pop dpl pop acc __endasm; #else LCD_CMD_MODE(); LCD_BYTE(LCD_CMD_CASET); LCD_DATA_MODE(); LCD_BYTE(0); LCD_BYTE((lcd_window_x)); LCD_BYTE(0); LCD_BYTE((LCD_WIDTH - 1)); LCD_CMD_MODE(); LCD_BYTE(LCD_CMD_RASET); LCD_DATA_MODE(); LCD_BYTE(0); LCD_BYTE((lcd_window_y)); LCD_BYTE(0); LCD_BYTE((LCD_HEIGHT - 1)); #endif /* * Start writing (RAMWR command). * * We have to do this particular command -> data transition * somewhat gingerly, since the Truly LCD is really picky. If we * transition from command to data while the write strobe is low, * it will falsely detect that as an additional byte-write that we * didn't intend. * * This paranoia is unnecessary but harmless on the Giantplus LCD. */ LCD_CMD_MODE(); LCD_BYTE(LCD_CMD_NOP); ADDR_PORT = 1; LCD_BYTE(LCD_CMD_RAMWR); LCD_DATA_MODE(); }