Details on the 3DO PBUS / Player Bus. This is the bus used to communicate with control pads, flight sticks, light guns, mice, and other peripherals. ====== Pinout ====== {{ :images:player_bus_controller_pinout.png?480x487 }}Taken from the [[:documentation:manuals_and_schematics|FZ-1 Technical Guide]] ====== Patent ====== {{:documentation:patents:wo09410636a1_-_player_bus_apparatus_and_method.pdf|WO09410636a1 - Player Bus Apparatus and Method.pdf}} {{ :images:player_bus_block_diagram.png?480x344 }} ====== Protocol ====== From the patent: pages 21-23
Since the above described arrangement permits 448 bits to be\\ transferred per field and the minimum bit transfer per device is\\ 8bits, a maximum of approximately 56 devices can be on the bus at\\ one time. Each of the player devices has an ID code embedded in its response\\ data. An ID code is mapped by software in the system to the number\\ of input and output bits for the device identified. Since the ID\\ code is embedded, it is received by the system 100 both at\\ initialization and when data is being read in under normal\\ operation. In this manner, it is possible to reconfigure the\\ system (add or delete devices) without re-initializing and without\\ adversely affecting those device already on the line. During an initialization sequence, a string of zeros is shifted\\ out from the system 100. A requirement for all of the player\\ devices is that they see a string of zeros either as an\\ initialization or don't cares. The first 4 bits of data stream received by the system 100 from\\ each device is that device's basic identification code (ID\\ code). The embedding of an ID code in the data stream functions as\\ follows for a joystick 15. The basic joystick 15 will have 8 bits\\ of data that are (inverted): down, up, right, left, switch-2,\\ switch-1, fire-2 and fire-1. Using the inability of the joystick\\ to indicate both up and down at the same time, the ID codes for a\\ basic joystick are 01QQ, 10QQ and 11QQ, where QQ is 01, 10 or\\ 11. All other devices start with 00QQ. All joysticks are incapable\\ of generating 00 for their first 2 bits. With regard to the escape\\ function, the 1100 sequence indicates escape for the joystick. In\\ all other devices, the escape function is indicated by the bit\\ immediately following the 4 bit identification code. A string of\\ zeros indicate the end of input data into the system 100 device.
===== Control Pad / Joypad ===== ^Bits (MSB → LSB)^Description| |1bit|set, the high order bit from the ID (0x80)| |2bit|unused, unset, part of the joypad mask| |1bit|set if DPAD DOWN pressed| |1bit|set if DPAD UP pressed| |1bit|set if DPAD RIGHT pressed| |1bit|set if DPAD LEFT pressed| |1bit|set if A pressed| |1bit|set if B pressed| |1bit|set if C pressed| |1bit|set if P pressed| |1bit|set if X pressed| |1bit|set if RIGHT TRIGGER pressed| |1bit|set if LEFT RIGGER pressed| |2bit|unused? unset with normal joypad| ===== Flightstick / Analog Controller ===== ^Bits (MSB → LSB)^Description| |8bit|identifier 0 (0x01)| |8bit|identifier 1 (0x7B)| |8bit|length? (0x08)| |8bit|horizontal position| |2bit|unused? / unset| |8bit|vertical position| |2bit|unused? / unset| |8bit|depth position| |4bit|0x2 (unsure meaning)| |1bit|set if TRIGGER / FIRE pressed| |1bit|set if A pressed| |1bit|set if B pressed| |1bit|set if C pressed| |1bit|set if DPAD UP pressed| |1bit|set if DPAD DOWN pressed| |1bit|set if DPAD RIGHT pressed| |1bit|set if DPAD LEFT pressed| |1bit|set if P pressed| |1bit|set if X pressed| |1bit|set if LEFT TRIGGER pressed| |1bit|set if RIGHT TRIGGER pressed| |4bit|unused? / unset| ===== Mouse ===== ^Bits (MSB → LSB)^Description| |8bit|identifier (0x49)| |1bit|set if LEFT BUTTON pressed| |1bit|set if MIDDLE BUTTON pressed| |1bit|set if RIGHT BUTTON pressed| |1bit|set if SHIFT BUTTON pressed| |10bit|x delta (signed)| |10bit|y delta (signed)| ===== Lightgun ===== According to the 3DO SDK's Examples/EventBroker/LightGun/lightgun.c: DESCRIPTION OF LIGHTGUN HARDWARE -------------------------------- The lightgun is not capable of returning an (X, Y) position value when reporting events. It does report a counter value that returns the time it took between the beginning of a field (vertical blank) and when the scan-beam passes into the field of view of the light sensor in the lightgun. The X and Y value can be calculated from the timer value returned from the lightgun based on how long it takes to draw from the start of one scan line to the start of the scan line immediately below it (YSCANTIME) and how long it takes to draw from the first pixel to the last pixel on the same scan line (XSCANTIME). A third required value, is a time offset value that takes into consideration the time between the beginning of a field and when scan-beam begings drawing to the first pixel on the first scan line (TIMEOFFSET). #define NTSC_DEFAULT_XSCANTIME 1030 #define NTSC_DEFAULT_YSCANTIME 12707 #define NTSC_DEFAULT_TIMEOFFSET -12835 #define PAL_DEFAULT_XSCANTIME 1051 #define PAL_DEFAULT_YSCANTIME 12796 #define PAL_DEFAULT_TIMEOFFSET -58995 #define PAL_WIDTH 388 #define NTSC_WIDTH 320 x = ((((10 * counter) % NTSC_DEFAULT_YSCANTIME) * NTSC_WIDTH) / (NTSC_DEFAULT_XSCANTIME * 10)); y = ((10 * counter) / NTSC_DEFAULT_YSCANTIME); From the 3DO SDK's Interfaces/2p5/includes/event.h: - The "Lightgun" generic class and event structures are for the use of pods/devices which can't report X and Y positions, but only a time (counter value) between the beginning of field, and the time that the scan-beam passed into the field-of-view of the lightgun sensor. Some lightguns can also send in a "signal quality" pulse counter, this being the number of successive horizontal scan lines during which the beam was seen at roughly the same horizontal posotion. A line pulse count of 0 means "no hit". typedef struct LightGunEventData { uint32 lged_ButtonBits; /* left justified, zero fill */ uint32 lged_Counter; /* counter at top-center of hit */ uint32 lged_LinePulseCount; /* # of scan lines which were hit */ } LightGunEventData; #define LightGunTrigger 0x80000000 ^Bits (MSB → LSB)^Description| |8bit|identifier (0x4D)| |1bit|set if TRIGGER pressed| |1bit|set if SERVICE pressed (arcade)| |1bit|set if COIN pressed (arcade)| |1bit|set if START pressed (arcade)| |1bit|set if HOLSTER (arcade) or OPTION (retail) pressed| |1bit|unused? / unset| |1bit|unused? / unset| |20bit|Counter: counter at top-center of hit| |5bit|LinePulseCount: number of scanlines which were hit| ===== Orbatak Trackball ===== Orbatak has two device types. The trackballs are the same as the regular mouse as described above. ===== Orbatak Coin / Start / Service ===== The extra buttons needed for the coin slots, start buttons, and service button are provided by the "SILLY_CONTROL_PAD" as it's defined in the 3DO SDK (event.h). ^Bits (MSB → LSB)^Description| |8bit|identifier (0xC0)| |8bit|0x00 / unset| |3bit|unused / unset| |1bit|set if COIN (P1) pressed| |1bit|set if COIN (P2) pressed| |1bit|set if START (P2) pressed| |1bit|set if START (P1) pressed| |1bit|set if SERVICE pressed| |8bit|0x00 / unset| ====== Portfolio Drivers ====== The 3DO's Portfolio operating system has the ability to dynamically load drivers for peripherals. These "ROM" files, which appear to be AIF files of dynamically loadable code, can live on the [[https://github.com/trapexit/portfolio_os/blob/master/src/input/DefaultDriver.c#L258|filesystem]] or be [[https://github.com/trapexit/portfolio_os/blob/master/src/input/DefaultDriver.c#L246|sent over the PBUS]] by the device. Details about PBUS devices can primarily be found in two locations: * [[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h|event.h]] : The header provided in the SDK for developers of the platform * [[https://github.com/trapexit/portfolio_os/tree/master/src/input|portfolio_os/src/input]] : The core operating system code that manages the high level POD abstraction Here is a list of known drivers: ^Device^Device ID^Driver^Notes| |Default|none|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/DefaultDriver.c|DefaultDriver.c]]| | |control pad|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/EventBroker.c#L1635|embedded into first byte]]|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/ControlPadDriver.c|ControlPadDriver.c]]| | |analog stick|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L814|0x01]]|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/StickDriver.c|StickDriver.c]] and [[https://ext.3dodev.com/3DO/Portfolio_2.5/cdrommaster/2p5/takeme/System/Drivers/cport1.rom|cport1.rom]]|Unsure about there being apparently a builtin and dynamically loaded driver. Unsure what the difference is between 0x01 device ID version and the [[https://github.com/trapexit/portfolio_os/blob/master/src/input/EventBroker.c#L377|0x4C version]].| |keyboard|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L815|0x02]] or [[https://github.com/trapexit/portfolio_os/blob/master/src/input/EventBroker.c#L376|0x4B]]|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/KeyboardDriver.c|KeyboardDriver.c]]|KeyboardDriver.c appears incomplete and non-functional.| |mouse|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L794|0x49]]|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/MouseDriver.c|MouseDriver.c]] and [[https://ext.3dodev.com/3DO/Portfolio_2.5/cdrommaster/2p5/takeme/System/Drivers/cport49.rom|cport49.rom]]|ROM can be found in numerous SDKs.| |stereoscopic glasses|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L793|0x41]]|[[https://ext.3dodev.com/3DO/Portfolio_2.5/cdrommaster/2p5/takeme/System/Drivers/cport41.rom|cport41.rom]]|ROM can be found in numerous SDKs.| |lightgun|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L795|0x4D]]|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/LightGunRom.c|LightGunRom.c]] and [[https://ext.3dodev.com/3DO/Portfolio_2.5/cdrommaster/2p5/takeme/System/Drivers/cport4D.rom|cport4D.rom]]|ROM can be found in numerous SDKs.| |splitter|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L796|0x56]]|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/SplitterDriver.c|SplitterDriver.c]]| | |splitter 2|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L797|0x57]]|?? [[https://github.com/trapexit/portfolio_os/blob/master/src/input/SplitterDriver.c|SplitterDriver.c]]|A different kind of splitter? Or a second splitter in the same device chain?| |ir receiver|[[https://github.com/trapexit/portfolio_os/blob/master/src/input/includes/event.h#L816|0x03]]|cport3.rom|ROM only found in the [[https://3dodev.com/software/sdks#do_m1_sdks|"3DO Dev Tools" archive]] under "3DO_OS/net1p0d8/remote/System/Drivers/"|