Author: wmb Date: 2008-11-04 01:57:29 +0100 (Tue, 04 Nov 2008) New Revision: 993
Modified: dev/ps2mouse.fth Log: Added "stream-poll?" and "adaptive-poll?" mouse methods so that client programs can track the mouse efficiently.
Modified: dev/ps2mouse.fth =================================================================== --- dev/ps2mouse.fth 2008-11-03 17:32:11 UTC (rev 992) +++ dev/ps2mouse.fth 2008-11-04 00:57:29 UTC (rev 993) @@ -66,7 +66,7 @@ : mouse2:1 h# e7 cmd ; : stream-on h# f4 cmd ; : stream-off h# f5 cmd ; -: stream-mode h# ea cmd ; +: stream-mode h# ea cmd stream-on ;
\ The Apex concentrator refuses to send motion and button events \ unless stream data is enabled! @@ -104,7 +104,7 @@ ; [then]
-\ Translate RML to RML +\ Translate MRL to RML create buttons 0 c, 1 c, 4 c, 5 c, 2 c, 3 c, 6 c, 7 c,
\ create Mitsumi \ Comment out this line if you don't support Mitsumi mouse @@ -128,7 +128,123 @@ : clear-queue ( -- ) begin get-data? while drop repeat ; : no-event ( -- 0 0 0 ) clear-queue 0 0 0 ;
+0 instance value mouse-byte# +instance variable mouse-bytes +0 instance value mouse-timestamp +2 instance value poll-delay + +: save-byte ( byte -- ) + mouse-bytes @ 8 lshift or mouse-bytes ! ( ) + mouse-byte# 1+ to mouse-byte# ( ) + get-msecs to mouse-timestamp + 2 to poll-delay +; +: out-of-packet ( -- ) + 0 to mouse-byte# + 0 to mouse-timestamp +; + +: stream-event ( byte -- false | x y buttons true ) + mouse-byte# case ( byte ) + 0 of + \ Discard if framing error + dup 8 and if save-byte else drop then ( ) + false exit + endof + + 1 of save-byte false exit then + endcase ( byte3 ) + + \ Fall through if already have 2 mouse bytes (this is the third) + out-of-packet + + mouse-bytes @ wbsplit ( byte3-ylow byte2-xlow byte1-stat ) + + dup 7 and buttons + c@ >r ( ylow xlow stat ) + swap over h# 10 ?negative -rot ( x ylow stat ) + h# 20 ?negative r> ( x y buttons ) + + true exit +; + +\ Time-based resynchronization. If we are in the middle of a packet, +\ but we poll and see no bytes and the interval since the last byte +\ was longer than the possible time between bytes within a packet, +\ we discard the queued-up bytes. +: ?reframe ( -- ) + mouse-byte# if + \ We don't trust time intervals <= ms/tick because the timestamp + \ could have happened just before a tick and the next sample + \ right after a tick, so the actual elapsed time could be almost + \ zero, but the reported time difference would be ms/tick . + get-msecs mouse-timestamp - ms/tick - 0 max d# 5 > if + out-of-packet + then + then +; headers + +: stream-poll? ( -- false | x y buttons true ) + begin get-data? while ( byte ) + \ If we have a packet, retry soon because there is likely to be another + \ right on its heels. The packet generation rate is 100/sec, but some + \ could be queued up, so we don't wait a full 10 ms + stream-event ?dup if exit then + repeat ( ) + + ?reframe + false +; + +\ delay-ms is a suggested delay until the next poll. It tells you when +\ a call to stream-poll? is likely to have something worthwhile to do. +\ In the middle of an incoming mouse packet, delay-ms will be a couple of +\ milliseconds, a bit longer than the interval between successive PS/2 bytes. +\ Just after receiving a packet, it will be a bit more than 10 mS, since +\ another packet is likely to follow (the standard mouse packet rate is +\ 100 packets/second). When idle, the delay is 56 milliseconds, just +\ longer than a worst-case PC tick interval, but short enough that a +\ human won't notice a delay. +\ This strikes a good balance between responsive, accurate mouse tracking +\ and minimal polling overhead. + +: adaptive-poll? ( -- false delay-ms | x y buttons true delay-ms ) + begin get-data? while ( byte ) + \ If we have a packet, retry soon because there is likely to be another + \ right on its heels. The packet generation rate is 100/sec, but some + \ could be queued up, so we don't wait a full 10 ms + stream-event ?dup if poll-delay exit then + repeat ( ) + + ?reframe + false poll-delay ( false delay-ms ) + + dup 2 = if 9 else d# 32 then to poll-delay ( false delay-ms ) +; +0 [if] +: adaptive-track ( -- ) + stream-mode + begin + adaptive-poll? >r if ( x y stat r: next-poll ) + (cr . 4 .r 4 .r ( r: next-poll ) + then ( r: next-poll ) + r> ms ( ) + key? until ( ) + stream-off +; +: stream-track ( -- ) + stream-mode + begin + stream-poll? if ( x y stat ) + (cr . 4 .r 4 .r ( ) + then ( ) + 5 ms ( ) + key? until ( ) + stream-off +; + +[then] + : poll ( -- x y buttons ) clear-queue
openfirmware@openfirmware.info