From ce240f42165c623c7c289787916dc148b0300f8a Mon Sep 17 00:00:00 2001 From: StapleButter Date: Mon, 1 May 2017 22:27:05 +0200 Subject: more wifi work: timers and their IRQs --- src/NDS.h | 1 + src/Wifi.cpp | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/Wifi.h | 11 ++++ 3 files changed, 168 insertions(+), 7 deletions(-) diff --git a/src/NDS.h b/src/NDS.h index 480341f..84616d9 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -28,6 +28,7 @@ enum { Event_LCD = 0, Event_SPU, + Event_Wifi, Event_ROMTransfer, diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 7b59315..a6a5d55 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -33,6 +33,9 @@ u16 IO[0x1000>>1]; u16 Random; +u64 USCounter; +u64 USCompare; + u16 BBCnt; u8 BBWrite; u8 BBRegs[0x100]; @@ -91,6 +94,102 @@ void Reset() } +void SetIRQ(u32 irq) +{ + u32 oldflags = IOPORT(W_IF) & IOPORT(W_IE); + + IOPORT(W_IF) |= (1<> 2) & 0x1F; @@ -152,6 +251,16 @@ u16 Read(u32 addr) case W_Preamble: return IOPORT(W_Preamble) & 0x0003; + case W_USCount0: return (u16)(USCounter & 0xFFFF); + case W_USCount1: return (u16)((USCounter >> 16) & 0xFFFF); + case W_USCount2: return (u16)((USCounter >> 32) & 0xFFFF); + case W_USCount3: return (u16)(USCounter >> 48); + + case W_USCompare0: return (u16)(USCompare & 0xFFFF); + case W_USCompare1: return (u16)((USCompare >> 16) & 0xFFFF); + case W_USCompare2: return (u16)((USCompare >> 32) & 0xFFFF); + case W_USCompare3: return (u16)(USCompare >> 48); + case W_BBRead: if ((IOPORT(W_BBCnt) & 0xF000) != 0x6000) { @@ -175,6 +284,12 @@ u16 Read(u32 addr) rdaddr += 2; if (rdaddr == (IOPORT(W_RXBufEnd) & 0x1FFE)) rdaddr = (IOPORT(W_RXBufBegin) & 0x1FFE); + if (rdaddr == (IOPORT(W_RXBufGapAddr) & 0x1FFE)) + { + rdaddr += ((IOPORT(W_RXBufGapSize) & 0x0FFF) << 1); + if (rdaddr >= (IOPORT(W_RXBufEnd) & 0x1FFE)) + rdaddr = rdaddr + (IOPORT(W_RXBufBegin) & 0x1FFE) - (IOPORT(W_RXBufEnd) & 0x1FFE); + } IOPORT(W_RXBufReadAddr) = rdaddr & 0x1FFE; IOPORT(W_RXBufDataRead) = ret; @@ -267,21 +382,23 @@ void Write(u32 addr, u16 val) break; case W_IF: - // IF: TODO + IOPORT(W_IF) &= ~val; + return; + case W_IFSet: + IOPORT(W_IF) |= (val & 0xFBFF); + printf("wifi: force-setting IF %04X\n", val); return; - case W_IE: - printf("WIFI IE=%04X\n", val); - break; case W_PowerState: if (val & 0x0002) { - // TODO: IRQ11 + // TODO: delay for this + SetIRQ(11); IOPORT(W_PowerState) = 0x0000; } return; case W_PowerForce: - printf("WIFI: forcing power %04X\n", val); + if ((val&0x8001)==0x8000) printf("WIFI: forcing power %04X\n", val); val &= 0x8001; if (val == 0x8001) { @@ -292,6 +409,34 @@ void Write(u32 addr, u16 val) IOPORT(W_RFStatus) = 9; } break; + case W_PowerUS: + // schedule timer event when the clock is enabled + // TODO: check whether this resets USCOUNT (and also which other events can reset it) + if ((IOPORT(W_PowerUS) & 0x0001) && !(val & 0x0001)) + NDS::ScheduleEvent(NDS::Event_Wifi, true, 33, USTimer, 0); + else if (!(IOPORT(W_PowerUS) & 0x0001) && (val & 0x0001)) + NDS::CancelEvent(NDS::Event_Wifi); + break; + + case W_USCountCnt: val &= 0x0001; break; + case W_USCompareCnt: + if (val & 0x0002) SetIRQ14(true); + val &= 0x0001; + break; + + case W_USCount0: USCounter = (USCounter & 0xFFFFFFFFFFFF0000) | (u64)val; return; + case W_USCount1: USCounter = (USCounter & 0xFFFFFFFF0000FFFF) | ((u64)val << 16); return; + case W_USCount2: USCounter = (USCounter & 0xFFFF0000FFFFFFFF) | ((u64)val << 32); return; + case W_USCount3: USCounter = (USCounter & 0x0000FFFFFFFFFFFF) | ((u64)val << 48); return; + + case W_USCompare0: + USCompare = (USCompare & 0xFFFFFFFFFFFF0000) | (u64)(val & 0xFC00); + if (val & 0x03FF) + printf("wifi: mysterious USCOMPARE bits set %08X%08X %04X\n", (u32)(USCompare>>32), (u32)USCompare, val); // TODO + return; + case W_USCompare1: USCompare = (USCompare & 0xFFFFFFFF0000FFFF) | ((u64)val << 16); return; + case W_USCompare2: USCompare = (USCompare & 0xFFFF0000FFFFFFFF) | ((u64)val << 32); return; + case W_USCompare3: USCompare = (USCompare & 0x0000FFFFFFFFFFFF) | ((u64)val << 48); return; case W_BBCnt: IOPORT(W_BBCnt) = val; @@ -320,12 +465,16 @@ void Write(u32 addr, u16 val) wraddr += 2; if (wraddr == (IOPORT(W_TXBufGapAddr) & 0x1FFE)) - wraddr += (IOPORT(W_TXBufGapSize) << 1); + wraddr += ((IOPORT(W_TXBufGapSize) & 0x0FFF) << 1); IOPORT(W_TXBufWriteAddr) = wraddr & 0x1FFE; } return; + case 0x80: + printf("BEACON ADDR %04X\n", val); + break; + // read-only ports case 0x000: case 0x044: diff --git a/src/Wifi.h b/src/Wifi.h index a351f7a..d28fda7 100644 --- a/src/Wifi.h +++ b/src/Wifi.h @@ -96,6 +96,15 @@ enum W_USCompareCnt = 0x0EA, W_CmdCountCnt = 0x0EE, + W_USCount0 = 0x0F8, + W_USCount1 = 0x0FA, + W_USCount2 = 0x0FC, + W_USCount3 = 0x0FE, + W_USCompare0 = 0x0F0, + W_USCompare1 = 0x0F2, + W_USCompare2 = 0x0F4, + W_USCompare3 = 0x0F6, + W_ContentFree = 0x10C, W_PreBeacon = 0x110, W_CmdCount = 0x118, @@ -133,6 +142,8 @@ enum void Reset(); +void USTimer(u32 param); + u16 Read(u32 addr); void Write(u32 addr, u16 val); -- cgit v1.2.3