DV Display: Begin exposing sprites

dv_stick
Mike Bell 2023-07-10 23:30:02 +01:00 zatwierdzone przez Phil Howard
rodzic 3c2c7ccc94
commit 765b8a6226
5 zmienionych plików z 193 dodań i 4 usunięć

Wyświetl plik

@ -398,16 +398,75 @@ namespace pimoroni {
buf[2] = full_width << 16;
buf[3] = (uint32_t)display_height << 16;
buf[4] = 0x00000001;
buf[5] = 0x00010000 + display_height + (bank << 24);
buf[6] = 0x00000001;
buf[5] = 0x00010000 + display_height + ((uint32_t)bank << 24);
buf[6] = 0x04000001;
ram.write(0, buf, 7 * 4);
ram.wait_for_finish_blocking();
}
void DVDisplay::write_sprite_table()
{
constexpr uint32_t buf_size = 32;
uint32_t buf[buf_size];
uint addr = (display_height + 7) * 4 + PALETTE_SIZE * 3;
uint sprite_type = 0x10000000u;
for (uint32_t i = 0; i < max_num_sprites; i += buf_size) {
for (uint32_t j = 0; j < buf_size; ++j) {
buf[j] = sprite_type + (i + j) * sprite_size + sprite_base_address;
}
ram.write(addr, buf, buf_size * 4);
ram.wait_for_finish_blocking();
addr += buf_size * 4;
}
}
void DVDisplay::write_header()
{
write_header_preamble();
set_scroll_idx_for_lines(1, 0, display_height);
write_sprite_table();
}
void DVDisplay::define_sprite(uint16_t sprite_data_idx, uint16_t width, uint16_t height, uint16_t* data)
{
uint32_t buf[33];
uint16_t* buf_ptr = (uint16_t*)buf;
uint addr = sprite_base_address + sprite_data_idx * sprite_size;
*buf_ptr++ = (height << 8) + width;
for (uint16_t i = 0; i < height; ++i)
{
*buf_ptr++ = width << 8;
}
uint len = (uint8_t*)buf_ptr - (uint8_t*)buf;
ram.write(addr, buf, len);
addr += len;
if (len & 2) addr += 2;
ram.write(addr, (uint32_t*)data, width * height * 2);
}
void DVDisplay::set_sprite(int sprite_num, uint16_t sprite_data_idx, const Point &p)
{
uint8_t buf[7];
buf[0] = 1; // BLEND_DEPTH
buf[1] = sprite_data_idx & 0xff;
buf[2] = sprite_data_idx >> 8;
buf[3] = p.x & 0xff;
buf[4] = p.x >> 8;
buf[5] = p.y & 0xff;
buf[6] = p.y >> 8;
i2c->write_bytes(I2C_ADDR, sprite_num, buf, 7);
}
void DVDisplay::clear_sprite(int sprite_num)
{
uint16_t off = 0xFFFF;
i2c->write_bytes(I2C_ADDR, sprite_num, (uint8_t*)&off, 2);
}
uint32_t DVDisplay::point_to_address(const Point& p) const {

Wyświetl plik

@ -60,6 +60,9 @@ namespace pimoroni {
static constexpr uint RAM_SEL = 8;
static constexpr uint32_t base_address = 0x10000;
static constexpr uint32_t max_num_sprites = 1024;
static constexpr uint32_t sprite_size = 0x900;
static constexpr uint32_t sprite_base_address = 0x800000 - (max_num_sprites * sprite_size);
uint16_t display_width = 0;
uint16_t display_height = 0;
uint16_t frame_width = 0;
@ -134,6 +137,20 @@ namespace pimoroni {
void flip();
void reset();
// Define the data for a sprite, the specified data index can then be supplied
// to set_sprite to use the sprite. Up to 1024 sprites can be defined.
// Each sprite can be up to 2KB big, with a maximum width or height of 64 pixels.
// So for ARGB1555 sprites 64x16, 32x32, 16x64 are examples of maximum sizes.
// Sprites are currently only supported when using ARGB1555 mode.
// You must define the sprite to each RAM bank.
void define_sprite(uint16_t sprite_data_idx, uint16_t width, uint16_t height, uint16_t* data);
// Display/move a sprite to a given position.
// Note sprite positions are always display relative (not scrolled)
// TODO: Blend mode
void set_sprite(int sprite_num, uint16_t sprite_data_idx, const Point &p);
void clear_sprite(int sprite_num);
// 32 colour palette mode. Note that palette entries range from 0-31,
// but when writing colour values the palette entry is in bits 6-2, so the
// entry value is effectively multiplied by 4.
@ -183,8 +200,9 @@ namespace pimoroni {
virtual void write_palette();
virtual void write_header();
virtual void write_sprite_table();
virtual void write_header_preamble();
void write_header_preamble();
void i2c_modify_bit(uint8_t reg, uint bit, bool enable);
private:

Wyświetl plik

@ -0,0 +1,15 @@
set(OUTPUT_NAME dv_sprite_test)
add_executable(
${OUTPUT_NAME}
dv_sprite_test.cpp
edid-decode.c
)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME} pico_stdlib dv_display hardware_i2c hardware_uart pico_graphics)
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,97 @@
#include <cstdio>
#include <math.h>
#include <stdio.h>
#include "hardware/gpio.h"
#include "hardware/uart.h"
#include "drivers/dv_display/dv_display.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
using namespace pimoroni;
#define DISPLAY_WIDTH 360
#define DISPLAY_HEIGHT 240
#define FRAME_WIDTH 720
#define FRAME_HEIGHT 480
#define SPRITE_WIDTH 8
#define SPRITE_HEIGHT 8
static uint16_t sprite_data[] = {
0x0001, 0x0001, 0x0001, 0xF000, 0xF000, 0x0001, 0x0001, 0x0001,
0x0001, 0x0001, 0xF000, 0xF000, 0xF000, 0xF000, 0x0001, 0x0001,
0x0001, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0x0001,
0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000,
0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000,
0x0001, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0x0001,
0x0001, 0x0001, 0xF000, 0xF000, 0xF000, 0xF000, 0x0001, 0x0001,
0x0001, 0x0001, 0x0001, 0xF000, 0xF000, 0x0001, 0x0001, 0x0001,
};
void on_uart_rx() {
while (uart_is_readable(uart1)) {
uint8_t ch = uart_getc(uart1);
putc(ch, stdout);
}
}
int main() {
stdio_init_all();
// Relay UART RX from the display driver
gpio_set_function(5, GPIO_FUNC_UART);
uart_init(uart1, 115200);
uart_set_hw_flow(uart1, false, false);
uart_set_format(uart1, 8, 1, UART_PARITY_NONE);
uart_set_fifo_enabled(uart1, false);
irq_set_exclusive_handler(UART1_IRQ, on_uart_rx);
irq_set_enabled(UART1_IRQ, true);
uart_set_irq_enables(uart1, true, false);
constexpr uint BUTTON_A = 9;
gpio_init(BUTTON_A);
gpio_set_dir(BUTTON_A, GPIO_IN);
gpio_pull_up(BUTTON_A);
//sleep_ms(5000);
DVDisplay display;
display.init(DISPLAY_WIDTH, DISPLAY_HEIGHT, DVDisplay::MODE_RGB555, FRAME_WIDTH, FRAME_HEIGHT);
PicoGraphics_PenDV_RGB555 graphics(FRAME_WIDTH, FRAME_HEIGHT, display);
display.define_sprite(0, SPRITE_WIDTH, SPRITE_HEIGHT, sprite_data);
graphics.set_pen(0x000F);
graphics.clear();
display.flip();
constexpr int NUM_SPRITES = 32;
Point sprite_pos[NUM_SPRITES];
Point sprite_dir[NUM_SPRITES];
for (int i = 0; i < 32; ++i) {
sprite_pos[i].x = rand() % DISPLAY_WIDTH;
sprite_pos[i].y = rand() % DISPLAY_HEIGHT;
sprite_dir[i].x = (rand() & 1) ? 1 : -1;
sprite_dir[i].y = (rand() & 1) ? 1 : -1;
}
while (true)
{
for (int i = 0; i < 32; ++i) {
display.set_sprite(i, 0, sprite_pos[i]);
sprite_pos[i] += sprite_dir[i];
if (sprite_pos[i].x >= DISPLAY_WIDTH || sprite_pos[i].x <= 0) {
sprite_dir[i].x = -sprite_dir[i].x;
sprite_pos[i].x += sprite_dir[i].x;
}
if (sprite_pos[i].y >= DISPLAY_HEIGHT || sprite_pos[i].y <= 0) {
sprite_dir[i].y = -sprite_dir[i].y;
sprite_pos[i].y += sprite_dir[i].y;
}
}
sleep_ms(16);
}
}

Wyświetl plik

@ -49,7 +49,7 @@ int main() {
gpio_set_dir(BUTTON_A, GPIO_IN);
gpio_pull_up(BUTTON_A);
sleep_ms(5000);
//sleep_ms(5000);
DVDisplay display;
display.init(DISPLAY_WIDTH, DISPLAY_HEIGHT, DVDisplay::MODE_RGB888, FRAME_WIDTH, FRAME_HEIGHT);