Re: Native C module: accessing objects
Posted: Mon Sep 07, 2020 6:43 pm
How about you just take the existing framebuf module, rename it and build on top of it?
Please see the new forum at
https://forum.micropython.org/
How about you just take the existing framebuf module, rename it and build on top of it?
The underlying issue here is that without a loader/symbol table, there's no way for your .mpy to be able to know the location of the existing framebuf code. We work around this for the core functionality by providing mp_fun_table. It's not really clear what the best way to support this -- there's a long list of "core adjacent" functionality (like framebuf), as well as things like port-specific HAL functionality (see below).pythoncoder wrote: ↑Tue Sep 08, 2020 8:15 amI was hoping to avoid having users build the firmware: this is a significant barrier for many people.
As it stands, this doesn't quite solve Peter's problem as it provides port-specific functionality, but the same mechanism could maybe be used.chibill wrote: ↑Tue Sep 08, 2020 8:12 pmIf https://github.com/micropython/micropython/pull/5711 ever gets looked at this will be possible I think.
But framebuf is a loadable module now?pythoncoder wrote: ↑Tue Sep 08, 2020 8:15 amI was hoping to avoid having users build the firmware: this is a significant barrier for many people.
Code: Select all
import framebuf_r
import framebuf
# Emulate a display driver subclassed from framebuf.FrameBuffer
db = bytearray(40 * 80 * 2)
device = framebuf.FrameBuffer(db, 40, 80, framebuf.RGB565)
def foo():
width = 20 # Glyph dimensions
height = 40
i = 0
while True:
# Source monochrome glyph
buf = bytearray(width * height // 8)
fbc = framebuf_r.FrameBuffer(buf, width, height, framebuf_r.MONO_HMSB)
# Destination: temporary color frame buffer for the glyph
bufd = bytearray(width * height * 2)
fbd = framebuf_r.FrameBuffer(bufd, width, height, framebuf_r.RGB565)
# Render it in specified colors to the temporary buffer
fbd.render(fbc, 0, 0, 0x5555, 0xaaaa) # fbc must be a framebuf_r otherwise we get a TypeError
# Instantiate a FrameBuffer pointed at color glyph
# Cannot be a framebuf_r
fbx = framebuf.FrameBuffer(bufd, width, height, framebuf.RGB565)
device.blit(fbx, 0, 0)
i += 1
print(i)
Code: Select all
#define MICROPY_PY_FRAMEBUF (1)
#include "py/dynruntime.h"
#if !defined(__linux__)
void *memset(void *s, int c, size_t n) {
return mp_fun_table.memset_(s, c, n);
}
#endif
mp_obj_type_t mp_type_framebuf;
#include "extmod/modframebuf.c"
// render(mono_framebuf, x, y, fgcolor, bgcolor=0)
STATIC mp_obj_t framebuf_render(size_t n_args, const mp_obj_t *args) {
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf));
if (source_in == MP_OBJ_NULL) {
mp_raise_TypeError(NULL);
}
mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in);
mp_int_t x = mp_obj_get_int(args[2]);
mp_int_t y = mp_obj_get_int(args[3]);
mp_int_t fgcol = mp_obj_get_int(args[4]);
mp_int_t bgcol = 0;
if (n_args > 5) {
bgcol = mp_obj_get_int(args[5]);
}
if (
(x >= self->width) ||
(y >= self->height) ||
(-x >= source->width) ||
(-y >= source->height)
) {
// Out of bounds, no-op.
return mp_const_none;
}
// Clip.
int x0 = MAX(0, x);
int y0 = MAX(0, y);
int x1 = MAX(0, -x);
int y1 = MAX(0, -y);
int x0end = MIN(self->width, x + source->width);
int y0end = MIN(self->height, y + source->height);
for (; y0 < y0end; ++y0) {
int cx1 = x1;
for (int cx0 = x0; cx0 < x0end; ++cx0) {
uint32_t col = getpixel(source, cx1, y1);
if (col == 0) {
setpixel(self, cx0, y0, bgcol);
}
else {
setpixel(self, cx0, y0, fgcol);
}
++cx1;
}
++y1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_render_obj, 5, 6, framebuf_render);
mp_map_elem_t framebuf_locals_dict_table[11];
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
mp_type_framebuf.base.type = (void*)&mp_type_type;
mp_type_framebuf.name = MP_QSTR_FrameBuffer;
mp_type_framebuf.make_new = framebuf_make_new;
mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer;
framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) };
framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) };
framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) };
framebuf_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_hline), MP_OBJ_FROM_PTR(&framebuf_hline_obj) };
framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) };
framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) };
framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) };
framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_render), MP_OBJ_FROM_PTR(&framebuf_render_obj) };
mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict;
mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf));
mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj));
mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB));
mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB));
mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8));
mp_store_global(MP_QSTR_MONO_HLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB));
mp_store_global(MP_QSTR_MONO_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB));
MP_DYNRUNTIME_INIT_EXIT
}