Maple bus
The Maple bus is the communications bus the Dreamcast uses to connect controllers and other related peripherals. It is a symmetrical serial protocol.
Hardware Overview
Four separate Maple Buses exist on a Dreamcast system - one for each player. Each Maple Bus consists of 2 signal/clock lines that are labeled SDCKA and SDCKB. Hardware on the Maple Bus consists of one host, zero or one main peripheral, and zero to five sub-peripherals. The only difference between a main peripheral and a sub-peripheral is that a main peripheral communicates to the host what sub-peripherals are attached during normal communication. The main peripheral is something like a Dreamcast controller, and the sub-peripherals are things like a VMU, jump pack, and microphone. The host and all connected peripheral devices communicate on the same 2-line Maple Bus.[1] Devices are powered with 5V from the host, and signals on the Maple Bus operate at 3.3V TTL.[2]
- Both lines on the Bus are pulled HIGH through weak pullup resistors
- Only one connected component on the bus may communicate at a time
- During communication, a device should not drive both lines HIGH for very long to prevent a downstream device from thinking the bus is free
- Before a component starts communicating, it must verify the bus is neutral for a sufficient amount of time
- A peripheral device will only communicate 1 packet of data in response to a request from the host[1]
Sense
The Dreamcast does not rely on any sense line as some projects implement.[2][3][4] Both ground wires from the controller are tied to ground at the controller port module on the Dreamcast. To detect the presence of a device, Dreamcast instead sends a device info request every 16 ms until a main peripheral responds on the bus.
Maple Bus Signals
There is no handshaking done to determine how fast each component may transmit on the Maple Bus. Transmission speeds are internally pre-determined by each hardware component. Generally speaking, for all signals, the minimum amount of time between an edge (transition between logic levels) of one line and an edge of the other is about 125 nanoseconds. The minimum amount of time between edges on the same line is about 225 nanoseconds.[5] There is no maximum time limit as long as both lines aren't held HIGH during active transmission for any extended amount of time. These guidelines may be applied for any sequence below.
Data Packet Start Sequence
Every data packet begins with a start sequence.
- SDCKA is brought LOW
- SDCKB is toggled 4 times
- SDCKA is then brought back HIGH to complete the sequence[6]
Data Packet End Sequence
Every packet is completed with an end sequence to commit the data to the target component.
- SDCKA is brought HIGH
- SDCKB is toggled HIGH then LOW
- SDCKA is toggled 2 times
- SDCKB is brought back HIGH to complete the sequence[6]
Data Bit Sequences
For each bit, one line of the maple bus acts as a clock while the other is the data to be sampled. A data bit is clocked when the designated clock line transitions from HIGH to LOW. The two lines trade their function after each bit. Line A acts as clock and B acts as data for the first bit. Line B acts as clock and A acts as data for the next bit. Line A acts as clock again for the bit after that. The pattern repeats until all data is transmitted.
Each bit transmission sequence can be broken down into 3 phases[7]:
- Phase 1 - Clock Conditioning: Bring clock HIGH and keep data at the state it was previously
- Phase 2 - Data Conditioning: Transition the data bit to the target value
- Phase 3 - Clocking: Bring clock LOW in order to have the data bit sampled
There are a total of 6 types of state transitions, depending on what the previous phase was and the target bit value. A depiction of state transitions can be seen in the image below.
Notice that each line, A & B transitions states in a staggard pattern i.e., only one line may change its logic level within each phase. Because of the staggard pattern, the minimum time between an edge of one line and an edge of the other is 1 phase length, and the minimum time between edges on the same line is the sum of the time of 2 phases. The total bit transmission time is of course the sum of the time of all 3 phases.
- The Dreamcast host transmits each phase at about 160 nanoseconds[5]
- This works out to be about 2 mbps raw data transfer speed
- Dreamcast controllers and other peripheral devices usually transmit a little slower at about 250 nanoseconds per phase and sometimes with about 110 to 130 microsecond delays between each 4-word chunk after the first frame word[5]
- This works out to between about 0.5 and 1.3 mbps raw data transfer speed
Light Gun CRT Beam Detection Sequence
The start sequence for light gun CRT beam detection looks similar to a data packet start sequence, but 8 pulses on the SDCKB line signify the start of this mode. This mode is used to gain precise timing for position detection of the electron beam for a specific pixel on a CRT monitor which the light gun is currently aiming at.
This mode is only activated when the main peripheral implements both Controller and either Gun or AR Gun function code. Dreamcast initiates this sequence to a light gun once the Dreamcast detects that the trigger (A button) has been pressed through normal data packet sequences. The light gun is expected to bring SDCKB LOW within the period of time marked blue in the image below once it detects that the electron beam of a CRT is in view of the light gun's lens. Once the Dreamcast brings SDCKA back HIGH, SDCKB must be brought back HIGH, and the control of SDCKB must be let go by the light gun. No end sequence is sent after this is completed.
The duration of time given for beam detection is the time it takes to scan either only odd lines or the entire screen, depending on how the specific game is coded. For a 60 Hz screen (59.94 Hz actual) displaying 480i, this is about 16.68 milliseconds for half or 33.37 milliseconds for full. If no beam is detected, meaning SDCKB remains HIGH throughout the entire period, then the game normally treats this as a gun reload event.
Reset Sequence
A reset sequence may be sent from the host in order to attempt to reset all devices on the bus. It is similar to a start sequence, but there are 14 pulses on SDCKB.
Maple Bus Data Packet
This section contains information about the packet structure inherent to the Maple Bus. Any data transmission follows this packet structure.
Word Format
Each word is 32 bits in length, transmitted in little-endian byte order. The most significant bit of each byte transmits first. This means that the most significant bit of the least significant byte of each word transmits first. All tables in this wiki list bytes in transmission order with the least significant bit (LSB) as the first byte.
When ASCII text or a byte stream is transmitted, the most significant byte is the first character of the 4 character sequence in each word. This means that the byte order of each word needs to be flipped before parsing the payload as a character or byte array. The size of an ASCII payload section is pre-determined based on the command. No NULL termination byte is supplied at the end of the string, and spaces (0x20) are used to pad out remaining characters at the end of the string.
Packet Data Format
A packet consists of the following data.
Frame Word
The following is how a frame word is broken down into its 4 parts[8].
Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB) |
---|---|---|---|
Number of Words in Payload |
Sender Address |
Recipient Address |
example:
Addressing
The following addresses are used for all components on the bus.
Player Number | Host | Main Peripheral | Sub-Peripheral 1 | Sub-Peripheral 2 | Sub-Peripheral 3 | Sub-Peripheral 4 | Sub-Peripheral 5 |
---|---|---|---|---|---|---|---|
1 | 0x00 | 0x20* | 0x01 | 0x02 | 0x04 | 0x08 | 0x10 |
2 | 0x40 | 0x60* | 0x41 | 0x42 | 0x44 | 0x48 | 0x50 |
3 | 0x80 | 0xA0* | 0x81 | 0x82 | 0x84 | 0x88 | 0x90 |
4 | 0xC0 | 0xE0* | 0xC1 | 0xC2 | 0xC4 | 0xC8 | 0xD0 |
*When the main peripheral responds with its sender address, it also sets the bits corresponding to which sub-peripherals are attached. For example, if sub-peripherals 1 and 2 are attached to player 1's main peripheral, the main peripheral will set its sender address to 0x23. This informs the host what else is attached. The host should still set the recipient address to 0x20 when sending data to this peripheral though.
In testing, there have been cases where a peripheral will respond with a sender address as if it is player 1. As such, the host should ignore whatever the upper 2 bits that the device uses as its sender address.
Commands
Below shows command values and their meanings.[8][9] For the communication direction, Host implies the Dreamcast and Device implies a peripheral.
Command Value | Description | Communication Direction | Number of Payload Words | Expected Response** |
---|---|---|---|---|
0x01 | Device Info Request* | Host->Device | 0 | 0x05 |
0x02 | Extended Device Info Request | Host->Device | 0 | 0x06 |
0x03 | Reset | Host->Device | 0 | 0x07 |
0x04 | Shutdown | Host->Device | 0 | 0x07 |
0x05 | Device Info | Device->Host | 28 | - |
0x06 | Extended Device Info | Device->Host | 48 | - |
0x07 | Acknowledge | Device->Host | 0 | - |
0x08 | Data Transfer | Device->Host | 2..255 | - |
0x09 | Get Condition | Host->Device | 1 | 0x08 |
0x0A | Get Memory Information | Host->Device | 2 | 0x08 |
0x0B | Block Read | Host->Device | 2 | 0x08 |
0x0C | Block Write | Host->Device | 3..255 | 0x07 |
0x0D | Get Last Error | Host->Device | 2 | 0x07 |
0x0E | Set Condition | Host->Device | 2..255 | 0x07 |
0xF9 | AR Error | Device->Host | 0 | - |
0xFA | LCD Error | Device->Host | 0 | - |
0xFB | File Error | Device->Host | 0 | - |
0xFC | Request Resend | ANY | 0 | Last Sent Command |
0xFD | Unknown Command | Device->Host | 0 | - |
0xFE | Function code Not Supported | Device->Host | 0 | - |
*Most peripheral devices won't respond to any other command until device info is requested for the device.
**This is the expected response when device didn't experience an error
Payload
The structure of a payload is dependent on the command used in the frame word.
Device Info Payload Structure (cmd 0x05)
Word 0 | Words 1-3 | Word 4 | Words 5-11 | Words 12-26 | Word 27 |
---|---|---|---|---|---|
Supported function codes mask* | Function definitions for up to 3 devices** | Byte 3 (MSB): Region code Byte 2: Connection direction code Bytes 1 and 0: first two characters of description ASCII string*** |
The rest of the description ASCII string*** | Producer information ASCII string*** | 2 most significant bytes: standby current consumption 2 least significant bytes: maximum current consumption**** |
*The supported function codes mask in device info responses will contain the bitmask for 1 or more devices ex: a VMU will have a mask of 0x0000000E for Timer, Screen, and Storage.
**The first word in this set is meant for the most significant bit that is set to 1 in the function codes word
***Refer to the word format section about how to parse ASCII strings.
****Current values in (x / 10) mA, each two byte value is transmitted as big-endian
Extended Device Info Payload Structure (cmd 0x06)
Word 0 | Words 1-3 | Word 4 | Words 5-11 | Words 12-26 | Word 27 | Words 28-47 |
---|---|---|---|---|---|---|
Supported function codes mask* | Function definitions for up to 3 devices** | Byte 3 (MSB): Region code Byte 2: Connection direction code Bytes 1 and 0: first two characters of description ASCII string*** |
The rest of the description ASCII string*** | Producer information ASCII string*** | 2 most significant bytes: standby current consumption 2 least significant bytes: maximum current consumption**** |
Version information and/or capabilities ASCII string*** |
*The supported function codes mask in device info responses will contain the bitmask for 1 or more devices ex: a VMU will have a mask of 0x0000000E for Timer, Screen, and Storage.
**The first word in this set is meant for the most significant bit that is set to 1 in the function codes word
***Refer to the word format section about how to parse ASCII strings.
****Current values in (x / 10) mA, each two byte value is transmitted as big-endian
Data Transfer Payload Structure (cmd 0x08)
Word 0 | Words 1..255 |
---|---|
Function code | Data - device dependent structure |
Get Condition Payload Structure (cmd 0x09)
Word 0 |
---|
Function code |
Get Memory Information Payload Structure (cmd 0x0A)
Word 0 | Word 1 |
---|---|
Function code | Location word* |
*Only the partition number should be set in the location word. Set all other bytes in the location word to 0.
Block Read Payload Structure (cmd 0x0B)
Word 0 | Word 1 |
---|---|
Function code | Location word |
Block Write Payload Structure (cmd 0x0C)
Word 0 | Word 1 | Words 2..255 |
---|---|---|
Function code | Location word | Data - device dependent structure |
Get Last Error Payload Structure (cmd 0x0D)
Word 0 | Word 1 |
---|---|
Function code | Location word |
Set Condition Payload Structure (cmd 0x0E)
Word 0 | Words 1..255 |
---|---|
Function code | Condition - device dependent structure |
Common Payload Word Types
The following word types are used in some of the above payload structures.
Function Codes
The below are function codes which are used to address functionality in some payloads[8].
Code / Mask | Description |
---|---|
0x00000001 | Controller |
0x00000002 | Storage |
0x00000004 | Screen |
0x00000008 | Timer |
0x00000010 | Audio Input |
0x00000020 | AR Gun |
0x00000040 | Keyboard |
0x00000080 | Gun |
0x00000100 | Vibration |
0x00000200 | Mouse |
Location Word
Below defines a location word which is used to address blocks of memory in some peripherals[8].
Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB) |
---|---|---|---|
Block LSB | Block MSB | Phase | Partition |
- Block: Memory block number index
- Phase: Sequence number (starts at 0 and counts up)
- Partition: Partition number (normally 0)
CRC
CRC byte transmits last, just before the end sequence is transmitted. It is the value after starting with 0 and applying XOR against each byte in the packet.
Peripheral Implementation
Refer to the following pages for a specific peripheral implementation.
References
- ↑ 1.0 1.1 [1] Geek Tech Report | Maple BUS in a nutshell or SEGA Dreamcast Peripherals how to make
- ↑ 2.0 2.1 [2] Raphaël Assenat | Dreamcast controller to USB build log
- ↑ [3] Dreamcast Programming - Controllers
- ↑ [4] Lewin Day | DREAMCAST CONTROLLER ADAPTER EVEN WORKS WITH MICE
- ↑ 5.0 5.1 5.2 [5] Tails86 | DreamcastControllerUsbPico Maple Bus Measurements
- ↑ 6.0 6.1 [6] Marcus Comstedt | Dreamcast Programming - Maple Bus Wire Protocol
- ↑ [7]Maple Bus Patent
- ↑ 8.0 8.1 8.2 8.3 [8] Marcus Comstedt | Dreamcast Programming - Maple Bus
- ↑ [9] Dreamcast Documents