81 lines
2.3 KiB
C
81 lines
2.3 KiB
C
/* Baremetal Risc-V USB <=> Amiga Joystick/Mouse HID converter.
|
|
* March 2026 - Anders Holck
|
|
* This software has no license. If you choose to use, please include my name :)
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include "usb_dwc2.h"
|
|
#include "pinmux.h"
|
|
#include "amiga_hw.h"
|
|
|
|
void delay(int count) {
|
|
for (volatile int i = 0; i < count; i++);
|
|
}
|
|
|
|
void usb_init_baremetal() {
|
|
// 1. Enable USB Clocks
|
|
uint32_t clk_en = read32(CLK_EN_1);
|
|
clk_en |= (1 << 13) | (1 << 14);
|
|
write32(CLK_EN_1, clk_en);
|
|
|
|
// 2. Power on PHY and release reset
|
|
write32(USB_PHY_CTRL, 0x07);
|
|
delay(10000);
|
|
|
|
// 3. Global Reset of DWC2 Core
|
|
write32(GRSTCTL, (1 << 0)); // Soft Reset
|
|
while (!(read32(GRSTCTL) & (1 << 29)));
|
|
delay(10000);
|
|
|
|
// 4. Force Device Mode and Basic Config
|
|
write32(GUSBCFG, (1 << 30) | (1 << 29)); // Force Device, PHY Interface
|
|
write32(DCFG, 0x0); // Full Speed
|
|
write32(GINTMSK, (1 << 12) | (1 << 13) | (1 << 4) | (1 << 18)); // Reset, Enum, RXFLVL, IEPInt
|
|
|
|
// 5. Connect
|
|
write32(DCTL, 0); // Clear Soft Disconnect
|
|
}
|
|
|
|
int main() {
|
|
pinmux_init_amiga();
|
|
usb_init_baremetal();
|
|
|
|
amiga_input_t input;
|
|
uint8_t hid_report[4] = {0}; // 2 bytes buttons, 2 bytes mouse
|
|
uint32_t report_timer = 0;
|
|
|
|
while (1) {
|
|
// 1. Poll Amiga Hardware
|
|
amiga_hw_poll(&input);
|
|
|
|
// 2. Poll USB State Machine
|
|
dwc2_poll();
|
|
|
|
// 3. Send HID Report every ~10ms (approximate)
|
|
if (++report_timer > 100) {
|
|
report_timer = 0;
|
|
|
|
// Format HID Report (Match hid_report_desc in usb_descriptors.h)
|
|
// Byte 0: Joy1 (5 bits) + Joy2 (3 bits)
|
|
// Byte 1: Joy2 (remaining 2 bits) + Padding
|
|
// Byte 2: Mouse X
|
|
// Byte 3: Mouse Y
|
|
|
|
hid_report[0] = input.joy1 | ((input.joy2 & 0x07) << 5);
|
|
hid_report[1] = (input.joy2 >> 3) & 0x03;
|
|
if (input.buttons & 0x01) hid_report[1] |= (1 << 2); // Mouse B1
|
|
if (input.buttons & 0x02) hid_report[1] |= (1 << 3); // Mouse B2
|
|
|
|
hid_report[2] = (uint8_t)input.mouse_x;
|
|
hid_report[3] = (uint8_t)input.mouse_y;
|
|
|
|
// Send via Endpoint 1 (Interrupt IN)
|
|
dwc2_send_packet(1, hid_report, 4);
|
|
}
|
|
|
|
delay(100);
|
|
}
|
|
|
|
return 0;
|
|
}
|