latest round of changes
This commit is contained in:
parent
dc415872e6
commit
e549bd915c
|
@ -6,7 +6,11 @@
|
|||
|
||||
#include "bindings/videocore/Sprite.h"
|
||||
#include "shared-bindings/displayio/Bitmap.h"
|
||||
#include "shared-module/displayio/Group.h"
|
||||
#include "shared-bindings/displayio/Group.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/displayio/TileGrid.h"
|
||||
#include "shared-bindings/displayio/Palette.h"
|
||||
|
||||
#include "bindings/videocore/hvs.h"
|
||||
#include "bindings/videocore/Hvs.h"
|
||||
|
@ -17,7 +21,6 @@ volatile uint32_t* dlist_memory = (volatile uint32_t*)SCALER5_LIST_MEMORY;
|
|||
volatile uint32_t* dlist_memory = (volatile uint32_t*)SCALER_LIST_MEMORY;
|
||||
#endif
|
||||
|
||||
extern const mp_obj_type_t hvs_channel_type;
|
||||
volatile struct hvs_channel *hvs_hw_channels = (volatile struct hvs_channel*)SCALER_DISPCTRL0;
|
||||
uint32_t dlist_slot = 128; // start a bit in, to not trash the firmware list
|
||||
|
||||
|
@ -37,12 +40,21 @@ hvs_channel_t hvs_channels[3] = {
|
|||
};
|
||||
|
||||
static mp_obj_t c_set_sprite_list(mp_obj_t self_in, mp_obj_t list) {
|
||||
mp_obj_t *unique_palettes = mp_obj_new_set(0, NULL);
|
||||
hvs_channel_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t sprite_list = mp_arg_validate_type(list, &mp_type_list, MP_QSTR_sprites);
|
||||
size_t len = 0;
|
||||
mp_obj_t *items;
|
||||
mp_obj_list_get(sprite_list, &len, &items);
|
||||
// first loop, find unique palettes
|
||||
for (uint32_t i=0; i<len; i++) {
|
||||
mp_obj_t sprite = mp_arg_validate_type(items[i], &hvs_sprite_type, MP_QSTR_todo);
|
||||
sprite_t *s = MP_OBJ_TO_PTR(sprite);
|
||||
if (s->palette) mp_obj_set_store(unique_palettes, s->palette);
|
||||
}
|
||||
// TODO, copy each palette to the dlist memory and set sprite->palette_addr to the addr its copied to
|
||||
uint32_t needed_slots = 1; // one more, to terminate the list
|
||||
// second loop, regenerate any display lists and count the total size
|
||||
for (uint32_t i=0; i<len; i++) {
|
||||
mp_obj_t sprite = mp_arg_validate_type(items[i], &hvs_sprite_type, MP_QSTR_todo);
|
||||
sprite_t *s = MP_OBJ_TO_PTR(sprite);
|
||||
|
@ -54,10 +66,10 @@ static mp_obj_t c_set_sprite_list(mp_obj_t self_in, mp_obj_t list) {
|
|||
mp_raise_ValueError(translate("too many sprites, unable to pageflip reliably"));
|
||||
}
|
||||
if ((dlist_slot + needed_slots) > 4096) {
|
||||
// early loop)
|
||||
dlist_slot = 128;
|
||||
}
|
||||
uint32_t starting_slot = dlist_slot;
|
||||
// third loop, copy dlist fragments to hw
|
||||
for (uint32_t i=0; i<len; i++) {
|
||||
mp_obj_t sprite = mp_arg_validate_type(items[i], &hvs_sprite_type, MP_QSTR_todo);
|
||||
sprite_t *s = MP_OBJ_TO_PTR(sprite);
|
||||
|
@ -80,7 +92,71 @@ static mp_obj_t c_set_sprite_list(mp_obj_t self_in, mp_obj_t list) {
|
|||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
static mp_obj_t c_hvs_show(mp_obj_t self_in, mp_obj_t root_group_in) {
|
||||
mp_obj_list_t *sprites = mp_obj_new_list(0, NULL);
|
||||
|
||||
hvs_channel_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
displayio_group_t *root_group = mp_arg_validate_type(root_group_in, &displayio_group_type, MP_QSTR_bitmap);
|
||||
printf("hvs channel: %ld\n", self->channel);
|
||||
printf("root group x: %d y: %d\n", root_group->x, root_group->y);
|
||||
printf("group scale (not implemented): %d\n", root_group->scale);
|
||||
size_t len = 0;
|
||||
mp_obj_t *items;
|
||||
mp_obj_list_get(root_group->members, &len, &items);
|
||||
printf("%d elements\n", len);
|
||||
for (uint i=0; i<len; i++) {
|
||||
printf("%d: %p\n", i, mp_obj_get_type(items[i]));
|
||||
if (mp_obj_get_type(items[i]) == &displayio_tilegrid_type) {
|
||||
displayio_tilegrid_t *tg = mp_arg_validate_type(items[i], &displayio_tilegrid_type, MP_QSTR_tilegrid);
|
||||
displayio_bitmap_t *bitmap = mp_arg_validate_type(tg->bitmap, &displayio_bitmap_type, MP_QSTR_bitmap);
|
||||
uint8_t *arr;
|
||||
if (tg->inline_tiles) arr = (uint8_t*)&tg->tiles;
|
||||
else arr = tg->tiles;
|
||||
/*
|
||||
printf("found tilegrid: %p\n", tg);
|
||||
printf("x %d, y %d\n", tg->x, tg->y);
|
||||
printf("w %d, h %d\n", tg->width_in_tiles, tg->height_in_tiles);
|
||||
printf("w %d, h %d\n", tg->pixel_width, tg->pixel_height);
|
||||
printf("w %d, h %d\n", tg->tile_width, tg->tile_height);
|
||||
printf("shader type: %p\n", mp_obj_get_type(tg->pixel_shader));
|
||||
*/
|
||||
enum hvs_pixel_format format = HVS_PIXEL_FORMAT_RGB332;
|
||||
int order = HVS_PIXEL_ORDER_ABGR;
|
||||
if (mp_obj_get_type(tg->pixel_shader) == &displayio_palette_type) {
|
||||
puts("tg uses a palette");
|
||||
format = HVS_PIXEL_FORMAT_PALETTE;
|
||||
}
|
||||
for (uint row=0; row < tg->height_in_tiles; row++) {
|
||||
for (uint col=0; col < tg->width_in_tiles; col++) {
|
||||
uint tile_offset = col + (row * tg->width_in_tiles);
|
||||
sprite_t *sprite = mp_obj_malloc(sprite_t, &hvs_sprite_type);
|
||||
sprite->bitmap = bitmap;
|
||||
if (format == HVS_PIXEL_FORMAT_PALETTE) sprite->palette = tg->pixel_shader;
|
||||
else sprite->palette = NULL;
|
||||
sprite->x = root_group->x + tg->x + (col * tg->tile_width);
|
||||
sprite->y = root_group->y + tg->y + (row * tg->tile_height);
|
||||
uint tile = arr[tile_offset];
|
||||
sprite->x_offset = (tile % tg->bitmap_width_in_tiles) * tg->tile_width;
|
||||
sprite->y_offset = (tile / tg->bitmap_width_in_tiles) * tg->tile_height;
|
||||
sprite->width = tg->tile_width;
|
||||
sprite->height = tg->tile_height;
|
||||
sprite->dirty = true;
|
||||
sprite->color_order = order;
|
||||
sprite->pixel_format = format;
|
||||
mp_obj_list_append(sprites, sprite);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
puts("unexpected item in group");
|
||||
}
|
||||
}
|
||||
c_set_sprite_list(self_in, sprites);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(fun_set_sprite_list, c_set_sprite_list);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(fun_hvs_show, c_hvs_show);
|
||||
|
||||
#define simpleprop(name) \
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(fun_get_##name, c_getter_##name); \
|
||||
|
@ -104,15 +180,32 @@ static mp_obj_t c_getter_enabled(mp_obj_t self_in) {
|
|||
return mp_obj_new_bool(ctrl & SCALER_DISPCTRLX_ENABLE);
|
||||
}
|
||||
|
||||
static mp_obj_t c_getter_frame(mp_obj_t self_in) {
|
||||
hvs_channel_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uint32_t stat = hvs_hw_channels[self->channel].dispstat;
|
||||
return MP_OBJ_NEW_SMALL_INT((stat >> 12) & 0x3f);
|
||||
}
|
||||
|
||||
static mp_obj_t c_getter_scanline(mp_obj_t self_in) {
|
||||
hvs_channel_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uint32_t stat = hvs_hw_channels[self->channel].dispstat;
|
||||
return MP_OBJ_NEW_SMALL_INT(stat & 0xfff);
|
||||
}
|
||||
|
||||
simpleprop(width);
|
||||
simpleprop(height);
|
||||
simpleprop(enabled);
|
||||
simpleprop(frame);
|
||||
simpleprop(scanline);
|
||||
|
||||
static const mp_rom_map_elem_t hvs_channel_locals_dict_table[] = {
|
||||
prop_entry(width),
|
||||
prop_entry(height),
|
||||
prop_entry(enabled),
|
||||
prop_entry(frame),
|
||||
prop_entry(scanline),
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_sprite_list), MP_ROM_PTR(&fun_set_sprite_list) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&fun_hvs_show) },
|
||||
};
|
||||
|
||||
static MP_DEFINE_CONST_DICT(hvs_channel_locals_dict, hvs_channel_locals_dict_table);
|
||||
|
|
|
@ -6,3 +6,4 @@ typedef struct {
|
|||
} hvs_channel_t;
|
||||
|
||||
extern hvs_channel_t hvs_channels[3];
|
||||
extern const mp_obj_type_t hvs_channel_type;
|
||||
|
|
|
@ -31,27 +31,58 @@ enum hvs_pixel_format bitmap_to_hvs(const displayio_bitmap_t *bitmap) {
|
|||
#error not implemented yet
|
||||
#else
|
||||
void hvs_regen_noscale_noviewport(sprite_t *s) {
|
||||
printf("xoffset: %ld yoffset: %ld\n", s->x_offset, s->y_offset);
|
||||
uint32_t *d = s->dlist;
|
||||
uint32_t phys_addr = (uint32_t)s->bitmap->data; // assumes identity map, should be physical addr
|
||||
int bytes_per_pixel = s->bitmap->bits_per_value / 8;
|
||||
uint stride = s->bitmap->stride * 4;
|
||||
phys_addr += bytes_per_pixel * s->x_offset;
|
||||
phys_addr += stride * s->y_offset;
|
||||
uint size = 7;
|
||||
if (s->pixel_format == HVS_PIXEL_FORMAT_PALETTE) size = 8;
|
||||
// CTL0
|
||||
d[0] = CONTROL_VALID
|
||||
| CONTROL_PIXEL_ORDER(s->color_order)
|
||||
| CONTROL_UNITY
|
||||
| CONTROL_FORMAT(s->pixel_format)
|
||||
| CONTROL_WORDS(7);
|
||||
| CONTROL_WORDS(size);
|
||||
// POS0
|
||||
d[1] = POS0_X(s->x) | POS0_Y(s->y) | POS0_ALPHA(0xff);
|
||||
// POS2, input size
|
||||
d[2] = POS2_H(s->bitmap->height) | POS2_W(s->bitmap->width) | (s->alpha_mode << 30);
|
||||
d[2] = POS2_H(s->height) | POS2_W(s->width) | (s->alpha_mode << 30);
|
||||
// POS3, context
|
||||
d[3] = 0xDEADBEEF;
|
||||
// PTR0
|
||||
d[4] = ((uint32_t)s->bitmap->data) // assumes identity map, should be physical addr
|
||||
d[4] = phys_addr
|
||||
| 0xc0000000; // and tell HVS to do uncached reads
|
||||
// context 0
|
||||
d[5] = 0xDEADBEEF;
|
||||
// pitch 0
|
||||
d[6] = s->bitmap->stride * 4;
|
||||
|
||||
d[6] = stride;
|
||||
if (s->pixel_format == HVS_PIXEL_FORMAT_PALETTE) {
|
||||
// https://github.com/librerpi/rpi-open-firmware/blob/93dc394d33f54a59a25a087213f46a20f5aad327/docs/hvs.txt#L107-L112
|
||||
uint bitsize;
|
||||
switch (s->bitmap->bits_per_value) {
|
||||
case 1:
|
||||
bitsize = 0;
|
||||
break;
|
||||
case 2:
|
||||
bitsize = 1;
|
||||
break;
|
||||
case 4:
|
||||
bitsize = 2;
|
||||
break;
|
||||
case 8:
|
||||
bitsize = 3;
|
||||
break;
|
||||
default:
|
||||
d[0] = 0;
|
||||
return;
|
||||
}
|
||||
uint initial_pixel_offset = 0;
|
||||
uint order = 0;
|
||||
d[7] = (bitsize << 30) | (initial_pixel_offset << 27) | (order << 26) | (s->palette_addr << 2);
|
||||
}
|
||||
//printf("w: %d, h: %d, stride: %d, bits per value: %d\n", s->bitmap->width, s->bitmap->height, s->bitmap->stride, s->bitmap->bits_per_value);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -11,10 +11,14 @@ typedef struct {
|
|||
uint32_t height;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t x_offset;
|
||||
uint32_t y_offset;
|
||||
uint32_t dlist[32];
|
||||
enum alpha_mode alpha_mode;
|
||||
uint32_t color_order;
|
||||
uint32_t palette_addr;
|
||||
enum hvs_pixel_format pixel_format;
|
||||
mp_obj_t palette;
|
||||
} sprite_t;
|
||||
|
||||
extern const mp_obj_type_t hvs_sprite_type;
|
||||
|
|
|
@ -23,9 +23,19 @@ def gif_animate():
|
|||
|
||||
x = 5
|
||||
y = 5
|
||||
lastframe = videocore.HvsChannel1.frame
|
||||
start = time.monotonic()
|
||||
|
||||
while True:
|
||||
framedelta = videocore.HvsChannel1.frame - lastframe
|
||||
lastframe = videocore.HvsChannel1.frame
|
||||
#print(f"delta: {framedelta} scanline: {videocore.HvsChannel1.scanline}/{videocore.HvsChannel1.height} overhead: {overhead} next: {next_delay}")
|
||||
end = time.monotonic()
|
||||
overhead = end - start
|
||||
|
||||
time.sleep(max(0, next_delay - overhead))
|
||||
|
||||
start = time.monotonic()
|
||||
next_delay = gif.next_frame()
|
||||
if (x > 0) and (x < xmax):
|
||||
x += xinc
|
||||
|
@ -45,10 +55,7 @@ def gif_animate():
|
|||
y = 0
|
||||
sprite.x = x
|
||||
sprite.y = y
|
||||
start = time.monotonic()
|
||||
videocore.HvsChannel1.set_sprite_list([sprite])
|
||||
end = time.monotonic()
|
||||
refresh = end-start
|
||||
#print("refresh time:")
|
||||
#print(refresh)
|
||||
|
||||
|
@ -80,7 +87,29 @@ def many_formats():
|
|||
format4 = make_color_sweep(4, dist * 3, color_order=3, red_start=0, red_max=31, green_start=5, green_max=63, blue_start = 11, blue_max=31)
|
||||
videocore.HvsChannel1.set_sprite_list([format1, format2, format3, format4])
|
||||
|
||||
#many_formats()
|
||||
gif_animate()
|
||||
def tilegrid():
|
||||
import adafruit_imageload
|
||||
import displayio
|
||||
import board
|
||||
# https://learn.adafruit.com/circuitpython-display-support-using-displayio/sprite-sheet
|
||||
sprite_sheet, palette = adafruit_imageload.load("/cp_sprite_sheet.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
|
||||
sprite = displayio.TileGrid(sprite_sheet, pixel_shader=palette, width=2, height=2, tile_width=16, tile_height=16)
|
||||
group = displayio.Group(scale=8)
|
||||
group.append(sprite)
|
||||
display = board.DISPLAY
|
||||
group.x = 30
|
||||
group.y = 30
|
||||
for i in range(30):
|
||||
sprite[0] = i % 6
|
||||
sprite[1] = (i+1) % 6
|
||||
sprite[2] = (i+2) % 6
|
||||
sprite[3] = (i+3) % 6
|
||||
for j in range(100):
|
||||
group.x = j
|
||||
display.show(group)
|
||||
return
|
||||
time.sleep(0.01)
|
||||
|
||||
print("Hello World!")
|
||||
#many_formats()
|
||||
#gif_animate()
|
||||
tilegrid()
|
||||
|
|
|
@ -30,8 +30,14 @@
|
|||
#include "bindings/videocore/Framebuffer.h"
|
||||
#include "shared-module/displayio/__init__.h"
|
||||
#include "shared-bindings/framebufferio/FramebufferDisplay.h"
|
||||
#include "bindings/videocore/Hvs.h"
|
||||
|
||||
void board_init(void) {
|
||||
hvs_channel_t *display = &allocate_display()->hvs_display;
|
||||
display->channel = 1;
|
||||
display->base.type = &hvs_channel_type;
|
||||
return;
|
||||
/*
|
||||
videocore_framebuffer_obj_t *fb = &allocate_display_bus()->videocore;
|
||||
fb->base.type = &videocore_framebuffer_type;
|
||||
common_hal_videocore_framebuffer_construct(fb, 640, 480);
|
||||
|
@ -43,6 +49,7 @@ void board_init(void) {
|
|||
MP_OBJ_FROM_PTR(fb),
|
||||
0,
|
||||
true);
|
||||
*/
|
||||
}
|
||||
|
||||
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.
|
||||
|
|
|
@ -60,7 +60,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
|||
// there is room for a 6bit int to be smuggled across reset, look into using that
|
||||
}
|
||||
|
||||
|
||||
// https://learn.adafruit.com/circuitpython-essentials/circuitpython-resetting
|
||||
void common_hal_mcu_reset(void) {
|
||||
common_hal_mcu_disable_interrupts();
|
||||
*REG32(PM_WDOG) = PM_PASSWORD | (1 & PM_WDOG_MASK);
|
||||
|
|
|
@ -38,7 +38,7 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_
|
|||
mp_obj_t pixel_shader, uint16_t width, uint16_t height,
|
||||
uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) {
|
||||
uint32_t total_tiles = width * height;
|
||||
// Sprites will only have one tile so save a little memory by inlining values in the pointer.
|
||||
// Sprites with only have one tile so save a little memory by inlining values in the pointer.
|
||||
uint8_t inline_tiles = sizeof(uint8_t *);
|
||||
if (total_tiles <= inline_tiles) {
|
||||
self->tiles = 0;
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef struct {
|
|||
mp_obj_t pixel_shader;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint16_t pixel_width;
|
||||
uint16_t pixel_width; // of the entire grid, covering width_in_tiles tiles
|
||||
uint16_t pixel_height;
|
||||
uint16_t bitmap_width_in_tiles;
|
||||
;
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
// Port unique frame buffers.
|
||||
#if CIRCUITPY_VIDEOCORE
|
||||
#include "bindings/videocore/Framebuffer.h"
|
||||
#include "bindings/videocore/Hvs.h"
|
||||
#endif
|
||||
#if CIRCUITPY_PICODVI
|
||||
#include "bindings/picodvi/Framebuffer.h"
|
||||
|
@ -88,6 +89,7 @@ typedef struct {
|
|||
displayio_epaperdisplay_obj_t epaper_display;
|
||||
#if CIRCUITPY_FRAMEBUFFERIO
|
||||
framebufferio_framebufferdisplay_obj_t framebuffer_display;
|
||||
hvs_channel_t hvs_display;
|
||||
#endif
|
||||
};
|
||||
} primary_display_t;
|
||||
|
|
Loading…
Reference in New Issue