📄 ps2socket.c
字号:
// 6) Wait for the device to bring Clock high. // 7) Wait for the device to bring Clock low. 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 */ vJPI_DioSetOutput( (uint32) 0, PS2_DIO_CLOCK | PS2_DIO_DATA); /* input pins (data) will pull HIGH, output pins (clock) are driven LOW */ vJPI_DioSetDirection( PS2_DIO_DATA, PS2_DIO_CLOCK);}/**************************************************************************** * * NAME: vWait100us *//*! *\DESCRIPTION Blocking wait for 100 us. *//* PARAMETERS: None. * * RETURNS: Void * ****************************************************************************/PRIVATE void vWait100us(void){ vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 100, 100); while ( ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_TIMER_INT_PERIOD) ) ;}/**************************************************************************** * * NAME: boDeviceClkStarted *//*! *\DESCRIPTION Look for start of data transfer sequence. * 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 */ vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 10000, 10000); while ( ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_TIMER_INT_PERIOD) ) { /* if clock lines goes low, then device is ready to read a burst */ if( boCLOCK_IS_LOW ) { vJPI_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){ vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 100, 100); /* Wait for the device to bring Clock high */ while ( (boCLOCK_IS_LOW) && ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_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 */ vJPI_TimerStop(PS2_SOCKET_TIMER); // APVW is this necessary ? vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 100, 100); /* while still high, wait */ while ( (boCLOCK_IS_HIGH) && ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_TIMER_INT_PERIOD) ) ; vJPI_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 */ vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 100, 100); /* while data line still high keep looking, with timeout */ while ( (boDATA_IS_HIGH) && ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_TIMER_INT_PERIOD) ) ; vJPI_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 */ vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 100, 100); /* while clock line still high keep looking, with timeout */ while ( (boCLOCK_IS_HIGH) && ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_TIMER_INT_PERIOD) ) ; vJPI_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 */ vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 100, 100); /* while clock or data lines still high keep looking, with timeout */ while ( (boCLOCK_IS_LOW || boDATA_IS_LOW) && ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_TIMER_INT_PERIOD) ) ; vJPI_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 + -