/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=895143]@version[/url] V2.00
* $Revision: 12 $
* $Date: 15/07/02 11:18a $
* [url=home.php?mod=space&uid=247401]@brief[/url] Demonstrate how to control PS/2 mouse movement on the screen.
* @note
* Copyright (C) 2014~2015 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "NUC123.h"
#define PLLCON_SETTING CLK_PLLCON_72MHz_HXT
#define PLL_CLOCK 72000000
#define DEVICE_ID 0x00
#define PS2CMD_RESET 0xFF
#define PS2CMD_RESEND 0xFE
#define PS2CMD_SET_DEFAULTS 0xF6
#define PS2CMD_DISABLE_DATA_REPORT 0xF5
#define PS2CMD_ENABLE_DATA_REPORT 0xF4
#define PS2CMD_SET_SAMPLE_RATE 0xF3
#define PS2CMD_GET_DEVICE_ID 0xF2
#define PS2CMD_SET_REMOTE_MODE 0xF0
#define PS2CMD_SET_WARP_MODE 0xEE
#define PS2CMD_RESET_WARP_MODE 0xEC
#define PS2CMD_READ_DATA 0xEB
#define PS2CMD_SET_STREAM_MODE 0xEA
#define PS2CMD_STATUS_REQUEST 0xE9
#define PS2CMD_SET_RESOLUTION 0xE8
#define PS2CMD_SET_SCALLING2 0xE7
#define PS2CMD_SET_SCALLING1 0xE6
#define PS2MOD_RESET 0x0
#define PS2MOD_STREAM 0x1
#define PS2MOD_REMOTE 0x2
#define PS2MOD_WARP 0x3
void SYS_Init(void);
void UART0_Init(void);
void PS2_Init(void);
uint8_t g_CMD_RESET = 0;
uint8_t g_opMode = PS2MOD_RESET;
uint8_t g_sampleRate = 0;
uint8_t g_resolution = 0;
uint8_t g_scalling = 0;
uint8_t g_dataReportEnable = 0;
uint32_t g_mouseData = 0;
uint8_t g_cmd[2] = {0};
uint32_t u32PS2ACK = 0xFA;
uint32_t u32PS2PASS = 0xAA;
uint32_t u32TxData;
uint32_t g_cnt = 0;
void SysTick_Handler(void)
{
if(g_opMode == PS2MOD_STREAM && g_dataReportEnable)
{
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
/* Calculate cursor moving data */
g_cnt++;
if(g_cnt < 101)
g_mouseData = (0x0 << 16) | (0x01 << 8) | 0x08; // move right */
else if(g_cnt < 201)
g_mouseData = (0xFF << 16) | (0x00 << 8) | 0x28; // move down */
else if(g_cnt < 301)
g_mouseData = (0x0 << 16) | (0xFF << 8) | 0x18; // move left */
else if(g_cnt < 401)
g_mouseData = (0x1 << 16) | (0x00 << 8) | 0x08; // move up */
else if(g_cnt > 401)
g_cnt = 1;
/* Transmit data*/
PS2_Write(&g_mouseData, 3);
if((g_cnt & 0x0F) == 0)
printf("Device->Host: Data report 0x%06x\n", g_mouseData);
}
}
}
void PS2_IRQHandler(void)
{
uint32_t u32RxData;
/* RXINT */
if(PS2_GET_INT_FLAG(PS2_PS2INTID_RXINT_Msk))
{
/* Clear PS2 Receive Interrupt flag */
PS2_CLR_RX_INT_FLAG();
/* Get Receive Data */
u32RxData = PS2_Read();
printf("\n u32RxData = 0x%x \n", u32RxData);
if(g_cmd[0])
{
/* If g_cmd[0] is not 0, it should be in data phase */
if(g_cmd[0] == PS2CMD_SET_SAMPLE_RATE)
{
printf("Host->Device: Set sample rate data %d\n", u32RxData);
if(u32RxData < 10) u32RxData = 10;
if(u32RxData > 200) u32RxData = 200;
g_sampleRate = u32RxData;
g_cmd[0] = 0;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
printf("Device->Host: ACK\n");
PS2_Write(&u32PS2ACK, 1);
}
else
{
printf("Something wrong!! Stop code!\n");
PS2_SET_CLK_LOW();
PS2_SET_DATA_HIGH();
PS2_ENABLE_OVERRIDE();
while(1);
}
}
else if(g_cmd[0] == PS2CMD_SET_RESOLUTION)
{
printf("Host->Device: Set resolution data %d\n", u32RxData);
if(u32RxData < 1) u32RxData = 1;
if(u32RxData > 3) u32RxData = 3;
g_resolution = (1 << u32RxData);
g_cmd[0] = 0;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
PS2_Write(&u32PS2ACK, 1);
printf("Device->Host: ACK\n");
}
else
{
printf("Something Wrong!! Stop code!\n");
PS2_SET_CLK_LOW();
PS2_SET_DATA_HIGH();
PS2_ENABLE_OVERRIDE();
while(1);
}
}
}
else
{
/* Only support PS2CMD_DISABLE_DATA_REPORT command when data report enabled */
if((u32RxData == PS2CMD_RESET) || (u32RxData == PS2CMD_DISABLE_DATA_REPORT) || (g_dataReportEnable == 0))
{
/* Process the command phase */
if(u32RxData == PS2CMD_RESET)
{
printf("Host->Device: Reset\n");
/* Reset command */
g_opMode = PS2MOD_RESET;
g_cmd[0] = 0;
/* Clear FIFO */
PS2_CLEAR_TX_FIFO();
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
u32TxData = u32PS2ACK;
PS2_Write(&u32TxData, 1);
printf("Device->Host: ACK\n");
g_CMD_RESET = 1;
}
}
else if(u32RxData == PS2CMD_SET_SAMPLE_RATE)
{
printf("Host->Device: Set sample rate\n");
/* Set sample rate */
g_cmd[0] = PS2CMD_SET_SAMPLE_RATE;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
PS2_Write(&u32PS2ACK, 1);
printf("Device->Host: ACK\n");
}
}
else if(u32RxData == PS2CMD_GET_DEVICE_ID)
{
printf("Host->Device: Get device ID\n");
g_cmd[0] = 0;
printf("(PS2->STATUS).TXEMPTY is (%0x)\n", ((PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk) >> PS2_PS2STATUS_TXEMPTY_Pos));
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
u32TxData = ((DEVICE_ID << 8) | u32PS2ACK);
PS2_Write(&u32TxData, 2);
printf("Device->Host: ACK + Device ID(0x%x)\n", DEVICE_ID);
}
}
else if(u32RxData == PS2CMD_SET_SCALLING2)
{
printf("Host->Device: Set scaling 2\n");
g_scalling = 2;
g_cmd[0] = 0;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
PS2_Write(&u32PS2ACK, 1);
printf("Device->Host: ACK\n");
}
}
else if(u32RxData == PS2CMD_SET_SCALLING1)
{
printf("Host->Device: Set scaling 1\n");
g_scalling = 1;
g_cmd[0] = 0;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
PS2_Write(&u32PS2ACK, 1);
printf("Device->Host: ACK\n");
}
}
else if(u32RxData == PS2CMD_ENABLE_DATA_REPORT)
{
printf("Host->Device: Enable data report\n");
g_dataReportEnable = 1;
g_cmd[0] = 0;
/* Set the timer for g_sampleRate */
/* The sample rate could be 10 ~ 200 samples/sec */
SysTick_Config(SystemCoreClock / g_sampleRate);
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
PS2_Write(&u32PS2ACK, 1);
printf("Device->Host: ACK\n");
}
}
else if(u32RxData == PS2CMD_DISABLE_DATA_REPORT)
{
printf("Host->Device: Disable data report\n");
g_dataReportEnable = 0;
g_cmd[0] = 0;
SysTick->CTRL = 0;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
PS2_Write(&u32PS2ACK, 1);
printf("Device->Host: ACK\n");
}
}
else if(u32RxData == PS2CMD_SET_RESOLUTION)
{
printf("Host->Device: Set resolution\n");
g_cmd[0] = PS2CMD_SET_RESOLUTION;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
PS2_Write(&u32PS2ACK, 1);
printf("Device->Host: ACK\n");
}
}
else if(u32RxData == PS2CMD_STATUS_REQUEST)
{
printf("Host->Device: PS2CMD_STATUS_REQUEST\n");
g_cmd[0] = 0;
/* Wait Tx ready */
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
u32TxData = ((0x64 << 24) | u32PS2ACK);
PS2_Write(&u32TxData, 4);
printf("Device->Host: ACK\n");
}
}
}
}
}
/* TXINT */
if(PS2_GET_INT_FLAG(PS2_PS2INTID_TXINT_Msk))
{
PS2_CLR_TX_INT_FLAG();
}
}
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Enable XT1_OUT (PF0) and XT1_IN (PF1) */
SYS->GPF_MFP &= ~(SYS_GPF_MFP_PF0_Msk | SYS_GPF_MFP_PF1_Msk);
SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;
/* Enable Internal RC 22.1184MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
/* Waiting for Internal RC clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
/* Enable external XTAL 12MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);
/* Waiting for external XTAL clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);
/* Set core clock as PLL_CLOCK from PLL */
CLK_SetCoreClock(PLL_CLOCK);
/* Enable UART module clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Enable UART module clock */
CLK_EnableModuleClock(PS2_MODULE);
/* Select IP clock source */
CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART_S_Msk;
CLK->CLKSEL1 |= CLK_CLKSEL1_UART_S_HXT;
/* Update System Core Clock */
SystemCoreClockUpdate();
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFP &= ~(SYS_GPB_MFP_PB0_Msk | SYS_GPB_MFP_PB1_Msk);
SYS->GPB_MFP |= (SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD);
/* Set PF multi-function pins for PS2 PS2_DAT and PS2_CLK */
SYS->GPF_MFP &= ~(SYS_GPF_MFP_PF2_Msk | SYS_GPF_MFP_PF3_Msk);
SYS->GPF_MFP |= (SYS_GPF_MFP_PF2_PS2_DAT | SYS_GPF_MFP_PF3_PS2_CLK);
}
void UART0_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
UART_Open(UART0, 115200);
}
void PS2_Init(void)
{
PS2_Open();
PS2_EnableInt(PS2_PS2CON_RXINTEN_Msk | PS2_PS2CON_TXINTEN_Msk);
NVIC_EnableIRQ(PS2_IRQn);
}
int main(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Lock protected registers */
SYS_LockReg();
/* Init UART0 for printf */
UART0_Init();
/* Init PS2 device */
PS2_Init();
g_cmd[0] = 0;
printf("\n\n");
printf("+-----------------------------------------------------------+\n");
printf("| PS2 Demo Code Test |\n");
printf("+-----------------------------------------------------------+\n");
printf("| Description : |\n");
printf("| The demo code will show the cursor moving on the |\n");
printf("| screen. |\n");
printf("+-----------------------------------------------------------+\n");
while(1)
{
if(g_opMode == PS2MOD_RESET)
{
if(g_CMD_RESET)
{
g_CMD_RESET = 0;
/* Delay 500ms*/
CLK_SysTickDelay(500000);
if(PS2_GET_STATUS() & PS2_PS2STATUS_TXEMPTY_Msk)
{
/* Transmit PASS & Device ID */
u32TxData = ((DEVICE_ID << 8) | u32PS2PASS);
PS2_Write(&u32TxData, 2);
printf("Device->Host: DEVICE ID\n");
/* TXINT */
while(PS2_GET_INT_FLAG(PS2_PS2INTID_TXINT_Msk))
{
PS2_CLR_TX_INT_FLAG();
}
}
}
else
{
/* Reset to default configuration */
g_sampleRate = 100;
g_resolution = 4;
g_scalling = 1;
g_dataReportEnable = 0;
/* Enter Stream mode */
g_opMode = PS2MOD_STREAM;
}
}
}
}
|