USB to quadrature encoder so you use modern USB mice on the Amiga.

Dependencies:   USBHOST

Introduction

This project is devised so you can attach a mouse (and/or steam controller) to a classic computer such as an Amiga. Computers of that era use bus mice which just send the pulses from the quadrature encoder wheels on the mouse directly to the computer with out interpretation.

Use

Program a build base on this repository to a STM32 nucleo board (I tested this on a NUCLEO STM32F411 board). You will then need connect the Nucleo board to your computers joystick and mouse ports as follows (if you only use a mouse you won't need a joystick lead :) ). If you use a steam controller the thumb stick and left pad are mapped to the Amiga's joystick port and the right pad and front trigger buttons are mapped to the mouse.

mouse_port_forward(D10) - Amiga Joystick pin 1
mouse_port_back(D11) - Amiga Joystick pin 2
mouse_port_left(D12) - Amiga Joystick pin 3
mouse_port_right(D13) - Amiga Joystick pin 4
mouse_port_left_button(D9) - Amiga Joystick pin 6
GND - Amiga joystick pin 8
mouse_port_right_button(D8) - Amiga Joystick pin 9

game_port_forward(PC_8) - Amiga Joystick pin 1
game_port_back(PC_12) - Amiga Joystick pin 2
game_port_left(PC_10) - Amiga Joystick pin 3
game_port_right(PC_11) - Amiga Joystick pin 4
game_port_left_button(PC_6) - Amiga Joystick pin 6
GND - Amiga joystick pin 8
game_port_right_button(PC_5) - Amiga Joystick pin 9

It is best NOT to use the 5V pin from the Amiga's joystick port to power the nucleo board as the power suppled by the Amiga is limited!

You will also need to attach a USB socket to the nuclea board so you can use the Nucleo's usb OTG support.

(1) 5V     - 5v
(2) PA11 - Data-
(3) PA12 - Data+
(4) GND - GND

According to the usb spec it is required to attach a 15k ohm resistor between D-/+ and ground but it appears the USB host works fine without this.

NOTES:

  • The right touch pad can take a little while before it generates mouse events.
  • I found that the STM USBHost library needed some modifications to correctly work with boot protocol (it needs to call set protocol) and hubs (getSize doesn't report the correct size). This project uses a modified USB host library with fixes for this (they will need a little more work before I can create a pull request).
Committer:
geekylou
Date:
Mon Aug 21 21:23:57 2017 +0000
Revision:
2:095eb20f0d3b
Parent:
1:ab916b5c1a4d
Child:
3:24067f6310fa
Change lines from LEDs to data lines connected to the 9pin D socket.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
geekylou 0:d0c521cb6c90 1 #include "mbed.h"
geekylou 0:d0c521cb6c90 2 #include "USBHostMSD.h"
geekylou 0:d0c521cb6c90 3 #include "USBHostMouse.h"
geekylou 0:d0c521cb6c90 4 #include "USBHostKeyboard.h"
geekylou 1:ab916b5c1a4d 5 #include "USBHostSteamController.h"
geekylou 0:d0c521cb6c90 6 #include "FATFileSystem.h"
geekylou 0:d0c521cb6c90 7 #include <stdlib.h>
geekylou 0:d0c521cb6c90 8
geekylou 1:ab916b5c1a4d 9 int x_cur = 0;
geekylou 1:ab916b5c1a4d 10 int y_cur = 0;
geekylou 0:d0c521cb6c90 11
geekylou 2:095eb20f0d3b 12 DigitalOut led4(D8);
geekylou 2:095eb20f0d3b 13 DigitalOut led(D9);
geekylou 2:095eb20f0d3b 14 DigitalOut led2(D10);
geekylou 2:095eb20f0d3b 15 DigitalOut led3(D12);
geekylou 2:095eb20f0d3b 16
geekylou 2:095eb20f0d3b 17 DigitalOut mouse_port_back(D11);
geekylou 2:095eb20f0d3b 18 DigitalOut mouse_port_left(D13);
geekylou 0:d0c521cb6c90 19
geekylou 0:d0c521cb6c90 20
geekylou 1:ab916b5c1a4d 21 void onMouseEvent(uint8_t buttons, int16_t x, int16_t y, int8_t z) {
geekylou 2:095eb20f0d3b 22 //printf("ME: buttons: %d, x: %d, y: %d, z: %d\r\n", buttons, x, y, z);
geekylou 0:d0c521cb6c90 23
geekylou 2:095eb20f0d3b 24 led = ~buttons & 1;
geekylou 2:095eb20f0d3b 25 led4 = ~buttons & 0x2;
geekylou 0:d0c521cb6c90 26
geekylou 0:d0c521cb6c90 27 while (x != 0 || y != 0)
geekylou 0:d0c521cb6c90 28 {
geekylou 0:d0c521cb6c90 29 if (x >0)
geekylou 0:d0c521cb6c90 30 {
geekylou 0:d0c521cb6c90 31 x--;
geekylou 0:d0c521cb6c90 32 x_cur = (x_cur+1) & 3;
geekylou 0:d0c521cb6c90 33 }
geekylou 0:d0c521cb6c90 34 else if (x < 0)
geekylou 0:d0c521cb6c90 35 {
geekylou 0:d0c521cb6c90 36 x++;
geekylou 0:d0c521cb6c90 37 x_cur = (x_cur-1) & 3;
geekylou 0:d0c521cb6c90 38 }
geekylou 0:d0c521cb6c90 39
geekylou 0:d0c521cb6c90 40 if (y >0)
geekylou 0:d0c521cb6c90 41 {
geekylou 0:d0c521cb6c90 42 y--;
geekylou 0:d0c521cb6c90 43 y_cur = (y_cur+1) & 3;
geekylou 0:d0c521cb6c90 44 }
geekylou 0:d0c521cb6c90 45 else if (y < 0)
geekylou 0:d0c521cb6c90 46 {
geekylou 0:d0c521cb6c90 47 y++;
geekylou 0:d0c521cb6c90 48 y_cur = (y_cur-1) & 3;
geekylou 0:d0c521cb6c90 49 }
geekylou 0:d0c521cb6c90 50
geekylou 0:d0c521cb6c90 51 //printf("x %d y %d\r\n", x, y);
geekylou 0:d0c521cb6c90 52
geekylou 0:d0c521cb6c90 53
geekylou 2:095eb20f0d3b 54 mouse_port_back = ((x_cur + 1)/2) & 1;
geekylou 2:095eb20f0d3b 55 mouse_port_left = (x_cur/2) & 0x1;
geekylou 0:d0c521cb6c90 56
geekylou 2:095eb20f0d3b 57 led2 = ((y_cur + 1)/2) & 1;
geekylou 2:095eb20f0d3b 58 led3 = (y_cur/2) & 0x1;
geekylou 0:d0c521cb6c90 59
geekylou 0:d0c521cb6c90 60 Thread::wait(1);
geekylou 0:d0c521cb6c90 61 }
geekylou 0:d0c521cb6c90 62 }
geekylou 1:ab916b5c1a4d 63
geekylou 1:ab916b5c1a4d 64 void onJSEvent(uint32_t buttons, int8_t x, int8_t y, int16_t x_b, int16_t y_b) {
geekylou 2:095eb20f0d3b 65 printf("buttons: %x, x: %d, y: %d, x_b: %d y_b:%d\r\n", buttons, x, y, x_b, y_b);
geekylou 1:ab916b5c1a4d 66
geekylou 2:095eb20f0d3b 67 led = ~buttons & 1;
geekylou 2:095eb20f0d3b 68 led4 = ~buttons & 0x2;
geekylou 1:ab916b5c1a4d 69
geekylou 2:095eb20f0d3b 70 //Thread::wait(1);
geekylou 1:ab916b5c1a4d 71 }
geekylou 0:d0c521cb6c90 72
geekylou 0:d0c521cb6c90 73 void mouse_task(void const *) {
geekylou 0:d0c521cb6c90 74
geekylou 0:d0c521cb6c90 75 USBHostMouse mouse;
geekylou 0:d0c521cb6c90 76 printf("mouse started\n");
geekylou 0:d0c521cb6c90 77 while(1) {
geekylou 0:d0c521cb6c90 78
geekylou 0:d0c521cb6c90 79 // try to connect a USB mouse
geekylou 0:d0c521cb6c90 80 while(!mouse.connect())
geekylou 0:d0c521cb6c90 81 Thread::wait(500);
geekylou 0:d0c521cb6c90 82
geekylou 0:d0c521cb6c90 83 // when connected, attach handler called on mouse event
geekylou 0:d0c521cb6c90 84 mouse.attachEvent(onMouseEvent);
geekylou 0:d0c521cb6c90 85
geekylou 0:d0c521cb6c90 86 // wait until the mouse is disconnected
geekylou 0:d0c521cb6c90 87 while(mouse.connected())
geekylou 0:d0c521cb6c90 88 Thread::wait(500);
geekylou 0:d0c521cb6c90 89 printf("mouse seen disconnected\n");
geekylou 0:d0c521cb6c90 90 }
geekylou 0:d0c521cb6c90 91 }
geekylou 0:d0c521cb6c90 92 void onKey(uint8_t key) {
geekylou 0:d0c521cb6c90 93 printf("Key: %c\r\n", key);
geekylou 0:d0c521cb6c90 94 }
geekylou 0:d0c521cb6c90 95 void keyboard_task(void const *) {
geekylou 0:d0c521cb6c90 96
geekylou 0:d0c521cb6c90 97 USBHostKeyboard keyboard;
geekylou 0:d0c521cb6c90 98
geekylou 0:d0c521cb6c90 99 while(1) {
geekylou 0:d0c521cb6c90 100 // try to connect a USB keyboard
geekylou 0:d0c521cb6c90 101 while(!keyboard.connect())
geekylou 0:d0c521cb6c90 102 Thread::wait(500);
geekylou 0:d0c521cb6c90 103
geekylou 0:d0c521cb6c90 104 // when connected, attach handler called on keyboard event
geekylou 0:d0c521cb6c90 105 keyboard.attach(onKey);
geekylou 0:d0c521cb6c90 106
geekylou 0:d0c521cb6c90 107 // wait until the keyboard is disconnected
geekylou 0:d0c521cb6c90 108 while(keyboard.connected())
geekylou 0:d0c521cb6c90 109 Thread::wait(500);
geekylou 0:d0c521cb6c90 110 }
geekylou 0:d0c521cb6c90 111 }
geekylou 0:d0c521cb6c90 112
geekylou 1:ab916b5c1a4d 113 void steamctrl_task(void const *) {
geekylou 1:ab916b5c1a4d 114
geekylou 1:ab916b5c1a4d 115 USBHostSteamController steam_controller;
geekylou 1:ab916b5c1a4d 116
geekylou 1:ab916b5c1a4d 117 while(1) {
geekylou 1:ab916b5c1a4d 118 // try to connect a USB keyboard
geekylou 1:ab916b5c1a4d 119 while(!steam_controller.connect())
geekylou 1:ab916b5c1a4d 120 Thread::wait(500);
geekylou 1:ab916b5c1a4d 121
geekylou 1:ab916b5c1a4d 122 // when connected, attach handler called on keyboard event
geekylou 1:ab916b5c1a4d 123 steam_controller.attachEvent(onJSEvent);
geekylou 1:ab916b5c1a4d 124
geekylou 1:ab916b5c1a4d 125 // wait until the keyboard is disconnected
geekylou 1:ab916b5c1a4d 126 while(steam_controller.connected())
geekylou 1:ab916b5c1a4d 127 Thread::wait(500);
geekylou 1:ab916b5c1a4d 128 }
geekylou 1:ab916b5c1a4d 129 }
geekylou 1:ab916b5c1a4d 130
geekylou 0:d0c521cb6c90 131
geekylou 0:d0c521cb6c90 132
geekylou 0:d0c521cb6c90 133 void msd_task(void const *) {
geekylou 0:d0c521cb6c90 134
geekylou 0:d0c521cb6c90 135 USBHostMSD msd;
geekylou 0:d0c521cb6c90 136 int i = 0;
geekylou 0:d0c521cb6c90 137 FATFileSystem fs("usb");
geekylou 0:d0c521cb6c90 138 int err;
geekylou 0:d0c521cb6c90 139 printf("wait for usb memory stick insertion\n");
geekylou 0:d0c521cb6c90 140 while(1) {
geekylou 0:d0c521cb6c90 141
geekylou 0:d0c521cb6c90 142 // try to connect a MSD device
geekylou 0:d0c521cb6c90 143 while(!msd.connect()) {
geekylou 0:d0c521cb6c90 144 Thread::wait(500);
geekylou 0:d0c521cb6c90 145 }
geekylou 0:d0c521cb6c90 146 if (fs.mount(&msd) != 0) continue;
geekylou 0:d0c521cb6c90 147 else
geekylou 0:d0c521cb6c90 148 printf("file system mounted\n");
geekylou 0:d0c521cb6c90 149
geekylou 0:d0c521cb6c90 150 if (!msd.connect()) {
geekylou 0:d0c521cb6c90 151 continue;
geekylou 0:d0c521cb6c90 152 }
geekylou 0:d0c521cb6c90 153
geekylou 0:d0c521cb6c90 154 // in a loop, append a file
geekylou 0:d0c521cb6c90 155 // if the device is disconnected, we try to connect it again
geekylou 0:d0c521cb6c90 156
geekylou 0:d0c521cb6c90 157 // append a file
geekylou 0:d0c521cb6c90 158 File file;
geekylou 0:d0c521cb6c90 159 err = file.open(&fs, "test1.txt", O_WRONLY | O_CREAT |O_APPEND);
geekylou 0:d0c521cb6c90 160
geekylou 0:d0c521cb6c90 161 if (err == 0) {
geekylou 0:d0c521cb6c90 162 char tmp[100];
geekylou 0:d0c521cb6c90 163 sprintf(tmp,"Hello fun USB stick World: %d!\r\n", i++);
geekylou 0:d0c521cb6c90 164 file.write(tmp,strlen(tmp));
geekylou 0:d0c521cb6c90 165 sprintf(tmp,"Goodbye World!\r\n");
geekylou 0:d0c521cb6c90 166 file.write(tmp,strlen(tmp));
geekylou 0:d0c521cb6c90 167 file.close();
geekylou 0:d0c521cb6c90 168 } else {
geekylou 0:d0c521cb6c90 169 printf("FILE == NULL\r\n");
geekylou 0:d0c521cb6c90 170 }
geekylou 0:d0c521cb6c90 171 Thread::wait(500);
geekylou 0:d0c521cb6c90 172 printf("again\n");
geekylou 0:d0c521cb6c90 173 // if device disconnected, try to connect again
geekylou 0:d0c521cb6c90 174 while (msd.connected()) {
geekylou 0:d0c521cb6c90 175 Thread::wait(500);
geekylou 0:d0c521cb6c90 176 }
geekylou 0:d0c521cb6c90 177 while (fs.unmount() < 0) {
geekylou 0:d0c521cb6c90 178 Thread::wait(500);
geekylou 0:d0c521cb6c90 179 printf("unmount\n");
geekylou 0:d0c521cb6c90 180 }
geekylou 0:d0c521cb6c90 181 }
geekylou 0:d0c521cb6c90 182 }
geekylou 0:d0c521cb6c90 183
geekylou 0:d0c521cb6c90 184 int main() {
geekylou 2:095eb20f0d3b 185 //Thread msdTask(msd_task, NULL, osPriorityNormal, 1024 * 4);
geekylou 2:095eb20f0d3b 186 Thread mouseTask(mouse_task, NULL, osPriorityNormal, 2048* 4);
geekylou 2:095eb20f0d3b 187 Thread steamctrlTask(steamctrl_task, NULL, osPriorityNormal, 2048* 4);
geekylou 1:ab916b5c1a4d 188 //Thread keyboardTask(keyboard_task, NULL, osPriorityNormal, 1024 * 4);
geekylou 0:d0c521cb6c90 189
geekylou 0:d0c521cb6c90 190 int x,y = 0;
geekylou 0:d0c521cb6c90 191 for(y=-10; y<10; y++)
geekylou 0:d0c521cb6c90 192 {
geekylou 0:d0c521cb6c90 193 x = y & 3;
geekylou 0:d0c521cb6c90 194 printf("phase %d[%d] %d\r\n",((x + 1)/2) & 1, x, (x/2) & 0x1 );
geekylou 0:d0c521cb6c90 195 }
geekylou 0:d0c521cb6c90 196 while(1) {
geekylou 0:d0c521cb6c90 197 //led=!led;
geekylou 0:d0c521cb6c90 198 Thread::wait(500);
geekylou 0:d0c521cb6c90 199 }
geekylou 0:d0c521cb6c90 200 }