1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 Damien P. George
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 // Modified bt HaaS begin
27 #include <stdio.h>
28 #include <string.h>
29 
30 #include "py/runtime.h"
31 
32 #include "py/objstr.h"
33 
34 #include "ulog/ulog.h"
35 
36 #if MICROPY_PY_FRAMEBUF
37 
38 #include "./font_petme128_8x8.h"
39 
40 #define LOG_TAG "MOD_FRAMEBUF"
41 
42 
43 typedef struct _mp_obj_framebuf_t {
44     mp_obj_base_t base;
45     mp_obj_t buf_obj; // need to store this to prevent GC from reclaiming buf
46     void *buf;
47     uint16_t width, height, stride;
48     uint8_t format;
49 } mp_obj_framebuf_t;
50 
51 typedef struct {
52     char *font_path;
53     FILE* fp;
54     unsigned char font_height;
55     unsigned char font_width;
56     unsigned char is_cn;
57 } font_t;
58 
59 // #if !MICROPY_ENABLE_DYNRUNTIME
60 STATIC const mp_obj_type_t mp_type_framebuf;
61 // #endif
62 
63 typedef void (*setpixel_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int, uint32_t);
64 typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int);
65 typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int, unsigned int, unsigned int, uint32_t);
66 
67 typedef struct _mp_framebuf_p_t {
68     setpixel_t setpixel;
69     getpixel_t getpixel;
70     fill_rect_t fill_rect;
71 } mp_framebuf_p_t;
72 
73 // constants for formats
74 #define FRAMEBUF_MVLSB    (0)
75 #define FRAMEBUF_RGB565   (1)
76 #define FRAMEBUF_GS2_HMSB (5)
77 #define FRAMEBUF_GS4_HMSB (2)
78 #define FRAMEBUF_GS8      (6)
79 #define FRAMEBUF_MHLSB    (3)
80 #define FRAMEBUF_MHMSB    (4)
81 
82 // constants for fonts
83 // 支持中英文 12-32
84 #define FONT_ASC8_8 (808)
85 #define FONT_ASC12_8 (1208)
86 #define FONT_PATH_ASC12_8 "/data/font/ASC12_8"
87 #define FONT_ASC16_8 (1608)
88 #define FONT_PATH_ASC16_8 "/data/font/ASC16_8"
89 #define FONT_ASC24_12 (2412)
90 #define FONT_PATH_ASC24_12 "/data/font/ASC24_12"
91 #define FONT_ASC32_16 (3216)
92 #define FONT_PATH_ASC32_16 "/data/font/ASC32_16"
93 // #define FONT_ASC48_24 (48)
94 // #define FONT_PATH_ASC48_24 "./font/ASC48_24"
95 #define FONT_HZK12 (1212)
96 #define FONT_PATH_HZK12 "/data/font/HZK12"
97 #define FONT_HZK16 (1616)
98 #define FONT_PATH_HZK16 "/data/font/HZK16"
99 #define FONT_HZK24 (2424)
100 #define FONT_PATH_HZK24 "/data/font/HZK24"
101 #define FONT_HZK32 (3232)
102 #define FONT_PATH_HZK32 "/data/font/HZK32"
103 
104 static font_t ASC8_8 = {NULL, NULL, 8, 8, 0};
105 static font_t ASC12_8 = {FONT_PATH_ASC12_8, NULL, 12, 8, 0};
106 static font_t ASC16_8 = {FONT_PATH_ASC16_8, NULL, 16, 8, 0};
107 static font_t ASC24_12 = {FONT_PATH_ASC24_12, NULL, 24, 12, 0};
108 static font_t ASC32_16 = {FONT_PATH_ASC32_16, NULL, 32, 16, 0};
109 
110 static font_t HZK12 = {FONT_PATH_HZK12, NULL, 12, 12, 1};
111 static font_t HZK16 = {FONT_PATH_HZK16, NULL, 16, 16, 1};
112 static font_t HZK24 = {FONT_PATH_HZK24, NULL, 24, 24, 1};
113 static font_t HZK32 = {FONT_PATH_HZK32, NULL, 32, 32, 1};
114 
115 // Functions for MHLSB and MHMSB
116 
mono_horiz_setpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,uint32_t col)117 STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
118     size_t index = (x + y * fb->stride) >> 3;
119     unsigned int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
120     ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
121 }
122 
mono_horiz_getpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y)123 STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
124     size_t index = (x + y * fb->stride) >> 3;
125     unsigned int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
126     return (((uint8_t *)fb->buf)[index] >> (offset)) & 0x01;
127 }
128 
mono_horiz_fill_rect(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,unsigned int w,unsigned int h,uint32_t col)129 STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
130     unsigned int reverse = fb->format == FRAMEBUF_MHMSB;
131     unsigned int advance = fb->stride >> 3;
132     while (w--) {
133         uint8_t *b = &((uint8_t *)fb->buf)[(x >> 3) + y * advance];
134         unsigned int offset = reverse ?  x & 7 : 7 - (x & 7);
135         for (unsigned int hh = h; hh; --hh) {
136             *b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
137             b += advance;
138         }
139         ++x;
140     }
141 }
142 
143 // Functions for MVLSB format
144 
mvlsb_setpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,uint32_t col)145 STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
146     size_t index = (y >> 3) * fb->stride + x;
147     uint8_t offset = y & 0x07;
148     ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
149 }
150 
mvlsb_getpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y)151 STATIC uint32_t mvlsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
152     return (((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x] >> (y & 0x07)) & 0x01;
153 }
154 
mvlsb_fill_rect(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,unsigned int w,unsigned int h,uint32_t col)155 STATIC void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
156     while (h--) {
157         uint8_t *b = &((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x];
158         uint8_t offset = y & 0x07;
159         for (unsigned int ww = w; ww; --ww) {
160             *b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
161             ++b;
162         }
163         ++y;
164     }
165 }
166 
167 // Functions for RGB565 format
168 
rgb565_setpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,uint32_t col)169 STATIC void rgb565_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
170     ((uint16_t *)fb->buf)[x + y * fb->stride] = col;
171 }
172 
rgb565_getpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y)173 STATIC uint32_t rgb565_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
174     return ((uint16_t *)fb->buf)[x + y * fb->stride];
175 }
176 
rgb565_fill_rect(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,unsigned int w,unsigned int h,uint32_t col)177 STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
178     uint16_t *b = &((uint16_t *)fb->buf)[x + y * fb->stride];
179     while (h--) {
180         for (unsigned int ww = w; ww; --ww) {
181             *b++ = col;
182         }
183         b += fb->stride - w;
184     }
185 }
186 
187 // Functions for GS2_HMSB format
188 
gs2_hmsb_setpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,uint32_t col)189 STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
190     uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
191     uint8_t shift = (x & 0x3) << 1;
192     uint8_t mask = 0x3 << shift;
193     uint8_t color = (col & 0x3) << shift;
194     *pixel = color | (*pixel & (~mask));
195 }
196 
gs2_hmsb_getpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y)197 STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
198     uint8_t pixel = ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
199     uint8_t shift = (x & 0x3) << 1;
200     return (pixel >> shift) & 0x3;
201 }
202 
gs2_hmsb_fill_rect(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,unsigned int w,unsigned int h,uint32_t col)203 STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
204     for (unsigned int xx = x; xx < x + w; xx++) {
205         for (unsigned int yy = y; yy < y + h; yy++) {
206             gs2_hmsb_setpixel(fb, xx, yy, col);
207         }
208     }
209 }
210 
211 // Functions for GS4_HMSB format
212 
gs4_hmsb_setpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,uint32_t col)213 STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
214     uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
215 
216     if (x % 2) {
217         *pixel = ((uint8_t)col & 0x0f) | (*pixel & 0xf0);
218     } else {
219         *pixel = ((uint8_t)col << 4) | (*pixel & 0x0f);
220     }
221 }
222 
gs4_hmsb_getpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y)223 STATIC uint32_t gs4_hmsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
224     if (x % 2) {
225         return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] & 0x0f;
226     }
227 
228     return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] >> 4;
229 }
230 
gs4_hmsb_fill_rect(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,unsigned int w,unsigned int h,uint32_t col)231 STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
232     col &= 0x0f;
233     uint8_t *pixel_pair = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
234     uint8_t col_shifted_left = col << 4;
235     uint8_t col_pixel_pair = col_shifted_left | col;
236     unsigned int pixel_count_till_next_line = (fb->stride - w) >> 1;
237     bool odd_x = (x % 2 == 1);
238 
239     while (h--) {
240         unsigned int ww = w;
241 
242         if (odd_x && ww > 0) {
243             *pixel_pair = (*pixel_pair & 0xf0) | col;
244             pixel_pair++;
245             ww--;
246         }
247 
248         memset(pixel_pair, col_pixel_pair, ww >> 1);
249         pixel_pair += ww >> 1;
250 
251         if (ww % 2) {
252             *pixel_pair = col_shifted_left | (*pixel_pair & 0x0f);
253             if (!odd_x) {
254                 pixel_pair++;
255             }
256         }
257 
258         pixel_pair += pixel_count_till_next_line;
259     }
260 }
261 
262 // Functions for GS8 format
263 
gs8_setpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,uint32_t col)264 STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
265     uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
266     *pixel = col & 0xff;
267 }
268 
gs8_getpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y)269 STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
270     return ((uint8_t *)fb->buf)[(x + y * fb->stride)];
271 }
272 
gs8_fill_rect(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,unsigned int w,unsigned int h,uint32_t col)273 STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
274     uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
275     while (h--) {
276         memset(pixel, col, w);
277         pixel += fb->stride;
278     }
279 }
280 
281 STATIC mp_framebuf_p_t formats[] = {
282     [FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
283     [FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
284     [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
285     [FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
286     [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect},
287     [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
288     [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
289 };
290 
setpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y,uint32_t col)291 static inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
292     formats[fb->format].setpixel(fb, x, y, col);
293 }
294 
getpixel(const mp_obj_framebuf_t * fb,unsigned int x,unsigned int y)295 static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
296     return formats[fb->format].getpixel(fb, x, y);
297 }
298 
fill_rect(const mp_obj_framebuf_t * fb,int x,int y,int w,int h,uint32_t col)299 STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
300     if (h < 1 || w < 1 || x + w <= 0 || y + h <= 0 || y >= fb->height || x >= fb->width) {
301         // No operation needed.
302         return;
303     }
304 
305     // clip to the framebuffer
306     int xend = MIN(fb->width, x + w);
307     int yend = MIN(fb->height, y + h);
308     x = MAX(x, 0);
309     y = MAX(y, 0);
310 
311     formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col);
312 }
313 
framebuf_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)314 STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
315     mp_arg_check_num(n_args, n_kw, 4, 5, false);
316 
317     mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t);
318     o->base.type = type;
319     o->buf_obj = args[0];
320 
321     mp_buffer_info_t bufinfo;
322     mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
323     o->buf = bufinfo.buf;
324 
325     o->width = mp_obj_get_int(args[1]);
326     o->height = mp_obj_get_int(args[2]);
327     o->format = mp_obj_get_int(args[3]);
328     if (n_args >= 5) {
329         o->stride = mp_obj_get_int(args[4]);
330     } else {
331         o->stride = o->width;
332     }
333 
334     switch (o->format) {
335         case FRAMEBUF_MVLSB:
336         case FRAMEBUF_RGB565:
337             break;
338         case FRAMEBUF_MHLSB:
339         case FRAMEBUF_MHMSB:
340             o->stride = (o->stride + 7) & ~7;
341             break;
342         case FRAMEBUF_GS2_HMSB:
343             o->stride = (o->stride + 3) & ~3;
344             break;
345         case FRAMEBUF_GS4_HMSB:
346             o->stride = (o->stride + 1) & ~1;
347             break;
348         case FRAMEBUF_GS8:
349             break;
350         default:
351             mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
352     }
353 
354     return MP_OBJ_FROM_PTR(o);
355 }
356 
framebuf_get_buffer(mp_obj_t self_in,mp_buffer_info_t * bufinfo,mp_uint_t flags)357 STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
358     (void)flags;
359     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);
360     bufinfo->buf = self->buf;
361     bufinfo->len = self->stride * self->height * (self->format == FRAMEBUF_RGB565 ? 2 : 1);
362     bufinfo->typecode = 'B'; // view framebuf as bytes
363     return 0;
364 }
365 
framebuf_fill(mp_obj_t self_in,mp_obj_t col_in)366 STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) {
367     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);
368     mp_int_t col = mp_obj_get_int(col_in);
369     formats[self->format].fill_rect(self, 0, 0, self->width, self->height, col);
370     return mp_const_none;
371 }
372 STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill);
373 
framebuf_fill_rect(size_t n_args,const mp_obj_t * args)374 STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) {
375     (void)n_args;
376 
377     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
378     mp_int_t x = mp_obj_get_int(args[1]);
379     mp_int_t y = mp_obj_get_int(args[2]);
380     mp_int_t width = mp_obj_get_int(args[3]);
381     mp_int_t height = mp_obj_get_int(args[4]);
382     mp_int_t col = mp_obj_get_int(args[5]);
383 
384     fill_rect(self, x, y, width, height, col);
385 
386     return mp_const_none;
387 }
388 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect);
389 
framebuf_pixel(size_t n_args,const mp_obj_t * args)390 STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) {
391     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
392     mp_int_t x = mp_obj_get_int(args[1]);
393     mp_int_t y = mp_obj_get_int(args[2]);
394     if (0 <= x && x < self->width && 0 <= y && y < self->height) {
395         if (n_args == 3) {
396             // get
397             return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y));
398         } else {
399             // set
400             setpixel(self, x, y, mp_obj_get_int(args[3]));
401         }
402     }
403     return mp_const_none;
404 }
405 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel);
406 
framebuf_hline(size_t n_args,const mp_obj_t * args)407 STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) {
408     (void)n_args;
409 
410     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
411     mp_int_t x = mp_obj_get_int(args[1]);
412     mp_int_t y = mp_obj_get_int(args[2]);
413     mp_int_t w = mp_obj_get_int(args[3]);
414     mp_int_t col = mp_obj_get_int(args[4]);
415 
416     fill_rect(self, x, y, w, 1, col);
417 
418     return mp_const_none;
419 }
420 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline);
421 
framebuf_vline(size_t n_args,const mp_obj_t * args)422 STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) {
423     (void)n_args;
424 
425     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
426     mp_int_t x = mp_obj_get_int(args[1]);
427     mp_int_t y = mp_obj_get_int(args[2]);
428     mp_int_t h = mp_obj_get_int(args[3]);
429     mp_int_t col = mp_obj_get_int(args[4]);
430 
431     fill_rect(self, x, y, 1, h, col);
432 
433     return mp_const_none;
434 }
435 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline);
436 
framebuf_rect(size_t n_args,const mp_obj_t * args)437 STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) {
438     (void)n_args;
439 
440     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
441     mp_int_t x = mp_obj_get_int(args[1]);
442     mp_int_t y = mp_obj_get_int(args[2]);
443     mp_int_t w = mp_obj_get_int(args[3]);
444     mp_int_t h = mp_obj_get_int(args[4]);
445     mp_int_t col = mp_obj_get_int(args[5]);
446 
447     fill_rect(self, x, y, w, 1, col);
448     fill_rect(self, x, y + h - 1, w, 1, col);
449     fill_rect(self, x, y, 1, h, col);
450     fill_rect(self, x + w - 1, y, 1, h, col);
451 
452     return mp_const_none;
453 }
454 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect);
455 
framebuf_line(size_t n_args,const mp_obj_t * args)456 STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
457     (void)n_args;
458 
459     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
460     mp_int_t x1 = mp_obj_get_int(args[1]);
461     mp_int_t y1 = mp_obj_get_int(args[2]);
462     mp_int_t x2 = mp_obj_get_int(args[3]);
463     mp_int_t y2 = mp_obj_get_int(args[4]);
464     mp_int_t col = mp_obj_get_int(args[5]);
465 
466     mp_int_t dx = x2 - x1;
467     mp_int_t sx;
468     if (dx > 0) {
469         sx = 1;
470     } else {
471         dx = -dx;
472         sx = -1;
473     }
474 
475     mp_int_t dy = y2 - y1;
476     mp_int_t sy;
477     if (dy > 0) {
478         sy = 1;
479     } else {
480         dy = -dy;
481         sy = -1;
482     }
483 
484     bool steep;
485     if (dy > dx) {
486         mp_int_t temp;
487         temp = x1;
488         x1 = y1;
489         y1 = temp;
490         temp = dx;
491         dx = dy;
492         dy = temp;
493         temp = sx;
494         sx = sy;
495         sy = temp;
496         steep = true;
497     } else {
498         steep = false;
499     }
500 
501     mp_int_t e = 2 * dy - dx;
502     for (mp_int_t i = 0; i < dx; ++i) {
503         if (steep) {
504             if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) {
505                 setpixel(self, y1, x1, col);
506             }
507         } else {
508             if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) {
509                 setpixel(self, x1, y1, col);
510             }
511         }
512         while (e >= 0) {
513             y1 += sy;
514             e -= 2 * dx;
515         }
516         x1 += sx;
517         e += 2 * dy;
518     }
519 
520     if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) {
521         setpixel(self, x2, y2, col);
522     }
523 
524     return mp_const_none;
525 }
526 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line);
527 
framebuf_blit(size_t n_args,const mp_obj_t * args)528 STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
529     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
530     mp_obj_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf));
531     if (source_in == MP_OBJ_NULL) {
532         mp_raise_TypeError(NULL);
533     }
534     mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in);
535 
536     mp_int_t x = mp_obj_get_int(args[2]);
537     mp_int_t y = mp_obj_get_int(args[3]);
538     mp_int_t key = -1;
539     if (n_args > 4) {
540         key = mp_obj_get_int(args[4]);
541     }
542 
543     if (
544         (x >= self->width) ||
545         (y >= self->height) ||
546         (-x >= source->width) ||
547         (-y >= source->height)
548         ) {
549         // Out of bounds, no-op.
550         return mp_const_none;
551     }
552 
553     // Clip.
554     int x0 = MAX(0, x);
555     int y0 = MAX(0, y);
556     int x1 = MAX(0, -x);
557     int y1 = MAX(0, -y);
558     int x0end = MIN(self->width, x + source->width);
559     int y0end = MIN(self->height, y + source->height);
560 
561     for (; y0 < y0end; ++y0) {
562         int cx1 = x1;
563         for (int cx0 = x0; cx0 < x0end; ++cx0) {
564             uint32_t col = getpixel(source, cx1, y1);
565             if (col != (uint32_t)key) {
566                 setpixel(self, cx0, y0, col);
567             }
568             ++cx1;
569         }
570         ++y1;
571     }
572     return mp_const_none;
573 }
574 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 5, framebuf_blit);
575 
framebuf_scroll(mp_obj_t self_in,mp_obj_t xstep_in,mp_obj_t ystep_in)576 STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) {
577     mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);
578     mp_int_t xstep = mp_obj_get_int(xstep_in);
579     mp_int_t ystep = mp_obj_get_int(ystep_in);
580     int sx, y, xend, yend, dx, dy;
581     if (xstep < 0) {
582         sx = 0;
583         xend = self->width + xstep;
584         dx = 1;
585     } else {
586         sx = self->width - 1;
587         xend = xstep - 1;
588         dx = -1;
589     }
590     if (ystep < 0) {
591         y = 0;
592         yend = self->height + ystep;
593         dy = 1;
594     } else {
595         y = self->height - 1;
596         yend = ystep - 1;
597         dy = -1;
598     }
599     for (; y != yend; y += dy) {
600         for (int x = sx; x != xend; x += dx) {
601             setpixel(self, x, y, getpixel(self, x - xstep, y - ystep));
602         }
603     }
604     return mp_const_none;
605 }
606 STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll);
607 
hz_get_mat(font_t * font,char * chr,unsigned char * mat)608 STATIC unsigned char hz_get_mat(font_t* font, char * chr, unsigned char * mat) {
609 
610     unsigned char font_width;
611     if(font == &HZK12){
612         font_width = 16;
613     }else{
614         font_width = font->font_width;
615     }
616 
617     unsigned char size = font->font_height;
618     unsigned char offset_step = (font->font_height * font_width / 8);
619     unsigned long offset = 0;
620 
621 	int t1 = (int) (*(chr) & 0xff);
622 	int t2 = (int) (*(chr + 1) & 0xff);
623 
624     if (t1 > 0xa0) {
625         if (size == 40 || size == 48) {
626             offset = ((t1 - 0xa1 - 0x0f) * 94 + (t2 - 0xa1)) * offset_step;
627         } else if (size == 12 || size == 16 || size == 24 || size == 32) {
628             offset = ((t1 - 0xa1) * 94 + (t2 - 0xa1)) * offset_step;
629         }
630     } else {
631         offset = (t1 + 156 - 1) * offset_step;
632     }
633 
634     if(font->fp == NULL){
635         font->fp = fopen(font->font_path , "rb");
636         if(font->fp == NULL){
637             LOGE(LOG_TAG,"error no font file %s\n", font->font_path);
638             memset(mat, 0, offset_step);
639             return 0;
640         }
641     }
642 
643     fseek(font->fp, offset, SEEK_SET);
644 	fread(mat, offset_step, 1, font->fp);
645 
646     return 1;
647 }
648 
hz_print_mat(mp_obj_framebuf_t * self,mp_int_t x,mp_int_t y,mp_int_t col,font_t * font,unsigned char * mat,mp_int_t zoom)649 STATIC void hz_print_mat(mp_obj_framebuf_t *self, mp_int_t x, mp_int_t y, mp_int_t col, font_t* font, unsigned char * mat, mp_int_t zoom) {
650     char key[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
651     if (font->font_height == 40 || font->font_height == 48) {
652         for (int i = 0; i < font->font_height; i++) {
653             for (int j = 0; j < font->font_width; j++) {
654                 int index = i * font->font_width + j;
655                 int flag = mat[index / 8] & key[index % 8];
656                 if(flag > 0){
657                     for(int r = 0; r < zoom; r++) {
658                         setpixel(self, x + j * zoom + r, y + i * zoom, col);
659                         for(int r = 0; r < zoom; r++) {
660                             setpixel(self, x + j * zoom, y + i * zoom + r, col);
661                         }
662                     }
663                 }
664             }
665         }
666     } else if (font->font_height == 16 || font->font_height == 24 || font->font_height == 32) {
667         for (int i = 0; i < font->font_height; i++) {
668             for (int j = 0; j < font->font_width; j++) {
669                 int index = j * font->font_width + i;
670                 int flag = mat[index / 8] & key[index % 8];
671                 if(flag > 0){
672                     for(int r = 0; r < zoom; r++) {
673                         setpixel(self, x + j * zoom + r, y + i * zoom, col);
674                         for(int r = 0; r < zoom; r++) {
675                             setpixel(self, x + j * zoom, y + i * zoom + r, col);
676                         }
677                     }
678                 }
679             }
680         }
681     } else if (font->font_height == 12) {
682         for (int i = 0; i < 12; i++) {
683             for (int j = 0; j < 12; j++) {
684                 int index = j * 16 + i;
685                 int flag = mat[index / 8] & key[index % 8];
686                 if(flag > 0){
687                     for(int r = 0; r < zoom; r++) {
688                         setpixel(self, x + j * zoom + r, y + i * zoom, col);
689                         for(int r = 0; r < zoom; r++) {
690                             setpixel(self, x + j * zoom, y + i * zoom + r, col);
691                         }
692                     }
693                 }
694             }
695         }
696     }
697 }
698 
asc_get_mat(font_t * font,char * chr,unsigned char * mat)699 STATIC unsigned char asc_get_mat(font_t* font, char * chr, unsigned char * mat){
700     int ascii = (int) (*chr);
701     if (ascii > 127 || ascii < 32) {
702         LOGE(LOG_TAG,"error : input char is invaild!");
703         return;
704     }
705 
706     unsigned char offset_step = (font->font_width * font->font_height / 8);
707     long offset = (ascii - 32) *  offset_step;
708 
709     if(font->fp == NULL){
710         font->fp = fopen(font->font_path , "rb");
711         if(font->fp == NULL){
712             LOGE(LOG_TAG,"error no font file %s\n", font->font_path);
713             memset(mat, 0, offset_step);
714             return 0;
715         }
716     }
717 
718     fseek(font->fp, offset, SEEK_SET);
719 	fread(mat, offset_step, 1, font->fp);
720 
721     return 1;
722 }
723 
asc_print_mat(mp_obj_framebuf_t * self,mp_int_t x,mp_int_t y,mp_int_t col,font_t * font,unsigned char * mat,mp_int_t zoom)724 STATIC void asc_print_mat(mp_obj_framebuf_t *self, mp_int_t x, mp_int_t y, mp_int_t col, font_t* font, unsigned char * mat, mp_int_t zoom) {
725     char key[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
726     if (font->font_height == 12 || font->font_height == 48) {
727 		for (int i = 0; i < font->font_height; i++) {
728 			for (int j = 0; j < font->font_width; j++) {
729 				int index = i * font->font_width + j;
730 				int flag = mat[index / 8] & key[index % 8];
731                 if(flag > 0){
732                     for(int r = 0; r < zoom; r++) {
733                         setpixel(self, x + j * zoom + r, y + i * zoom, col);
734                         for(int r = 0; r < zoom; r++) {
735                             setpixel(self, x + j * zoom, y + i * zoom + r, col);
736                         }
737                     }
738                 }
739 			}
740 		}
741 		} else {
742 		for (int i = 0; i < font->font_height; i++) {
743 			for (int j = 0; j < font->font_width; j++) {
744 					int index = j * font->font_height + i;
745 				int flag = mat[index / 8] & key[index % 8];
746                 if(flag > 0){
747                     for(int r = 0; r < zoom; r++) {
748                         setpixel(self, x + j * zoom + r, y + i * zoom, col);
749                         for(int r = 0; r < zoom; r++) {
750                             setpixel(self, x + j * zoom, y + i * zoom + r, col);
751                         }
752                     }
753                 }
754 			}
755 		}
756 	}
757 }
758 
framebuf_text_helper(mp_obj_framebuf_t * self,size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)759 STATIC mp_obj_t framebuf_text_helper(mp_obj_framebuf_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
760     // extract arguments
761     enum { ARG_s, ARG_x, ARG_y, ARG_c, ARG_size, ARG_zoom, ARG_space, ARG_font};
762     static const mp_arg_t allowed_args[] = {
763         { MP_QSTR_s, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE}},
764         { MP_QSTR_x, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0}},
765         { MP_QSTR_y, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0}},
766         { MP_QSTR_c, MP_ARG_INT, {.u_int = 1}},
767         { MP_QSTR_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = -1}},
768         { MP_QSTR_zoom, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1}},
769         { MP_QSTR_space, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0}},
770         { MP_QSTR_font, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = -1}},
771     };
772 
773     // parse args
774     mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
775     mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
776 
777     mp_int_t x0 = args[ARG_x].u_int;
778     mp_int_t y0 = args[ARG_y].u_int;
779     mp_int_t font = args[ARG_font].u_int;
780     mp_int_t size = args[ARG_size].u_int;
781     mp_int_t col = args[ARG_c].u_int;
782     mp_int_t space = args[ARG_space].u_int;
783     mp_int_t zoom = args[ARG_zoom].u_int;
784 
785     mp_check_self(mp_obj_is_str_or_bytes(args[ARG_s].u_obj));
786     GET_STR_DATA_LEN(args[ARG_s].u_obj, str, str_len);
787 
788     if(str_len == 0)
789         return mp_const_none;
790 
791     font_t *cn_font;
792     font_t *en_font;
793 
794     if(font != -1){
795         switch (font)
796         {
797         case FONT_ASC8_8:
798             cn_font = NULL;
799             en_font = NULL;
800             break;
801 
802         case FONT_ASC12_8:
803             cn_font = NULL;
804             en_font = &ASC12_8;
805             break;
806         case FONT_ASC16_8:
807             cn_font = NULL;
808             en_font = &ASC16_8;
809             break;
810         case FONT_ASC24_12:
811             cn_font = NULL;
812             en_font = &ASC24_12;
813             break;
814         case FONT_ASC32_16:
815             cn_font = NULL;
816             en_font = &ASC32_16;
817             break;
818 
819         case FONT_HZK12:
820             cn_font = &HZK12;
821             en_font = NULL;
822             break;
823         case FONT_HZK16:
824             cn_font = &HZK16;
825             en_font = NULL;
826             break;
827         case FONT_HZK24:
828             cn_font = &HZK24;
829             en_font = NULL;
830             break;
831         case FONT_HZK32:
832             cn_font = &HZK32;
833             en_font = NULL;
834             break;
835         default:
836             LOGE(LOG_TAG,"error wrong font\n");
837             break;
838         }
839     }
840 
841     if(size != -1){
842         switch(size){
843         case 8:
844             cn_font = NULL;
845             en_font = NULL;
846             break;
847         case 12:
848             cn_font = &HZK12;
849             en_font = &ASC12_8;
850             break;
851         case 16:
852             cn_font = &HZK16;
853             en_font = &ASC16_8;
854             break;
855         case 24:
856             cn_font = &HZK24;
857             en_font = &ASC24_12;
858             break;
859         case 32:
860             cn_font = &HZK32;
861             en_font = &ASC32_16;
862             break;
863         default:
864             LOGE(LOG_TAG,"error wrong size. only support 12 16 24 32\n");
865         }
866     }
867 
868     if(font == -1 && size == -1){
869         cn_font = &HZK12;
870         en_font = &ASC8_8;
871     }
872 
873     int x = x0;
874 
875     // loop over chars
876     for (int i=0; *(str+i); ++i) {
877         int chr = *(uint8_t *)(str+i);
878         if(chr > 127){
879             // cn
880             if(cn_font == NULL){
881                 LOGE(LOG_TAG,"error wrong chr. no cn font selected\n");
882                 continue;
883             }
884 
885             unsigned char * chr_data;
886 
887             if(cn_font == &HZK12){
888                 chr_data = (unsigned char *)malloc(16 * cn_font->font_height/8);
889             }else{
890                 chr_data = (unsigned char *)malloc(cn_font->font_width*cn_font->font_height/8);
891             }
892 
893             if(hz_get_mat(cn_font, str+i, chr_data))
894                 hz_print_mat(self, x, y0, col, cn_font, chr_data, zoom);
895             ++i;
896             x += cn_font->font_width * zoom + space;
897             free(chr_data);
898         }
899         if (chr >= 32 && chr <= 127) {
900             // en
901             if (en_font == &ASC8_8) {
902                 // get char data
903                 const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8];
904 
905                 for (int j = 0; j < 8; j++, x++) {
906                     if (0 <= x && x < self->width) {
907                         uint vline_data = chr_data[j];
908                         for (int y = y0; vline_data; vline_data >>= 1, y++) {
909                             if (vline_data & 1) {
910                                 if (0 <= y && y < self->height) {
911                                     setpixel(self, x, y, col);
912                                 }
913                             }
914                         }
915                     }
916                 }
917 
918                 x += space;
919 
920             }else if(en_font== NULL){
921                 LOGE(LOG_TAG,"error wrong chr. no en font selected\n");
922                 continue;
923             }else{
924                 unsigned char * chr_data = (unsigned char *)malloc(cn_font->font_width*cn_font->font_height/8);
925                 if(asc_get_mat(en_font, str+i, chr_data))
926                     asc_print_mat(self, x, y0, col, en_font, chr_data, zoom);
927                 x += en_font->font_width * zoom + space;
928                 free(chr_data);
929             }
930         }
931     }
932 
933     if(cn_font && cn_font->fp){
934         fclose(cn_font->fp);
935         cn_font->fp = NULL;
936     }
937     if(en_font && en_font->fp){
938         fclose(en_font->fp);
939         en_font->fp = NULL;
940     }
941 
942     return mp_const_none;
943 }
944 
framebuf_text(size_t n_args,const mp_obj_t * args,mp_map_t * kw_args)945 STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
946     framebuf_text_helper(args[0], n_args - 1, args + 1, kw_args);
947     return mp_const_none;
948 }
949 MP_DEFINE_CONST_FUN_OBJ_KW(framebuf_text_obj, 1, framebuf_text);
950 
951 // #if !MICROPY_ENABLE_DYNRUNTIME
952 STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = {
953     { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) },
954     { MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) },
955     { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&framebuf_pixel_obj) },
956     { MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&framebuf_hline_obj) },
957     { MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) },
958     { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) },
959     { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) },
960     { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) },
961     { MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) },
962     { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) },
963 };
964 STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
965 
966 STATIC const mp_obj_type_t mp_type_framebuf = {
967     { &mp_type_type },
968     .name = MP_QSTR_FrameBuffer,
969     .make_new = framebuf_make_new,
970     .buffer_p = { .get_buffer = framebuf_get_buffer },
971     .locals_dict = (mp_obj_dict_t *)&framebuf_locals_dict,
972 };
973 // #endif
974 
975 // this factory function is provided for backwards compatibility with old FrameBuffer1 class
legacy_framebuffer1(size_t n_args,const mp_obj_t * args)976 STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) {
977     mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t);
978     o->base.type = &mp_type_framebuf;
979 
980     mp_buffer_info_t bufinfo;
981     mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
982     o->buf = bufinfo.buf;
983 
984     o->width = mp_obj_get_int(args[1]);
985     o->height = mp_obj_get_int(args[2]);
986     o->format = FRAMEBUF_MVLSB;
987     if (n_args >= 4) {
988         o->stride = mp_obj_get_int(args[3]);
989     } else {
990         o->stride = o->width;
991     }
992 
993     return MP_OBJ_FROM_PTR(o);
994 }
995 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1);
996 
997 // #if !MICROPY_ENABLE_DYNRUNTIME
998 STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
999     { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) },
1000     { MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) },
1001     { MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) },
1002     { MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
1003     { MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
1004     { MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) },
1005     { MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) },
1006     { MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) },
1007     { MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) },
1008     { MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) },
1009     { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) },
1010 
1011     { MP_ROM_QSTR(MP_QSTR_ASC8_8), MP_ROM_INT(FONT_ASC8_8) },
1012     { MP_ROM_QSTR(MP_QSTR_ASC12_8), MP_ROM_INT(FONT_ASC12_8) },
1013     { MP_ROM_QSTR(MP_QSTR_ASC16_8), MP_ROM_INT(FONT_ASC16_8) },
1014     { MP_ROM_QSTR(MP_QSTR_ASC24_12), MP_ROM_INT(FONT_ASC24_12) },
1015     { MP_ROM_QSTR(MP_QSTR_ASC32_16), MP_ROM_INT(FONT_ASC32_16) },
1016 
1017     { MP_ROM_QSTR(MP_QSTR_HZK12), MP_ROM_INT(FONT_HZK12) },
1018     { MP_ROM_QSTR(MP_QSTR_HZK16), MP_ROM_INT(FONT_HZK16) },
1019     { MP_ROM_QSTR(MP_QSTR_HZK24), MP_ROM_INT(FONT_HZK24) },
1020     { MP_ROM_QSTR(MP_QSTR_HZK32), MP_ROM_INT(FONT_HZK32) },
1021 };
1022 
1023 STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table);
1024 
1025 const mp_obj_module_t mp_module_framebuf = {
1026     .base = { &mp_type_module },
1027     .globals = (mp_obj_dict_t *)&framebuf_module_globals,
1028 };
1029 // #endif
1030 
1031 #endif // MICROPY_PY_FRAMEBUF
1032 
1033 // Modified bt HaaS end
1034