blob: 1f22c8524a500cdf66ce08f5bf7978e3b6eae521 [file] [log] [blame]
wdenk3be717f2004-01-03 19:43:48 +00001/*
2 * (C) Copyright 2003, Li-Pro.Net <www.li-pro.net>
3 * Stephan Linz <linz@li-pro.net>
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk3be717f2004-01-03 19:43:48 +00006 *
7 * common/sevenseg.c
8 *
9 * NIOS PIO based seven segment led support functions
10 */
11
12#include <common.h>
13#include <nios-io.h>
14
15#ifdef CONFIG_SEVENSEG
16
17#define SEVENDEG_MASK_DP ((SEVENSEG_DIGIT_DP << 8) | SEVENSEG_DIGIT_DP)
18
19#ifdef SEVENSEG_WRONLY /* emulate read access */
20#if (SEVENSEG_ACTIVE == 0)
21static unsigned int sevenseg_portval = ~0;
22#else
23static unsigned int sevenseg_portval = 0;
24#endif
25#endif
26
27static int sevenseg_init_done = 0;
28
29static inline void __sevenseg_set_masked (unsigned int mask, int value)
30{
wdenk2cefd152004-02-08 22:55:38 +000031 nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;
wdenk3be717f2004-01-03 19:43:48 +000032
33#ifdef SEVENSEG_WRONLY /* emulate read access */
34
35#if (SEVENSEG_ACTIVE == 0)
36 if (value)
37 sevenseg_portval &= ~mask;
38 else
39 sevenseg_portval |= mask;
40#else
41 if (value)
42 sevenseg_portval |= mask;
43 else
44 sevenseg_portval &= ~mask;
45#endif
46
47 piop->data = sevenseg_portval;
48
49#else /* !SEVENSEG_WRONLY */
50
51#if (SEVENSEG_ACTIVE == 0)
52 if (value)
53 piop->data &= ~mask;
54 else
55 piop->data |= mask;
56#else
57 if (value)
58 piop->data |= mask;
59 else
60 piop->data &= ~mask;
61#endif
62
63#endif /* SEVENSEG_WRONLY */
64}
65
66static inline void __sevenseg_toggle_masked (unsigned int mask)
67{
68 nios_pio_t *piop = (nios_pio_t*)SEVENSEG_BASE;
69
70#ifdef SEVENSEG_WRONLY /* emulate read access */
71
72 sevenseg_portval ^= mask;
73 piop->data = sevenseg_portval;
74
75#else /* !SEVENSEG_WRONLY */
76
77 piop->data ^= mask;
78
79#endif /* SEVENSEG_WRONLY */
80}
81
82static inline void __sevenseg_set (unsigned int value)
83{
wdenk2cefd152004-02-08 22:55:38 +000084 nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;
wdenk3be717f2004-01-03 19:43:48 +000085
86#ifdef SEVENSEG_WRONLY /* emulate read access */
87
88#if (SEVENSEG_ACTIVE == 0)
89 sevenseg_portval = (sevenseg_portval & SEVENDEG_MASK_DP)
Wolfgang Denkec7fbf52013-10-04 17:43:24 +020090 | ((~value) & (~SEVENDEG_MASK_DP));
wdenk3be717f2004-01-03 19:43:48 +000091#else
92 sevenseg_portval = (sevenseg_portval & SEVENDEG_MASK_DP)
Wolfgang Denkec7fbf52013-10-04 17:43:24 +020093 | (value);
wdenk3be717f2004-01-03 19:43:48 +000094#endif
95
96 piop->data = sevenseg_portval;
97
98#else /* !SEVENSEG_WRONLY */
99
100#if (SEVENSEG_ACTIVE == 0)
101 piop->data = (piop->data & SEVENDEG_MASK_DP)
102 | ((~value) & (~SEVENDEG_MASK_DP));
103#else
104 piop->data = (piop->data & SEVENDEG_MASK_DP)
105 | (value);
106#endif
107
108#endif /* SEVENSEG_WRONLY */
109}
110
111static inline void __sevenseg_init (void)
112{
wdenk2cefd152004-02-08 22:55:38 +0000113 nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;
wdenk3be717f2004-01-03 19:43:48 +0000114
115 __sevenseg_set(0);
116
117#ifndef SEVENSEG_WRONLY /* setup direction */
118
119 piop->direction |= mask;
120
121#endif /* SEVENSEG_WRONLY */
122}
123
124
125void sevenseg_set(int value)
126{
127 unsigned char digits[] = {
128 SEVENSEG_DIGITS_0,
129 SEVENSEG_DIGITS_1,
130 SEVENSEG_DIGITS_2,
131 SEVENSEG_DIGITS_3,
132 SEVENSEG_DIGITS_4,
133 SEVENSEG_DIGITS_5,
134 SEVENSEG_DIGITS_6,
135 SEVENSEG_DIGITS_7,
136 SEVENSEG_DIGITS_8,
137 SEVENSEG_DIGITS_9,
138 SEVENSEG_DIGITS_A,
139 SEVENSEG_DIGITS_B,
140 SEVENSEG_DIGITS_C,
141 SEVENSEG_DIGITS_D,
142 SEVENSEG_DIGITS_E,
143 SEVENSEG_DIGITS_F
144 };
145
146 if (!sevenseg_init_done) {
147 __sevenseg_init();
148 sevenseg_init_done++;
149 }
150
151 switch (value & SEVENSEG_MASK_CTRL) {
152
153 case SEVENSEG_RAW:
154 __sevenseg_set( (
155 (digits[((value & SEVENSEG_MASK_VAL) >> 4)] << 8) |
156 digits[((value & SEVENSEG_MASK_VAL) & 0xf)] ) );
157 return;
158 break; /* paranoia */
159
160 case SEVENSEG_OFF:
161 __sevenseg_set(0);
162 __sevenseg_set_masked(SEVENDEG_MASK_DP, 0);
163 return;
164 break; /* paranoia */
165
166 case SEVENSEG_SET_DPL:
167 __sevenseg_set_masked(SEVENSEG_DIGIT_DP, 1);
168 return;
169 break; /* paranoia */
170
171 case SEVENSEG_SET_DPH:
172 __sevenseg_set_masked((SEVENSEG_DIGIT_DP << 8), 1);
173 return;
174 break; /* paranoia */
175
176 case SEVENSEG_RES_DPL:
177 __sevenseg_set_masked(SEVENSEG_DIGIT_DP, 0);
178 return;
179 break; /* paranoia */
180
181 case SEVENSEG_RES_DPH:
182 __sevenseg_set_masked((SEVENSEG_DIGIT_DP << 8), 0);
183 return;
184 break; /* paranoia */
185
186 case SEVENSEG_TOG_DPL:
187 __sevenseg_toggle_masked(SEVENSEG_DIGIT_DP);
188 return;
189 break; /* paranoia */
190
191 case SEVENSEG_TOG_DPH:
192 __sevenseg_toggle_masked((SEVENSEG_DIGIT_DP << 8));
193 return;
194 break; /* paranoia */
195
196 case SEVENSEG_LO:
197 case SEVENSEG_HI:
198 case SEVENSEG_STR:
199 default:
200 break;
201 }
202}
203
204#endif /* CONFIG_SEVENSEG */