Files
amiga-joymouse/amiga_hw.c
T

78 lines
2.5 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 "amiga_hw.h"
#include "usb_dwc2.h"
#define GPIOA_EXT_PORTA 0x03020050
// GPIOA Bit Mappings (From PINS.md)
#define BIT_JOY1_FIRE 28
#define BIT_JOY1_UP 29
#define BIT_JOY1_DOWN 14
#define BIT_JOY1_LEFT 15
#define BIT_JOY1_RIGHT 16
#define BIT_JOY2_FIRE 17
#define BIT_JOY2_UP 18
#define BIT_JOY2_DOWN 19
#define BIT_JOY2_LEFT 20
#define BIT_JOY2_RIGHT 21
#define BIT_MOUSE_H_P 22
#define BIT_MOUSE_V_P 23
#define BIT_MOUSE_H_D 24
#define BIT_MOUSE_V_D 25
#define BIT_MOUSE_BT1 26
#define BIT_MOUSE_BT2 27
static uint8_t last_h_pulse = 0;
static uint8_t last_v_pulse = 0;
void amiga_hw_poll(amiga_input_t *input) {
uint32_t val = read32(GPIOA_EXT_PORTA);
// 1. Joystick 1 (Active Low - Amiga pulls to GND)
input->joy1 = 0;
if (!(val & (1 << BIT_JOY1_UP))) input->joy1 |= (1 << 0);
if (!(val & (1 << BIT_JOY1_DOWN))) input->joy1 |= (1 << 1);
if (!(val & (1 << BIT_JOY1_LEFT))) input->joy1 |= (1 << 2);
if (!(val & (1 << BIT_JOY1_RIGHT))) input->joy1 |= (1 << 3);
if (!(val & (1 << BIT_JOY1_FIRE))) input->joy1 |= (1 << 4);
// 2. Joystick 2
input->joy2 = 0;
if (!(val & (1 << BIT_JOY2_UP))) input->joy2 |= (1 << 0);
if (!(val & (1 << BIT_JOY2_DOWN))) input->joy2 |= (1 << 1);
if (!(val & (1 << BIT_JOY2_LEFT))) input->joy2 |= (1 << 2);
if (!(val & (1 << BIT_JOY2_RIGHT))) input->joy2 |= (1 << 3);
if (!(val & (1 << BIT_JOY2_FIRE))) input->joy2 |= (1 << 4);
// 3. Mouse Buttons
input->buttons = 0;
if (!(val & (1 << BIT_MOUSE_BT1))) input->buttons |= (1 << 0);
if (!(val & (1 << BIT_MOUSE_BT2))) input->buttons |= (1 << 1);
// 4. Mouse Quadrature Decoding (Simplified)
// Amiga Mouse uses 2 pulses per axis (Clock/Data or Phase A/B)
// Here we treat H-Pulse and V-Pulse as "clocks" and H-Dir/V-Dir as "direction"
uint8_t curr_h_pulse = (val >> BIT_MOUSE_H_P) & 1;
uint8_t curr_v_pulse = (val >> BIT_MOUSE_V_P) & 1;
input->mouse_x = 0;
if (curr_h_pulse != last_h_pulse) {
uint8_t h_dir = (val >> BIT_MOUSE_H_D) & 1;
input->mouse_x = (h_dir == curr_h_pulse) ? 1 : -1;
last_h_pulse = curr_h_pulse;
}
input->mouse_y = 0;
if (curr_v_pulse != last_v_pulse) {
uint8_t v_dir = (val >> BIT_MOUSE_V_D) & 1;
input->mouse_y = (v_dir == curr_v_pulse) ? 1 : -1;
last_v_pulse = curr_v_pulse;
}
}