⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mouse.c

📁 用ST92163开发的鼠标
💻 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 + -