Implement gyro

This commit is contained in:
Jeffrey Pfau 2013-10-21 02:54:52 -07:00
parent c77ed8c11e
commit 0458184a5e
6 changed files with 80 additions and 5 deletions

View File

@ -1,6 +1,7 @@
#include "gba.h"
#include "gba-gpio.h"
#include "gba-sensors.h"
#include <time.h>
@ -13,6 +14,8 @@ static void _rtcProcessByte(struct GBACartridgeGPIO* gpio);
static void _rtcUpdateClock(struct GBACartridgeGPIO* gpio);
static unsigned _rtcBCD(unsigned value);
static void _gyroReadPins(struct GBACartridgeGPIO* gpio);
static const int RTC_BYTES[8] = {
0, // Force reset
0, // Empty
@ -45,7 +48,7 @@ void GBAGPIOWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint16_t valu
gpio->readWrite = value;
break;
default:
GBALog(0, GBA_LOG_WARN, "Invalid GPIO address");
GBALog(gpio->p, GBA_LOG_WARN, "Invalid GPIO address");
}
if (gpio->readWrite) {
@ -73,6 +76,10 @@ void _readPins(struct GBACartridgeGPIO* gpio) {
if (gpio->gpioDevices & GPIO_RTC) {
_rtcReadPins(gpio);
}
if (gpio->gpioDevices & GPIO_GYRO) {
_gyroReadPins(gpio);
}
}
void _outputPins(struct GBACartridgeGPIO* gpio, unsigned pins) {
@ -81,7 +88,9 @@ void _outputPins(struct GBACartridgeGPIO* gpio, unsigned pins) {
old &= gpio->direction;
gpio->gpioBase[0] = old | (pins & ~gpio->direction & 0xF);
}
};
}
// == RTC
void _rtcReadPins(struct GBACartridgeGPIO* gpio) {
// Transfer sequence:
@ -115,7 +124,7 @@ void _rtcReadPins(struct GBACartridgeGPIO* gpio) {
// GPIO direction should always != reading
if (gpio->dir1) {
if (gpio->rtc.command.reading) {
GBALog(0, GBA_LOG_GAME_ERROR, "Attempting to write to RTC while in read mode");
GBALog(gpio->p, GBA_LOG_GAME_ERROR, "Attempting to write to RTC while in read mode");
}
++gpio->rtc.bitsRead;
if (gpio->rtc.bitsRead == 8) {
@ -168,7 +177,7 @@ void _rtcProcessByte(struct GBACartridgeGPIO* gpio) {
break;
}
} else {
GBALog(0, GBA_LOG_WARN, "Invalid RTC command byte: %02X", gpio->rtc.bits);
GBALog(gpio->p, GBA_LOG_WARN, "Invalid RTC command byte: %02X", gpio->rtc.bits);
}
} else {
switch (gpio->rtc.command.command) {
@ -176,7 +185,7 @@ void _rtcProcessByte(struct GBACartridgeGPIO* gpio) {
gpio->rtc.control.packed = gpio->rtc.bits;
break;
case RTC_FORCE_IRQ:
GBALog(0, GBA_LOG_STUB, "Unimplemented RTC command %u", gpio->rtc.command.command);
GBALog(gpio->p, GBA_LOG_STUB, "Unimplemented RTC command %u", gpio->rtc.command.command);
break;
case RTC_RESET:
case RTC_DATETIME:
@ -234,3 +243,38 @@ unsigned _rtcBCD(unsigned value) {
counter += (value % 10) << 4;
return counter;
}
// == Gyro
void GBAGPIOInitGyro(struct GBACartridgeGPIO* gpio) {
gpio->gpioDevices |= GPIO_GYRO;
gpio->gyroSample = 0;
gpio->gyroEdge = 0;
}
void _gyroReadPins(struct GBACartridgeGPIO* gpio) {
struct GBARotationSource* gyro = gpio->p->rotationSource;
if (!gyro) {
return;
}
if (gpio->p0) {
if (gyro->sample) {
gyro->sample(gyro);
}
int32_t sample = gyro->readGyroZ(gyro);
// Normalize to ~12 bits, focused on 0x6C0
gpio->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
}
if (gpio->gyroEdge && !gpio->p1) {
// Write bit on falling edge
unsigned bit = gpio->gyroSample >> 15;
gpio->gyroSample <<= 1;
_outputPins(gpio, bit << 2);
}
gpio->gyroEdge = gpio->p1;
}

View File

@ -64,6 +64,7 @@ struct GBARTC {
};
struct GBACartridgeGPIO {
struct GBA* p;
int gpioDevices;
enum GPIODirection readWrite;
uint16_t* gpioBase;
@ -89,6 +90,9 @@ struct GBACartridgeGPIO {
};
struct GBARTC rtc;
uint16_t gyroSample;
int gyroEdge;
};
void GBAGPIOInit(struct GBACartridgeGPIO* gpio, uint16_t* gpioBase);
@ -96,4 +100,6 @@ void GBAGPIOWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint16_t valu
void GBAGPIOInitRTC(struct GBACartridgeGPIO* gpio);
void GBAGPIOInitGyro(struct GBACartridgeGPIO* gpio);
#endif

View File

@ -34,6 +34,7 @@ void GBAMemoryInit(struct GBAMemory* memory) {
memory->wram = mmap(0, SIZE_WORKING_RAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
memory->iwram = mmap(0, SIZE_WORKING_IRAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
memory->rom = 0;
memory->gpio.p = memory->p;
memset(memory->io, 0, sizeof(memory->io));
memset(memory->dma, 0, sizeof(memory->dma));

15
src/gba/gba-sensors.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef GBA_SENSORS_H
#define GBA_SENSORS_H
#include <stdint.h>
struct GBARotationSource {
void (*sample)(struct GBARotationSource*);
int32_t (*readTiltX)(struct GBARotationSource*);
int32_t (*readTiltY)(struct GBARotationSource*);
int32_t (*readGyroZ)(struct GBARotationSource*);
};
#endif

View File

@ -33,6 +33,7 @@ static const struct GBACartridgeOverride _overrides[] = {
{ 'EVXA', SAVEDATA_FLASH1M, GPIO_RTC },
{ 'E4XA', SAVEDATA_FLASH1M, GPIO_NONE },
{ 'EEPB', SAVEDATA_FLASH1M, GPIO_RTC },
{ 'EWZR', SAVEDATA_SRAM, GPIO_RUMBLE | GPIO_GYRO },
{ 0, 0, 0 }
};
@ -69,6 +70,7 @@ void GBAInit(struct GBA* gba) {
gba->springIRQ = 0;
gba->keySource = 0;
gba->rotationSource = 0;
gba->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR;
@ -485,6 +487,10 @@ void _checkOverrides(struct GBA* gba, uint32_t id) {
if (_overrides[i].gpio & GPIO_RTC) {
GBAGPIOInitRTC(&gba->memory.gpio);
}
if (_overrides[i].gpio & GPIO_GYRO) {
GBAGPIOInitGyro(&gba->memory.gpio);
}
return;
}
}

View File

@ -54,6 +54,8 @@ enum GBAKey {
GBA_KEY_L = 9
};
struct GBARotationSource;
struct GBABoard {
struct ARMBoard d;
struct GBA* p;
@ -85,6 +87,7 @@ struct GBA {
int springIRQ;
int* keySource;
struct GBARotationSource* rotationSource;
const char* activeFile;
const char* savefile;