Jump to content
IGNORED

PS2 mouse on TI99 ;)


rocky007

Recommended Posts

At least i started this project. I thought about it since my Kaboom! conversion.

 

Today i made a first working prototype using a Arduino Uno ( very early beta ;) )

 

Two modes are included ( only mode 1 on this video ) :

 

Mode 1 : simply converting mouse signal to simple joystick signal. It gives some compatibility with games or programs like TI-Artist and could be used in TI BASIC / XB.

 

Mode 2 : the advanced version transfert 12 bits datas through joystick port 2 giving accurate mouse velocity. ( X on 4 bits, Y on 4 bits , left / right buttons ) . This version requires a special driver ( could be done in MLC, Ti Forth, assembler or compiled basic ).

 

C++ , XBasic, ASM , MLC sources codes & schematics coming soon ;)

 

http://www.youtube.com/watch?v=4mMbGm99mO0&feature=youtu.be

http://www.youtube.com/watch?v=yONq3uKtioY&feature=youtu.be

Edited by rocky007
  • Like 6
Link to comment
Share on other sites

At least i started this project. I thought about it since my Kaboom! conversion.

 

Today i made a first working prototype using a Arduino Uno ( very early beta ;) )

 

Two modes are included ( only mode 1 on this video ) :

 

Mode 1 : simply converting mouse signal to simple joystick signal. It gives some compatibility with games or programs like TI-Artist and could be used in TI BASIC / XB.

 

Mode 2 : the advanced version transfert 12 bits datas through joystick port 2 giving accurate mouse velocity. ( X on 4 bits, Y on 4 bits , left / right buttons ) . This version requires a special driver ( could be done in MLC, Ti Forth, assembler or compiled basic ).

 

C++ , XBasic, ASM , MLC sources codes & schematics coming soon ;)

 

http://www.youtube.com/watch?v=4mMbGm99mO0&feature=youtu.be

http://www.youtube.com/watch?v=yONq3uKtioY&feature=youtu.be

 

 

Now that is really cool, new and potentially very useful ! Great job.

 

Why are you not going to pass all 3 or 4 bytes of the PS/2 data ? Just curious I am not criticizing ;-).....

Link to comment
Share on other sites

Very cool so I wondered if RXB could access this using my CALL IO(type,bits,CRUbase,variable) ! type=2,bits=8,CRUbase=joystick address/2,variable=bit value)

Using this command you could read the CRU bits from the Input/Output chip and use the values.

 

Here is an example that reads all the CRU lines of the Keyboard and shows them working:

100 DISPLAY AT(1,1)ERASE ALL:"THIS PROGRAM CHECKS FOR	 UNUSUAL KEYS BEING PRESSED, EVEN IF MORE THAN FOUR KEYS ARE BEING PRESSED AT ONCE"
110 CALL IO(2,16,3,A,B) :: IF A=18 AND B=255 THEN 110 ELSE CALL HPUT(24,3,RPT$(" ",30),24,24,STR$(A)&" "&STR$(B))
120 IF A=146 THEN CALL HPUT(24,3,"FUNCTION KEY")ELSE IF B=191 THEN CALL HPUT(24,3,"CONTROL KEY")ELSE IF B=223 THEN CALL HPUT(24,3,"SHIFT KEY")
130 IF B=251 THEN CALL HPUT(24,3,"ENTER KEY")ELSE IF B=253 THEN CALL HPUT(24,3,"SPACE BAR")ELSE IF B=254 THEN CALL HPUT(24,3,"PLUS/EQUAL KEY")
140 GOTO 110

 

Would not be hard to modify for reading the joystick ports and using the command. For example you can put more then one CALL IO in one command up to check 10 CRU lines at one time in one command.

 

Here is a video I made of the demo:

 

http://www.youtube.com/watch?v=sHTHDngNMcE

 

Rich

Edited by RXB
  • Like 1
Link to comment
Share on other sites

Now that is really cool, new and potentially very useful ! Great job.

 

Why are you not going to pass all 3 or 4 bytes of the PS/2 data ? Just curious I am not criticizing ;-).....

 

for two reasons, but i maybe wrong :

 

1st byte of PS2 data give the buttons status and, i suppose, moving status. From this, i keep only 2 bits ( the buttons )

2nd & 3rd bytes are the velocity X and Y. As the TI resolution is only 256*192, i think only 4 bits resolution is enough

 

the second reason is the transfert : my protocol use 4 directions. As i can't have a perfect timing, i need to simulate a CLK with one direction and RTS with another direction.

 

in my case : RTS : up , CLK : down, LEFT : bit high, RIGHt : bit low

 

Data are packed like this : RTS, 1 bit left button, 1 bit right button, 4 bits X , 1 bit X sign, 4 bits Y, 1 bit Y sign

so, before each bit, i have to sent the CLK, so in total i have 25 pulses to sent to TI99 for only 12 bits.

Sending the 3 bytes would requires 49 pulses. 25 is already heavy...49 seems really too much to have a quick response in games by exemple...but i didn't yet made my final tests about that.

 

 

Very cool so I wondered if RXB could access this using my CALL IO(type,bits,CRUbase,variable) ! type=2,bits=8,CRUbase=joystick address/2,variable=bit value)

Using this command you could read the CRU bits from the Input/Output chip and use the values.

 

thank you very much for the video. That's a very interesting suggestion, i thought about the possibility to sent the data in other way, very quickly :

 

Joystick # 1 : using the four directions + fire gives me 5 bits for X

Joystick # 2 : same, but for Y.

 

like this, i can access anytime to X and Y, with sync at all. But need to reduce resolution to 3 bits + 1 for sign

 

In basic, it won't work using JOYST, because it can't read both X -4 and X +4 in same time. I'm not sure if this "selection" is made by software or hardware. But i hope that i could be possible on low level. I'll make some tests with RXB, it could be very interesting.

 

Another option could be also the CS1 port.

Edited by rocky007
Link to comment
Share on other sites

for two reasons, but i maybe wrong :

 

1st byte of PS2 data give the buttons status and, i suppose, moving status. From this, i keep only 2 bits ( the buttons )

2nd & 3rd bytes are the velocity X and Y. As the TI resolution is only 256*192, i think only 4 bits resolution is enough

 

the second reason is the transfert : my protocol use 4 directions. As i can't have a perfect timing, i need to simulate a CLK with one direction and RTS with another direction.

 

in my case : RTS : up , CLK : down, LEFT : bit high, RIGHt : bit low

 

Data are packed like this : RTS, 1 bit left button, 1 bit right button, 4 bits X , 1 bit X sign, 4 bits Y, 1 bit Y sign

so, before each bit, i have to sent the CLK, so in total i have 25 pulses to sent to TI99 for only 12 bits.

Sending the 3 bytes would requires 49 pulses. 25 is already heavy...49 seems really too much to have a quick response in games by exemple...but i didn't yet made my final tests about that.

 

 

 

 

thank you very much for the video. That's a very interesting suggestion, i thought about the possibility to sent the data in other way, very quickly :

 

Joystick # 1 : using the four directions + fire gives me 5 bits for X

Joystick # 2 : same, but for Y.

 

like this, i can access anytime to X and Y, with sync at all. But need to reduce resolution to 3 bits + 1 for sign

 

In basic, it won't work using JOYST, because it can't read both X -4 and X +4 in same time. I'm not sure if this "selection" is made by software or hardware. But i hope that i could be possible on low level. I'll make some tests with RXB, it could be very interesting.

 

Another option could be also the CS1 port.

 

 

That's good thinking. No way in the world you should need 8 bits of velocity for 256 pixels. I guess worst cast scenario it would require 16 VDP ticks (~1/4 second) to traverse the screen. +1

 

I have been tinkering with a PS/2 mouse interface as well (design only) and since you have progressed much further than I let me ask you a question that you or someone else will know. Since the PS/2 interface is open collector the BUSS must be driven high by something. Is it the mouse that energizes the BUSS through pull ups to 5V or does the host do that ? Hopefully it is the host as the TI Uc I chose to use isn't TTL proof and cannot handle more than 3V input safely.

 

Again, Neat project and it seems well done.

 

Marcus...

Link to comment
Share on other sites

I have been tinkering with a PS/2 mouse interface as well (design only) and since you have progressed much further than I let me ask you a question that you or someone else will know. Since the PS/2 interface is open collector the BUSS must be driven high by something. Is it the mouse that energizes the BUSS through pull ups to 5V or does the host do that ? Hopefully it is the host as the TI Uc I chose to use isn't TTL proof and cannot handle more than 3V input safely.

 

Again, Neat project and it seems well done.

 

Marcus...

In my case mouse is 5V powered by the host, so i hadn't to think about a conversion between 3V and 5V.

Conversion could be a problem if you want to sent command to the mouse but i think i couldn't be a problem if you only receive data.

In that case, you can simply use pullup. For bidirectional, you have to use level shifter ICs.

Link to comment
Share on other sites

In my case mouse is 5V powered by the host, so i hadn't to think about a conversion between 3V and 5V.

Conversion could be a problem if you want to sent command to the mouse but i think i couldn't be a problem if you only receive data.

In that case, you can simply use pullup. For bidirectional, you have to use level shifter ICs.

 

Sorry I don't know about Audrinos so I'll ask... I'm guessing it is 5V and TTL compatible on I/O pins and you have the clock and data lines from the mouse connected directly to the Uc ? If this is the case then It sounds like the Mouse is responsible for keeping the buss high.

Link to comment
Share on other sites

Sorry I don't know about Audrinos so I'll ask... I'm guessing it is 5V and TTL compatible on I/O pins and you have the clock and data lines from the mouse connected directly to the Uc ?

 

arduino have 2 pins for TTL but it's not used in this case. Here, it uses only 2 simple 5V digital I/O pins.

 

Here it is the code for PS/2 protocol from arduino librairy. It details you precisely the exchange with pins status.

 

 

void gohi(int pin)

{

pinMode(pin, INPUT);

digitalWrite(pin, HIGH);

}

 

void golo(int pin)

{

pinMode(pin, OUTPUT);

digitalWrite(pin, LOW);

}

 

void mouse_write(char data)

{

char i;

char parity = 1;

 

/* put pins in output mode */

gohi(MDATA);

gohi(MCLK);

delayMicroseconds(300);

golo(MCLK);

delayMicroseconds(300);

golo(MDATA);

delayMicroseconds(10);

/* start bit */

gohi(MCLK);

/* wait for mouse to take control of clock); */

while (digitalRead(MCLK) == HIGH)

;

/* clock is low, and we are clear to send data */

for (i=0; i < 8; i++) {

if (data & 0x01) {

gohi(MDATA);

}

else {

golo(MDATA);

}

/* wait for clock cycle */

while (digitalRead(MCLK) == LOW)

;

while (digitalRead(MCLK) == HIGH)

;

parity = parity ^ (data & 0x01);

data = data >> 1;

}

/* parity */

if (parity) {

gohi(MDATA);

}

else {

golo(MDATA);

}

while (digitalRead(MCLK) == LOW)

;

while (digitalRead(MCLK) == HIGH)

;

/* stop bit */

gohi(MDATA);

delayMicroseconds(50);

while (digitalRead(MCLK) == HIGH)

;

/* wait for mouse to switch modes */

while ((digitalRead(MCLK) == LOW) || (digitalRead(MDATA) == LOW))

;

/* put a hold on the incoming data. */

golo(MCLK);

 

}

 

/*

* Get a byte of data from the mouse

*/

char mouse_read(void)

{

char data = 0x00;

int i;

char bit = 0x01;

 

/* start the clock */

gohi(MCLK);

gohi(MDATA);

delayMicroseconds(50);

while (digitalRead(MCLK) == HIGH)

;

delayMicroseconds(5); /* not sure why */

while (digitalRead(MCLK) == LOW) /* eat start bit */

;

for (i=0; i < 8; i++) {

while (digitalRead(MCLK) == HIGH)

;

if (digitalRead(MDATA) == HIGH) {

data = data | bit;

}

while (digitalRead(MCLK) == LOW)

;

bit = bit << 1;

}

/* eat parity bit, which we ignore */

while (digitalRead(MCLK) == HIGH)

;

while (digitalRead(MCLK) == LOW)

;

/* eat stop bit */

while (digitalRead(MCLK) == HIGH)

;

while (digitalRead(MCLK) == LOW)

;

 

/* put a hold on the incoming data. */

golo(MCLK);

 

return data;

}

 

void mouse_init()

{

gohi(MCLK);

gohi(MDATA);

// Sending reset to mouse

mouse_write(0xff);

mouse_read(); /* ack byte */

// Read ack byte1

mouse_read(); /* blank */

mouse_read(); /* blank */

// Sending remote mode code

mouse_write(0xf0); /* remote mode */

mouse_read(); /* ack */

// Read ack byte2\

delayMicroseconds(100);

}

Edited by rocky007
Link to comment
Share on other sites

arduino have 2 pins for TTL but it's not used in this case. Here, it uses only 2 simple 5V digital I/O pins.

 

Here it is the code for PS/2 protocol from arduino librairy. It details you precisely the exchange with pins status.

 

 

void gohi(int pin)

{

pinMode(pin, INPUT);

digitalWrite(pin, HIGH);

}

 

 

 

Thanks but that looks like 'C' and I don't know 'C' from 'D' or 'E'. The Uc I am using has an assembly language remarkably similar to 9900 (at least in mnemonics, addressing and syntax.) So I will be using that.

 

I'm still unsure where the HIGH signal is generated so let me ask you this. Are you using the pull ups in the Uc's pins to create the high condition and using the mouses open collector to create the low ? Or are the I/O pins only detecting high or low ?

Link to comment
Share on other sites

the Uc have 20K pullup inside, simply activated by command digitalWrite(pin, HIGH or LOW)

 

Thanks Rocky, that's the info I was wondering about. So for the record, the buss heat is generated outside of the peripherals (whatever they may be....)

Link to comment
Share on other sites

  • 3 weeks later...

Here it is !!! this new version works very very well... i used finally a totally different system :

 

I'm using all directions of joystick #1 and #2 to code the X,Y mouse movements. I made it so easy that it could be used even in TI-BASIC !

( but i recommend compilation for smooth and fast moves )

 

Here it is my method :

 

10 CALL JOYST(1,X1,Y1)

20 CALL JOYST(1,X2,Y2)

 

IF X1=-4 AND Y1=0 THEN Xspeed=1

IF X1=-4 AND Y1=4 THEN Xspeed=2

IF X1=0 AND Y1=4 THEN Xspeed=4

IF X1=4 AND Y1=4 THEN Xspeed=8

IF X1=4 AND Y1=0 THEN Xspeed=-1

IF X1=4 AND Y1=-4 THEN Xspeed=-2

IF X1=0 AND Y1=-4 THEN Xspeed=-4

IF X1=-4 AND Y1=-4 THEN Xspeed=-8

 

IF X2=-4 AND Y2=0 THEN Yspeed=1

IF X2=-4 AND Y2=4 THEN Yspeed=2

IF X2=0 AND Y2=4 THEN Yspeed=4

IF X2=4 AND Y2=4 THEN Yspeed=8

IF X2=4 AND Y2=0 THEN Yspeed=-1

IF X2=4 AND Y2=-4 THEN Yspeed=-2

IF X2=0 AND Y2=-4 THEN Yspeed=-4

IF X2=-4 AND Y2=-4 THEN Yspeed=-8

 

CALL KEY(1,A,K1)

CALL KEY(2,A,K2)

 

K1 -> mouse left button

K2 -> mouse right button

 

An simple TI extended basic driver could be this :

 

10 CALL CLEAR

20 DIM A(10),B(10),S(10)

30 A(1)=0 :: A(5)=1 :: A(9)=2

40 B(1)=0 :: B(5)=4 :: B(9)=8

45 FOR I=0 TO 10::READ S(I):: NEXT I

50 CALL JOYST(1,X1,Y1) :: CALL JOYST(2,X2,Y2)

60 X1=X1+5 :: Y1=Y1+5 :: X2=X2+5 :: Y2=Y2+5

70 PRINT "X :";S(A(X1)+B(Y1));"Y :";S(A(X2)+B(Y2))

80 GOTO 50

100 DATA -8,-4,-2,0,1,0,-1,0,2,4,8

 

 

This program could be ported easily in any language.

After tests, this speed table is enough accurate for 1 pixel precision moves and enough fast for big dynamic moves.

 

You can now integrate mouse in any of your program ;)

 

http://youtu.be/XApW0SCS_gA

 

and in Extended Basic ( not compiled ) :

 

Edited by rocky007
Link to comment
Share on other sites

RXB shortens and speeds this up slightly:

10 CALL CLEAR

20 DIM A(10),B(10),S(10)

30 A(1)=0 :: A(5)=1 :: A(9)=2

40 B(1)=0 :: B(5)=4 :: B(9)=8

45 FOR I=0 TO 10::READ S(I):: NEXT I

50 CALL JOYST(1,X1,Y1,2,X2,Y2)

60 X1=X1+5 :: Y1=Y1+5 :: X2=X2+5 :: Y2=Y2+5

70 PRINT "X :";S(A(X1)+B(Y1));"Y :";S(A(X2)+B(Y2))

80 GOTO 50

100 DATA -8,-4,-2,0,1,0,-1,0,2,4,8

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...