forked from micropython/micropython
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
337b800
commit eff21fc
Showing
6 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
|
||
#include "py/obj.h" | ||
#include "py/objproperty.h" | ||
|
||
#include "bindings/videocore/Sprite.h" | ||
#include "shared-bindings/displayio/Bitmap.h" | ||
#include "py/runtime.h" | ||
|
||
#include "bindings/videocore/hvs.h" | ||
#include "bindings/videocore/Hvs.h" | ||
|
||
#if BCM_VERSION == 2711 | ||
volatile uint32_t* dlist_memory = (volatile uint32_t*)SCALER5_LIST_MEMORY; | ||
#else | ||
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 | ||
|
||
hvs_channel_t hvs_channels[3] = { | ||
[0] = { | ||
.base.type = &hvs_channel_type, | ||
.channel = 0, | ||
}, | ||
[1] = { | ||
.base.type = &hvs_channel_type, | ||
.channel = 1, | ||
}, | ||
[2] = { | ||
.base.type = &hvs_channel_type, | ||
.channel = 2, | ||
}, | ||
}; | ||
|
||
static mp_obj_t c_set_sprite_list(mp_obj_t self_in, mp_obj_t list) { | ||
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); | ||
uint32_t needed_slots = 1; // one more, to terminate the list | ||
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); | ||
c_maybe_regen(sprite); | ||
uint8_t length = (s->dlist[0] >> 24) & 0x3f; | ||
needed_slots += length; | ||
} | ||
if (needed_slots > (4096/2)) { | ||
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; | ||
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); | ||
uint8_t length = (s->dlist[0] >> 24) & 0x3f; | ||
for (int j=0; j<length; j++) { | ||
dlist_memory[dlist_slot++] = s->dlist[j]; | ||
} | ||
} | ||
dlist_memory[dlist_slot++] = CONTROL_END; | ||
switch (self->channel) { | ||
case 0: | ||
*((volatile uint32_t*)SCALER_DISPLIST0) = starting_slot; | ||
break; | ||
case 1: | ||
*((volatile uint32_t*)SCALER_DISPLIST1) = starting_slot; | ||
break; | ||
case 2: | ||
*((volatile uint32_t*)SCALER_DISPLIST2) = starting_slot; | ||
break; | ||
} | ||
return mp_const_none; | ||
} | ||
MP_DEFINE_CONST_FUN_OBJ_2(fun_set_sprite_list, c_set_sprite_list); | ||
|
||
#define simpleprop(name) \ | ||
static MP_DEFINE_CONST_FUN_OBJ_1(fun_get_##name, c_getter_##name); \ | ||
static MP_PROPERTY_GETTER(prop_##name, (mp_obj_t)&fun_get_##name) | ||
|
||
#define prop_entry(name) { MP_ROM_QSTR(MP_QSTR_##name), MP_ROM_PTR(&prop_##name) } | ||
|
||
static mp_obj_t c_getter_width(mp_obj_t self_in) { | ||
hvs_channel_t *self = MP_OBJ_TO_PTR(self_in); | ||
uint32_t ctrl = hvs_hw_channels[self->channel].dispctrl; | ||
return MP_OBJ_NEW_SMALL_INT((ctrl >> 12) & 0xfff); | ||
} | ||
static mp_obj_t c_getter_height(mp_obj_t self_in) { | ||
hvs_channel_t *self = MP_OBJ_TO_PTR(self_in); | ||
uint32_t ctrl = hvs_hw_channels[self->channel].dispctrl; | ||
return MP_OBJ_NEW_SMALL_INT(ctrl & 0xfff); | ||
} | ||
static mp_obj_t c_getter_enabled(mp_obj_t self_in) { | ||
hvs_channel_t *self = MP_OBJ_TO_PTR(self_in); | ||
uint32_t ctrl = hvs_hw_channels[self->channel].dispctrl; | ||
return mp_obj_new_bool(ctrl & SCALER_DISPCTRLX_ENABLE); | ||
} | ||
|
||
simpleprop(width); | ||
simpleprop(height); | ||
simpleprop(enabled); | ||
|
||
static const mp_rom_map_elem_t hvs_channel_locals_dict_table[] = { | ||
prop_entry(width), | ||
prop_entry(height), | ||
prop_entry(enabled), | ||
{ MP_ROM_QSTR(MP_QSTR_set_sprite_list), MP_ROM_PTR(&fun_set_sprite_list) }, | ||
}; | ||
|
||
static MP_DEFINE_CONST_DICT(hvs_channel_locals_dict, hvs_channel_locals_dict_table); | ||
|
||
const mp_obj_type_t hvs_channel_type = { | ||
{ &mp_type_type }, | ||
.name = MP_QSTR_HvsChannel, | ||
.locals_dict = (mp_obj_dict_t*)&hvs_channel_locals_dict, | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#pragma once | ||
|
||
typedef struct { | ||
mp_obj_base_t base; | ||
uint32_t channel; | ||
} hvs_channel_t; | ||
|
||
extern hvs_channel_t hvs_channels[3]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
|
||
#include "py/obj.h" | ||
#include "py/objproperty.h" | ||
|
||
#include "bindings/videocore/Sprite.h" | ||
#include "py/runtime.h" | ||
|
||
|
||
STATIC mp_obj_t hvs_sprite_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { | ||
sprite_t *sprite = m_new_obj(sprite_t); | ||
sprite->base.type = &hvs_sprite_type; | ||
sprite->bitmap = NULL; | ||
sprite->dirty = true; | ||
sprite->alpha_mode = alpha_mode_fixed; | ||
printf("sprite is at %p\n", sprite); | ||
return MP_OBJ_FROM_PTR(sprite); | ||
} | ||
|
||
enum hvs_pixel_format bitmap_to_hvs(const displayio_bitmap_t *bitmap) { | ||
switch (bitmap->bits_per_value) { | ||
case 16: | ||
return HVS_PIXEL_FORMAT_RGB555; | ||
} | ||
return HVS_PIXEL_FORMAT_RGB332; | ||
} | ||
|
||
#if BCM_VERSION == 2711 | ||
#error not implemented yet | ||
#else | ||
void hvs_regen_noscale_noviewport(sprite_t *s) { | ||
uint32_t *d = s->dlist; | ||
// CTL0 | ||
d[0] = CONTROL_VALID | ||
| CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR) | ||
| CONTROL_UNITY | ||
| CONTROL_FORMAT(bitmap_to_hvs(s->bitmap)) | ||
| CONTROL_WORDS(7); | ||
// 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); | ||
// POS3, context | ||
d[3] = 0xDEADBEEF; | ||
// PTR0 | ||
d[4] = ((uint32_t)s->bitmap->data) // assumes identity map, should be physical addr | ||
| 0xc0000000; // and tell HVS to do uncached reads | ||
// context 0 | ||
d[5] = 0xDEADBEEF; | ||
// pitch 0 | ||
d[6] = s->bitmap->stride * 4; | ||
|
||
//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 | ||
|
||
mp_obj_t c_maybe_regen(mp_obj_t self_in) { | ||
sprite_t *self = MP_OBJ_TO_PTR(self_in); | ||
if (self->dirty) { | ||
//printf("regen time\n"); | ||
hvs_regen_noscale_noviewport(self); | ||
self->dirty = false; | ||
} else puts("not dirty"); | ||
return mp_const_none; | ||
} | ||
MP_DEFINE_CONST_FUN_OBJ_1(fun_maybe_regen, c_maybe_regen); | ||
|
||
STATIC mp_obj_t get_image_c(mp_obj_t self_in) { | ||
sprite_t *self = MP_OBJ_TO_PTR(self_in); | ||
if (self->bitmap) return MP_OBJ_FROM_PTR(self->bitmap); | ||
else return mp_const_none; | ||
} | ||
STATIC mp_obj_t set_image_c(mp_obj_t self_in, mp_obj_t value) { | ||
displayio_bitmap_t *bitmap = mp_arg_validate_type(value, &displayio_bitmap_type, MP_QSTR_bitmap); | ||
sprite_t *self = MP_OBJ_TO_PTR(self_in); | ||
self->bitmap = bitmap; | ||
self->dirty = true; | ||
if (self->width == 0) self->width = bitmap->width; | ||
if (self->height == 0) self->height = bitmap->height; | ||
return value; | ||
} | ||
MP_DEFINE_CONST_FUN_OBJ_1(get_image_fun, get_image_c); | ||
MP_DEFINE_CONST_FUN_OBJ_2(set_image_fun, set_image_c); | ||
MP_PROPERTY_GETSET(image_prop, (mp_obj_t)&get_image_fun, (mp_obj_t)&set_image_fun); | ||
|
||
#define simpleprop(name) \ | ||
static mp_obj_t c_getter_##name(mp_obj_t self_in) { sprite_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(self->name); } \ | ||
static mp_obj_t c_setter_##name(mp_obj_t self_in, mp_obj_t value) { sprite_t *self = MP_OBJ_TO_PTR(self_in); self->name = mp_obj_get_int(value); self->dirty = true; return mp_const_none; } \ | ||
static MP_DEFINE_CONST_FUN_OBJ_1(fun_get_##name, c_getter_##name); \ | ||
static MP_DEFINE_CONST_FUN_OBJ_2(fun_set_##name, c_setter_##name); \ | ||
static MP_PROPERTY_GETSET(prop_##name, (mp_obj_t)&fun_get_##name, (mp_obj_t)&fun_set_##name) | ||
|
||
#define prop_entry(name) { MP_ROM_QSTR(MP_QSTR_##name), MP_ROM_PTR(&prop_##name) } | ||
|
||
simpleprop(width); | ||
simpleprop(height); | ||
simpleprop(x); | ||
simpleprop(y); | ||
|
||
STATIC const mp_rom_map_elem_t hvs_sprite_locals_dict_table[] = { | ||
{ MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&image_prop) }, | ||
prop_entry(width), | ||
prop_entry(height), | ||
prop_entry(x), | ||
prop_entry(y), | ||
{ MP_ROM_QSTR(MP_QSTR_maybe_regen), MP_ROM_PTR(&fun_maybe_regen) }, | ||
}; | ||
|
||
STATIC MP_DEFINE_CONST_DICT(hvs_sprite_locals_dict, hvs_sprite_locals_dict_table); | ||
|
||
const mp_obj_type_t hvs_sprite_type = { | ||
{ &mp_type_type }, | ||
.flags = 0, //MP_TYPE_FLAG_EXTENDED, | ||
.name = MP_QSTR_Sprite, | ||
.locals_dict = (mp_obj_dict_t*)&hvs_sprite_locals_dict, | ||
.make_new = hvs_sprite_make_new, | ||
//MP_TYPE_EXTENDED_FIELDS( | ||
//), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#pragma once | ||
|
||
#include "shared-bindings/displayio/Bitmap.h" | ||
#include "bindings/videocore/hvs.h" | ||
|
||
typedef struct { | ||
mp_obj_base_t base; | ||
displayio_bitmap_t *bitmap; | ||
bool dirty; | ||
uint32_t width; | ||
uint32_t height; | ||
uint32_t x; | ||
uint32_t y; | ||
uint32_t dlist[32]; | ||
enum alpha_mode alpha_mode; | ||
} sprite_t; | ||
|
||
extern const mp_obj_type_t hvs_sprite_type; | ||
mp_obj_t c_maybe_regen(mp_obj_t self_in); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters