|  | /* | 
|  | * (C) Copyright 2003, Li-Pro.Net <www.li-pro.net> | 
|  | * Stephan Linz <linz@li-pro.net> | 
|  | * | 
|  | * See file CREDITS for list of people who contributed to this | 
|  | * project. | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License as | 
|  | * published by the Free Software Foundation; either version 2 of | 
|  | * the License, or (at your option) any later version. | 
|  | * | 
|  | * This program is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License | 
|  | * along with this program; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 
|  | * MA 02111-1307 USA | 
|  | * | 
|  | * common/sevenseg.c | 
|  | * | 
|  | * NIOS PIO based seven segment led support functions | 
|  | */ | 
|  |  | 
|  | #include <common.h> | 
|  | #include <nios-io.h> | 
|  |  | 
|  | #ifdef	CONFIG_SEVENSEG | 
|  |  | 
|  | #define SEVENDEG_MASK_DP	((SEVENSEG_DIGIT_DP << 8) | SEVENSEG_DIGIT_DP) | 
|  |  | 
|  | #ifdef	SEVENSEG_WRONLY	/* emulate read access */ | 
|  | #if (SEVENSEG_ACTIVE == 0) | 
|  | static unsigned int sevenseg_portval = ~0; | 
|  | #else | 
|  | static unsigned int sevenseg_portval = 0; | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | static int sevenseg_init_done = 0; | 
|  |  | 
|  | static inline void __sevenseg_set_masked (unsigned int mask, int value) | 
|  | { | 
|  | nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE; | 
|  |  | 
|  | #ifdef	SEVENSEG_WRONLY	/* emulate read access */ | 
|  |  | 
|  | #if (SEVENSEG_ACTIVE == 0) | 
|  | if (value) | 
|  | sevenseg_portval &= ~mask; | 
|  | else | 
|  | sevenseg_portval |= mask; | 
|  | #else | 
|  | if (value) | 
|  | sevenseg_portval |= mask; | 
|  | else | 
|  | sevenseg_portval &= ~mask; | 
|  | #endif | 
|  |  | 
|  | piop->data = sevenseg_portval; | 
|  |  | 
|  | #else	/* !SEVENSEG_WRONLY */ | 
|  |  | 
|  | #if (SEVENSEG_ACTIVE == 0) | 
|  | if (value) | 
|  | piop->data &= ~mask; | 
|  | else | 
|  | piop->data |= mask; | 
|  | #else | 
|  | if (value) | 
|  | piop->data |= mask; | 
|  | else | 
|  | piop->data &= ~mask; | 
|  | #endif | 
|  |  | 
|  | #endif	/* SEVENSEG_WRONLY */ | 
|  | } | 
|  |  | 
|  | static inline void __sevenseg_toggle_masked (unsigned int mask) | 
|  | { | 
|  | nios_pio_t *piop = (nios_pio_t*)SEVENSEG_BASE; | 
|  |  | 
|  | #ifdef	SEVENSEG_WRONLY	/* emulate read access */ | 
|  |  | 
|  | sevenseg_portval ^= mask; | 
|  | piop->data = sevenseg_portval; | 
|  |  | 
|  | #else	/* !SEVENSEG_WRONLY */ | 
|  |  | 
|  | piop->data ^= mask; | 
|  |  | 
|  | #endif	/* SEVENSEG_WRONLY */ | 
|  | } | 
|  |  | 
|  | static inline void __sevenseg_set (unsigned int value) | 
|  | { | 
|  | nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE; | 
|  |  | 
|  | #ifdef	SEVENSEG_WRONLY	/* emulate read access */ | 
|  |  | 
|  | #if (SEVENSEG_ACTIVE == 0) | 
|  | sevenseg_portval = (sevenseg_portval &   SEVENDEG_MASK_DP) | 
|  | | ((~value)         & (~SEVENDEG_MASK_DP)); | 
|  | #else | 
|  | sevenseg_portval = (sevenseg_portval & SEVENDEG_MASK_DP) | 
|  | | (value); | 
|  | #endif | 
|  |  | 
|  | piop->data = sevenseg_portval; | 
|  |  | 
|  | #else	/* !SEVENSEG_WRONLY */ | 
|  |  | 
|  | #if (SEVENSEG_ACTIVE == 0) | 
|  | piop->data = (piop->data &   SEVENDEG_MASK_DP) | 
|  | | ((~value)   & (~SEVENDEG_MASK_DP)); | 
|  | #else | 
|  | piop->data = (piop->data & SEVENDEG_MASK_DP) | 
|  | | (value); | 
|  | #endif | 
|  |  | 
|  | #endif	/* SEVENSEG_WRONLY */ | 
|  | } | 
|  |  | 
|  | static inline void __sevenseg_init (void) | 
|  | { | 
|  | nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE; | 
|  |  | 
|  | __sevenseg_set(0); | 
|  |  | 
|  | #ifndef	SEVENSEG_WRONLY	/* setup direction */ | 
|  |  | 
|  | piop->direction |= mask; | 
|  |  | 
|  | #endif	/* SEVENSEG_WRONLY */ | 
|  | } | 
|  |  | 
|  |  | 
|  | void sevenseg_set(int value) | 
|  | { | 
|  | unsigned char	digits[] = { | 
|  | SEVENSEG_DIGITS_0, | 
|  | SEVENSEG_DIGITS_1, | 
|  | SEVENSEG_DIGITS_2, | 
|  | SEVENSEG_DIGITS_3, | 
|  | SEVENSEG_DIGITS_4, | 
|  | SEVENSEG_DIGITS_5, | 
|  | SEVENSEG_DIGITS_6, | 
|  | SEVENSEG_DIGITS_7, | 
|  | SEVENSEG_DIGITS_8, | 
|  | SEVENSEG_DIGITS_9, | 
|  | SEVENSEG_DIGITS_A, | 
|  | SEVENSEG_DIGITS_B, | 
|  | SEVENSEG_DIGITS_C, | 
|  | SEVENSEG_DIGITS_D, | 
|  | SEVENSEG_DIGITS_E, | 
|  | SEVENSEG_DIGITS_F | 
|  | }; | 
|  |  | 
|  | if (!sevenseg_init_done) { | 
|  | __sevenseg_init(); | 
|  | sevenseg_init_done++; | 
|  | } | 
|  |  | 
|  | switch (value & SEVENSEG_MASK_CTRL) { | 
|  |  | 
|  | case SEVENSEG_RAW: | 
|  | __sevenseg_set( ( | 
|  | (digits[((value & SEVENSEG_MASK_VAL) >>  4)] << 8) | | 
|  | digits[((value & SEVENSEG_MASK_VAL) & 0xf)] ) ); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_OFF: | 
|  | __sevenseg_set(0); | 
|  | __sevenseg_set_masked(SEVENDEG_MASK_DP, 0); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_SET_DPL: | 
|  | __sevenseg_set_masked(SEVENSEG_DIGIT_DP, 1); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_SET_DPH: | 
|  | __sevenseg_set_masked((SEVENSEG_DIGIT_DP << 8), 1); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_RES_DPL: | 
|  | __sevenseg_set_masked(SEVENSEG_DIGIT_DP, 0); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_RES_DPH: | 
|  | __sevenseg_set_masked((SEVENSEG_DIGIT_DP << 8), 0); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_TOG_DPL: | 
|  | __sevenseg_toggle_masked(SEVENSEG_DIGIT_DP); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_TOG_DPH: | 
|  | __sevenseg_toggle_masked((SEVENSEG_DIGIT_DP << 8)); | 
|  | return; | 
|  | break;	/* paranoia */ | 
|  |  | 
|  | case SEVENSEG_LO: | 
|  | case SEVENSEG_HI: | 
|  | case SEVENSEG_STR: | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | #endif	/* CONFIG_SEVENSEG */ |