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