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:
Sat Aug 19 19:48:20 2017 +0000
Revision:
1:ab916b5c1a4d
Parent:
0:d0c521cb6c90
Child:
2:095eb20f0d3b
Add steam controller support.

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