DS SPI: Add TSC stub

This commit is contained in:
Vicki Pfau 2017-02-22 16:43:44 -08:00
parent 71a590b492
commit 198efff577
5 changed files with 121 additions and 4 deletions

View File

@ -16,6 +16,7 @@ CXX_GUARD_START
#include <mgba/internal/ds/dma.h>
#include <mgba/internal/ds/io.h>
#include <mgba/internal/ds/slot1.h>
#include <mgba/internal/ds/spi.h>
enum DSMemoryRegion {
DS7_REGION_BIOS = 0x0,
@ -86,6 +87,7 @@ struct DSMemory {
uint16_t io7[DS7_REG_MAX >> 1];
uint16_t io9[DS9_REG_MAX >> 1];
struct DSSlot1 slot1;
struct DSSPIBus spiBus;
uint16_t vramMirror[9][0x40];
uint16_t vramMode[9][8];

View File

@ -11,6 +11,7 @@
CXX_GUARD_START
#include <mgba/core/log.h>
#include <mgba/core/timing.h>
mLOG_DECLARE_CATEGORY(DS_SPI);
@ -23,13 +24,43 @@ DECL_BIT(DSSPICNT, CSHold, 11);
DECL_BIT(DSSPICNT, DoIRQ, 14);
DECL_BIT(DSSPICNT, Enable, 15);
DECL_BITFIELD(DSTSCControlByte, uint8_t);
// TODO
DECL_BITS(DSTSCControlByte, Channel, 4, 3);
DECL_BIT(DSTSCControlByte, Control, 7);
enum {
DS_SPI_DEV_POWERMAN = 0,
DS_SPI_DEV_FIRMWARE = 1,
DS_SPI_DEV_TSC = 2
};
enum {
DS_TSC_CHANNEL_TEMP_0 = 0,
DS_TSC_CHANNEL_TS_Y = 1,
DS_TSC_CHANNEL_BATTERY_V = 2,
DS_TSC_CHANNEL_TS_Z1 = 3,
DS_TSC_CHANNEL_TS_Z2 = 4,
DS_TSC_CHANNEL_TS_X = 5,
DS_TSC_CHANNEL_MIC = 6,
DS_TSC_CHANNEL_TEMP_1 = 7,
};
struct DSSPIBus {
bool holdEnabled;
uint8_t firmwareMode;
struct mTimingEvent tscEvent;
uint8_t tscControlByte;
uint16_t tscRegister;
int tscOffset;
uint8_t powmgrByte;
};
struct DS;
void DSSPIReset(struct DS* ds);
DSSPICNT DSSPIWriteControl(struct DS* ds, uint16_t control);
void DSSPIWrite(struct DS* ds, uint8_t datum);

View File

@ -246,7 +246,7 @@ void DS7IOWrite(struct DS* ds, uint32_t address, uint16_t value) {
break;
case DS7_REG_SPIDATA:
DSSPIWrite(ds, value);
return;
break;
default:
{
uint32_t v2 = DSIOWrite(&ds->ds7, address, value);

View File

@ -181,6 +181,8 @@ void DSMemoryReset(struct DS* ds) {
ds->ds7.memory.slot1Access = true;
ds->ds9.memory.slot1Access = false;
DSSPIReset(ds);
DSVideoConfigureVRAM(ds, 0, 0);
DSVideoConfigureVRAM(ds, 1, 0);
DSVideoConfigureVRAM(ds, 2, 0);

View File

@ -9,13 +9,95 @@
mLOG_DEFINE_CATEGORY(DS_SPI, "DS SPI");
static void _tscEvent(struct mTiming*, void* context, uint32_t cyclesLate);
void DSSPIReset(struct DS* ds) {
memset(&ds->memory.spiBus, 0, sizeof(ds->memory.spiBus));
ds->memory.spiBus.tscEvent.name = "DS SPI TSC";
ds->memory.spiBus.tscEvent.context = ds;
ds->memory.spiBus.tscEvent.callback = _tscEvent;
ds->memory.spiBus.tscEvent.priority = 0x60;
}
DSSPICNT DSSPIWriteControl(struct DS* ds, uint16_t control) {
// TODO
mLOG(DS_SPI, STUB, "Unimplemented control write: %04X", control);
if (!ds->memory.spiBus.holdEnabled) {
ds->memory.spiBus.tscControlByte = 0;
}
ds->memory.spiBus.holdEnabled = DSSPICNTIsCSHold(control);
return control;
}
void DSSPIWrite(struct DS* ds, uint8_t datum) {
mLOG(DS_SPI, STUB, "Unimplemented data write: %02X", datum);
// TODO
DSSPICNT control = ds->memory.io7[DS7_REG_SPICNT >> 1];
if (!DSSPICNTIsEnable(control)) {
return;
}
uint32_t baud = 19 - DSSPICNTGetBaud(control);
baud = DS_ARM7TDMI_FREQUENCY >> baud;
switch (DSSPICNTGetChipSelect(control)) {
case DS_SPI_DEV_TSC:
control = DSSPICNTFillBusy(control);
mTimingDeschedule(&ds->ds7.timing, &ds->memory.spiBus.tscEvent);
mTimingSchedule(&ds->ds7.timing, &ds->memory.spiBus.tscEvent, baud);
break;
case DS_SPI_DEV_POWERMAN:
case DS_SPI_DEV_FIRMWARE:
default:
mLOG(DS_SPI, STUB, "Unimplemented data write: %04X:%02X", control, datum);
break;
}
ds->memory.io7[DS7_REG_SPICNT >> 1] = control;
}
static void _tscEvent(struct mTiming* timing, void* context, uint32_t cyclesLate) {
UNUSED(cyclesLate);
struct DS* ds = context;
uint8_t oldValue = ds->memory.io7[DS7_REG_SPIDATA >> 1];
DSSPICNT control = ds->memory.io7[DS7_REG_SPICNT >> 1];
uint8_t newValue = 0;
// TODO: /PENIRQ
if (ds->memory.spiBus.tscOffset > 0) {
// TODO: Make generic?
if (ds->memory.spiBus.tscOffset < 12) {
newValue = (ds->memory.spiBus.tscRegister & 0x1F) << 3;
ds->memory.spiBus.tscOffset = 12;
} else {
newValue = 0;
}
} else if (ds->memory.spiBus.tscControlByte) {
switch (DSTSCControlByteGetChannel(ds->memory.spiBus.tscControlByte)) {
case DS_TSC_CHANNEL_TS_X:
mLOG(DS_SPI, STUB, "Unimplemented TSC channel X");
ds->memory.spiBus.tscRegister = 0;
break;
case DS_TSC_CHANNEL_TS_Y:
mLOG(DS_SPI, STUB, "Unimplemented TSC channel Y");
ds->memory.spiBus.tscRegister = 0xFFF;
break;
case DS_TSC_CHANNEL_TEMP_0:
case DS_TSC_CHANNEL_BATTERY_V:
case DS_TSC_CHANNEL_TS_Z1:
case DS_TSC_CHANNEL_TS_Z2:
case DS_TSC_CHANNEL_MIC:
case DS_TSC_CHANNEL_TEMP_1:
ds->memory.spiBus.tscRegister = 0;
mLOG(DS_SPI, STUB, "Unimplemented TSC channel %i", DSTSCControlByteGetChannel(ds->memory.spiBus.tscControlByte));
}
newValue = (ds->memory.spiBus.tscRegister >> 5) & 0x7F;
ds->memory.spiBus.tscOffset = 7;
}
if (DSTSCControlByteIsControl(oldValue)) {
ds->memory.spiBus.tscControlByte = oldValue;
ds->memory.spiBus.tscOffset = 0;
}
control = DSSPICNTClearBusy(control);
ds->memory.io7[DS7_REG_SPIDATA >> 1] = newValue;
ds->memory.io7[DS7_REG_SPICNT >> 1] = control;
if (DSSPICNTIsDoIRQ(control)) {
DSRaiseIRQ(ds->ds7.cpu, ds->ds7.memory.io, DS_IRQ_SPI);
}
}