Statistics
| Branch: | Revision:

root / hw / jazz_led.c @ c60e08d9

History | View | Annotate | Download (9.4 kB)

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

    
25
#include "hw.h"
26
#include "mips.h"
27
#include "console.h"
28
#include "pixel_ops.h"
29

    
30
//#define DEBUG_LED
31

    
32
typedef enum {
33
    REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
34
} screen_state_t;
35

    
36
typedef struct LedState {
37
    target_phys_addr_t base;
38
    uint8_t segments;
39
    DisplayState *ds;
40
    QEMUConsole *console;
41
    screen_state_t state;
42
} LedState;
43

    
44
static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
45
{
46
    LedState *s = opaque;
47
    int relative_addr = addr - s->base;
48
    uint32_t val;
49

    
50
    switch (relative_addr) {
51
        case 0:
52
            val = s->segments;
53
            break;
54
        default:
55
#ifdef DEBUG_LED
56
            printf("jazz led: invalid read [0x%x]\n", relative_addr);
57
#endif
58
            val = 0;
59
    }
60

    
61
    return val;
62
}
63

    
64
static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
65
{
66
    uint32_t v;
67
#ifdef TARGET_WORDS_BIGENDIAN
68
    v = led_readb(opaque, addr) << 8;
69
    v |= led_readb(opaque, addr + 1);
70
#else
71
    v = led_readb(opaque, addr);
72
    v |= led_readb(opaque, addr + 1) << 8;
73
#endif
74
    return v;
75
}
76

    
77
static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
78
{
79
    uint32_t v;
80
#ifdef TARGET_WORDS_BIGENDIAN
81
    v = led_readb(opaque, addr) << 24;
82
    v |= led_readb(opaque, addr + 1) << 16;
83
    v |= led_readb(opaque, addr + 2) << 8;
84
    v |= led_readb(opaque, addr + 3);
85
#else
86
    v = led_readb(opaque, addr);
87
    v |= led_readb(opaque, addr + 1) << 8;
88
    v |= led_readb(opaque, addr + 2) << 16;
89
    v |= led_readb(opaque, addr + 3) << 24;
90
#endif
91
    return v;
92
}
93

    
94
static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
95
{
96
    LedState *s = opaque;
97
    int relative_addr = addr - s->base;
98

    
99
    switch (relative_addr) {
100
        case 0:
101
            s->segments = val;
102
            s->state |= REDRAW_SEGMENTS;
103
            break;
104
        default:
105
#ifdef DEBUG_LED
106
            printf("jazz led: invalid write of 0x%02x at [0x%x]\n", val, relative_addr);
107
#endif
108
            break;
109
    }
110
}
111

    
112
static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
113
{
114
#ifdef TARGET_WORDS_BIGENDIAN
115
    led_writeb(opaque, addr, (val >> 8) & 0xff);
116
    led_writeb(opaque, addr + 1, val & 0xff);
117
#else
118
    led_writeb(opaque, addr, val & 0xff);
119
    led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
120
#endif
121
}
122

    
123
static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
124
{
125
#ifdef TARGET_WORDS_BIGENDIAN
126
    led_writeb(opaque, addr, (val >> 24) & 0xff);
127
    led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
128
    led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
129
    led_writeb(opaque, addr + 3, val & 0xff);
130
#else
131
    led_writeb(opaque, addr, val & 0xff);
132
    led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
133
    led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
134
    led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
135
#endif
136
}
137

    
138
static CPUReadMemoryFunc *led_read[3] = {
139
    led_readb,
140
    led_readw,
141
    led_readl,
142
};
143

    
144
static CPUWriteMemoryFunc *led_write[3] = {
145
    led_writeb,
146
    led_writew,
147
    led_writel,
148
};
149

    
150
/***********************************************************/
151
/* jazz_led display */
152

    
153
static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
154
{
155
    uint8_t *d;
156
    int x, bpp;
157

    
158
    bpp = (ds->depth + 7) >> 3;
159
    d = ds->data + ds->linesize * posy + bpp * posx1;
160
    switch(bpp) {
161
        case 1:
162
            for (x = posx1; x <= posx2; x++) {
163
                *((uint8_t *)d) = color;
164
                d++;
165
            }
166
            break;
167
        case 2:
168
            for (x = posx1; x <= posx2; x++) {
169
                *((uint16_t *)d) = color;
170
                d += 2;
171
            }
172
            break;
173
        case 4:
174
            for (x = posx1; x <= posx2; x++) {
175
                *((uint32_t *)d) = color;
176
                d += 4;
177
            }
178
            break;
179
    }
180
}
181

    
182
static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
183
{
184
    uint8_t *d;
185
    int y, bpp;
186

    
187
    bpp = (ds->depth + 7) >> 3;
188
    d = ds->data + ds->linesize * posy1 + bpp * posx;
189
    switch(bpp) {
190
        case 1:
191
            for (y = posy1; y <= posy2; y++) {
192
                *((uint8_t *)d) = color;
193
                d += ds->linesize;
194
            }
195
            break;
196
        case 2:
197
            for (y = posy1; y <= posy2; y++) {
198
                *((uint16_t *)d) = color;
199
                d += ds->linesize;
200
            }
201
            break;
202
        case 4:
203
            for (y = posy1; y <= posy2; y++) {
204
                *((uint32_t *)d) = color;
205
                d += ds->linesize;
206
            }
207
            break;
208
    }
209
}
210

    
211
static void jazz_led_update_display(void *opaque)
212
{
213
    LedState *s = opaque;
214
    DisplayState *ds = s->ds;
215
    uint8_t *d1;
216
    uint32_t color_segment, color_led;
217
    int y, bpp;
218

    
219
    if (s->state & REDRAW_BACKGROUND) {
220
        /* clear screen */
221
        bpp = (ds->depth + 7) >> 3;
222
        d1 = ds->data;
223
        for (y = 0; y < ds->height; y++) {
224
            memset(d1, 0x00, ds->width * bpp);
225
            d1 += ds->linesize;
226
        }
227
    }
228

    
229
    if (s->state & REDRAW_SEGMENTS) {
230
        /* set colors according to bpp */
231
        switch (ds->depth) {
232
            case 8:
233
                color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
234
                color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
235
                break;
236
            case 15:
237
                color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa);
238
                color_led = rgb_to_pixel15(0x00, 0xff, 0x00);
239
                break;
240
            case 16:
241
                color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
242
                color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
243
            case 24:
244
                color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
245
                color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
246
                break;
247
            case 32:
248
                color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa);
249
                color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
250
                break;
251
            default:
252
                return;
253
        }
254

    
255
        /* display segments */
256
        draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
257
        draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
258
        draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
259
        draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
260
        draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
261
        draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
262
        draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
263

    
264
        /* display led */
265
        if (!(s->segments & 0x01))
266
            color_led = 0; /* black */
267
        draw_horizontal_line(ds, 68, 50, 50, color_led);
268
        draw_horizontal_line(ds, 69, 49, 51, color_led);
269
        draw_horizontal_line(ds, 70, 48, 52, color_led);
270
        draw_horizontal_line(ds, 71, 49, 51, color_led);
271
        draw_horizontal_line(ds, 72, 50, 50, color_led);
272
    }
273

    
274
    s->state = REDRAW_NONE;
275
    dpy_update(ds, 0, 0, ds->width, ds->height);
276
}
277

    
278
static void jazz_led_invalidate_display(void *opaque)
279
{
280
    LedState *s = opaque;
281
    s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
282
}
283

    
284
static void jazz_led_screen_dump(void *opaque, const char *filename)
285
{
286
    printf("jazz_led_screen_dump() not implemented\n");
287
}
288

    
289
static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
290
{
291
    LedState *s = opaque;
292
    char buf[2];
293

    
294
    dpy_cursor(s->ds, -1, -1);
295
    qemu_console_resize(s->console, 2, 1);
296

    
297
    /* TODO: draw the segments */
298
    snprintf(buf, 2, "%02hhx\n", s->segments);
299
    console_write_ch(chardata++, 0x00200100 | buf[0]);
300
    console_write_ch(chardata++, 0x00200100 | buf[1]);
301

    
302
    dpy_update(s->ds, 0, 0, 2, 1);
303
}
304

    
305
void jazz_led_init(DisplayState *ds, target_phys_addr_t base)
306
{
307
    LedState *s;
308
    int io;
309

    
310
    s = qemu_mallocz(sizeof(LedState));
311
    if (!s)
312
        return;
313

    
314
    s->base = base;
315
    s->ds = ds;
316
    s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
317

    
318
    io = cpu_register_io_memory(0, led_read, led_write, s);
319
    cpu_register_physical_memory(s->base, 1, io);
320

    
321
    s->console = graphic_console_init(ds, jazz_led_update_display,
322
                                     jazz_led_invalidate_display,
323
                                     jazz_led_screen_dump,
324
                                     jazz_led_text_update, s);
325
    qemu_console_resize(s->console, 60, 80);
326
}