all repos — mgba @ 86003496b0af95e897ab4ceea86e8d32efe01d75

mGBA Game Boy Advance Emulator

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}