-
-
Notifications
You must be signed in to change notification settings - Fork 778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serial I/O registers do not exhibit proper pull-up/pull-down behaviour #2810
Comments
It looks like this is handled properly when there's no driver attached, which...is never the case in the Qt version. Can you check the SDL version to see if this is handled properly? I don't have a test ROM. |
test roms: green screen = client detected (server) / transfer successful (car-mode), red screen = no client (server) / transfer timed out (car-mode) both show red on hardware, but show green in mgba-qt. the transfers do work correctly though when multiplayer windows are setup, so the code is functional last I tried the SDL frontend didn't compile/run correctly on my system, so I need to look into that |
Both of these test ROMs look weird to me. server.gba never sets bit 3 to 0, so master's SI bit is never pulled low. car-mode.gba never clears bit 0, so neither GBA is driving the clock. Neither of these should work on hardware, unless there's something I'm missing. |
Pretty sure mGBA's IO viewer behaves weirdly with serial registers. Server doesn't need to set SO low normally. unfortunately I'm just heading to lunch. reference code in 30 minutes |
I was setting breakpoints in gdb, not just looking at the viewer. Am I supposed to be running server on P1 and car-mode on P2? Doing that, P2 turns green but P1 doesn't. Which is weird, but the SI bit is changing between low and high. |
static volatile bool hadTrans = false;
void sioInit(bool master)
{
REG_RCNT = R_MODE_SPI_32BIT;
REG_SIOCNT = SIO_MODE_SPI_32BIT | \
(master ? SPI_CLOCK_256KHZ : SPI_CLOCK_EXTERNAL) | \
SPI_SO_HIGH | SIO_IRQ_ENABLE;
}
bool sioWaitIRQ()
{
// 50 ms timeout
REG_TM0CNT = TIMER_FREQ_16KHZ;
REG_TM0VAL = 65536 - 819;
REG_TM1CNT = TIMER_FREQ_CASCADE | TIMER_ENABLE;
REG_TM1VAL = 0;
REG_TM0CNT |= TIMER_ENABLE;
while (!hadTrans && !REG_TM1VAL);
return hadTrans;
}
bool sioWait()
{
// 50 ms timeout
REG_TM0CNT = TIMER_FREQ_16KHZ;
REG_TM0VAL = 65536 - 819;
REG_TM1CNT = TIMER_FREQ_CASCADE | TIMER_ENABLE;
REG_TM1VAL = 0;
REG_TM0CNT |= TIMER_ENABLE;
while ((REG_SIOCNT & SPI_START) && !REG_TM1VAL);
return !(REG_SIOCNT & SPI_START);
}
bool sioWaitReady()
{
// 50 ms timeout
REG_TM0CNT = TIMER_FREQ_16KHZ;
REG_TM0VAL = 65536 - 819;
REG_TM1CNT = TIMER_FREQ_CASCADE | TIMER_ENABLE;
REG_TM1VAL = 0;
REG_TM0CNT |= TIMER_ENABLE;
while ((REG_SIOCNT & SPI_SI_STATE) && !REG_TM1VAL);
return !(REG_SIOCNT & SPI_SI_STATE);
}
void sioComplete(u16 irq)
{
(void)irq;
hadTrans = true;
}
bool sioTransfer(u32 value)
{
hadTrans = false;
if (!sioWaitReady())
{
return false;
}
REG_SIODATA32 = value;
REG_SIOCNT |= SPI_START;
if (!sioWait())
{
return false;
}
return true;
}
bool sioReceive(u32 *value)
{
hadTrans = false;
REG_SIOCNT &= ~SPI_SO_HIGH;
REG_SIOCNT |= SPI_START;
if (!sioWait())
{
return false;
}
REG_SIOCNT |= SPI_SO_HIGH;
*value = REG_SIODATA32;
return true;
} https://github.com/LunarLambda/sdk-seven/blob/main/libseven/include/seven/hw/serial/spi.h Both ROMs just check if sioReceive (slave)/sioTransfer (master) succeed |
Maybe it's hitting the timeout then. Which it shouldn't be, considering the transfer should take ~31 ms, not 50. |
Why would the transfer take 31 ms? It's 32 bits at 256Kbit/s = ~0.1ms? |
Because I'm half asleep and did the math wrong. |
Does the server only check once for the background color set? If car-mode.gba starts before server.gba, it's set green. |
it attempts transfer once a frame during vblank, and sets the bg color there |
from the debug logs it does seem like transfers are running correctly. usually i start server.gba first but it didn't seem to make a difference in my testing while (true)
{
biosVBlankIntrWait();
u32 data = randNext();
if (sioTransfer(data))
{
BG_PALETTE[0] = 0x03E0;
}
else
{
BG_PALETTE[0] = 0x001F;
}
} |
I haven't pushed the patches yet. |
I haven't (or am able to) test every case of this, but most notably, in Normal mode, bit 2 of SIOCNT is supposed to show the state of the SO signal of the opposing GBA. It's a pull-up, meaning when no GBA is connected, that bit should be 1.
A lot (if not all) serial code is meant to pull SO low to signal readiness. However, in mGBA, when no multiplayer window is open, that bit always returns 0, causing a client to be falsely detected.
The text was updated successfully, but these errors were encountered: