📄 ps2socket.c
字号:
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 + -