@@ -564,14 +564,19 @@ STATIC mp_int_t get_pixel_from_font_data(const unsigned char *data, int x, int y
564564 return ((data[y]>>(4 -x))&1 );
565565}
566566
567- microbit_image_obj_t * microbit_image_for_char ( char c) {
567+ void microbit_image_set_from_char ( greyscale_t *img, char c) {
568568 const unsigned char *data = get_font_data_from_char (c);
569- greyscale_t *result = greyscale_new (5 ,5 );
570569 for (int x = 0 ; x < 5 ; ++x) {
571570 for (int y = 0 ; y < 5 ; ++y) {
572- result ->setPixelValue (x, y, get_pixel_from_font_data (data, x, y)*MAX_BRIGHTNESS);
571+ img ->setPixelValue (x, y, get_pixel_from_font_data (data, x, y)*MAX_BRIGHTNESS);
573572 }
574573 }
574+ }
575+
576+
577+ microbit_image_obj_t *microbit_image_for_char (char c) {
578+ greyscale_t *result = greyscale_new (5 ,5 );
579+ microbit_image_set_from_char (result, c);
575580 return (microbit_image_obj_t *)result;
576581}
577582
@@ -799,4 +804,114 @@ const mp_obj_type_t microbit_scrolling_string_iterator_type = {
799804 .locals_dict = NULL ,
800805};
801806
807+ /* * Facade types to present a string as a sequence of images.
808+ * These are necessary to avoid allocation during iteration,
809+ * which may happen in interrupt handlers.
810+ */
811+
812+ typedef struct _string_image_facade_t {
813+ mp_obj_base_t base;
814+ mp_obj_t string;
815+ greyscale_t *image;
816+ } string_image_facade_t ;
817+
818+ static mp_obj_t string_image_facade_subscr (mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
819+ if (value == MP_OBJ_SENTINEL) {
820+ // Fill in image
821+ string_image_facade_t *self = (string_image_facade_t *)self_in;
822+ mp_uint_t len;
823+ const char *text = mp_obj_str_get_data (self->string , &len);
824+ mp_uint_t index = mp_get_index (self->base .type , len, index_in, false );
825+ microbit_image_set_from_char (self->image , text[index]);
826+ return self->image ;
827+ } else {
828+ return MP_OBJ_NULL; // op not supported
829+ }
830+ }
831+
832+ static mp_obj_t facade_unary_op (mp_uint_t op, mp_obj_t self_in) {
833+ string_image_facade_t *self = (string_image_facade_t *)self_in;
834+ switch (op) {
835+ case MP_UNARY_OP_LEN:
836+ return mp_obj_len (self->string );
837+ default : return MP_OBJ_NULL; // op not supported
838+ }
839+ }
840+
841+ static mp_obj_t microbit_facade_iterator (mp_obj_t iterable);
842+
843+ const mp_obj_type_t string_image_facade_type = {
844+ { &mp_type_type },
845+ .name = MP_QSTR_Facade,
846+ .print = NULL ,
847+ .make_new = NULL ,
848+ .call = NULL ,
849+ .unary_op = facade_unary_op,
850+ .binary_op = NULL ,
851+ .attr = NULL ,
852+ .subscr = string_image_facade_subscr,
853+ .getiter = microbit_facade_iterator,
854+ .iternext = NULL ,
855+ .buffer_p = {NULL },
856+ .stream_p = NULL ,
857+ .bases_tuple = NULL ,
858+ NULL
859+ };
860+
861+
862+ typedef struct _facade_iterator_t {
863+ mp_obj_base_t base;
864+ mp_obj_t string;
865+ mp_uint_t index;
866+ greyscale_t *image;
867+ } facade_iterator_t ;
868+
869+ mp_obj_t microbit_string_facade (mp_obj_t string) {
870+ string_image_facade_t *result = m_new_obj (string_image_facade_t );
871+ result->base .type = &string_image_facade_type;
872+ result->string = string;
873+ result->image = greyscale_new (5 ,5 );
874+ return result;
875+ }
876+
877+ static mp_obj_t microbit_facade_iter_next (mp_obj_t iter_in) {
878+ facade_iterator_t *iter = (facade_iterator_t *)iter_in;
879+ mp_uint_t len;
880+ const char *text = mp_obj_str_get_data (iter->string , &len);
881+ if (iter->index >= len) {
882+ return MP_OBJ_STOP_ITERATION;
883+ }
884+ microbit_image_set_from_char (iter->image , text[iter->index ]);
885+ iter->index ++;
886+ return iter->image ;
887+ }
888+
889+ const mp_obj_type_t microbit_facade_iterator_type = {
890+ { &mp_type_type },
891+ .name = MP_QSTR_iterator,
892+ .print = NULL ,
893+ .make_new = NULL ,
894+ .call = NULL ,
895+ .unary_op = NULL ,
896+ .binary_op = NULL ,
897+ .attr = NULL ,
898+ .subscr = NULL ,
899+ .getiter = mp_identity,
900+ .iternext = microbit_facade_iter_next,
901+ .buffer_p = {NULL },
902+ .stream_p = NULL ,
903+ .bases_tuple = NULL ,
904+ NULL
905+ };
906+
907+ mp_obj_t microbit_facade_iterator (mp_obj_t iterable_in) {
908+ facade_iterator_t *result = m_new_obj (facade_iterator_t );
909+ string_image_facade_t *iterable = (string_image_facade_t *)iterable_in;
910+ result->base .type = µbit_facade_iterator_type;
911+ result->string = iterable->string ;
912+ result->image = iterable->image ;
913+ result->index = 0 ;
914+ return result;
915+ }
916+
802917}
0 commit comments