all repos — mgba @ 0de46a78679adf820eba08c3f72e64202540b692

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 void _lightReadPins(struct GBACartridgeGPIO* gpio);
 28
 29static const int RTC_BYTES[8] = {
 30	0, // Force reset
 31	0, // Empty
 32	7, // Date/Time
 33	0, // Force IRQ
 34	1, // Control register
 35	0, // Empty
 36	3, // Time
 37	0 // Empty
 38};
 39
 40void GBAGPIOInit(struct GBACartridgeGPIO* gpio, uint16_t* base) {
 41	gpio->gpioBase = base;
 42	GBAGPIOClear(gpio);
 43}
 44
 45void GBAGPIOClear(struct GBACartridgeGPIO* gpio) {
 46	gpio->gpioDevices = GPIO_NONE;
 47	gpio->direction = GPIO_WRITE_ONLY;
 48	gpio->pinState = 0;
 49	gpio->direction = 0;
 50}
 51
 52void GBAGPIOWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint16_t value) {
 53	switch (address) {
 54	case GPIO_REG_DATA:
 55		gpio->pinState &= ~gpio->direction;
 56		gpio->pinState |= value;
 57		_readPins(gpio);
 58		break;
 59	case GPIO_REG_DIRECTION:
 60		gpio->direction = value;
 61		break;
 62	case GPIO_REG_CONTROL:
 63		gpio->readWrite = value;
 64		break;
 65	default:
 66		GBALog(gpio->p, GBA_LOG_WARN, "Invalid GPIO address");
 67	}
 68	if (gpio->readWrite) {
 69		uint16_t old = gpio->gpioBase[0];
 70		old &= ~gpio->direction;
 71		gpio->gpioBase[0] = old | gpio->pinState;
 72	} else {
 73		gpio->gpioBase[0] = 0;
 74	}
 75}
 76
 77void GBAGPIOInitRTC(struct GBACartridgeGPIO* gpio) {
 78	gpio->gpioDevices |= GPIO_RTC;
 79	gpio->rtc.bytesRemaining = 0;
 80
 81	gpio->rtc.transferStep = 0;
 82
 83	gpio->rtc.bitsRead = 0;
 84	gpio->rtc.bits = 0;
 85	gpio->rtc.commandActive = 0;
 86	gpio->rtc.command.packed = 0;
 87	gpio->rtc.control.packed = 0x40;
 88	memset(gpio->rtc.time, 0, sizeof(gpio->rtc.time));
 89}
 90
 91void _readPins(struct GBACartridgeGPIO* gpio) {
 92	if (gpio->gpioDevices & GPIO_RTC) {
 93		_rtcReadPins(gpio);
 94	}
 95
 96	if (gpio->gpioDevices & GPIO_GYRO) {
 97		_gyroReadPins(gpio);
 98	}
 99
100	if (gpio->gpioDevices & GPIO_RUMBLE) {
101		_rumbleReadPins(gpio);
102	}
103
104	if (gpio->gpioDevices & GPIO_LIGHT_SENSOR) {
105		_lightReadPins(gpio);
106	}
107}
108
109void _outputPins(struct GBACartridgeGPIO* gpio, unsigned pins) {
110	if (gpio->readWrite) {
111		uint16_t old = gpio->gpioBase[0];
112		old &= gpio->direction;
113		gpio->pinState = old | (pins & ~gpio->direction & 0xF);
114		gpio->gpioBase[0] = gpio->pinState;
115	}
116}
117
118// == RTC
119
120void _rtcReadPins(struct GBACartridgeGPIO* gpio) {
121	// Transfer sequence:
122	// P: 0 | 1 |  2 | 3
123	// == Initiate
124	// > HI | - | LO | -
125	// > HI | - | HI | -
126	// == Transfer bit (x8)
127	// > LO | x | HI | -
128	// > HI | - | HI | -
129	// < ?? | x | ?? | -
130	// == Terminate
131	// >  - | - | LO | -
132	switch (gpio->rtc.transferStep) {
133	case 0:
134		if ((gpio->pinState & 5) == 1) {
135			gpio->rtc.transferStep = 1;
136		}
137		break;
138	case 1:
139		if ((gpio->pinState & 5) == 5) {
140			gpio->rtc.transferStep = 2;
141		}
142		break;
143	case 2:
144		if (!gpio->p0) {
145			gpio->rtc.bits &= ~(1 << gpio->rtc.bitsRead);
146			gpio->rtc.bits |= gpio->p1 << gpio->rtc.bitsRead;
147		} else {
148			if (gpio->p2) {
149				// GPIO direction should always != reading
150				if (gpio->dir1) {
151					if (gpio->rtc.command.reading) {
152						GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Attempting to write to RTC while in read mode");
153					}
154					++gpio->rtc.bitsRead;
155					if (gpio->rtc.bitsRead == 8) {
156						_rtcProcessByte(gpio);
157					}
158				} else {
159					_outputPins(gpio, 5 | (_rtcOutput(gpio) << 1));
160					++gpio->rtc.bitsRead;
161					if (gpio->rtc.bitsRead == 8) {
162						--gpio->rtc.bytesRemaining;
163						if (gpio->rtc.bytesRemaining <= 0) {
164							gpio->rtc.commandActive = 0;
165							gpio->rtc.command.reading = 0;
166						}
167						gpio->rtc.bitsRead = 0;
168					}
169				}
170			} else {
171				gpio->rtc.bitsRead = 0;
172				gpio->rtc.bytesRemaining = 0;
173				gpio->rtc.commandActive = 0;
174				gpio->rtc.command.reading = 0;
175				gpio->rtc.transferStep = 0;
176			}
177		}
178		break;
179	}
180}
181
182void _rtcProcessByte(struct GBACartridgeGPIO* gpio) {
183	--gpio->rtc.bytesRemaining;
184	if (!gpio->rtc.commandActive) {
185		union RTCCommandData command;
186		command.packed = gpio->rtc.bits;
187		if (command.magic == 0x06) {
188			gpio->rtc.command = command;
189
190			gpio->rtc.bytesRemaining = RTC_BYTES[gpio->rtc.command.command];
191			gpio->rtc.commandActive = gpio->rtc.bytesRemaining > 0;
192			switch (command.command) {
193			case RTC_RESET:
194				gpio->rtc.control.packed = 0;
195				break;
196			case RTC_DATETIME:
197			case RTC_TIME:
198				_rtcUpdateClock(gpio);
199				break;
200			case RTC_FORCE_IRQ:
201			case RTC_CONTROL:
202				break;
203			}
204		} else {
205			GBALog(gpio->p, GBA_LOG_WARN, "Invalid RTC command byte: %02X", gpio->rtc.bits);
206		}
207	} else {
208		switch (gpio->rtc.command.command) {
209		case RTC_CONTROL:
210			gpio->rtc.control.packed = gpio->rtc.bits;
211			break;
212		case RTC_FORCE_IRQ:
213			GBALog(gpio->p, GBA_LOG_STUB, "Unimplemented RTC command %u", gpio->rtc.command.command);
214			break;
215		case RTC_RESET:
216		case RTC_DATETIME:
217		case RTC_TIME:
218			break;
219		}
220	}
221
222	gpio->rtc.bits = 0;
223	gpio->rtc.bitsRead = 0;
224	if (!gpio->rtc.bytesRemaining) {
225		gpio->rtc.commandActive = 0;
226		gpio->rtc.command.reading = 0;
227	}
228}
229
230unsigned _rtcOutput(struct GBACartridgeGPIO* gpio) {
231	uint8_t outputByte = 0;
232	switch (gpio->rtc.command.command) {
233	case RTC_CONTROL:
234		outputByte = gpio->rtc.control.packed;
235		break;
236	case RTC_DATETIME:
237	case RTC_TIME:
238		outputByte = gpio->rtc.time[7 - gpio->rtc.bytesRemaining];
239		break;
240	case RTC_FORCE_IRQ:
241	case RTC_RESET:
242		break;
243	}
244	unsigned output = (outputByte >> gpio->rtc.bitsRead) & 1;
245	return output;
246}
247
248void _rtcUpdateClock(struct GBACartridgeGPIO* gpio) {
249	time_t t;
250	struct GBARTCSource* rtc = gpio->p->rtcSource;
251	if (rtc) {
252		rtc->sample(rtc);
253		t = rtc->unixTime(rtc);
254	} else {
255		t = time(0);
256	}
257	struct tm date;
258#ifdef _WIN32
259	date = *localtime(&t);
260#else
261	localtime_r(&t, &date);
262#endif
263	gpio->rtc.time[0] = _rtcBCD(date.tm_year - 100);
264	gpio->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
265	gpio->rtc.time[2] = _rtcBCD(date.tm_mday);
266	gpio->rtc.time[3] = _rtcBCD(date.tm_wday);
267	if (gpio->rtc.control.hour24) {
268		gpio->rtc.time[4] = _rtcBCD(date.tm_hour);
269	} else {
270		gpio->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
271	}
272	gpio->rtc.time[5] = _rtcBCD(date.tm_min);
273	gpio->rtc.time[6] = _rtcBCD(date.tm_sec);
274}
275
276unsigned _rtcBCD(unsigned value) {
277	int counter = value % 10;
278	value /= 10;
279	counter += (value % 10) << 4;
280	return counter;
281}
282
283// == Gyro
284
285void GBAGPIOInitGyro(struct GBACartridgeGPIO* gpio) {
286	gpio->gpioDevices |= GPIO_GYRO;
287	gpio->gyroSample = 0;
288	gpio->gyroEdge = 0;
289}
290
291void _gyroReadPins(struct GBACartridgeGPIO* gpio) {
292	struct GBARotationSource* gyro = gpio->p->rotationSource;
293	if (!gyro) {
294		return;
295	}
296
297	if (gpio->p0) {
298		if (gyro->sample) {
299			gyro->sample(gyro);
300		}
301		int32_t sample = gyro->readGyroZ(gyro);
302
303		// Normalize to ~12 bits, focused on 0x6C0
304		gpio->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
305	}
306
307	if (gpio->gyroEdge && !gpio->p1) {
308		// Write bit on falling edge
309		unsigned bit = gpio->gyroSample >> 15;
310		gpio->gyroSample <<= 1;
311		_outputPins(gpio, bit << 2);
312	}
313
314	gpio->gyroEdge = gpio->p1;
315}
316
317// == Rumble
318
319void GBAGPIOInitRumble(struct GBACartridgeGPIO* gpio) {
320	gpio->gpioDevices |= GPIO_RUMBLE;
321}
322
323void _rumbleReadPins(struct GBACartridgeGPIO* gpio) {
324	struct GBARumble* rumble = gpio->p->rumble;
325	if (!rumble) {
326		return;
327	}
328
329	rumble->setRumble(rumble, gpio->p3);
330}
331
332// == Light sensor
333
334void GBAGPIOInitLightSensor(struct GBACartridgeGPIO* gpio) {
335	gpio->gpioDevices |= GPIO_LIGHT_SENSOR;
336	gpio->lightCounter = 0;
337	gpio->lightEdge = false;
338	gpio->lightSample = 0xFF;
339}
340
341void _lightReadPins(struct GBACartridgeGPIO* gpio) {
342	if (gpio->p2) {
343		// Boktai chip select
344		return;
345	}
346	if (gpio->p1) {
347		struct GBALuminanceSource* lux = gpio->p->luminanceSource;
348		GBALog(gpio->p, GBA_LOG_DEBUG, "[SOLAR] Got reset");
349		gpio->lightCounter = 0;
350		if (lux) {
351			lux->sample(lux);
352			gpio->lightSample = lux->readLuminance(lux);
353		} else {
354			gpio->lightSample = 0xFF;
355		}
356	}
357	if (gpio->p0 && gpio->lightEdge) {
358		++gpio->lightCounter;
359	}
360	gpio->lightEdge = !gpio->p0;
361
362	bool sendBit = gpio->lightCounter >= gpio->lightSample;
363	_outputPins(gpio, sendBit << 3);
364	GBALog(gpio->p, GBA_LOG_DEBUG, "[SOLAR] Output %u with pins %u", gpio->lightCounter, gpio->pinState);
365}
366
367// == Tilt (not technically GPIO)
368
369void GBAGPIOInitTilt(struct GBACartridgeGPIO* gpio) {
370	gpio->gpioDevices |= GPIO_TILT;
371	gpio->tiltX = 0xFFF;
372	gpio->tiltY = 0xFFF;
373	gpio->tiltState = 0;
374}
375
376void GBAGPIOTiltWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint8_t value) {
377	switch (address) {
378	case 0x8000:
379		if (value == 0x55) {
380			gpio->tiltState = 1;
381		} else {
382			GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
383		}
384		break;
385	case 0x8100:
386		if (value == 0xAA && gpio->tiltState == 1) {
387			gpio->tiltState = 0;
388			struct GBARotationSource* rotationSource = gpio->p->rotationSource;
389			if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
390				return;
391			}
392			if (rotationSource->sample) {
393				rotationSource->sample(rotationSource);
394			}
395			int32_t x = rotationSource->readTiltX(rotationSource);
396			int32_t y = rotationSource->readTiltY(rotationSource);
397			// Normalize to ~12 bits, focused on 0x3A0
398			gpio->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
399			gpio->tiltY = (y >> 21) + 0x3A0;
400		} else {
401			GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
402		}
403		break;
404	default:
405		GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
406		break;
407	}
408}
409
410uint8_t GBAGPIOTiltRead(struct GBACartridgeGPIO* gpio, uint32_t address) {
411	switch (address) {
412	case 0x8200:
413		return gpio->tiltX & 0xFF;
414	case 0x8300:
415		return ((gpio->tiltX >> 8) & 0xF) | 0x80;
416	case 0x8400:
417		return gpio->tiltY & 0xFF;
418	case 0x8500:
419		return (gpio->tiltY >> 8) & 0xF;
420	default:
421		GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor read from %04x", address);
422		break;
423	}
424	return 0xFF;
425}
426
427// == Serialization
428
429void GBAGPIOSerialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state) {
430	state->gpio.readWrite = gpio->readWrite;
431	state->gpio.pinState = gpio->pinState;
432	state->gpio.pinDirection = gpio->direction;
433	state->gpio.devices = gpio->gpioDevices;
434	state->gpio.rtc = gpio->rtc;
435	state->gpio.gyroSample = gpio->gyroSample;
436	state->gpio.gyroEdge = gpio->gyroEdge;
437	state->gpio.tiltSampleX = gpio->tiltX;
438	state->gpio.tiltSampleY = gpio->tiltY;
439	state->gpio.tiltState = gpio->tiltState;
440	state->gpio.lightCounter = gpio->lightCounter;
441	state->gpio.lightSample = gpio->lightSample;
442	state->gpio.lightEdge = gpio->lightEdge;
443}
444
445void GBAGPIODeserialize(struct GBACartridgeGPIO* gpio, struct GBASerializedState* state) {
446	gpio->readWrite = state->gpio.readWrite;
447	gpio->pinState = state->gpio.pinState;
448	gpio->direction = state->gpio.pinDirection;
449	// TODO: Deterministic RTC
450	gpio->rtc = state->gpio.rtc;
451	gpio->gyroSample = state->gpio.gyroSample;
452	gpio->gyroEdge = state->gpio.gyroEdge;
453	gpio->tiltX = state->gpio.tiltSampleX;
454	gpio->tiltY = state->gpio.tiltSampleY;
455	gpio->tiltState = state->gpio.tiltState;
456	gpio->lightCounter = state->gpio.lightCounter;
457	gpio->lightSample = state->gpio.lightSample;
458	gpio->lightEdge = state->gpio.lightEdge;
459}