sevenseg.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * (C) Copyright 2003, Li-Pro.Net <www.li-pro.net>
  3. * Stephan Linz <linz@li-pro.net>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. *
  7. * common/sevenseg.c
  8. *
  9. * NIOS PIO based seven segment led support functions
  10. */
  11. #include <common.h>
  12. #include <nios-io.h>
  13. #ifdef CONFIG_SEVENSEG
  14. #define SEVENDEG_MASK_DP ((SEVENSEG_DIGIT_DP << 8) | SEVENSEG_DIGIT_DP)
  15. #ifdef SEVENSEG_WRONLY /* emulate read access */
  16. #if (SEVENSEG_ACTIVE == 0)
  17. static unsigned int sevenseg_portval = ~0;
  18. #else
  19. static unsigned int sevenseg_portval = 0;
  20. #endif
  21. #endif
  22. static int sevenseg_init_done = 0;
  23. static inline void __sevenseg_set_masked (unsigned int mask, int value)
  24. {
  25. nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;
  26. #ifdef SEVENSEG_WRONLY /* emulate read access */
  27. #if (SEVENSEG_ACTIVE == 0)
  28. if (value)
  29. sevenseg_portval &= ~mask;
  30. else
  31. sevenseg_portval |= mask;
  32. #else
  33. if (value)
  34. sevenseg_portval |= mask;
  35. else
  36. sevenseg_portval &= ~mask;
  37. #endif
  38. piop->data = sevenseg_portval;
  39. #else /* !SEVENSEG_WRONLY */
  40. #if (SEVENSEG_ACTIVE == 0)
  41. if (value)
  42. piop->data &= ~mask;
  43. else
  44. piop->data |= mask;
  45. #else
  46. if (value)
  47. piop->data |= mask;
  48. else
  49. piop->data &= ~mask;
  50. #endif
  51. #endif /* SEVENSEG_WRONLY */
  52. }
  53. static inline void __sevenseg_toggle_masked (unsigned int mask)
  54. {
  55. nios_pio_t *piop = (nios_pio_t*)SEVENSEG_BASE;
  56. #ifdef SEVENSEG_WRONLY /* emulate read access */
  57. sevenseg_portval ^= mask;
  58. piop->data = sevenseg_portval;
  59. #else /* !SEVENSEG_WRONLY */
  60. piop->data ^= mask;
  61. #endif /* SEVENSEG_WRONLY */
  62. }
  63. static inline void __sevenseg_set (unsigned int value)
  64. {
  65. nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;
  66. #ifdef SEVENSEG_WRONLY /* emulate read access */
  67. #if (SEVENSEG_ACTIVE == 0)
  68. sevenseg_portval = (sevenseg_portval & SEVENDEG_MASK_DP)
  69. | ((~value) & (~SEVENDEG_MASK_DP));
  70. #else
  71. sevenseg_portval = (sevenseg_portval & SEVENDEG_MASK_DP)
  72. | (value);
  73. #endif
  74. piop->data = sevenseg_portval;
  75. #else /* !SEVENSEG_WRONLY */
  76. #if (SEVENSEG_ACTIVE == 0)
  77. piop->data = (piop->data & SEVENDEG_MASK_DP)
  78. | ((~value) & (~SEVENDEG_MASK_DP));
  79. #else
  80. piop->data = (piop->data & SEVENDEG_MASK_DP)
  81. | (value);
  82. #endif
  83. #endif /* SEVENSEG_WRONLY */
  84. }
  85. static inline void __sevenseg_init (void)
  86. {
  87. nios_pio_t *piop __attribute__((unused)) = (nios_pio_t*)SEVENSEG_BASE;
  88. __sevenseg_set(0);
  89. #ifndef SEVENSEG_WRONLY /* setup direction */
  90. piop->direction |= mask;
  91. #endif /* SEVENSEG_WRONLY */
  92. }
  93. void sevenseg_set(int value)
  94. {
  95. unsigned char digits[] = {
  96. SEVENSEG_DIGITS_0,
  97. SEVENSEG_DIGITS_1,
  98. SEVENSEG_DIGITS_2,
  99. SEVENSEG_DIGITS_3,
  100. SEVENSEG_DIGITS_4,
  101. SEVENSEG_DIGITS_5,
  102. SEVENSEG_DIGITS_6,
  103. SEVENSEG_DIGITS_7,
  104. SEVENSEG_DIGITS_8,
  105. SEVENSEG_DIGITS_9,
  106. SEVENSEG_DIGITS_A,
  107. SEVENSEG_DIGITS_B,
  108. SEVENSEG_DIGITS_C,
  109. SEVENSEG_DIGITS_D,
  110. SEVENSEG_DIGITS_E,
  111. SEVENSEG_DIGITS_F
  112. };
  113. if (!sevenseg_init_done) {
  114. __sevenseg_init();
  115. sevenseg_init_done++;
  116. }
  117. switch (value & SEVENSEG_MASK_CTRL) {
  118. case SEVENSEG_RAW:
  119. __sevenseg_set( (
  120. (digits[((value & SEVENSEG_MASK_VAL) >> 4)] << 8) |
  121. digits[((value & SEVENSEG_MASK_VAL) & 0xf)] ) );
  122. return;
  123. break; /* paranoia */
  124. case SEVENSEG_OFF:
  125. __sevenseg_set(0);
  126. __sevenseg_set_masked(SEVENDEG_MASK_DP, 0);
  127. return;
  128. break; /* paranoia */
  129. case SEVENSEG_SET_DPL:
  130. __sevenseg_set_masked(SEVENSEG_DIGIT_DP, 1);
  131. return;
  132. break; /* paranoia */
  133. case SEVENSEG_SET_DPH:
  134. __sevenseg_set_masked((SEVENSEG_DIGIT_DP << 8), 1);
  135. return;
  136. break; /* paranoia */
  137. case SEVENSEG_RES_DPL:
  138. __sevenseg_set_masked(SEVENSEG_DIGIT_DP, 0);
  139. return;
  140. break; /* paranoia */
  141. case SEVENSEG_RES_DPH:
  142. __sevenseg_set_masked((SEVENSEG_DIGIT_DP << 8), 0);
  143. return;
  144. break; /* paranoia */
  145. case SEVENSEG_TOG_DPL:
  146. __sevenseg_toggle_masked(SEVENSEG_DIGIT_DP);
  147. return;
  148. break; /* paranoia */
  149. case SEVENSEG_TOG_DPH:
  150. __sevenseg_toggle_masked((SEVENSEG_DIGIT_DP << 8));
  151. return;
  152. break; /* paranoia */
  153. case SEVENSEG_LO:
  154. case SEVENSEG_HI:
  155. case SEVENSEG_STR:
  156. default:
  157. break;
  158. }
  159. }
  160. #endif /* CONFIG_SEVENSEG */