From dddd25a776fb0d9c002c1b6b039e24bb3048e6ff Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 1 Aug 2020 12:14:55 -0500 Subject: Combine similar strings to reduce size of translations This is a slight trade-off with code size, in places where a "_varg" mp_raise variant is now used. The net savings on trinket_m0 is just 32 bytes. It also means that the translation will include the original English text, and cannot be translated. These are usually names of Python types such as int, set, or dict or special values such as "inf" or "Nan". --- py/obj.c | 6 +++--- py/objdict.c | 2 +- py/objint.c | 4 ++-- py/objlist.c | 2 +- py/objset.c | 2 +- py/runtime.c | 8 ++++++++ py/runtime.h | 1 + 7 files changed, 17 insertions(+), 8 deletions(-) (limited to 'py') diff --git a/py/obj.c b/py/obj.c index 7644b5de8..2b0c46f49 100644 --- a/py/obj.c +++ b/py/obj.c @@ -263,7 +263,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { mp_raise_TypeError(translate("can't convert to int")); } else { mp_raise_TypeError_varg( - translate("can't convert %s to int"), mp_obj_get_type_str(arg)); + translate("can't convert %s to %s"), mp_obj_get_type_str(arg), "int"); } } } @@ -326,7 +326,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { mp_raise_TypeError(translate("can't convert to float")); } else { mp_raise_TypeError_varg( - translate("can't convert %s to float"), mp_obj_get_type_str(arg)); + translate("can't convert %s to %s"), mp_obj_get_type_str(arg), "float"); } } @@ -359,7 +359,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { mp_raise_TypeError(translate("can't convert to complex")); } else { mp_raise_TypeError_varg( - translate("can't convert %s to complex"), mp_obj_get_type_str(arg)); + translate("can't convert %s to %s"), mp_obj_get_type_str(arg), "complex"); } } } diff --git a/py/objdict.c b/py/objdict.c index 39169fe1a..6ddf7ddde 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -313,7 +313,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { size_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { - mp_raise_msg(&mp_type_KeyError, translate("popitem(): dictionary is empty")); + mp_raise_msg_varg(&mp_type_KeyError, translate("pop from empty %s"), "dict"); } self->map.used--; mp_obj_t items[] = {next->key, next->value}; diff --git a/py/objint.c b/py/objint.c index 82f5aadd1..7726fb8d8 100644 --- a/py/objint.c +++ b/py/objint.c @@ -141,9 +141,9 @@ STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { mp_obj_t mp_obj_new_int_from_float(mp_float_t val) { int cl = fpclassify(val); if (cl == FP_INFINITE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, translate("can't convert inf to int"))); + mp_raise_OverflowError_varg(translate("can't convert %s to %s"), "inf", "int"); } else if (cl == FP_NAN) { - mp_raise_ValueError(translate("can't convert NaN to int")); + mp_raise_ValueError_varg(translate("can't convert %s to %s"), "NaN", "int"); } else { mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val); if (icl == MP_FP_CLASS_FIT_SMALLINT) { diff --git a/py/objlist.c b/py/objlist.c index 9242020d4..b2de72374 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -274,7 +274,7 @@ STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = mp_instance_cast_to_native_base(args[0], &mp_type_list); if (self->len == 0) { - mp_raise_IndexError(translate("pop from empty list")); + mp_raise_IndexError_varg(translate("pop from empty %s"), "list"); } size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); mp_obj_t ret = self->items[index]; diff --git a/py/objset.c b/py/objset.c index d986c6dda..82b10e7e8 100644 --- a/py/objset.c +++ b/py/objset.c @@ -368,7 +368,7 @@ STATIC mp_obj_t set_pop(mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t obj = mp_set_remove_first(&self->set); if (obj == MP_OBJ_NULL) { - mp_raise_msg(&mp_type_KeyError, translate("pop from an empty set")); + mp_raise_IndexError_varg(translate("pop from empty %s"), "set"); } return obj; } diff --git a/py/runtime.c b/py/runtime.c index 91ead1fba..c0a4f44a1 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1546,6 +1546,14 @@ NORETURN void mp_raise_IndexError(const compressed_string_t *msg) { mp_raise_msg(&mp_type_IndexError, msg); } +NORETURN void mp_raise_IndexError_varg(const compressed_string_t *fmt, ...) { + va_list argptr; + va_start(argptr,fmt); + mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_IndexError, fmt, argptr); + va_end(argptr); + nlr_raise(exception); +} + NORETURN void mp_raise_ValueError(const compressed_string_t *msg) { mp_raise_msg(&mp_type_ValueError, msg); } diff --git a/py/runtime.h b/py/runtime.h index d3a82333e..ed37f90d9 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -160,6 +160,7 @@ NORETURN void mp_raise_AttributeError(const compressed_string_t *msg); NORETURN void mp_raise_RuntimeError(const compressed_string_t *msg); NORETURN void mp_raise_ImportError(const compressed_string_t *msg); NORETURN void mp_raise_IndexError(const compressed_string_t *msg); +NORETURN void mp_raise_IndexError_varg(const compressed_string_t *msg, ...); NORETURN void mp_raise_OSError(int errno_); NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str); NORETURN void mp_raise_OSError_msg(const compressed_string_t *msg); -- cgit v1.2.3 From 67eb93fc98325697876f581c8e4879bd1b88368f Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 1 Aug 2020 13:05:30 -0500 Subject: py: introduce, use mp_raise_msg_vlist This saves a very small amount of flash, 8 bytes on trinket_m0 --- py/runtime.c | 26 ++++++++++++-------------- py/runtime.h | 1 + 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'py') diff --git a/py/runtime.c b/py/runtime.c index c0a4f44a1..87c24dc56 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1522,12 +1522,16 @@ NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_strin } } +NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, va_list argptr) { + mp_obj_t exception = mp_obj_new_exception_msg_vlist(exc_type, fmt, argptr); + nlr_raise(exception); +} + NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, ...) { va_list argptr; va_start(argptr,fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(exc_type, fmt, argptr); + mp_raise_msg_vlist(exc_type, fmt, argptr); va_end(argptr); - nlr_raise(exception); } NORETURN void mp_raise_AttributeError(const compressed_string_t *msg) { @@ -1549,9 +1553,8 @@ NORETURN void mp_raise_IndexError(const compressed_string_t *msg) { NORETURN void mp_raise_IndexError_varg(const compressed_string_t *fmt, ...) { va_list argptr; va_start(argptr,fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_IndexError, fmt, argptr); + mp_raise_msg_vlist(&mp_type_IndexError, fmt, argptr); va_end(argptr); - nlr_raise(exception); } NORETURN void mp_raise_ValueError(const compressed_string_t *msg) { @@ -1561,9 +1564,8 @@ NORETURN void mp_raise_ValueError(const compressed_string_t *msg) { NORETURN void mp_raise_ValueError_varg(const compressed_string_t *fmt, ...) { va_list argptr; va_start(argptr,fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_ValueError, fmt, argptr); + mp_raise_msg_vlist(&mp_type_ValueError, fmt, argptr); va_end(argptr); - nlr_raise(exception); } NORETURN void mp_raise_TypeError(const compressed_string_t *msg) { @@ -1573,9 +1575,8 @@ NORETURN void mp_raise_TypeError(const compressed_string_t *msg) { NORETURN void mp_raise_TypeError_varg(const compressed_string_t *fmt, ...) { va_list argptr; va_start(argptr,fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_TypeError, fmt, argptr); + mp_raise_msg_vlist(&mp_type_TypeError, fmt, argptr); va_end(argptr); - nlr_raise(exception); } NORETURN void mp_raise_OSError(int errno_) { @@ -1597,9 +1598,8 @@ NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str) { NORETURN void mp_raise_OSError_msg_varg(const compressed_string_t *fmt, ...) { va_list argptr; va_start(argptr,fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_OSError, fmt, argptr); + mp_raise_msg_vlist(&mp_type_OSError, fmt, argptr); va_end(argptr); - nlr_raise(exception); } NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg) { @@ -1609,17 +1609,15 @@ NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg) { NORETURN void mp_raise_NotImplementedError_varg(const compressed_string_t *fmt, ...) { va_list argptr; va_start(argptr,fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_NotImplementedError, fmt, argptr); + mp_raise_msg_vlist(&mp_type_NotImplementedError, fmt, argptr); va_end(argptr); - nlr_raise(exception); } NORETURN void mp_raise_OverflowError_varg(const compressed_string_t *fmt, ...) { va_list argptr; va_start(argptr,fmt); - mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_OverflowError, fmt, argptr); + mp_raise_msg_vlist(&mp_type_OverflowError, fmt, argptr); va_end(argptr); - nlr_raise(exception); } NORETURN void mp_raise_MpyError(const compressed_string_t *msg) { diff --git a/py/runtime.h b/py/runtime.h index ed37f90d9..dbc04b94e 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -152,6 +152,7 @@ void mp_import_all(mp_obj_t module); NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg); NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, ...); +NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, va_list argptr); NORETURN void mp_raise_ValueError(const compressed_string_t *msg); NORETURN void mp_raise_ValueError_varg(const compressed_string_t *fmt, ...); NORETURN void mp_raise_TypeError(const compressed_string_t *msg); -- cgit v1.2.3 From 92917b84f1a173a06d337d82a7a5568f680ff268 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 1 Aug 2020 16:03:00 -0500 Subject: fix exception type for pop from empty set --- py/objset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/objset.c b/py/objset.c index 82b10e7e8..6764a5c6f 100644 --- a/py/objset.c +++ b/py/objset.c @@ -368,7 +368,7 @@ STATIC mp_obj_t set_pop(mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t obj = mp_set_remove_first(&self->set); if (obj == MP_OBJ_NULL) { - mp_raise_IndexError_varg(translate("pop from empty %s"), "set"); + mp_raise_msg_varg(&mp_type_KeyError, translate("pop from empty %s"), "set"); } return obj; } -- cgit v1.2.3 From c37a25f0e5d1c877909855f6a3294e43b854bbbd Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 4 Aug 2020 10:59:31 -0500 Subject: Use qstrs to save an additional 4 bytes --- py/obj.c | 12 ++++++++---- py/obj.h | 1 + py/objint.c | 4 ++-- shared-bindings/i2cperipheral/I2CPeripheral.c | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) (limited to 'py') diff --git a/py/obj.c b/py/obj.c index 2b0c46f49..404fdd5d9 100644 --- a/py/obj.c +++ b/py/obj.c @@ -57,8 +57,12 @@ mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { } } +qstr mp_obj_get_type_qstr(mp_const_obj_t o_in) { + return mp_obj_get_type(o_in)->name; +} + const char *mp_obj_get_type_str(mp_const_obj_t o_in) { - return qstr_str(mp_obj_get_type(o_in)->name); + return qstr_str(mp_obj_get_type_qstr(o_in)); } void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { @@ -263,7 +267,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { mp_raise_TypeError(translate("can't convert to int")); } else { mp_raise_TypeError_varg( - translate("can't convert %s to %s"), mp_obj_get_type_str(arg), "int"); + translate("can't convert %q to %q"), mp_obj_get_type_qstr(arg), MP_QSTR_int); } } } @@ -326,7 +330,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { mp_raise_TypeError(translate("can't convert to float")); } else { mp_raise_TypeError_varg( - translate("can't convert %s to %s"), mp_obj_get_type_str(arg), "float"); + translate("can't convert %q to %q"), mp_obj_get_type_qstr(arg), MP_QSTR_float); } } @@ -359,7 +363,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { mp_raise_TypeError(translate("can't convert to complex")); } else { mp_raise_TypeError_varg( - translate("can't convert %s to %s"), mp_obj_get_type_str(arg), "complex"); + translate("can't convert %q to %q"), mp_obj_get_type_qstr(arg), MP_QSTR_complex); } } } diff --git a/py/obj.h b/py/obj.h index e603d4a49..656190cb3 100644 --- a/py/obj.h +++ b/py/obj.h @@ -680,6 +680,7 @@ mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items); mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); const char *mp_obj_get_type_str(mp_const_obj_t o_in); +qstr mp_obj_get_type_qstr(mp_const_obj_t o_in); bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects mp_obj_t mp_instance_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type); diff --git a/py/objint.c b/py/objint.c index 7726fb8d8..b12bb3995 100644 --- a/py/objint.c +++ b/py/objint.c @@ -141,9 +141,9 @@ STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { mp_obj_t mp_obj_new_int_from_float(mp_float_t val) { int cl = fpclassify(val); if (cl == FP_INFINITE) { - mp_raise_OverflowError_varg(translate("can't convert %s to %s"), "inf", "int"); + mp_raise_OverflowError_varg(translate("can't convert %q to %q"), MP_QSTR_inf, MP_QSTR_int); } else if (cl == FP_NAN) { - mp_raise_ValueError_varg(translate("can't convert %s to %s"), "NaN", "int"); + mp_raise_ValueError_varg(translate("can't convert %q to %q"), MP_QSTR_NaN, MP_QSTR_int); } else { mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val); if (icl == MP_FP_CLASS_FIT_SMALLINT) { diff --git a/shared-bindings/i2cperipheral/I2CPeripheral.c b/shared-bindings/i2cperipheral/I2CPeripheral.c index 39f787062..dfc58cd24 100644 --- a/shared-bindings/i2cperipheral/I2CPeripheral.c +++ b/shared-bindings/i2cperipheral/I2CPeripheral.c @@ -86,7 +86,7 @@ STATIC mp_obj_t i2cperipheral_i2c_peripheral_make_new(const mp_obj_type_t *type, while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { mp_int_t value; if (!mp_obj_get_int_maybe(item, &value)) { - mp_raise_TypeError_varg(translate("can't convert %s to %s"), "address", "int"); + mp_raise_TypeError_varg(translate("can't convert %q to %q"), MP_QSTR_address, MP_QSTR_int); } if (value < 0x00 || value > 0x7f) { mp_raise_ValueError(translate("address out of bounds")); -- cgit v1.2.3 From 89797fd3f9d36cd7e2e7a125dbbe02f598874060 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 4 Aug 2020 11:15:22 -0500 Subject: various: Use mp_obj_get_type_qstr more widely This removes runtime allocations of the cstring version of the qstring. It is not a size improvement --- extmod/vfs_fat_file.c | 2 +- extmod/vfs_posix_file.c | 2 +- ports/unix/file.c | 2 +- py/obj.c | 14 +++++++------- py/objstr.c | 14 +++++++------- py/objstrunicode.c | 2 +- py/objtype.c | 12 ++++++------ py/proto.c | 4 ++-- py/runtime.c | 28 ++++++++++++++-------------- 9 files changed, 40 insertions(+), 40 deletions(-) (limited to 'py') diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 0642f4a9c..89786bfa3 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -42,7 +42,7 @@ const byte fresult_to_errno_table[20] = { STATIC void file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; - mp_printf(print, "", mp_obj_get_type_str(self_in), MP_OBJ_TO_PTR(self_in)); + mp_printf(print, "", mp_obj_get_type_qstr(self_in), MP_OBJ_TO_PTR(self_in)); } STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index eefc1d905..3f887785e 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -34,7 +34,7 @@ STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { STATIC void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); + mp_printf(print, "", mp_obj_get_type_qstr(self_in), self->fd); } mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) { diff --git a/ports/unix/file.c b/ports/unix/file.c index e4f62e3d5..222dca462 100644 --- a/ports/unix/file.c +++ b/ports/unix/file.c @@ -60,7 +60,7 @@ extern const mp_obj_type_t mp_type_textio; STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); + mp_printf(print, "", mp_obj_get_type_qstr(self_in), self->fd); } STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { diff --git a/py/obj.c b/py/obj.c index 404fdd5d9..41fdaf633 100644 --- a/py/obj.c +++ b/py/obj.c @@ -381,7 +381,7 @@ void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) { mp_raise_TypeError(translate("expected tuple/list")); } else { mp_raise_TypeError_varg( - translate("object '%s' is not a tuple or list"), mp_obj_get_type_str(o)); + translate("object '%q' is not a tuple or list"), mp_obj_get_type_qstr(o)); } } } @@ -410,8 +410,8 @@ size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool mp_raise_TypeError(translate("indices must be integers")); } else { mp_raise_TypeError_varg( - translate("%q indices must be integers, not %s"), - type->name, mp_obj_get_type_str(index)); + translate("%q indices must be integers, not %q"), + type->name, mp_obj_get_type_qstr(index)); } } @@ -465,7 +465,7 @@ mp_obj_t mp_obj_len(mp_obj_t o_in) { mp_raise_TypeError(translate("object has no len")); } else { mp_raise_TypeError_varg( - translate("object of type '%s' has no len()"), mp_obj_get_type_str(o_in)); + translate("object of type '%q' has no len()"), mp_obj_get_type_qstr(o_in)); } } else { return len; @@ -508,21 +508,21 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { mp_raise_TypeError(translate("object does not support item deletion")); } else { mp_raise_TypeError_varg( - translate("'%s' object does not support item deletion"), mp_obj_get_type_str(base)); + translate("'%q' object does not support item deletion"), mp_obj_get_type_qstr(base)); } } else if (value == MP_OBJ_SENTINEL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("object is not subscriptable")); } else { mp_raise_TypeError_varg( - translate("'%s' object is not subscriptable"), mp_obj_get_type_str(base)); + translate("'%q' object is not subscriptable"), mp_obj_get_type_qstr(base)); } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("object does not support item assignment")); } else { mp_raise_TypeError_varg( - translate("'%s' object does not support item assignment"), mp_obj_get_type_str(base)); + translate("'%q' object does not support item assignment"), mp_obj_get_type_qstr(base)); } } } diff --git a/py/objstr.c b/py/objstr.c index 5e0c6fdfa..572bf299d 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1280,8 +1280,8 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar terse_str_format_value_error(); } else { mp_raise_ValueError_varg( - translate("unknown format code '%c' for object of type '%s'"), - type, mp_obj_get_type_str(arg)); + translate("unknown format code '%c' for object of type '%q'"), + type, mp_obj_get_type_qstr(arg)); } } } @@ -1352,8 +1352,8 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar terse_str_format_value_error(); } else { mp_raise_ValueError_varg( - translate("unknown format code '%c' for object of type '%s'"), - type, mp_obj_get_type_str(arg)); + translate("unknown format code '%c' for object of type '%q'"), + type, mp_obj_get_type_qstr(arg)); } } } else { @@ -1388,8 +1388,8 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar terse_str_format_value_error(); } else { mp_raise_ValueError_varg( - translate("unknown format code '%c' for object of type '%s'"), - type, mp_obj_get_type_str(arg)); + translate("unknown format code '%c' for object of type '%q'"), + type, mp_obj_get_type_qstr(arg)); } } } @@ -2133,7 +2133,7 @@ STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("can't convert to str implicitly")); } else { - const qstr src_name = mp_obj_get_type(self_in)->name; + const qstr src_name = mp_obj_get_type_qstr(self_in); nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, translate("can't convert '%q' object to %q implicitly"), src_name, src_name == MP_QSTR_str ? MP_QSTR_bytes : MP_QSTR_str)); diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 351a67e91..19d89a31c 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -151,7 +151,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s if (MP_OBJ_IS_SMALL_INT(index)) { i = MP_OBJ_SMALL_INT_VALUE(index); } else if (!mp_obj_get_int_maybe(index, &i)) { - mp_raise_TypeError_varg(translate("string indices must be integers, not %s"), mp_obj_get_type_str(index)); + mp_raise_TypeError_varg(translate("string indices must be integers, not %q"), mp_obj_get_type_qstr(index)); } const byte *s, *top = self_data + self_len; if (i < 0) diff --git a/py/objtype.c b/py/objtype.c index fd51ce36b..ccd014c33 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -193,7 +193,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_ printf("mp_obj_class_lookup: Returning: "); mp_obj_print(lookup->dest[0], PRINT_REPR); printf(" "); // Don't try to repr() lookup->dest[1], as we can be called recursively - printf("<%s @%p>\n", mp_obj_get_type_str(lookup->dest[1]), lookup->dest[1]); + printf("<%q @%p>\n", mp_obj_get_type_qstr(lookup->dest[1]), lookup->dest[1]); #endif return; } @@ -285,7 +285,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k } // TODO: CPython prints fully-qualified type name - mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self); + mp_printf(print, "<%q object at %p>", mp_obj_get_type_qstr(self_in), self); } mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { @@ -376,8 +376,8 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, cons if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("__init__() should return None")); } else { - mp_raise_TypeError_varg(translate("__init__() should return None, not '%s'"), - mp_obj_get_type_str(init_ret)); + mp_raise_TypeError_varg(translate("__init__() should return None, not '%q'"), + mp_obj_get_type_qstr(init_ret)); } } @@ -891,8 +891,8 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("object not callable")); } else { - mp_raise_TypeError_varg(translate("'%s' object is not callable"), - mp_obj_get_type_str(self_in)); + mp_raise_TypeError_varg(translate("'%q' object is not callable"), + mp_obj_get_type_qstr(self_in)); } } mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/py/proto.c b/py/proto.c index e5053130b..e4da157f0 100644 --- a/py/proto.c +++ b/py/proto.c @@ -45,6 +45,6 @@ const void *mp_proto_get_or_throw(uint16_t name, mp_const_obj_t obj) { if (proto) { return proto; } - mp_raise_TypeError_varg(translate("'%s' object does not support '%q'"), - mp_obj_get_type_str(obj), name); + mp_raise_TypeError_varg(translate("'%q' object does not support '%q'"), + mp_obj_get_type_qstr(obj), name); } diff --git a/py/runtime.c b/py/runtime.c index 87c24dc56..f9ef7819d 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -279,8 +279,8 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { mp_raise_TypeError(translate("unsupported type for operator")); } else { mp_raise_TypeError_varg( - translate("unsupported type for %q: '%s'"), - mp_unary_op_method_name[op], mp_obj_get_type_str(arg)); + translate("unsupported type for %q: '%q'"), + mp_unary_op_method_name[op], mp_obj_get_type_qstr(arg)); } } } @@ -586,8 +586,8 @@ unsupported_op: mp_raise_TypeError(translate("unsupported type for operator")); } else { mp_raise_TypeError_varg( - translate("unsupported types for %q: '%s', '%s'"), - mp_binary_op_method_name[op], mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)); + translate("unsupported types for %q: '%q', '%q'"), + mp_binary_op_method_name[op], mp_obj_get_type_qstr(lhs), mp_obj_get_type_qstr(rhs)); } zero_division: @@ -627,7 +627,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, cons if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("object not callable")); } else { - mp_raise_TypeError_varg(translate("'%s' object is not callable"), mp_obj_get_type_str(fun_in)); + mp_raise_TypeError_varg(translate("'%q' object is not callable"), mp_obj_get_type_qstr(fun_in)); } } @@ -1104,8 +1104,8 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { ((mp_obj_type_t*)MP_OBJ_TO_PTR(base))->name, attr)); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, - translate("'%s' object has no attribute '%q'"), - mp_obj_get_type_str(base), attr)); + translate("'%q' object has no attribute '%q'"), + mp_obj_get_type_qstr(base), attr)); } } } @@ -1172,8 +1172,8 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { mp_raise_AttributeError(translate("no such attribute")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, - translate("'%s' object cannot assign attribute '%q'"), - mp_obj_get_type_str(base), attr)); + translate("'%q' object cannot assign attribute '%q'"), + mp_obj_get_type_qstr(base), attr)); } } @@ -1213,7 +1213,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { mp_raise_TypeError(translate("object not iterable")); } else { mp_raise_TypeError_varg( - translate("'%s' object is not iterable"), mp_obj_get_type_str(o_in)); + translate("'%q' object is not iterable"), mp_obj_get_type_qstr(o_in)); } } @@ -1234,8 +1234,8 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("object not an iterator")); } else { - mp_raise_TypeError_varg(translate("'%s' object is not an iterator"), - mp_obj_get_type_str(o_in)); + mp_raise_TypeError_varg(translate("'%q' object is not an iterator"), + mp_obj_get_type_qstr(o_in)); } } } @@ -1270,8 +1270,8 @@ mp_obj_t mp_iternext(mp_obj_t o_in) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError(translate("object not an iterator")); } else { - mp_raise_TypeError_varg(translate("'%s' object is not an iterator"), - mp_obj_get_type_str(o_in)); + mp_raise_TypeError_varg(translate("'%q' object is not an iterator"), + mp_obj_get_type_qstr(o_in)); } } } -- cgit v1.2.3 From c849b781c0186d93a1165784ce4e22d2178d5ccb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 4 Aug 2020 11:27:36 -0500 Subject: Combine 'index out of range' messages --- extmod/moductypes.c | 2 +- ports/atmel-samd/common-hal/pulseio/PulseIn.c | 2 +- ports/cxd56/common-hal/pulseio/PulseIn.c | 2 +- ports/mimxrt10xx/common-hal/pulseio/PulseIn.c | 2 +- ports/nrf/common-hal/pulseio/PulseIn.c | 2 +- ports/stm/common-hal/pulseio/PulseIn.c | 2 +- py/objstr.c | 4 ++-- py/objstrunicode.c | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) (limited to 'py') diff --git a/extmod/moductypes.c b/extmod/moductypes.c index a384f1e2c..dc8ac4c72 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -520,7 +520,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS); arr_sz &= VALUE_MASK(VAL_TYPE_BITS); if (index >= arr_sz) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, translate("struct: index out of range"))); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_struct); } if (t->len == 2) { diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index be8165a5a..81ccc4fec 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -330,7 +330,7 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, } if (index < 0 || index >= self->len) { common_hal_mcu_enable_interrupts(); - mp_raise_IndexError(translate("index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); } uint16_t value = self->buffer[(self->start + index) % self->maxlen]; common_hal_mcu_enable_interrupts(); diff --git a/ports/cxd56/common-hal/pulseio/PulseIn.c b/ports/cxd56/common-hal/pulseio/PulseIn.c index 045acc9d2..e54b5083d 100644 --- a/ports/cxd56/common-hal/pulseio/PulseIn.c +++ b/ports/cxd56/common-hal/pulseio/PulseIn.c @@ -190,7 +190,7 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t *self, int16_ } if (index < 0 || index >= self->len) { common_hal_mcu_enable_interrupts(); - mp_raise_IndexError(translate("index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); } uint16_t value = self->buffer[(self->start + index) % self->maxlen]; common_hal_mcu_enable_interrupts(); diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c index e89a49e80..f5757ab78 100644 --- a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c +++ b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c @@ -237,7 +237,7 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, // } // if (index < 0 || index >= self->len) { // common_hal_mcu_enable_interrupts(); -// mp_raise_IndexError(translate("index out of range")); +// mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); // } // uint16_t value = self->buffer[(self->start + index) % self->maxlen]; // common_hal_mcu_enable_interrupts(); diff --git a/ports/nrf/common-hal/pulseio/PulseIn.c b/ports/nrf/common-hal/pulseio/PulseIn.c index 80ff2c529..c5de3a4b4 100644 --- a/ports/nrf/common-hal/pulseio/PulseIn.c +++ b/ports/nrf/common-hal/pulseio/PulseIn.c @@ -271,7 +271,7 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_ if ( !self->paused ) { nrfx_gpiote_in_event_enable(self->pin, true); } - mp_raise_IndexError(translate("index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); } uint16_t value = self->buffer[(self->start + index) % self->maxlen]; diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c index b43fdd554..a667cf010 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.c +++ b/ports/stm/common-hal/pulseio/PulseIn.c @@ -249,7 +249,7 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_ } if (index < 0 || index >= self->len) { HAL_NVIC_EnableIRQ(self->irq); - mp_raise_IndexError(translate("index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); } uint16_t value = self->buffer[(self->start + index) % self->maxlen]; HAL_NVIC_EnableIRQ(self->irq); diff --git a/py/objstr.c b/py/objstr.c index 572bf299d..edb562df2 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1076,7 +1076,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } field_name = str_to_int(field_name, field_name_top, &index); if ((uint)index >= n_args - 1) { - mp_raise_IndexError(translate("tuple index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_tuple); } arg = args[index + 1]; *arg_i = -1; @@ -1104,7 +1104,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } } if ((uint)*arg_i >= n_args - 1) { - mp_raise_IndexError(translate("tuple index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_tuple); } arg = args[(*arg_i) + 1]; (*arg_i)++; diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 19d89a31c..50250abfa 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -162,7 +162,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s if (is_slice) { return self_data; } - mp_raise_IndexError(translate("string index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_str); } if (!UTF8_IS_CONT(*s)) { ++i; @@ -181,7 +181,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s if (is_slice) { return top; } - mp_raise_IndexError(translate("string index out of range")); + mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_str); } // Then check completion if (i-- == 0) { -- cgit v1.2.3 From 024c8da57869b2aa49004f091520aaf5dacb26e6 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 4 Aug 2020 11:41:04 -0500 Subject: Combine some "can't convert" messages --- py/obj.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'py') diff --git a/py/obj.c b/py/obj.c index 41fdaf633..6fa11f025 100644 --- a/py/obj.c +++ b/py/obj.c @@ -264,7 +264,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { return mp_obj_int_get_checked(arg); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - mp_raise_TypeError(translate("can't convert to int")); + mp_raise_TypeError_varg(translate("can't convert to %q"), MP_QSTR_int); } else { mp_raise_TypeError_varg( translate("can't convert %q to %q"), mp_obj_get_type_qstr(arg), MP_QSTR_int); @@ -327,7 +327,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { if (!mp_obj_get_float_maybe(arg, &val)) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - mp_raise_TypeError(translate("can't convert to float")); + mp_raise_TypeError_varg(translate("can't convert to %q"), MP_QSTR_float); } else { mp_raise_TypeError_varg( translate("can't convert %q to %q"), mp_obj_get_type_qstr(arg), MP_QSTR_float); @@ -360,7 +360,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { mp_obj_complex_get(arg, real, imag); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - mp_raise_TypeError(translate("can't convert to complex")); + mp_raise_TypeError_varg(translate("can't convert to %q"), MP_QSTR_complex); } else { mp_raise_TypeError_varg( translate("can't convert %q to %q"), mp_obj_get_type_qstr(arg), MP_QSTR_complex); -- cgit v1.2.3 From 65e26f4a068129662c9793fd070530a35cc568b1 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 4 Aug 2020 14:05:32 -0500 Subject: py: mp_obj_get_type_qstr as macro saves 24 bytes --- py/obj.c | 4 ---- py/obj.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'py') diff --git a/py/obj.c b/py/obj.c index 6fa11f025..0cff2f1a4 100644 --- a/py/obj.c +++ b/py/obj.c @@ -57,10 +57,6 @@ mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { } } -qstr mp_obj_get_type_qstr(mp_const_obj_t o_in) { - return mp_obj_get_type(o_in)->name; -} - const char *mp_obj_get_type_str(mp_const_obj_t o_in) { return qstr_str(mp_obj_get_type_qstr(o_in)); } diff --git a/py/obj.h b/py/obj.h index 656190cb3..e9d867f77 100644 --- a/py/obj.h +++ b/py/obj.h @@ -680,7 +680,7 @@ mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items); mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); const char *mp_obj_get_type_str(mp_const_obj_t o_in); -qstr mp_obj_get_type_qstr(mp_const_obj_t o_in); +#define mp_obj_get_type_qstr(o_in) (mp_obj_get_type((o_in))->name) bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects mp_obj_t mp_instance_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type); -- cgit v1.2.3 From 93b373d617ff7a99eb936628d50d954f5db53f43 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 4 Aug 2020 18:34:59 -0500 Subject: "pop from empty %q" Saves 12 bytes code on trinket m0 --- locale/circuitpython.pot | 5 ++--- ports/atmel-samd/common-hal/pulseio/PulseIn.c | 2 +- ports/cxd56/common-hal/pulseio/PulseIn.c | 2 +- ports/mimxrt10xx/common-hal/pulseio/PulseIn.c | 2 +- ports/nrf/common-hal/pulseio/PulseIn.c | 2 +- ports/stm/common-hal/pulseio/PulseIn.c | 2 +- py/objdict.c | 2 +- py/objlist.c | 2 +- py/objset.c | 2 +- shared-bindings/ps2io/Ps2.c | 2 +- 10 files changed, 11 insertions(+), 12 deletions(-) (limited to 'py') diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index e40b8a614..fb9869bd4 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-04 13:58-0500\n" +"POT-Creation-Date: 2020-08-04 18:42-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -2894,8 +2894,7 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseIn.c #: ports/stm/common-hal/pulseio/PulseIn.c py/objdict.c py/objlist.c py/objset.c #: shared-bindings/ps2io/Ps2.c -#, c-format -msgid "pop from empty %s" +msgid "pop from empty %q" msgstr "" #: py/objint_mpz.c diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index 81ccc4fec..d3d993672 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -298,7 +298,7 @@ void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) { uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) { if (self->len == 0) { - mp_raise_IndexError_varg(translate("pop from empty %s"), "PulseIn"); + mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); } common_hal_mcu_disable_interrupts(); uint16_t value = self->buffer[self->start]; diff --git a/ports/cxd56/common-hal/pulseio/PulseIn.c b/ports/cxd56/common-hal/pulseio/PulseIn.c index e54b5083d..7c3e4a9d0 100644 --- a/ports/cxd56/common-hal/pulseio/PulseIn.c +++ b/ports/cxd56/common-hal/pulseio/PulseIn.c @@ -160,7 +160,7 @@ void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t *self) { uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t *self) { if (self->len == 0) { - mp_raise_IndexError_varg(translate("pop from empty %s"), "PulseIn"); + mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); } common_hal_mcu_disable_interrupts(); uint16_t value = self->buffer[self->start]; diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c index f5757ab78..cea11a4b9 100644 --- a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c +++ b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c @@ -201,7 +201,7 @@ void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) { uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) { // if (self->len == 0) { -// mp_raise_IndexError_varg(translate("pop from empty %s"), "PulseIn"); +// mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); // } // common_hal_mcu_disable_interrupts(); // uint16_t value = self->buffer[self->start]; diff --git a/ports/nrf/common-hal/pulseio/PulseIn.c b/ports/nrf/common-hal/pulseio/PulseIn.c index c5de3a4b4..ca44a20b4 100644 --- a/ports/nrf/common-hal/pulseio/PulseIn.c +++ b/ports/nrf/common-hal/pulseio/PulseIn.c @@ -284,7 +284,7 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) { if (self->len == 0) { - mp_raise_IndexError_varg(translate("pop from empty %s"), "PulseIn"); + mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); } if ( !self->paused ) { diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c index a667cf010..015ee8536 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.c +++ b/ports/stm/common-hal/pulseio/PulseIn.c @@ -258,7 +258,7 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) { if (self->len == 0) { - mp_raise_IndexError_varg(translate("pop from empty %s"), "PulseIn"); + mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); } HAL_NVIC_DisableIRQ(self->irq); uint16_t value = self->buffer[self->start]; diff --git a/py/objdict.c b/py/objdict.c index 6ddf7ddde..63fd86f35 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -313,7 +313,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { size_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { - mp_raise_msg_varg(&mp_type_KeyError, translate("pop from empty %s"), "dict"); + mp_raise_msg_varg(&mp_type_KeyError, translate("pop from empty %q"), MP_QSTR_dict); } self->map.used--; mp_obj_t items[] = {next->key, next->value}; diff --git a/py/objlist.c b/py/objlist.c index b2de72374..51ec920be 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -274,7 +274,7 @@ STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = mp_instance_cast_to_native_base(args[0], &mp_type_list); if (self->len == 0) { - mp_raise_IndexError_varg(translate("pop from empty %s"), "list"); + mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_list); } size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); mp_obj_t ret = self->items[index]; diff --git a/py/objset.c b/py/objset.c index 6764a5c6f..b8f0f07ed 100644 --- a/py/objset.c +++ b/py/objset.c @@ -368,7 +368,7 @@ STATIC mp_obj_t set_pop(mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t obj = mp_set_remove_first(&self->set); if (obj == MP_OBJ_NULL) { - mp_raise_msg_varg(&mp_type_KeyError, translate("pop from empty %s"), "set"); + mp_raise_msg_varg(&mp_type_KeyError, translate("pop from empty %q"), MP_QSTR_set); } return obj; } diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c index 64d93f6ad..0977e08ff 100644 --- a/shared-bindings/ps2io/Ps2.c +++ b/shared-bindings/ps2io/Ps2.c @@ -133,7 +133,7 @@ STATIC mp_obj_t ps2io_ps2_obj_popleft(mp_obj_t self_in) { int b = common_hal_ps2io_ps2_popleft(self); if (b < 0) { - mp_raise_IndexError_varg(translate("pop from empty %s"), "Ps2 buffer"); + mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_Ps2_space_buffer); } return MP_OBJ_NEW_SMALL_INT(b); } -- cgit v1.2.3 From c1400bae9bbdd55f650ddfe24edf6778f08c35b8 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 6 Aug 2020 16:03:31 -0500 Subject: sharpmemory: Implement support for Sharp Memory Displays in framebufferio --- py/circuitpy_defns.mk | 5 + py/circuitpy_mpconfig.h | 22 +- py/circuitpy_mpconfig.mk | 6 +- py/qstr.c | 1 + .../sharpdisplay/SharpMemoryFramebuffer.c | 92 +++++++ .../sharpdisplay/SharpMemoryFramebuffer.h | 34 +++ shared-bindings/sharpdisplay/__init__.c | 47 ++++ shared-bindings/sharpdisplay/__init__.h | 0 shared-module/displayio/__init__.c | 33 ++- shared-module/displayio/__init__.h | 10 + shared-module/framebufferio/FramebufferDisplay.c | 21 +- shared-module/framebufferio/FramebufferDisplay.h | 3 +- .../sharpdisplay/SharpMemoryFramebuffer.c | 282 +++++++++++++++++++++ .../sharpdisplay/SharpMemoryFramebuffer.h | 60 +++++ shared-module/sharpdisplay/__init__.c | 0 shared-module/sharpdisplay/__init__.h | 0 supervisor/shared/display.c | 21 +- 17 files changed, 608 insertions(+), 29 deletions(-) create mode 100644 shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c create mode 100644 shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h create mode 100644 shared-bindings/sharpdisplay/__init__.c create mode 100644 shared-bindings/sharpdisplay/__init__.h create mode 100644 shared-module/sharpdisplay/SharpMemoryFramebuffer.c create mode 100644 shared-module/sharpdisplay/SharpMemoryFramebuffer.h create mode 100644 shared-module/sharpdisplay/__init__.c create mode 100644 shared-module/sharpdisplay/__init__.h (limited to 'py') diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index a39e0c9dd..515b386f9 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -222,6 +222,9 @@ endif ifeq ($(CIRCUITPY_SDIOIO),1) SRC_PATTERNS += sdioio/% endif +ifeq ($(CIRCUITPY_SHARPDISPLAY),1) +SRC_PATTERNS += sharpdisplay/% +endif ifeq ($(CIRCUITPY_STAGE),1) SRC_PATTERNS += _stage/% endif @@ -409,6 +412,8 @@ SRC_SHARED_MODULE_ALL = \ random/__init__.c \ rgbmatrix/RGBMatrix.c \ rgbmatrix/__init__.c \ + sharpdisplay/SharpMemoryFramebuffer.c \ + sharpdisplay/__init__.c \ socket/__init__.c \ storage/__init__.c \ struct/__init__.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 255ab99b9..f0e8adffa 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -499,13 +499,6 @@ extern const struct _mp_obj_module_t pixelbuf_module; #define PIXELBUF_MODULE #endif -#if CIRCUITPY_RGBMATRIX -extern const struct _mp_obj_module_t rgbmatrix_module; -#define RGBMATRIX_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rgbmatrix),(mp_obj_t)&rgbmatrix_module }, -#else -#define RGBMATRIX_MODULE -#endif - #if CIRCUITPY_PULSEIO extern const struct _mp_obj_module_t pulseio_module; #define PULSEIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, @@ -520,6 +513,13 @@ extern const struct _mp_obj_module_t ps2io_module; #define PS2IO_MODULE #endif +#if CIRCUITPY_RGBMATRIX +extern const struct _mp_obj_module_t rgbmatrix_module; +#define RGBMATRIX_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rgbmatrix),(mp_obj_t)&rgbmatrix_module }, +#else +#define RGBMATRIX_MODULE +#endif + #if CIRCUITPY_RANDOM extern const struct _mp_obj_module_t random_module; #define RANDOM_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, @@ -562,6 +562,13 @@ extern const struct _mp_obj_module_t sdioio_module; #define SDIOIO_MODULE #endif +#if CIRCUITPY_SHARPDISPLAY +extern const struct _mp_obj_module_t sharpdisplay_module; +#define SHARPDISPLAY_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_sharpdisplay),(mp_obj_t)&sharpdisplay_module }, +#else +#define SHARPDISPLAY_MODULE +#endif + #if CIRCUITPY_STAGE extern const struct _mp_obj_module_t stage_module; #define STAGE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module }, @@ -737,6 +744,7 @@ extern const struct _mp_obj_module_t watchdog_module; SAMD_MODULE \ SDCARDIO_MODULE \ SDIOIO_MODULE \ + SHARPDISPLAY_MODULE \ STAGE_MODULE \ STORAGE_MODULE \ STRUCT_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 2cf8426e5..1ba71fa02 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -95,7 +95,7 @@ CFLAGS += -DCIRCUITPY_COUNTIO=$(CIRCUITPY_COUNTIO) CIRCUITPY_DISPLAYIO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_DISPLAYIO=$(CIRCUITPY_DISPLAYIO) -CIRCUITPY_FRAMEBUFFERIO ?= 0 +CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_FRAMEBUFFERIO=$(CIRCUITPY_FRAMEBUFFERIO) CIRCUITPY_VECTORIO ?= $(CIRCUITPY_DISPLAYIO) @@ -144,7 +144,6 @@ CFLAGS += -DCIRCUITPY_OS=$(CIRCUITPY_OS) CIRCUITPY_PIXELBUF ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_PIXELBUF=$(CIRCUITPY_PIXELBUF) -# Only for SAMD boards for the moment CIRCUITPY_RGBMATRIX ?= 0 CFLAGS += -DCIRCUITPY_RGBMATRIX=$(CIRCUITPY_RGBMATRIX) @@ -176,6 +175,9 @@ CFLAGS += -DCIRCUITPY_SDCARDIO=$(CIRCUITPY_SDCARDIO) CIRCUITPY_SDIOIO ?= 0 CFLAGS += -DCIRCUITPY_SDIOIO=$(CIRCUITPY_SDIOIO) +CIRCUITPY_SHARPDISPLAY ?= $(CIRCUITPY_FRAMEBUFFERIO) +CFLAGS += -DCIRCUITPY_SHARPDISPLAY=$(CIRCUITPY_SHARPDISPLAY) + # Currently always off. CIRCUITPY_STAGE ?= 0 CFLAGS += -DCIRCUITPY_STAGE=$(CIRCUITPY_STAGE) diff --git a/py/qstr.c b/py/qstr.c index 17d8517c9..c9ba298fb 100755 --- a/py/qstr.c +++ b/py/qstr.c @@ -137,6 +137,7 @@ STATIC const byte *find_qstr(qstr q) { while (q < pool->total_prev_len) { pool = pool->prev; } + assert(q - pool->total_prev_len < pool->len); return pool->qstrs[q - pool->total_prev_len]; } diff --git a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c new file mode 100644 index 000000000..e8f4e970a --- /dev/null +++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c @@ -0,0 +1,92 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/objarray.h" +#include "py/runtime.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" + +STATIC mp_obj_t sharpdisplay_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_spi_bus, ARG_chip_select, ARG_width, ARG_height, ARG_baudrate, NUM_ARGS }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_spi_bus, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_chip_select, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} }, + { MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} }, + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 2000000} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS ); + + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mcu_pin_obj_t *chip_select = validate_obj_is_free_pin(args[ARG_chip_select].u_obj); + busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi_bus].u_obj); + + sharpdisplay_framebuffer_obj_t* self = &allocate_display_bus_or_raise()->sharpdisplay; + self->base.type = &sharpdisplay_framebuffer_type; + + common_hal_sharpdisplay_framebuffer_construct(self, spi, chip_select, args[ARG_baudrate].u_int, args[ARG_width].u_int, args[ARG_height].u_int); + + return MP_OBJ_FROM_PTR(self); +} + + +STATIC mp_int_t sharpdisplay_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + sharpdisplay_framebuffer_obj_t *self = (sharpdisplay_framebuffer_obj_t*)self_in; + // a readonly framebuffer would be unusual but not impossible + if ((flags & MP_BUFFER_WRITE) && !(self->bufinfo.typecode & MP_OBJ_ARRAY_TYPECODE_FLAG_RW)) { + return 1; + } + *bufinfo = self->bufinfo; + return 0; +} + +STATIC mp_obj_t sharpdisplay_framebuffer_deinit(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = (sharpdisplay_framebuffer_obj_t*)self_in; + common_hal_sharpdisplay_framebuffer_deinit(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(sharpdisplay_framebuffer_deinit_obj, sharpdisplay_framebuffer_deinit); + +STATIC const mp_rom_map_elem_t sharpdisplay_framebuffer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sharpdisplay_framebuffer_deinit_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(sharpdisplay_framebuffer_locals_dict, sharpdisplay_framebuffer_locals_dict_table); + +const mp_obj_type_t sharpdisplay_framebuffer_type = { + { &mp_type_type }, + .name = MP_QSTR_SharpMemoryFramebuffer, + .buffer_p = { .get_buffer = sharpdisplay_framebuffer_get_buffer, }, + .make_new = sharpdisplay_framebuffer_make_new, + .protocol = &sharpdisplay_framebuffer_proto, + .locals_dict = (mp_obj_dict_t*)&sharpdisplay_framebuffer_locals_dict, +}; diff --git a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h new file mode 100644 index 000000000..30f1b867b --- /dev/null +++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" +// #include "shared-module/framebufferio/FramebufferDisplay.h" + +#include "py/objtype.h" + +extern const mp_obj_type_t sharpdisplay_framebuffer_type; diff --git a/shared-bindings/sharpdisplay/__init__.c b/shared-bindings/sharpdisplay/__init__.c new file mode 100644 index 000000000..d1f728c61 --- /dev/null +++ b/shared-bindings/sharpdisplay/__init__.c @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h" + +//| """Support for Sharp Memory Display framebuffers""" +//| + +STATIC const mp_rom_map_elem_t sharpdisplay_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sharpdisplay) }, + { MP_ROM_QSTR(MP_QSTR_SharpMemoryFramebuffer), MP_ROM_PTR(&sharpdisplay_framebuffer_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(sharpdisplay_module_globals, sharpdisplay_module_globals_table); + +const mp_obj_module_t sharpdisplay_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&sharpdisplay_module_globals, +}; diff --git a/shared-bindings/sharpdisplay/__init__.h b/shared-bindings/sharpdisplay/__init__.h new file mode 100644 index 000000000..e69de29bb diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index efc28470f..e52ec5b9e 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -19,14 +19,19 @@ #include "supervisor/spi_flash_api.h" #include "py/mpconfig.h" +#if CIRCUITPY_SHARPDISPLAY +#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h" +#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" +#endif + primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT]; -#if CIRCUITPY_RGBMATRIX -STATIC bool any_display_uses_this_rgbmatrix(rgbmatrix_rgbmatrix_obj_t* pm) { +#if CIRCUITPY_RGBMATRIX || CIRCUITPY_SHARPDISPLAY +STATIC bool any_display_uses_this_framebuffer(mp_obj_base_t *obj) { for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { - if (displays[i].framebuffer_display.base.type == &framebufferio_framebufferdisplay_type) { + if (displays[i].display_base.type == &framebufferio_framebufferdisplay_type) { framebufferio_framebufferdisplay_obj_t* display = &displays[i].framebuffer_display; - if (display->framebuffer == pm) { + if (display->framebuffer == obj) { return true; } } @@ -105,6 +110,10 @@ void common_hal_displayio_release_displays(void) { #if CIRCUITPY_FRAMEBUFFERIO } else if (bus_type == &rgbmatrix_RGBMatrix_type) { common_hal_rgbmatrix_rgbmatrix_deinit(&displays[i].rgbmatrix); +#endif +#if CIRCUITPY_SHARPDISPLAY + } else if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) { + common_hal_sharpdisplay_framebuffer_deinit(&displays[i].sharpdisplay); #endif } displays[i].fourwire_bus.base.type = &mp_type_NoneType; @@ -170,9 +179,18 @@ void reset_displays(void) { #if CIRCUITPY_RGBMATRIX } else if (displays[i].rgbmatrix.base.type == &rgbmatrix_RGBMatrix_type) { rgbmatrix_rgbmatrix_obj_t * pm = &displays[i].rgbmatrix; - if(!any_display_uses_this_rgbmatrix(pm)) { + if(!any_display_uses_this_framebuffer(&pm->base)) { common_hal_rgbmatrix_rgbmatrix_deinit(pm); } +#endif +#if CIRCUITPY_SHARPDISPLAY + } else if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) { + sharpdisplay_framebuffer_obj_t * sharp = &displays[i].sharpdisplay; + if(any_display_uses_this_framebuffer(&sharp->base)) { + common_hal_sharpdisplay_framebuffer_reset(sharp); + } else { + common_hal_sharpdisplay_framebuffer_deinit(sharp); + } #endif } else { // Not an active display bus. @@ -203,6 +221,11 @@ void displayio_gc_collect(void) { rgbmatrix_rgbmatrix_collect_ptrs(&displays[i].rgbmatrix); } #endif +#if CIRCUITPY_SHARPDISPLAY + if (displays[i].rgbmatrix.base.type == &sharpdisplay_framebuffer_type) { + common_hal_sharpdisplay_framebuffer_collect_ptrs(&displays[i].sharpdisplay); + } +#endif if (displays[i].display.base.type == NULL) { continue; diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h index 9eb10c28b..44ad5a9a9 100644 --- a/shared-module/displayio/__init__.h +++ b/shared-module/displayio/__init__.h @@ -36,18 +36,28 @@ #include "shared-bindings/displayio/Group.h" #include "shared-bindings/displayio/I2CDisplay.h" #include "shared-bindings/displayio/ParallelBus.h" +#if CIRCUITPY_RGBMATRIX #include "shared-bindings/rgbmatrix/RGBMatrix.h" +#endif +#if CIRCUITPY_SHARPDISPLAY +#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" +#endif typedef struct { union { + mp_obj_base_t bus_base; displayio_fourwire_obj_t fourwire_bus; displayio_i2cdisplay_obj_t i2cdisplay_bus; displayio_parallelbus_obj_t parallel_bus; #if CIRCUITPY_RGBMATRIX rgbmatrix_rgbmatrix_obj_t rgbmatrix; +#endif +#if CIRCUITPY_SHARPDISPLAY + sharpdisplay_framebuffer_obj_t sharpdisplay; #endif }; union { + mp_obj_base_t display_base; displayio_display_obj_t display; displayio_epaperdisplay_obj_t epaper_display; #if CIRCUITPY_FRAMEBUFFERIO diff --git a/shared-module/framebufferio/FramebufferDisplay.c b/shared-module/framebufferio/FramebufferDisplay.c index 9a6797cd8..6b5346877 100644 --- a/shared-module/framebufferio/FramebufferDisplay.c +++ b/shared-module/framebufferio/FramebufferDisplay.c @@ -156,7 +156,7 @@ STATIC const displayio_area_t* _get_refresh_areas(framebufferio_framebufferdispl return NULL; } -#define MARK_ROW_DIRTY(r) (dirty_row_bitmask[r/8] = (1 << (r & 7))) +#define MARK_ROW_DIRTY(r) (dirty_row_bitmask[r/8] |= (1 << (r & 7))) STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const displayio_area_t* area, uint8_t *dirty_row_bitmask) { uint16_t buffer_size = 128; // In uint32_ts @@ -250,6 +250,10 @@ STATIC bool _refresh_area(framebufferio_framebufferdisplay_obj_t* self, const di } STATIC void _refresh_display(framebufferio_framebufferdisplay_obj_t* self) { + self->framebuffer_protocol->get_bufinfo(self->framebuffer, &self->bufinfo); + if(!self->bufinfo.buf) { + return; + } displayio_display_core_start_refresh(&self->core); const displayio_area_t* current_area = _get_refresh_areas(self); if (current_area) { @@ -348,17 +352,18 @@ void release_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self) { self->base.type = &mp_type_NoneType; } -void reset_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self) { - common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, true); - common_hal_framebufferio_framebufferdisplay_show(self, NULL); -} - void framebufferio_framebufferdisplay_collect_ptrs(framebufferio_framebufferdisplay_obj_t* self) { gc_collect_ptr(self->framebuffer); displayio_display_core_collect_ptrs(&self->core); } void framebufferio_framebufferdisplay_reset(framebufferio_framebufferdisplay_obj_t* self) { - common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, true); - common_hal_framebufferio_framebufferdisplay_show(self, NULL); + mp_obj_type_t *fb_type = mp_obj_get_type(self->framebuffer); + if(fb_type != NULL && fb_type != &mp_type_NoneType) { + common_hal_framebufferio_framebufferdisplay_set_auto_refresh(self, true); + common_hal_framebufferio_framebufferdisplay_show(self, NULL); + self->core.full_refresh = true; + } else { + release_framebufferdisplay(self); + } } diff --git a/shared-module/framebufferio/FramebufferDisplay.h b/shared-module/framebufferio/FramebufferDisplay.h index 027086b5a..111c9f670 100644 --- a/shared-module/framebufferio/FramebufferDisplay.h +++ b/shared-module/framebufferio/FramebufferDisplay.h @@ -55,7 +55,6 @@ typedef struct { void framebufferio_framebufferdisplay_background(framebufferio_framebufferdisplay_obj_t* self); void release_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self); -void reset_framebufferdisplay(framebufferio_framebufferdisplay_obj_t* self); void framebufferio_framebufferdisplay_reset(framebufferio_framebufferdisplay_obj_t* self); void framebufferio_framebufferdisplay_collect_ptrs(framebufferio_framebufferdisplay_obj_t* self); @@ -73,7 +72,7 @@ typedef int (*framebuffer_get_first_pixel_offset_fun)(mp_obj_t); typedef int (*framebuffer_get_grayscale_fun)(mp_obj_t); typedef int (*framebuffer_get_height_fun)(mp_obj_t); typedef int (*framebuffer_get_native_frames_per_second_fun)(mp_obj_t); -typedef int (*framebuffer_get_pixels_in_byte_share_row_fun)(mp_obj_t); +typedef bool (*framebuffer_get_pixels_in_byte_share_row_fun)(mp_obj_t); typedef int (*framebuffer_get_row_stride_fun)(mp_obj_t); typedef int (*framebuffer_get_width_fun)(mp_obj_t); typedef mp_float_t (*framebuffer_get_brightness_fun)(mp_obj_t); diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c new file mode 100644 index 000000000..ac9c22572 --- /dev/null +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c @@ -0,0 +1,282 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/gc.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h" +#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" + +#include "supervisor/memory.h" + +#define SHARPMEM_BIT_WRITECMD_LSB (0x80) +#define SHARPMEM_BIT_VCOM_LSB (0x40) + +static inline void *hybrid_alloc(size_t sz) { + if (gc_alloc_possible()) { + return m_malloc(sz + sizeof(void*), true); + } else { + supervisor_allocation *allocation = allocate_memory(align32_size(sz), false); + if (!allocation) { + return NULL; + } + memset(allocation->ptr, 0, sz); + return allocation->ptr; + } +} + +static inline void hybrid_free(void *ptr_in) { + supervisor_allocation *allocation = allocation_from_ptr(ptr_in); + + if (allocation) { + free_memory(allocation); + } +} + +STATIC uint8_t bitrev(uint8_t n) { + uint8_t r = 0; + for(int i=0;i<8;i++) r |= ((n>>i) & 1)<<(7-i); + return r; +} + +int common_hal_sharpdisplay_framebuffer_get_width(sharpdisplay_framebuffer_obj_t *self) { + return self->width; +} + +int common_hal_sharpdisplay_framebuffer_get_height(sharpdisplay_framebuffer_obj_t *self) { + return self->height; +} + +int common_hal_sharpdisplay_framebuffer_get_row_stride(sharpdisplay_framebuffer_obj_t *self) { + return (self->width + 7) / 8 + 2; +} + +int common_hal_sharpdisplay_framebuffer_get_first_pixel_offset(sharpdisplay_framebuffer_obj_t *self) { + return 2; +} + +bool common_hal_sharpdisplay_framebuffer_get_reverse_pixels_in_byte(sharpdisplay_framebuffer_obj_t *self) { + return true; +} + +bool common_hal_sharpdisplay_framebuffer_get_pixels_in_byte_share_row(sharpdisplay_framebuffer_obj_t *self) { + return true; +} + +void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self) { + if (!allocation_from_ptr(self->bufinfo.buf)) { + self->bufinfo.buf = NULL; + } + + if (self->bus != &self->inline_bus +#if BOARD_SPI + && self->bus != common_hal_board_get_spi() +#endif + ) { + memcpy(&self->inline_bus, self->bus, sizeof(busio_spi_obj_t)); + self->bus = &self->inline_bus; + } +} + +void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self) { + +} + +void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo) { + if (!self->bufinfo.buf) { + int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self); + int height = common_hal_sharpdisplay_framebuffer_get_height(self); + self->bufinfo.len = row_stride * height + 2; + self->bufinfo.buf = hybrid_alloc(self->bufinfo.len); + + uint8_t *data = self->bufinfo.buf; + *data++ = SHARPMEM_BIT_WRITECMD_LSB; + + for(int y=0; yfull_refresh = true; + } + *bufinfo = self->bufinfo; +} + +void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self) { + if (self->base.type != &sharpdisplay_framebuffer_type) { + return; + } + + if (self->bus == &self->inline_bus) { + common_hal_busio_spi_deinit(self->bus); + } + + common_hal_reset_pin(self->chip_select.pin); + + hybrid_free(self->bufinfo.buf); + + memset(self, 0, sizeof(*self)); +} + +void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_t *self, busio_spi_obj_t *spi, mcu_pin_obj_t *chip_select, int baudrate, int width, int height) { + common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select); + common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL); + common_hal_never_reset_pin(chip_select); + + self->bus = spi; + common_hal_busio_spi_never_reset(self->bus); + + self->width = width; + self->height = height; + self->baudrate = baudrate; + + int row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self); + self->bufinfo.len = row_stride * height + 2; + self->bufinfo.buf = gc_alloc(self->bufinfo.len, false, true); + + uint8_t *data = self->bufinfo.buf; + *data++ = SHARPMEM_BIT_WRITECMD_LSB; + + for(int y=0; yheight; y++) { + *data = bitrev(y+1); + data += row_stride; + } + self->full_refresh = true; +} + +void common_hal_sharpdisplay_framebuffer_swapbuffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask) { + // claim SPI bus + if (!common_hal_busio_spi_try_lock(self->bus)) { + return; + } + common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8); + + // set chip select high + common_hal_digitalio_digitalinout_set_value(&self->chip_select, true); + + // output the toggling signal + uint8_t *data = self->bufinfo.buf; + data[0] ^= SHARPMEM_BIT_VCOM_LSB; + +#define PARTIAL_UPDATES (1) +#if PARTIAL_UPDATES + common_hal_busio_spi_write(self->bus, data++, 1); + + // output each changed row + size_t row_stride = common_hal_sharpdisplay_framebuffer_get_row_stride(self); + for(int y=0; yheight; y++) { + if(self->full_refresh || (dirty_row_bitmask[y/8] & (1 << (y & 7)))) { + common_hal_busio_spi_write(self->bus, data, row_stride); + } + data += row_stride; + } + + // output a trailing zero + common_hal_busio_spi_write(self->bus, data, 1); +#else + common_hal_busio_spi_write(self->bus, data, self->bufinfo.len); +#endif + + // set chip select low + common_hal_digitalio_digitalinout_set_value(&self->chip_select, false); + + // release SPI bus + common_hal_busio_spi_unlock(self->bus); + + self->full_refresh = false; +} + +STATIC void sharpdisplay_framebuffer_deinit(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = self_in; + common_hal_sharpdisplay_framebuffer_deinit(self); +} + +STATIC void sharpdisplay_framebuffer_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) { + sharpdisplay_framebuffer_obj_t *self = self_in; + common_hal_sharpdisplay_framebuffer_get_bufinfo(self, bufinfo); +} + +STATIC int sharpdisplay_framebuffer_get_color_depth(mp_obj_t self_in) { + return 1; +} + +STATIC int sharpdisplay_framebuffer_get_height(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = self_in; + return common_hal_sharpdisplay_framebuffer_get_height(self); +} + +STATIC int sharpdisplay_framebuffer_get_width(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = self_in; + return common_hal_sharpdisplay_framebuffer_get_width(self); +} + +STATIC int sharpdisplay_framebuffer_get_first_pixel_offset(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = self_in; + return common_hal_sharpdisplay_framebuffer_get_first_pixel_offset(self); +} + +STATIC bool sharpdisplay_framebuffer_get_pixels_in_byte_share_row(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = self_in; + return common_hal_sharpdisplay_framebuffer_get_pixels_in_byte_share_row(self); +} + +STATIC bool sharpdisplay_framebuffer_get_reverse_pixels_in_byte(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = self_in; + return common_hal_sharpdisplay_framebuffer_get_reverse_pixels_in_byte(self); +} + +STATIC int sharpdisplay_framebuffer_get_row_stride(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = self_in; + return common_hal_sharpdisplay_framebuffer_get_row_stride(self); +} + +STATIC void sharpdisplay_framebuffer_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmask) { + sharpdisplay_framebuffer_obj_t *self = self_in; + common_hal_sharpdisplay_framebuffer_swapbuffers(self, dirty_row_bitmask); +} + +const framebuffer_p_t sharpdisplay_framebuffer_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer) + .deinit = sharpdisplay_framebuffer_deinit, + .get_bufinfo = sharpdisplay_framebuffer_get_bufinfo, + .get_color_depth = sharpdisplay_framebuffer_get_color_depth, + .get_height = sharpdisplay_framebuffer_get_height, + .get_width = sharpdisplay_framebuffer_get_width, + .swapbuffers = sharpdisplay_framebuffer_swapbuffers, + + .get_first_pixel_offset = sharpdisplay_framebuffer_get_first_pixel_offset, + .get_pixels_in_byte_share_row = sharpdisplay_framebuffer_get_pixels_in_byte_share_row, + .get_reverse_pixels_in_byte = sharpdisplay_framebuffer_get_reverse_pixels_in_byte, + .get_row_stride = sharpdisplay_framebuffer_get_row_stride, +}; + +void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t *self) { + gc_collect_ptr(self->framebuffer); + gc_collect_ptr(self->bus); + gc_collect_ptr(self->bufinfo.buf); +} diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h new file mode 100644 index 000000000..8acacc94e --- /dev/null +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h @@ -0,0 +1,60 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-module/framebufferio/FramebufferDisplay.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t framebuffer; + busio_spi_obj_t* bus; + busio_spi_obj_t inline_bus; + digitalio_digitalinout_obj_t chip_select; + mp_buffer_info_t bufinfo; + + uint16_t width, height; + uint32_t baudrate; + + bool full_refresh:1; +} sharpdisplay_framebuffer_obj_t; + +void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_t *self, busio_spi_obj_t *spi, mcu_pin_obj_t *chip_select, int baudrate, int width, int height); +void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask); +void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self); +void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo); +int common_hal_sharpdisplay_framebuffer_get_height(sharpdisplay_framebuffer_obj_t *self); +int common_hal_sharpdisplay_framebuffer_get_width(sharpdisplay_framebuffer_obj_t *self); +void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask); +void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self); +void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self); + +extern const framebuffer_p_t sharpdisplay_framebuffer_proto; + +void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t*); diff --git a/shared-module/sharpdisplay/__init__.c b/shared-module/sharpdisplay/__init__.c new file mode 100644 index 000000000..e69de29bb diff --git a/shared-module/sharpdisplay/__init__.h b/shared-module/sharpdisplay/__init__.h new file mode 100644 index 000000000..e69de29bb diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index 9c074209b..a86ef6396 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -38,6 +38,11 @@ #include "shared-module/displayio/__init__.h" #endif +#if CIRCUITPY_SHARPDISPLAY +#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h" +#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" +#endif + extern size_t blinka_bitmap_data[]; extern displayio_bitmap_t blinka_bitmap; extern displayio_group_t circuitpython_splash; @@ -116,15 +121,21 @@ void supervisor_display_move_memory(void) { grid->inline_tiles = false; } MP_STATE_VM(terminal_tilegrid_tiles) = NULL; - #if CIRCUITPY_RGBMATRIX for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { - if (displays[i].rgbmatrix.base.type == &rgbmatrix_RGBMatrix_type) { - rgbmatrix_rgbmatrix_obj_t * pm = &displays[i].rgbmatrix; + #if CIRCUITPY_RGBMATRIX + if (displays[i].rgbmatrix.base.type == &rgbmatrix_RGBMatrix_type) { + rgbmatrix_rgbmatrix_obj_t * pm = &displays[i].rgbmatrix; common_hal_rgbmatrix_rgbmatrix_reconstruct(pm, NULL); - } + } + #endif + #if CIRCUITPY_SHARPDISPLAY + if (displays[i].bus_base.type == &sharpdisplay_framebuffer_type) { + sharpdisplay_framebuffer_obj_t * sharp = &displays[i].sharpdisplay; + common_hal_sharpdisplay_framebuffer_reconstruct(sharp); + } + #endif } #endif - #endif } size_t blinka_bitmap_data[32] = { -- cgit v1.2.3 From cff448205f165dfd5ec40cc5b336decff045d4cd Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 12 Aug 2020 07:39:28 -0500 Subject: Don't define SHARPDISPLAY when !DISPLAYIO .. even if FULL_BUILD --- py/circuitpy_mpconfig.mk | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'py') diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 1ba71fa02..56060fa59 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -95,7 +95,11 @@ CFLAGS += -DCIRCUITPY_COUNTIO=$(CIRCUITPY_COUNTIO) CIRCUITPY_DISPLAYIO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_DISPLAYIO=$(CIRCUITPY_DISPLAYIO) +ifeq ($(CIRCUITPY_DISPLAYIO),1) CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_FULL_BUILD) +else +CIRCUITPY_FRAMEBUFFERIO ?= 0 +endif CFLAGS += -DCIRCUITPY_FRAMEBUFFERIO=$(CIRCUITPY_FRAMEBUFFERIO) CIRCUITPY_VECTORIO ?= $(CIRCUITPY_DISPLAYIO) -- cgit v1.2.3 From 08ed09acc6c73bae5475735e6e39b10ccd951d36 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 16 Aug 2020 20:38:05 -0500 Subject: makeqstrdata: don't print "compression incrased length" messages This check as implemented is misleading, because it compares the compressed size in bytes (including the length indication) with the source string length in Unicode code points. For English this is approximately fair, but for Japanese this is quite unfair and produces an excess of "increased length" messages. This message might have existed for one of two reasons: * to alert to an improperly function huffman compression * to call attention to a need for a "string is stored uncompressed" case We know by now that the huffman compression is functioning as designed and effective in general. Just to be on the safe side, I did some back-of-the-envelope estimates. I considered these three replacements for "the true source string size, in bytes": + decompressed_len_utf8 = len(decompressed.encode('utf-8')) + decompressed_len_utf16 = len(decompressed.encode('utf-16be')) + decompressed_len_bitsize = ((1+len(decompressed)) * math.ceil(math.log(1+len(values), 2)) + 7) // 8 The third counts how many bits each character requires (fewer than 128 characters in the source character set = 7, fewer than 256 = 8, fewer than 512 = 9, etc, adding a string-terminating value) and is in some way representative of the best way we would be able to store "uncompressed strings". The Japanese translation (largest as of writing) has just a few strings which increase by this metric. However, the amount of loss due to expansion in those cases is outweighed by the cost of adding 1 bit per string to indicate whether it's compressed or not. For instance, in the BOARD=trinket_m0 TRANSLATION=ja build the loss is 47 bytes over 300 strings. Adding 1 bit to each of 300 strings will cost about 37 bytes, leaving just 5 Thumb instructions to implement the code to check and decode "uncompressed" strings in order to break even. --- py/makeqstrdata.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'py') diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index df2c687e5..6132298a5 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -259,8 +259,6 @@ def compress(encoding_table, decompressed, encoded_length_bits, len_translation_ current_bit -= 1 if current_bit != 7: current_byte += 1 - if current_byte > len(decompressed): - print("Note: compression increased length", repr(decompressed), len(decompressed), current_byte, file=sys.stderr) return enc[:current_byte] def qstr_escape(qst): -- cgit v1.2.3 From d01f5dc0bdb3ea98d4cf234b7c08c8cc36694c1a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 17 Aug 2020 17:17:59 -0700 Subject: Turn off terminalio for ja and ko The font is missing many characters and the build needs the space. We can optimize font storage when we get a good font. The serial output will work as usual. --- ports/atmel-samd/mpconfigport.mk | 10 +++++++ py/circuitpy_defns.mk | 5 +++- py/circuitpy_mpconfig.h | 10 +++++-- py/circuitpy_mpconfig.mk | 3 ++ supervisor/shared/display.c | 60 +++++++++++++++++++++++++++------------- supervisor/shared/display.h | 6 ++++ supervisor/shared/serial.c | 2 +- supervisor/supervisor.mk | 4 ++- 8 files changed, 75 insertions(+), 25 deletions(-) (limited to 'py') diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 5788a160b..3fecf867e 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -47,6 +47,16 @@ USB_MSC_EP_NUM_OUT = 1 CIRCUITPY_ULAB = 0 +ifeq ($(TRANSLATION), ja) +RELEASE_NEEDS_CLEAN_BUILD = 1 +CIRCUITPY_TERMINALIO = 0 +endif + +ifeq ($(TRANSLATION), ko) +RELEASE_NEEDS_CLEAN_BUILD = 1 +CIRCUITPY_TERMINALIO = 0 +endif + endif # samd21 # Put samd51-only choices here. diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 515b386f9..b70ae64a8 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -145,7 +145,7 @@ ifeq ($(CIRCUITPY_DIGITALIO),1) SRC_PATTERNS += digitalio/% endif ifeq ($(CIRCUITPY_DISPLAYIO),1) -SRC_PATTERNS += displayio/% terminalio/% fontio/% +SRC_PATTERNS += displayio/% endif ifeq ($(CIRCUITPY_VECTORIO),1) SRC_PATTERNS += vectorio/% @@ -237,6 +237,9 @@ endif ifeq ($(CIRCUITPY_SUPERVISOR),1) SRC_PATTERNS += supervisor/% endif +ifeq ($(CIRCUITPY_TERMINALIO),1) +SRC_PATTERNS += terminalio/% fontio/% +endif ifeq ($(CIRCUITPY_TIME),1) SRC_PATTERNS += time/% endif diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index f0e8adffa..12d667d8f 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -347,16 +347,20 @@ extern const struct _mp_obj_module_t displayio_module; extern const struct _mp_obj_module_t fontio_module; extern const struct _mp_obj_module_t terminalio_module; #define DISPLAYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_displayio), (mp_obj_t)&displayio_module }, -#define FONTIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_fontio), (mp_obj_t)&fontio_module }, -#define TERMINALIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_terminalio), (mp_obj_t)&terminalio_module }, #ifndef CIRCUITPY_DISPLAY_LIMIT #define CIRCUITPY_DISPLAY_LIMIT (1) #endif #else #define DISPLAYIO_MODULE +#define CIRCUITPY_DISPLAY_LIMIT (0) +#endif + +#if CIRCUITPY_DISPLAYIO && CIRCUITPY_TERMINALIO +#define FONTIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_fontio), (mp_obj_t)&fontio_module }, +#define TERMINALIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_terminalio), (mp_obj_t)&terminalio_module }, +#else #define FONTIO_MODULE #define TERMINALIO_MODULE -#define CIRCUITPY_DISPLAY_LIMIT (0) #endif #if CIRCUITPY_FRAMEBUFFERIO diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 56060fa59..bdc1e77d5 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -195,6 +195,9 @@ CFLAGS += -DCIRCUITPY_STRUCT=$(CIRCUITPY_STRUCT) CIRCUITPY_SUPERVISOR ?= 1 CFLAGS += -DCIRCUITPY_SUPERVISOR=$(CIRCUITPY_SUPERVISOR) +CIRCUITPY_TERMINALIO ?= $(CIRCUITPY_DISPLAYIO) +CFLAGS += -DCIRCUITPY_TERMINALIO=$(CIRCUITPY_TERMINALIO) + CIRCUITPY_TIME ?= 1 CFLAGS += -DCIRCUITPY_TIME=$(CIRCUITPY_TIME) diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index 08dd71404..634720d0a 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -29,6 +29,7 @@ #include #include "py/mpstate.h" +#include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/displayio/Group.h" #include "shared-bindings/displayio/Palette.h" #include "shared-bindings/displayio/TileGrid.h" @@ -48,15 +49,21 @@ extern size_t blinka_bitmap_data[]; extern displayio_bitmap_t blinka_bitmap; extern displayio_group_t circuitpython_splash; +#if CIRCUITPY_TERMINALIO static supervisor_allocation* tilegrid_tiles = NULL; +#endif void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { + // Default the scale to 2 because we may show blinka without the terminal for + // languages that don't have font support. + uint8_t scale = 2; + + #if CIRCUITPY_TERMINALIO displayio_tilegrid_t* grid = &supervisor_terminal_text_grid; uint16_t width_in_tiles = (width_px - blinka_bitmap.width) / grid->tile_width; // determine scale based on h - uint8_t scale = 1; - if (width_in_tiles > 80) { - scale = 2; + if (width_in_tiles < 80) { + scale = 1; } width_in_tiles = (width_px - blinka_bitmap.width * scale) / (grid->tile_width * scale); uint16_t height_in_tiles = height_px / (grid->tile_height * scale); @@ -64,7 +71,6 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { if (remaining_pixels > 0) { height_in_tiles += 1; } - circuitpython_splash.scale = scale; uint16_t total_tiles = width_in_tiles * height_in_tiles; @@ -94,34 +100,42 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { grid->full_change = true; common_hal_terminalio_terminal_construct(&supervisor_terminal, grid, &supervisor_terminal_font); + #endif + + circuitpython_splash.scale = scale; } void supervisor_stop_terminal(void) { + #if CIRCUITPY_TERMINALIO if (tilegrid_tiles != NULL) { free_memory(tilegrid_tiles); tilegrid_tiles = NULL; supervisor_terminal_text_grid.inline_tiles = false; supervisor_terminal_text_grid.tiles = NULL; } + #endif } void supervisor_display_move_memory(void) { - #if CIRCUITPY_DISPLAYIO + #if CIRCUITPY_TERMINALIO displayio_tilegrid_t* grid = &supervisor_terminal_text_grid; - if (MP_STATE_VM(terminal_tilegrid_tiles) == NULL || grid->tiles != MP_STATE_VM(terminal_tilegrid_tiles)) { - return; - } - uint16_t total_tiles = grid->width_in_tiles * grid->height_in_tiles; + if (MP_STATE_VM(terminal_tilegrid_tiles) != NULL && + grid->tiles == MP_STATE_VM(terminal_tilegrid_tiles)) { + uint16_t total_tiles = grid->width_in_tiles * grid->height_in_tiles; - tilegrid_tiles = allocate_memory(align32_size(total_tiles), false); - if (tilegrid_tiles != NULL) { - memcpy(tilegrid_tiles->ptr, grid->tiles, total_tiles); - grid->tiles = (uint8_t*) tilegrid_tiles->ptr; - } else { - grid->tiles = NULL; - grid->inline_tiles = false; + tilegrid_tiles = allocate_memory(align32_size(total_tiles), false); + if (tilegrid_tiles != NULL) { + memcpy(tilegrid_tiles->ptr, grid->tiles, total_tiles); + grid->tiles = (uint8_t*) tilegrid_tiles->ptr; + } else { + grid->tiles = NULL; + grid->inline_tiles = false; + } + MP_STATE_VM(terminal_tilegrid_tiles) = NULL; } - MP_STATE_VM(terminal_tilegrid_tiles) = NULL; + #endif + + #if CIRCUITPY_DISPLAYIO for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { #if CIRCUITPY_RGBMATRIX if (displays[i].rgbmatrix.base.type == &rgbmatrix_RGBMatrix_type) { @@ -254,18 +268,26 @@ displayio_tilegrid_t blinka_sprite = { .in_group = true }; +#if CIRCUITPY_TERMINALIO +#define CHILD_COUNT 2 displayio_group_child_t splash_children[2] = { {&blinka_sprite, &blinka_sprite}, {&supervisor_terminal_text_grid, &supervisor_terminal_text_grid} }; +#else +#define CHILD_COUNT 1 +displayio_group_child_t splash_children[1] = { + {&blinka_sprite, &blinka_sprite}, +}; +#endif displayio_group_t circuitpython_splash = { .base = {.type = &displayio_group_type }, .x = 0, .y = 0, .scale = 2, - .size = 2, - .max_size = 2, + .size = CHILD_COUNT, + .max_size = CHILD_COUNT, .children = splash_children, .item_removed = false, .in_group = false, diff --git a/supervisor/shared/display.h b/supervisor/shared/display.h index 2a2ccf46d..4110cfe8e 100644 --- a/supervisor/shared/display.h +++ b/supervisor/shared/display.h @@ -27,6 +27,10 @@ #ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_DISPLAY_H #define MICROPY_INCLUDED_SUPERVISOR_SHARED_DISPLAY_H +#include + +#if CIRCUITPY_TERMINALIO + #include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/displayio/TileGrid.h" #include "shared-bindings/fontio/BuiltinFont.h" @@ -42,6 +46,8 @@ extern displayio_bitmap_t supervisor_terminal_font_bitmap; extern displayio_tilegrid_t supervisor_terminal_text_grid; extern terminalio_terminal_obj_t supervisor_terminal; +#endif + void supervisor_start_terminal(uint16_t width_px, uint16_t height_px); void supervisor_stop_terminal(void); diff --git a/supervisor/shared/serial.c b/supervisor/shared/serial.c index 8eb78a90e..303f89e75 100644 --- a/supervisor/shared/serial.c +++ b/supervisor/shared/serial.c @@ -99,7 +99,7 @@ void serial_write_substring(const char* text, uint32_t length) { if (length == 0) { return; } -#if CIRCUITPY_DISPLAYIO +#if CIRCUITPY_TERMINALIO int errcode; common_hal_terminalio_terminal_write(&supervisor_terminal, (const uint8_t*) text, length, &errcode); #endif diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index a066fc0fd..25b240036 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -110,7 +110,9 @@ ifeq ($(CIRCUITPY_DISPLAYIO), 1) SRC_SUPERVISOR += \ supervisor/shared/display.c - SUPERVISOR_O += $(BUILD)/autogen_display_resources.o + ifeq ($(CIRCUITPY_TERMINALIO), 1) + SUPERVISOR_O += $(BUILD)/autogen_display_resources.o + endif endif ifndef USB_INTERFACE_NAME USB_INTERFACE_NAME = "CircuitPython" -- cgit v1.2.3 From 79a3796b1cd74b376e091e63c1b3a2426ec3187c Mon Sep 17 00:00:00 2001 From: Taku Fukada Date: Tue, 18 Aug 2020 23:21:14 +0900 Subject: Calculate the Huffman codebook without MP_QSTRs --- py/makeqstrdata.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'py') diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 6132298a5..04c893876 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -102,10 +102,6 @@ def translate(translation_file, i18ns): def compute_huffman_coding(translations, qstrs, compression_filename): all_strings = [x[1] for x in translations] - - # go through each qstr and print it out - for _, _, qstr in qstrs.values(): - all_strings.append(qstr) all_strings_concat = "".join(all_strings) counts = collections.Counter(all_strings_concat) cb = huffman.codebook(counts.items()) -- cgit v1.2.3