~ruther/qmk_firmware

239bdbf41936566c0ae5b0cbd8c6bf7dd824f7fb — tmk 14 years ago 3015f19
PS/2: request to resend when error is occured.
4 files changed, 93 insertions(+), 110 deletions(-)

M keyboard.c
M ps2.c
M ps2_vusb/main.c
M vusb/host.c
M keyboard.c => keyboard.c +1 -0
@@ 106,6 106,7 @@ void keyboard_proc(void)
        return;
    }

    // TODO: should send only when changed from last report
    if (matrix_is_modified()) {
        host_send_keyboard_report();
#ifdef DEBUG_LED

M ps2.c => ps2.c +90 -33
@@ 96,13 96,15 @@ void ps2_host_init(void)
#endif
}

// TODO: send using interrupt if available
uint8_t ps2_host_send(uint8_t data)
{
    bool parity;
RETRY:
    parity = true;
    ps2_error = 0;

    uint8_t res = 0;
    bool parity = true;
    ps2_error = PS2_ERR_NONE;
#ifdef PS2_INT_DISABLE
    PS2_INT_DISABLE();
#endif
    /* terminate a transmission if we have */
    inhibit();
    _delay_us(100);


@@ 139,15 141,15 @@ RETRY:
    WAIT(clock_hi, 50, 8);
    WAIT(data_hi, 50, 9);

    uint8_t res = ps2_host_recv_response();
    if (res == 0xFE && data != 0xFE)
        goto RETRY;

    inhibit();
    return res;
    res = ps2_host_recv_response();
ERROR:
#ifdef PS2_INT_ENABLE
    PS2_INT_ENABLE();
    idle();
#else
    inhibit();
    return 0;
#endif
    return res;
}

/* receive data when host want else inhibit communication */


@@ 209,46 211,99 @@ static inline uint8_t pbuf_dequeue(void)
/* get data received by interrupt */
uint8_t ps2_host_recv(void)
{
    // TODO: release clock line after 100us when inhibited by error
    if (ps2_error) {
        ps2_host_send(0xFE);    // request to resend
        ps2_error = PS2_ERR_NONE;
    }
    return pbuf_dequeue();
}

#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0)
#define DEBUGP(x) do { PORTC = x; } while (0)
ISR(PS2_INT_VECT)
{
    /* interrupt means start bit comes */
    pbuf_enqueue(recv_data());
    static enum {
        INIT,
        START,
        BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
        PARITY,
        STOP,
    } state = INIT;
    static uint8_t data = 0;
    static uint8_t parity = 1;

    // TODO: abort if elapse 100us from previous interrupt

    // return unless falling edge
    if (clock_in()) {
        goto RETURN;
    }

    /* release lines(idle state) */
    idle();
    _delay_us(5);
    state++;
    DEBUGP(state);
    switch (state) {
        case START:
            if (data_in())
                goto ERROR;
            break;
        case BIT0:
        case BIT1:
        case BIT2:
        case BIT3:
        case BIT4:
        case BIT5:
        case BIT6:
        case BIT7:
            data >>= 1;
            if (data_in()) {
                data |= 0x80;
                parity++;
            }
            break;
        case PARITY:
            if (data_in()) {
                if (!(parity & 0x01))
                    goto ERROR;
            } else {
                if (parity & 0x01)
                    goto ERROR;
            }
            break;
        case STOP:
            if (!data_in())
                goto ERROR;
            pbuf_enqueue(data);
            goto DONE;
            break;
        default:
            goto ERROR;
    }
    goto RETURN;
ERROR:
    DEBUGP(0xFF);
    inhibit();
    ps2_error = state;
DONE:
    state = INIT;
    data = 0;
    parity = 1;
RETURN:
    return;
}
#endif


/*
static void ps2_reset(void)
{
    ps2_host_send(0xFF);
    if (ps2_host_recv_response() == 0xFA) {
        _delay_ms(1000);
        ps2_host_recv_response();
    }
}
*/

/* send LED state to keyboard */
void ps2_host_set_led(uint8_t led)
{
#ifdef PS2_INT_DISABLE
    PS2_INT_DISABLE();
#endif
    ps2_host_send(0xED);
    ps2_host_recv_response();
    ps2_host_send(led);
    ps2_host_recv_response();
#ifdef PS2_INT_ENABLE
    PS2_INT_ENABLE();
    idle();
#endif
}




@@ 257,7 312,7 @@ static uint8_t recv_data(void)
{
    uint8_t data = 0;
    bool parity = true;
    ps2_error = 0;
    ps2_error = PS2_ERR_NONE;

    /* start bit [1] */
    WAIT(clock_lo, 1, 1);


@@ 307,6 362,7 @@ static inline bool clock_in()
{
    PS2_CLOCK_DDR  &= ~(1<<PS2_CLOCK_BIT);
    PS2_CLOCK_PORT |=  (1<<PS2_CLOCK_BIT);
    _delay_us(1);
    return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
}
static inline void data_lo()


@@ 324,6 380,7 @@ static inline bool data_in()
{
    PS2_DATA_DDR  &= ~(1<<PS2_DATA_BIT);
    PS2_DATA_PORT |=  (1<<PS2_DATA_BIT);
    _delay_us(1);
    return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
}


M ps2_vusb/main.c => ps2_vusb/main.c +2 -49
@@ 49,7 49,7 @@ int main(void)
    usbInit();

    print_enable = true;
    //debug_enable = true;
    debug_enable = true;
    keyboard_init();

    /* enforce re-enumeration, do this while interrupts are disabled! */


@@ 64,56 64,9 @@ int main(void)

    //uint8_t fn_bits = 0;
    while (1) {                /* main event loop */
        DEBUGP(0x01);
        wdt_reset();
        usbPoll();
        host_vusb_keyboard_send();

        DEBUGP(0x02);
        keyboard_proc();
        DEBUGP(0x03);
/*
        matrix_scan();
        fn_bits = 0;
        host_swap_keyboard_report();
        host_clear_keyboard_report();
        mousekey_clear_report();
        for (int row = 0; row < matrix_rows(); row++) {
            for (int col = 0; col < matrix_cols(); col++) {
                if (!matrix_is_on(row, col)) continue;

                uint8_t code = layer_get_keycode(row, col);
                if (code == KB_NO) {
                    // do nothing
                }
                else if (IS_MOD(code)) {
                    host_add_mod_bit(MOD_BIT(code));
                }
                else if (IS_KEY(code)) {
                    host_add_key(code);
                }
                else if (IS_FN(code)) {
                    fn_bits |= FN_BIT(code);
                }
                else if (IS_MOUSEKEY(code)) {
                    mousekey_decode(code);
                }
                else {
                    debug("ignore keycode: "); debug_hex(code); debug("\n");
                }
            }
        }
        DEBUGP(0x03);
        layer_switching(fn_bits);
        if (matrix_is_modified()) {
            host_send_keyboard_report();
        }
        mousekey_send();

        if (last_led != host_keyboard_led()) {
            led_set(host_keyboard_led());
            last_led = host_keyboard_led();
        }
*/
        host_vusb_keyboard_send();
    }
}

M vusb/host.c => vusb/host.c +0 -28
@@ 258,33 258,6 @@ PROGMEM uchar keyboard_hid_report[] = {
 */
PROGMEM uchar mouse_hid_report[] = {
    /* from HID 1.11 spec example */
    0x05, 0x01,     // Usage Page (Generic Desktop),
    0x09, 0x02,     // Usage (Mouse),
    0xA1, 0x01,     // Collection (Application),
    0x09, 0x01,     //   Usage (Pointer),
    0xA1, 0x00,     //   Collection (Physical),
    0x05, 0x09,     //     Usage Page (Buttons),
    0x19, 0x01,     //     Usage Minimum (01),
    0x29, 0x03,     //     Usage Maximun (03),
    0x15, 0x00,     //     Logical Minimum (0),
    0x25, 0x01,     //     Logical Maximum (1),
    0x95, 0x03,     //     Report Count (3),
    0x75, 0x01,     //     Report Size (1),
    0x81, 0x02,     //     Input (Data, Variable, Absolute), ;3 button bits
    0x95, 0x01,     //     Report Count (1),
    0x75, 0x05,     //     Report Size (5),
    0x81, 0x01,     //     Input (Constant), ;5 bit padding
    0x05, 0x01,     //     Usage Page (Generic Desktop),
    0x09, 0x30,     //     Usage (X),
    0x09, 0x31,     //     Usage (Y),
    0x15, 0x81,     //     Logical Minimum (-127),
    0x25, 0x7F,     //     Logical Maximum (127),
    0x75, 0x08,     //     Report Size (8),
    0x95, 0x02,     //     Report Count (2),
    0x81, 0x06,     //     Input (Data, Variable, Relative), ;2 position bytes (X & Y)
    0xC0,           //   End Collection,
    0xC0,           // End Collection
/*
    0x05, 0x01,        // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,        // USAGE (Mouse)
    0xa1, 0x01,        // COLLECTION (Application)


@@ 355,7 328,6 @@ PROGMEM uchar mouse_hid_report[] = {
    0xc0,              //     END_COLLECTION
    0xc0,              //   END_COLLECTION
    0xc0               // END_COLLECTION
*/
};