From ce8b6bc7b96564eb6b981de36132087eece77227 Mon Sep 17 00:00:00 2001 From: luigi__ Date: Sun, 23 Aug 2009 19:45:01 +0000 Subject: [PATCH] Wifi: add support for periodic beacon transmission. The socket stuff works fine; I could see all the beacons by using an ethernet sniffer, as expected :) --- desmume/src/wifi.cpp | 107 +++++++++++++++++++++++++++++++++++++------ desmume/src/wifi.h | 7 ++- 2 files changed, 99 insertions(+), 15 deletions(-) diff --git a/desmume/src/wifi.cpp b/desmume/src/wifi.cpp index 8a3cc99e2..96e419062 100644 --- a/desmume/src/wifi.cpp +++ b/desmume/src/wifi.cpp @@ -621,6 +621,9 @@ static void WIFI_triggerIRQMask(u16 mask) static void WIFI_triggerIRQ(u8 irq) { + if (irq == 14) + wifiMac.BeaconCount2 = 0xFFFF; + WIFI_triggerIRQMask(1< 0x1000-6) { WIFI_LOG(1, "TX slot %i trying to send a packet overflowing from the TX buffer (address %04X). Attempt ignored.\n", @@ -719,28 +722,28 @@ static void WIFI_TXStart(u8 slot) return; } - /* 12 byte header TX Header: http://www.akkit.org/info/dswifi.htm#FmtTx */ + // 12 byte header TX Header: http://www.akkit.org/info/dswifi.htm#FmtTx txLen = wifiMac.circularBuffer[address+5]; - /* zero length */ + // zero length if (txLen == 0) { WIFI_LOG(1, "TX slot %i trying to send a packet with length field set to zero. Attempt ignored.\n", slot); return; } - /* unsupported txRate */ + // unsupported txRate switch (wifiMac.circularBuffer[address+4] & 0xFF) { - case 10: /* 1 mbit */ - case 20: /* 2 mbit */ + case 10: // 1 mbit + case 20: // 2 mbit break; - default: /* other rates */ + default: // other rates WIFI_LOG(1, "TX slot %i trying to send a packet with transfer rate field set to an invalid value of %i. Attempt ignored.\n", slot, wifiMac.circularBuffer[address+4] & 0xFF); return; } - /* FIXME: calculate FCS */ + // FIXME: calculate FCS WIFI_triggerIRQ(WIFI_IRQ_SENDSTART) ; @@ -763,7 +766,48 @@ static void WIFI_TXStart(u8 slot) wifiMac.circularBuffer[address+4] &= 0x00FF; #endif } -} +} + +static void WIFI_BeaconTXStart() +{ + if (wifiMac.BeaconEnable) + { + u16 txLen; + u16 address = wifiMac.BeaconAddr; + // is there even enough space for the header (6 hwords) in the tx buffer? + if (address > 0x1000-6) + { + return; + } + + // 12 byte header TX Header: http://www.akkit.org/info/dswifi.htm#FmtTx + txLen = wifiMac.circularBuffer[address+5]; + // zero length + if (txLen == 0) + { + return; + } + + // unsupported txRate + switch (wifiMac.circularBuffer[address+4] & 0xFF) + { + case 10: // 1 mbit + case 20: // 2 mbit + break; + default: // other rates + return; + } + + // FIXME: calculate FCS + + WIFI_triggerIRQ(WIFI_IRQ_SENDSTART); + wifiCom->SendPacket((u8*)&wifiMac.circularBuffer[address+6], txLen); + WIFI_triggerIRQ(WIFI_IRQ_SENDCOMPLETE); + + wifiMac.circularBuffer[address] = 0x0001; + wifiMac.circularBuffer[address+4] &= 0x00FF; + } +} void WIFI_write16(u32 address, u16 val) { @@ -933,9 +977,6 @@ void WIFI_write16(u32 address, u16 val) WIFI_LOG(3, "Beacon transmission enabled to send the packet at %08X every %i milliseconds.\n", 0x04804000 + (wifiMac.BeaconAddr << 1), wifiMac.BeaconInterval); break ; - case REG_WIFI_BEACONPERIOD: - wifiMac.BeaconInterval = val & 0x03FF; - break; case REG_WIFI_TXLOC1: case REG_WIFI_TXLOC2: case REG_WIFI_TXLOC3: @@ -989,6 +1030,15 @@ void WIFI_write16(u32 address, u16 val) case REG_WIFI_USCOMPARECNT: wifiMac.ucmpEnable = (val & 1)==1 ; break ; + case REG_WIFI_BEACONPERIOD: + wifiMac.BeaconInterval = val & 0x03FF; + break; + case REG_WIFI_BEACONCOUNT1: + wifiMac.BeaconCount1 = val; + break; + case REG_WIFI_BEACONCOUNT2: + wifiMac.BeaconCount2 = val; + break; case REG_WIFI_BBSIOCNT: WIFI_setBB_CNT(val) ; break ; @@ -1206,6 +1256,10 @@ u16 WIFI_read16(u32 address) return (u16)(wifiMac.usec >> 32); case REG_WIFI_USCOMPARE3: return (u16)(wifiMac.usec >> 48); + case REG_WIFI_BEACONCOUNT1: + return wifiMac.BeaconCount1; + case REG_WIFI_BEACONCOUNT2: + return wifiMac.BeaconCount2; case REG_WIFI_POWER_US: return wifiMac.crystalEnabled?0:1 ; case REG_WIFI_CIRCBUFRD_END: @@ -1236,7 +1290,7 @@ void WIFI_usTrigger() { if (wifiMac.crystalEnabled) { - /* a usec (=3F03 cycles) has passed */ + /* a usec has passed */ if (wifiMac.usecEnable) wifiMac.usec++ ; if (wifiMac.eCountEnable) @@ -1246,6 +1300,31 @@ void WIFI_usTrigger() wifiMac.eCount-- ; } } + + // The beacon counters are in milliseconds + // GBATek says they're decremented every 1024 usecs + if (!(wifiMac.usec & 1023)) + { + wifiMac.BeaconCount1--; + if (wifiMac.BeaconCount1 == 0) + { + // FIXME: handle pre-beacon interval for IRQ 15 + WIFI_triggerIRQ(WIFI_IRQ_TIMEPREBEACON); + WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); + + WIFI_BeaconTXStart(); + + wifiMac.BeaconCount1 = wifiMac.BeaconInterval; + } + + if (wifiMac.BeaconCount2 > 0) + { + if (wifiMac.BeaconCount2 == 1) + WIFI_triggerIRQ(WIFI_IRQ_TIMEPOSTBEACON); + + wifiMac.BeaconCount2--; + } + } } if ((wifiMac.ucmpEnable) && (wifiMac.ucmp == wifiMac.usec)) { diff --git a/desmume/src/wifi.h b/desmume/src/wifi.h index de1115455..d4c29fcfc 100644 --- a/desmume/src/wifi.h +++ b/desmume/src/wifi.h @@ -91,6 +91,8 @@ #define REG_WIFI_USCOUNTER2 0x0FC #define REG_WIFI_USCOUNTER3 0x0FE #define REG_WIFI_EXTRACOUNT 0x118 +#define REG_WIFI_BEACONCOUNT1 0x11C +#define REG_WIFI_BEACONCOUNT2 0x134 #define REG_WIFI_BBSIOCNT 0x158 #define REG_WIFI_BBSIOWRITE 0x15A #define REG_WIFI_BBSIOREAD 0x15C @@ -335,6 +337,7 @@ typedef union #define WIFI_IRQ_RECVSTART 6 #define WIFI_IRQ_SENDSTART 7 #define WIFI_IRQ_RFWAKEUP 11 +#define WIFI_IRQ_TIMEPOSTBEACON 13 #define WIFI_IRQ_TIMEBEACON 14 #define WIFI_IRQ_TIMEPREBEACON 15 @@ -389,7 +392,6 @@ typedef struct u16 TXStat; u16 BeaconAddr; BOOL BeaconEnable; - u16 BeaconInterval; u16 TXSeqNo; u8 txCurSlot; u8 txSlotBusy[3]; @@ -425,6 +427,9 @@ typedef struct BOOL ucmpEnable ; u16 eCount ; BOOL eCountEnable ; + u16 BeaconInterval; + u16 BeaconCount1; + u16 BeaconCount2; /* subchips */ rffilter_t RF ;