| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #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];
- }
|