Does anyone here got an example of a simple PIC-based PS/2 device that can be used to control the cursor in windows? Circuit(seen a lot) and programming. Just a simple example of the PIC sending data through PS/2 port to the PC to move the cursor, that's all. Nothing more, nothing less. PIC -> PS/2 -> PC -> CursorMoves And of course, the button presses and all. i googled so hard today to no avail. I found a lot of articles on the protocol but no source codes to allow me to see how it can be implemented. Preferably an example in C, Assembly I can look into as well. I need it to get started with my project, which is basically to replace a mouse as a pointing device. The pointing method and everything I do my own way, it's just the sending data through the PS/2 that I do not know. Thanks in advance.
You could always get an older mouse and get the circuit out of that and use the PIC to send "clicks" to the mouse circuit, should be easy enough.
I did an AVR touchpad project kind of the other way round, but perhaps some of that info might be helpful to you. There's also a link to my source code in Basic. The PS2 protocol documents pretty much contain everything you need, you just have to migrate the described functionality into code.
There was one online, but now it's gone. Try contacting the author via email (panda.cs.ndsu.nodak.edu is what it gave), if you can't reach him, PM me, pretty sure I have a copy of the PIC asm files somewhere.
Found the code, on second thought, it says you can redistribute if you don't change the headers, so here goes. Here's the heading from my copy of the page (This totally validates me "Scrapbook"-ing every page of interest, but this was before I had ScrapBook installed) Code: ; PS/2 Mouse Emulator by Adam Chapweske (chap0179@tc.umn.edu) v1.51 ; http://panda.cs.ndsu.nodak.edu/~achapwes/ ; This was written for the PIC16F84 with an RC oscillator @ 20pF/5kohm ; (will work with any oscillator between 3.50 MHz - 5.76 MHz) ; ; FEEL FREE TO USE THIS CODE FOR NON-COMMERCIAL PURPOSES ONLY. YOU MAY DISTRIBUTE ; THIS CODE ONLY IF IT IS UNMODIFIED FROM ITS ORIGINAL FORM AND IT MUST CONTAIN THIS ; HEADING. I DO NOT IMPLY ANY WARANTEES OR GUARANTEES. USE AT YOUR OWN RISK. ENJOY!!! ; ; Copyright 2001, Adam Chapweske ;--------------------------------------------------------------------------------------------- ; CLOCK/TIMING INFORMATION: ;--------------------------------------------------------------------------------------------- ; ; PS/2 bus clock low time = 40 us +/- 25% (30 us - 50 us) ; PS/2 bus clock high time = 40 us +/- 25% (30 us - 50 us) ; RC osc @ 20pF/5k = 4.61 MHz +/- 25% (3.50 MHz - 5.76 MHz) ; 1 instruction cycle @ 4.61 MHz (RC) = 0.87 us +/- 25% (0.65 us - 1.09 us) ; Optimum PS/2 bus clock low time @4.61MHz = 45.97 instruction cycles ; Actual PS/2 bus clock low time = 46 instruction cycles ; Actual PS/2 bus clock low time @4.61MHz (RC) = 40.0us +/- 25% (30us-50us) ; Actual PS/2 bus clock frequency @461MHz (RC) = 12.5 kHz +/- 25% (10.0kHz-16.7kHz) ;--------------------------------------------------------------------------------------------- ; HEADER: ;--------------------------------------------------------------------------------------------- TITLE "PS/2 Mouse Emulator" SUBTITLE "Copyright 2001, Adam Chapweske" LIST P=16F84 INCLUDE "p16f84.inc" RADIX DEC ERRORLEVEL -224, 1 __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC ;--------------------------------------------------------------------------------------------- ; DEFINES: ;--------------------------------------------------------------------------------------------- #DEFINE DATA PORTA, 2 ;May be assigned to any I/O pin #DEFINE CLOCK PORTA, 3 ;May be assigned to any I/O pin #DEFINE PS2_Yp PORTB, 0 ;May be assigned to any I/O pin #DEFINE PS2_Yn PORTB, 1 ;May be assigned to any I/O pin #DEFINE PS2_Xp PORTB, 2 ;May be assigned to any I/O pin #DEFINE PS2_Xn PORTB, 3 ;May be assigned to any I/O pin #DEFINE PS2_Bl PORTB, 4 ;May be assigned to any I/O pin #DEFINE PS2_Br PORTB, 5 ;May be assigned to any I/O pin #DEFINE PERIOD 20 ;Time between reading of inputs. Min=(osc frequency)/204800 #DEFINE DISTANCE 2 ;Amount by which X/Y counters are incremented/decremented ;--------------------------------------------------------------------------------------------- ; RAM ALLOCATION: ;--------------------------------------------------------------------------------------------- cblock 0x0C TEMP0, TEMP1 RECEIVE, PARITY, COUNTER ;Used in I/O routines REPORT_RATE, RESOLUTION ;Used for responses to status requests FLAGS, XY_FLAGS dBUTTONS ;"Delta Button States" X_COUNTER Y_COUNTER endc ;--------------------------------------------------------------------------------------------- ;FLAGS: ; bit 7 -- Always 0 ; bit 6 -- Stream(0)/Remote(1) mode ; bit 5 -- Disable(0)/Enable(1) reporting ; bit 4 -- 1:1(0)/2:1(1) Scaling ; bit 3 -- Always 0 ; bit 2 -- Always 0 ; bit 1 -- Always 0 ; bit 0 -- Always 0 MODE equ 6 ENABLE equ 5 SCALE equ 4 ;--------------------------------------------------------------------------------------------- ;XY_FLAGS: ; bit 7 -- Y Counter overflow ; bit 6 -- X Counter overflow ; bit 5 -- Y counter sign bit ; bit 4 -- X counter sign bit ; bit 3 -- Always 1 ; bit 2 -- Always 0 (middle button) ; bit 1 -- Previous right button state ; bit 0 -- Previous left button state yOVF equ 7 xOVF equ 6 ySIGN equ 5 xSIGN equ 4 ;dBUTTONS ; bit 7 -- Always 0 ; bit 6 -- Always 0 ; bit 5 -- Always 0 ; bit 4 -- Always 0 ; bit 3 -- Always 0 ; bit 2 -- Always 0 ; bit 1 -- Change in right buton state ; bit 0 -- Change in left button state ;--------------------------------------------------------------------------------------------- cblock ;Contains to-be-sent packet and last packet sent LENGTH SEND1 SEND2 SEND3 endc ;--------------------------------------------------------------------------------------------- ; MACROS: ;--------------------------------------------------------------------------------------------- ;Delay "Cycles" instruction cycles Delay macro Time if (Time==1) nop exitm endif if (Time==2) goto $ + 1 exitm endif if (Time==3) nop goto $ + 1 exitm endif if (Time==4) goto $ + 1 goto $ + 1 exitm endif if (Time==5) goto $ + 1 goto $ + 1 nop exitm endif if (Time==6) goto $ + 1 goto $ + 1 goto $ + 1 exitm endif if (Time==7) goto $ + 1 goto $ + 1 goto $ + 1 nop exitm endif if (Time%4==0) movlw (Time-4)/4 call Delay_us exitm endif if (Time%4==1) movlw (Time-5)/4 call Delay_us nop exitm endif if (Time%4==2) movlw (Time-6)/4 call Delay_us goto $ + 1 exitm endif if (Time%4==3) movlw (Time-7)/4 call Delay_us goto $ + 1 nop exitm endif endm ;--------------------------------------------------------------------------------------------- ; ORG 0x000: ;--------------------------------------------------------------------------------------------- org 0x000 goto Start ;--------------------------------------------------------------------------------------------- ; HANDLE COMMAND: ;--------------------------------------------------------------------------------------------- if (high Table1End != 0) ERROR "Command handler table must be in low memory page" endif Command movlw 0x04 ;Test for a resolution value subwf RECEIVE, w bnc SetResolution movlw 0xC8 ;Test for report rate value subwf RECEIVE, w bnc SetReportRate movlw 0xE6 ;0xE6 is lowest code subwf RECEIVE, w bnc MainLoop HandlerTable addwf PCL, f ;Add offset goto Mouse_E6 ;0xE6 - Set Scaling 1:1 goto Mouse_E7 ;0xE7 - Set Scaling 2:1 goto MainLoop ;0xE8 - Set Resolution goto Mouse_E9 ;0xE9 - Status Request goto Mouse_EA ;0xEA - Set Stream Mode goto Report ;0xEB - Read Data goto MainLoop ;0xEC - Reset Wrap Mode goto MainLoop ;0xED - goto WrapMode ;0xEE - Set Wrap Mode goto MainLoop ;0xEF goto Mouse_F0 ;0xF0 - Set Remote Mode goto MainLoop ;0xF1 goto Mouse_F2 ;0xF2 - Read Device Type goto MainLoop ;0xF3 - Set Report Rate goto Mouse_F4 ;0xF4 - Enable goto Mouse_F5 ;0xF5 - Disable goto Mouse_F6 ;0xF6 - Set Default goto MainLoop ;0xF7 goto MainLoop ;0xF8 goto MainLoop ;0xF9 goto MainLoop ;0xFA goto MainLoop ;0xFB goto MainLoop ;0xFC goto MainLoop ;0xFD goto PacketOut ;0xFE - Resend Table1End goto Reset ;0xFF - Reset ;--------------------------------------------------------------------------------------------- ; START: ;--------------------------------------------------------------------------------------------- Start clrf PORTA clrf PORTB bsf STATUS, RP0 ;(TRISA=TRISB=0xFF by default) movlw 0x57 ;Timer mode, assign max. prescaler, enable pullups movwf OPTION_REG bcf STATUS, RP0 movlw 0x08 ;Bit 3 always = 1, clear previous button states movwf XY_FLAGS ; goto Reset ;--------------------------------------------------------------------------------------------- ; Reset Mode: ;--------------------------------------------------------------------------------------------- Reset movlw 0xAA movwf SEND1 ;Load BAT completion code call LoadDefaults clrf SEND2 ;Load Device ID (0x00) movlw 0x02 movwf LENGTH call BATdelay goto PacketOut ;Output 2-byte "completion-code, device ID" packet ;--------------------------------------------------------------------------------------------- ; Stream/Remote Mode: ;--------------------------------------------------------------------------------------------- MainLoop clrf X_COUNTER ;Clear movement counters clrf Y_COUNTER MainLoop1 btfss DATA ;Check for host request-to-send goto PacketIn movlw PERIOD ;Report period subwf TMR0, w btfss STATUS, C ;TMR0=report period? goto MainLoop1 ; No--loop clrf TMR0 ; Yes--reset TMR0, then read inputs... call ReadInputs btfsc FLAGS, MODE ;Stream(0)/Remote(1) mode goto MainLoop1 btfss FLAGS, ENABLE ;Disable(0)/Enable(1) reporting goto MainLoop1 movf X_COUNTER, w ;Test for X-movement iorwf Y_COUNTER, w ;Test for Y-movement iorwf dBUTTONS, w ;Test for change in button states bz MainLoop1 ; goto Report ;--------------------------------------------------------------------------------------------- ; REPORT: ;--------------------------------------------------------------------------------------------- Report movf dBUTTONS, w xorwf XY_FLAGS, f ;Find current button state movf XY_FLAGS, w movwf SEND1 movf X_COUNTER, w movwf SEND2 movf Y_COUNTER, w movwf SEND3 movlw 0x03 ;Movement data report length movwf LENGTH ; goto PacketOut ;--------------------------------------------------------------------------------------------- ; OUTPUT PACKET ;--------------------------------------------------------------------------------------------- PacketOut movlw SEND1 ;First byte of packet movwf FSR movf LENGTH, w ;Length of packet movwf TEMP1 PacketOutLoop movf INDF, w ;Get data byte call ByteOut ; Output that byte xorlw 0xFF ;Test for RTS error bz PacketIn xorlw 0xFE ^ 0xFF ;Test for inhibit error bz PacketOut incf FSR, f ;Point to next byte decfsz TEMP1, f goto PacketOutLoop goto MainLoop ;--------------------------------------------------------------------------------------------- ; READ PACKET ;--------------------------------------------------------------------------------------------- PacketIn call ByteIn xorlw 0xFF ;Test for parity/framing error bz Mouse_ERR xorlw 0xFE ^ 0xFF ;Test for inhibit error bz MainLoop1 movlw 0xFE ;Test for "Resend" command xorwf RECEIVE, w bz PacketOut Acknowledge movlw 0xFA ;Acknowledge call ByteOut goto Command ;--------------------------------------------------------------------------------------------- ; READ INPUTS: ;--------------------------------------------------------------------------------------------- ReadInputs movlw DISTANCE btfss PS2_Xp ;Read inputs addwf X_COUNTER, f btfss PS2_Yp addwf Y_COUNTER, f btfss PS2_Xn subwf X_COUNTER, f btfss PS2_Yn subwf Y_COUNTER, f bcf XY_FLAGS, xSIGN btfsc X_COUNTER, 7 bsf XY_FLAGS, xSIGN bcf XY_FLAGS, ySIGN btfsc Y_COUNTER, 7 bsf XY_FLAGS, ySIGN movf XY_FLAGS, w ;Get previous button states andlw b'00000111' btfss PS2_Bl ;Find changes in button states xorlw b'00000001' btfss PS2_Br xorlw b'00000010' movwf dBUTTONS ;Save *change* in button state retlw 0x00 ;--------------------------------------------------------------------------------------------- ; WRAP MODE: ;--------------------------------------------------------------------------------------------- WrapMode btfsc DATA ;Wait for RTS goto WrapMode call ByteIn ;Read one byte from host xorlw 0xFE ;Test for aborted transmission bz WrapMode movf RECEIVE, w xorlw 0xFF ;Test for "Reset" command bz Acknowledge xorlw 0xFF^0xEC ;Test for "Reset Wrap Mode" command bz Acknowledge xorlw 0xEC call ByteOut ;Else, echo goto WrapMode ;--------------------------------------------------------------------------------------------- ; LOAD DEFAULT VALUES: ;--------------------------------------------------------------------------------------------- LoadDefaults movlw 100 ;Default report rate movwf REPORT_RATE movlw 0x02 ;Default resolution movwf RESOLUTION clrf FLAGS ;Stream mode, 1:1 scaling, disabled retlw 0x00 ;--------------------------------------------------------------------------------------------- ; EMULATE BAT: ;--------------------------------------------------------------------------------------------- BATdelay clrf TEMP0 ;Used for a 400 ms delay at power-on clrf TEMP1 DelayLoop Delay 6 decfsz TEMP0, f goto DelayLoop decfsz TEMP1, f goto DelayLoop retlw 0x00 ;--------------------------------------------------------------------------------------------- ; HANDLE COMMANDS: ;--------------------------------------------------------------------------------------------- SetResolution movf RECEIVE, w movwf RESOLUTION goto MainLoop SetReportRate movf RECEIVE, w movwf REPORT_RATE goto MainLoop ;0xE6 - Set Scaling 1:1 Mouse_E6 bcf FLAGS, SCALE goto MainLoop ;0xE7 - Set Scaling 2:1 Mouse_E7 bsf FLAGS, SCALE goto MainLoop ;0xE9 - Status Request Mouse_E9 movf FLAGS, w btfss PS2_Bl iorlw 0x04 btfss PS2_Br iorlw 0x01 movwf SEND1 movf RESOLUTION, w movwf SEND2 movf REPORT_RATE, w movwf SEND3 movlw 0x03 movwf LENGTH goto PacketOut ;0xEA - Set Stream Mode Mouse_EA bcf FLAGS, MODE goto MainLoop ;0xF0 - Set Remote Mode Mouse_F0 bsf FLAGS, MODE goto MainLoop ;0xF2 - Get Device ID Mouse_F2 clrf SEND1 movlw 0x01 movwf LENGTH goto PacketOut ;0xF4 - Enable Reporting Mouse_F4 bsf FLAGS, ENABLE goto MainLoop ;0xF5 - Disable Reporting Mouse_F5 bcf FLAGS, ENABLE goto MainLoop ;0xF6 - Set Default Mouse_F6 call LoadDefaults goto MainLoop ;Invalid command Mouse_ERR movlw 0xFE call ByteOut goto MainLoop ;--------------------------------------------------------------------------------------------- ; OUTPUT ONE BYTE: - TIMING IS CRITICAL!!! ;--------------------------------------------------------------------------------------------- ByteOut movwf TEMP0 InhibitLoop btfss CLOCK ;Test for inhibit goto InhibitLoop Delay 100 ;(50 microsec = 58 clock cycles, min) btfss CLOCK goto InhibitLoop btfss DATA ;Check for request-to-send retlw 0xFF clrf PARITY movlw 0x08 movwf COUNTER movlw 0x00 call BitOut ;Start bit (0) btfss CLOCK ;Test for inhibit goto ByteOutEnd Delay 4 ByteOutLoop movf TEMP0, w xorwf PARITY, f call BitOut ;Data bits btfss CLOCK ;Test for inhibit goto ByteOutEnd rrf TEMP0, f decfsz COUNTER, f goto ByteOutLoop Delay 2 comf PARITY, w call BitOut ;Parity bit btfss CLOCK ;Test for inhibit goto ByteOutEnd Delay 5 movlw 0xFF call BitOut ;Stop bit (1) Delay 48 retlw 0x00 ByteOutEnd bsf STATUS, RP0 bsf DATA bsf CLOCK bcf STATUS, RP0 retlw 0xFE BitOut bsf STATUS, RP0 andlw 0x01 btfss STATUS, Z bsf DATA btfsc STATUS, Z bcf DATA Delay 21 bcf CLOCK Delay 45 bsf CLOCK bcf STATUS, RP0 Delay 5 return ;--------------------------------------------------------------------------------------------- ; READ ONE BYTE: (Takes about 1ms) - TIMING IS CRITICAL!!! ;--------------------------------------------------------------------------------------------- ByteIn btfss CLOCK ;Test for Request-to-send retlw 0xFE btfsc DATA retlw 0xFE movlw 0x08 movwf COUNTER clrf PARITY Delay 28 ByteInLoop call BitIn ;Data bits btfss CLOCK ;Test for inhibit retlw 0xFE bcf STATUS, C rrf RECEIVE, f iorwf RECEIVE, f xorwf PARITY,f decfsz COUNTER, f goto ByteInLoop Delay 1 call BitIn ;Parity bit btfss CLOCK ;Test for inhibit retlw 0xFE xorwf PARITY, f Delay 5 ByteInLoop1 Delay 1 call BitIn ;Stop bit btfss CLOCK ;Test for inhibit retlw 0xFE xorlw 0x00 btfsc STATUS, Z clrf PARITY btfsc STATUS, Z ;Stop bit = 1? goto ByteInLoop1 ; No--keep clocking. bsf STATUS, RP0 ;Acknowledge bcf DATA Delay 11 bcf CLOCK Delay 45 bsf CLOCK Delay 7 bsf DATA bcf STATUS, RP0 btfss PARITY, 7 ;Parity correct? retlw 0xFF ; No--return error Delay 45 retlw 0x00 BitIn Delay 8 bsf STATUS, RP0 bcf CLOCK Delay 45 bsf CLOCK bcf STATUS, RP0 Delay 21 btfsc DATA retlw 0x80 retlw 0x00 ;--------------------------------------------------------------------------------------------- ; DELAY: ;--------------------------------------------------------------------------------------------- ;Delays 4w+4 cycles (including call,return, and movlw) (0=256) Delay_us addlw -1 ;Precise delays used in I/O btfss STATUS, Z goto Delay_us return end
Thanks for the help guys. agent420 for reference to your AVR Pad shotgunefx for the source code and schematic of a PIC based mouse. r4tch3t for a rather interesting idea. Maybe I should consider that if all else fails. At least for demonstration purposes .
You might be interested to know that i use the above assembly source code (with modification) by Adam Chapweske for this project: http://www.creativemods.com/forums/viewtopic.php?t=6892
groovygamegear.com has some great interface devices for good prices. I keep looking at it and thinking of making my own game controller.
This might have come a bit too late, but i finally get to work on making my own air mouse. I stumble upon a brick wall when in PS/2 part. This is my PS/2 line analysis, debugging program of some sort. The PIC reports every transaction that occurs on the line, successful send, successful receive, parity/stopbit error or any inhibition during transfer. considering i see the data being sent and received is the same as described by the documentation, I think the initialization part is a bit on the successful side........ ..... other than the host PC (in this case a laptop) keeps hogging the line and spams 0x10 to the PIC, preventing it from reporting movement packet when it is allowed to as indicated by host sending 0xF4 and the PIC replying 0xFA right before the 0x10 spamming. Other commands from host PC that I don't know how to respond to. I see these sometimes but, they don't pop up as often. 0xFA <--- i thought the PIC is suppose to be the one sending this ack byte, not receiving the ack byte 0xEC <--- suppose to be when mouse in wrap mode, but wrap mode command (0xEE) never came in the first place 0xED <--- came after i reply 0xFA to command 0xEC above, i just simply added the ack to test it out. 0xED came after 0xEC any further help greatly appreciated