mirror of https://github.com/mgba-emu/mgba.git
DS SPI: Add TSC stub
This commit is contained in:
parent
71a590b492
commit
198efff577
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
88
src/ds/spi.c
88
src/ds/spi.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue