📄 ps2socket.c
字号:
/****************************************************************************//*! *\MODULE JN-AN-1072 Jenie Wireless Keyboard * *\COMPONENT $RCSfile: PS2socket.c,v $ * *\VERSION $Name: $ * *\REVISION $Revision: 1.2 $ * *\DATED $Date: 2007/11/22 08:33:21 $ * *\STATUS $State: Exp $ * *\AUTHOR APV Ward * *\DESCRIPTION PS2 Socket - implementation. * * This file contains the code that provides a full PS2 socket service. * It also supports the application's need to read from the PS2 bus, * as well as enableing/disabling the bus. PS2 is a bi-directional bus, and * this file provides both bus read and bus write functions - however, the * keyboard application only uses the bus read function. * * This file also defines which DIO pins on the J4 connector are used to * connect to the PS2 bus. *//* CHANGE HISTORY * * $Log: PS2socket.c,v $ * Revision 1.2 2007/11/22 08:33:21 mlook * JPI updates * Project and makefile renaming * * Revision 1.1 2007/11/14 10:18:24 mlook * Initial checkin * * * * LAST MODIFIED BY $Author: mlook $ * $Modtime: $ * **************************************************************************** * * This software is owned by Jennic and/or its supplier and is protected * under applicable copyright laws. All rights are reserved. We grant You, * and any third parties, a license to use this software solely and * exclusively on Jennic products. You, and any third parties must reproduce * the copyright and warranty notice and any other legend of ownership on each * copy or partial copy of the software. * * THIS SOFTWARE IS PROVIDED "AS IS". JENNIC MAKES NO WARRANTIES, WHETHER * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, * ACCURACY OR LACK OF NEGLIGENCE. JENNIC SHALL NOT, IN ANY CIRCUMSTANCES, * BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, SPECIAL, * INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON WHATSOEVER. * * Copyright Jennic Ltd 2005, 2006, 2007. All rights reserved * ****************************************************************************//****************************************************************************//*** Include files ***//****************************************************************************/#include <jendefs.h>#include <JPI.h>#include <AppHardwareApi.h>#include "PS2socket.h"/****************************************************************************//*** Macro Definitions ***//****************************************************************************//* External triger DIO18 - for debug scope *//* Clock: DIO19 *//* Data: DIO20 */#define DEBUG_EXT_TRIG ((uint32) (1 << 18))#define PS2_DIO_CLOCK ((uint32) (1 << 19))#define PS2_DIO_DATA ((uint32) (1 << 20))/* Clock and data-line control macros: easier to read */#define vSET_CLOCK_HIGH vJPI_DioSetDirection( PS2_DIO_CLOCK, (uint32) 0 )#define vSET_CLOCK_LOW vJPI_DioSetDirection( (uint32) 0, PS2_DIO_CLOCK )#define vSET_DATA_HIGH vJPI_DioSetDirection( PS2_DIO_DATA, (uint32) 0 )#define vSET_DATA_LOW vJPI_DioSetDirection( (uint32) 0, PS2_DIO_DATA )#define boCLOCK_IS_HIGH (u32JPI_DioReadInput() & PS2_DIO_CLOCK)#define boCLOCK_IS_LOW (!(u32JPI_DioReadInput() & PS2_DIO_CLOCK))#define boDATA_IS_HIGH (u32JPI_DioReadInput() & PS2_DIO_DATA)#define boDATA_IS_LOW (!(u32JPI_DioReadInput() & PS2_DIO_DATA))/* for debug scope */#define vSET_TRIG_HIGH vJPI_DioSetDirection( DEBUG_EXT_TRIG, (uint32) 0 )#define vSET_TRIG_LOW vJPI_DioSetDirection( (uint32) 0, DEBUG_EXT_TRIG )/* Timers: using macro overloading, so that timer choice can easily be changed */#define PS2_SOCKET_TIMER E_JPI_TIMER_1#define PS2_DATA_WIDTH 8/****************************************************************************//*** Type Definitions ***//****************************************************************************//****************************************************************************//*** Local Function Prototypes ***//****************************************************************************/PRIVATE uint16 u16FindStartBit (void);PRIVATE uint16 u16FindDataBit (void);PRIVATE uint16 u16FindParityBit (uint8);PRIVATE uint16 u16FindStopBit (void);PRIVATE uint16 u16FindClkFallingEdge (void);PRIVATE void vIdle (void);/* Write byte functions */PRIVATE void vWait100us (void);PRIVATE bool_t boDeviceClkStarted (void);PRIVATE bool_t boDataBitClocked (void);PRIVATE bool_t boDataWentLow (void);PRIVATE bool_t boClockWentLow (void);PRIVATE bool_t boDataClkReleased (void);/****************************************************************************//*** Exported Functions ***//****************************************************************************//**************************************************************************** * * NAME: u16PS2socketInit *//*! *\DESCRIPTION Initialisation. * * Initialises the PS2 interface into a known state by setting the PS2 * bus to idle. *//* PARAMETERS: None. * * RETURNS: PS2_STATUS_SUCCESS * ****************************************************************************/PUBLIC uint16 u16PS2socketInit(void){ /* set debug scope trigger as output and low */ vJPI_DioSetOutput ( (uint32) 0, DEBUG_EXT_TRIG); vJPI_DioSetDirection( (uint32) 0, DEBUG_EXT_TRIG); vIdle(); return PS2_STATUS_SUCCESS;}/**************************************************************************** * * NAME: u16PS2socketClose *//*! *\DESCRIPTION Closes the PS2 interface by setting the PS2 bus to idle. *//* PARAMETERS: None. * * RETURNS: PS2_STATUS_SUCCESS * ****************************************************************************/PUBLIC void vPS2socketClose(void){ vIdle();}/**************************************************************************** * * NAME: vPS2socketBusEnable *//*! *\DESCRIPTION Enable the PS2 bus by releasing the open-collector clock line. *//* PARAMETERS: None. * * RETURNS: Void * ****************************************************************************/PUBLIC void vPS2socketBusEnable(void){ /* set clock and data lines as inputs */ vJPI_DioSetDirection( (PS2_DIO_DATA | PS2_DIO_CLOCK), (uint32) 0);}/**************************************************************************** * * NAME: vPS2socketBusDisable *//*! *\DESCRIPTION Disable the PS2 bus by pulling the open-collector clock line low. *//* PARAMETERS: None. * * RETURNS: Void * ****************************************************************************/PUBLIC void vPS2socketBusDisable(void){ vIdle();}/**************************************************************************** * * NAME: boPS2socketBusReady *//*! *\DESCRIPTION Returns the current status of the PS2 clock and data lines. * Both lines low indicates bus active - also consistant with a start bit. *//* PARAMETERS: None. * * RETURNS: TRUE if both clock and data lines are low. * ****************************************************************************/PUBLIC bool_t boPS2socketBusReady(void){ /* if clock and data lines are low, then PS2 data burst has started */ return (bool_t) ( ! (u32JPI_DioReadInput() & (PS2_DIO_CLOCK | PS2_DIO_DATA)) );}/**************************************************************************** * * NAME: boPS2socketBusIdle *//*! *\DESCRIPTION Returns the current status of the PS2 clock and data lines. * Both lines high indicates bus idle. *//* PARAMETERS: None. * * RETURNS: TRUE if both clock and data lines are high (bus idle). * ****************************************************************************/PUBLIC bool_t boPS2socketBusIdle(void){ /* if BOTH clock and data lines are high, then PS2 bus is idle */ return (bool_t)( (u32JPI_DioReadInput() & (PS2_DIO_CLOCK | PS2_DIO_DATA)) == (PS2_DIO_CLOCK | PS2_DIO_DATA) );}/**************************************************************************** * * NAME: boPS2socketBusStarted *//*! *\DESCRIPTION Returns the current status of the PS2 clock and data lines. * Both lines low indicates bus active - also consistant with a start bit. * Scan lines for at least 100 us, return earlier if bus cycle starts. *//* PARAMETERS: None. * * RETURNS: TRUE if both clock and data lines are low. * ****************************************************************************/PUBLIC bool_t boPS2socketBusStarted(void){ /* Start timer */ vJPI_TimerStart(PS2_SOCKET_TIMER, E_JPI_TIMER_MODE_SINGLESHOT, 100, 100); while ( ! (u8JPI_TimerFired(PS2_SOCKET_TIMER) & E_JPI_TIMER_INT_PERIOD) ) { /* if clock and data lines are low, then PS2 data burst has started */ if( ! (u32JPI_DioReadInput() & (PS2_DIO_CLOCK | PS2_DIO_DATA)) ) { vJPI_TimerStop(PS2_SOCKET_TIMER); return TRUE; } } return FALSE;}/**************************************************************************** * * NAME: u16PS2socketRead *//*! *\DESCRIPTION Read a data burst from the PS2 device. * * A full description of the PS2 bus protocol would not be appropriate here. * However, here is a simple overview of a read sequence: * * PS2 device drives the clock line, unless the line is already low(device disabled). * Falling edge of the clock line strobes valid date. * Data burst starts with an active low start bit, * followed by 8 data bits (LSB first) * followed by an ODD parity bit, * followed by an active high stop bit. * * At any stage a data burst can be aborted if the open-collector clock line * is pulled low for more than 100 uS. If this happens before the 11th data bit * period has completed, then the data burst must be sent again (after the clock * line has been released for more than 50 uS). *//* PARAMETERS: None. * * RETURNS: uint16 - PS2 code (8 bits), or error code (16 bits) * ****************************************************************************/PUBLIC uint16 u16PS2socketRead(void){ uint8 u8Loop; uint8 u8Read = 0; uint8 u8ParityCount = 0; uint16 u16Status; /* enter here after detecting a falling edge on PS2 clock line */ /* check for the start bit from the bus, abort if not present */ u16Status = u16FindStartBit(); if (u16Status != PS2_STATUS_START_BIT) return u16Status; /* Now look for the data part of the transmission */ for (u8Loop = 0; u8Loop < PS2_DATA_WIDTH; u8Loop++) { u16Status = u16FindDataBit(); /* look for single clocked-data bit */ switch (u16Status) { case PS2_STATUS_DATA_1_BIT: u8Read |= (0x01 << u8Loop); u8ParityCount++; break; case PS2_STATUS_DATA_0_BIT: /* bit accumulator already 0 */ break; case PS2_ERROR_DEVICE_CLK_DATA_TO: /* timeout */ return u16Status; break; default: /* Error condition catch-all */ return PS2_ERROR_UNKNOWN; break; } } /* look for the parity bit, abort if not correct */ u16Status = u16FindParityBit(u8ParityCount); if (u16Status != PS2_STATUS_SUCCESS) return u16Status; /* look for a stop bit, abort if not present */ u16Status = u16FindStopBit(); if (u16Status == PS2_ERROR_NO_STOP_BIT) return u16Status; /* successful read from the PS2 bus, return code */ return (uint16) u8Read;}/**************************************************************************** * * NAME: u16PS2socketWrite *//*! *\DESCRIPTION PS2 bus write sequence. * The PS2 bus is bidirectional, for a PS2 keyboard * the back channel carries config and status commands (auto-repeat rates, * shift, caps lock LED control etc). * * This function NOT used in this keyboard demo application. *//* PARAMETERS: None. * * RETURNS: PS2_STATUS_SUCCESS if write successful, else these error coes * PS2_ERROR_DEVICE_CLK_START_TO * PS2_ERROR_DEVICE_CLK_DATA_TO * PS2_ERROR_DEVICE_CLK_PARY_TO * PS2_ERROR_DEVICE_ACK_0 * PS2_ERROR_DEVICE_ACK_1 * PS2_ERROR_DEVICE_ACK_2 * ****************************************************************************/PUBLIC uint16 u16PS2socketWrite(uint8 u8Datum){ uint8 u8Loop; uint8 u8ParityCount = 0; /* DEBUG */ vSET_TRIG_HIGH; // 1) Bring the Clock line low for at least 100 microseconds. // Both output latches low, but data is an input vIdle(); vWait100us(); // 2) Bring the Data line low. vSET_DATA_LOW; // 3) Release the Clock line. vSET_CLOCK_HIGH; // 4) Wait for the device to bring the Clock line low. if ( ! boDeviceClkStarted() ) return PS2_ERROR_DEVICE_CLK_START_TO; /* send data byte */ for (u8Loop = 0; u8Loop < PS2_DATA_WIDTH; u8Loop++) { // 5) Set/reset the Data line to send the first data bit if (u8Datum & (0x01 << u8Loop)) { vSET_DATA_HIGH; u8ParityCount++; } else { vSET_DATA_LOW; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -