symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/jazz_led.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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     uint8_t segments;
       
    38     DisplayState *ds;
       
    39     QEMUConsole *console;
       
    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     uint32_t val;
       
    47 
       
    48     switch (addr) {
       
    49         case 0:
       
    50             val = s->segments;
       
    51             break;
       
    52         default:
       
    53 #ifdef DEBUG_LED
       
    54             printf("jazz led: invalid read [0x%x]\n", relative_addr);
       
    55 #endif
       
    56             val = 0;
       
    57     }
       
    58 
       
    59     return val;
       
    60 }
       
    61 
       
    62 static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
       
    63 {
       
    64     uint32_t v;
       
    65 #ifdef TARGET_WORDS_BIGENDIAN
       
    66     v = led_readb(opaque, addr) << 8;
       
    67     v |= led_readb(opaque, addr + 1);
       
    68 #else
       
    69     v = led_readb(opaque, addr);
       
    70     v |= led_readb(opaque, addr + 1) << 8;
       
    71 #endif
       
    72     return v;
       
    73 }
       
    74 
       
    75 static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
       
    76 {
       
    77     uint32_t v;
       
    78 #ifdef TARGET_WORDS_BIGENDIAN
       
    79     v = led_readb(opaque, addr) << 24;
       
    80     v |= led_readb(opaque, addr + 1) << 16;
       
    81     v |= led_readb(opaque, addr + 2) << 8;
       
    82     v |= led_readb(opaque, addr + 3);
       
    83 #else
       
    84     v = led_readb(opaque, addr);
       
    85     v |= led_readb(opaque, addr + 1) << 8;
       
    86     v |= led_readb(opaque, addr + 2) << 16;
       
    87     v |= led_readb(opaque, addr + 3) << 24;
       
    88 #endif
       
    89     return v;
       
    90 }
       
    91 
       
    92 static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
       
    93 {
       
    94     LedState *s = opaque;
       
    95 
       
    96     switch (addr) {
       
    97         case 0:
       
    98             s->segments = val;
       
    99             s->state |= REDRAW_SEGMENTS;
       
   100             break;
       
   101         default:
       
   102 #ifdef DEBUG_LED
       
   103             printf("jazz led: invalid write of 0x%02x at [0x%x]\n", val, relative_addr);
       
   104 #endif
       
   105             break;
       
   106     }
       
   107 }
       
   108 
       
   109 static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
       
   110 {
       
   111 #ifdef TARGET_WORDS_BIGENDIAN
       
   112     led_writeb(opaque, addr, (val >> 8) & 0xff);
       
   113     led_writeb(opaque, addr + 1, val & 0xff);
       
   114 #else
       
   115     led_writeb(opaque, addr, val & 0xff);
       
   116     led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
       
   117 #endif
       
   118 }
       
   119 
       
   120 static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
       
   121 {
       
   122 #ifdef TARGET_WORDS_BIGENDIAN
       
   123     led_writeb(opaque, addr, (val >> 24) & 0xff);
       
   124     led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
       
   125     led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
       
   126     led_writeb(opaque, addr + 3, val & 0xff);
       
   127 #else
       
   128     led_writeb(opaque, addr, val & 0xff);
       
   129     led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
       
   130     led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
       
   131     led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
       
   132 #endif
       
   133 }
       
   134 
       
   135 static CPUReadMemoryFunc *led_read[3] = {
       
   136     led_readb,
       
   137     led_readw,
       
   138     led_readl,
       
   139 };
       
   140 
       
   141 static CPUWriteMemoryFunc *led_write[3] = {
       
   142     led_writeb,
       
   143     led_writew,
       
   144     led_writel,
       
   145 };
       
   146 
       
   147 /***********************************************************/
       
   148 /* jazz_led display */
       
   149 
       
   150 static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
       
   151 {
       
   152     uint8_t *d;
       
   153     int x, bpp;
       
   154 
       
   155     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
       
   156     d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
       
   157     switch(bpp) {
       
   158         case 1:
       
   159             for (x = posx1; x <= posx2; x++) {
       
   160                 *((uint8_t *)d) = color;
       
   161                 d++;
       
   162             }
       
   163             break;
       
   164         case 2:
       
   165             for (x = posx1; x <= posx2; x++) {
       
   166                 *((uint16_t *)d) = color;
       
   167                 d += 2;
       
   168             }
       
   169             break;
       
   170         case 4:
       
   171             for (x = posx1; x <= posx2; x++) {
       
   172                 *((uint32_t *)d) = color;
       
   173                 d += 4;
       
   174             }
       
   175             break;
       
   176     }
       
   177 }
       
   178 
       
   179 static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
       
   180 {
       
   181     uint8_t *d;
       
   182     int y, bpp;
       
   183 
       
   184     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
       
   185     d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
       
   186     switch(bpp) {
       
   187         case 1:
       
   188             for (y = posy1; y <= posy2; y++) {
       
   189                 *((uint8_t *)d) = color;
       
   190                 d += ds_get_linesize(ds);
       
   191             }
       
   192             break;
       
   193         case 2:
       
   194             for (y = posy1; y <= posy2; y++) {
       
   195                 *((uint16_t *)d) = color;
       
   196                 d += ds_get_linesize(ds);
       
   197             }
       
   198             break;
       
   199         case 4:
       
   200             for (y = posy1; y <= posy2; y++) {
       
   201                 *((uint32_t *)d) = color;
       
   202                 d += ds_get_linesize(ds);
       
   203             }
       
   204             break;
       
   205     }
       
   206 }
       
   207 
       
   208 static void jazz_led_update_display(void *opaque)
       
   209 {
       
   210     LedState *s = opaque;
       
   211     DisplayState *ds = s->ds;
       
   212     uint8_t *d1;
       
   213     uint32_t color_segment, color_led;
       
   214     int y, bpp;
       
   215 
       
   216     if (s->state & REDRAW_BACKGROUND) {
       
   217         /* clear screen */
       
   218         bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
       
   219         d1 = ds_get_data(ds);
       
   220         for (y = 0; y < ds_get_height(ds); y++) {
       
   221             memset(d1, 0x00, ds_get_width(ds) * bpp);
       
   222             d1 += ds_get_linesize(ds);
       
   223         }
       
   224     }
       
   225 
       
   226     if (s->state & REDRAW_SEGMENTS) {
       
   227         /* set colors according to bpp */
       
   228         switch (ds_get_bits_per_pixel(ds)) {
       
   229             case 8:
       
   230                 color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
       
   231                 color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
       
   232                 break;
       
   233             case 15:
       
   234                 color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa);
       
   235                 color_led = rgb_to_pixel15(0x00, 0xff, 0x00);
       
   236                 break;
       
   237             case 16:
       
   238                 color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
       
   239                 color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
       
   240             case 24:
       
   241                 color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
       
   242                 color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
       
   243                 break;
       
   244             case 32:
       
   245                 color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa);
       
   246                 color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
       
   247                 break;
       
   248             default:
       
   249                 return;
       
   250         }
       
   251 
       
   252         /* display segments */
       
   253         draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
       
   254         draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
       
   255         draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
       
   256         draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
       
   257         draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
       
   258         draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
       
   259         draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
       
   260 
       
   261         /* display led */
       
   262         if (!(s->segments & 0x01))
       
   263             color_led = 0; /* black */
       
   264         draw_horizontal_line(ds, 68, 50, 50, color_led);
       
   265         draw_horizontal_line(ds, 69, 49, 51, color_led);
       
   266         draw_horizontal_line(ds, 70, 48, 52, color_led);
       
   267         draw_horizontal_line(ds, 71, 49, 51, color_led);
       
   268         draw_horizontal_line(ds, 72, 50, 50, color_led);
       
   269     }
       
   270 
       
   271     s->state = REDRAW_NONE;
       
   272     dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
       
   273 }
       
   274 
       
   275 static void jazz_led_invalidate_display(void *opaque)
       
   276 {
       
   277     LedState *s = opaque;
       
   278     s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
       
   279 }
       
   280 
       
   281 static void jazz_led_screen_dump(void *opaque, const char *filename)
       
   282 {
       
   283     printf("jazz_led_screen_dump() not implemented\n");
       
   284 }
       
   285 
       
   286 static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
       
   287 {
       
   288     LedState *s = opaque;
       
   289     char buf[2];
       
   290 
       
   291     dpy_cursor(s->ds, -1, -1);
       
   292     qemu_console_resize(s->console, 2, 1);
       
   293 
       
   294     /* TODO: draw the segments */
       
   295     snprintf(buf, 2, "%02hhx\n", s->segments);
       
   296     console_write_ch(chardata++, 0x00200100 | buf[0]);
       
   297     console_write_ch(chardata++, 0x00200100 | buf[1]);
       
   298 
       
   299     dpy_update(s->ds, 0, 0, 2, 1);
       
   300 }
       
   301 
       
   302 void jazz_led_init(DisplayState *ds, target_phys_addr_t base)
       
   303 {
       
   304     LedState *s;
       
   305     int io;
       
   306 
       
   307     s = qemu_mallocz(sizeof(LedState));
       
   308     if (!s)
       
   309         return;
       
   310 
       
   311     s->ds = ds;
       
   312     s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
       
   313 
       
   314     io = cpu_register_io_memory(0, led_read, led_write, s);
       
   315     cpu_register_physical_memory(base, 1, io);
       
   316 
       
   317     s->console = graphic_console_init(ds, jazz_led_update_display,
       
   318                                      jazz_led_invalidate_display,
       
   319                                      jazz_led_screen_dump,
       
   320                                      jazz_led_text_update, s);
       
   321     qemu_console_resize(s->console, 60, 80);
       
   322 }