first submission
This commit is contained in:
@@ -0,0 +1,684 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : usbd_composite_km.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/08/20
|
||||
* Description : USB keyboard and mouse processing.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Header Files */
|
||||
#include "usbd_composite_km.h"
|
||||
|
||||
uint8_t USBD_ENDPx_DataUp( uint8_t endp, uint8_t *pbuf, uint16_t len );
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Variable Definition */
|
||||
|
||||
/* Mouse */
|
||||
volatile uint8_t MS_Scan_Done = 0x00; // Mouse Movement Scan Done
|
||||
volatile uint16_t MS_Scan_Result = 0x00F0; // Mouse Movement Scan Result
|
||||
uint8_t MS_Data_Pack[ DEF_ENDP_SIZE_MS ] = { 0x00 }; // Mouse IN Data Packet
|
||||
|
||||
/* Keyboard */
|
||||
volatile uint8_t KB_Scan_Done = 0x00; // Keyboard Keys Scan Done
|
||||
volatile uint16_t KB_Scan_Result = 0xF000; // Keyboard Keys Current Scan Result
|
||||
volatile uint16_t KB_Scan_Last_Result = 0xF000; // Keyboard Keys Last Scan Result
|
||||
uint8_t KB_Data_Pack[ DEF_ENDP_SIZE_KB ] = { 0x00 }; // Keyboard IN Data Packet
|
||||
volatile uint8_t KB_LED_Last_Status = 0x00; // Keyboard LED Last Result
|
||||
volatile uint8_t KB_LED_Cur_Status = 0x00; // Keyboard LED Current Result
|
||||
|
||||
/* USART */
|
||||
volatile uint8_t USART_Recv_Dat = 0x00;
|
||||
volatile uint8_t USART_Send_Flag = 0x00;
|
||||
volatile uint8_t USART_Send_Cnt = 0x00;
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Interrupt Function Declaration */
|
||||
void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
|
||||
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
|
||||
|
||||
/*********************************************************************
|
||||
* @fn TIM3_Init
|
||||
*
|
||||
* @brief Initialize timer3 for keyboard and mouse scan.
|
||||
*
|
||||
* @param arr - The specific period value
|
||||
* psc - The specifies prescaler value
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void TIM3_Init( uint16_t arr, uint16_t psc )
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = { 0 };
|
||||
NVIC_InitTypeDef NVIC_InitStructure = { 0 };
|
||||
|
||||
/* Enable Timer3 Clock */
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );
|
||||
|
||||
/* Initialize Timer3 */
|
||||
TIM_TimeBaseStructure.TIM_Period = arr;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = psc;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure );
|
||||
|
||||
TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE );
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init( &NVIC_InitStructure );
|
||||
|
||||
/* Enable Timer3 */
|
||||
TIM_Cmd( TIM3, ENABLE );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn TIM3_IRQHandler
|
||||
*
|
||||
* @brief This function handles TIM3 global interrupt request.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void TIM3_IRQHandler( void )
|
||||
{
|
||||
if( TIM_GetITStatus( TIM3, TIM_IT_Update ) != RESET )
|
||||
{
|
||||
/* Clear interrupt flag */
|
||||
TIM_ClearITPendingBit( TIM3, TIM_IT_Update );
|
||||
|
||||
/* Handle keyboard scan */
|
||||
KB_Scan( );
|
||||
|
||||
/* Handle mouse scan */
|
||||
MS_Scan( );
|
||||
|
||||
/* Start timing for uploading the key value received from USART2 */
|
||||
if( USART_Send_Flag )
|
||||
{
|
||||
USART_Send_Cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USART2_Init
|
||||
*
|
||||
* @brief Initialize UART2 to receive keyboard data sent through the
|
||||
* PC serial software.
|
||||
*
|
||||
* @param baudrate - Serial baud rate
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USART2_Init( uint32_t baudrate )
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
|
||||
USART_InitTypeDef USART_InitStructure = { 0 };
|
||||
NVIC_InitTypeDef NVIC_InitStructure = { 0 };
|
||||
|
||||
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_Init( GPIOA, &GPIO_InitStructure );
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
GPIO_Init( GPIOA, &GPIO_InitStructure );
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init( &NVIC_InitStructure );
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
|
||||
USART_Init( USART2, &USART_InitStructure );
|
||||
USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );
|
||||
USART_Cmd( USART2, ENABLE );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USART2_IRQHandler
|
||||
*
|
||||
* @brief This function handles USART2 global interrupt request.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USART2_IRQHandler( void )
|
||||
{
|
||||
if( USART_GetITStatus( USART2, USART_IT_RXNE) != RESET )
|
||||
{
|
||||
/* Save the key value received from USART2 */
|
||||
USART_Recv_Dat = USART_ReceiveData( USART2 ) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn USART2_Receive_Handle
|
||||
*
|
||||
* @brief This function handles the key value received from USART2.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void USART2_Receive_Handle( void )
|
||||
{
|
||||
uint8_t status;
|
||||
static uint8_t flag = 0x00;
|
||||
|
||||
if( flag == 0 )
|
||||
{
|
||||
/* Store the received specified key value into the keyboard data buffer */
|
||||
if( ( USART_Recv_Dat == DEF_KEY_CHAR_A ) ||
|
||||
( USART_Recv_Dat == DEF_KEY_CHAR_W ) ||
|
||||
( USART_Recv_Dat == DEF_KEY_CHAR_S ) ||
|
||||
( USART_Recv_Dat == DEF_KEY_CHAR_D ) )
|
||||
{
|
||||
memset( KB_Data_Pack, 0x00, DEF_ENDP_SIZE_KB );
|
||||
KB_Data_Pack[ 2 ] = USART_Recv_Dat;
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
else if( flag == 1 )
|
||||
{
|
||||
/* Load keyboard data to endpoint 1 */
|
||||
status = USBD_ENDPx_DataUp(ENDP1, KB_Data_Pack, DEF_ENDP_SIZE_KB);
|
||||
|
||||
if( status == USB_SUCCESS )
|
||||
{
|
||||
/* Enable timing for uploading the key value */
|
||||
USART_Send_Cnt = 0;
|
||||
USART_Send_Flag = 1;
|
||||
flag = 2;
|
||||
}
|
||||
}
|
||||
else if( flag == 2 )
|
||||
{
|
||||
/* Delay 10ms to ensure that the key value is successfully uploaded,
|
||||
* and prepare the data packet indicating the key release.
|
||||
*/
|
||||
if( USART_Send_Cnt >= 50 )
|
||||
{
|
||||
USART_Send_Flag = 0;
|
||||
memset( KB_Data_Pack, 0x00, DEF_ENDP_SIZE_KB );
|
||||
flag = 3;
|
||||
}
|
||||
}
|
||||
else if( flag == 3 )
|
||||
{
|
||||
/* Load keyboard data to endpoint 1 */
|
||||
status = USBD_ENDPx_DataUp(ENDP1, KB_Data_Pack, DEF_ENDP_SIZE_KB);
|
||||
/* Clear variables for next reception */
|
||||
if( status == USB_SUCCESS )
|
||||
{
|
||||
USART_Recv_Dat = 0;
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn KB_Scan_Init
|
||||
*
|
||||
* @brief Initialize IO for keyboard scan.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void KB_Scan_Init( void )
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
|
||||
|
||||
/* Enable GPIOB clock */
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
|
||||
|
||||
/* Initialize GPIOB (Pin4-Pin7) for the keyboard scan */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init( GPIOB, &GPIO_InitStructure );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn KB_Sleep_Wakeup_Cfg
|
||||
*
|
||||
* @brief Configure keyboard wake up mode.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void KB_Sleep_Wakeup_Cfg( void )
|
||||
{
|
||||
EXTI_InitTypeDef EXTI_InitStructure = { 0 };
|
||||
|
||||
/* Enable GPIOB clock */
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB, GPIO_PinSource12 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line12;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB, GPIO_PinSource13 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line13;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB, GPIO_PinSource14 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line14;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB, GPIO_PinSource15 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line15;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
EXTI->INTENR |= EXTI_INTENR_MR12 | EXTI_INTENR_MR13 | EXTI_INTENR_MR14 | EXTI_INTENR_MR15;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn KB_Scan
|
||||
*
|
||||
* @brief Perform keyboard scan.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void KB_Scan( void )
|
||||
{
|
||||
static uint16_t scan_cnt = 0;
|
||||
static uint16_t scan_result = 0;
|
||||
|
||||
scan_cnt++;
|
||||
if( ( scan_cnt % 10 ) == 0 )
|
||||
{
|
||||
scan_cnt = 0;
|
||||
|
||||
/* Determine whether the two scan results are consistent */
|
||||
if( scan_result == ( GPIO_ReadInputData( GPIOB ) & 0xF000 ) )
|
||||
{
|
||||
KB_Scan_Done = 1;
|
||||
KB_Scan_Result = scan_result;
|
||||
}
|
||||
}
|
||||
else if( ( scan_cnt % 5 ) == 0 )
|
||||
{
|
||||
/* Save the first scan result */
|
||||
scan_result = ( GPIO_ReadInputData( GPIOB ) & 0xF000 );
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn KB_Scan_Handle
|
||||
*
|
||||
* @brief Handle keyboard scan data.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void KB_Scan_Handle( void )
|
||||
{
|
||||
uint8_t i, j;
|
||||
uint8_t status;
|
||||
static uint8_t key_cnt = 0x00;
|
||||
static uint8_t flag = 0x00;
|
||||
if( KB_Scan_Done )
|
||||
{
|
||||
KB_Scan_Done = 0;
|
||||
|
||||
if( KB_Scan_Result != KB_Scan_Last_Result )
|
||||
{
|
||||
for( i = 12; i < 16; i++ )
|
||||
{
|
||||
/* Determine that there is at least one key is pressed or released */
|
||||
if( ( KB_Scan_Result & ( 1 << i ) ) != ( KB_Scan_Last_Result & ( 1 << i ) ) )
|
||||
{
|
||||
if( ( KB_Scan_Result & ( 1 << i ) ) ) // Key press
|
||||
{
|
||||
if( i == 12 )
|
||||
{
|
||||
for( j = 2; j < 8; j++ )
|
||||
{
|
||||
if( KB_Data_Pack[ j ] == DEF_KEY_CHAR_W )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( i == 13 )
|
||||
{
|
||||
for( j = 2; j < 8; j++ )
|
||||
{
|
||||
if( KB_Data_Pack[ j ] == DEF_KEY_CHAR_A )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( i == 14 )
|
||||
{
|
||||
for( j = 2; j < 8; j++ )
|
||||
{
|
||||
if( KB_Data_Pack[ j ] == DEF_KEY_CHAR_S )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( i == 15 )
|
||||
{
|
||||
for( j = 2; j < 8; j++ )
|
||||
{
|
||||
if( KB_Data_Pack[ j ] == DEF_KEY_CHAR_D )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( j == 8 )
|
||||
{
|
||||
KB_Data_Pack[ 5 ] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( &KB_Data_Pack[ j ], &KB_Data_Pack[ j + 1 ], ( 8 - j - 1 ) );
|
||||
KB_Data_Pack[ 7 ] = 0;
|
||||
}
|
||||
key_cnt--;
|
||||
}
|
||||
else // Key release
|
||||
{
|
||||
if( i == 12 )
|
||||
{
|
||||
KB_Data_Pack[ 2 + key_cnt ] = DEF_KEY_CHAR_W;
|
||||
}
|
||||
else if( i == 13 )
|
||||
{
|
||||
KB_Data_Pack[ 2 + key_cnt ] = DEF_KEY_CHAR_A;
|
||||
}
|
||||
else if( i == 14 )
|
||||
{
|
||||
KB_Data_Pack[ 2 + key_cnt ] = DEF_KEY_CHAR_S;
|
||||
}
|
||||
else if( i == 15 )
|
||||
{
|
||||
KB_Data_Pack[ 2 + key_cnt ] = DEF_KEY_CHAR_D;
|
||||
}
|
||||
key_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the keyboard data to the buffer of endpoint 1 and set the data uploading flag */
|
||||
KB_Scan_Last_Result = KB_Scan_Result;
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( flag )
|
||||
{
|
||||
/* Load keyboard data to endpoint 1 */
|
||||
status = USBD_ENDPx_DataUp(ENDP1, KB_Data_Pack, DEF_ENDP_SIZE_KB);
|
||||
if( status == USB_SUCCESS )
|
||||
{
|
||||
/* Clear flag after successful loading */
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* @fn KB_LED_Handle
|
||||
*
|
||||
* @brief Handle keyboard lighting.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void KB_LED_Handle( void )
|
||||
{
|
||||
if( KB_LED_Cur_Status != KB_LED_Last_Status )
|
||||
{
|
||||
if( ( KB_LED_Cur_Status & 0x01 ) != ( KB_LED_Last_Status & 0x01 ) )
|
||||
{
|
||||
if( KB_LED_Cur_Status & 0x01 )
|
||||
{
|
||||
printf("Turn on the NUM LED\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Turn off the NUM LED\r\n");
|
||||
}
|
||||
}
|
||||
if( ( KB_LED_Cur_Status & 0x02 ) != ( KB_LED_Last_Status & 0x02 ) )
|
||||
{
|
||||
if( KB_LED_Cur_Status & 0x02 )
|
||||
{
|
||||
printf("Turn on the CAPS LED\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Turn off the CAPS LED\r\n");
|
||||
}
|
||||
}
|
||||
if( ( KB_LED_Cur_Status & 0x04 ) != ( KB_LED_Last_Status & 0x04 ) )
|
||||
{
|
||||
if( KB_LED_Cur_Status & 0x04 )
|
||||
{
|
||||
printf("Turn on the SCROLL LED\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Turn off the SCROLL LED\r\n");
|
||||
}
|
||||
}
|
||||
KB_LED_Last_Status = KB_LED_Cur_Status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* @fn MS_Scan_Init
|
||||
*
|
||||
* @brief Initialize IO for mouse scan.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void MS_Scan_Init( void )
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
|
||||
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init( GPIOA, &GPIO_InitStructure );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn MS_Sleep_Wakeup_Cfg
|
||||
*
|
||||
* @brief Configure mouse wake up mode.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void MS_Sleep_Wakeup_Cfg( void )
|
||||
{
|
||||
EXTI_InitTypeDef EXTI_InitStructure = { 0 };
|
||||
|
||||
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOA, GPIO_PinSource4 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line4;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOA, GPIO_PinSource5 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOA, GPIO_PinSource6 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line6;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
GPIO_EXTILineConfig( GPIO_PortSourceGPIOA, GPIO_PinSource7 );
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line7;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init( &EXTI_InitStructure );
|
||||
|
||||
EXTI->INTENR |= EXTI_INTENR_MR4 | EXTI_INTENR_MR5 | EXTI_INTENR_MR6 | EXTI_INTENR_MR7;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn MS_Scan
|
||||
*
|
||||
* @brief Perform mouse scan.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void MS_Scan( void )
|
||||
{
|
||||
static uint16_t scan_cnt = 0;
|
||||
static uint16_t scan_result = 0;
|
||||
|
||||
scan_cnt++;
|
||||
if( scan_cnt >= 2 )
|
||||
{
|
||||
scan_cnt = 0;
|
||||
|
||||
/* Determine whether the two scan results are consistent */
|
||||
if( scan_result == ( GPIO_ReadInputData( GPIOA ) & 0x00F0 ) )
|
||||
{
|
||||
MS_Scan_Result = scan_result;
|
||||
MS_Scan_Done = 1;
|
||||
}
|
||||
}
|
||||
else if( scan_cnt >= 1 )
|
||||
{
|
||||
/* Save the first scan result */
|
||||
scan_result = ( GPIO_ReadInputData( GPIOA ) & 0x00F0 );
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn MS_Scan_Handle
|
||||
*
|
||||
* @brief Handle mouse scan data.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void MS_Scan_Handle( void )
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t status;
|
||||
static uint8_t flag = 0x00;
|
||||
|
||||
if( MS_Scan_Done )
|
||||
{
|
||||
MS_Scan_Done = 0;
|
||||
|
||||
memset( MS_Data_Pack, 0x00, DEF_ENDP_SIZE_MS );
|
||||
|
||||
for( i = 4; i < 8; i++ )
|
||||
{
|
||||
/* Determine that the mouse is moved */
|
||||
if( ( MS_Scan_Result & ( 1 << i ) ) == 0 )
|
||||
{
|
||||
if( i == 4 )
|
||||
{
|
||||
MS_Data_Pack[ 1 ] += 0x02;
|
||||
}
|
||||
else if( i == 5 )
|
||||
{
|
||||
MS_Data_Pack[ 1 ] += 0xFE;
|
||||
}
|
||||
else if( i == 6 )
|
||||
{
|
||||
MS_Data_Pack[ 2 ] += 0x02;
|
||||
}
|
||||
else if( i == 7 )
|
||||
{
|
||||
MS_Data_Pack[ 2 ] += 0xFE;
|
||||
}
|
||||
|
||||
/* Set the data uploading flag */
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( flag )
|
||||
{
|
||||
/* Load mouse data to endpoint 2 */
|
||||
status = USBD_ENDPx_DataUp(ENDP2, MS_Data_Pack, DEF_ENDP_SIZE_MS);
|
||||
if( status == USB_SUCCESS )
|
||||
{
|
||||
/* Clear flag after successful loading */
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn MCU_Sleep_Wakeup_Operate
|
||||
*
|
||||
* @brief Perform sleep operation
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void MCU_Sleep_Wakeup_Operate( void )
|
||||
{
|
||||
EXTI_ClearFlag( EXTI_Line12 | EXTI_Line13 | EXTI_Line14 | EXTI_Line15 );
|
||||
EXTI_ClearFlag( EXTI_Line4 | EXTI_Line5 | EXTI_Line6 | EXTI_Line7 );
|
||||
|
||||
// printf( "Sleep\r\n" );
|
||||
__WFE( );
|
||||
|
||||
if( EXTI_GetFlagStatus( EXTI_Line12 | EXTI_Line13 | EXTI_Line14 | EXTI_Line15 ) != RESET )
|
||||
{
|
||||
EXTI_ClearFlag( EXTI_Line12 | EXTI_Line13 | EXTI_Line14 | EXTI_Line15 );
|
||||
Resume(RESUME_INTERNAL);
|
||||
}
|
||||
else if( EXTI_GetFlagStatus( EXTI_Line4 | EXTI_Line5 | EXTI_Line6 | EXTI_Line7 ) != RESET )
|
||||
{
|
||||
EXTI_ClearFlag( EXTI_Line4 | EXTI_Line5 | EXTI_Line6 | EXTI_Line7 );
|
||||
Resume(RESUME_INTERNAL);
|
||||
}
|
||||
// printf( "Wake\r\n" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user