You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.7 KiB
216 lines
5.7 KiB
#include "gc_read.h"
|
|
#include "gc_controller.h"
|
|
|
|
#define CONTROLLER_TIMEOUT 60
|
|
|
|
bool init_message[9] = {0, 0, 0, 0, 0, 0, 0, 0, 1};
|
|
bool request_message[25] = {
|
|
0, 1, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 1, 1,
|
|
0, 0, 0, 0, 0, 0, 1, 0, 1};
|
|
|
|
void start_message(void) {
|
|
setPinOutput(GAMECUBE_DATA_PIN);
|
|
writePinLow(GAMECUBE_DATA_PIN);
|
|
}
|
|
|
|
void send_bit(bool b) {
|
|
if (b) {
|
|
writePinLow(GAMECUBE_DATA_PIN);
|
|
wait_ns(900);
|
|
writePinHigh(GAMECUBE_DATA_PIN);
|
|
wait_ns(2900);
|
|
} else {
|
|
writePinLow(GAMECUBE_DATA_PIN);
|
|
wait_ns(2900);
|
|
writePinHigh(GAMECUBE_DATA_PIN);
|
|
wait_ns(900);
|
|
}
|
|
}
|
|
|
|
void wait_for_ready(void) {
|
|
setPinInputHigh(GAMECUBE_DATA_PIN);
|
|
|
|
// wait for long high
|
|
uint8_t ready = 0;
|
|
while (ready < 5) {
|
|
if (readPin(GAMECUBE_DATA_PIN))
|
|
ready++;
|
|
else
|
|
ready = 0;
|
|
wait_us(1);
|
|
}
|
|
}
|
|
|
|
void end_message(void) {
|
|
setPinInputHigh(GAMECUBE_DATA_PIN);
|
|
}
|
|
|
|
uint8_t buffer[9] = {0};
|
|
uint16_t buttons_debounce = 0;
|
|
bool initialised = false;
|
|
bool calibrated = false;
|
|
uint8_t mid_values[4] = {128, 128, 128, 128};
|
|
uint8_t max_values[4] = {210, 210, 210, 210};
|
|
uint8_t min_values[4] = {35, 35, 35, 35};
|
|
|
|
void gamecube_init(void) {
|
|
setPinInputHigh(GAMECUBE_DATA_PIN);
|
|
}
|
|
|
|
void gamecube_scan(uint16_t * buttons, uint8_t * joysticks) {
|
|
bool exiting = false;
|
|
uint16_t timeout_counter = 0;
|
|
|
|
// somehow we're missing the first bit, which can safely be ignored
|
|
// i'm not sure if it's something with the timing or what
|
|
uint8_t buffer_bit = 1;
|
|
|
|
chSysLock();
|
|
|
|
if (!initialised) {
|
|
wait_for_ready();
|
|
|
|
start_message();
|
|
for (uint8_t i = 0; i < 9; i++)
|
|
send_bit(init_message[i]);
|
|
end_message();
|
|
|
|
initialised = true;
|
|
}
|
|
|
|
wait_for_ready();
|
|
|
|
start_message();
|
|
for (uint8_t i = 0; i < 25; i++)
|
|
send_bit(request_message[i]);
|
|
end_message();
|
|
|
|
while (!exiting) {
|
|
timeout_counter = 0;
|
|
// wait for low or timeout
|
|
while (readPin(GAMECUBE_DATA_PIN)) {
|
|
wait_ns(100);
|
|
timeout_counter++;
|
|
if (timeout_counter > CONTROLLER_TIMEOUT) {
|
|
exiting = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!exiting) {
|
|
// wait for the data part
|
|
wait_ns(1950);
|
|
bool b = readPin(GAMECUBE_DATA_PIN);
|
|
if (b)
|
|
buffer[buffer_bit / 8] |= (1 << (7 - (buffer_bit % 8)));
|
|
else
|
|
buffer[buffer_bit / 8] &= ~(1 << (7 - (buffer_bit % 8)));
|
|
buffer_bit++;
|
|
|
|
// wait for high
|
|
while (!readPin(GAMECUBE_DATA_PIN));
|
|
}
|
|
}
|
|
|
|
chSysUnlock();
|
|
|
|
// basic debouncing for buttons
|
|
uint16_t combined_buttons = buffer[0] | (buffer[1] << 8);
|
|
*buttons |= buttons_debounce & combined_buttons;
|
|
*buttons &= buttons_debounce | combined_buttons;
|
|
buttons_debounce = combined_buttons;
|
|
|
|
if (!calibrated && mid_values[0] > 0) {
|
|
mid_values[0] = buffer[2];
|
|
mid_values[1] = buffer[3];
|
|
mid_values[2] = buffer[4];
|
|
mid_values[3] = buffer[5];
|
|
calibrated = true;
|
|
}
|
|
|
|
if (max_values[0] < buffer[2])
|
|
max_values[0] = buffer[2];
|
|
if (max_values[1] < buffer[3])
|
|
max_values[1] = buffer[3];
|
|
if (max_values[2] < buffer[4])
|
|
max_values[2] = buffer[4];
|
|
if (max_values[3] < buffer[5])
|
|
max_values[3] = buffer[5];
|
|
|
|
if (min_values[0] > buffer[2])
|
|
min_values[0] = buffer[2];
|
|
if (min_values[1] > buffer[3])
|
|
min_values[1] = buffer[3];
|
|
if (min_values[2] > buffer[4])
|
|
min_values[2] = buffer[4];
|
|
if (min_values[3] > buffer[5])
|
|
min_values[3] = buffer[5];
|
|
|
|
// values from my GC controller in Windows
|
|
// 30 - 138 - 236
|
|
// 20 - 124 - 225
|
|
// 37 - 135 - 222
|
|
// 34 - 126 - 216
|
|
|
|
// this should be 127? i don't understand what i'm doing wrong yet
|
|
#define JOYSTICK_SCALER 180.0
|
|
|
|
int32_t lx_temp = (int16_t)buffer[2] - mid_values[0];
|
|
if (lx_temp > 0)
|
|
lx_temp *= JOYSTICK_SCALER / (max_values[0]-mid_values[0]);
|
|
else
|
|
lx_temp *= JOYSTICK_SCALER / (mid_values[0]-min_values[0]);
|
|
lx_temp += STICK_CENTER;
|
|
if (lx_temp > 255)
|
|
lx_temp = 255;
|
|
if (lx_temp < 0)
|
|
lx_temp = 0;
|
|
|
|
int32_t ly_temp = (int16_t)buffer[3] - mid_values[1];
|
|
if (ly_temp > 0)
|
|
ly_temp *= JOYSTICK_SCALER / (max_values[1]-mid_values[1]);
|
|
else
|
|
ly_temp *= JOYSTICK_SCALER / (mid_values[1]-min_values[1]);
|
|
ly_temp += STICK_CENTER;
|
|
if (ly_temp > 255)
|
|
ly_temp = 255;
|
|
if (ly_temp < 0)
|
|
ly_temp = 0;
|
|
|
|
int32_t rx_temp = (int16_t)buffer[4] - mid_values[2];
|
|
if (rx_temp > 0)
|
|
rx_temp *= JOYSTICK_SCALER / (max_values[2]-mid_values[2]);
|
|
else
|
|
rx_temp *= JOYSTICK_SCALER / (mid_values[2]-min_values[2]);
|
|
rx_temp += STICK_CENTER;
|
|
if (rx_temp > 255)
|
|
rx_temp = 255;
|
|
if (rx_temp < 0)
|
|
rx_temp = 0;
|
|
|
|
int32_t ry_temp = (int16_t)buffer[5] - mid_values[3];
|
|
if (ry_temp > 0)
|
|
ry_temp *= JOYSTICK_SCALER / (max_values[3]-mid_values[3]);
|
|
else
|
|
ry_temp *= JOYSTICK_SCALER / (mid_values[3]-min_values[3]);
|
|
ry_temp += STICK_CENTER;
|
|
if (ry_temp > 255)
|
|
ry_temp = 255;
|
|
if (ry_temp < 0)
|
|
ry_temp = 0;
|
|
|
|
// checks to avoid a data skip (0 values on input, which aren't possible, i think)
|
|
if (buffer[2])
|
|
joysticks[0] = lx_temp;
|
|
if (buffer[3])
|
|
joysticks[1] = ly_temp;
|
|
if (buffer[4])
|
|
joysticks[2] = rx_temp;
|
|
if (buffer[5])
|
|
joysticks[3] = ry_temp;
|
|
if (buffer[6])
|
|
joysticks[4] = buffer[6];
|
|
if (buffer[7])
|
|
joysticks[5] = buffer[7];
|
|
}
|
|
|