     if (usbStatus == -1) {
         Serial.println("OSC did not start.");
     }
-#endif
-
-    initNeutralTable();
-    initHenkanTable();
+    Serial.println("Started");
+#endif
+
+    initKeyMappings();
 
     HidComposite.SetReportParser(0, &keyboardReportParser);
     HidComposite.SetReportParser(1, &mouseReportParser);
     HidKeyboard.SetReportParser(0, &keyboardReportParser);
     HidMouse.SetReportParser(0, &mouseReportParser);
+
+    Joystick.setXAxisRange(STICK_UP, STICK_DOWN);
+    Joystick.setYAxisRange(STICK_LEFT, STICK_RIGHT);
+
     Mouse.begin();
     Keyboard.begin();
+    Joystick.begin();
 }
 
 void loop() {

#define KEY_HOME 0x4A
#define KEY_END 0x4D

#define KEY_COUNT 0x100

#define OUTPUT_TO_SERIAL 1

uint8_t neutralTable[KEY_COUNT];
void initNeutralTable(){
    for (int i = 0; i < KEY_COUNT; ++i){
        neutralTable[i] = i;
    }

    neutralTable[KEY_Q        ] = KEY_COLON;
    neutralTable[KEY_W        ] = KEY_COMMA;
    neutralTable[KEY_E        ] = KEY_PERIOD;
    neutralTable[KEY_R        ] = KEY_P;
    neutralTable[KEY_T        ] = KEY_Y;
    neutralTable[KEY_Y        ] = KEY_F;
    neutralTable[KEY_U        ] = KEY_G;
    neutralTable[KEY_I        ] = KEY_C;
    neutralTable[KEY_O        ] = KEY_R;
    neutralTable[KEY_P        ] = KEY_L;
    neutralTable[KEY_AT       ] = KEY_SLASH;
    neutralTable[KEY_S        ] = KEY_O;
    neutralTable[KEY_D        ] = KEY_E;
    neutralTable[KEY_F        ] = KEY_U;
    neutralTable[KEY_G        ] = KEY_I;
    neutralTable[KEY_H        ] = KEY_D;
    neutralTable[KEY_J        ] = KEY_H;
    neutralTable[KEY_K        ] = KEY_T;
    neutralTable[KEY_L        ] = KEY_N;
    neutralTable[KEY_SEMICOLON] = KEY_S;
    neutralTable[KEY_COLON    ] = KEY_MINUS;
    neutralTable[KEY_Z        ] = KEY_SEMICOLON;
    neutralTable[KEY_X        ] = KEY_Q;
    neutralTable[KEY_C        ] = KEY_J;
    neutralTable[KEY_V        ] = KEY_K;
    neutralTable[KEY_B        ] = KEY_X;
    neutralTable[KEY_N        ] = KEY_B;
    neutralTable[KEY_M        ] = KEY_M;
    neutralTable[KEY_COMMA    ] = KEY_W;
    neutralTable[KEY_PERIOD   ] = KEY_V;
    neutralTable[KEY_SLASH    ] = KEY_Z;
}

uint8_t henkanTable[KEY_COUNT];
void initHenkanTable(){
    for (int i = 0; i < KEY_COUNT; ++i){
        henkanTable[i] = i;
    }

    henkanTable[KEY_Q        ] = KEY_1;
    henkanTable[KEY_W        ] = KEY_2;
    henkanTable[KEY_E        ] = KEY_3;
    henkanTable[KEY_R        ] = KEY_4;
    henkanTable[KEY_T        ] = KEY_5;
    henkanTable[KEY_Y        ] = KEY_6;
    henkanTable[KEY_U        ] = KEY_7;
    henkanTable[KEY_I        ] = KEY_8;
    henkanTable[KEY_O        ] = KEY_9;
    henkanTable[KEY_P        ] = KEY_0;
    henkanTable[KEY_AT       ] = KEY_SLASH;
    henkanTable[KEY_A        ] = KEY_TAB;
    henkanTable[KEY_S        ] = KEY_ESCAPE;
    henkanTable[KEY_D        ] = KEY_ENTER;
    henkanTable[KEY_F        ] = KEY_BACKSPACE;
    henkanTable[KEY_G        ] = KEY_DELETE;
    henkanTable[KEY_H        ] = KEY_HOME;
    henkanTable[KEY_J        ] = KEY_LEFT;
    henkanTable[KEY_K        ] = KEY_UP;
    henkanTable[KEY_L        ] = KEY_RIGHT;
    henkanTable[KEY_SEMICOLON] = KEY_END;
    henkanTable[KEY_COLON    ] = KEY_MINUS;
    henkanTable[KEY_Z        ] = KEY_AT;
    henkanTable[KEY_X        ] = KEY_BRACKET_OPEN;
    henkanTable[KEY_C        ] = KEY_BRACKET_CLOSE;
    henkanTable[KEY_V        ] = KEY_HAT;
    henkanTable[KEY_B        ] = KEY_X;
    henkanTable[KEY_N        ] = KEY_B;
    henkanTable[KEY_M        ] = KEY_BACKSLASH;
    henkanTable[KEY_COMMA    ] = KEY_DOWN;
    henkanTable[KEY_PERIOD   ] = KEY_YEN;
    henkanTable[KEY_SLASH    ] = KEY_HAN_ZEN;
}

bool remove(uint8_t *buf, uint8_t key){
    uint8_t index;

    for (index = 2; index < LEN; ++index) {
        if (buf[index] == key) break;
    }

    if (index == LEN) return false;

    for (; index < LEN - 1; ++index) {
        buf[index] = buf[index + 1];
    }

    buf[LEN - 1] = 0;

    return true;
}

void changeCapsLockToControl(uint8_t *buf){
    if (remove(buf, KEY_CAPS_LOCK)) buf[0] |= MODIFIER_CTRL_LEFT;
}

void changeMuhenkanToShift(uint8_t *buf) {
    if (remove(buf, KEY_MUHENKAN)) buf[0] |= MODIFIER_SHIFT_LEFT;
}

bool henkanPrev = false;

void handleCustomModifier(uint8_t *buf) {
    bool henkan = remove(buf, KEY_HENKAN);

    // modifierが変化した時にはキーを出力しない
    if (!henkanPrev && henkan || henkanPrev && !henkan) {
        for (int i = 2; i < LEN; i++) {
            buf[i] = 0;
        }
    } else if (henkan){
        for (int i = 2; i < LEN; i++){
            buf[i] = henkanTable[buf[i]];
        }
    } else {
        for (int i = 2; i < LEN; i++){
            buf[i] = neutralTable[buf[i]];
        }
    }

    henkanPrev = henkan;
}


class HIDKeyboardReportParser : public HIDReportParser {
public:
    virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
#if OUTPUT_TO_SERIAL
        Serial.print("SRC:  ");
        for (int i = 0; i < LEN; i++) {
            Serial.print(buf[i], HEX);
            Serial.print(" ");
        }
        Serial.println("");
#endif

        changeCapsLockToControl(buf);
        changeMuhenkanToShift(buf);
        handleCustomModifier(buf);

#if OUTPUT_TO_SERIAL
        Serial.print("DEST: ");
        for (int i = 0; i < len; i++) {
            Serial.print(buf[i], HEX);
            Serial.print(" ");
        }
        Serial.println("");
#endif

        Keyboard.sendReport((KeyReport *)buf);
    }
};


class HIDMouseReportParser : public MouseReportParser {
protected:
    virtual void OnMouseMove(MOUSEINFO *mouseInfo)        { Mouse.move((signed char)(mouseInfo->dX * 1.5), (signed char)(mouseInfo->dY * 1.5), 0); }
    virtual void OnLeftButtonDown(MOUSEINFO *mouseInfo)   { Mouse.press(MOUSE_LEFT); }
    virtual void OnLeftButtonUp(MOUSEINFO *mouseInfo)     { Mouse.release(MOUSE_LEFT); }
    virtual void OnRightButtonDown(MOUSEINFO *mouseInfo)  { Mouse.press(MOUSE_RIGHT); }
    virtual void OnRightButtonUp(MOUSEINFO *mouseInfo)    { Mouse.release(MOUSE_RIGHT); }
    virtual void OnMiddleButtonDown(MOUSEINFO *mouseInfo) { Mouse.press(MOUSE_MIDDLE); }
    virtual void OnMiddleButtonUp(MOUSEINFO *mouseInfo)   { Mouse.release(MOUSE_MIDDLE); }
};

USB    Usb;
USBHub Hub(&Usb);

HIDBoot<USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE> HidComposite(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD>                          HidKeyboard(&Usb);
HIDBoot<USB_HID_PROTOCOL_MOUSE>                             HidMouse(&Usb);

HIDKeyboardReportParser keyboardReportParser;
HIDMouseReportParser mouseReportParser;

void setup() {
    int usbStatus = Usb.Init();

#include <usbhub.h>
#include <Keyboard.h>
#include <Mouse.h>
#include <Joystick.h>

#define OUTPUT_TO_SERIAL 0

#define NUM_REPORT_KEYS 6

#define MODIFIER_LEFT_CTRL 0x1
#define MODIFIER_LEFT_SHIFT 0x2
#define MODIFIER_LEFT_ALT 0x4
#define MODIFIER_RIGHT_SHIFT 0x20
#define MODIFIER_RIGHT_ALT 0x40

#define KEY_CAPS_LOCK 0x39
#define KEY_HENKAN 0x8A
