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 22:01:47 2017 +0000
Revision:
3:24067f6310fa
Parent:
2:095eb20f0d3b
Child:
4:02e4f0ab23ff
Use ticker to update quadrature status.  Ticker speed is currently fixed but this should be based on x/y values

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