/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/

#include "stc.h"
#include "usb.h"
#include "usb_req_class.h"
#include "pad.h"

#include "timer.h"

BYTE bHidIdle;
BYTE bKeyCode     = 0;
BYTE bKeyDebounce = 0;
BOOL fKeyOK;
BOOL padIdle;

void usb_req_class()
{
    switch (Setup.bRequest) {
        case GET_REPORT:
            usb_get_report();
            break;
        case SET_REPORT:
            usb_set_report();
            break;
        case GET_IDLE:
            usb_get_idle();
            break;
        case SET_IDLE:
            usb_set_idle();
            break;
        case GET_PROTOCOL:
            usb_get_protocol();
            break;
        case SET_PROTOCOL:
            usb_set_protocol();
            break;
        default:
            usb_setup_stall();
            return;
    }
}

void usb_get_report()
{
    if ((DeviceState != DEVSTATE_CONFIGURED) ||
        (Setup.bmRequestType != (IN_DIRECT | CLASS_REQUEST | INTERFACE_RECIPIENT))) {
        usb_setup_stall();
        return;
    }

    Ep0State.pData = UsbBuffer;
    Ep0State.wSize = Setup.wLength;

    usb_setup_in();
}

void usb_set_report()
{
    if ((DeviceState != DEVSTATE_CONFIGURED) ||
        (Setup.bmRequestType != (OUT_DIRECT | CLASS_REQUEST | INTERFACE_RECIPIENT))) {
        usb_setup_stall();
        return;
    }

    Ep0State.pData = UsbBuffer;
    Ep0State.wSize = Setup.wLength;

    usb_setup_out();
}

void usb_get_idle()
{
    if ((DeviceState != DEVSTATE_CONFIGURED) ||
        (Setup.bmRequestType != (IN_DIRECT | CLASS_REQUEST | INTERFACE_RECIPIENT))) {
        usb_setup_stall();
        return;
    }

    Ep0State.pData = &bHidIdle;
    Ep0State.wSize = 1;

    usb_setup_in();
}

void usb_set_idle()
{
    if ((DeviceState != DEVSTATE_CONFIGURED) ||
        (Setup.bmRequestType != (OUT_DIRECT | CLASS_REQUEST | INTERFACE_RECIPIENT))) {
        usb_setup_stall();
        return;
    }

    bHidIdle = Setup.wValueH;

    usb_setup_status();
}

void usb_get_protocol()
{
    usb_setup_stall();
}

void usb_set_protocol()
{
    usb_setup_stall();
}

void usb_class_in()
{

    if (DeviceState != DEVSTATE_CONFIGURED)
        return;

    if (!UsbInBusy && fKeyOK) {

        fKeyOK = 0;

        padIdle = 0;
        switch (bKeyCode) {
            case 0xfe:
                LPadCode |= ADOWN;
                break;
            case 0xfd:
                LPadCode |= BDOWN;
                break;
            case 0xfb:
                LPadCode |= XDOWN;
                break;
            case 0xf7:
                LPadCode |= YDOWN;
                break;
            case 0xef:
                HLXCode = 0x00;
                LLXCode = 0x80;
                break;
            case 0xdf:
                HLXCode = 0xff;
                LLXCode = 0x7f;
                break;
            case 0xbf:
                HLYCode = 0x00;
                LLYCode = 0x80;
                break;
            case 0x7f:
                HLYCode = 0xff;
                LLYCode = 0x7f;
                // IAP_CONTR = 0x60;
                break;
            case 0xff:
                padIdle = 1;
                break;
        }
    }

    if (!UsbInBusy) {

        UsbInBusy = 1;

        IE2 &= ~0x80; // EUSB = 0;
        usb_write_reg(INDEX, 1);

        usb_write_fifo(FIFO1, keyPadData, 20);
        usb_write_reg(INCSR1, INIPRDY);

        IE2 |= 0x80; // EUSB = 1;
    }
}

void scan_key()
{

    BYTE key;

    P0M0 = 0x00;
    P0M1 = 0x00;

    key = 0;
    P0  = 0xff;
    P06 = 0;
    _nop_();
    _nop_();
    key |= P0 & 0x0f;
    P06 = 1;
    P07 = 0;
    _nop_();
    _nop_();
    key |= (P0 & 0x0f) << 4;
    P07 = 1;

    if (key != bKeyCode) {
        bKeyCode     = key;
        bKeyDebounce = 20;
    } else {
        if (bKeyDebounce) {
            bKeyDebounce--;
            if (bKeyDebounce == 0) {
                fKeyOK = 1;
            }
        }
    }
}
