1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Filename: cfag12864b-example.c |
4 | * Version: 0.1.0 |
5 | * Description: cfag12864b LCD userspace example program |
6 | * |
7 | * Author: Copyright (C) Miguel Ojeda <ojeda@kernel.org> |
8 | * Date: 2006-10-31 |
9 | */ |
10 | |
11 | /* |
12 | * ------------------------ |
13 | * start of cfag12864b code |
14 | * ------------------------ |
15 | */ |
16 | |
17 | #include <string.h> |
18 | #include <fcntl.h> |
19 | #include <unistd.h> |
20 | #include <sys/types.h> |
21 | #include <sys/stat.h> |
22 | #include <sys/mman.h> |
23 | |
24 | #define CFAG12864B_WIDTH (128) |
25 | #define CFAG12864B_HEIGHT (64) |
26 | #define CFAG12864B_SIZE (128 * 64 / 8) |
27 | #define CFAG12864B_BPB (8) |
28 | #define CFAG12864B_ADDRESS(x, y) ((y) * CFAG12864B_WIDTH / \ |
29 | CFAG12864B_BPB + (x) / CFAG12864B_BPB) |
30 | #define CFAG12864B_BIT(n) (((unsigned char) 1) << (n)) |
31 | |
32 | #undef CFAG12864B_DOCHECK |
33 | #ifdef CFAG12864B_DOCHECK |
34 | #define CFAG12864B_CHECK(x, y) ((x) < CFAG12864B_WIDTH && \ |
35 | (y) < CFAG12864B_HEIGHT) |
36 | #else |
37 | #define CFAG12864B_CHECK(x, y) (1) |
38 | #endif |
39 | |
40 | int cfag12864b_fd; |
41 | unsigned char * cfag12864b_mem; |
42 | unsigned char cfag12864b_buffer[CFAG12864B_SIZE]; |
43 | |
44 | /* |
45 | * init a cfag12864b framebuffer device |
46 | * |
47 | * No error: return = 0 |
48 | * Unable to open: return = -1 |
49 | * Unable to mmap: return = -2 |
50 | */ |
51 | static int cfag12864b_init(char *path) |
52 | { |
53 | cfag12864b_fd = open(file: path, O_RDWR); |
54 | if (cfag12864b_fd == -1) |
55 | return -1; |
56 | |
57 | cfag12864b_mem = mmap(addr: 0, CFAG12864B_SIZE, PROT_READ | PROT_WRITE, |
58 | MAP_SHARED, fd: cfag12864b_fd, offset: 0); |
59 | if (cfag12864b_mem == MAP_FAILED) { |
60 | close(fd: cfag12864b_fd); |
61 | return -2; |
62 | } |
63 | |
64 | return 0; |
65 | } |
66 | |
67 | /* |
68 | * exit a cfag12864b framebuffer device |
69 | */ |
70 | static void cfag12864b_exit(void) |
71 | { |
72 | munmap(addr: cfag12864b_mem, CFAG12864B_SIZE); |
73 | close(fd: cfag12864b_fd); |
74 | } |
75 | |
76 | /* |
77 | * set (x, y) pixel |
78 | */ |
79 | static void cfag12864b_set(unsigned char x, unsigned char y) |
80 | { |
81 | if (CFAG12864B_CHECK(x, y)) |
82 | cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] |= |
83 | CFAG12864B_BIT(x % CFAG12864B_BPB); |
84 | } |
85 | |
86 | /* |
87 | * unset (x, y) pixel |
88 | */ |
89 | static void cfag12864b_unset(unsigned char x, unsigned char y) |
90 | { |
91 | if (CFAG12864B_CHECK(x, y)) |
92 | cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &= |
93 | ~CFAG12864B_BIT(x % CFAG12864B_BPB); |
94 | } |
95 | |
96 | /* |
97 | * is set (x, y) pixel? |
98 | * |
99 | * Pixel off: return = 0 |
100 | * Pixel on: return = 1 |
101 | */ |
102 | static unsigned char cfag12864b_isset(unsigned char x, unsigned char y) |
103 | { |
104 | if (CFAG12864B_CHECK(x, y)) |
105 | if (cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] & |
106 | CFAG12864B_BIT(x % CFAG12864B_BPB)) |
107 | return 1; |
108 | |
109 | return 0; |
110 | } |
111 | |
112 | /* |
113 | * not (x, y) pixel |
114 | */ |
115 | static void cfag12864b_not(unsigned char x, unsigned char y) |
116 | { |
117 | if (cfag12864b_isset(x, y)) |
118 | cfag12864b_unset(x, y); |
119 | else |
120 | cfag12864b_set(x, y); |
121 | } |
122 | |
123 | /* |
124 | * fill (set all pixels) |
125 | */ |
126 | static void cfag12864b_fill(void) |
127 | { |
128 | unsigned short i; |
129 | |
130 | for (i = 0; i < CFAG12864B_SIZE; i++) |
131 | cfag12864b_buffer[i] = 0xFF; |
132 | } |
133 | |
134 | /* |
135 | * clear (unset all pixels) |
136 | */ |
137 | static void cfag12864b_clear(void) |
138 | { |
139 | unsigned short i; |
140 | |
141 | for (i = 0; i < CFAG12864B_SIZE; i++) |
142 | cfag12864b_buffer[i] = 0; |
143 | } |
144 | |
145 | /* |
146 | * format a [128*64] matrix |
147 | * |
148 | * Pixel off: src[i] = 0 |
149 | * Pixel on: src[i] > 0 |
150 | */ |
151 | static void cfag12864b_format(unsigned char * matrix) |
152 | { |
153 | unsigned char i, j, n; |
154 | |
155 | for (i = 0; i < CFAG12864B_HEIGHT; i++) |
156 | for (j = 0; j < CFAG12864B_WIDTH / CFAG12864B_BPB; j++) { |
157 | cfag12864b_buffer[i * CFAG12864B_WIDTH / CFAG12864B_BPB + |
158 | j] = 0; |
159 | for (n = 0; n < CFAG12864B_BPB; n++) |
160 | if (matrix[i * CFAG12864B_WIDTH + |
161 | j * CFAG12864B_BPB + n]) |
162 | cfag12864b_buffer[i * CFAG12864B_WIDTH / |
163 | CFAG12864B_BPB + j] |= |
164 | CFAG12864B_BIT(n); |
165 | } |
166 | } |
167 | |
168 | /* |
169 | * blit buffer to lcd |
170 | */ |
171 | static void cfag12864b_blit(void) |
172 | { |
173 | memcpy(dest: cfag12864b_mem, src: cfag12864b_buffer, CFAG12864B_SIZE); |
174 | } |
175 | |
176 | /* |
177 | * ---------------------- |
178 | * end of cfag12864b code |
179 | * ---------------------- |
180 | */ |
181 | |
182 | #include <stdio.h> |
183 | |
184 | #define EXAMPLES 6 |
185 | |
186 | static void example(unsigned char n) |
187 | { |
188 | unsigned short i, j; |
189 | unsigned char matrix[CFAG12864B_WIDTH * CFAG12864B_HEIGHT]; |
190 | |
191 | if (n > EXAMPLES) |
192 | return; |
193 | |
194 | printf(format: "Example %i/%i - " , n, EXAMPLES); |
195 | |
196 | switch (n) { |
197 | case 1: |
198 | printf(format: "Draw points setting bits" ); |
199 | cfag12864b_clear(); |
200 | for (i = 0; i < CFAG12864B_WIDTH; i += 2) |
201 | for (j = 0; j < CFAG12864B_HEIGHT; j += 2) |
202 | cfag12864b_set(x: i, y: j); |
203 | break; |
204 | |
205 | case 2: |
206 | printf(format: "Clear the LCD" ); |
207 | cfag12864b_clear(); |
208 | break; |
209 | |
210 | case 3: |
211 | printf(format: "Draw rows formatting a [128*64] matrix" ); |
212 | memset(s: matrix, c: 0, CFAG12864B_WIDTH * CFAG12864B_HEIGHT); |
213 | for (i = 0; i < CFAG12864B_WIDTH; i++) |
214 | for (j = 0; j < CFAG12864B_HEIGHT; j += 2) |
215 | matrix[j * CFAG12864B_WIDTH + i] = 1; |
216 | cfag12864b_format(matrix); |
217 | break; |
218 | |
219 | case 4: |
220 | printf(format: "Fill the lcd" ); |
221 | cfag12864b_fill(); |
222 | break; |
223 | |
224 | case 5: |
225 | printf(format: "Draw columns unsetting bits" ); |
226 | for (i = 0; i < CFAG12864B_WIDTH; i += 2) |
227 | for (j = 0; j < CFAG12864B_HEIGHT; j++) |
228 | cfag12864b_unset(x: i, y: j); |
229 | break; |
230 | |
231 | case 6: |
232 | printf(format: "Do negative not-ing all bits" ); |
233 | for (i = 0; i < CFAG12864B_WIDTH; i++) |
234 | for (j = 0; j < CFAG12864B_HEIGHT; j ++) |
235 | cfag12864b_not(x: i, y: j); |
236 | break; |
237 | } |
238 | |
239 | puts(s: " - [Press Enter]" ); |
240 | } |
241 | |
242 | int main(int argc, char *argv[]) |
243 | { |
244 | unsigned char n; |
245 | |
246 | if (argc != 2) { |
247 | printf( |
248 | format: "Syntax: %s fbdev\n" |
249 | "Usually: /dev/fb0, /dev/fb1...\n" , argv[0]); |
250 | return -1; |
251 | } |
252 | |
253 | if (cfag12864b_init(path: argv[1])) { |
254 | printf(format: "Can't init %s fbdev\n" , argv[1]); |
255 | return -2; |
256 | } |
257 | |
258 | for (n = 1; n <= EXAMPLES; n++) { |
259 | example(n); |
260 | cfag12864b_blit(); |
261 | while (getchar() != '\n'); |
262 | } |
263 | |
264 | cfag12864b_exit(); |
265 | |
266 | return 0; |
267 | } |
268 | |