From 8cdcab75514032e253914b2d24c180bf91de7612 Mon Sep 17 00:00:00 2001 From: Jarno Lehtinen Date: Thu, 10 Aug 2017 19:44:06 +0300 Subject: [PATCH] Create c64_usb_mouse_paddles.ino --- C64_1351_Mouse/c64_usb_mouse_paddles.ino | 138 +++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 C64_1351_Mouse/c64_usb_mouse_paddles.ino diff --git a/C64_1351_Mouse/c64_usb_mouse_paddles.ino b/C64_1351_Mouse/c64_usb_mouse_paddles.ino new file mode 100644 index 0000000..b1585b1 --- /dev/null +++ b/C64_1351_Mouse/c64_usb_mouse_paddles.ino @@ -0,0 +1,138 @@ +#include +#include + +#define POTSENSE 4 //ICP1 (Arduino Pro Micro: pin4, Arduino Uno: pin8) + +#define POTX 9 // POT AX 9, also OC1A +#define POTY 10 // POT AY 5, also OC1B +#define LBTN 5 // BTN 6, Joystick FIRE switch +#define RBTN 6 // UP 1, Joystick UP switch +#define PDL1BTN 7 // LEFT 3, Paddle 1 FIRE switch +#define PDL2BTN 8 // RIGHT 4, Paddle 2 FIRE switch + +int16_t dx = 0; +int16_t dy = 0; +uint8_t buttons = 0; + +uint8_t update = 1; + +class MouseRptParser : public MouseReportParser { +protected: + void OnMouseMove(MOUSEINFO *mi); + void OnLeftButtonUp(MOUSEINFO *mi); + void OnLeftButtonDown(MOUSEINFO *mi); + void OnRightButtonUp(MOUSEINFO *mi); + void OnRightButtonDown(MOUSEINFO *mi); + void OnMiddleButtonUp(MOUSEINFO *mi); + void OnMiddleButtonDown(MOUSEINFO *mi); +}; +void MouseRptParser::OnMouseMove(MOUSEINFO *mi) { + dx=mi->dX; + dy=mi->dY; + update = 1; +}; +void MouseRptParser::OnLeftButtonUp(MOUSEINFO *mi) { + buttons &= ~1; + update = 1; +}; +void MouseRptParser::OnLeftButtonDown(MOUSEINFO *mi) { + buttons |= 1; + update = 1; +}; +void MouseRptParser::OnRightButtonUp(MOUSEINFO *mi) { + buttons &= ~2; + update = 1; +}; +void MouseRptParser::OnRightButtonDown(MOUSEINFO *mi) { + buttons |= 2; + update = 1; +}; +void MouseRptParser::OnMiddleButtonUp(MOUSEINFO *mi) { +}; +void MouseRptParser::OnMiddleButtonDown(MOUSEINFO *mi) { +}; + +USB Usb; +USBHub Hub(&Usb); +HIDBoot HidMouse(&Usb); + +MouseRptParser Prs; + + +static uint8_t potmouse_xcounter = 0; ///< x axis counter +static uint8_t potmouse_ycounter = 0; ///< y axis counter + +static volatile uint16_t x; ///< precalculated OCR1A value (YPOT) +static volatile uint16_t y; ///< precalculated OCR1B value (XPOT) + +void setup() { + if (Usb.Init() == -1) { + } + delay(200); + HidMouse.SetReportParser(0, &Prs); + + pinMode(LBTN, INPUT); pinMode(RBTN, INPUT); + pinMode(PDL1BTN, INPUT); pinMode(PDL2BTN, INPUT); + + pinMode(POTX, OUTPUT); pinMode(POTY, OUTPUT); + digitalWrite(POTX, HIGH); digitalWrite(POTY, HIGH); + pinMode(POTSENSE, INPUT); // pullup off, hi-biased by OC1A + + TIMSK1 = _BV(ICIE1); // ICIE1: Timer/Counter1, Input Capture Interrupt Enable + TCCR1B = _BV(ICNC1) | _BV(CS10); //CS10: No prescaler, ICNC1: Input Capture Noise Canceller +} + + +void loop() { + Usb.Task(); + if (update) { + //potmouse_xcounter = (potmouse_xcounter + (dx/2)) & 0177; // modulo 128 + //potmouse_ycounter = (potmouse_ycounter - (dy/2)) & 0177; + int16_t t1 = (potmouse_xcounter - (dx/2)); + int16_t t2 = (potmouse_ycounter + (dy/2)); + potmouse_xcounter = constrain(t1, 0, 255); + potmouse_ycounter = constrain(t2, 0, 255); + /*if (t1 < 0) t1 = 0; if (t1 > 255) t1 = 255; + potmouse_xcounter = t1; //(potmouse_xcounter - (dx/2));// & 0xff; // modulo 256 + if (t2 < 0) t2 = 0; if (t2 > 255) t2 = 255; + potmouse_ycounter = t2; //(potmouse_ycounter + (dy/2));// & 0xff;*/ + + //(buttons & 001) ? pinMode(LBTN, OUTPUT) : pinMode(LBTN, INPUT); + //(buttons & 002) ? pinMode(RBTN, OUTPUT) : pinMode(RBTN, INPUT); + (buttons & 001) ? pinMode(PDL1BTN, OUTPUT) : pinMode(PDL1BTN, INPUT); + (buttons & 002) ? pinMode(PDL2BTN, OUTPUT) : pinMode(PDL2BTN, INPUT); + + cli(); + //x = (320 + potmouse_xcounter)*16; //16 clock cycles = 1us + //y = (320 + potmouse_ycounter)*16; + //x = (192 + potmouse_xcounter)*16; //16 clock cycles = 1us + //y = (192 + potmouse_ycounter)*16; + x = (256 + potmouse_xcounter)*16; //16 clock cycles = 1us + y = (256 + potmouse_ycounter)*16; + sei(); + update = 0; + } + delayMicroseconds(100); +} + + +ISR(TIMER1_CAPT_vect) { // ICIE1 + // OC1A/OC1B -> LOW + TCCR1A = _BV(COM1A1) | _BV(COM1B1); // Clear OC1A / OC1B on Compare Match (Set output to low level) + TCCR1C |= _BV(FOC1A) | _BV(FOC1B); // FOC1A / FOC1B Force Output Compare A and B + + // init the output compare values + OCR1A = ICR1 + x; //ICR1: Input Capture Register + OCR1B = ICR1 + y; + + TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(COM1B0); // Set OC1A / OC1B on Compare Match (Set output to high level). + + TIMSK1 = _BV(OCIE1A); // OCIE1A: Timer/Counter Output Compare Match Interrupt Enable A // disable other TIMER1 interrupts + TIFR1 = 0xff; // Clear all pending TIMER1 interrupt flags +} + + +ISR(TIMER1_COMPA_vect) { // OCIE1A + TIMSK1 = _BV(ICIE1); // ICIE1: Timer/Counter1, Input Capture Interrupt Enable // disable other TIMER1 interrupts + TIFR1 = 0xff; // Clear all pending TIMER1 interrupt flags +}