1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 */
9 #include <rtconfig.h>
10
11 #ifdef BSP_USING_LCD_QRCODE
12 #include <qrcode.h>
13 #include "drv_lcd.h"
14 #include "lcd_qrcode.h"
15 #define DBG_TAG "drv.lcd.qrcode"
16 #define DBG_LVL DBG_INFO
17 #include <rtdbg.h>
18
19 static QRCode qrcode;
20
get_enlargement_factor(rt_uint16_t x,rt_uint16_t y,rt_uint8_t size)21 static rt_uint8_t get_enlargement_factor(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size)
22 {
23 rt_uint8_t enlargement_factor = 1 ;
24
25 if (x + size * 8 <= LCD_W && y + size * 8 <= LCD_H)
26 {
27 enlargement_factor = 8;
28 }
29 else if (x + size * 4 <= LCD_W &&y + size * 4 <= LCD_H)
30 {
31 enlargement_factor = 4;
32 }
33 else if (x + size * 2 <= LCD_W && y + size * 2 <= LCD_H)
34 {
35 enlargement_factor = 2;
36 }
37
38 return enlargement_factor;
39 }
40
show_qrcode_by_point(rt_uint16_t x,rt_uint16_t y,rt_uint8_t size,rt_uint8_t enlargement_factor)41 static void show_qrcode_by_point(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size, rt_uint8_t enlargement_factor)
42 {
43 rt_uint32_t width = 0, high = 0;
44 for (high = 0; high < size; high++)
45 {
46 for (width = 0; width < size; width++)
47 {
48 if (qrcode_getModule(&qrcode, width, high))
49 {
50 /* magnify pixel */
51 for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
52 {
53 for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
54 {
55 lcd_draw_point(x + enlargement_factor * width + offset_x, y + enlargement_factor * high + offset_y);
56 }
57 }
58 }
59 }
60 }
61 }
62
show_qrcode_by_line(rt_uint16_t x,rt_uint16_t y,rt_uint8_t size,rt_uint8_t enlargement_factor,rt_uint8_t * qrcode_buf)63 static void show_qrcode_by_line(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size, rt_uint8_t enlargement_factor,rt_uint8_t *qrcode_buf)
64 {
65 rt_uint32_t width = 0, high = 0;
66 for (high = 0; high < qrcode.size; high++)
67 {
68 for (width = 0; width < qrcode.size; width++)
69 {
70 if (qrcode_getModule(&qrcode, width, high))
71 {
72 /* magnify pixel */
73 for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
74 {
75 for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
76 {
77 /* save the information of modules */
78 qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor)] = FORE_COLOR >> 8;
79 qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor) + 1] = FORE_COLOR;
80 }
81 }
82 }
83 else
84 {
85 /* magnify pixel */
86 for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
87 {
88 for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
89 {
90 /* save the information of blank */
91 qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor)] = BACK_COLOR >> 8;
92 qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor) + 1] = BACK_COLOR;
93 }
94 }
95 }
96 }
97 /* display a line of qrcode */
98 lcd_show_image(x, y + high * enlargement_factor, qrcode.size * enlargement_factor, enlargement_factor, qrcode_buf);
99 }
100 }
101
102 /**
103 * display the qrcode on the lcd.
104 * size = (4 * version +17) * enlargement
105 *
106 * @param x x position
107 * @param y y position
108 * @param version version of qrcode (ECC_LOW, ECC_MEDIUM, ECC_QUARTILE or ECC_HIGH)
109 * @param ecc level of error correction
110 * @param data string
111 * @param enlargement enlargement_factor
112 *
113 * @return 0: display success
114 * -1: generate qrcode failed
115 * -5: memory low
116 */
lcd_show_qrcode(rt_uint16_t x,rt_uint16_t y,rt_uint8_t version,rt_uint8_t ecc,const char * data,rt_uint8_t enlargement)117 rt_err_t lcd_show_qrcode(rt_uint16_t x, rt_uint16_t y, rt_uint8_t version, rt_uint8_t ecc, const char *data, rt_uint8_t enlargement)
118 {
119 RT_ASSERT(data);
120
121 rt_int8_t result = 0;
122 rt_uint8_t enlargement_factor = 1;
123 rt_uint8_t *qrcode_buf = RT_NULL;
124
125 if (x + version * 4 + 17 > LCD_W || y + version * 4 + 17 > LCD_H)
126 {
127 LOG_E("The qrcode is too big!");
128 return -RT_ERROR;
129 }
130
131 rt_uint8_t *qrcodeBytes = (rt_uint8_t *)rt_calloc(1, qrcode_getBufferSize(version));
132 if (qrcodeBytes == RT_NULL)
133 {
134 LOG_E("no memory for qrcode!");
135 return -RT_ENOMEM;
136 }
137
138 /* generate qrcode */
139 result = qrcode_initText(&qrcode, qrcodeBytes, version, ecc, data);
140 if (result >= 0)
141 {
142 /* set enlargement factor */
143 if(enlargement == 0)
144 {
145 enlargement_factor = get_enlargement_factor(x, y, qrcode.size);
146 }
147 else
148 {
149 enlargement_factor = enlargement;
150 }
151
152 /* malloc memory for quick display of qrcode */
153 qrcode_buf = rt_malloc(qrcode.size * 2 * enlargement_factor * enlargement_factor);
154 if (qrcode_buf == RT_NULL)
155 {
156 /* clear lcd */
157 lcd_fill(x, y, x + qrcode.size, y + qrcode.size, BACK_COLOR);
158
159 /* draw point to display qrcode */
160 show_qrcode_by_point(x, y, qrcode.size, enlargement_factor);
161 }
162 else
163 {
164 /* quick display of qrcode */
165 show_qrcode_by_line(x, y, qrcode.size, enlargement_factor,qrcode_buf);
166 }
167 result = RT_EOK;
168 }
169 else
170 {
171 LOG_E("QRCODE(%s) generate falied(%d)\n", data, result);
172 result = -RT_ENOMEM;
173 goto __exit;
174 }
175
176 __exit:
177 if (qrcodeBytes)
178 {
179 rt_free(qrcodeBytes);
180 }
181
182 if (qrcode_buf)
183 {
184 rt_free(qrcode_buf);
185 }
186
187 return result;
188 }
189 #endif /* BSP_USING_LCD_QRCODE */
190