Skip to content

Instantly share code, notes, and snippets.

@Quantum-cross
Last active September 16, 2019 02:51
Show Gist options
  • Save Quantum-cross/892be82bd60753944225ff22bf564737 to your computer and use it in GitHub Desktop.
Save Quantum-cross/892be82bd60753944225ff22bf564737 to your computer and use it in GitHub Desktop.
Converts PS/2 mouse to be used on Amiga!
// I've tested this with an arduino UNO and an arduino NANO
// With the nano I had to program externally, maybe the bootloader interferes?
// With an optical mouse you probably need to disconnect power from the amiga pin 7
// and power externally as the mouse port can only supply 50 mA
#include <ps2.h>
// grab the ps2 library here: https://playground.arduino.cc/uploads/ComponentLib/ps2.zip
// You may need to change a line in file "ps2.h"
// from '#include "WProgram.h"'
// to '#include "Arduino.h"'
#include <avr/wdt.h>
// Mouse inputs from PS/2
// Can also use "USB" mice if they also support PS/2 protocol
#define CLK 6 // USB Green
#define DAT 5 // USB White
// Amiga Pin
#define XA 8 // 4
#define XB 9 // 2
#define YA 10 // 1
#define YB 11 // 3
// If any axis is reversed then swap A/B
#define LB 2 // 6
#define MB 3 // 5
#define RB 4 // 9
// See code below for explanation of this.
// TL;DR set this as low as you can without experiencing
// erratic cursor motion with fast mouse movements
#define DELAY_US 151
PS2 mouse(CLK, DAT);
void setup()
{
// Serial.begin(19200);
// Set outputs
pinMode(XA, OUTPUT);
pinMode(XB, OUTPUT);
pinMode(YA, OUTPUT);
pinMode(YB, OUTPUT);
pinMode(LB, OUTPUT);
pinMode(MB, OUTPUT);
pinMode(RB, OUTPUT);
digitalWrite(LB, 1);
digitalWrite(MB, 1);
digitalWrite(RB, 1);
// Enable WDT, in case mouse disconnects
wdt_enable(WDTO_500MS);
// Init mouse
mouse.write(0xff); // reset
mouse.read(); // ack byte
mouse.read(); // blank */
mouse.read(); // blank */
mouse.write(0xf0); // remote mode
mouse.read(); // ack
delayMicroseconds(100);
wdt_reset();
}
// To hold current state of gray codes
byte xstate = 0;
byte ystate = 0;
void loop()
{
char mstat;
unsigned char mx;
unsigned char my;
char left;
char right;
char middle;
char xsign;
char ysign;
char xover;
char yover;
// Get mouse data
mouse.write(0xeb); // give me data!
mouse.read(); // ignore ack
mstat = mouse.read();
mx = mouse.read();
my = mouse.read();
// Parse state byte
// Button states
left = !( mstat &0b00000001);
right = !((mstat>>1)&0b00000001);
middle = !((mstat>>2)&0b00000001);
// Sign bits
xsign = (mstat>>4)&0b00000001 ;
ysign = (mstat>>5)&0b00000001 ;
// Overflow bits (not handled)
xover = (mstat>>6)&0b00000001 ;
yover = (mstat>>7)&0b00000001 ;
// If negative, fix the two's complement
if (xsign){
mx = 256-mx;
}
if (ysign){
my = 256-my;
}
// Write button pins
digitalWrite(LB, left);
digitalWrite(MB, middle);
digitalWrite(RB, right);
// Move pointer
move(mx, xsign, my, ysign);
// if(xsign) Serial.print("-");
// Serial.print(mx, DEC);
// Serial.println();
// Keep watchdog happy
wdt_reset();
}
// Move the cursor x and y pixels
void move(unsigned char x, bool left, unsigned char y, bool down){
while ((x > 0)||(y > 0)){
if (x > 0){
left ? move_left_1():move_right_1();
x--;
}
if (y > 0){
down ? move_down_1():move_up_1();
y--;
}
// We need to put a delay here, we can't strobe the X/Y pins
// too fast or the amiga may miss parts of the grey code.
// If this happens the mouse will skip and go backwards.
// The way gray code works is if any bit flip is missed it is
// impossible to know which direction the mouse moved.
// delayMicroseconds(149); // This worked on my Arduino UNO
delayMicroseconds(DELAY_US); // 150 uS worked on my Arudino Nano
// Set this as low as you can without getting erratic cursor movements
// when moving the mouse quickly.
// If the delay is removed, then the mouse will be much more responsive
// but will also skip and go backwards with fast movements
// Maybe this is dependent on the noise on the X/Y lines?
}
}
void move_left_1(){
set_gray(xstate, false, XA, XB);
xstate--;
xstate %= 4;
}
void move_right_1(){
set_gray(xstate, true, XA, XB);
xstate = (xstate+1)%4;
}
void move_down_1(){
set_gray(ystate, false, YA, YB);
ystate--;
ystate %= 4;
}
void move_up_1(){
set_gray(ystate, true, YA, YB);
ystate = (ystate+1)%4;
}
// Probably not the best way to do this.
void set_gray(int state, bool up, int a, int b){
if(up){
switch (state){
case 0:
digitalWrite(b, 1);
break;
case 1:
digitalWrite(a, 1);
break;
case 2:
digitalWrite(b, 0);
break;
case 3:
digitalWrite(a, 0);
break;
default:
break;
}
}
else{
switch (state){
case 0:
digitalWrite(a, 1);
break;
case 1:
digitalWrite(b, 0);
break;
case 2:
digitalWrite(a, 0);
break;
case 3:
digitalWrite(b, 1);
default:
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment