Annotation of qemu/hw/jazz_led.c, revision 1.1.1.7
1.1 root 1: /*
2: * QEMU JAZZ LED emulator.
3: *
1.1.1.7 ! root 4: * Copyright (c) 2007-2012 Herve Poussineau
1.1 root 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:
25: #include "console.h"
26: #include "pixel_ops.h"
1.1.1.7 ! root 27: #include "trace.h"
! 28: #include "sysbus.h"
1.1.1.5 root 29:
1.1 root 30: typedef enum {
31: REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
32: } screen_state_t;
33:
34: typedef struct LedState {
1.1.1.7 ! root 35: SysBusDevice busdev;
! 36: MemoryRegion iomem;
1.1 root 37: uint8_t segments;
38: DisplayState *ds;
39: screen_state_t state;
40: } LedState;
41:
1.1.1.7 ! root 42: static uint64_t jazz_led_read(void *opaque, target_phys_addr_t addr,
! 43: unsigned int size)
1.1 root 44: {
45: LedState *s = opaque;
1.1.1.7 ! root 46: uint8_t val;
1.1 root 47:
1.1.1.7 ! root 48: val = s->segments;
! 49: trace_jazz_led_read(addr, val);
1.1.1.5 root 50:
1.1 root 51: return val;
52: }
53:
1.1.1.7 ! root 54: static void jazz_led_write(void *opaque, target_phys_addr_t addr,
! 55: uint64_t val, unsigned int size)
1.1 root 56: {
57: LedState *s = opaque;
1.1.1.7 ! root 58: uint8_t new_val = val & 0xff;
1.1 root 59:
1.1.1.7 ! root 60: trace_jazz_led_write(addr, new_val);
1.1.1.5 root 61:
1.1.1.7 ! root 62: s->segments = new_val;
! 63: s->state |= REDRAW_SEGMENTS;
1.1 root 64: }
65:
1.1.1.7 ! root 66: static const MemoryRegionOps led_ops = {
! 67: .read = jazz_led_read,
! 68: .write = jazz_led_write,
! 69: .endianness = DEVICE_NATIVE_ENDIAN,
! 70: .impl.min_access_size = 1,
! 71: .impl.max_access_size = 1,
1.1 root 72: };
73:
74: /***********************************************************/
75: /* jazz_led display */
76:
77: static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
78: {
79: uint8_t *d;
80: int x, bpp;
81:
1.1.1.2 root 82: bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
83: d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
1.1 root 84: switch(bpp) {
85: case 1:
86: for (x = posx1; x <= posx2; x++) {
87: *((uint8_t *)d) = color;
88: d++;
89: }
90: break;
91: case 2:
92: for (x = posx1; x <= posx2; x++) {
93: *((uint16_t *)d) = color;
94: d += 2;
95: }
96: break;
97: case 4:
98: for (x = posx1; x <= posx2; x++) {
99: *((uint32_t *)d) = color;
100: d += 4;
101: }
102: break;
103: }
104: }
105:
106: static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
107: {
108: uint8_t *d;
109: int y, bpp;
110:
1.1.1.2 root 111: bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
112: d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
1.1 root 113: switch(bpp) {
114: case 1:
115: for (y = posy1; y <= posy2; y++) {
116: *((uint8_t *)d) = color;
1.1.1.2 root 117: d += ds_get_linesize(ds);
1.1 root 118: }
119: break;
120: case 2:
121: for (y = posy1; y <= posy2; y++) {
122: *((uint16_t *)d) = color;
1.1.1.2 root 123: d += ds_get_linesize(ds);
1.1 root 124: }
125: break;
126: case 4:
127: for (y = posy1; y <= posy2; y++) {
128: *((uint32_t *)d) = color;
1.1.1.2 root 129: d += ds_get_linesize(ds);
1.1 root 130: }
131: break;
132: }
133: }
134:
135: static void jazz_led_update_display(void *opaque)
136: {
137: LedState *s = opaque;
138: DisplayState *ds = s->ds;
139: uint8_t *d1;
140: uint32_t color_segment, color_led;
141: int y, bpp;
142:
143: if (s->state & REDRAW_BACKGROUND) {
144: /* clear screen */
1.1.1.2 root 145: bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
146: d1 = ds_get_data(ds);
147: for (y = 0; y < ds_get_height(ds); y++) {
148: memset(d1, 0x00, ds_get_width(ds) * bpp);
149: d1 += ds_get_linesize(ds);
1.1 root 150: }
151: }
152:
153: if (s->state & REDRAW_SEGMENTS) {
154: /* set colors according to bpp */
1.1.1.2 root 155: switch (ds_get_bits_per_pixel(ds)) {
1.1 root 156: case 8:
157: color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
158: color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
159: break;
160: case 15:
161: color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa);
162: color_led = rgb_to_pixel15(0x00, 0xff, 0x00);
163: break;
164: case 16:
165: color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
166: color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
167: case 24:
168: color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
169: color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
170: break;
171: case 32:
172: color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa);
173: color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
174: break;
175: default:
176: return;
177: }
178:
179: /* display segments */
180: draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
181: draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
182: draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
183: draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
184: draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
185: draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
186: draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
187:
188: /* display led */
189: if (!(s->segments & 0x01))
190: color_led = 0; /* black */
191: draw_horizontal_line(ds, 68, 50, 50, color_led);
192: draw_horizontal_line(ds, 69, 49, 51, color_led);
193: draw_horizontal_line(ds, 70, 48, 52, color_led);
194: draw_horizontal_line(ds, 71, 49, 51, color_led);
195: draw_horizontal_line(ds, 72, 50, 50, color_led);
196: }
197:
198: s->state = REDRAW_NONE;
1.1.1.2 root 199: dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
1.1 root 200: }
201:
202: static void jazz_led_invalidate_display(void *opaque)
203: {
204: LedState *s = opaque;
205: s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
206: }
207:
1.1.1.2 root 208: static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
209: {
210: LedState *s = opaque;
211: char buf[2];
212:
213: dpy_cursor(s->ds, -1, -1);
214: qemu_console_resize(s->ds, 2, 1);
215:
216: /* TODO: draw the segments */
217: snprintf(buf, 2, "%02hhx\n", s->segments);
218: console_write_ch(chardata++, 0x00200100 | buf[0]);
219: console_write_ch(chardata++, 0x00200100 | buf[1]);
220:
221: dpy_update(s->ds, 0, 0, 2, 1);
222: }
223:
1.1.1.7 ! root 224: static int jazz_led_post_load(void *opaque, int version_id)
1.1 root 225: {
1.1.1.7 ! root 226: /* force refresh */
! 227: jazz_led_invalidate_display(opaque);
1.1 root 228:
1.1.1.7 ! root 229: return 0;
! 230: }
1.1 root 231:
1.1.1.7 ! root 232: static const VMStateDescription vmstate_jazz_led = {
! 233: .name = "jazz-led",
! 234: .version_id = 0,
! 235: .minimum_version_id = 0,
! 236: .minimum_version_id_old = 0,
! 237: .post_load = jazz_led_post_load,
! 238: .fields = (VMStateField[]) {
! 239: VMSTATE_UINT8(segments, LedState),
! 240: VMSTATE_END_OF_LIST()
! 241: }
! 242: };
1.1 root 243:
1.1.1.7 ! root 244: static int jazz_led_init(SysBusDevice *dev)
! 245: {
! 246: LedState *s = FROM_SYSBUS(LedState, dev);
! 247:
! 248: memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
! 249: sysbus_init_mmio(dev, &s->iomem);
1.1 root 250:
1.1.1.2 root 251: s->ds = graphic_console_init(jazz_led_update_display,
252: jazz_led_invalidate_display,
1.1.1.7 ! root 253: NULL,
1.1.1.2 root 254: jazz_led_text_update, s);
1.1.1.7 ! root 255:
! 256: return 0;
! 257: }
! 258:
! 259: static void jazz_led_reset(DeviceState *d)
! 260: {
! 261: LedState *s = DO_UPCAST(LedState, busdev.qdev, d);
! 262:
! 263: s->segments = 0;
! 264: s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
1.1.1.2 root 265: qemu_console_resize(s->ds, 60, 80);
1.1 root 266: }
1.1.1.7 ! root 267:
! 268: static void jazz_led_class_init(ObjectClass *klass, void *data)
! 269: {
! 270: DeviceClass *dc = DEVICE_CLASS(klass);
! 271: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
! 272:
! 273: k->init = jazz_led_init;
! 274: dc->desc = "Jazz LED display",
! 275: dc->vmsd = &vmstate_jazz_led;
! 276: dc->reset = jazz_led_reset;
! 277: }
! 278:
! 279: static TypeInfo jazz_led_info = {
! 280: .name = "jazz-led",
! 281: .parent = TYPE_SYS_BUS_DEVICE,
! 282: .instance_size = sizeof(LedState),
! 283: .class_init = jazz_led_class_init,
! 284: };
! 285:
! 286: static void jazz_led_register(void)
! 287: {
! 288: type_register_static(&jazz_led_info);
! 289: }
! 290:
! 291: type_init(jazz_led_register);
unix.superglobalmegacorp.com