// Drivers #include // SPI USB #include #define SPI_SCLK 32 #define SPI_MISO 35 #define SPI_MOSI 33 #define SPI_SS 5 #define PIN_MOUSE_V 19 // LAN_TX0 #define PIN_MOUSE_H 26 // LAN_RX1 #define PIN_MOUSE_VQ 27 // LAN_CRS #define PIN_MOUSE_HQ 23 // LAN_MDC #define PIN_MOUSE_MBTN 21 // LAN_TXEN #define PIN_MOUSE_LBTN 25 // LAN_RX0 #define PIN_MOUSE_RBTN 17 // LAN_CLK #define MOUSE_SCALE_MAX 63 #define MOUSE_PULSE_DELAY 70 const byte mouseStates[4][2] = { {0, 0}, {0, 1}, {1, 1}, {1, 0} }; uint64_t lastHandleMicros = 0; int8_t Xchange = 0; int8_t Ychange = 0; byte Xdir = 0; byte Ydir = 0; class MouseRptParser : public MouseReportParser { protected: void OnMouseMove (MOUSEINFO *mi); void OnRightButtonUp (MOUSEINFO *mi); void OnRightButtonDown (MOUSEINFO *mi); void OnLeftButtonDown (MOUSEINFO *mi); void OnLeftButtonUp (MOUSEINFO *mi); void OnMiddleButtonDown (MOUSEINFO *mi); void OnMiddleButtonUp (MOUSEINFO *mi); }; void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi) { Serial.println("BTN-R: UP"); digitalWrite(PIN_MOUSE_RBTN, HIGH); }; void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi) { Serial.println("BTN-R: DOWN"); digitalWrite(PIN_MOUSE_RBTN, LOW); }; void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi) { Serial.println("BTN-L: DOWN"); digitalWrite(PIN_MOUSE_LBTN, LOW); }; void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi) { Serial.println("BTN-L: UP"); digitalWrite(PIN_MOUSE_LBTN, HIGH); }; void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi) { Serial.println("BTN-M: DOWN"); digitalWrite(PIN_MOUSE_MBTN, LOW); Xchange+=16; }; void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi) { Serial.println("BTN-M: UP"); digitalWrite(PIN_MOUSE_MBTN, HIGH); }; bool mouseYworking = false; int mouseYTableIndex = 0; void amigaYpulse(int8_t count) { if (count == 0) return; if (mouseYworking) return; mouseYworking = true; byte mapped = map(abs(count), 0, 127, 1, MOUSE_SCALE_MAX); for (byte i = 0; i < mapped; i++) { if (count < 0) { mouseYTableIndex++; if (mouseYTableIndex > 3) { mouseYTableIndex = 0; } } else { mouseYTableIndex--; if (mouseYTableIndex < 0) { mouseYTableIndex = 3; } } digitalWrite(PIN_MOUSE_V, mouseStates[mouseYTableIndex][0]); digitalWrite(PIN_MOUSE_VQ, mouseStates[mouseYTableIndex][1]); delayMicroseconds(MOUSE_PULSE_DELAY); } mouseYworking = false; } int mouseXTableIndex = 0; void amigaXpulse(int8_t count) { if (count == 0) return; for (byte i = 0; i < map(abs(count), 0, 127, 1, MOUSE_SCALE_MAX); i++) { if (count < 0) { mouseXTableIndex++; if (mouseXTableIndex > 3) { mouseXTableIndex = 0; } } else { mouseXTableIndex--; if (mouseXTableIndex < 0) { mouseXTableIndex = 3; } } digitalWrite(PIN_MOUSE_H, mouseStates[mouseXTableIndex][0]); digitalWrite(PIN_MOUSE_HQ, mouseStates[mouseXTableIndex][1]); delayMicroseconds(MOUSE_PULSE_DELAY); } } void processXTableIndex(bool dir) { if (dir) { mouseXTableIndex++; if (mouseXTableIndex > 3) { mouseXTableIndex = 0; } } else { mouseXTableIndex--; if (mouseXTableIndex < 0) { mouseXTableIndex = 3; } } } void processYTableIndex(bool dir) { if (dir) { mouseYTableIndex++; if (mouseYTableIndex > 3) { mouseYTableIndex = 0; } } else { mouseYTableIndex--; if (mouseYTableIndex < 0) { mouseYTableIndex = 3; } } } void writeAnalogPorts() { digitalWrite(PIN_MOUSE_H, mouseStates[mouseXTableIndex][0]); digitalWrite(PIN_MOUSE_HQ, mouseStates[mouseXTableIndex][1]); digitalWrite(PIN_MOUSE_V, mouseStates[mouseYTableIndex][0]); digitalWrite(PIN_MOUSE_VQ, mouseStates[mouseYTableIndex][1]); } void handleAnalogMove() { // Do nothing if no change if ((Xchange == 0) && (Ychange == 0)) { return; } if (lastHandleMicros + MOUSE_PULSE_DELAY > micros()) { return; } if (Xchange > 0) { processXTableIndex(Xdir); Xchange--; } if (Ychange > 0) { processYTableIndex(Ydir); Ychange--; } writeAnalogPorts(); lastHandleMicros = micros(); } void MouseRptParser::OnMouseMove(MOUSEINFO *mi) { //amigaYpulse(mi->dY); //amigaXpulse(mi->dX); //return; if ((Xchange != 0) || (Ychange != 0)) { Serial.println("Too FAST"); Serial.print("X: "); Serial.println(Xchange); Serial.print("Y: "); Serial.println(Ychange); } if (mi->dX != 0) { Xchange += map(abs(mi->dX), 0, 127, 1, MOUSE_SCALE_MAX); } if (mi->dY != 0) { Ychange += map(abs(mi->dY), 0, 127, 1, MOUSE_SCALE_MAX); } Xdir = mi->dX < 0 ? true : false; Ydir = mi->dY < 0 ? true : false; }; // This is only for single USB device (without HUB) // In this example we support keyboard or mouse USB Usb; HIDBoot HidMouse(&Usb); MouseRptParser PrsMouse; void setupAnalogMouse() { pinMode(PIN_MOUSE_V, OUTPUT); pinMode(PIN_MOUSE_VQ, OUTPUT); pinMode(PIN_MOUSE_H, OUTPUT); pinMode(PIN_MOUSE_HQ, OUTPUT); pinMode(PIN_MOUSE_LBTN, OUTPUT); pinMode(PIN_MOUSE_MBTN, OUTPUT); pinMode(PIN_MOUSE_RBTN, OUTPUT); // Default button state is not pressed digitalWrite(PIN_MOUSE_LBTN, HIGH); digitalWrite(PIN_MOUSE_MBTN, HIGH); digitalWrite(PIN_MOUSE_RBTN, HIGH); } void setup() { // put your setup code here, to run once: Serial.begin(115200); Serial.println("INIT"); Serial.print("USB init..."); SPI.begin(SPI_SCLK, SPI_MISO, SPI_MOSI, SPI_SS); if (Usb.Init() == -1) { Serial.println("WARN: Usb init failed."); } else { Serial.println(" DONE"); } setupAnalogMouse(); HidMouse.SetReportParser(0, &PrsMouse); Serial.println("Ready to rock and roll..."); } void loop() { Usb.Task(); handleAnalogMove(); }