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 * 2019-08-29 zdzn first version
9 */
10
11 #include <rthw.h>
12 #include <rtthread.h>
13 #include <rtdevice.h>
14
15 #include "mbox.h"
16 #include "drv_fb.h"
17 #include "mmu.h"
18
19 #define CHAR_W 8
20 #define CHAR_H 12
21
22 #define COLOR_DELTA 0.05
23 static struct rt_hdmi_fb_device _hdmi;
24 fb_t fb_info;
25
26 // https://github.com/xinu-os/xinu/blob/1789b7a50b5b73c2ea76ebd764c54a034097d04d/device/framebuffer_rpi/font.c
27 unsigned char FONT[] = {
28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
61 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'!'*/
62 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'"'*/
63 0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, 0x00, 0x00, /*'#'*/
64 0x00, 0x00, 0x08, 0x3c, 0x0a, 0x1c, 0x28, 0x1e, 0x08, 0x00, 0x00, 0x00, /*'$'*/
65 0x00, 0x00, 0x06, 0x26, 0x10, 0x08, 0x04, 0x32, 0x30, 0x00, 0x00, 0x00, /*'%'*/
66 0x00, 0x00, 0x1c, 0x02, 0x02, 0x04, 0x2a, 0x12, 0x2c, 0x00, 0x00, 0x00, /*'&'*/
67 0x00, 0x18, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'''*/
68 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, /*'('*/
69 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00, /*')'*/
70 0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, /*'*'*/
71 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /*'+'*/
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*','*/
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'-'*/
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*'.'*/
75 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /*'/'*/
76 0x00, 0x1c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'0'*/
77 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'1'*/
78 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'2'*/
79 0x00, 0x1c, 0x22, 0x20, 0x18, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'3'*/
80 0x00, 0x10, 0x18, 0x18, 0x14, 0x14, 0x3e, 0x10, 0x38, 0x00, 0x00, 0x00, /*'4'*/
81 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'5'*/
82 0x00, 0x18, 0x04, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'6'*/
83 0x00, 0x3e, 0x22, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, /*'7'*/
84 0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'8'*/
85 0x00, 0x1c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x10, 0x0c, 0x00, 0x00, 0x00, /*'9'*/
86 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*':'*/
87 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*';'*/
88 0x00, 0x00, 0x00, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, /*'<'*/
89 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, /*'='*/
90 0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, /*'>'*/
91 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'?'*/
92 0x00, 0x00, 0x1c, 0x22, 0x3a, 0x3a, 0x1a, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'@'*/
93 0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, 0x00, 0x00, /*'A'*/
94 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'B'*/
95 0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'C'*/
96 0x00, 0x00, 0x0e, 0x12, 0x22, 0x22, 0x22, 0x12, 0x0e, 0x00, 0x00, 0x00, /*'D'*/
97 0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'E'*/
98 0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'F'*/
99 0x00, 0x00, 0x1c, 0x22, 0x02, 0x32, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'G'*/
100 0x00, 0x00, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'H'*/
101 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, /*'I'*/
102 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'J'*/
103 0x00, 0x00, 0x22, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'K'*/
104 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'L'*/
105 0x00, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'M'*/
106 0x00, 0x00, 0x22, 0x26, 0x26, 0x2a, 0x32, 0x32, 0x22, 0x00, 0x00, 0x00, /*'N'*/
107 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'O'*/
108 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'P'*/
109 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x30, 0x00, 0x00, /*'Q'*/
110 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'R'*/
111 0x00, 0x00, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'S'*/
112 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'T'*/
113 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'U'*/
114 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'V'*/
115 0x00, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, 0x00, 0x00, /*'W'*/
116 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00, 0x00, /*'X'*/
117 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'Y'*/
118 0x00, 0x00, 0x3e, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'Z'*/
119 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, /*'['*/
120 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, /*'\'*/
121 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, /*']'*/
122 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'^'*/
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, /*'_'*/
124 0x00, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'`'*/
125 0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'a'*/
126 0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'b'*/
127 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, /*'c'*/
128 0x00, 0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'d'*/
129 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'e'*/
130 0x00, 0x38, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, /*'f'*/
131 0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'g'*/
132 0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'h'*/
133 0x00, 0x08, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'i'*/
134 0x00, 0x10, 0x10, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, /*'j'*/
135 0x00, 0x02, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x00, 0x00, 0x00, /*'k'*/
136 0x00, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'l'*/
137 0x00, 0x00, 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x22, 0x00, 0x00, 0x00, /*'m'*/
138 0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'n'*/
139 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'o'*/
140 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, /*'p'*/
141 0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, /*'q'*/
142 0x00, 0x00, 0x00, 0x00, 0x1a, 0x06, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'r'*/
143 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x00, /*'s'*/
144 0x00, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, /*'t'*/
145 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'u'*/
146 0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'v'*/
147 0x00, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00, 0x00, 0x00, /*'w'*/
148 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, /*'x'*/
149 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'y'*/
150 0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00, /*'z'*/
151 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, /*'{'*/
152 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /*'|'*/
153 0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, /*'}'*/
154 0x00, 0x04, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'~'*/
155 0x00, 0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x22, 0x3e, 0x00, 0x00, 0x00, /*DEL*/
156 };
157
newline(fb_t * fb)158 void newline(fb_t* fb)
159 {
160 uint8_t* to;
161 uint8_t* from;
162 int i;
163 fb->y++;
164 fb->x = 0;
165
166 if (fb->y == (fb->height / CHAR_H))
167 {
168
169 to = (uint8_t*) fb->addr;
170 from = to + (CHAR_H * fb->pitch);
171
172 for (i = 0; i < ((fb->height - CHAR_H) * fb->pitch); i++)
173 {
174 *to++ = *from++;
175 }
176
177 uint32_t *addr = (uint32_t*) (fb->addr) + (fb->height - CHAR_H) * fb->width;
178
179 for (i = 0; i < (CHAR_H * fb->width); i++)
180 {
181 *addr++ = fb->back;
182 }
183
184 fb->y--;
185 }
186 }
187
clear_line(fb_t * fb,const int line)188 void clear_line(fb_t *fb, const int line)
189 {
190 int i;
191 uint32_t* addr;
192 if (line > fb->height / CHAR_H)
193 {
194 fb->y = 0;
195 }
196 else
197 {
198 fb->y = line;
199 }
200
201 fb->x = 0;
202
203 addr = (uint32_t*) (fb->addr + (line * CHAR_H * fb->depth * fb->width));
204 for (i = 0; i < (CHAR_H * fb->width); i++)
205 {
206 *addr++ = fb->back;
207 }
208
209 }
210
fb_draw_char(fb_t * fb,char s)211 void fb_draw_char(fb_t *fb, char s)
212 {
213 unsigned char* addr = (unsigned char*) fb->addr;
214 unsigned char *glyph = (unsigned char*) FONT + (s) * 12;
215 // calculate the offset on screen
216 int offs = (fb->y * CHAR_H * fb->pitch) + (fb->x * (CHAR_W + 1) * 4);
217 // variables
218 int i, j, line, mask, bytesperline = (CHAR_W + 7) / 8;
219 // display a character
220 for (j = 0; j < CHAR_H; j++)
221 {
222 // display one row
223 line = offs;
224 mask = 1;
225 for (i = 0; i < CHAR_W; i++)
226 {
227 // if bit set, we use white color, otherwise black
228 *((unsigned int*) (addr + line)) = ((int) *glyph) & mask ? fb->fore : fb->back;
229 mask <<= 1;
230 line += 4;
231 }
232 // adjust to next line
233 glyph += bytesperline;
234 offs += fb->pitch;
235 }
236 }
237
fb_print(fb_t * fb,char * s)238 void fb_print(fb_t *fb, char *s)
239 {
240
241 // draw next character if it's not zero
242 while (*s)
243 {
244 // handle carrige return
245 if (*s == '\r')
246 {
247 fb->x = 0;
248 }
249 else if (*s == '\n')
250 {
251 newline(fb);
252 }
253 else if (*s == '\t')
254 {
255 fb->x = ((fb->x + 4) >> 2) << 2;
256 }
257 else if (*s == '\b')
258 {
259 if (fb->x)
260 {
261 fb->x--;
262 fb_draw_char(fb, ' ');
263 }
264 }
265 else
266 {
267 fb_draw_char(fb, *s);
268 fb->x++;
269 }
270 // next character
271 if (fb->x == fb->width / CHAR_W)
272 {
273 newline(fb);
274 }
275 s++;
276 }
277 }
278
hdmi_fb_open(rt_device_t dev,rt_uint16_t oflag)279 rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag)
280 {
281 return RT_EOK;
282 }
283
hdmi_fb_close(rt_device_t dev)284 rt_err_t hdmi_fb_close(rt_device_t dev)
285 {
286 return RT_EOK;
287 }
288
hdmi_fb_read(rt_device_t dev,rt_off_t pos,void * buf,rt_size_t size)289 rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
290 {
291 return 0;
292 }
293
hdmi_fb_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)294 rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
295 {
296 fb_print(&_hdmi.fb, (char *) buffer);
297 #ifdef BSP_USING_HDMI_DISPLAY
298 rt_device_t uart = rt_device_find("uart1");
299 int old_flag = uart->open_flag;
300 uart->open_flag |= RT_DEVICE_FLAG_STREAM;
301 rt_device_write(uart, 0, buffer, size);
302 uart->open_flag = old_flag;
303 #endif
304 return size;
305 }
306
hdmi_fb_control(rt_device_t dev,int cmd,void * args)307 rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args)
308 {
309 return RT_EOK;
310 }
311
312 const static struct rt_device_ops hdmi_fb_ops =
313 {
314 RT_NULL,
315 hdmi_fb_open,
316 hdmi_fb_close,
317 hdmi_fb_read,
318 hdmi_fb_write,
319 hdmi_fb_control
320 };
321
322 static struct rt_device_graphic_info _hdmi_info;
323
hdmi_draw_rect(const char * pixel,int x1,int y1,int x2,int y2)324 static void hdmi_draw_rect(const char* pixel, int x1, int y1, int x2, int y2)
325 {
326 int i, j;
327 int line;
328 for (j = y1; j <= y2; j++)
329 {
330 line = (j * _hdmi.fb.pitch) + (x1 * 4);
331 for (i = x1; i <= x2; i++)
332 {
333 // if bit set, we use white color, otherwise black
334 *((unsigned int*) (_hdmi_info.framebuffer + line)) = *(unsigned int*) pixel;
335 line += 4;
336 }
337 }
338
339 }
340
hdmi_set_pixel(const char * pixel,int x,int y)341 static void hdmi_set_pixel(const char* pixel, int x, int y)
342 {
343 *(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) = *(uint32_t *) pixel;
344 }
345
hdmi_get_pixel(char * pixel,int x,int y)346 static void hdmi_get_pixel(char* pixel, int x, int y)
347 {
348 uint32_t ret = 0;
349 ret = (*(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) & 0x00FFFFFF);
350 *pixel = ret;
351 }
352
hdmi_draw_hline(const char * pixel,int x1,int x2,int y)353 static void hdmi_draw_hline(const char* pixel, int x1, int x2, int y)
354 {
355 hdmi_draw_rect(pixel, x1, y, x2, y);
356 }
357
hdmi_draw_vline(const char * pixel,int x,int y1,int y2)358 static void hdmi_draw_vline(const char* pixel, int x, int y1, int y2)
359 {
360 hdmi_draw_rect(pixel, x, y1, x, y2);
361 }
362
hdmi_blit_line(const char * pixels,int x,int y,rt_size_t size)363 static void hdmi_blit_line(const char* pixels, int x, int y, rt_size_t size)
364 {
365 int i = 0;
366 uint32_t *pixel_base = (uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4));
367 uint32_t *colors = (uint32_t *) pixels;
368 for (i = 0; i < size; i++)
369 {
370 pixel_base[i] = colors[i];
371 }
372 }
373
374 static struct rt_device_graphic_ops hdmi_ops =
375 {
376 hdmi_set_pixel,
377 hdmi_get_pixel,
378 hdmi_draw_hline,
379 hdmi_draw_vline,
380 hdmi_blit_line
381 };
382
rt_hdmi_fb_device_init(struct rt_hdmi_fb_device * hdmi_fb,const char * name)383 rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name)
384 {
385 struct rt_device *device;
386 RT_ASSERT(hdmi_fb != RT_NULL);
387
388 device = &hdmi_fb->parent;
389 device->user_data = &hdmi_ops;
390
391 /* set device type */
392 device->type = RT_Device_Class_Graphic;
393 /* initialize device interface */
394 #ifdef RT_USING_DEVICE_OPS
395 device->ops = &hdmi_fb_ops;
396 #else
397 device->init = RT_NULL;
398 device->open = hdmi_fb_open;
399 device->close = hdmi_fb_close;
400 device->read = hdmi_fb_read;
401 device->write = hdmi_fb_write;
402 device->control = hdmi_fb_control;
403 #endif
404
405 /* register to device manager */
406 rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
407
408 return RT_EOK;
409 }
410
411 /**
412 * Show a picture
413 */
print_fb_info()414 void print_fb_info()
415 {
416 rt_kprintf("FrameBuffer Info: \n \t width %x\t height %x\t depth %x\t addr %x\t size %x\t \n", fb_info.width,
417 fb_info.height, fb_info.depth, fb_info.addr, fb_info.size);
418 rt_kprintf("call mbox:%x,%x,%x,%x,%x\n", mbox[0], mbox[1], mbox[2], mbox[3], mbox[4]);
419 }
420
hdmi_fb_init()421 int hdmi_fb_init()
422 {
423 unsigned int *mbox = (unsigned int*) MBOX_ADDR;
424 mbox[0] = 35 * 4;
425 mbox[1] = MBOX_REQUEST;
426
427 mbox[2] = 0x48003; //set phy wh
428 mbox[3] = 8;
429 mbox[4] = 8;
430 mbox[5] = 640; //FrameBufferInfo.width
431 mbox[6] = 480; //FrameBufferInfo.height
432
433 mbox[7] = 0x48004; //set virt wh
434 mbox[8] = 8;
435 mbox[9] = 8;
436 mbox[10] = 640; //FrameBufferInfo.virtual_width
437 mbox[11] = 480; //FrameBufferInfo.virtual_height
438
439 mbox[12] = 0x48009; //set virt offset
440 mbox[13] = 8;
441 mbox[14] = 8;
442 mbox[15] = 0; //FrameBufferInfo.x_offset
443 mbox[16] = 0; //FrameBufferInfo.y.offset
444
445 mbox[17] = 0x48005; //set depth
446 mbox[18] = 4;
447 mbox[19] = 4;
448 mbox[20] = 32; //FrameBufferInfo.depth
449
450 mbox[21] = 0x48006; //set pixel order
451 mbox[22] = 4;
452 mbox[23] = 4;
453 mbox[24] = 1; //RGB, not BGR preferably
454
455 mbox[25] = 0x40001; //get framebuffer, gets alignment on request
456 mbox[26] = 8;
457 mbox[27] = 8;
458 mbox[28] = 4096; //FrameBufferInfo.pointer
459 mbox[29] = 0; //FrameBufferInfo.size
460
461 mbox[30] = 0x40008; //get pitch
462 mbox[31] = 4;
463 mbox[32] = 4;
464 mbox[33] = 0; //FrameBufferInfo.pitch
465
466 mbox[34] = MBOX_TAG_LAST;
467 if (mbox_call(MBOX_CH_PROP, MMU_DISABLE) && mbox[20] == 32 && mbox[28] != 0)
468 {
469 mbox[28] &= 0x3FFFFFFF;
470 _hdmi.fb.width = mbox[5];
471 _hdmi.fb.height = mbox[6];
472 _hdmi.fb.pitch = mbox[33];
473 //_hdmi.fb.addr = (void*)((unsigned long)mbox[28]);
474 _hdmi.fb.addr = (rt_uint32_t) mbox[28];
475 _hdmi.fb.size = mbox[29];
476 _hdmi.fb.depth = 32;
477 _hdmi.fb.x = 0;
478 _hdmi.fb.y = 0;
479 _hdmi.fb.fore = CONSOLE_WHITE;
480 _hdmi.fb.back = CONSOLE_BLACK;
481 rt_hdmi_fb_device_init(&_hdmi, "hdmi");
482 rt_hw_change_mmu_table(_hdmi.fb.addr, _hdmi.fb.size, _hdmi.fb.addr, DEVICE_MEM);
483 fb_info.width = _hdmi.fb.width;
484 fb_info.height = _hdmi.fb.height;
485 fb_info.addr = _hdmi.fb.addr;
486 fb_info.size = _hdmi.fb.size;
487 fb_info.pitch = _hdmi.fb.pitch;
488 fb_info.depth = _hdmi.fb.depth;
489 _hdmi_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
490 _hdmi_info.bits_per_pixel = _hdmi.fb.depth;
491 _hdmi_info.width = _hdmi.fb.width;
492 _hdmi_info.height = _hdmi.fb.height;
493 _hdmi_info.framebuffer = (rt_uint8_t *) _hdmi.fb.addr;
494 }
495 return 0;
496 }
497
498 INIT_DEVICE_EXPORT(hdmi_fb_init);
499