Use ~10€ to connect modern mouse to MSX

Page 1/18
| 2 | 3 | 4 | 5 | 6

By NYYRIKKI

Enlighted (4924)

NYYRIKKI's picture

27-10-2013, 18:32

ℋℯℓℓℴ,

Now this is DIY again, but very easy one. This requires only minimal to none soldering skills / other hardware experience.

Required hardware:
- Arduino (I used UNO R3 that costs about 7-8€ including required USB-cable for programming)
- PS/2 or USB-connector (look nearby dumpster)
- Old PS/2 or USB-mouse (-"-)
- Joystick connector & cables

Why? Because MSX-mice are getting rare & expensive and this is practically only way to get modern optical mouse for MSX. Compared to native MSX-mice this has also some advantages like possibility to adjust the resolution on the fly.
Running Naked in a Field of Flowers

See here picture of device put together:

Here is software & all the needed instructions:


    /////////////////////////////
   //  PS/2-mouse to MSX v1.0 //
  //  Made By: NYYRIKKI 2013 //
 ////////////////////////////

/*
   Usage:
   Press reset = Mouse mode
   Press reset & hold right mousebutton down = Joystick emulation
   Press reset & hold left mousebutton down = Mouse + Joystick emulation *
   
   If you have mouse with a scrolling wheel (optional) you can use the
   wheel to adjust speed of mouse and/or sensitivity of joystick.
   
   If status LED does NOT blink check your PS2-mouse connection and press reset.

   (*) Please note: This mode might cause problems with some of the existing software.
//////////////////////////////////////////////////////////////////////////////////*/

  // As of Arduino 1.0 ps2.zip should be unpacked into arduino/libraries.
  // In ps2.h replace "WProgram.h" with "Arduino.h".
 
  #include 

  /////////////////////////////////
 // HW Connection instructions: //
/////////////////////////////////

// PS/2 connector: (Female)   USB-connetor: (Female)
//
//           1 2                    ---------
//          3   4                  | 4 3 2 1 |
//           5|6                    -=======-
//
//        Mini-DIN-6F                 USB-AF
//
//            (Both looking from outside)
//
// Connecting PS2: 
// pin 1 -> DATA
// pin 3 -> GND
// pin 4 -> +5V
// pin 5 -> CLK

// Define Arduino pins used in format: CLK , DATA

  PS2 mouse(11, 10);  
  
// If you use USB-connector, connect:
// pin 1 -> +5V
// pin 2 -> DATA
// pin 3 -> CLK 
// pin 4 -> GND
//
// Usually USB-mice that are produced before 2010 support PS/2 protocol out of the box.
//
// Connecting Joystick:
//
//  MSX-connector : Arduino pin
//     (DB9F)
  #define JoyPin1 2
  #define JoyPin2 3
  #define JoyPin3 4
  #define JoyPin4 5
  //      JoyPin5 +5V (N/C or power)
  #define JoyPin6 6
  #define JoyPin7 7
  #define JoyPin8 8
  //      JoyPin9 GND (Connect to Arduino GND)
  
  #define InfoPin 13 // Status LED

///////////////////////////////////////////////////////////////////////////////

// Variables
  char rx=0,ry=0,rz=0,x=0,y=0,mx=0,my=0,jx=0,jy=0,scale=15,MouseID=0,EmuMode=0;
  char olimit=60, ilimit=50, solimit=0, silimit=0, mstat=0, StatCnt=0;
  long time; // No C

void mouse_init()
{
  mouse.write(0xff);   // reset
  mouse.read();        // ack byte
  mouse.read();        // Self-test passed
  mouse.read();        // Mouse ID
  mouse.write(0xf0);   // remote mode
  mouse.read();        // ack
  
  mouse.write(0xeb);   // give me data!
  mouse.read();        // ignore ack
 
  EmuMode = mouse.read() & 3; // Read Emulation mode from buttons
  if (EmuMode==3) EmuMode=0;
 
  mouse.read();        // ignore X
  mouse.read();        // ignore Y
  
  mouse.write(0xf3);   // Set sample rate
  mouse.read();        // ack
  mouse.write(200);    // Max sample rate
  mouse.read();        // ack  
  
  mouse.write(0xf3);   // Set sample rate
  mouse.read();        // ack
  mouse.write(100);
  mouse.read();        // ack  
  
  mouse.write(0xf3);   // Set sample rate
  mouse.read();        // ack
  mouse.write(80);
  mouse.read();        // ack  
  
  mouse.write(0xf2);   // Get device ID
  mouse.read();        // ack
  MouseID = mouse.read();   // Mouse ID
  
  mouse.write(0xf3);   // Set sample rate
  mouse.read();        // ack
  mouse.write(200);    // Max sample rate
  mouse.read();        // ack  
  
  mouse.write(0xe8);   // Set Resolution
  mouse.read();        // ack
  mouse.write(2);      // 4 counts/mm
  mouse.read();        // ack  
  
  delayMicroseconds(100);
}

void setup()
{  
  digitalWrite(JoyPin1,LOW);
  digitalWrite(JoyPin2,LOW);
  digitalWrite(JoyPin3,LOW);
  digitalWrite(JoyPin4,LOW);
  digitalWrite(JoyPin6,LOW);
  digitalWrite(JoyPin7,LOW);

  digitalWrite(InfoPin,LOW);
  pinMode(InfoPin,OUTPUT);
  
  Serial.begin(9600);
  Serial.print("\n\nPS/2-mouse to MSX-mouse converter for Arduino\n");
  Serial.print("---------------------------------------------\n");
  Serial.print("Made By: NYYRIKKI 2013\n\n");
  Serial.print("Initializing PS/2 mouse...");
  mouse_init();
  Serial.print("Ok\n\nI'm a ");
  switch (EmuMode) {
    case 0: Serial.print ("mouse!");
    break;
    case 1: Serial.print ("mouse & joystick hybrid!");
    break;
    case 2: Serial.print("joystick!");
    break;
  }
  Serial.print("\n");
}

void loop()
{
  StatCnt++;
  if (StatCnt==50) StatCnt=0;
  
  mouse.write(0xeb);    // give me data!
  mouse.read();         // ignore ack
  mstat = mouse.read(); // Read buttons

  rx = mouse.read();
  ry = mouse.read();  

  if (MouseID==3) {
    rz=mouse.read();
    scale=scale-rz;
    if (scale<5) scale=5;
    if (scale>25) scale=25;
  }
 
  if(mstat&1) pinMode(JoyPin6,OUTPUT); else pinMode(JoyPin6,INPUT);
  if(mstat&2) pinMode(JoyPin7,OUTPUT); else pinMode(JoyPin7,INPUT);
  
  if (EmuMode==0 | EmuMode==1) {  // Mouse emulation 
  
    mx = mx-rx;
    my = my+ry;
    x=mx*(scale)/20;
    y=my*(scale)/20;

    time=millis()+40;
    
    sendMSX(x);  //-X
    sendMSX(y);  //-Y
    if (millis()time) break;};
    JoyHigh(); 
 }

  if (EmuMode==2 | EmuMode==1){   // Joystick emulation

    jy=jy+ry;
    jx=jx-rx;
    if (StatCnt<40) digitalWrite(InfoPin,LOW); else digitalWrite(InfoPin,HIGH);
    if (digitalRead(JoyPin8)==LOW) {
      solimit=olimit*(scale)/20;
      silimit=ilimit*(scale)/20;

      if (jy>solimit) jy=solimit;
      if (jy<-solimit) jy=-solimit;
      if (jx>solimit) jx=solimit;
      if (jx<-solimit) jx=-solimit;
  
      if (jy>silimit)  pinMode(JoyPin1,OUTPUT); else pinMode(JoyPin1,INPUT);
      if (jy<-silimit) pinMode(JoyPin2,OUTPUT); else pinMode(JoyPin2,INPUT);
      if (jx>silimit)  pinMode(JoyPin3,OUTPUT); else pinMode(JoyPin3,INPUT);
      if (jx<-silimit) pinMode(JoyPin4,OUTPUT); else pinMode(JoyPin4,INPUT);
    } else JoyHigh();
  }
}

void sendMSX(char c)
{
    while (digitalRead(JoyPin8)==LOW) {if (millis()>time) return;};
    if(c&128) pinMode(JoyPin4,INPUT); else pinMode(JoyPin4,OUTPUT);
    if(c&64)  pinMode(JoyPin3,INPUT); else pinMode(JoyPin3,OUTPUT);
    if(c&32)  pinMode(JoyPin2,INPUT); else pinMode(JoyPin2,OUTPUT);
    if(c&16)  pinMode(JoyPin1,INPUT); else pinMode(JoyPin1,OUTPUT);
    while (digitalRead(JoyPin8)==HIGH) {if (millis()>time) return;};
    if(c&8)   pinMode(JoyPin4,INPUT); else pinMode(JoyPin4,OUTPUT);
    if(c&4)   pinMode(JoyPin3,INPUT); else pinMode(JoyPin3,OUTPUT);
    if(c&2)   pinMode(JoyPin2,INPUT); else pinMode(JoyPin2,OUTPUT);
    if(c&1)   pinMode(JoyPin1,INPUT); else pinMode(JoyPin1,OUTPUT);
}
      
void JoyHigh()
{
    pinMode(JoyPin1,INPUT);
    pinMode(JoyPin2,INPUT);
    pinMode(JoyPin3,INPUT);
    pinMode(JoyPin4,INPUT);
}
Login or register to post comments

By AxelF

Champion (318)

AxelF's picture

27-10-2013, 19:37

WOW this is awsome ..

It would be nice to make this project a standalone (without the UNO).
The ATmega168 needs very few components to run, and can be powered by the MSX Gameport.

By NYYRIKKI

Enlighted (4924)

NYYRIKKI's picture

27-10-2013, 20:31

@AxelF: The code should run on ATmega168 without any modifications, so if you like soldering, then go ahead. That is so small chip, that you can even mount it inside a mouse if you like. Smile

BTW the codebox seems to cut off parts of the code again, so better to download it instead... (Click here to download.)

By rogermm

Master (130)

rogermm's picture

27-10-2013, 21:23

We have plans to use the ARM and USB host interface on MSXARM(http://187.33.0.151/MsxArm/MsxArm) to connect modern USB mouse on MSX. Demos source code (using USB mouse) exists(like Arduino) for MSXARM ARM chip.
We will need to work on integration with the MSX(like you do). The rule in the project is: less hardware + more functionality(devices) = cheap & less complexity. Anyways this is a interesting project

By sd_snatcher

Prophet (2734)

sd_snatcher's picture

27-10-2013, 22:40

Excellent initiative, NYYRIKKI!

Here in Brazil we use the MSXpro/Anikun adapter. Do you know if your code would run in the 16F628A PIC it uses?

Some suggestions for your code:

1) Use clipping when doing math on the offsets. This allows the current optical mice, that have a much higher resolution than the original MSX mice, to be supported properly

2) Add support for the MSX-Trackball protocol too. This would allow the HAL software that only support trackballs also to be supported.

By NYYRIKKI

Enlighted (4924)

NYYRIKKI's picture

27-10-2013, 22:58

sd_snatcher wrote:

Here in Brazil we use the MSXpro/Anikun adapter. Do you know if your code would run in the 16F628A PIC it uses?

No, that is totally different thing.

Anyway very good improvement ideas and quite easy to implement...

By NYYRIKKI

Enlighted (4924)

NYYRIKKI's picture

28-10-2013, 06:41

If you like to save some money/space and build this without the Arduino UNO R3, then I think this would be quite a good option... Saves you also some money as this costs < 4€

By WORP3

Paladin (787)

WORP3's picture

28-10-2013, 08:49

It should even be possible to place it all inside a DB9 connector. You know something like this:

Taking a very small AVR chip and run it directly on the MSX 5V and on it's internal oscillator should make it very small.

By Jupp3

Resident (41)

Jupp3's picture

28-10-2013, 19:49

How about adding a male DB9 connector for joystick, and make it also work as mouse / joystick switcher? Way more popular on Amigas (where mouses are more widely used / needed), usually they work so, that whenever you click joystick button, it goes to joystick mode, and on mouse button to mouse mode. I guess there should be a safe way to do that in hardware on MSX aswell.

Of course this could also be updated to work as an adapter for USB joysticks, although I guess most users prefer proper atari-style sticks. Only benefit would be that it's easier to find one with >1 button Smile

Only missing emulation of C64 and Amiga mice, and we would have an Individual Computers Micromys killer. I bet the casing would look better in any case Tongue

(Okay, the latest version doesn't look quite THAT bad...)

Is the joystick mode like Commodore 1350 btw? (basically movement speed determines how often certain direction gets triggered)

By NYYRIKKI

Enlighted (4924)

NYYRIKKI's picture

29-10-2013, 15:46

Jupp3 wrote:

How about adding a male DB9 connector for joystick, and make it also work as mouse / joystick switcher?

That is very easy to do and you don't even need to add switch. It seems that mouse & joystick can live at the same time at the same port. (See source) You can connect joystick buttons (pins 6 & 7) in paraller with arduino and select 4 Arduino pins for directional input (joystick pins 1-4) Then modify the joystick input routine to pass the pin statuses trough. Please note how ever that current code does not work at all if PS/2 mouse is not connected.

Quote:

Is the joystick mode like Commodore 1350 btw? (basically movement speed determines how often certain direction gets triggered)

No, that would not work very well on most games. The joystick emulation has just virtual box (you can alter the box size with wheel) where you can move the invisible cursor. When you are near the edge of a box the direction gets triggered and it stays triggered until you move the mouse cursor away from the edge.

By Jupp3

Resident (41)

Jupp3's picture

30-10-2013, 14:27

Quote:

No, that would not work very well on most games.

I know. The fact is, though, there's NO way to do it properly. Joystick games are meant to be played with joysticks. It works the best on games, where the movement seems to be a bit too fast on joystick normally.

It works somehow, whenever you can change the movement speed, and disable any "acceleration", if any. As you probably know, next to no games support doing that, but many programs do (some of which support "real" mouse protocol anyway)

Still, that's how Commodore did that with first mouse (1350), on the next one (1351) it was already "secondary function".

Anyway, need to test that code on Roland S-330 some day Smile

Page 1/18
| 2 | 3 | 4 | 5 | 6
My MSX profile