



/**
 ******************************************************************************
 *
 * @file        MG32_Mouse_API.c
 * @brief       Mouse API C code.
 
 * @par         Project
 *              Mouse
 * @version     V1.01
 * @date        2025/06/11
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 * 
 ******************************************************************************* 
 * @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */
 
 
 
/* Includes ------------------------------------------------------------------*/
#include "MG32_Mouse_API.h"
#include "MG32_USBD_API.h"
#include "MG32_Button_API.h"
#include "MG32_Wheel_API.h"
/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
MouseCTR_TypeDef Mouse_CTR;


/* Private function prototypes -----------------------------------------------*/
void MOUSE_BTN_IRQHandler(void);
void MOUSE_WHEEL_IRQHandler(void);

static void API_Mouse_GPIOIT_Init(void);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/

/**
 *******************************************************************************
 * @brief	  Buttoon interrupt handler 
 * @details     
 * @return      
 * @exception No  
 * @note
 *******************************************************************************
 */
void MOUSE_BTN_IRQHandler(void)
{
    API_Mouse_WakeupIT_Cmd(DISABLE);
    
    Ep0.USBStatus = Ep0.USBStatus | USB_STATUS_BUS_EXTIEVENT_WAKEUP;
    
}
/**
 *******************************************************************************
 * @brief	   Wheel interrupt handler 
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void MOUSE_WHEEL_IRQHandler(void)
{
    API_Mouse_WakeupIT_Cmd(DISABLE);

    Ep0.USBStatus = Ep0.USBStatus | USB_STATUS_BUS_EXTIEVENT_WAKEUP;

}
/**
 *******************************************************************************
 * @brief	   GPIN intterupt enable or disable   
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_WakeupIT_Cmd( FunctionalState Mouse_Wakeup_Cmd) 
{
    uint8_t API_Mouse_WakeupIT_CmdTmp;
    
    
    EXIC_ClearPxTriggerEventFlag( MOUSE_BTN_EXIC_MODE_PORT,
                                 (MOUSE_BTN_L_EXIC_MASK  | MOUSE_BTN_R_EXIC_MASK | MOUSE_BTN_M_EXIC_MASK |
                                  MOUSE_BTN_BW_EXIC_MASK | MOUSE_BTN_FW_EXIC_MASK));
    
    EXIC_ClearPxTriggerEventFlag( MOUSE_WHEEL_EXIC_MODE_PORT,
                                  (MOUSE_WHEEL_ZA_EXIC_MASK|MOUSE_WHEEL_ZB_EXIC_MASK));
    
    /*Enable button interrupt*/
    if( Mouse_Wakeup_Cmd == ENABLE)
    {
        API_Mouse_WakeupIT_CmdTmp = API_Wheel_GetStatus();
        
        /*Interrupt trigger is level when MCU into STOP mode (becase MCU no clock) */
        /* H level trigger*/
        if( API_Mouse_WakeupIT_CmdTmp == 0)
        {
            GPIO_PinInverse_Cmd(WHEEL_ZA_IOM_PIN,ENABLE);
            GPIO_PinInverse_Cmd(WHEEL_ZB_IOM_PIN,ENABLE);
        }
        /* L level trigger*/
        else
        {
            GPIO_PinInverse_Cmd(WHEEL_ZA_IOM_PIN,DISABLE);
            GPIO_PinInverse_Cmd(WHEEL_ZB_IOM_PIN,DISABLE);
        }
        EXIC_PxTriggerITEA_Cmd(   MOUSE_BTN_EXIC_IT, ENABLE);
        EXIC_PxTriggerITEA_Cmd( MOUSE_WHEEL_EXIC_IT, ENABLE);
    }
    /*Disable button interrupt*/
    else
    {
        EXIC_PxTriggerITEA_Cmd(   MOUSE_BTN_EXIC_IT, DISABLE);
        EXIC_PxTriggerITEA_Cmd( MOUSE_WHEEL_EXIC_IT, DISABLE);     
    }
}
/**
 *******************************************************************************
 * @brief	   Mouse paramter initial.  
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_Parameter_DeInit(void)
{
    uint8_t API_Mouse_Parameter_DeInitTmp;
    
    Mouse_CTR.IdleRate            = 0;
    Mouse_CTR.Protocol            = 1;
    
    Mouse_CTR.ReportDataTmp.Button.B = 0;
    Mouse_CTR.ReportDataTmp.X_Axis.H = 0;
    Mouse_CTR.ReportDataTmp.Y_Axis.H = 0;
    Mouse_CTR.ReportDataTmp.Wheel    = 0;
    for( API_Mouse_Parameter_DeInitTmp = 0; API_Mouse_Parameter_DeInitTmp < Mosue_ReportSize;API_Mouse_Parameter_DeInitTmp++)
    {
        Mouse_CTR.ReportData[API_Mouse_Parameter_DeInitTmp] = 0;
    }

    Mouse_CTR.BaseCount           = 0;
}
/**
 *******************************************************************************
 * @brief	   Mouse initial. 
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_Init(void)
{
    /*Mouse status */
    Mouse_CTR.Status = Mouse_Status_Init;
    
    /*Button initial*/
    API_Button_Init();
    
    /*Wheel initial*/
    API_Wheel_Init();
    
    /*GPIO interrupt initial*/
    API_Mouse_GPIOIT_Init();

    /*USB initial*/
    API_USBD_Init(); 
    
    /*Parameter initial*/
    API_Mouse_Parameter_DeInit();
    

    /*Time base initial (systick)*/
    InitTick(24000000UL/4,0);               // 250us
    
    /*Mouse status */
    Mouse_CTR.Status = Mouse_Status_Idle;
    
}
/**
 *******************************************************************************
 * @brief	   Button detect status and handler  
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_ButtonHandler(void)
{
    /*Detect button status.*/
    API_Button_GetStatus();
    
    /*Judge button whether change or not.*/
    if( BTN_CTR.Button_ChangeFlag == 0)
    {
        return;
    }
    BTN_CTR.Button_ChangeFlag = 0;
    /*Normal Function*/
    Mouse_CTR.ReportDataTmp.Button.MBIT.L_Button  = BTN_CTR.ButtonStatus[BTN_L_Data];
    Mouse_CTR.ReportDataTmp.Button.MBIT.R_Button  = BTN_CTR.ButtonStatus[BTN_R_Data];
    Mouse_CTR.ReportDataTmp.Button.MBIT.M_Button  = BTN_CTR.ButtonStatus[BTN_M_Data];
    Mouse_CTR.ReportDataTmp.Button.MBIT.BW_Button = BTN_CTR.ButtonStatus[BTN_BW_Data];
    Mouse_CTR.ReportDataTmp.Button.MBIT.FW_Button = BTN_CTR.ButtonStatus[BTN_FW_Data];
    
    Mouse_CTR.Status |= Mouse_Status_BNTReportChange;
}
/**
 *******************************************************************************
 * @brief	   Wheel status handler  
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_WheelHandler(void)
{
    /*Judge wheel status whether change or not.*/
    if( Wheel_CTR.Wheel_ChangeFlag == 0)
    {
        return;
    }
    Wheel_CTR.Wheel_ChangeFlag = 0;
    /*Wheel function*/
    Mouse_CTR.ReportDataTmp.Wheel = Wheel_CTR.Wheel_Data;
    Wheel_CTR.Wheel_Data          = 0;
    
    Mouse_CTR.Status |= Mouse_Status_WheelReportChange;
}
/**
 *******************************************************************************
 * @brief	   Sensor status handler  
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_SensorHandler(void)
{

    /*
    The sample code no include to read sensor.
    
    */
    
    /* If sensor data change
    
    Mouse_CTR.ReportDataTmp.X_Axis.H = Sensor X axis data;
    Mouse_CTR.ReportDataTmp.Y_Axis.H = Sensor Y axis data;
    
    or
    
    Mouse_CTR.ReportDataTmp.X_Axis.B[0] =  Low byte of sensor X axis data
    Mouse_CTR.ReportDataTmp.X_Axis.B[1] = High btye of sensor X axis data
    Mouse_CTR.ReportDataTmp.Y_Axis.B[0] =  Low byte of sensor X axis data
    Mouse_CTR.ReportDataTmp.Y_Axis.B[1] = High byte of sensor X axis data
    
    
    Mouse_CTR.Status |= Mouse_Status_SensorReportChange;
    
    */
}
/**
 *******************************************************************************
 * @brief	   Mouse report handler  
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_ReportHandler(void)
{
    int16_t API_Mouse_ReportHandlerTmp;
    
    /*Judge Mouse report whether change or not.*/
    if( (Mouse_CTR.Status & Mouse_Status_ReportChange)==0)
    {
        return;
    }
 
    if((Ep0.USBStatus & USB_STATUS_EMULATION_MASK)==USB_STATUS_EMULATION_OK)
    {
        Mouse_CTR.Status  = Mouse_Status_UpdateReport;
        
        if(Mouse_CTR.Protocol == 1)
        {
            Mouse_CTR.ReportData[Mouse_Report_Button] = Mouse_CTR.ReportDataTmp.Button.B;
            Mouse_CTR.ReportData[Mouse_Report_X_L]    = Mouse_CTR.ReportDataTmp.X_Axis.B[0];
            Mouse_CTR.ReportData[Mouse_Report_X_H]    = Mouse_CTR.ReportDataTmp.X_Axis.B[1];
            Mouse_CTR.ReportData[Mouse_Report_Y_L]    = Mouse_CTR.ReportDataTmp.Y_Axis.B[0];
            Mouse_CTR.ReportData[Mouse_Report_Y_H]    = Mouse_CTR.ReportDataTmp.Y_Axis.B[1];
            Mouse_CTR.ReportData[Mouse_Report_Wheel]  = (uint8_t)Mouse_CTR.ReportDataTmp.Wheel; 
            
            
            USB_SetEndpointTXData( Mouse_EPn , &Mouse_CTR.ReportData[0], Mosue_ReportSize);
        }
        else
        {
            Mouse_CTR.ReportData[Mouse_BIOS_Report_Button] = Mouse_CTR.ReportDataTmp.Button.B;
            
            API_Mouse_ReportHandlerTmp = (int16_t)Mouse_CTR.ReportDataTmp.X_Axis.H;
            
            if( API_Mouse_ReportHandlerTmp > 127)
            {
                Mouse_CTR.ReportData[Mouse_BIOS_Report_X] = 0x7F;
            }
            else if( API_Mouse_ReportHandlerTmp < -127)
            {
                Mouse_CTR.ReportData[Mouse_BIOS_Report_X] = 0x81;
            }
            else
            {
                Mouse_CTR.ReportData[Mouse_BIOS_Report_X] = Mouse_CTR.ReportDataTmp.X_Axis.B[0];
            }
            
            API_Mouse_ReportHandlerTmp = (int16_t)Mouse_CTR.ReportDataTmp.Y_Axis.H;
            
            if( API_Mouse_ReportHandlerTmp > 127)
            {
                Mouse_CTR.ReportData[Mouse_BIOS_Report_Y] = 0x7F;
            }
            else if( API_Mouse_ReportHandlerTmp < -127)
            {
                Mouse_CTR.ReportData[Mouse_BIOS_Report_Y] = 0x81;
            }
            else
            {
                Mouse_CTR.ReportData[Mouse_BIOS_Report_Y] = Mouse_CTR.ReportDataTmp.Y_Axis.B[0];
            }
            
            USB_SetEndpointTXData( Mouse_EPn , &Mouse_CTR.ReportData[0], Mouse_BIOS_ReportSize);
        }
        Mouse_CTR.ReportDataTmp.Wheel             = 0;
    }
}
/**
 *******************************************************************************
 * @brief	   USB state handler.  
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_USBHandler(void)
{
    uint32_t API_Mouse_USBHandlerTmp;
    
    API_Mouse_USBHandlerTmp = ( Ep0.USBStatus & USB_STATUS_BUS_MASK);
    
    
    /*USB Flow function*/
    if(API_Mouse_USBHandlerTmp!=0)
    {
        switch( API_Mouse_USBHandlerTmp)
        {
            //============================================================================================
            // During handling the ohter functions USB bus happen suspend status. 
            case USB_STATUS_BUS_SUSPEND:
                                                                          Ep0.USBStatus = Ep0.USBStatus & ((uint32_t)(~USB_STATUS_BUS_SUSPEND));
                                                                          //-------------------------------------------------------------------------
                                                                          //If host allow remote wakeup enable the other external wakeup signal.
                                                                          if(( Ep0.USBStatus & USB_STATUS_RWEN_MASK) == USB_STATUS_RWEN_ENABLE)
                                                                          {
                                                                              API_Mouse_WakeupIT_Cmd(ENABLE);
                                                                              
                                                                              //To do......
                                                                          }
                                                                          
                                                                          USB_IT_Config( USB_IT_BUS_RWKF , ENABLE);               /*!< Enable USB Bus event wakeup interrupt in STOP mode.*/ 
                                                                          
                                                                          STOP_WFI();
                                                                          
                                                                          API_Mouse_Parameter_DeInit();
                                                                          break;
            //============================================================================================
            //Detect USB Bus no supsend in STOP mode.            
            case USB_STATUS_BUS_BUSEVENT_WAKEUP:
                                                                          Ep0.USBStatus = Ep0.USBStatus & ((uint32_t)(~USB_STATUS_BUS_BUSEVENT_WAKEUP));
                                                                          
                                                                          // To do......
                                                                          break;
            //============================================================================================
            //During handling the other functions extern wakeup signal happen.
            case USB_STATUS_BUS_EXTIEVENT_WAKEUP:
                                                                          Ep0.USBStatus = Ep0.USBStatus & ((uint32_t)(~USB_STATUS_BUS_EXTIEVENT_WAKEUP));
                                                                          //-------------------------------------------------------------------------
                                                                          //If host allow remote wakeup send remote wakeup signal to host.
                                                                          USB_TriggerRemoteWakeup();
                                                                          
                                                                          
                                                                          break;                                                       
            //============================================================================================
            //During handling the ohter functions USB bus happen suspend and resume status.
            case ( USB_STATUS_BUS_SUSPEND | USB_STATUS_BUS_RESUME):
                                                                          Ep0.USBStatus = Ep0.USBStatus & ((uint32_t)(~USB_STATUS_BUS_SUSPEND)); 
                                                                          
                                                                          break;
            //============================================================================================
            //During handling the ohter function USB bus happen resume status.
            case (USB_STATUS_BUS_BUSEVENT_WAKEUP | USB_STATUS_BUS_RESUME):
            case (USB_STATUS_BUS_RESUME):
                                                                          Ep0.USBStatus = Ep0.USBStatus & ((uint32_t)(~(USB_STATUS_BUS_BUSEVENT_WAKEUP | USB_STATUS_BUS_RESUME)));

                                                                          break;
            
            //============================================================================================
            case (USB_STATUS_BUS_BUSEVENT_WAKEUP | USB_STATUS_BUS_RESET):
            case USB_STATUS_BUS_RESET:
                                                                          Ep0.USBStatus = Ep0.USBStatus & ((uint32_t)(~(USB_STATUS_BUS_BUSEVENT_WAKEUP | USB_STATUS_BUS_RESET)));
                                                                          // To do...
                                                                          
                                                                          break;
            default:                                                      
                                                                          // To do...
                                                                          
                                                                          break;
        }
        
        Ep0.USBStatus = Ep0.USBStatus & (~API_Mouse_USBHandlerTmp);
    }
    
}
/**
 *******************************************************************************
 * @brief	   Mouse flow handler.  
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
void API_Mouse_Handler(void)
{
    /*USB flow*/
    API_Mouse_USBHandler();

}
/**
 *******************************************************************************
 * @brief	   GPIN intterupt enable or disable   
 * @details     
 * @return      
 * @exception  No 
 * @note
 *******************************************************************************
 */
static void API_Mouse_GPIOIT_Init(void)
{
    EXIC_TRGSTypeDef EXIC_TRGS;
    
    /*Set GPIO interrupt trigger mode for Button (falling edge)*/
    EXIC_TRGS.EXIC_TRGS_Mode = Edge;
    EXIC_TRGS.EXIC_Pin       = ( MOUSE_BTN_L_EXIC_MODE_PIN  |
                                 MOUSE_BTN_R_EXIC_MODE_PIN  |
                                 MOUSE_BTN_M_EXIC_MODE_PIN  |
                                 MOUSE_BTN_BW_EXIC_MODE_PIN |
                                 MOUSE_BTN_FW_EXIC_MODE_PIN );
    EXIC_PxTriggerMode_Select(MOUSE_BTN_EXIC_MODE_PORT,&EXIC_TRGS);
    
    EXIC_PxTriggerOrMask_Select( MOUSE_BTN_EXIC_MODE_PORT,
                                (MOUSE_BTN_L_EXIC_MASK  | MOUSE_BTN_R_EXIC_MASK | MOUSE_BTN_M_EXIC_MASK |
                                 MOUSE_BTN_BW_EXIC_MASK | MOUSE_BTN_FW_EXIC_MASK));
    
    
    /*Set GPIO interrupt trigger mode for Wheel (falling edge)*/
    EXIC_TRGS.EXIC_Pin       = ( MOUSE_WHEEL_ZA_EXIC_MODE_PIN  |
                                 MOUSE_WHEEL_ZB_EXIC_MODE_PIN );
    
    EXIC_PxTriggerMode_Select(MOUSE_WHEEL_EXIC_MODE_PORT,&EXIC_TRGS);

    EXIC_PxTriggerOrMask_Select( MOUSE_WHEEL_EXIC_MODE_PORT,
                                (MOUSE_WHEEL_ZA_EXIC_MASK|MOUSE_WHEEL_ZB_EXIC_MASK));
                                     
    /*Wheel & Button GPIO interrupt handle*/
    EXIC_PxTriggerITEA_Cmd(   MOUSE_BTN_EXIC_IT, DISABLE);
    EXIC_PxTriggerITEA_Cmd( MOUSE_WHEEL_EXIC_IT, DISABLE);
    
    NVIC_EnableIRQ(EXINT1_IRQn);
    NVIC_EnableIRQ(EXINT2_IRQn);
}









