1 /**********************************************/
2 // File     :     joystick.c
3 // Author   :     John Bliss
4 // Date     :     September 27th 2019
5 /**********************************************/
6 
7 #include "joystick.h"
8 
9 
10 enum joy_status joy1_mode = NONE;
11 enum joy_status joy2_mode = NONE;
12 
13 
14 static SDL_GameController *joystick1 = NULL;
15 static SDL_GameController *joystick2 = NULL;
16 static bool old_clock = false;
17 static bool writing = false;
18 static uint16_t joystick1_state = 0;
19 static uint16_t joystick2_state = 0;
20 static uint8_t clock_count = 0;
21 
22 bool joystick_latch, joystick_clock;
23 bool joystick1_data, joystick2_data;
24 
joystick_init()25 bool joystick_init()
26 {
27 	int joystick1_number = -1;
28 	//Try to get first controller, if it is not set to 1
29 	if (joy1_mode != NONE) {
30 		for (int i = 0; i < SDL_NumJoysticks(); i++) {
31 			if (SDL_IsGameController(i)) {
32 				joystick1 = SDL_GameControllerOpen(i);
33 				if (joystick1) {
34 					joystick1_number = i;
35 					break;
36 				} else {
37 					fprintf(stderr, "Could not open gamecontroller %i: %s\n", i, SDL_GetError());
38 				}
39 			}
40 		}
41 	}
42 	if (joy2_mode != NONE) {
43 		for (int i=0; i < SDL_NumJoysticks(); i++) {
44 			if (SDL_IsGameController(i) && joystick1_number != i) {
45 				joystick2 = SDL_GameControllerOpen(i);
46 				if (joystick2) {
47 					break;
48 				} else {
49 					fprintf(stderr, "Could not open gamecontroller %i: %s\n", i, SDL_GetError());
50 				}
51 			}
52 		}
53 	}
54 	writing = false;
55 	return true;
56 }
57 
joystick_step()58 void joystick_step()
59 {
60 	if (!writing) { //if we are not already writing, check latch to
61 		//see if we need to start
62 		handle_latch(joystick_latch, joystick_clock);
63 		return;
64 	}
65 
66 	//if we have started writing controller data and the latch has dropped,
67 	// we need to start the next bit
68 	if (!joystick_latch) {
69 		//check if clock has changed
70 		if (joystick_clock != old_clock) {
71 			if (old_clock) {
72 				old_clock = joystick_clock;
73 			} else {  //only write next bit when the new clock is high
74 				clock_count +=1;
75 				old_clock = joystick_clock;
76 				if (clock_count < 16) { // write out the next 15 bits
77 					joystick1_data = (joy1_mode != NONE) ? (joystick1_state & 1) : 1;
78 					joystick2_data = (joy2_mode != NONE) ? (joystick2_state & 1) : 1;
79 					joystick1_state = joystick1_state >> 1;
80 					joystick2_state = joystick2_state >> 1;
81 				} else {
82 					//Done writing controller data
83 					//reset flag and set count to 0
84 					writing = false;
85 					clock_count = 0;
86 					joystick1_data = (joy1_mode != NONE) ? 0 : 1;
87 					joystick2_data = (joy2_mode != NONE) ? 0 : 1;
88 				}
89 			}
90 		}
91 	}
92 
93 
94 
95 }
96 
handle_latch(bool latch,bool clock)97 bool handle_latch(bool latch, bool clock)
98 {
99 	if (latch){
100 		clock_count = 0;
101 		//get the 16-representation to put to the VIA
102 		joystick1_state = get_joystick_state(joystick1, joy1_mode);
103 		joystick2_state = get_joystick_state(joystick2, joy2_mode);
104 		//set writing flag to true to signal we will start writing controller data
105 		writing = true;
106 		old_clock = clock;
107 		//preload the first bit onto VIA
108 		joystick1_data = (joy1_mode != NONE) ? (joystick1_state & 1) : 1;
109 		joystick2_data = (joy2_mode != NONE) ? (joystick2_state & 1) : 1;
110 		joystick1_state = joystick1_state >> 1;
111 		joystick2_state = joystick2_state >> 1;
112 	}
113 
114 	return latch;
115 }
116 
117 //get current state from SDL controller
118 //Should replace this with SDL events, so we do not miss inputs when polling
get_joystick_state(SDL_GameController * control,enum joy_status mode)119 uint16_t get_joystick_state(SDL_GameController *control, enum joy_status mode)
120 {
121 	if (mode == NES) {
122 		bool a_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_A);
123 		bool b_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_X);
124 		bool select_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_BACK);
125 		bool start_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_START);
126 		bool up_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_UP);
127 		bool down_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
128 		bool left_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
129 		bool right_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
130 
131 		return
132 		(!a_pressed) |
133 		(!b_pressed) << 1 |
134 		(!select_pressed) << 2 |
135 		(!start_pressed) << 3 |
136 		(!up_pressed) << 4 |
137 		(!down_pressed) << 5 |
138 		(!left_pressed) << 6 |
139 		(!right_pressed) << 7 |
140 		0x0000;
141 	}
142 	if (mode == SNES) {
143 		bool b_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_A);
144 		bool y_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_X);
145 		bool select_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_BACK);
146 		bool start_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_START);
147 		bool up_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_UP);
148 		bool down_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
149 		bool left_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
150 		bool right_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
151 		bool a_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_B);
152 		bool x_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_Y);
153 		bool l_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
154 		bool r_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
155 
156 
157 		return
158 		(!b_pressed) |
159 		(!y_pressed) << 1 |
160 		(!select_pressed) << 2 |
161 		(!start_pressed) << 3 |
162 		(!up_pressed) << 4 |
163 		(!down_pressed) << 5 |
164 		(!left_pressed) << 6 |
165 		(!right_pressed) << 7 |
166 		(!a_pressed) << 8 |
167 		(!x_pressed) << 9 |
168 		(!l_pressed) << 10 |
169 		(!r_pressed) << 11 |
170 		0xF000;
171 	}
172 
173 	return 0xFFFF;
174 }
175