Skip to content
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

Closed
LunarLambda opened this issue Feb 3, 2023 · 14 comments
Closed
Labels
hardware:link Issues in linking and serial subsystems platform:GBA Game Boy Advance-related issues
Milestone

Comments

@LunarLambda
Copy link
Contributor

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.

@endrift endrift added platform:GBA Game Boy Advance-related issues hardware:link Issues in linking and serial subsystems labels Feb 3, 2023
@endrift endrift added this to the mGBA 0.10.2 milestone Feb 3, 2023
@endrift
Copy link
Member

endrift commented Feb 3, 2023

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.

@LunarLambda
Copy link
Contributor Author

LunarLambda commented Feb 3, 2023

test roms: green screen = client detected (server) / transfer successful (car-mode), red screen = no client (server) / transfer timed out (car-mode)

car-mode.zip

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

@endrift
Copy link
Member

endrift commented Feb 3, 2023

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.

@LunarLambda
Copy link
Contributor Author

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

@endrift
Copy link
Member

endrift commented Feb 3, 2023

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.

@LunarLambda
Copy link
Contributor Author

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

@endrift
Copy link
Member

endrift commented Feb 3, 2023

Maybe it's hitting the timeout then. Which it shouldn't be, considering the transfer should take ~31 ms, not 50.

@LunarLambda
Copy link
Contributor Author

Why would the transfer take 31 ms? It's 32 bits at 256Kbit/s = ~0.1ms?

@endrift
Copy link
Member

endrift commented Feb 3, 2023

Because I'm half asleep and did the math wrong.

@LunarLambda
Copy link
Contributor Author

image

I based my code off this schematic, maybe that can help too

@endrift
Copy link
Member

endrift commented Feb 3, 2023

Does the server only check once for the background color set? If car-mode.gba starts before server.gba, it's set green.

@LunarLambda
Copy link
Contributor Author

it attempts transfer once a frame during vblank, and sets the bg color there

@LunarLambda
Copy link
Contributor Author

LunarLambda commented Feb 3, 2023

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;
        }
    }

@endrift
Copy link
Member

endrift commented Feb 3, 2023

I haven't pushed the patches yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hardware:link Issues in linking and serial subsystems platform:GBA Game Boy Advance-related issues
Projects
None yet
Development

No branches or pull requests

2 participants