Skip to content

Commit 5ca3f5d

Browse files
committed
[app-dreameye] Added QR Code scanning.
1 parent 77682ac commit 5ca3f5d

File tree

5 files changed

+223
-44
lines changed

5 files changed

+223
-44
lines changed

applications/dreameye/app.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<app name="DreamEye" version="0.1.0" icon="images/icon.png">
2+
<app name="DreamEye" version="0.2.0" icon="images/icon.png">
33
<resources>
4+
<module src="../../modules/quirc.klf" />
45
<module src="../../modules/dreameye.klf" />
56
<module src="modules/app_dreameye.klf" />
67
<font src="../../fonts/ttf/arial_lite.ttf" type="ttf" size="14" name="arial" />
@@ -64,11 +65,17 @@
6465
<label font="m23" color="#ffffff" text="Preview 160x120" />
6566
</input>
6667
</panel>
67-
<panel height="70" width="100%">
68+
<panel height="65" width="100%">
6869
<input type="button" width="280" height="60" onclick="console:app -o -n Main" align="center">
6970
<label font="m23" color="#ffffff" text="Exit" />
7071
</input>
7172
</panel>
73+
<panel height="20" width="100%">
74+
<panel x="25">
75+
<label align="left" color="#333333" font="arial" width="100%" height="20"
76+
text="No QR Code" name="qr-data" />
77+
</panel>
78+
</panel>
7279
</panel>
7380
</cardstack>
7481
</body>

applications/dreameye/modules/Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
#
22
# DreamEye app module for DreamShell
3-
# Copyright (C) 2023 SWAT
3+
# Copyright (C) 2023, 2024 SWAT
44
# http://www.dc-swat.ru
55
#
66

77
APP_NAME = dreameye
88
TARGET_NAME = app_$(APP_NAME)
9-
OBJS = module.o
10-
DBG_LIBS = -lds -ldreameye
9+
OBJS = module.o qr_code.o
10+
DBG_LIBS = -lds -ldreameye -lquirc
1111
EXPORTS_FILE = exports.txt
1212

1313
VER_MAJOR = 0
14-
VER_MINOR = 1
14+
VER_MINOR = 2
1515
VER_MICRO = 0
1616

1717
KOS_CFLAGS += -I./

applications/dreameye/modules/module.c

Lines changed: 84 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,69 +6,115 @@
66

77
#include <ds.h>
88
#include <drivers/dreameye.h>
9+
#include "qr_code.h"
910

1011
DEFAULT_MODULE_EXPORTS(app_dreameye);
1112

1213
static struct {
1314

14-
App_t *app;
15-
GUI_Widget *pages;
15+
App_t *app;
16+
dreameye_preview_t preview;
1617

17-
int preview_isp_mode;
18-
int preview_fullscreen;
19-
int preview_x;
20-
int preview_y;
21-
int preview_scale;
18+
GUI_Widget *pages;
19+
GUI_Widget *qr_data;
2220

2321
} self;
2422

2523
static void ShowCameraPreview() {
26-
maple_device_t *dev = maple_enum_type(0, MAPLE_FUNC_CAMERA);
27-
dreameye_preview_shutdown();
28-
if(dev) {
29-
dreameye_preview_init(dev, self.preview_isp_mode,
30-
self.preview_fullscreen, self.preview_scale,
31-
self.preview_x, self.preview_y);
32-
} else {
33-
ds_printf("DS_ERROR: No camera present\n");
34-
}
24+
25+
int w, h;
26+
maple_device_t *dev = maple_enum_type(0, MAPLE_FUNC_CAMERA);
27+
28+
if(!dev) {
29+
return;
30+
}
31+
dreameye_preview_shutdown(dev);
32+
33+
if(self.preview.isp_mode == DREAMEYE_ISP_MODE_QSIF) {
34+
w = 160;
35+
h = 120;
36+
} else {
37+
w = 320;
38+
h = 240;
39+
}
40+
if(qr_scan_resize(w, h) < 0) {
41+
ds_printf("DS_ERROR: Couldn't allocate QR buffer\n");
42+
}
43+
dreameye_preview_init(dev, &self.preview);
44+
}
45+
46+
static int execute_string(const char *str) {
47+
if (!strncmp(str, "dsc:", 4)) {
48+
if(dsystem_buff(str + 4) == CMD_OK) {
49+
return 0;
50+
}
51+
}
52+
else if (!strncmp(str, "lua:", 4)) {
53+
if (LuaDo(LUA_DO_STRING, str + 4, GetLuaState()) < 1) {
54+
return 0;
55+
}
56+
}
57+
return -1;
58+
}
59+
60+
static void frame_callback(maple_device_t *dev, uint8_t *frame, size_t len) {
61+
(void)dev;
62+
63+
/* Max payload is 8896, but Dreameye can't this I guess. */
64+
char qr_str[2048];
65+
66+
if(!qr_scan_frame(self.preview.bpp, frame, len, qr_str)) {
67+
if(strcmp(GUI_LabelGetText(self.qr_data), qr_str)) {
68+
GUI_LabelSetText(self.qr_data, qr_str);
69+
execute_string(qr_str);
70+
}
71+
}
72+
else if(strncmp(GUI_LabelGetText(self.qr_data), "No QR Code", 10)) {
73+
GUI_LabelSetText(self.qr_data, "No QR Code");
74+
}
3575
}
3676

3777
void DreamEyeApp_Init(App_t *app) {
38-
self.app = app;
39-
self.pages = APP_GET_WIDGET("pages");
40-
41-
self.preview_isp_mode = DREAMEYE_ISP_MODE_QSIF;
42-
self.preview_fullscreen = 0;
43-
self.preview_scale = 2;
44-
self.preview_x = 160;
45-
self.preview_y = 220;
78+
self.app = app;
79+
self.pages = APP_GET_WIDGET("pages");
80+
self.qr_data = APP_GET_WIDGET("qr-data");
81+
82+
self.preview.isp_mode = DREAMEYE_ISP_MODE_QSIF;
83+
self.preview.bpp = 12;
84+
self.preview.fullscreen = 0;
85+
self.preview.scale = 2;
86+
self.preview.x = 160;
87+
self.preview.y = 235;
88+
self.preview.callback = frame_callback;
89+
90+
qr_scan_init();
4691
}
4792

4893
void DreamEyeApp_Shutdown(App_t *app) {
49-
(void)app;
50-
dreameye_preview_shutdown();
94+
(void)app;
95+
dreameye_preview_shutdown(NULL);
96+
qr_scan_shutdown();
5197
}
5298

5399
void DreamEyeApp_Open(App_t *app) {
54-
(void)app;
55-
ShowCameraPreview();
100+
(void)app;
101+
ShowCameraPreview();
56102
}
57103

58104
void DreamEyeApp_ShowPage(GUI_Widget *widget) {
59-
(void)widget;
105+
(void)widget;
60106
}
61107

62108
void DreamEyeApp_ShowPreview(GUI_Widget *widget) {
63-
const char *object_name = GUI_ObjectGetName((GUI_Object *)widget);
109+
const char *object_name = GUI_ObjectGetName((GUI_Object *)widget);
64110

65-
if(object_name[8] == '1') {
66-
self.preview_isp_mode = DREAMEYE_ISP_MODE_QSIF;
67-
self.preview_scale = 2;
68-
} else {
69-
self.preview_isp_mode = DREAMEYE_ISP_MODE_SIF;
70-
self.preview_scale = 1;
71-
}
111+
if(object_name[8] == '1') {
112+
self.preview.isp_mode = DREAMEYE_ISP_MODE_QSIF;
113+
self.preview.scale = 2;
114+
} else {
115+
self.preview.isp_mode = DREAMEYE_ISP_MODE_SIF;
116+
self.preview.scale = 1;
117+
}
72118

73-
ShowCameraPreview();
119+
ShowCameraPreview();
74120
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* DreamShell ##version##
2+
3+
qr_code.c - DreamEye app QR Code scanner
4+
Copyright (C) 2024 SWAT
5+
*/
6+
7+
#include <ds.h>
8+
#include <quirc.h>
9+
10+
static struct quirc *qr = NULL;
11+
static struct quirc_code code;
12+
static struct quirc_data data;
13+
14+
static void yuyv_to_luma(const uint8_t *src, int src_pitch,
15+
int w, int h, uint8_t *dst, int dst_pitch) {
16+
int y;
17+
18+
for (y = 0; y < h; y++) {
19+
int x;
20+
const uint8_t *srow = src + y * src_pitch;
21+
uint8_t *drow = dst + y * dst_pitch;
22+
23+
for (x = 0; x < w; x += 2) {
24+
*(drow++) = srow[0];
25+
*(drow++) = srow[2];
26+
srow += 4;
27+
}
28+
}
29+
}
30+
31+
int qr_scan_frame(int bpp, uint8_t *frame, size_t len, char *qr_data) {
32+
33+
int i, w, h, count, rv = -1;
34+
uint8_t *buf;
35+
uint64_t begin, end;
36+
37+
if (!qr) {
38+
return rv;
39+
}
40+
41+
begin = timer_ns_gettime64();
42+
buf = quirc_begin(qr, &w, &h);
43+
44+
switch (bpp) {
45+
case 12:
46+
/* TODO: Maybe just map it possible? */
47+
memcpy(buf, frame, w * h);
48+
break;
49+
case 16:
50+
yuyv_to_luma(frame, w * 2, w, h, buf, w);
51+
break;
52+
default:
53+
quirc_end(qr);
54+
return rv;
55+
}
56+
57+
quirc_end(qr);
58+
count = quirc_count(qr);
59+
60+
for (i = 0; i < count; i++) {
61+
62+
quirc_extract(qr, i, &code);
63+
64+
if (!quirc_decode(&code, &data)) {
65+
66+
end = timer_ns_gettime64();
67+
68+
if(data.data_type != QUIRC_DATA_TYPE_BYTE) {
69+
ds_printf("QR data: unsupported, time %d ns\n",
70+
(end - begin) / 1000000);
71+
ds_printf("Version: %d, ECC: %c, Mask: %d, Type: %d\n",
72+
data.version, "MLHQ"[data.ecc_level],
73+
data.mask, data.data_type);
74+
continue;
75+
}
76+
77+
ds_printf("QR data: \"%s\", time %d ms\n",
78+
data.payload, (end - begin) / 1000000);
79+
rv = 0;
80+
81+
if(qr_data) {
82+
memcpy(qr_data, data.payload, strlen((char *)data.payload) + 1);
83+
}
84+
}
85+
}
86+
return rv;
87+
}
88+
89+
int qr_scan_resize(int w, int h) {
90+
if (quirc_resize(qr, w, h) < 0) {
91+
ds_printf("DS_ERROR: Couldn't allocate QR buffer\n");
92+
return -1;
93+
}
94+
return 0;
95+
}
96+
97+
int qr_scan_init() {
98+
if (qr) {
99+
return 0;
100+
}
101+
qr = quirc_new();
102+
if (qr) {
103+
return 0;
104+
}
105+
return -1;
106+
}
107+
108+
void qr_scan_shutdown() {
109+
if (!qr) {
110+
return;
111+
}
112+
quirc_destroy(qr);
113+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* DreamShell ##version##
2+
3+
qr_code.h - DreamEye app QR Code scanner
4+
Copyright (C) 2024 SWAT
5+
*/
6+
7+
#include <ds.h>
8+
9+
int qr_scan_init();
10+
void qr_scan_shutdown();
11+
12+
int qr_scan_resize(int w, int h);
13+
int qr_scan_frame(int bpp, uint8_t *frame, size_t len, char *qr_data);

0 commit comments

Comments
 (0)