OSDN Git Service

Luminary board input support.
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 18 Nov 2007 14:36:08 +0000 (14:36 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 18 Nov 2007 14:36:08 +0000 (14:36 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3689 c046a42c-6fe2-441c-8c8c-71466251a162

Makefile
hw/devices.h
hw/irq.c
hw/stellaris.c
hw/stellaris_input.c [new file with mode: 0644]

index 82e4202..493330c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,7 @@ OBJS+=block.o
 
 OBJS+=irq.o
 OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
-OBJS+=ssd0303.o ssd0323.o ads7846.o 
+OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o
 OBJS+=scsi-disk.o cdrom.o
 OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o
 
index 3827745..07c673b 100644 (file)
@@ -16,4 +16,7 @@ uint32_t ads7846_read(void *opaque);
 void ads7846_write(void *opaque, uint32_t value);
 struct ads7846_state_s *ads7846_init(qemu_irq penirq);
 
+/* stellaris_input.c */
+void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
+
 #endif
index 960155a..eca707d 100644 (file)
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -65,5 +65,7 @@ static void qemu_notirq(void *opaque, int line, int level)
 
 qemu_irq qemu_irq_invert(qemu_irq irq)
 {
+    /* The default state for IRQs is low, so raise the output now.  */
+    qemu_irq_raise(irq);
     return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
 }
index 878c7f8..3dbb2ce 100644 (file)
 #include "sysemu.h"
 #include "boards.h"
 
+#define GPIO_A 0
+#define GPIO_B 1
+#define GPIO_C 2
+#define GPIO_D 3
+#define GPIO_E 4
+#define GPIO_F 5
+#define GPIO_G 6
+
+#define BP_OLED_I2C  0x01
+#define BP_OLED_SSI  0x02
+#define BP_GAMEPAD   0x04
+
 typedef const struct {
     const char *name;
     uint32_t did0;
@@ -25,7 +37,7 @@ typedef const struct {
     uint32_t dc2;
     uint32_t dc3;
     uint32_t dc4;
-    enum {OLED_I2C, OLED_SSI} oled;
+    uint32_t peripherals;
 } stellaris_board_info;
 
 /* General purpose timer module.  */
@@ -991,7 +1003,7 @@ static stellaris_board_info stellaris_boards[] = {
     0x01071013,
     0x3f0f01ff,
     0x0000001f,
-    OLED_I2C
+    BP_OLED_I2C
   },
   { "LM3S6965EVB",
     0x10010002,
@@ -1001,7 +1013,7 @@ static stellaris_board_info stellaris_boards[] = {
     0x030f5317,
     0x0f0f87ff,
     0x5000007f,
-    OLED_SSI
+    BP_OLED_SSI | BP_GAMEPAD
   }
 };
 
@@ -1052,7 +1064,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
     if (board->dc2 & (1 << 12)) {
         i2c = i2c_init_bus();
         stellaris_i2c_init(0x40020000, pic[8], i2c);
-        if (board->oled == OLED_I2C) {
+        if (board->peripherals & BP_OLED_I2C) {
             ssd0303_init(ds, i2c, 0x3d);
         }
     }
@@ -1064,15 +1076,27 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
         }
     }
     if (board->dc2 & (1 << 4)) {
-        if (board->oled == OLED_SSI) {
+        if (board->peripherals & BP_OLED_SSI) {
             void * oled;
             /* FIXME: Implement chip select for OLED/MMC.  */
-            oled = ssd0323_init(ds, &gpio_out[2][7]);
+            oled = ssd0323_init(ds, &gpio_out[GPIO_C][7]);
             pl022_init(0x40008000, pic[7], ssd0323_xfer_ssi, oled);
         } else {
             pl022_init(0x40008000, pic[7], NULL, NULL);
         }
     }
+    if (board->peripherals & BP_GAMEPAD) {
+        qemu_irq gpad_irq[5];
+        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
+
+        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
+        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
+        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
+        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
+        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
+
+        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
+    }
 }
 
 /* FIXME: Figure out how to generate these from stellaris_boards.  */
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
new file mode 100644 (file)
index 0000000..461868b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Gamepad style buttons connected to IRQ/GPIO lines
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the GPL.
+ */
+#include "hw.h"
+#include "devices.h"
+#include "console.h"
+
+typedef struct {
+    qemu_irq irq;
+    int keycode;
+    int pressed;
+} gamepad_button;
+
+typedef struct {
+    gamepad_button *buttons;
+    int num_buttons;
+    int extension;
+} gamepad_state;
+
+static void stellaris_gamepad_put_key(void * opaque, int keycode)
+{
+    gamepad_state *s = (gamepad_state *)opaque;
+    int i;
+    int down;
+
+    if (keycode == 0xe0 && !s->extension) {
+        s->extension = 0x80;
+        return;
+    }
+
+    down = (keycode & 0x80) == 0;
+    keycode = (keycode & 0x7f) | s->extension;
+
+    for (i = 0; i < s->num_buttons; i++) {
+        if (s->buttons[i].keycode == keycode
+                && s->buttons[i].pressed != down) {
+            s->buttons[i].pressed = down;
+            qemu_set_irq(s->buttons[i].irq, down);
+        }
+    }
+
+    s->extension = 0;
+}
+
+/* Returns an array 5 ouput slots.  */
+void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
+{
+    gamepad_state *s;
+    int i;
+
+    s = (gamepad_state *)qemu_mallocz(sizeof (gamepad_state));
+    s->buttons = (gamepad_button *)qemu_mallocz(n * sizeof (gamepad_button));
+    for (i = 0; i < n; i++) {
+        s->buttons[i].irq = irq[i];
+        s->buttons[i].keycode = keycode[i];
+    }
+    s->num_buttons = n;
+    qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
+}
+
+