📄 mouse.c
字号:
#include <cpu.h>
#include <usb.h>
#pragma register_file EP4TxAddr 32
extern volatile void *EP4TxAddr ;
#pragma register_file EP4TxCount 34
extern volatile WORD EP4TxCount ;
#pragma register_file EP4RxAddr 36
extern volatile void *EP4RxAddr ;
#pragma register_file EP4RxCount 38
extern volatile WORD EP4RxCount ;
#pragma register_file EP5TxAddr 40
extern volatile void *EP5TxAddr ;
#pragma register_file EP5TxCount 42
extern volatile WORD EP5TxCount ;
//#pragma register_file EP5RxAddr 44
//extern volatile void *EP5RxAddr ;
//#pragma register_file EP5RxCount 46
//extern volatile WORD EP5RxCount ;
//#pragma register_file ms_tout 44
//extern volatile BYTE ms_tout ;
WORD ms_tout ;
#define DATA_IN() ;
#define DATA_OUT() ;
#define DATA_LOW() (P3DR = ~0x10)
#define DATA_HIGH() (P3DR = 0xFF)
#define DATA_IS_HIGH() (P3DR & 0x10)
#define CLK_LOW() (P3DR = ~0x20)
#define CLK_HIGH() (P3DR = 0xFF) ;
#define CLK_IS_HIGH() (P3DR & 0x20)
#define WAIT_CLK_LOW() ms_tout = 0x1FF ; \
do { \
if( !CLK_IS_HIGH()) \
break ; \
} while( --ms_tout) ; \
\
if( !ms_tout) \
return 1 ; \
//#define WAIT_C_L( a) asm( "\n\
// clr r1\n\
//tst_clkl" #a ":\n\
// tm R227, #0x20\n\
// jrz clk_is_low" #a "\n\
// djnz r1, tst_clk" #a "\n\
// ld r1, #1\n\
// ret\n\
//clk_is_low" #a ":\n")
#define WAIT_CLK_HIGH() ms_tout = 0x1FF ; \
do { \
if( CLK_IS_HIGH()) \
break ; \
} while( --ms_tout) ; \
\
if( !ms_tout) \
return 1 ; \
//#define WAIT_C_H( a) asm( "\n\
// clr r1\n\
//tst_clkh" #a ":\n\
// tm R227, #0x20\n\
// jrnz c_is_high" #a "\n\
// djnz r1, tst_clkh" #a "\n\
// ld r1, #1\n\
// ret\n\
//c_is_high" #a ":\n")
//#define WAIT_CLK_HIGH() ms_tout = 0 ; \
// while( !CLK_IS_HIGH()) \
// if( !( --ms_tout)) \
// return 1 ; \
//
#define FAIL() ms_tout = 0 ; \
return 1 ;
const unsigned char mouse_str[] = {
0xF3, 0xC8, 0xF3, 0x64, 0xF3, 0x50, 0xF0, 0xE8, 0x03, 0xF3, 0x64
} ;
#define MSINIT_SIZE ( sizeof mouse_str / sizeof mouse_str[ 0])
static BYTE mouse_length = 0 ;
static BYTE mouse_fsm = 0 ;
BYTE Mouse_Buffer[ 4] ;
static void MOUSE_Send( void) ;
unsigned char mouse_cmd( unsigned char c) /* returns TRUE on error */
{
unsigned char cnt ;
unsigned char parity = 1 ;
spp( P3C_PG) ;
/* Request mouse attention */
WAIT_CLK_HIGH() ;
/* Lower data line */
DATA_LOW() ;
DATA_OUT() ;
di() ;
/* Wait clock to be low again */
WAIT_CLK_LOW() ;
/* Transmit byte */
for( cnt = 0 ; cnt < 8 ; cnt++)
{
if( c & 1)
{
DATA_HIGH() ;
parity ^= 1 ;
}
else
DATA_LOW() ;
c >>= 1 ;
WAIT_CLK_HIGH() ;
WAIT_CLK_LOW() ;
}
/* Parity */
if( parity)
DATA_HIGH() ;
else
DATA_LOW() ;
WAIT_CLK_HIGH() ;
WAIT_CLK_LOW() ;
/* Stop bit */
DATA_HIGH() ;
WAIT_CLK_HIGH() ;
DATA_IN() ;
WAIT_CLK_LOW() ;
/* Line control bit: Mouse pulls data low on correct reception */
parity = DATA_IS_HIGH() ;
WAIT_CLK_HIGH() ;
if( !parity)
{
/* Inhibit io */
CLK_LOW() ;
ei() ;
ms_tout = 0x17F ; /* Delay for Logitech mouse */
while( ms_tout--)
;
}
ei() ;
return parity ;
}
unsigned char mouse_read( void)
{
unsigned char data = 0 ;
unsigned char cnt ;
unsigned char parity ;
// unsigned char error ;
spp( P3C_PG) ;
di() ;
/* Release bus == enable transmission */
CLK_HIGH() ;
WAIT_CLK_HIGH() ;
/* Start bit */
WAIT_CLK_LOW() ;
parity = 0 ;
// error = 0 ;
WAIT_CLK_HIGH() ;
for( cnt = 0 ; cnt < 8 ; cnt++)
{
WAIT_CLK_LOW() ;
data >>= 1 ;
if( DATA_IS_HIGH())
{
data |= 0x80 ;
parity ^= 1 ;
}
else
{
data &= ~0x80 ;
}
WAIT_CLK_HIGH() ;
}
/* Parity */
WAIT_CLK_LOW() ;
if( DATA_IS_HIGH())
{
parity ^= 1 ;
}
if( !parity)
{
/* Parity error */
// error += 1 ;
FAIL() ;
}
WAIT_CLK_HIGH() ;
/* Stop bit */
WAIT_CLK_LOW() ;
if( !DATA_IS_HIGH())
{
/* Stop bit error */
// error += 1 ;
FAIL() ;
}
else
{
WAIT_CLK_HIGH() ;
CLK_LOW() ; /* Inhibit IO */
ei() ;
ms_tout = 0x17F ; /* Delay for Logitech mouse */
while( ms_tout--)
;
ms_tout = 1 ;
}
ei() ;
return data ;
}
BYTE mouse_ret( BYTE val)
{
if( !mouse_cmd( val))
return mouse_read() ;
else
return 1 ;
}
void mouse_init( void)
{
if( mouse_fsm < MSINIT_SIZE)
{
if( mouse_ret( mouse_str[ mouse_fsm]) == 0xFA)
{
mouse_fsm += 1 ;
} else
mouse_fsm = 0 ;
}
else
{
mouse_length = 3 ;
if( mouse_ret( 0xF2) == 0xFA) /* READ_DT */
{
BYTE id ;
id = mouse_read() ;
if( ms_tout && (id == 3))
{
mouse_length += 1 ;
// if( mouse_ret( 0xE7) == 0xFA) /* Set resolution */
// {
// if( mouse_ret( 0x03) == 0xFA) /* 16 counts per mm */
// {
// nop() ;
// }
// }
}
mouse_fsm += 1 ;
}
else
mouse_fsm = 0 ;
}
/* Release bus */
CLK_HIGH() ;
ei() ;
}
void mouse_poll( void)
{
BYTE ack ;
ack = mouse_ret( 0xEB) ;
if( ack == 0xFA) /* READ_DATA */
{
Mouse_Buffer[ 0] = mouse_read() & 0x07 ;
if( ms_tout)
{
Mouse_Buffer[ 1] = mouse_read() ;
if( ms_tout)
{
Mouse_Buffer[ 2] = (BYTE) -((signed char) mouse_read()) ;
if( ms_tout && (mouse_length == 4))
{
Mouse_Buffer[ 3] = (BYTE) -((signed char) mouse_read()) ;
// ms_data[ 3] = (BYTE) -((signed char) ms_data[ 3]) ;
// ms_data[ 3] ; // <<= 1 ; // 2 ;
}
else
{
Mouse_Buffer[ 3] = 0 ;
}
}
}
else
nop() ;
} else
mouse_fsm = 0 ;
/* Release bus */
CLK_HIGH() ;
ei() ;
if( ms_tout && (ack == 0xFA))
MOUSE_Send() ;
}
void MOUSE_proc( void)
{
if( configuration_status[ 2])
{
// spp( 4) ;
// if( (ENDPR5_A & 0x30) == 0x20 /* STAT_NAK */)
// {
// if( mouse_fsm < (MSINIT_SIZE + 1))
// mouse_init() ;
// else
// mouse_poll() ;
// }
if( mouse_fsm <= MSINIT_SIZE)
{
mouse_init() ;
}
else
{
spp( 4) ;
if( (ENDPR5_A & 0x30) == 0x20 /* STAT_NAK */)
{
mouse_poll() ;
}
}
}
}
static void MOUSE_Send( void)
{
static BYTE cnt = 4 ;
if( !Mouse_Buffer[ 0] &&
!Mouse_Buffer[ 1] &&
!Mouse_Buffer[ 2] &&
!Mouse_Buffer[ 3])
{
if( cnt)
cnt-- ;
}
else
{
cnt = 4 ;
}
if( cnt)
{
EP5TxAddr = Mouse_Buffer ;
EP5TxCount = sizeof Mouse_Buffer ;
spp( 4) ;
ENDPR5_A |= 0x30 ; /* Tx Valid */
}
}
void MOUSE_reset( void)
{
/* Always called in Endpoint 0 (HUB) context */
spp( 4) ;
ENDPR4_A |= 0x02 ; /* Control endpoint */
EP4RxAddr = RxBuffer[ 2] ;
EP4RxCount = MAX_PACKET_SIZE ;
EP4TxAddr = 0 ; /* Insure there is a valid Tx address in case of a STATUS IN */
ENDPR4_A &= ~0x30 ; /* EP4 TX STAT_DISABLED */
ENDPR4_B |= 0x30 ; /* EP4 RX STAT_VALID */
/* INT IN */
ENDPR5_A &= ~0x30 ; /* EP5 TX STAT_DISABLED */
ENDPR5_B &= ~0x30 ; /* EP5 RX STAT_DISABLED */
ENDPR5_B |= 0x1 ; /* EP5 is Device 1 Endpoint 1 */
spp( USB_PG) ;
DADDR2 = 0 | 0x80 ; /* EP0 default address */
}
void MOUSE_set_configuration( BYTE configuration_status)
{
/* Called in the CTL endpoint context */
if( configuration_status == 0)
{
/* device is not configured */
ENDPR5_A &= ~0x30 ; /* Disable Tx */
}
else
{
/* device is configured */
ENDPR5_A &= ~0x70 ;
ENDPR5_A |= 0x20 ; /* Tx STAT_NAK */
}
}
#pragma INTERRUPT ep4_int
void ep4_int( void)
{
spp( 4) ;
if( ENDPR4_A == 0xEE) /* Correct SETUP received */
{
ENDPR4_B |= 0x80 ; /* By default we expect STATUS_OUT */
CurDevice = 2 ;
CurRxBuffer = (BYTE *) EP4RxAddr ;
fsm_state[ 2] = do_setup() ;
switch( fsm_state[ 2])
{
case TX_STALL:
ENDPR4_A &= ~0x30 ; /* Clear STAT bits */
ENDPR4_A |= 0x10 ; /* Tx STAT_STALL */
break ;
case TX_N:
EP4TxAddr = data_ptr ;
if( data_size[ 2] >= MAX_PACKET_SIZE)
{
EP4TxCount = MAX_PACKET_SIZE ;
}
else
{
EP4TxCount = data_size[ 2] ;
fsm_state[ 2] = TX_LAST ;
}
ENDPR4_A |= 0x30 ; /* TX STAT_VALID */
break ;
case TX_ACK_ADDR:
case TX_0:
EP4TxCount = 0 ; /* Enable the transmission */
ENDPR4_A |= 0x30 ;
break ;
default:
nop() ;
}
}
else if( (ENDPR4_A & 0xBF) == 0xAA) /* IN (don't care toggle) */
{
switch( fsm_state[ 2])
{
case TX_N: /* after IN( n) => send next */
EP4TxAddr += EP4TxCount ;
data_size[ 2] -= EP4TxCount ;
if( data_size[ 2] < MAX_PACKET_SIZE)
{
EP4TxCount = data_size[ 2] ;
fsm_state[ 2] = TX_LAST ;
}
ENDPR4_A |= 0x30 ; /* Tx STAT_VALID */
break ;
case TX_LAST: /* after a IN( 0) => expect STATUS_OUT */
break ;
case TX_ACK_ADDR:
spp( USB_PG) ;
DADDR2 = 0x80 | address[ 2] ;
spp( 4) ;
/* Fall Through */
case TX_0: /* STATUS_IN */
fsm_state[ 2] = UNDEFINED ;
break ;
}
}
else if( (ENDPR4_A & 0x8F) == 0x82) /* OUT (don't care Tx STAT */
{
switch( fsm_state[ 2])
{
case TX_N: /* HOST stops transmission */
ENDPR4_A &= ~0x30 ; /* Tx STAT_DISABLE */
/* Fall Through */
case TX_LAST: /* Status_out following transmission */
fsm_state[ 2] = UNDEFINED ;
}
}
EP4RxCount = MAX_PACKET_SIZE ;
ENDPR4_B |= 0x30 ; /* Rx STAT_VALID */
ENDPR4_A &= ~0x80 ; /* Reset CTR */
}
#pragma INTERRUPT ep5_int
void ep5_int( void)
{
spp( 4) ;
ENDPR5_A &= ~0x80 ; /* Reset CTR bit */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -