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

📄 ps2socket.c

📁 基于Jennic公司Zigbee芯片JN5139做的无线键盘项目源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		if ( ! boDataBitClocked() )
			return PS2_ERROR_DEVICE_CLK_DATA_TO;
	}

	// 8)   Set the parity bit
	if (u8ParityCount & 0x01)
	{
		/* already ODD parity count, so DATA line LOW */
		vSET_DATA_LOW;
	}
	else
	{
		/* parity even, add a parity (HIGH) bit */
		vSET_DATA_HIGH;
	}
	if ( ! boDataBitClocked() )
		return PS2_ERROR_DEVICE_CLK_PARY_TO;

	// 9)   Release the Data line by setting as input
	vSET_DATA_HIGH;

	// 10) Wait for the device to bring Data low.
	if ( ! boDataWentLow() )
		return PS2_ERROR_DEVICE_ACK_1;

	// 11) Wait for the device to bring Clock  low.
	if ( ! boClockWentLow() )
		return PS2_ERROR_DEVICE_ACK_2;

	// 12) Wait for the device to release Data and Clock
	if ( ! boDataClkReleased() )
		return PS2_ERROR_DEVICE_ACK_3;

	return PS2_STATUS_SUCCESS;
}

/****************************************************************************
 *
 * NAME: u16FindStartBit
 *
 * DESCRIPTION:
 * Non-blocking scan of the bus, looking for a clocked low data-bit
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		PS2_STATUS_START_BIT    if seen a start bit, else
 *				PS2_ERROR_NO_START_BIT
 *
 ****************************************************************************/

PRIVATE uint16 u16FindStartBit(void)
{
	/* clock has already gone low, valid start bit should be ready */

	if (boDATA_IS_LOW)
		return PS2_STATUS_START_BIT;
	else
		return PS2_ERROR_NO_START_BIT;
}

/****************************************************************************
 *
 * NAME: u16FindDataBit
 *
 * DESCRIPTION:
 * Blocking scan of the bus, looking for a clocked data bit
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		PS2_STATUS_DATA_1_BIT    if seen a high data bit, else
 *				PS2_STATUS_DATA_0_BIT
 *
 ****************************************************************************/

PRIVATE uint16 u16FindDataBit(void)
{
	/* To get here we must have seen a clock falling-edge, so wait for */
	/* a rising edge */

	if (u16FindClkFallingEdge() == PS2_ERROR_DEVICE_CLK_EDGE_TO)
		return PS2_ERROR_DEVICE_CLK_DATA_TO;

	/* clock cycle (lo, hi, lo) has occurred, so read next data bit */

	if (boDATA_IS_HIGH)
		return PS2_STATUS_DATA_1_BIT;
	else
		return PS2_STATUS_DATA_0_BIT;
}

/****************************************************************************
 *
 * NAME: u16FindParityBit
 *
 * DESCRIPTION:
 * Blocking call - looks for a parity bit then checks for parity error.
 *
 * PARAMETERS: 	uint8 - number of high data bits in received 8 bit data word.
 *
 * RETURNS:		PS2_STATUS_SUCCESS    if ODD parity found, else
 *				PS2_ERROR_PARITY
 *
 ****************************************************************************/

PRIVATE uint16 u16FindParityBit(uint8 u8count)
{
	/* just seen last data bit, wait for a clock cycle */
	if (u16FindClkFallingEdge() == PS2_ERROR_DEVICE_CLK_EDGE_TO)
		return PS2_ERROR_DEVICE_CLK_PARY_TO;

	/* now read parity bit, if set add to 'set bits' counter */
	if (boDATA_IS_HIGH)
		u8count++;

	if (u8count & 0x01)
		return PS2_STATUS_SUCCESS;
	else
		return PS2_ERROR_PARITY;
}

/****************************************************************************
 *
 * NAME: u16FindStopBit
 *
 * DESCRIPTION:
 * Blocking call - looks for a clocked HIGH (stop) bit.
 *
 * PARAMETERS: 	None
 *
 * RETURNS:		PS2_STATUS_SUCCESS    if stop bit found, else
 *				PS2_ERROR_NO_STOP_BIT
 *
 ****************************************************************************/

PRIVATE uint16 u16FindStopBit(void)
{
	if (u16FindClkFallingEdge() == PS2_ERROR_DEVICE_CLK_EDGE_TO)
		return PS2_ERROR_DEVICE_CLK_STOP_TO;

	/* look for STOP bit, a HIGH data line	*/
	if (boDATA_IS_HIGH)
		return PS2_STATUS_SUCCESS;
	else
		return PS2_ERROR_NO_STOP_BIT;
}

/****************************************************************************
 *
 * NAME: u16FindClkFallingEdge
 *
 * DESCRIPTION:
 * Blocking call - looks for a LOW-HIGH-LOW clock transition.
 * Uses a simple timeout counter to prevent function from hanging if no clock.
 * This mechanism is dependent upon processor clock (fixed for the JN5121),
 * but the scan period is too chort to use a sleep timer.
 *
 * PARAMETERS: 	None
 *
 * RETURNS:		PS2_STATUS_SUCCESS
 *			or  PS2_ERROR_DEVICE_CLK_EDGE_TO - if no clock transition.
 *
 ****************************************************************************/

PRIVATE uint16 u16FindClkFallingEdge(void)
{
	/* APVW use 16 meg timers */

	/* simple timeout counter to avoid hanging on no clock edge */
	uint16 u16TimeOut = 0;

	/* clock must be low now, so wait for a rising edge */
	while ( boCLOCK_IS_LOW && (++u16TimeOut) )
		;

	/* If timeout counter wrapped, then clock timeout error has occurred */
	if (u16TimeOut == 0)
		return PS2_ERROR_DEVICE_CLK_EDGE_TO;

	/* now wait for a falling edge and hence valid data */
	u16TimeOut = 0;
	while ( boCLOCK_IS_HIGH && (++u16TimeOut) )
		;

	/* If timeout counter wrapped, then clock timeout error has occurred */
	if (u16TimeOut == 0)
		return PS2_ERROR_DEVICE_CLK_EDGE_TO;

	/* successful clock LOW-HIGH-LOW transition */
	return PS2_STATUS_SUCCESS;
}

/****************************************************************************
 *
 * NAME: vIdle
 *
 * DESCRIPTION:
 * Disable the PS2 bus by pulling the open-collector clock line low.
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		Void
 *
 ****************************************************************************/

PRIVATE void vIdle(void)
{
	/* set output latch to LOW for all lines */
	vAHI_DioSetOutput( (uint32) 0, PS2_DIO_CLOCK | PS2_DIO_DATA);

	/* input pins (data) will pull HIGH, output pins (clock) are driven LOW */
	vAHI_DioSetDirection( PS2_DIO_DATA, PS2_DIO_CLOCK);
}

/****************************************************************************
 *
 * NAME: vWait100us
 *
 * DESCRIPTION:
 * Blocking wait for 100 us.  Uses 32kHz wakeuptimer.
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		Void
 *
 ****************************************************************************/

PRIVATE void vWait100us(void)
{
	vAHI_TimerStartSingleShot(PS2_SOCKET_TIMER, 100, 100);

	while ( ! (u8AHI_TimerFired(PS2_SOCKET_TIMER) & E_AHI_TIMER_INT_PERIOD) )
		;
}

/****************************************************************************
 *
 * NAME: boDeviceClkStarted
 *
 * DESCRIPTION:
 * Look for the PS2 device (clock master) to pull clock low, thereby starting
 * PS2 data transfer sequence.
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		TRUE if clock negative edge seen, else FALSE
 *
 ****************************************************************************/

PRIVATE bool_t boDeviceClkStarted(void)
{
	/* allow PS2 device upto 10 ms to bring clock low */
	vAHI_TimerStartSingleShot(PS2_SOCKET_TIMER, 10000, 10000);

	while ( ! (u8AHI_TimerFired(PS2_SOCKET_TIMER) & E_AHI_TIMER_INT_PERIOD) )
	{
		/* if clock lines goes low, then device is ready to read a burst */
		if( boCLOCK_IS_LOW )
		{
			vAHI_TimerStop(PS2_SOCKET_TIMER);
			return TRUE;
		}
	}
	return FALSE;
}


/****************************************************************************
 *
 * NAME: boDataBitClocked
 *
 * DESCRIPTION:
 * Looks for a low-high-low sequence on the PS2 clock line. Waits for 100us to
 * allow upto two clock cycles at the lowest PS2 clock frequency of 10 kHz.
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		TRUE if clock sequence seen, else FALSE
 *
 ****************************************************************************/

PRIVATE bool_t boDataBitClocked(void)
{
	vAHI_TimerStartSingleShot(PS2_SOCKET_TIMER, 100, 100);

	/* Wait for the device to bring Clock high */
	while ( (boCLOCK_IS_LOW)
	         && ! (u8AHI_TimerFired(PS2_SOCKET_TIMER) & E_AHI_TIMER_INT_PERIOD) )
	  	;

	/* if clock is still low then must have timed-out, error: no clock */
	if (boCLOCK_IS_LOW)
	return FALSE;

	/* Wait for the device to bring Clock low */
	vAHI_TimerStop(PS2_SOCKET_TIMER); // APVW is this necessary ?
	vAHI_TimerStartSingleShot(PS2_SOCKET_TIMER, 100, 100);

	/* while still high, wait */
	while ( (boCLOCK_IS_HIGH)
	         && ! (u8AHI_TimerFired(PS2_SOCKET_TIMER) & E_AHI_TIMER_INT_PERIOD) )
	  	;

	vAHI_TimerStop(PS2_SOCKET_TIMER); // APVW is this necessary ?

	if (boCLOCK_IS_LOW)
		return TRUE;
	else
		return FALSE;
}

/****************************************************************************
 *
 * NAME: boDataWentLow
 *
 * DESCRIPTION:
 * Allow 100us for PS2 device (clock master) to take data line low.
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		TRUE if data line negative edge seen, else FALSE
 *
 ****************************************************************************/

PRIVATE bool_t boDataWentLow(void)
{
	/* Maximum wait for the device to bring Data low */
	vAHI_TimerStartSingleShot(PS2_SOCKET_TIMER, 100, 100);

	/* while data line still high keep looking, with timeout */
	while ( (boDATA_IS_HIGH)
	         && ! (u8AHI_TimerFired(PS2_SOCKET_TIMER) & E_AHI_TIMER_INT_PERIOD) )
	  	;

	vAHI_TimerStop(PS2_SOCKET_TIMER);

	if (boDATA_IS_LOW)
		return TRUE;
	else
		return FALSE;
}

/****************************************************************************
 *
 * NAME: boClockWentLow
 *
 * DESCRIPTION:
 * Allow 100us for PS2 device (clock master) to take clock line low.
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		TRUE if clock negative edge seen, else FALSE
 *
 ****************************************************************************/

PRIVATE bool_t boClockWentLow(void)
{
	/* Wait for the device to bring Clock low */
	vAHI_TimerStartSingleShot(PS2_SOCKET_TIMER, 100, 100);

	/* while clock line still high keep looking, with timeout */
	while ( (boCLOCK_IS_HIGH)
	         && ! (u8AHI_TimerFired(PS2_SOCKET_TIMER) & E_AHI_TIMER_INT_PERIOD) )
	  	;

	vAHI_TimerStop(PS2_SOCKET_TIMER);

	if (boCLOCK_IS_LOW)
		return TRUE;
	else
		return FALSE;
}

/****************************************************************************
 *
 * NAME: boDataClkReleased
 *
 * DESCRIPTION:
 * Allow 100us for PS2 device (clock master) to take clock and data line high.
 *
 * PARAMETERS: 	None.
 *
 * RETURNS:		TRUE if clock and data positive edge seen, else FALSE
 *
 ****************************************************************************/

PRIVATE bool_t boDataClkReleased(void)
{
	/* Wait for the device to release (go high) clock and data lines  */
	vAHI_TimerStartSingleShot(PS2_SOCKET_TIMER, 100, 100);

	/* while clock or data lines still high keep looking, with timeout */
	while ( (boCLOCK_IS_LOW || boDATA_IS_LOW)
	         && ! (u8AHI_TimerFired(PS2_SOCKET_TIMER) & E_AHI_TIMER_INT_PERIOD) )
	  	;

	vAHI_TimerStop(PS2_SOCKET_TIMER);

	if (boCLOCK_IS_HIGH && boDATA_IS_HIGH)
		return TRUE;
	else
		return FALSE;
}

/****************************************************************************/
/***        END OF FILE                                                   ***/
/****************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -