Statistics
| Branch: | Revision:

root / hw / jazz_led.c @ 4d3b6f6e

History | View | Annotate | Download (9.3 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
    screen_state_t state;
41
} LedState;
42

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

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

    
60
    return val;
61
}
62

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

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

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

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

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

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

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

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

    
149
/***********************************************************/
150
/* jazz_led display */
151

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

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

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

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

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

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

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

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

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

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

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

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

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

    
293
    dpy_cursor(s->ds, -1, -1);
294
    dpy_resize(s->ds, 2, 1);
295

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

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

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

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

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

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

    
320
    graphic_console_init(ds, jazz_led_update_display,
321
                         jazz_led_invalidate_display, jazz_led_screen_dump,
322
                         jazz_led_text_update, s);
323
}