Copy only modified lines to LCD
Results in speedup of 65 fps to 80 fps in some cases where the screen does not change often between frames. Signed-off-by: Mahyar Koshkouei <mk@deltabeard.com>
This commit is contained in:
+49
-4
@@ -97,6 +97,12 @@ union core_cmd {
|
|||||||
uint32_t full;
|
uint32_t full;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gb_priv {
|
||||||
|
uint32_t lcd_line_hashes[LCD_HEIGHT];
|
||||||
|
uint dma_pixel_buffer_chan;
|
||||||
|
};
|
||||||
|
static struct gb_priv gb_priv = { 0 };
|
||||||
|
|
||||||
/* Pixel data is stored in here. */
|
/* Pixel data is stored in here. */
|
||||||
static uint8_t pixels_buffer[LCD_WIDTH];
|
static uint8_t pixels_buffer[LCD_WIDTH];
|
||||||
|
|
||||||
@@ -274,6 +280,7 @@ void main_core1(void)
|
|||||||
// Sleep used for debugging LCD window.
|
// Sleep used for debugging LCD window.
|
||||||
//sleep_ms(1000);
|
//sleep_ms(1000);
|
||||||
|
|
||||||
|
/* Handle commands coming from core0. */
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
cmd.full = multicore_fifo_pop_blocking();
|
cmd.full = multicore_fifo_pop_blocking();
|
||||||
@@ -296,6 +303,7 @@ void main_core1(void)
|
|||||||
HEDLEY_UNREACHABLE();
|
HEDLEY_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_LCD
|
||||||
void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[LCD_WIDTH],
|
void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[LCD_WIDTH],
|
||||||
const uint_fast8_t line)
|
const uint_fast8_t line)
|
||||||
{
|
{
|
||||||
@@ -305,14 +313,26 @@ void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[LCD_WIDTH],
|
|||||||
while(__atomic_load_n(&lcd_line_busy, __ATOMIC_SEQ_CST))
|
while(__atomic_load_n(&lcd_line_busy, __ATOMIC_SEQ_CST))
|
||||||
tight_loop_contents();
|
tight_loop_contents();
|
||||||
|
|
||||||
|
//memcpy(pixels_buffer, pixels, LCD_WIDTH);
|
||||||
|
dma_hw->sniff_data = 0;
|
||||||
|
//line_to_copy = line;
|
||||||
|
dma_channel_set_read_addr(gb_priv.dma_pixel_buffer_chan, pixels, false);
|
||||||
|
dma_channel_set_write_addr(gb_priv.dma_pixel_buffer_chan, pixels_buffer, true);
|
||||||
|
dma_channel_wait_for_finish_blocking(gb_priv.dma_pixel_buffer_chan);
|
||||||
|
|
||||||
|
if(gb_priv.lcd_line_hashes[line] == dma_hw->sniff_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gb_priv.lcd_line_hashes[line] = dma_hw->sniff_data;
|
||||||
|
|
||||||
/* Populate command. */
|
/* Populate command. */
|
||||||
cmd.cmd = CORE_CMD_LCD_LINE;
|
cmd.cmd = CORE_CMD_LCD_LINE;
|
||||||
cmd.data = line;
|
cmd.data = line;
|
||||||
|
|
||||||
__atomic_store_n(&lcd_line_busy, 1, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&lcd_line_busy, 1, __ATOMIC_SEQ_CST);
|
||||||
memcpy(pixels_buffer, pixels, LCD_WIDTH);
|
|
||||||
multicore_fifo_push_blocking(cmd.full);
|
multicore_fifo_push_blocking(cmd.full);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@@ -354,18 +374,17 @@ int main(void)
|
|||||||
clock_configure(clk_peri, 0,
|
clock_configure(clk_peri, 0,
|
||||||
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
|
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
|
||||||
125 * 1000 * 1000, 125 * 1000 * 1000);
|
125 * 1000 * 1000, 125 * 1000 * 1000);
|
||||||
spi_init(spi0, 32*1000*1000);
|
spi_init(spi0, 16*1000*1000);
|
||||||
spi_set_format(spi0, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
spi_set_format(spi0, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||||
|
|
||||||
/* Start Core1, which processes requests to the LCD. */
|
/* Start Core1, which processes requests to the LCD. */
|
||||||
//puts_raw("Launching Core 1");
|
|
||||||
putstdio("CORE1 ");
|
putstdio("CORE1 ");
|
||||||
multicore_launch_core1(main_core1);
|
multicore_launch_core1(main_core1);
|
||||||
|
|
||||||
/* Initialise GB context. */
|
/* Initialise GB context. */
|
||||||
memcpy(rom_bank0, rom, sizeof(rom_bank0));
|
memcpy(rom_bank0, rom, sizeof(rom_bank0));
|
||||||
ret = gb_init(&gb, &gb_rom_read, &gb_cart_ram_read,
|
ret = gb_init(&gb, &gb_rom_read, &gb_cart_ram_read,
|
||||||
&gb_cart_ram_write, &gb_error, NULL);
|
&gb_cart_ram_write, &gb_error, &gb_priv);
|
||||||
putstdio("GB ");
|
putstdio("GB ");
|
||||||
|
|
||||||
if(ret != GB_INIT_NO_ERROR)
|
if(ret != GB_INIT_NO_ERROR)
|
||||||
@@ -376,6 +395,32 @@ int main(void)
|
|||||||
|
|
||||||
#if ENABLE_LCD
|
#if ENABLE_LCD
|
||||||
gb_init_lcd(&gb, &lcd_draw_line);
|
gb_init_lcd(&gb, &lcd_draw_line);
|
||||||
|
{
|
||||||
|
/* initialise pixel buffer copy DMA. */
|
||||||
|
static dma_channel_config dma_config;
|
||||||
|
gb_priv.dma_pixel_buffer_chan = dma_claim_unused_channel(true);
|
||||||
|
dma_config = dma_channel_get_default_config(gb_priv.dma_pixel_buffer_chan);
|
||||||
|
channel_config_set_transfer_data_size(&dma_config, DMA_SIZE_32);
|
||||||
|
channel_config_set_read_increment(&dma_config, true);
|
||||||
|
channel_config_set_write_increment(&dma_config, true);
|
||||||
|
dma_sniffer_enable(gb_priv.dma_pixel_buffer_chan, 0x0, true);
|
||||||
|
channel_config_set_sniff_enable(&dma_config, true);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
irq_set_exclusive_handler(DMA_IRQ_1, core0_irq_dma_lcd_line_copy);
|
||||||
|
dma_channel_set_irq1_enabled(gb_priv.dma_pixel_buffer_chan, true);
|
||||||
|
irq_set_enabled(DMA_IRQ_1, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dma_channel_configure(
|
||||||
|
gb_priv.dma_pixel_buffer_chan,
|
||||||
|
&dma_config,
|
||||||
|
pixels_buffer,
|
||||||
|
0, /* We don't have a pointer to the pixel buffer here. */
|
||||||
|
LCD_WIDTH/sizeof(uint32_t),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
putstdio("LCD ");
|
putstdio("LCD ");
|
||||||
//gb.direct.interlace = 1;
|
//gb.direct.interlace = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user