Maple bus: Difference between revisions

From dreamcast.wiki
Jump to navigation Jump to search
mNo edit summary
 
(65 intermediate revisions by the same user not shown)
Line 5: Line 5:
[[File:Dreamcast Port.png|thumb|Dreamcast Port]]
[[File:Dreamcast Port.png|thumb|Dreamcast Port]]


A 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. Devices are powered with 5V from the host, and signals on the Maple Bus operate at 3.3V TTL.
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.<ref name="MBNutshell">''[https://tech-en.netlify.app/articles/en540236/index.html] Geek Tech Report | Maple BUS in a nutshell or SEGA Dreamcast Peripherals how to make''</ref> Devices are powered with 5V from the host, and signals on the Maple Bus operate at 3.3V TTL.<ref name="raphnet">''[https://www.raphnet.net/programmation/dreamcast_usb/index_en.php] Raphaël Assenat | Dreamcast controller to USB build log''</ref>


[[File:Maple Bus Electronics Block Diagram.png|Maple Bus Electronics Block Diagram]]
[[File:Maple Bus Electronics Block Diagram.png|frameless|500px|Maple Bus Electronics Block Diagram]]
 
[[File:Maple Bus Hardware Communication.png|thumb|Maple Bus Hardware Communication]]


* Both lines on the Bus are pulled HIGH through weak pullup resistors
* Both lines on the Bus are pulled HIGH through weak pullup resistors
Line 15: Line 13:
* During communication, a device should not drive both lines HIGH for very long to prevent a downstream device from thinking the bus is free
* 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
* 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
* A peripheral device will only communicate 1 packet of data in response to a request from the host<ref name="MBNutshell" />
 
[[File:Maple Bus Hardware Communication.png|frameless|600px|Maple Bus Hardware Communication]]
 
=== Sense ===
 
The Dreamcast does not rely on any sense line as some projects implement.<ref name="raphnet" /><ref>''[http://mc.pp.se/dc/controller.html] Dreamcast Programming - Controllers''</ref><ref>''[https://hackaday.com/2021/03/16/dreamcast-controller-adapter-even-works-with-mice/] Lewin Day | DREAMCAST CONTROLLER ADAPTER EVEN WORKS WITH MICE''</ref> 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 ==
== 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 another is about 125 nanoseconds. The minimum amount of time between edges on the same line is about 225 nanoseconds. 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.
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.<ref name="MBMeasurements">''[https://github.com/OrangeFox86/DreamcastControllerUsbPico/tree/main/measurements] Tails86 | DreamcastControllerUsbPico Maple Bus Measurements''</ref> 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.


=== Start Sequence ===
=== Data Packet Start Sequence ===


[[File:Maple Bus Start Sequence.png|thumb|Maple Bus Start Sequence]]
[[File:Maple Bus Start Sequence.png|thumb|Maple Bus Start Sequence]]


Every packet begins with a start sequence.  
Every data packet begins with a start sequence.  


# SDCKA is brought LOW
# SDCKA is brought LOW
# SDCKB is toggled 4 times
# SDCKB is toggled 4 times
# SDCKA is then brought back HIGH to complete the sequence
# SDCKA is then brought back HIGH to complete the sequence<ref name="MBWireProtocol">''[http://mc.pp.se/dc/maplewire.html] Marcus Comstedt | Dreamcast Programming - Maple Bus Wire Protocol''</ref>
<br>
<br>


=== End Sequence ===
=== Data Packet End Sequence ===


[[File:Maple Bus End Sequence.png|thumb|Maple Bus End Sequence]]
[[File:Maple Bus End Sequence.png|thumb|Maple Bus End Sequence]]
Line 41: Line 45:
# SDCKB is toggled HIGH then LOW
# SDCKB is toggled HIGH then LOW
# SDCKA is toggled 2 times
# SDCKA is toggled 2 times
# SDCKB is brought back HIGH to complete the sequence
# SDCKB is brought back HIGH to complete the sequence<ref name="MBWireProtocol"/>
<br><br><br><br><br><br>
<br><br><br><br><br><br>


Line 50: Line 54:
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.
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 state transition can be broken down into 3 phases:
Each bit transmission sequence can be broken down into 3 phases<ref>''[https://archive.org/details/MaplePatent/mode/1up]Maple Bus Patent''</ref>:
* Phase 1 - Clock Conditioning: Bring clock HIGH and keep data at the state it was previously
* 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 2 - Data Conditioning: Transition the data bit to the target value
Line 59: Line 63:
[[File:Maple Bus Data.png|Maple Bus Data]]
[[File:Maple Bus Data.png|Maple Bus Data]]


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 one edge and the next on each line is the sum of the time of 2 phases.
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<ref name="MBMeasurements" />
** 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<ref name="MBMeasurements" />
** 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 [[Maple_bus#Function_Codes|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.
 
[[File:Light Gun CRT Beam Detect.png|Light Gun CRT Beam Detect]]
 
=== 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.


Dreamcast host transmits with each "phase" lasting about 160 nanoseconds which means each bit can be transmitted in about 480 nanoseconds. Dreamcast controllers and other peripheral devices usually transmit a little slower with each phase lasting about 250 nanoseconds with about 110 microsecond delays between each 3-word chunk after the first frame word.
[[File:Maple Bus Reset Sequence.png|Maple Bus Reset Sequence]]


== Maple Bus Packet ==
== Maple Bus Data Packet ==


This section contains information about the packet structure inherent to the Maple Bus. Any data transmission follows this packet structure.
This section contains information about the packet structure inherent to the Maple Bus. Any data transmission follows this packet structure.
Line 77: Line 100:
A packet consists of the following data.
A packet consists of the following data.


* '''Frame:''' 1 32-Bit Word
* '''[[Maple_bus#Frame_Word|Frame]]:''' 1 32-Bit Word
* '''Payload:''' 0 to 255 32-Bit Words
* '''[[Maple_bus#Payload|Payload]]:''' 0 to 255 32-Bit Words
* '''CRC:''' 1 Byte
* '''[[Maple_bus#CRC|CRC]]:''' 1 Byte
 
==== Frame Word ====
==== Frame Word ====


The following is how a frame word is broken down into its 4 parts.
The following is how a frame word is broken down into its 4 parts<ref name="DPMapleBus">''[http://mc.pp.se/dc/maplebus.html] Marcus Comstedt | Dreamcast Programming - Maple Bus''</ref>.


{| class="wikitable"
{| class="wikitable"
Line 89: Line 111:
! Byte 0 (LSB) !! Byte 1 !! Byte 2 !! Byte 3 (MSB)
! Byte 0 (LSB) !! Byte 1 !! Byte 2 !! Byte 3 (MSB)
|-
|-
| <div style="text-align: center;">Number of Words<br>in Payload</div> || <div style="text-align: center;">Sender<br>Address</div> || <div style="text-align: center;">Recipient<br>Address</div> || <div style="text-align: center;">Command</div>
| <div style="text-align: center;">Number of Words<br>in Payload</div> || <div style="text-align: center;">Sender<br>[[Maple_bus#Addressing|Address]]</div> || <div style="text-align: center;">Recipient<br>[[Maple_bus#Addressing|Address]]</div> || <div style="text-align: center;">[[Maple_bus#Commands|Command]]</div>
|}
|}


Line 115: Line 137:
<nowiki>*</nowiki>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.
<nowiki>*</nowiki>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 source address as if it is player 1. As such, the host should ignore whatever the upper 2 bits that the device uses as its source address.
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 =====
===== Commands =====
Below shows command values and their meanings.<ref name="DPMapleBus"/><ref name="DCDocs">''[https://github.com/Kochise/dreamcast-docs/tree/master/CONTROLR/DOCS] Dreamcast Documents''</ref> For the communication direction, Host implies the Dreamcast and Device implies a peripheral.


{| class="wikitable"
{| class="wikitable"
|-
|-
! Command Value !! Description !! Communication Direction !! Number of Payload Words !! Expected Response
! Command Value !! Description !! Communication Direction !! Number of Payload Words !! Expected Response**
|-
|-
| 0x01 || Device Info Request* || Host->Device || 0 || 0x05  
| 0x01 || Device Info Request* || Host->Device || 0 || 0x05  
Line 131: Line 155:
| 0x04 || Shutdown || Host->Device || 0 || 0x07  
| 0x04 || Shutdown || Host->Device || 0 || 0x07  
|-
|-
| 0x05 || Device Info || Device->Host || 28 || -  
| 0x05 || Device Info || Device->Host || [[Maple_bus#Device_Info_Payload_Structure_.28cmd_0x05.29|28]] || -  
|-
|-
| 0x06 || Extended Device Info || Device->Host || 48 || -  
| 0x06 || Extended Device Info || Device->Host || [[Maple_bus#Extended_Device_Info_Payload_Structure_.28cmd_0x06.29|48]] || -  
|-
|-
| 0x07 || Acknowledge || Device->Host || 0 || -  
| 0x07 || Acknowledge || Device->Host || 0 || -  
|-
|-
| 0x08 || Data Transfer || Device->Host || 2..255 || -  
| 0x08 || Data Transfer || Device->Host || [[Maple_bus#Data_Transfer_Payload_Structure_.28cmd_0x08.29|2..255]] || -
|-
| 0x09 || Get Condition || Host->Device || [[Maple_bus#Get_Condition_Payload_Structure_.28cmd_0x09.29|1]] || 0x08
|-
| 0x0A || Get Memory Information || Host->Device || [[Maple_bus#Get_Memory_Information_Payload_Structure_.28cmd_0x0A.29|2]] || 0x08
|-
|-
| 0x09 || Get Condition || Host->Device || 1 || 0x08  
| 0x0B || Block Read || Host->Device || [[Maple_bus#Block_Read_Payload_Structure_.28cmd_0x0B.29|2]] || 0x08  
|-
|-
| 0x0A || Get Memory Information || Host->Device || 2 || 0x08
| 0x0C || Block Write || Host->Device || [[Maple_bus#Block_Write_Payload_Structure_.28cmd_0x0C.29|3..255]] || 0x07
|-
|-
| 0x0B || Block Read || Host->Device || 2 || 0x08
| 0x0D || Get Last Error || Host->Device || [[Maple_bus#Get_Last_Error_Payload_Structure_.28cmd_0x0D.29|2]] || 0x07
|-
|-
| 0x0C || Block Write || Host->Device || 3..255 || 0x07  
| 0x0E || Set Condition || Host->Device || [[Maple_bus#Set_Condition_Payload_Structure_.28cmd_0x0E.29|2..255]] || 0x07  
|-
|-
| 0x0D || Get Last Error || Host->Device || 2 || 0x07
| 0xF9 || AR Error || Device->Host || 0 || -
|-
|-
| 0x0E || Set Condition || Host->Device || 2..255 || 0x07
| 0xFA || LCD Error || Device->Host || 0 || -
|-
|-
| 0xFB || File Error || Device->Host || 0 || -  
| 0xFB || File Error || Device->Host || 0 || -  
|-
|-
| 0xFC || Request Resend || Device->Host || 0 || -
| 0xFC || Request Resend || ANY || 0 || Last Sent Command
|-
|-
| 0xFD || Unknown Command || Device->Host || 0 || -  
| 0xFD || Unknown Command || Device->Host || 0 || -  
|-
|-
| 0xFE || Function Code Not Supported || Device->Host || 0 || -  
| 0xFE || [[Maple_bus#Function_Codes|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.
<nowiki>*</nowiki>Most peripheral devices won't respond to any other command until device info is requested for the device.
 
<nowiki>**</nowiki>This is the expected response when device didn't experience an error


==== Payload ====
==== Payload ====


The structure of a payload is structured based on the command used in the frame word.
The structure of a payload is dependent on the command used in the frame word.


===== Device Info Payload Structure (cmd 0x05) =====
===== Device Info Payload Structure (cmd 0x05) =====
Line 172: Line 202:
! Word 0 !! Words 1-3 !! Word 4 !! Words 5-11 !! Words 12-26 !! Word 27
! 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** || MSB: Region code <br> 2 least significant bytes: 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 <br> 2 least significant bytes: maximum current consumption
| Supported [[Maple_bus#Function_Codes|function codes]] mask* || Function definitions for up to 3 devices** || Byte 3 (MSB): Region code <br> Byte 2: Connection direction code <br> 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 <br> 2 least significant bytes: maximum current consumption****
|}
|}


Line 179: Line 209:
<nowiki>**</nowiki>The first word in this set is meant for the most significant bit that is set to 1 in the function codes word
<nowiki>**</nowiki>The first word in this set is meant for the most significant bit that is set to 1 in the function codes word


<nowiki>***</nowiki>Refer to the [word format](#word-format) section about how to parse ASCII strings.
<nowiki>***</nowiki>Refer to the [[Maple_bus#Word_Format|word format]] section about how to parse ASCII strings.
 
<nowiki>****</nowiki>Current values in (x / 10) mA, each two byte value is transmitted as big-endian


===== Extended Device Info Payload Structure (cmd 0x06) =====
===== Extended Device Info Payload Structure (cmd 0x06) =====
Line 187: Line 219:
! Word 0 !! Words 1-3 !! Word 4 !! Words 5-11 !! Words 12-26 !! Word 27 !! Words 28-47
! 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** || MSB: Region code <br> 2 least significant bytes: 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 <br> 2 least significant bytes: maximum current consumption || Version information and/or capabilities ASCII string***
| Supported [[Maple_bus#Function_Codes|function codes]] mask* || Function definitions for up to 3 devices** || Byte 3 (MSB): Region code <br> Byte 2: Connection direction code <br> 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 <br> 2 least significant bytes: maximum current consumption**** || Version information and/or capabilities ASCII string***
|}
|}


Line 194: Line 226:
<nowiki>**</nowiki>The first word in this set is meant for the most significant bit that is set to 1 in the function codes word
<nowiki>**</nowiki>The first word in this set is meant for the most significant bit that is set to 1 in the function codes word


<nowiki>***</nowiki>Refer to the [word format](#word-format) section about how to parse ASCII strings.
<nowiki>***</nowiki>Refer to the [[Maple_bus#Word_Format|word format]] section about how to parse ASCII strings.
 
<nowiki>****</nowiki>Current values in (x / 10) mA, each two byte value is transmitted as big-endian


===== Data Transfer Payload Structure (cmd 0x08) =====
===== Data Transfer Payload Structure (cmd 0x08) =====
Line 202: Line 236:
! Word 0 !! Words 1..255
! Word 0 !! Words 1..255
|-
|-
| Function code || Data - device dependent structure
| [[Maple_bus#Function_Codes|Function code]] || Data - device dependent structure
|}
|}


Line 211: Line 245:
! Word 0  
! Word 0  
|-
|-
| Function code
| [[Maple_bus#Function_Codes|Function code]]
|}
|}


Line 220: Line 254:
! Word 0 !! Word 1
! Word 0 !! Word 1
|-
|-
| Function code || Location word
| [[Maple_bus#Function_Codes|Function code]] || [[Maple_bus#Location_Word|Location word]]*
|}
|}
<nowiki>*</nowiki>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) =====
===== Block Read Payload Structure (cmd 0x0B) =====
Line 229: Line 265:
! Word 0 !! Word 1
! Word 0 !! Word 1
|-
|-
| Function code || Location word
| [[Maple_bus#Function_Codes|Function code]] || [[Maple_bus#Location_Word|Location word]]
|}
|}


Line 238: Line 274:
! Word 0 !! Word 1 !! Words 2..255
! Word 0 !! Word 1 !! Words 2..255
|-
|-
| Function code || Location word || Data - device dependent structure
| [[Maple_bus#Function_Codes|Function code]] || [[Maple_bus#Location_Word|Location word]] || Data - device dependent structure
|}
|}


Line 247: Line 283:
! Word 0 !! Word 1
! Word 0 !! Word 1
|-
|-
| Function code || Location word
| [[Maple_bus#Function_Codes|Function code]] || [[Maple_bus#Location_Word|Location word]]
|}
|}


Line 256: Line 292:
! Word 0 !! Words 1..255
! Word 0 !! Words 1..255
|-
|-
| Function code || Condition - device dependent structure
| [[Maple_bus#Function_Codes|Function code]] || Condition - device dependent structure
|}
|}


Line 265: Line 301:
====== Function Codes ======
====== Function Codes ======


The below are function codes which are used to address functionality in some payloads.
The below are function codes which are used to address functionality in some payloads<ref name="DPMapleBus"/>.


{| class="wikitable"
{| class="wikitable"
Line 294: Line 330:
====== Location Word ======
====== Location Word ======


Below defines a location word which is used to address blocks of memory in some peripherals.
Below defines a location word which is used to address blocks of memory in some peripherals<ref name="DPMapleBus"/>.


{| class="wikitable"
{| class="wikitable"
Line 304: Line 340:


* '''Block''': Memory block number index
* '''Block''': Memory block number index
* '''Phase''': Sequence number
* '''Phase''': Sequence number (starts at 0 and counts up)
* '''Partition''': Partition number (normally 0)
* '''Partition''': Partition number (normally 0)


Line 310: Line 346:


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.
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.
* [[Controller peripheral]]
* [[VMU peripheral]]
* [[Jump pack peripheral]]
== References ==
<references />

Latest revision as of 22:56, 10 March 2024

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

Dreamcast Port

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]

Maple Bus Electronics Block Diagram

  • 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]

Maple Bus Hardware Communication

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

Maple Bus Start Sequence

Every data packet begins with a start sequence.

  1. SDCKA is brought LOW
  2. SDCKB is toggled 4 times
  3. SDCKA is then brought back HIGH to complete the sequence[6]


Data Packet End Sequence

Maple Bus End Sequence

Every packet is completed with an end sequence to commit the data to the target component.

  1. SDCKA is brought HIGH
  2. SDCKB is toggled HIGH then LOW
  3. SDCKA is toggled 2 times
  4. SDCKB is brought back HIGH to complete the sequence[6]







Data Bit Sequences

Maple Bus Clocking Phases

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.

Maple Bus Data

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.

Light Gun CRT Beam Detect

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 Reset Sequence

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:

Frame Word 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. 1.0 1.1 [1] Geek Tech Report | Maple BUS in a nutshell or SEGA Dreamcast Peripherals how to make
  2. 2.0 2.1 [2] Raphaël Assenat | Dreamcast controller to USB build log
  3. [3] Dreamcast Programming - Controllers
  4. [4] Lewin Day | DREAMCAST CONTROLLER ADAPTER EVEN WORKS WITH MICE
  5. 5.0 5.1 5.2 [5] Tails86 | DreamcastControllerUsbPico Maple Bus Measurements
  6. 6.0 6.1 [6] Marcus Comstedt | Dreamcast Programming - Maple Bus Wire Protocol
  7. [7]Maple Bus Patent
  8. 8.0 8.1 8.2 8.3 [8] Marcus Comstedt | Dreamcast Programming - Maple Bus
  9. [9] Dreamcast Documents