src/gba/gba-gpio.c (view raw)
1#include "gba.h"
2
3#include "gba-gpio.h"
4#include "gba-sensors.h"
5#include "gba-serialize.h"
6
7#include <time.h>
8
9static void _readPins(struct GBACartridgeGPIO* gpio);
10static void _outputPins(struct GBACartridgeGPIO* gpio, unsigned pins);
11
12static void _rtcReadPins(struct GBACartridgeGPIO* gpio);
13static unsigned _rtcOutput(struct GBACartridgeGPIO* gpio);
14static void _rtcProcessByte(struct GBACartridgeGPIO* gpio);
15static void _rtcUpdateClock(struct GBACartridgeGPIO* gpio);
16static unsigned _rtcBCD(unsigned value);
17
18static void _gyroReadPins(struct GBACartridgeGPIO* gpio);
19
20static void _rumbleReadPins(struct GBACartridgeGPIO* gpio);
21
22static const int RTC_BYTES[8] = {
23 0, // Force reset
24 0, // Empty
25 7, // Date/Time
26 0, // Force IRQ
27 1, // Control register
28 0, // Empty
29 3, // Time
30 0 // Empty
31};
32
33void GBAGPIOInit(struct GBACartridgeGPIO* gpio, uint16_t* base) {
34 gpio->gpioDevices = GPIO_NONE;
35 gpio->direction = GPIO_WRITE_ONLY;
36 gpio->gpioBase = base;
37 gpio->pinState = 0;
38 gpio->direction = 0;
39}
40
41void GBAGPIOWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint16_t value) {
42 switch (address) {
43 case GPIO_REG_DATA:
44 gpio->pinState = value;
45 _readPins(gpio);
46 break;
47 case GPIO_REG_DIRECTION:
48 gpio->direction = value;
49 break;
50 case GPIO_REG_CONTROL:
51 gpio->readWrite = value;
52 break;
53 default:
54 GBALog(gpio->p, GBA_LOG_WARN, "Invalid GPIO address");
55 }
56
57 if (gpio->readWrite) {
58 uint16_t old = gpio->gpioBase[0];
59 old &= ~gpio->direction;
60 gpio->gpioBase[0] = old | (value & gpio->direction);
61 }
62}
63
64void GBAGPIOInitRTC(struct GBACartridgeGPIO* gpio) {
65 gpio->gpioDevices |= GPIO_RTC;
66 gpio->rtc.bytesRemaining = 0;
67
68 gpio->rtc.transferStep = 0;
69
70 gpio->rtc.bitsRead = 0;
71 gpio->rtc.bits = 0;
72 gpio->rtc.commandActive = 0;
73 gpio->rtc.command.packed = 0;
74 gpio->rtc.control.packed = 0x40;
75 memset(gpio->rtc.time, 0, sizeof(gpio->rtc.time));
76}
77
78void _readPins(struct GBACartridgeGPIO* gpio) {
79 if (gpio->gpioDevices & GPIO_RTC) {
80 _rtcReadPins(gpio);
81 }
82
83 if (gpio->gpioDevices & GPIO_GYRO) {
84 _gyroReadPins(gpio);
85 }
86
87 if (gpio->gpioDevices & GPIO_RUMBLE) {
88 _rumbleReadPins(gpio);
89 }
90}
91
92void _outputPins(struct GBACartridgeGPIO* gpio, unsigned pins) {
93 if (gpio->readWrite) {
94 uint16_t old = gpio->gpioBase[0];
95 old &= gpio->direction;
96 gpio->gpioBase[0] = old | (pins & ~gpio->direction & 0xF);
97 }
98}
99
100// == RTC
101
102void _rtcReadPins(struct GBACartridgeGPIO* gpio) {
103 // Transfer sequence:
104 // P: 0 | 1 | 2 | 3
105 // == Initiate
106 // > HI | - | LO | -
107 // > HI | - | HI | -
108 // == Transfer bit (x8)
109 // > LO | x | HI | -
110 // > HI | - | HI | -
111 // < ?? | x | ?? | -
112 // == Terminate
113 // > - | - | LO | -
114 switch (gpio->rtc.transferStep) {
115 case 0:
116 if ((gpio->pinState & 5) == 1) {
117 gpio->rtc.transferStep = 1;
118 }
119 break;
120 case 1:
121 if ((gpio->pinState & 5) == 5) {
122 gpio->rtc.transferStep = 2;
123 }
124 break;
125 case 2:
126 if (!gpio->p0) {
127 gpio->rtc.bits &= ~(1 << gpio->rtc.bitsRead);
128 gpio->rtc.bits |= gpio->p1 << gpio->rtc.bitsRead;
129 } else {
130 if (gpio->p2) {
131 // GPIO direction should always != reading
132 if (gpio->dir1) {
133 if (gpio->rtc.command.reading) {
134 GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Attempting to write to RTC while in read mode");
135 }
136 ++gpio->rtc.bitsRead;
137 if (gpio->rtc.bitsRead == 8) {
138 _rtcProcessByte(gpio);
139 }
140 } else {
141 _outputPins(gpio, 5 | (_rtcOutput(gpio) << 1));
142 ++gpio->rtc.bitsRead;
143 if (gpio->rtc.bitsRead == 8) {
144 --gpio->rtc.bytesRemaining;
145 if (gpio->rtc.bytesRemaining <= 0) {
146 gpio->rtc.commandActive = 0;
147 gpio->rtc.command.reading = 0;
148 }
149 gpio->rtc.bitsRead = 0;
150 }
151 }
152 } else {
153 gpio->rtc.bitsRead = 0;
154 gpio->rtc.bytesRemaining = 0;
155 gpio->rtc.commandActive = 0;
156 gpio->rtc.command.reading = 0;
157 gpio->rtc.transferStep = 0;
158 }
159 }
160 break;
161 }
162}
163
164void _rtcProcessByte(struct GBACartridgeGPIO* gpio) {
165 --gpio->rtc.bytesRemaining;
166 if (!gpio->rtc.commandActive) {
167 union RTCCommandData command;
168 command.packed = gpio->rtc.bits;
169 if (command.magic == 0x06) {
170 gpio->rtc.command = command;
171
172 gpio->rtc.bytesRemaining = RTC_BYTES[gpio->rtc.command.command];
173 gpio->rtc.commandActive = gpio->rtc.bytesRemaining > 0;
174 switch (command.command) {
175 case RTC_RESET:
176 gpio->rtc.control.packed = 0;
177 break;
178 case RTC_DATETIME:
179 case RTC_TIME:
180 _rtcUpdateClock(gpio);
181 break;
182 case RTC_FORCE_IRQ:
183 case RTC_CONTROL:
184 break;
185 }
186 } else {
187 GBALog(gpio->p, GBA_LOG_WARN, "Invalid RTC command byte: %02X", gpio->rtc.bits);
188 }
189 } else {
190 switch (gpio->rtc.command.command) {
191 case RTC_CONTROL:
192 gpio->rtc.control.packed = gpio->rtc.bits;
193 break;
194 case RTC_FORCE_IRQ:
195 GBALog(gpio->p, GBA_LOG_STUB, "Unimplemented RTC command %u", gpio->rtc.command.command);
196 break;
197 case RTC_RESET:
198 case RTC_DATETIME:
199 case RTC_TIME:
200 break;
201 }
202 }
203
204 gpio->rtc.bits = 0;
205 gpio->rtc.bitsRead = 0;
206 if (!gpio->rtc.bytesRemaining) {
207 gpio->rtc.commandActive = 0;
208 gpio->rtc.command.reading = 0;
209 }
210}
211
212unsigned _rtcOutput(struct GBACartridgeGPIO* gpio) {
213 uint8_t outputByte = 0;
214 switch (gpio->rtc.command.command) {
215 case RTC_CONTROL:
216 outputByte = gpio->rtc.control.packed;
217 break;
218 case RTC_DATETIME:
219 case RTC_TIME:
220 outputByte = gpio->rtc.time[7 - gpio->rtc.bytesRemaining];
221 break;
222 case RTC_FORCE_IRQ:
223 case RTC_RESET:
224 break;
225 }
226 unsigned output = (outputByte >> gpio->rtc.bitsRead) & 1;
227 return output;
228}
229
230void _rtcUpdateClock(struct GBACartridgeGPIO* gpio) {
231 time_t t = time(0);
232 struct tm date;
233#ifdef _WIN32
234 date = *localtime(&t);
235#else
236 localtime_r(&t, &date);
237#endif
238 gpio->rtc.time[0] = _rtcBCD(date.tm_year - 100);
239 gpio->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
240 gpio->rtc.time[2] = _rtcBCD(date.tm_mday);
241 gpio->rtc.time[3] = _rtcBCD(date.tm_wday);
242 if (gpio->rtc.control.hour24) {
243 gpio->rtc.time[4] = _rtcBCD(date.tm_hour);
244 } else {
245 gpio->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
246 }
247 gpio->rtc.time[5] = _rtcBCD(date.tm_min);
248 gpio->rtc.time[6] = _rtcBCD(date.tm_sec);
249}
250
251unsigned _rtcBCD(unsigned value) {
252 int counter = value % 10;
253 value /= 10;
254 counter += (value % 10) << 4;
255 return counter;
256}
257
258// == Gyro
259
260void GBAGPIOInitGyro(struct GBACartridgeGPIO* gpio) {
261 gpio->gpioDevices |= GPIO_GYRO;
262 gpio->gyroSample = 0;
263 gpio->gyroEdge = 0;
264}
265
266void _gyroReadPins(struct GBACartridgeGPIO* gpio) {
267 struct GBARotationSource* gyro = gpio->p->rotationSource;
268 if (!gyro) {
269 return;
270 }
271
272 if (gpio->p0) {
273 if (gyro->sample) {
274 gyro->sample(gyro);
275 }
276 int32_t sample = gyro->readGyroZ(gyro);
277
278 // Normalize to ~12 bits, focused on 0x6C0
279 gpio->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
280 }
281
282 if (gpio->gyroEdge && !gpio->p1) {
283 // Write bit on falling edge
284 unsigned bit = gpio->gyroSample >> 15;
285 gpio->gyroSample <<= 1;
286 _outputPins(gpio, bit << 2);
287 }
288
289 gpio->gyroEdge = gpio->p1;
290}
291
292// == Rumble
293
294void GBAGPIOInitRumble(struct GBACartridgeGPIO* gpio) {
295 gpio->gpioDevices |= GPIO_RUMBLE;
296}
297
298void _rumbleReadPins(struct GBACartridgeGPIO* gpio) {
299 struct GBARumble* rumble = gpio->p->rumble;
300 if (!rumble) {
301 return;
302 }
303
304 rumble->setRumble(rumble, gpio->p3);
305}
306
307// == Serialization
308
309void GBAGPIOSerialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state) {
310 state->gpio.readWrite = gpio->readWrite;
311 state->gpio.pinState = gpio->pinState;
312 state->gpio.pinDirection = gpio->direction;
313 state->gpio.devices = gpio->gpioDevices;
314 state->gpio.rtc = gpio->rtc;
315 state->gpio.gyroSample = gpio->gyroSample;
316 state->gpio.gyroEdge = gpio->gyroEdge;
317}
318
319void GBAGPIODeserialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state) {
320 gpio->readWrite = state->gpio.readWrite;
321 gpio->pinState = state->gpio.pinState;
322 gpio->direction = state->gpio.pinDirection;
323 // TODO: Deterministic RTC
324 gpio->rtc = state->gpio.rtc;
325 gpio->gyroSample = state->gpio.gyroSample;
326 gpio->gyroEdge = state->gpio.gyroEdge;
327}