From 70e16613420f3f84149810e9621c4cb65c52bd2c Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 4 Feb 2014 00:39:55 -0800 Subject: [PATCH] Begin SIO --- src/gba/gba-io.c | 12 +++++++- src/gba/gba-sio.c | 29 +++++++++++++++++++ src/gba/gba-sio.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++ src/gba/gba.c | 3 ++ src/gba/gba.h | 2 ++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/gba/gba-sio.c create mode 100644 src/gba/gba-sio.h diff --git a/src/gba/gba-io.c b/src/gba/gba-io.c index eb80bb0b5..9c163cb31 100644 --- a/src/gba/gba-io.c +++ b/src/gba/gba-io.c @@ -1,6 +1,7 @@ #include "gba-io.h" #include "gba-serialize.h" +#include "gba-sio.h" #include "gba-video.h" static const int _isValidRegister[REG_MAX >> 1] = { @@ -89,7 +90,7 @@ static const int _isSpecialRegister[REG_MAX >> 1] = { void GBAIOInit(struct GBA* gba) { gba->memory.io[REG_DISPCNT >> 1] = 0x0080; - gba->memory.io[REG_RCNT >> 1] = 0x8000; + gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL; gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF; } @@ -250,6 +251,15 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { GBATimerWriteTMCNT_HI(gba, 3, value); break; + // SIO + case REG_SIOCNT: + GBASIOWriteSIOCNT(&gba->sio, value); + break; + case REG_RCNT: + value &= 0xC1FF; + GBASIOWriteRCNT(&gba->sio, value); + break; + // Interrupts and misc case REG_WAITCNT: GBAAdjustWaitstates(&gba->memory, value); diff --git a/src/gba/gba-sio.c b/src/gba/gba-sio.c new file mode 100644 index 000000000..31e84b97d --- /dev/null +++ b/src/gba/gba-sio.c @@ -0,0 +1,29 @@ +#include "gba-sio.h" + +#include "gba-io.h" + +static void _switchMode(struct GBASIO* sio) { + int mode = ((sio->rcnt >> 14) & 0xC) | ((sio->siocnt >> 12) & 0x3); + if (mode < 8) { + sio->mode = (enum GBASIOMode) (mode & 0x3); + } else { + sio->mode = (enum GBASIOMode) (mode & 0xC); + } + // TODO: hangup if we have an existing connection +} + +void GBASIOInit(struct GBASIO* sio) { + sio->rcnt = RCNT_INITIAL; + sio->siocnt = 0; + _switchMode(sio); +} + +void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) { + sio->rcnt = value; + _switchMode(sio); +} + +void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) { + sio->siocnt = value; + _switchMode(sio); +} diff --git a/src/gba/gba-sio.h b/src/gba/gba-sio.h new file mode 100644 index 000000000..184b5067b --- /dev/null +++ b/src/gba/gba-sio.h @@ -0,0 +1,72 @@ +#ifndef GBA_SIO_H +#define GBA_SIO_H + +#include + +enum GBASIOMode { + SIO_NORMAL_8 = 0, + SIO_NORMAL_32 = 1, + SIO_MULTI = 2, + SIO_UART = 3, + SIO_GPIO = 8, + SIO_JOYBUS = 12 +}; + +enum GBASIOMultiMode { + VBA_LINK_COMPAT +}; + +enum { + RCNT_INITIAL = 0x8000 +}; + +struct GBASIODriver { + int (*attach)(struct GBASIODriver* driver); +}; + +struct GBASIO { + struct GBA* p; + + enum GBASIOMode mode; + enum GBASIOMultiMode multiMode; + struct GBASIODriver* driver; + + uint16_t rcnt; + union { + struct { + unsigned sc : 1; + unsigned internalSc : 1; + unsigned si : 1; + unsigned idleSo : 1; + unsigned : 4; + unsigned start : 1; + unsigned : 3; + unsigned length : 1; + unsigned : 1; + unsigned irq : 1; + unsigned : 1; + } normalControl; + + struct { + unsigned baud : 2; + unsigned slave : 1; + unsigned ready : 1; + unsigned id : 2; + unsigned error : 1; + unsigned busy : 1; + unsigned : 6; + unsigned irq : 1; + unsigned : 1; + } multiplayerControl; + + uint16_t siocnt; + }; +}; + +void GBASIOInit(struct GBASIO* sio); + +void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value); +void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value); +void GBASIOWriteSIOMLT_SEND(struct GBASIO* sio, uint16_t value); + +#endif diff --git a/src/gba/gba.c b/src/gba/gba.c index c0b8223ae..8adeeaa83 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -122,6 +122,9 @@ void GBAInit(struct GBA* gba) { GBAIOInit(gba); + gba->sio.p = gba; + GBASIOInit(&gba->sio); + gba->timersEnabled = 0; memset(gba->timers, 0, sizeof(gba->timers)); diff --git a/src/gba/gba.h b/src/gba/gba.h index 8b55ccd5d..0b33f5cae 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -7,6 +7,7 @@ #include "gba-memory.h" #include "gba-video.h" #include "gba-audio.h" +#include "gba-sio.h" #include @@ -74,6 +75,7 @@ struct GBA { struct GBAMemory memory; struct GBAVideo video; struct GBAAudio audio; + struct GBASIO sio; struct GBASync* sync;