spi
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
spi [2024/09/29 11:44] – arisotura | spi [2025/04/17 15:44] (current) – arisotura | ||
---|---|---|---|
Line 7: | Line 7: | ||
The gamepad uses a pretty simple SPI controller with 16-byte FIFOs for reading and writing. Due to the way this is designed, one has to be mindful to avoid FIFO overflows/ | The gamepad uses a pretty simple SPI controller with 16-byte FIFOs for reading and writing. Due to the way this is designed, one has to be mindful to avoid FIFO overflows/ | ||
+ | |||
+ | The SPI controller doesn' | ||
The SPI controller has the following registers: | The SPI controller has the following registers: | ||
Line 15: | Line 17: | ||
| 0xF000440C | FIFO status | | | 0xF000440C | FIFO status | | ||
| 0xF0004410 | Data input/ | | 0xF0004410 | Data input/ | ||
- | | 0xF0004414 | ?? | | + | | 0xF0004414 | SPI low-level control |
| 0xF0004418 | IRQ enable | | | 0xF0004418 | IRQ enable | | ||
| 0xF0004420 | Number of bytes to read | | | 0xF0004420 | Number of bytes to read | | ||
Line 26: | Line 28: | ||
^ Bits ^ Desc. ^ | ^ Bits ^ Desc. ^ | ||
- | | 0-2 | Clock multiplier | + | | 0-2 | Clock source |
| 3-10 | Clock divider | | | 3-10 | Clock divider | | ||
+ | | 11-14 | ?? | | ||
| 15 | SPI enable (possibly just clock enable) | | | 15 | SPI enable (possibly just clock enable) | | ||
- | The clock multiplier | + | The clock source |
- | The following | + | The clock source |
- | ^ Multiplier ^ Clock ^ | + | |
- | | 0 | 32MHz | | + | |
- | | 1 | 12MHz | | + | |
- | | 2 | ??? | | + | |
- | | 3 | ??? | | + | |
- | | 4 | ~857MHz | | + | |
- | | 5 | 3.38MHz | | + | |
- | | 6 | 15.9MHz | | + | |
- | | 7 | 3.38MHz | | + | |
- | + | ||
- | Not sure how these values are generated internally. I couldn' | + | |
- | + | ||
- | The clock divider | + | |
Observed settings in the stock firmware are the following: | Observed settings in the stock firmware are the following: | ||
- | ^ Register value ^ Destination ^ Clock speed ^ | + | ^ Register value ^ Destination ^ Clock speed ^ |
- | | 0x808C | + | | 0x808C |
- | | 0x8018 | + | | 0x8018 |
- | | 0x835C | + | | 0x835C |
- | | 0x83F8 | + | | 0x83F8 |
- | | 0x8400 | + | | 0x8400 |
Line 79: | Line 69: | ||
SPI IRQ flags. Writing a 1 to a flag clears it. | SPI IRQ flags. Writing a 1 to a flag clears it. | ||
+ | |||
+ | The flags only get set when the corresponding IRQ is enabled in register 0xF0004418. | ||
^ Bits ^ Desc. ^ | ^ Bits ^ Desc. ^ | ||
Line 98: | Line 90: | ||
| 0-4 | Free space in write FIFO (16 when empty) | | | 0-4 | Free space in write FIFO (16 when empty) | | ||
| 8-12 | Occupied space in read FIFO (16 when full) | | | 8-12 | Occupied space in read FIFO (16 when full) | | ||
+ | |||
+ | When writing data, transfer completion should be checked for by waiting for a write IRQ rather than relying on the write FIFO level. Even when the write FIFO is empty, there may still be data being transferred. | ||
Line 110: | Line 104: | ||
WARNING: if the write FIFO is already full, writes to this register are discarded. There seems to be no error signal in this case, so you have to be mindful of this. | WARNING: if the write FIFO is already full, writes to this register are discarded. There seems to be no error signal in this case, so you have to be mindful of this. | ||
- | In a similar vein, a read transfer will halt if the read FIFO is full. | + | In a similar vein, a read transfer will halt if the read FIFO is full (and resume when it is no longer full). |
+ | |||
+ | Using [[DMA]] takes care of this automatically, | ||
It isn't known if there are IRQs for FIFO full/empty conditions, but there doesn' | It isn't known if there are IRQs for FIFO full/empty conditions, but there doesn' | ||
- | |||
- | Not yet known how SPI DMA works. | ||
**0xF0004414** | **0xF0004414** | ||
- | Unknown. Bits 0-1, 4, 15 set by firmware code. | + | Controls low-level aspects of the SPI protocol. |
+ | |||
+ | ^ Bits ^ Desc. ^ | ||
+ | | 0 | CPHA - Clock phase | | ||
+ | | 1 | CPOL - Clock polarity; 0=invert source clock, 1=use source clock as-is | | ||
+ | | 4 | ?? | | ||
+ | | 15 | ?? | | ||
+ | |||
+ | Clearing bit 15 has weird effects: seems to force CPOL to 1? This causes the transmitted data to be offset | ||
Line 157: | Line 159: | ||
Setting both bits will result in both devices being selected at the same time. | Setting both bits will result in both devices being selected at the same time. | ||
+ | |||
+ | Unknown if there are more devices? The diagnostics firmware accesses a third device named ' | ||
+ | |||
+ | On a retail gamepad, register 0xF0004424 only has two bits. | ||
+ | |||
+ | |||
+ | ===== Using with DMA ===== | ||
+ | |||
+ | The SPI controller can be used conjointly with [[DMA]] channels 0 or 1. Due to the simplistic design of the FIFO system, using DMA is more straightforward as it will take care of keeping the FIFOs happy for you. | ||
+ | |||
+ | To write using DMA, you simply start a DMA transfer instead of writing to 0xF0004410. You should rely on the SPI write IRQ to detect transfer completion. | ||
+ | |||
+ | To read using DMA, you set 0xF0004420 to the desired read length, then start a DMA transfer instead of reading from 0xF0004410. You should rely on the DMA IRQ to detect transfer completion. | ||
spi.1727610292.txt.gz · Last modified: 2024/09/29 11:44 by arisotura