1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include <stdint.h>
6 
7 #include "amp_config.h"
8 #include "amp_defines.h"
9 #include "board_mgr.h"
10 #include "be_inl.h"
11 #include "fontlib.h"
12 
13 #define MOD_STR "LCD"
14 
15 typedef struct lcd_handle {
16     uint32_t width;
17     uint32_t height;
18 } lcd_handle_t;
19 
20 static lcd_handle_t *lcd_handle = NULL;
21 
lcd_init(uint32_t width,uint32_t height)22 static int8_t lcd_init(uint32_t width, uint32_t height)
23 {
24     if (NULL != lcd_handle) {
25         return -1;
26     }
27     lcd_handle_t *new_handle = aos_calloc(1, sizeof(*new_handle));
28     if (NULL == new_handle) {
29         return -1;
30     }
31     amp_hal_lcd_init(NULL);
32     new_handle->height = height;
33     new_handle->width  = width;
34     lcd_handle         = new_handle;
35     return 0;
36 }
37 
lcd_deinit(void)38 static int8_t lcd_deinit(void)
39 {
40     if (NULL != lcd_handle) {
41         aos_free(lcd_handle);
42         lcd_handle = NULL;
43     }
44     return 0;
45 }
46 
lcd_draw_char(uint16_t x,uint16_t y,uint8_t num,uint8_t size,uint32_t fcolor)47 static int8_t lcd_draw_char(uint16_t x, uint16_t y, uint8_t num, uint8_t size,
48                             uint32_t fcolor)
49 {
50     uint8_t i        = 0;
51     uint8_t j        = 0;
52     uint8_t temp     = 0;
53     uint16_t xtemp   = x;
54     uint16_t ytemp   = y;
55     uint8_t char_len = 0;
56     uint8_t *pos     = NULL;
57     num              = num - ' ';
58     if (12 == size) {
59         pos      = (uint8_t *)&g_asc2_1206[num];
60         char_len = 12;
61     } else if (16 == size) {
62         pos      = (uint8_t *)&g_asc2_1608[num];
63         char_len = 16;
64     } else if (24 == size) {
65         pos      = (uint8_t *)&g_asc2_2412[num];
66         char_len = 36;
67     } else if (36 == size) {
68         pos      = (uint8_t *)&g_asc2_3636[num];
69         char_len = 90;
70     } else {
71         return -1;
72     }
73     for (i = 0; i < char_len; ++i) {
74         temp = *pos++;
75         for (j = 0; j < 8; ++j) {
76             if (temp & 0x80) {
77                 amp_hal_lcd_draw_point(xtemp, ytemp, fcolor);
78             }
79             temp <<= 1;
80             ytemp += 1;
81             if (size == (ytemp - y)) {
82                 ytemp = y;
83                 xtemp += 1;
84                 break;
85             }
86         }
87     }
88     return 0;
89 }
90 
lcd_draw_str(uint16_t x,uint16_t y,uint8_t * str,uint8_t size,uint32_t color,int8_t new_line)91 static int8_t lcd_draw_str(uint16_t x, uint16_t y, uint8_t *str, uint8_t size,
92                            uint32_t color, int8_t new_line)
93 {
94     uint16_t xstart = x;
95     uint16_t ystart = y;
96     uint16_t xres   = 0;
97     uint16_t yres   = 0;
98     if (NULL == lcd_handle) {
99         return -1;
100     }
101     xres = lcd_handle->width;
102     yres = lcd_handle->height;
103     while ((*str <= '~') && (*str >= ' ')) {
104         if (new_line) {
105             if (xstart > xres) {
106                 xstart = x;
107                 ystart += size;
108             }
109             if (ystart > yres) {
110                 break;
111             }
112         }
113         lcd_draw_char(xstart, ystart, *str, size, color);
114         xstart += size / 2;
115         str += 1;
116     }
117     return 0;
118 }
119 
lcd_draw_rect(int32_t x1,int32_t y1,int32_t x2,int32_t y2,uint32_t color,uint8_t need_fill)120 static void lcd_draw_rect(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
121                           uint32_t color, uint8_t need_fill)
122 {
123     int32_t i = 0;
124     if (need_fill) {
125         for (i = y1; i <= y2; i++) amp_hal_lcd_draw_line(x1, i, color, x2 - x1 + 1);
126     } else {
127         for (i = x1; i <= x2; ++i) {
128             amp_hal_lcd_draw_point(i, y1, color);
129             amp_hal_lcd_draw_point(i, y2, color);
130         }
131         for (i = y1; i <= y2; ++i) {
132             amp_hal_lcd_draw_point(x1, i, color);
133             amp_hal_lcd_draw_point(x2, i, color);
134         }
135     }
136 }
137 
native_lcd_open(duk_context * ctx)138 static duk_ret_t native_lcd_open(duk_context *ctx)
139 {
140     int ret = -1;
141 
142     if (!duk_is_object(ctx, 0)) {
143         amp_warn(MOD_STR, "parameter must be object");
144         goto out;
145     }
146     duk_get_prop_string(ctx, 0, "height");
147     duk_get_prop_string(ctx, 0, "width");
148     /* [ parameter height width ] */
149     if (!duk_is_number(ctx, -1) || !duk_is_number(ctx, -2)) {
150         amp_warn(MOD_STR, "parameter object must be `{height:number,width:number}`");
151         duk_pop_2(ctx);
152         goto out;
153     }
154     uint32_t width  = duk_get_int(ctx, -1);
155     uint32_t height = duk_get_int(ctx, -2);
156     duk_pop_2(ctx);
157     ret = lcd_init(width, height);
158 out:
159     duk_push_int(ctx, ret);
160     return 1;
161 }
162 
native_lcd_close(duk_context * ctx)163 static duk_ret_t native_lcd_close(duk_context *ctx)
164 {
165     lcd_deinit();
166     duk_push_int(ctx, 0);
167     return 1;
168 }
169 
native_lcd_fill(duk_context * ctx)170 static duk_ret_t native_lcd_fill(duk_context *ctx)
171 {
172     int ret = -1;
173 
174     if (!duk_is_object(ctx, 0)) {
175         amp_warn(MOD_STR, "parameter must be object");
176         goto out;
177     }
178 
179     /* [ parameter sx sy ex ey color fill ] */
180     duk_get_prop_string(ctx, 0, "sx");
181     duk_get_prop_string(ctx, 0, "sy");
182     duk_get_prop_string(ctx, 0, "ex");
183     duk_get_prop_string(ctx, 0, "ey");
184     duk_get_prop_string(ctx, 0, "color");
185     duk_get_prop_string(ctx, 0, "fill");
186 
187     if (!duk_is_number(ctx, -6)    /* sx */
188         || !duk_is_number(ctx, -5) /* sy */
189         || !duk_is_number(ctx, -4) /* ex */
190         || !duk_is_number(ctx, -3) /* ey */
191         || !duk_is_number(ctx, -2) /* color */
192     ) {
193         amp_warn(MOD_STR,
194             "parameter object must be "
195             "`{sx:number,sy:number,ex:number,ey:number,color:number}`");
196         goto pop_out;
197     }
198 
199     int sx      = duk_get_int(ctx, -6);
200     int sy      = duk_get_int(ctx, -5);
201     int ex      = duk_get_int(ctx, -4);
202     int ey      = duk_get_int(ctx, -3);
203     int color   = duk_get_int(ctx, -2);
204     int is_fill = duk_get_int_default(ctx, -1, 0);
205     lcd_draw_rect(sx, sy, ex, ey, color, is_fill);
206     ret = 0;
207 
208 pop_out:
209     duk_pop_n(ctx, 6);
210 
211 out:
212     duk_push_int(ctx, ret);
213     return 1;
214 }
215 
native_lcd_show(duk_context * ctx)216 static duk_ret_t native_lcd_show(duk_context *ctx)
217 {
218     int ret = -1;
219 
220     if (!duk_is_object(ctx, 0)) {
221         amp_warn(MOD_STR, "parameter must be object");
222         goto out;
223     }
224 
225     /* [ parameter x y color newline str size ] */
226     duk_get_prop_string(ctx, 0, "x");
227     duk_get_prop_string(ctx, 0, "y");
228     duk_get_prop_string(ctx, 0, "color");
229     duk_get_prop_string(ctx, 0, "newline");
230     duk_get_prop_string(ctx, 0, "str");
231     duk_get_prop_string(ctx, 0, "size");
232 
233     if (!duk_is_number(ctx, -6)    /* x */
234         || !duk_is_number(ctx, -5) /* y */
235         || !duk_is_number(ctx, -4) /* color */
236         || !duk_is_number(ctx, -3) /* newline */
237         || !duk_is_string(ctx, -2) /* str */
238         || !duk_is_number(ctx, -1) /* size */
239     ) {
240         amp_warn(MOD_STR,
241             "parameter object must be "
242             "`{x:number,y:number,color:number,newline:number,str:string,size:"
243             "number}`");
244         goto pop_out;
245     }
246 
247     int x_pos       = duk_get_int(ctx, -6);
248     int y_pos       = duk_get_int(ctx, -5);
249     int color       = duk_get_int(ctx, -4);
250     int is_newline  = duk_get_int(ctx, -3);
251     const char *str = duk_get_string(ctx, -2);
252     int front_size  = duk_get_int(ctx, -1);
253 
254     if ((16 != front_size) && (12 != front_size) && (24 != front_size) &&
255         (36 != front_size)) {
256         ret = -1;
257         goto pop_out;
258     }
259 
260     lcd_draw_str(x_pos, y_pos, (uint8_t *)str, front_size, color, is_newline);
261     ret = 0;
262 
263 pop_out:
264     duk_pop_n(ctx, 6);
265 
266 out:
267     duk_push_int(ctx, ret);
268     return 1;
269 }
270 
module_lcd_register(void)271 void module_lcd_register(void)
272 {
273     duk_context *ctx = be_get_context();
274 
275     duk_push_object(ctx);
276 
277     AMP_ADD_FUNCTION("open",  native_lcd_open, 1);
278     AMP_ADD_FUNCTION("close", native_lcd_close, 1);
279     AMP_ADD_FUNCTION("show",  native_lcd_show, 1);
280     AMP_ADD_FUNCTION("fill",  native_lcd_fill, 1);
281 
282     duk_put_prop_string(ctx, -2, "LCD");
283 }
284