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