DV Display: Support multiple scroll offsets

dv_stick
Mike Bell 2023-07-01 00:03:11 +01:00 zatwierdzone przez Phil Howard
rodzic b9cd998709
commit 3c2c7ccc94
5 zmienionych plików z 1829 dodań i 1759 usunięć

Wyświetl plik

@ -119,7 +119,7 @@ namespace pimoroni {
while (gpio_get(VSYNC) == 0);
gpio_put(RAM_SEL, bank);
if (rewrite_header) {
write_header();
set_scroll_idx_for_lines(-1, 0, display_height);
rewrite_header = false;
}
}
@ -128,9 +128,35 @@ namespace pimoroni {
swd_reset();
}
void DVDisplay::set_display_offset(const Point& p) {
void DVDisplay::set_display_offset(const Point& p, int idx) {
int32_t offset = (int32_t)point_to_address(p) - (int32_t)point_to_address({0,0});
i2c->write_bytes(I2C_ADDR, I2C_REG_SCROLL, (uint8_t*)&offset, 4);
i2c->write_bytes(I2C_ADDR, I2C_REG_SCROLL_BASE + 4*(idx-1), (uint8_t*)&offset, 4);
}
void DVDisplay::set_scroll_idx_for_lines(int idx, int miny, int maxy) {
constexpr int buf_size = 32;
uint32_t buf[buf_size];
uint addr = 4 * (7 + miny);
uint line_type = (uint)mode << 28;
if (idx >= 0) line_type |= (uint)idx << 30;
for (int i = miny; i < maxy; i += buf_size) {
int maxj = std::min(buf_size, maxy - i);
if (idx >= 0) {
for (int j = 0; j < maxj; ++j) {
buf[j] = line_type + ((uint32_t)h_repeat << 24) + ((i + j) * frame_width * 6) + base_address;
}
}
else {
ram.read_blocking(addr, buf, maxj);
for (int j = 0; j < maxj; ++j) {
buf[j] &= 0xC0000000;
buf[j] |= line_type + ((uint32_t)h_repeat << 24) + ((i + j) * frame_width * 6) + base_address;
}
}
ram.write(addr, buf, maxj * 4);
ram.wait_for_finish_blocking();
addr += 4 * maxj;
}
}
uint8_t DVDisplay::get_gpio() {
@ -294,7 +320,7 @@ namespace pimoroni {
{
mode = new_mode;
rewrite_header = true;
write_header();
set_scroll_idx_for_lines(-1, 0, display_height);
if (mode == MODE_PALETTE) {
write_palette();
}
@ -381,19 +407,7 @@ namespace pimoroni {
void DVDisplay::write_header()
{
write_header_preamble();
uint32_t buf[8];
uint addr = 4 * 7;
uint line_type = 0x80000000u + ((uint)mode << 28);
mp_printf(&mp_plat_print, "Write header, line type %08x\n", line_type);
for (int i = 0; i < display_height; i += 8) {
for (int j = 0; j < 8; ++j) {
buf[j] = line_type + ((uint32_t)h_repeat << 24) + ((i + j) * frame_width * 6) + base_address;
}
ram.write(addr, buf, 8 * 4);
ram.wait_for_finish_blocking();
addr += 4 * 8;
}
set_scroll_idx_for_lines(1, 0, display_height);
}
uint32_t DVDisplay::point_to_address(const Point& p) const {

Wyświetl plik

@ -31,8 +31,8 @@ namespace pimoroni {
// I2C address and registers
static constexpr uint I2C_ADDR = 0x0D;
static constexpr uint I2C_REG_SET_RES = 0xF8;
static constexpr uint I2C_REG_START = 0xF9;
static constexpr uint I2C_REG_SET_RES = 0xFC;
static constexpr uint I2C_REG_START = 0xFD;
static constexpr uint I2C_REG_GPIO = 0xC0;
static constexpr uint I2C_REG_LED = 0xC1;
static constexpr uint I2C_REG_GPIO_HI = 0xC8;
@ -41,7 +41,7 @@ namespace pimoroni {
static constexpr uint I2C_REG_GPIO_HI_PULL_UP = 0xCB;
static constexpr uint I2C_REG_GPIO_HI_PULL_DOWN = 0xCC;
static constexpr uint I2C_REG_EDID = 0xED;
static constexpr uint I2C_REG_SCROLL = 0xF0;
static constexpr uint I2C_REG_SCROLL_BASE = 0xF0;
//--------------------------------------------------
// Variables
@ -146,9 +146,14 @@ namespace pimoroni {
void write_palette_pixel_span(const Point &p, uint l, uint8_t* data);
void read_palette_pixel_span(const Point &p, uint l, uint8_t *data);
// Set the top left corner of the display within the frame, if a larger
// frame is specified than the display.
void set_display_offset(const Point& p);
// Set the scroll offset for a set of scanlines on the display. There are 3 scroll offsets, indexes 1-3.
// By default, all scanlines are offset by scroll idx 1, so setting this effectively moves the
// top left corner of the display within the frame.
void set_display_offset(const Point& p, int idx=1);
// Configure the scroll offset index to use for a set of scanlines (inclusive of miny, exclusive of maxy),
// this applies to the current bank only - you need to set again after flipping to apply the same setting to the other bank.
void set_scroll_idx_for_lines(int idx, int miny, int maxy);
uint8_t get_gpio();
uint8_t get_gpio_hi();

Wyświetl plik

@ -13,7 +13,7 @@ using namespace pimoroni;
#define DISPLAY_HEIGHT 480
#define FRAME_WIDTH 1000
#define FRAME_HEIGHT 480
#define FRAME_HEIGHT 600
#define READ_EDID 0
#if READ_EDID
@ -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);
@ -90,18 +90,23 @@ int main() {
printf(".\n");
graphics.clear();
printf("..\n");
display.set_scroll_idx_for_lines(0, 100, 200);
display.set_scroll_idx_for_lines(2, 300, FRAME_HEIGHT);
display.flip();
printf("...\n");
sleep_ms(2000);
graphics.set_pen(0, 0, 0xFF);
graphics.clear();
display.set_scroll_idx_for_lines(0, 100, 200);
display.set_scroll_idx_for_lines(2, 300, FRAME_HEIGHT);
display.flip();
printf("Starting\n");
graphics.set_font("bitmap8");
Point scroll = {0, 0};
int scroll_dir = 1;
Point scroll1 = {0, 0};
Point scroll2 = {0, 0};
int scroll_dir[2] = {1,1};
constexpr int NUM_CIRCLES = 50;
struct Circle {
@ -204,20 +209,18 @@ int main() {
//printf("%02x %02x\n", display.get_gpio(), display.get_gpio_hi());
display.set_display_offset(scroll);
#if 1
scroll.x += scroll_dir;
if (scroll.x + DISPLAY_WIDTH > FRAME_WIDTH || scroll.x < 0) {
scroll_dir = -scroll_dir;
scroll.x += scroll_dir;
display.set_display_offset(scroll1, 1);
display.set_display_offset(scroll2, 2);
scroll1.x += scroll_dir[0];
if (scroll1.x + DISPLAY_WIDTH > FRAME_WIDTH || scroll1.x < 0) {
scroll_dir[0] = -scroll_dir[0];
scroll1.x += scroll_dir[0];
}
#else
scroll.y += scroll_dir;
if (scroll.y + DISPLAY_HEIGHT > FRAME_HEIGHT || scroll.y < 0) {
scroll_dir = -scroll_dir;
scroll.y += scroll_dir;
scroll2.y += scroll_dir[1];
if (scroll2.y + DISPLAY_HEIGHT > FRAME_HEIGHT || scroll2.y < 0) {
scroll_dir[1] = -scroll_dir[1];
scroll2.y += scroll_dir[1];
}
#endif
++frames;
display.set_gpio_hi_pull_up_all(frames & 0x3F);