1/*	$NetBSD: iq80310_7seg.c,v 1.9 2005/12/11 12:17:09 christos Exp $	*/
2
3/*
4 * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed for the NetBSD Project by
20 *	Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 *    or promote products derived from this software without specific prior
23 *    written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * Support for the 7-segment display on the Intel IQ80310.
40 */
41
42#include <sys/cdefs.h>
43__KERNEL_RCSID(0, "$NetBSD: iq80310_7seg.c,v 1.9 2005/12/11 12:17:09 christos Exp $");
44
45#include <sys/param.h>
46#include <sys/systm.h>
47
48#include <sys/bus.h>
49
50#include <evbarm/iq80310/iq80310reg.h>
51#include <evbarm/iq80310/iq80310var.h>
52#include <evbarm/iq80310/obiovar.h>
53
54static int snakestate;
55
56/*
57 * The 7-segment display looks like so:
58 *
59 *         A
60 *	+-----+
61 *	|     |
62 *    F	|     | B
63 *	|  G  |
64 *	+-----+
65 *	|     |
66 *    E	|     | C
67 *	|  D  |
68 *	+-----+ o  DP
69 *
70 * Setting a bit clears the corresponding segment on the
71 * display.
72 */
73#define	SEG_A			(1 << 0)
74#define	SEG_B			(1 << 1)
75#define	SEG_C			(1 << 2)
76#define	SEG_D			(1 << 3)
77#define	SEG_E			(1 << 4)
78#define	SEG_F			(1 << 5)
79#define	SEG_G			(1 << 6)
80#define	SEG_DP			(1 << 7)
81
82static const uint8_t digitmap[] = {
83/*	+#####+
84 *	#     #
85 *	#     #
86 *	#     #
87 *	+-----+
88 *	#     #
89 *	#     #
90 *	#     #
91 *	+#####+
92 */
93	SEG_G,
94
95/*	+-----+
96 *	|     #
97 *	|     #
98 *	|     #
99 *	+-----+
100 *	|     #
101 *	|     #
102 *	|     #
103 *	+-----+
104 */
105	SEG_A|SEG_D|SEG_E|SEG_F|SEG_G,
106
107/*	+#####+
108 *	|     #
109 *	|     #
110 *	|     #
111 *	+#####+
112 *	#     |
113 *	#     |
114 *	#     |
115 *	+#####+
116 */
117	SEG_C|SEG_F,
118
119/*	+#####+
120 *	|     #
121 *	|     #
122 *	|     #
123 *	+#####+
124 *	|     #
125 *	|     #
126 *	|     #
127 *	+#####+
128 */
129	SEG_E|SEG_F,
130
131/*	+-----+
132 *	#     #
133 *	#     #
134 *	#     #
135 *	+#####+
136 *	|     #
137 *	|     #
138 *	|     #
139 *	+-----+
140 */
141	SEG_A|SEG_D|SEG_E,
142
143/*	+#####+
144 *	#     |
145 *	#     |
146 *	#     |
147 *	+#####+
148 *	|     #
149 *	|     #
150 *	|     #
151 *	+#####+
152 */
153	SEG_B|SEG_E,
154
155/*	+#####+
156 *	#     |
157 *	#     |
158 *	#     |
159 *	+#####+
160 *	#     #
161 *	#     #
162 *	#     #
163 *	+#####+
164 */
165	SEG_B,
166
167/*	+#####+
168 *	|     #
169 *	|     #
170 *	|     #
171 *	+-----+
172 *	|     #
173 *	|     #
174 *	|     #
175 *	+-----+
176 */
177	SEG_D|SEG_E|SEG_F,
178
179/*	+#####+
180 *	#     #
181 *	#     #
182 *	#     #
183 *	+#####+
184 *	#     #
185 *	#     #
186 *	#     #
187 *	+#####+
188 */
189	0,
190
191/*	+#####+
192 *	#     #
193 *	#     #
194 *	#     #
195 *	+#####+
196 *	|     #
197 *	|     #
198 *	|     #
199 *	+-----+
200 */
201	SEG_D|SEG_E,
202};
203
204static uint8_t
205iq80310_7seg_xlate(char c)
206{
207	uint8_t rv;
208
209	if (c >= '0' && c <= '9')
210		rv = digitmap[c - '0'];
211	else if (c == '.')
212		rv = (uint8_t) ~SEG_DP;
213	else
214		rv = 0xff;
215
216	return (rv);
217}
218
219void
220iq80310_7seg(char a, char b)
221{
222	uint8_t msb, lsb;
223
224	msb = iq80310_7seg_xlate(a);
225	lsb = iq80310_7seg_xlate(b);
226
227	snakestate = 0;
228
229	CPLD_WRITE(IQ80310_7SEG_MSB, msb);
230	CPLD_WRITE(IQ80310_7SEG_LSB, lsb);
231}
232
233static const uint8_t snakemap[][2] = {
234
235/*	+#####+		+#####+
236 *	|     |		|     |
237 *	|     |		|     |
238 *	|     |		|     |
239 *	+-----+		+-----+
240 *	|     |		|     |
241 *	|     |		|     |
242 *	|     |		|     |
243 *	+-----+		+-----+
244 */
245	{ ~SEG_A,	~SEG_A },
246
247/*	+-----+		+-----+
248 *	#     |		|     #
249 *	#     |		|     #
250 *	#     |		|     #
251 *	+-----+		+-----+
252 *	|     |		|     |
253 *	|     |		|     |
254 *	|     |		|     |
255 *	+-----+		+-----+
256 */
257	{ ~SEG_F,	~SEG_B },
258
259/*	+-----+		+-----+
260 *	|     |		|     |
261 *	|     |		|     |
262 *	|     |		|     |
263 *	+#####+		+#####+
264 *	|     |		|     |
265 *	|     |		|     |
266 *	|     |		|     |
267 *	+-----+		+-----+
268 */
269	{ ~SEG_G,	~SEG_G },
270
271/*	+-----+		+-----+
272 *	|     |		|     |
273 *	|     |		|     |
274 *	|     |		|     |
275 *	+-----+		+-----+
276 *	|     #		#     |
277 *	|     #		#     |
278 *	|     #		#     |
279 *	+-----+		+-----+
280 */
281	{ ~SEG_C,	~SEG_E },
282
283/*	+-----+		+-----+
284 *	|     |		|     |
285 *	|     |		|     |
286 *	|     |		|     |
287 *	+-----+		+-----+
288 *	|     |		|     |
289 *	|     |		|     |
290 *	|     |		|     |
291 *	+#####+		+#####+
292 */
293	{ ~SEG_D,	~SEG_D },
294
295/*	+-----+		+-----+
296 *	|     |		|     |
297 *	|     |		|     |
298 *	|     |		|     |
299 *	+-----+		+-----+
300 *	#     |		|     #
301 *	#     |		|     #
302 *	#     |		|     #
303 *	+-----+		+-----+
304 */
305	{ ~SEG_E,	~SEG_C },
306
307/*	+-----+		+-----+
308 *	|     |		|     |
309 *	|     |		|     |
310 *	|     |		|     |
311 *	+#####+		+#####+
312 *	|     |		|     |
313 *	|     |		|     |
314 *	|     |		|     |
315 *	+-----+		+-----+
316 */
317	{ ~SEG_G,	~SEG_G },
318
319/*	+-----+		+-----+
320 *	|     #		#     |
321 *	|     #		#     |
322 *	|     #		#     |
323 *	+-----+		+-----+
324 *	|     |		|     |
325 *	|     |		|     |
326 *	|     |		|     |
327 *	+-----+		+-----+
328 */
329	{ ~SEG_B,	~SEG_F },
330};
331
332void
333iq80310_7seg_snake(void)
334{
335	int cur = snakestate;
336
337	CPLD_WRITE(IQ80310_7SEG_MSB, snakemap[cur][0]);
338	CPLD_WRITE(IQ80310_7SEG_LSB, snakemap[cur][1]);
339
340	snakestate = (cur + 1) & 7;
341}
342