jazz_led.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * QEMU JAZZ LED emulator.
  3. *
  4. * Copyright (c) 2007 Hervé Poussineau
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "hw.h"
  25. #include "mips.h"
  26. #include "console.h"
  27. #include "pixel_ops.h"
  28. //#define DEBUG_LED
  29. typedef enum {
  30. REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
  31. } screen_state_t;
  32. typedef struct LedState {
  33. uint8_t segments;
  34. DisplayState *ds;
  35. screen_state_t state;
  36. } LedState;
  37. static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
  38. {
  39. LedState *s = opaque;
  40. uint32_t val;
  41. switch (addr) {
  42. case 0:
  43. val = s->segments;
  44. break;
  45. default:
  46. #ifdef DEBUG_LED
  47. printf("jazz led: invalid read [0x%x]\n", relative_addr);
  48. #endif
  49. val = 0;
  50. }
  51. return val;
  52. }
  53. static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
  54. {
  55. uint32_t v;
  56. #ifdef TARGET_WORDS_BIGENDIAN
  57. v = led_readb(opaque, addr) << 8;
  58. v |= led_readb(opaque, addr + 1);
  59. #else
  60. v = led_readb(opaque, addr);
  61. v |= led_readb(opaque, addr + 1) << 8;
  62. #endif
  63. return v;
  64. }
  65. static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
  66. {
  67. uint32_t v;
  68. #ifdef TARGET_WORDS_BIGENDIAN
  69. v = led_readb(opaque, addr) << 24;
  70. v |= led_readb(opaque, addr + 1) << 16;
  71. v |= led_readb(opaque, addr + 2) << 8;
  72. v |= led_readb(opaque, addr + 3);
  73. #else
  74. v = led_readb(opaque, addr);
  75. v |= led_readb(opaque, addr + 1) << 8;
  76. v |= led_readb(opaque, addr + 2) << 16;
  77. v |= led_readb(opaque, addr + 3) << 24;
  78. #endif
  79. return v;
  80. }
  81. static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  82. {
  83. LedState *s = opaque;
  84. switch (addr) {
  85. case 0:
  86. s->segments = val;
  87. s->state |= REDRAW_SEGMENTS;
  88. break;
  89. default:
  90. #ifdef DEBUG_LED
  91. printf("jazz led: invalid write of 0x%02x at [0x%x]\n", val, relative_addr);
  92. #endif
  93. break;
  94. }
  95. }
  96. static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  97. {
  98. #ifdef TARGET_WORDS_BIGENDIAN
  99. led_writeb(opaque, addr, (val >> 8) & 0xff);
  100. led_writeb(opaque, addr + 1, val & 0xff);
  101. #else
  102. led_writeb(opaque, addr, val & 0xff);
  103. led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  104. #endif
  105. }
  106. static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  107. {
  108. #ifdef TARGET_WORDS_BIGENDIAN
  109. led_writeb(opaque, addr, (val >> 24) & 0xff);
  110. led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
  111. led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
  112. led_writeb(opaque, addr + 3, val & 0xff);
  113. #else
  114. led_writeb(opaque, addr, val & 0xff);
  115. led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  116. led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  117. led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  118. #endif
  119. }
  120. static CPUReadMemoryFunc *led_read[3] = {
  121. led_readb,
  122. led_readw,
  123. led_readl,
  124. };
  125. static CPUWriteMemoryFunc *led_write[3] = {
  126. led_writeb,
  127. led_writew,
  128. led_writel,
  129. };
  130. /***********************************************************/
  131. /* jazz_led display */
  132. static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
  133. {
  134. uint8_t *d;
  135. int x, bpp;
  136. bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
  137. d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
  138. switch(bpp) {
  139. case 1:
  140. for (x = posx1; x <= posx2; x++) {
  141. *((uint8_t *)d) = color;
  142. d++;
  143. }
  144. break;
  145. case 2:
  146. for (x = posx1; x <= posx2; x++) {
  147. *((uint16_t *)d) = color;
  148. d += 2;
  149. }
  150. break;
  151. case 4:
  152. for (x = posx1; x <= posx2; x++) {
  153. *((uint32_t *)d) = color;
  154. d += 4;
  155. }
  156. break;
  157. }
  158. }
  159. static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
  160. {
  161. uint8_t *d;
  162. int y, bpp;
  163. bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
  164. d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
  165. switch(bpp) {
  166. case 1:
  167. for (y = posy1; y <= posy2; y++) {
  168. *((uint8_t *)d) = color;
  169. d += ds_get_linesize(ds);
  170. }
  171. break;
  172. case 2:
  173. for (y = posy1; y <= posy2; y++) {
  174. *((uint16_t *)d) = color;
  175. d += ds_get_linesize(ds);
  176. }
  177. break;
  178. case 4:
  179. for (y = posy1; y <= posy2; y++) {
  180. *((uint32_t *)d) = color;
  181. d += ds_get_linesize(ds);
  182. }
  183. break;
  184. }
  185. }
  186. static void jazz_led_update_display(void *opaque)
  187. {
  188. LedState *s = opaque;
  189. DisplayState *ds = s->ds;
  190. uint8_t *d1;
  191. uint32_t color_segment, color_led;
  192. int y, bpp;
  193. if (s->state & REDRAW_BACKGROUND) {
  194. /* clear screen */
  195. bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
  196. d1 = ds_get_data(ds);
  197. for (y = 0; y < ds_get_height(ds); y++) {
  198. memset(d1, 0x00, ds_get_width(ds) * bpp);
  199. d1 += ds_get_linesize(ds);
  200. }
  201. }
  202. if (s->state & REDRAW_SEGMENTS) {
  203. /* set colors according to bpp */
  204. switch (ds_get_bits_per_pixel(ds)) {
  205. case 8:
  206. color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
  207. color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
  208. break;
  209. case 15:
  210. color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa);
  211. color_led = rgb_to_pixel15(0x00, 0xff, 0x00);
  212. break;
  213. case 16:
  214. color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
  215. color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
  216. case 24:
  217. color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
  218. color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
  219. break;
  220. case 32:
  221. color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa);
  222. color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
  223. break;
  224. default:
  225. return;
  226. }
  227. /* display segments */
  228. draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
  229. draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
  230. draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
  231. draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
  232. draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
  233. draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
  234. draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
  235. /* display led */
  236. if (!(s->segments & 0x01))
  237. color_led = 0; /* black */
  238. draw_horizontal_line(ds, 68, 50, 50, color_led);
  239. draw_horizontal_line(ds, 69, 49, 51, color_led);
  240. draw_horizontal_line(ds, 70, 48, 52, color_led);
  241. draw_horizontal_line(ds, 71, 49, 51, color_led);
  242. draw_horizontal_line(ds, 72, 50, 50, color_led);
  243. }
  244. s->state = REDRAW_NONE;
  245. dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
  246. }
  247. static void jazz_led_invalidate_display(void *opaque)
  248. {
  249. LedState *s = opaque;
  250. s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
  251. }
  252. static void jazz_led_screen_dump(void *opaque, const char *filename)
  253. {
  254. printf("jazz_led_screen_dump() not implemented\n");
  255. }
  256. static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
  257. {
  258. LedState *s = opaque;
  259. char buf[2];
  260. dpy_cursor(s->ds, -1, -1);
  261. qemu_console_resize(s->ds, 2, 1);
  262. /* TODO: draw the segments */
  263. snprintf(buf, 2, "%02hhx\n", s->segments);
  264. console_write_ch(chardata++, 0x00200100 | buf[0]);
  265. console_write_ch(chardata++, 0x00200100 | buf[1]);
  266. dpy_update(s->ds, 0, 0, 2, 1);
  267. }
  268. void jazz_led_init(target_phys_addr_t base)
  269. {
  270. LedState *s;
  271. int io;
  272. s = qemu_mallocz(sizeof(LedState));
  273. s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
  274. io = cpu_register_io_memory(0, led_read, led_write, s);
  275. cpu_register_physical_memory(base, 1, io);
  276. s->ds = graphic_console_init(jazz_led_update_display,
  277. jazz_led_invalidate_display,
  278. jazz_led_screen_dump,
  279. jazz_led_text_update, s);
  280. qemu_console_resize(s->ds, 60, 80);
  281. }