version 0.03 Originally documented by Stephen Stair (sgstair AT akkit.org) Additional information and corrections provided by Martin Korth and anonymous contributors Please contact me if you find errors or omissions, thanks :) |
Non-Wifi HardwareGeneral InformationRelated Registers - System control |
Wifi HardwareGeneral InformationWifi Hardware Overview/Capability Wifi I/O Map Hardware Init Sequence BaseBand chip registers RF chip data formats Register Documentation Wifi Rx Registers Wifi Tx Registers Wifi RF/BB Chip Control Registers Wifi Other Registers Wifi Unknown Registers Additional Information Wifi Transmit Procedure Wifi Receive Procedure Wifi Change Channels Procedure About the "undefined" data in this document |
Formats/etcGeneral Formats802.11 Wifi Formats Hardware TX header Hardware RX header |
Bit Description 15 Enable (1=enabled, 0=not) When the SPI is enabled, any writes to the data register initiate a serial transfer. 7 Busy - This bit is 1 when a transfer is currently in progressThe SPI_CR register lets you configure how SPI transfers will take place.
Bit Description 0 ? 1 ? 2 ?Set a bit to '1' to enable power to that system, '0' to disable.
Bit Description 0 V-Blank 1 H-Blank 2 V-Match 3 Timer0 4 Timer1 5 Timer2 6 Timer3 7 ? 8 Dma0 9 Dma1 10 Dma2 11 Dma3 12 Keypad 13 GBA Cart 14-18 ? 19 DS Card control 20 DS Card IRQ signal 21-23 ? 24 Wifi 25-31 ?All the bits are '1' to enable and '0' to disable the interrupt.
Bit Description 0 Sound Power 1 Wifi Power 2-15 UnusedSet a bit to '1' to enable power to that system, '0' to disable.
Bit Description 0 V-Blank 1 H-Blank 2 V-Match 3 Timer0 4 Timer1 5 Timer2 6 Timer3 7 Unused/Reserved 8 Dma0 9 Dma1 10 Dma2 11 Dma3 12 Keypad 13 GBA Cart 14 Unused/Reserved 15 Unused/Reserved 16-18 ? 19 DS Card control 20 DS Card IRQ signal 21 ? 22-31 ?All the bits are '1' to enable and '0' to disable the interrupt.
Bit Description 0 Screen Power 1 2D Core A Power 2 Rasterizer Engine Power 3 Geometry Engine Power 4-8 ? 9 2D Core B Power 10-14 ? 15 LCD Swap (1=Core A on top, 0=Core B on top)Set a bit to '1' to enable power to that system, '0' to disable.
Address | Section ---------|-------------------- 04800000 | Main wifi register section to | read/write normal 04800FFF |____________________ 04801000 | Wifi Register section mirror to | read to "action" registers does not produce action (like read fifo 0x04800060) 04801FFF |____________________ 04802000 | Wifi Register section mirror to | read to "action" registers does not produce action (like read fifo 0x04800060) 04802FFF |____________________ 04803000 | Wifi Register section mirror to | read to "action" registers does not produce action (like read fifo 0x04800060) 04803FFF |____________________ 04804000 | MAC Memory section to | tx data, rx data, wep keys kept here | general sram, read/write 16bit | | 04805FFF |____________________ 04806000 | Wifi Register section mirror to | read to "action" registers does not produce action (like read fifo 0x04800060) 04806FFF |____________________ 04807000 | Wifi Register section mirror to | read to "action" registers does not produce action (like read fifo 0x04800060) 04807FFF |____________________This memory map then repeats/wraps around in the 0x04800000-0x04ffffff memory space.
Offset R/W Name [Init Value] Description 0x0000 R ? [1440] ? 0x0004 R/W W_MODE_RST [0000] Mode/Reset 0x0006 R/W W_MODE_WEP [0000] Mode / Wep modes. masks: 0x0040, 0x0018 (wep mode), 0x0003 (wifi mode) 0x0008 ?/W ? [0000] always set to 0? 0x000A ?/W Name [0000] [bit7 - ingore rx duplicates] 0x0010 R/W W_IF [0000] Wifi Interrupt Request Flags (works like IF) 0x0012 R/W W_IE [0000] Wifi Interrupt Enable 0x0018 R/W W_MACADDR [0000 0000 0000] Hardware MAC Address (6 bytes) 0x0020 R/W W_BSSID [0000 0000 0000] BSSID (6 bytes) 0x0028 ?/W W_AID [0000] the AID value assigned by a BSS. 0x002A ?/W ? [0000] set to the same thing as W_AID always 0x002C ?/W W_RETRLIMIT [0707] Retry Limit (set from 0x00-0xFF) 0x002E ?/? ? [0000] 0x0030 ?/W W_RXCNT [0000] Receive control, top bit = enable, bottom bit = latch rx range registers 0x0032 ?/W Name [0000] WEP engine enable: 0x8000 = enable, 0x0000 = disable [enables/disables WEP processing of sent/received packets] 0x0034 ?/? ? [0000] 0x0036 ?/W Name [0001] 1==disable? 0x0038 ?/W Name [0003] transmit-related power save or something [ bit 0 is power save related ] 0x003C ?/W W_POWERSTATE [0200] Power save - [=1: queue disable power state] [=2: queue enable power state] [bit9 = current power state, read only] - "enableing" causes rx wakeup interrupt 0x0040 ?/W W_FORCEPS [0000] Force Power State - [bit 15: allow forcing of power state, 1=force] [bit0: power state to force 0=disable, 1=enable] 0x0044 R W_RANDOM [????] random value. value constantly changes to random values between 1 and 0x07ff (more info further down) 0x0048 ?/W Name [0000] =0, =3 [=3 is power-save related.] 0x0050 R/W W_RXRANGEBEGIN [4000] The first location in mac memory used for the RX circular buffer (latched when bottom bit of W_RXCNT is set) 0x0052 R/W W_RXRANGEEND [4800] The address immediately after the last location in MAC memory used for the RX circular buffer (latched when bottom bit of W_RXCNT is set) 0x0054 R W_RXHWWRITECSR [0000] The hardware Write cursor, address=value*2+0x4000 - This points to the first "free" halfword in the buffer. 0x0056 R/W W_WRITECSRLATCH [0000] When bottom bit of W_RXCNT is set, this value is loaded into W_RXHWWRWITECSR 0x0058 R/W W_CIRCBUFRDADR [0000] A read cursor in the circular buffer; not used for anything but manual reading of W_CIRCBUFREAD 0x005A R/W W_RXREADCSR [0000] The "Begin" location of the circular buffer; the hardware write cursor will not go past this value when writing data. Must be moved by software after reading a packet 0x005C R/W Name [0000] (mask 0x0fff) Counts down; triggers wifi interrupt 9 when it reaches 0 0x0060 R W_CIRCBUFREAD [xxxx] every time you read this address it returns the data in the mac buffer at the address in W_CIRCBUFRDADR and increments W_CIRCBUFRDADR by 2 0x0062 R/W Name [0000] mask 0x1ffe 0x0064 R/W Name [0000] mask 0x0fff 0x0068 R/W W_CIRCBUFWRADR [0000] A write cursor in the circular buffer; not used for anything but manual writing to W_CIRCBUFWRITE (haven't checked to see if this actually is a circular buffer thing, the read one is though) 0x006C R/W Name [0000] mask 0x0fff 0x0070 R/W W_CIRCBUFWRITE [xxxx] When you read, this register mirrors W_CIRCBUFREAD without modifying W_CIRCBUFRDADR.. when you write, it writes the value to the address in MAC mem specified by W_CIRCBUFWRADR, and increments it by 2. 0x0074 R/W W_CIRCBUFWR_END [0000] Same as W_RXRANGEEND for the W_RXREADCSR, this is for W_RXWRITEADR; but there's no begin register, see the next register for more info 0x0076 ?/W W_CIRCBUFWR_SKIP[0000] When W_RXWRITECURSOR = W_CIRCBUFWR_END, this value * 2 is added to it. So when [WRITEADR]==[END], [WRITEADR]+=[SKIP]*2; 0x0078 ?/W Name [0000] Appears to mirror W_CIRCBUFWRADR 0x0080 R/W W_BEACONTRANS [0000] Enables automatic transmission of frames at regular intervals. top bit=enable, bottom 12 bits = MAC mem address/2 of frame header 0x0084 ?/W Name [0000] Description 0x0088 R/W W_LISTENCOUNT [0000] Decrements; when it reaches zero, it's reloaded with W_LISTENINT 0x008C R/W W_BEACONPERIOD [0064] Frequency in milliseconds of beacon transmission 0x008E R/W W_LISTENINT [0000] Listen interval; related to W_LISTENCOUNT 0x0090 ?/W Name [0000] Description 0x0094 ?/W Name [0000] ? 0x0098 ?/W Name [0000] Description 0x00A0 R/W Name [0050] ? 0x00A0 R/W W_TXLOC1 [0000] Transmit slot #1 (bit 0) 0x00A4 R/W W_TXLOC2 [0000] Transmit slot #2 (bit 2) 0x00A8 R/W W_TXLOC3 [0000] Transmit slot #3 (bit 3) 0x00AC W W_TXOPT [0050] Transmit options... Options that exist are unclear. 0x00AE W W_TXCNT [0050] Write here to enable the transmission of one or more of the 3 transmit slots 0x00B0 R/? W_TXINFO [0010] Info about transmit state 0x00B4 ?/W Name [0000] Description 0x00B6 R/? Name [0000] Description 0x00B8 R/? W_TXSTAT [0000] Status of recently transmitted frame 0x00BA R/? Name [0000] Description 0x00BC ?/W Name [0001] [ |=6: short preamble, &=~6: long preamble ] 0x00C0 R/? Name [0000] Description 0x00C4 R/? Name [0000] Description 0x00C8 R/? Name [0000] Description 0x00D0 R/W W_RXFILTER [0401] Specifies what packets to allow, combinations are unknown. 0x00D4 ?/W Name [0001] Description 0x00D8 ?/W Name [0004] Description 0x00DA ?/W Name [0602] Description 0x00E0 ?/W Name [0008] Description 0x00E8 R/W W_USCOUNTERCNT [0000] Microsecond counter control, 0x0001 = enabled 0x00EA ?/W W_USCOMPARECNT [0000] Microsecond compare control, 0x0001 = enabled (to enable interrupt 14) 0x00EC ?/W Name [3F03] Description 0x00EE ?/W Name [0001] Description 0x00F0 ?/W W_USCOMPARE0 [FC00] F0-F7 are compared with F8 through FF - note lower 10 bits are always 0, so compare has 1/1024 microsecond resolution. 0x00F2 ?/W W_USCOMPARE1 [FFFF] When they match, 11C is reloaded with W_BEACONPERIOD, 134 is set to FFFF, and interrupt 14 triggers (may not be related) 0x00F4 ?/W W_USCOMPARE2 [FFFF] 0x00F6 ?/W W_USCOMPARE3 [FFFF] 0x00F8 R/W W_USCOUNTER0 [0000] Microsecond counter, bottom 16 bits 0x00FA R/W W_USCOUNTER1 [0000] Microsecond counter, bits 16-31 0x00FC R/W W_USCOUNTER2 [0000] Microsecond counter, bits 32-47 0x00FE R/W W_USCOUNTER3 [0000] Microsecond counter, bits 48-63 0x0100 ?/W Name [0000] Description 0x0102 ?/W Name [0000] Description 0x0104 ?/W Name [0000] Description 0x0106 ?/W Name [0000] Description 0x010C ?/W Name [0000] [Set to the remaining duration of contention-free period when receiving beacons - only *really* necessary for the wimpy powersaving mode] 0x0110 ?/W Name [0000] Description 0x0118 ?/W Name [0000] Description 0x011C ?/W Name [0000] (Decreases, when reaches 0 is reloaded with W_BEACONPERIOD) 0x0120 R/W ? [0048] 0x0122 R/W ? [4840] mask 0xffff 0x0124 R/W ? [0000] mask 0xffff 0x0126 R/W ? [0080] 0x0128 R/W ? [0000] mask 0xffff 0x012A R/W ? [1000] 0x0130 R/W ? [0142] mask 0x0fff 0x0132 R/W ? [8064] mask 0x8fff 0x0134 R/W W_BEACONCOUNT [FFFF] (I think) This is the millisecond counter that tracks when beacons are expected to be transmitted. ["Active zone time" - it tracks some aspect of the Contention-free period] 0x0140 R/W ? [0000] mask 0xffff 0x0142 R/W ? [2443] mask 0xffff 0x0144 R/W ? [0042] 0x0146 R/W ? [0016] 0x0148 R/W ? [0016] 0x014A R/W ? [0016] 0x014C R/W ? [162C] 0x0150 ?/W Name [0204] Description 0x0154 ?/W Name [0058] Description 0x0158 ?/W W_BBSIOCNT [00B5] 0x6xxx - read from address xxx, 0x5xxx - write to address xxx 0x015A ?/W W_BBSIOWRITE [0000] byte data to write 0x015C ?/W W_BBSIOREAD [00B5] byte data read 0x015E ?/W W_BBSIOBUSY [0000] Bit 0 = set when busy 0x0160 ?/W Name [0100] Description 0x0168 ?/W Name [800D] Description 0x016A ?/W Name [0001] Description 0x0170 ?/W Name [0000] Description 0x0172 ?/W Name [0000] Description 0x0174 ?/W Name [0000] Description 0x0176 ?/W Name [0000] Description 0x0178 ?/W Name [0800] Description 0x017C ?/W W_RFSIODATA2 [0800] Description 0x017E ?/W W_RFSIODATA1 [C008] Description 0x0180 ?/W W_RFSIOBUSY [0000] Description 0x0184 ?/W W_RFSIOCNT [0018] Description 0x0190 ?/W Name [0000] Description 0x0194 ?/W Name [0000] Description 0x0198 ?/W Name [0000] Description 0x019C ?/W Name [0004] Bit 0 = carrier sense? 0x01A0 ?/W Name [0000] Description 0x01A2 ?/W Name [0001] Description 0x01A4 ?/W Name [0000] Rate used when signal test is enabled (0x0A or 0x14 for 1 or 2 mbit) 0x01A8 R Name [0000] REG_WL_STATSINC: Bitmask for which statistics have been increased atleast once. 0x01AA R/W Name [0000] REG_WL_STATSIECNTUP: Statistic Interrupt Enable Control register for Count Up. bitmasks: 0x20 = FCS_ERROR, 0x40 = FCS_OK, 0x800 = DUPE, ? 0x01AC R Name [0000] REG_WL_STATSOVF. Bitmask that tells which statistics have overflowed. 0x01AE R/W Name [0000] REG_WL_STATSIEOVF. Statistic Interrupt Enable Control register for Overflow. bitmasks same as STATSIECNTUP. 0x01B0 R W_STAT [0000] W_STAT is a collection of byte-granular statistics entries. These entries reset to 0 when read. 0x01B2 R W_STAT [0000] [RX_LengthErrorCount | RX_RateErrorCount] 0x01B4 R W_STAT [0000] 0x01B6 R W_STAT [0000] 0x01B8 R W_STAT [0000] 0x01BA R W_STAT [0000] 0x01BC R W_STAT [0000] 0x01BE R W_STAT [0000] 0x01C0 R W_STAT [0000] 0x01C4 R W_STAT [0000] 0x01D0 R W_STAT [0000] [1D0 - 1DE are 15 entries related to multiplayer response errors] 0x01D2 R W_STAT [0000] 0x01D4 R W_STAT [0000] 0x01D6 R W_STAT [0000] 0x01D8 R W_STAT [0000] 0x01DA R W_STAT [0000] 0x01DC R W_STAT [0000] 0x01DE R W_STAT [0000] 0x01F0 ?/W Name [0000] Description 0x0204 ?/W Name [0000] Description 0x0208 ?/W Name [0000] Description 0x020C ?/W Name [0050] Description 0x0210 ?/W Name [0000] Description 0x0214 ?/W Name [0009] Description 0x021C ?/W Name [0000] "Force Interrupt" - writing a value here will enable the flags in W_IF 0x0220 ?/W Name [0000] has something to do with whether the packet is ignored or allowed by the packet filtering system 0x0224 ?/W Name [0003] Description 0x0228 ?/W Name [0000] Description 0x0230 ?/W Name [0047] Description 0x0234 ?/W Name [0EFF] Description 0x0238 ?/W Name [0000] Description 0x023C ?/W Name [0000] Description 0x0244 ?/W Name [0000] Description 0x0248 ?/W Name [0000] Description 0x024C ?/W Name [0000] Description 0x024E ?/W Name [0000] Description 0x0250 ?/W Name [0000] Description 0x0258 ?/W Name [0000] Description 0x025C ?/W Name [0000] Description 0x0260 ?/W Name [0FEF] Description 0x0264 ?/W Name [0000] Description 0x0268 R/W W_RXUNITS [0005] Contains the number of HWORDs written to MAC mem since the start of the packet (this + W_RXHWWRITECSR = next empty word in MAC mem) 0x0270 ?/W Name [0000] Description 0x0274 ?/W Name [0000] Description 0x0278 ?/W Name [000F] Description 0x027C ?/W Name [0000] Description 0x0290 ?/W Name [FFFF] bit 0 = ? 0x0298 ?/W Name [0000] Description 0x02A0 ?/W Name [0000] Description 0x02A2 ?/W Name [7FFF] Description 0x02A4 ?/W Name [0000] Description 0x02A8 ?/W Name [0000] Description 0x02AC ?/W Name [0038] Description 0x02B0 ?/W Name [0000] Description 0x02B4 ?/W Name [0000] Description 0x02B8 ?/W Name [0000] Description 0x02C0 ?/W Name [0000] Description 0x02C4 ?/W Name [000A] Description 0x02C8 ?/W Name [0000] Description 0x02CC ?/W Name [0000] Description 0x02F0 ?/W Name [0000] Description 0x02F2 ?/W Name [0000] Description 0x02F4 ?/W Name [0000] Description 0x02F6 ?/W Name [0000] Description 0x4000 R/W W_MACMEM [random] MAC memory (0x2000 bytes) 0x5F60 ? Used for something, not included in the rx circular buffer. (ssid maybe?) 0x5F80 W_WEPKEY1 (32 bytes) 0x5FA0 W_WEPKEY2 (32 bytes) 0x5FC0 W_WEPKEY3 (32 bytes) 0x5FE0 W_WEPKEY4 (32 bytes)
[Init Sequence:] POWERCNT |= 2; -- Enable power to the wifi system *((volatile u16 *)0x04000206) = 0x30; -- unclear if this is necessary, or exactly what it does. Set Mac address - copy 6 bytes from flash[0x36] to mac address at 0x04800018 W_IE = 0; -- Disable interrupts Wake Up the wireless system: [u16 0x04800036] = 0 -- (still not sure what this does) delay 8 ms [u16 0x04800168] = 0 -- (still not sure what this does) temp = BB_Read(1); -- read baseband address 1 BB_Write(1,temp&0x7F); -- clear bit 8 & write back BB_Write(1,temp); -- restore bit 8 & write back (probably an init) delay 30 ms RF_Init -- same as "Init the RF system", below. this or the other one is probably not necessary. Init the Mac system: Set the following registers (offset from 0x04800000) to the specified values: reg[0x04] = 0 -- set hardware mode reg[0x08] = 0 -- ? reg[0x0A] = 0 -- ? (related to rx filter) reg[0x12] = 0 -- Wifi IE = 0 reg[0x10] = 0xffff -- reset Wifi IF reg[0x254]= 0 -- ? reg[0xB4] = 0xffff -- ? reg[0x80] = 0 -- Disable automatic beacon transmission reg[0x2A] = 0 -- ? reg[0x28] = 0 -- set AID to 0 reg[0xE8] = 0 -- Disable microsecond counter reg[0xEA] = 0 -- ? reg[0xEE] = 1 -- ? reg[0xEC] = 0x3F03 -- ? reg[0x1A2]= 1 -- ? reg[0x1A0]= 0 -- ? reg[0x110]= 0x0800 -- ? reg[0xBC] = 1 -- ? and disable short preamble reg[0xD4] = 3 -- ? reg[0xD8] = 4 -- ? reg[0xDA] = 0x0602 -- ? reg[0x76] = 0 -- set W_CIRCBUFWR_SKIP to 0 (skip nothing when using write circular buffer) Init the RF system: write 16bit values from flash (starting at offset 0x44) to the following list of registers (offset from 0x04800000) - the actual assignments are also listed here for reference. list: 0x146, 0x148, 0x14A, 0x14C, 0x120, 0x122, 0x154, 0x144, 0x130, 0x132, 0x140, 0x142, 0x38, 0x124, 0x128, 0x150 Actual assignments (based on present firmware dumps): reg[0x146] = 0x0002 -- ? (I'm speculating wildly here, but I'd bet most of these are timing values.) reg[0x148] = 0x0017 -- ? reg[0x14A] = 0x0026 -- ? reg[0x14C] = 0x1818 -- ? reg[0x120] = 0x0048 -- ? reg[0x122] = 0x4840 -- ? reg[0x154] = 0x0058 -- ? reg[0x144] = 0x0042 -- ? reg[0x130] = 0x0140 -- ? reg[0x132] = 0x8064 -- ? reg[0x140] = 0xE0E0 -- ? reg[0x142] = 0x2443 -- ? reg[0x038] = 0x000E -- ? [unclear, but related to power saving] reg[0x124] = 0x0032 -- ? reg[0x128] = 0x01F4 -- ? reg[0x150] = 0x0101 -- ? numentries = flash byte at 0x42 (=0x0C == 12) numbits = flash byte at 0x41 numbytes = (numbits+7)/8; reg[0x184] = ((numbits<<1) & 0x0100) | (numbits&0x7F) -- W_RFSIOCNT, specifies number of bits per transfer if flash byte 0x40 == 3 { -- doesn't in current firmware... for(i=0;i<numentries;i++) RF_Write(0x50000 | (i<<8) | flash byte at 0xCE+i); -- not going to go over this one, as it's not the case in present firmware. } else { for(i=0;i<numentries;i++) RF_Write(numbytes flash bytes, starting at 0xCE + i*numbytes); } For the second case, which is the currently used one, the following values are written to RF_Write: (see section on RF chip for more speculation) RF_Write 0x00C007 RF_Write 0x129C03 RF_Write 0x141728 RF_Write 0x1AE8BA RF_Write 0x1D456F RF_Write 0x23FFFA RF_Write 0x241D30 RF_Write 0x280001 RF_Write 0x2C0000 RF_Write 0x069C03 RF_Write 0x080022 RF_Write 0x0DFF6F -- really odd values, unclear exactly what they mean but it's likely they're initializing a PLL or something with various frequencies or options. Init the BaseBand System: -- and you thought the RF init was bad? The baseband init is rather simple, just read in 105 values and write them to the baseband. simple, eh? :) routine goes like this: reg(0x160) = 0x0100 for(i=0;i<0x69;i++) BB_Write( i, flash byte 0x64+i ); For your convenience (or torture), all 105 values are listed here: BB_Write 0, 0x6D BB_Write 1, 0x9E BB_Write 2, 0x40 BB_Write 3, 0x05 BB_Write 4, 0x1B BB_Write 5, 0x6C BB_Write 6, 0x48 BB_Write 7, 0x80 BB_Write 8, 0x38 BB_Write 9, 0x00 BB_Write 10, 0x35 BB_Write 11, 0x07 BB_Write 12, 0x00 BB_Write 13, 0x00 BB_Write 14, 0x00 BB_Write 15, 0x00 BB_Write 16, 0x00 BB_Write 17, 0x00 BB_Write 18, 0x00 BB_Write 19, 0x00 BB_Write 20, 0xB0 BB_Write 21, 0x00 BB_Write 22, 0x04 BB_Write 23, 0x01 BB_Write 24, 0xD8 BB_Write 25, 0xFF BB_Write 26, 0xFF BB_Write 27, 0xC7 BB_Write 28, 0xBB BB_Write 29, 0x01 BB_Write 30, 0xB6 BB_Write 31, 0x7F BB_Write 32, 0x5A BB_Write 33, 0x01 BB_Write 34, 0x3F BB_Write 35, 0x01 BB_Write 36, 0x3F BB_Write 37, 0x36 BB_Write 38, 0x36 BB_Write 39, 0x00 BB_Write 40, 0x78 BB_Write 41, 0x28 BB_Write 42, 0x55 BB_Write 43, 0x08 BB_Write 44, 0x28 BB_Write 45, 0x16 BB_Write 46, 0x00 BB_Write 47, 0x01 BB_Write 48, 0x0E BB_Write 49, 0x20 BB_Write 50, 0x02 BB_Write 51, 0x98 BB_Write 52, 0x98 BB_Write 53, 0x1F BB_Write 54, 0x0A BB_Write 55, 0x08 BB_Write 56, 0x04 BB_Write 57, 0x01 BB_Write 58, 0x00 BB_Write 59, 0x00 BB_Write 60, 0x00 BB_Write 61, 0xFF BB_Write 62, 0xFF BB_Write 63, 0xFE BB_Write 64, 0xFE BB_Write 65, 0xFE BB_Write 66, 0xFE BB_Write 67, 0xFC BB_Write 68, 0xFC BB_Write 69, 0xFA BB_Write 70, 0xFA BB_Write 71, 0xFA BB_Write 72, 0xFA BB_Write 73, 0xFA BB_Write 74, 0xF8 BB_Write 75, 0xF8 BB_Write 76, 0xF6 BB_Write 77, 0xA5 BB_Write 78, 0x12 BB_Write 79, 0x14 BB_Write 80, 0x12 BB_Write 81, 0x41 BB_Write 82, 0x23 BB_Write 83, 0x03 BB_Write 84, 0x04 BB_Write 85, 0x70 BB_Write 86, 0x35 BB_Write 87, 0x0E BB_Write 86, 0x16 BB_Write 89, 0x16 BB_Write 90, 0x00 BB_Write 91, 0x00 BB_Write 92, 0x06 BB_Write 93, 0x01 BB_Write 94, 0xFF BB_Write 95, 0xFE BB_Write 98, 0xFF BB_Write 97, 0xFF BB_Write 98, 0x00 BB_Write 99, 0x0E BB_Write 100, 0x13 BB_Write 101, 0x00 BB_Write 102, 0x00 BB_Write 103, 0x28 BB_Write 104, 0x1C (--phew--) Set Mac address - copy 6 bytes from flash[0x36] to mac address at 0x04800018 -- now just set some default varibles W_RETRLIMIT=7 -- actually, we now know this needs to be set for every transmit Set channel (see section on changing channels) Set Mode 2 -- sets bottom 3 bits of W_MODE_WEP to 2 Set Wep Mode / key -- Wep mode is bits 3..5 of W_MODE_WEP BB_Write 0x13, 0x00 -- BB register 0x13 is CCA operation (0=carrier sense only, 1=only valid with ED value, 2=CS or ED, 3=CS and ED) BB_Write 0x35, 0x1F -- BB register 0x35 is ED (Energy Detection Threshold values 0..61, representing -60dBm to -80dBm - I think in that order) -- To further init wifi to the point that you can properly send and receive data, there are some more variables that need to be set. reg[0x032] = 0x8000 -- Enable wep processing on packets which bear the WEP flag in the 802.11 header reg[0x134] = 0xFFFF -- resets a millisecond counter related to beacons reg[0x028] = 0 -- clear W_AID value reg[0x02A] = 0 -- ? (they just like setting it when they set W_AID) reg[0x0E8] = 1 -- enable microsecond counter reg[0x038] = 0 -- disable transmit power save reg[0x020] = 0 -- clear BSSID (this and the next 2 writes) reg[0x022] = 0 reg[0x024] = 0 -- TX prepare reg[0x0AE] = 0x000D -- flush all pending transmits -- RX prepare reg[0x030] = 0x8000 -- enable RX system reg[0x050] = 0x4C00 -- RX Fifo begin (these are just my default values, you can set basicly whatever you want. reg[0x052] = 0x5F60 -- RX Fifo end (length = 4960 bytes) reg[0x056] = 0x0600 -- fifo begin latch address, 0xC00/2 = 0x600 reg[0x05A] = 0x0600 -- fifo end, same as begin at start. reg[0x062] = 0x5F5E -- last element of fifo (unclear if this is necessary) reg[0x030] = 0x8001 -- enable, and latch new fifo values for hardware use reg[0x030] = 0x8000 -- enable receive (this is duplicated) W_IF=0xFFFF -- clear interrupt flags W_IE=(whatever) -- set enabled interrupts reg[0x1AE] = 0x1FFF -- set what STAT *overflows* you would like to cause an interrupt reg[0x1AA] = 0 -- set what STAT *increases* you would like to cause an interrupt reg[0x0D0] = 0x181 -- set this to 0x581 when you successfully connect to an access point and fill W_BSSID with a mac address for it. (W_RXFILTER) [not sure on the values for this yet] reg[0x0E0] = 0x000B -- ? reg[0x008] = 0 -- ? reg[0x00A] = 0 -- ? [related to filtering] reg[0x004] = 1 -- hardware mode reg[0x0E8] = 1 -- enable microsecond counter (this is duplicated too) reg[0x0EA] = 1 -- ? [possibly related to microsecond counter compare register] reg[0x048] = 0 -- ? [disabling a power saving technique, no doubt] reg[0x038] &= ~2 -- ? [this too] reg[0x048] = 0 -- ? [umm, it's done again. unclear if it's necessary] reg[0x0AE] = 2 -- setting a bit that doesn't appear to be used; purpose is unclear. reg[0x03C] |= 2 -- queue enable power! (RX power, we beleive) reg[0x0AC] = 0xFFFF -- reset something. And, that's it. after all that the DS should be happy to send and receive packets. It's very possible there are unnecessary register sets in here, but this pseudocode is based very closely on my current working codebase, and it should work. I just haven't had the time to weed out all of the unnecessary parts, and test to verify they were indeed unnecessary. Please keep in mind that this is very preliminary information, if you find bugs or can't make it work, please let me know (contact info on the top and bottom of this page)
while(W_RFSIOBUSY&1); W_RFSIODATA1=(data & 0xFFFF); W_RFSIODATA2=(data >> 16); while(W_RFSIOBUSY&1);
counter=10000; while((W_BBSIOBUSY&1) && (--counter)); if(!counter) return -1; W_BBSIOWRITE=data; W_BBSIOCNT=address | 0x5000; counter=10000; while((W_BBSIOBUSY&1) && (--counter)); return 0;
counter=10000; while((W_BBSIOBUSY&1) && (--counter)); if(!counter) return -1; W_BBSIOCNT=address | 0x6000; while(W_BBSIOBUSY&1); return W_BBSIOREAD;
void Read_Flash(int address, char * destination, int length) { int i; while(SPI_CR&0x80); SPI_CR=0x8900; SPI_DATA=3; while(SPI_CR&0x80); SPI_DATA=(address>>16)&255; while(SPI_CR&0x80); SPI_DATA=(address>>8)&255; while(SPI_CR&0x80); SPI_DATA=(address)&255; while(SPI_CR&0x80); for(i=0;i<length;i++) { SPI_DATA=0; while(SPI_CR&0x80); destination[i]=SPI_DATA; } SPI_CR=0; }
Address | Initial Value | Meaning 0 0x6D ? 1 0x9E [unsetting/resetting bit 7 initializes/resets the system] 2 0x40 ? 3 0x05 ? 4 0x1B ? 5 0x6C ? 6 0x48 ? 7 0x80 ? 8 0x38 ? 9 0x00 ? 10 0x35 ? 11 0x07 ? 12 0x00 ? 13 0x00 ? 14 0x00 ? 15 0x00 ? 16 0x00 ? 17 0x00 ? 18 0x00 ? 19 0x00 CCA operation - criteria for receiving (0=only use Carrier Sense (CS), 1=only use Energy Detection (ED), 2=receive if CS OR ED, 3= receive only if CS AND ED) 20 0xB0 ? 21 0x00 ? 22 0x04 ? 23 0x01 ? 24 0xD8 ? 25 0xFF ? 26 0xFF ? 27 0xC7 ? 28 0xBB ? 29 0x01 ? 30 0xB6 ? 31 0x7F ? 32 0x5A ? 33 0x01 ? 34 0x3F ? 35 0x01 ? 36 0x3F ? 37 0x36 ? 38 0x36 ? 39 0x00 ? 40 0x78 ? 41 0x28 ? 42 0x55 ? 43 0x08 ? 44 0x28 ? 45 0x16 ? 46 0x00 ? 47 0x01 ? 48 0x0E ? 49 0x20 ? 50 0x02 ? 51 0x98 ? 52 0x98 ? 53 0x1F Energy Detection (ED) criteria - value 0..61 (representing energy levels of -60dBm to -80dBm) 54 0x0A ? 55 0x08 ? 56 0x04 ? 57 0x01 ? 58 0x00 ? 59 0x00 ? 60 0x00 ? 61 0xFF ? 62 0xFF ? 63 0xFE ? 64 0xFE ? 65 0xFE ? 66 0xFE ? 67 0xFC ? 68 0xFC ? 69 0xFA ? 70 0xFA ? 71 0xFA ? 72 0xFA ? 73 0xFA ? 74 0xF8 ? 75 0xF8 ? 76 0xF6 ? 77 0xA5 ? 78 0x12 ? 79 0x14 ? 80 0x12 ? 81 0x41 ? 82 0x23 ? 83 0x03 ? 84 0x04 ? 85 0x70 ? 86 0x35 ? 87 0x0E ? 86 0x16 ? 89 0x16 ? 90 0x00 ? 91 0x00 ? 92 0x06 ? 93 0x01 ? 94 0xFF ? 95 0xFE ? 98 0xFF ? 97 0xFF ? 98 0x00 ? 99 0x0E ? 100 0x13 ? 101 0x00 ? 102 0x00 ? 103 0x28 ? 104 0x1C ?
[Used in RF init:] 0x00C007 0x129C03 0x141728 0x1AE8BA 0x1D456F 0x23FFFA 0x241D30 0x280001 0x2C0000 0x069C03 0x080022 0x0DFF6F [Written when changing channels:]
Bit Description 15 Enable Queuing received data to RX FIFO 0 Latch registers for RX FIFOLatched registers include: W_RXRANGEBEGIN, W_RXRANGEEND and also W_HWWRITECSR=W_WRITECSRLATCH
Bit Description 0 Receive Complete interrupt - raised immediately after a packet is received and stored in the RX fifo 1 Transmit Complete interrupt - raised immediately after a packet is done being transmitted 2 Receive Count Up interrupt - raised when a packet is received, regardless of whether it's stored in the RX fifo 3 Transmit Error interrupt - raised when transmit header is incorrect, or another error occured. 4 Statistics Count Overflow interrupt - raised when a stat is increased 5 Statistics Ack Count Overflow interrupt - raised when a certain kind of stat is increased 6 Start Receive interrupt - raised when a packet has just started to be received 7 Start Transmit interrupt - raised when a packet has just started to be transmitted 8 ? 9 ? 10 ? 11 RF Wakeup Interrupt - raised when the RF system wakes up 12 ? 13 ? 14 Beacon Timeslot interrupt - raised right after a beacon should have been sent, in a "safe zone" for sending data 15 Pre Beacon Timeslot interrupt - raised right before a beacon is predicted to be sent (if the timings are configured correctly)Write a '1' to a bit to clear it.
(1) Copy the TX Header followed by the 802.11 packet to send anywhere it will fit in MAC memory (halfword-aligned) (2) Take the offset from start of MAC memory that you put the packet, divide it by 2, and or with 0x8000 - store this in one of the W_TXLOC registers (3) Set W_RETRLIMIT, to allow your packet to be retried until an ack is received (set it to 7, or something similar) (4) Store the bit associated with the W_TXLOC register you used into W_TXCNT - this will send the packet. (5) You can then read the result data in W_TXSTAT when the TX is over (you can tell either by polling or interrupt) to find out how many retries were used, and if the packet was ACK'dOf course, this is just the simplest approach, you can be a lot more clever about it.
(1) Calculate the length of the new packet (read "received frame length" which is +8 bytes from the start of the packet) - total frame length is (12 + received frame length) padded to a multiple of 4 bytes. (2) Read the data out of the RX FIFO area (keep in mind it's a circular buffer and you may have to wrap around the end of the buffer) (3) Set the value of W_RXREADCSR to the location of the next packet (add the length of the packet, and wrap around if necessary)Keep in mind, W_RXREADCSR and W_RXHWWRITECSR must be multiplied by 2 to get a byte offset from the start of MAC memory.
read 3 bytes of flash starting at (0xF2+(channel-1)*6) to a temporary value call RF_Write with the 3 bytes you just read (as a 0-padded long value) read 3 bytes of flash starting at (0xF5+(channel-1)*6) to a temporary value again, call RF_Write with the 3 bytes you just read (as a 0-padded long value) delay a few milliseconds call BB_Write with parameters 0x1E, and the byte in flash at 0x146+(channel-1)Congrats, you are now ready to transmit/receive on whatever channel you picked.
Offset Description +0 Unknown (used by hardware) +2 Unknown (used by hardware) +4 Unknown (used by hardware) +6 Unknown (used by hardware) +8 Transmit rate (speed in megabits multiplied by 10 - 1.0Mbit is 0x0A, 2.0Mbit is 0x14) +10 Transmit length (bytes) transmits the data at +12 through +12+length-1 inclusive.Important note! TX length includes the length of a 4-byte "FCS" (checksum) for the packet. The hardware generates the FCS for you, but you still must include it in the packet length. Also note that if the 802.11 WEP enabled bit is set in the header, the packet will be automatically encrypted via the wep algorithm - however, the software is responsible for providing the 4-byte IV block with the WEP key ID and the 24bit IV value. - ALSO, you must include the length of the *encrypted* FCS used in packets that have wep enabled (increase the tx length by another 4 bytes) - this value is calculated automaticly for you, but you are responsible for including it in the length of your packet (if you have data there, it'll be replaced by the FCS.)
Offset Description +0 Unknown (used by hardware) +2 Unknown (used by hardware) +4 Unknown (used by hardware) +6 Unknown (used by hardware) +8 Received frame length (bytes) +10 RSSI Range (Bottom 8 bits are MAX RSSI, top 8 bits are MIN RSSI, during the receipt of the packet)Important Note: Received frame lengths are always multiples of 4 bytes. While the actual header length + received frame length may be less, when incrementing the read cursor you must pad the length to a multiple of 4 bytes