possibly all files needed to make things work
This commit is contained in:
parent
708bb4f55d
commit
09ff4b0c99
15 changed files with 783 additions and 16 deletions
216
keyboards/handwired/gc_controller/gc_read.c
Normal file
216
keyboards/handwired/gc_controller/gc_read.c
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#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];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue