iq81342_7seg.c revision 302408
1/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2001, 2002, 2003 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 IQ81342. 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: stable/11/sys/arm/xscale/i8134x/iq81342_7seg.c 236987 2012-06-13 04:38:09Z imp $"); 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/kernel.h> 48#include <sys/module.h> 49#include <sys/bus.h> 50#include <sys/sysctl.h> 51 52#include <machine/bus.h> 53 54#include <arm/xscale/i8134x/i81342reg.h> 55#include <arm/xscale/i8134x/iq81342reg.h> 56#include <arm/xscale/i8134x/iq81342var.h> 57 58#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v) 59 60static int snakestate; 61 62/* 63 * The 7-segment display looks like so: 64 * 65 * A 66 * +-----+ 67 * | | 68 * F | | B 69 * | G | 70 * +-----+ 71 * | | 72 * E | | C 73 * | D | 74 * +-----+ o DP 75 * 76 * Setting a bit clears the corresponding segment on the 77 * display. 78 */ 79#define SEG_A (1 << 1) 80#define SEG_B (1 << 2) 81#define SEG_C (1 << 3) 82#define SEG_D (1 << 4) 83#define SEG_E (1 << 5) 84#define SEG_F (1 << 6) 85#define SEG_G (1 << 7) 86#define SEG_DP (1 << 0) 87 88static const uint8_t digitmap[] = { 89/* +#####+ 90 * # # 91 * # # 92 * # # 93 * +-----+ 94 * # # 95 * # # 96 * # # 97 * +#####+ 98 */ 99 (unsigned char)~SEG_G, 100 101/* +-----+ 102 * | # 103 * | # 104 * | # 105 * +-----+ 106 * | # 107 * | # 108 * | # 109 * +-----+ 110 */ 111 SEG_B|SEG_C, 112 113/* +#####+ 114 * | # 115 * | # 116 * | # 117 * +#####+ 118 * # | 119 * # | 120 * # | 121 * +#####+ 122 */ 123 ~(SEG_C|SEG_F), 124 125/* +#####+ 126 * | # 127 * | # 128 * | # 129 * +#####+ 130 * | # 131 * | # 132 * | # 133 * +#####+ 134 */ 135 ~(SEG_E|SEG_F), 136 137/* +-----+ 138 * # # 139 * # # 140 * # # 141 * +#####+ 142 * | # 143 * | # 144 * | # 145 * +-----+ 146 */ 147 ~(SEG_A|SEG_D|SEG_E), 148 149/* +#####+ 150 * # | 151 * # | 152 * # | 153 * +#####+ 154 * | # 155 * | # 156 * | # 157 * +#####+ 158 */ 159 ~(SEG_B|SEG_E), 160 161/* +#####+ 162 * # | 163 * # | 164 * # | 165 * +#####+ 166 * # # 167 * # # 168 * # # 169 * +#####+ 170 */ 171 ~(SEG_B), 172 173/* +#####+ 174 * | # 175 * | # 176 * | # 177 * +-----+ 178 * | # 179 * | # 180 * | # 181 * +-----+ 182 */ 183 ~(SEG_D|SEG_E|SEG_F), 184 185/* +#####+ 186 * # # 187 * # # 188 * # # 189 * +#####+ 190 * # # 191 * # # 192 * # # 193 * +#####+ 194 */ 195 ~0, 196 197/* +#####+ 198 * # # 199 * # # 200 * # # 201 * +#####+ 202 * | # 203 * | # 204 * | # 205 * +-----+ 206 */ 207 ~(SEG_D|SEG_E), 208}; 209 210static uint8_t 211iq81342_7seg_xlate(char c) 212{ 213 uint8_t rv; 214 215 if (c >= '0' && c <= '9') 216 rv = digitmap[c - '0']; 217 else if (c == '.') 218 rv = (uint8_t) ~SEG_DP; 219 else 220 rv = 0xff; 221 222 return (rv); 223} 224 225void 226iq81342_7seg(char a, char b) 227{ 228 uint8_t msb, lsb; 229 230 msb = iq81342_7seg_xlate(a); 231 lsb = iq81342_7seg_xlate(b); 232 233 snakestate = 0; 234 235 WRITE(IQ8134X_7SEG_MSB, msb); 236 WRITE(IQ8134X_7SEG_LSB, lsb); 237} 238 239static const uint8_t snakemap[][2] = { 240 241/* +#####+ +#####+ 242 * | | | | 243 * | | | | 244 * | | | | 245 * +-----+ +-----+ 246 * | | | | 247 * | | | | 248 * | | | | 249 * +-----+ +-----+ 250 */ 251 { SEG_A, SEG_A }, 252 253/* +-----+ +-----+ 254 * # | | # 255 * # | | # 256 * # | | # 257 * +-----+ +-----+ 258 * | | | | 259 * | | | | 260 * | | | | 261 * +-----+ +-----+ 262 */ 263 { SEG_F, SEG_B }, 264 265/* +-----+ +-----+ 266 * | | | | 267 * | | | | 268 * | | | | 269 * +#####+ +#####+ 270 * | | | | 271 * | | | | 272 * | | | | 273 * +-----+ +-----+ 274 */ 275 { SEG_G, SEG_G }, 276 277/* +-----+ +-----+ 278 * | | | | 279 * | | | | 280 * | | | | 281 * +-----+ +-----+ 282 * | # # | 283 * | # # | 284 * | # # | 285 * +-----+ +-----+ 286 */ 287 { SEG_C, SEG_E }, 288 289/* +-----+ +-----+ 290 * | | | | 291 * | | | | 292 * | | | | 293 * +-----+ +-----+ 294 * | | | | 295 * | | | | 296 * | | | | 297 * +#####+ +#####+ 298 */ 299 { SEG_D, SEG_D }, 300 301/* +-----+ +-----+ 302 * | | | | 303 * | | | | 304 * | | | | 305 * +-----+ +-----+ 306 * # | | # 307 * # | | # 308 * # | | # 309 * +-----+ +-----+ 310 */ 311 { SEG_E, SEG_C }, 312 313/* +-----+ +-----+ 314 * | | | | 315 * | | | | 316 * | | | | 317 * +#####+ +#####+ 318 * | | | | 319 * | | | | 320 * | | | | 321 * +-----+ +-----+ 322 */ 323 { SEG_G, SEG_G }, 324 325/* +-----+ +-----+ 326 * | # # | 327 * | # # | 328 * | # # | 329 * +-----+ +-----+ 330 * | | | | 331 * | | | | 332 * | | | | 333 * +-----+ +-----+ 334 */ 335 { SEG_B, SEG_F }, 336}; 337 338static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg"); 339static int freq = 20; 340SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0, 341 "7 Seg update frequency"); 342static void 343iq81342_7seg_snake(void) 344{ 345 static int snakefreq; 346 int cur = snakestate; 347 348 snakefreq++; 349 if ((snakefreq % freq)) 350 return; 351 WRITE(IQ8134X_7SEG_MSB, snakemap[cur][0]); 352 WRITE(IQ8134X_7SEG_LSB, snakemap[cur][1]); 353 354 snakestate = (cur + 1) & 7; 355} 356 357struct iq81342_7seg_softc { 358 device_t dev; 359}; 360 361static int 362iq81342_7seg_probe(device_t dev) 363{ 364 365 device_set_desc(dev, "IQ81342 7seg"); 366 return (0); 367} 368 369extern void (*i80321_hardclock_hook)(void); 370static int 371iq81342_7seg_attach(device_t dev) 372{ 373 374 i80321_hardclock_hook = iq81342_7seg_snake; 375 return (0); 376} 377 378static device_method_t iq81342_7seg_methods[] = { 379 DEVMETHOD(device_probe, iq81342_7seg_probe), 380 DEVMETHOD(device_attach, iq81342_7seg_attach), 381 {0, 0}, 382}; 383 384static driver_t iq81342_7seg_driver = { 385 "iqseg", 386 iq81342_7seg_methods, 387 sizeof(struct iq81342_7seg_softc), 388}; 389static devclass_t iq81342_7seg_devclass; 390 391DRIVER_MODULE(iqseg, iq, iq81342_7seg_driver, iq81342_7seg_devclass, 0, 0); 392