all repos — mgba @ a6f895da7d1cc6a7664d7d0aba44c11921cf99f0

mGBA Game Boy Advance Emulator

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}