Saturn Controller Protocol MK80116-MK80100

RDC

Member
Hey all,

Most people that have seen my work know it's pretty much all done on the hardware side of things, but here over the last few years I've been trying to get into the coding side of things as well.

I've been tinkering around here with the different protocols controllers use, so instead of hacking the thing up up I can just plug it into something. The PSX (neGcon specifically), N64 and now I've been messing with the Saturn.

The Saturn controller connector has 9 pins. Looking into the end of the plug on the controller, beveled side up..

Code:
/-----------\
| 987654321 |
|___________|

1 - 5v (Power to Controller)
2 - D1 (Data 1)
3 - D0 (Data 0)
4 - S1 (Select 1)
5 - S0 (Select 0)
6 - Detect/?
7 - D3 (Data 3)
8 - D2 (Data 2)
9 - Ground

The standard 6 button Saturn controller uses 2 Select Bits, S1 and S0 and then it has 4 Data Bits, D3, D2, D1 and D0. From those 2 select bits, 4 different states can be set, 10, 01, 00 and 11 and then from each of those 4 different states 4 bits of data can be read from the D3, D2, D1 and D0 lines.

Select Bits - Data Bits
S1 S0 - D3, D2, D1, D0

10 - DR, DL, DD, DU
01 - ST, A, C, B
00 - R, X, Y, Z
11 - L, *, *, *

* are not used.

To 'read' what button on the controller is pressed, you change the Select bits and then 'see' what's going on with the 4 Data bits. Any button that is pressed will be a Logic 0 (ground) while unpressed buttons will have a Logic 1 (voltage) there.

This is what it looks like on a Logic Analyzer with no buttons pressed. You can see the S1 (green) and S0 (yellow) lines changing states. The D3, D2, D1 and D0 lines are all Hi (Logic 1) during these changes, when there is a 0 there then you know a button is pressed.

6ButtonLA_zps54225114.jpg


Now if only the A button were pressed, you'd get this..

10 - 1,1,1,1
01 - 1,0,1,1 <-- The A button is pressed here
00 - 1,1,1,1
11 - 1,*,*,*

Then what it looks like on the Logic Analyzer. Only the Data line for A is Lo, and only during the time that the Select Bits are 01.

6ButtonALA_zpsd158b6fb.jpg


Then if DR, C and X are pressed..

10 - 0,1,1,1 <-- DR is pressed here
01 - 1,1,0,1 <--C is pressed here
00 - 1,0,1,1 <--X is pressed here
11 - 1,*,*,*

Then again what that looks like on the LA, and again those Data lines are only Lo during the times the Select Bits are for each one.

6ButtonDRCXLA_zps2412a16f.jpg


This all may seem like a lot to check, with having to switch between the 4 different states and then checking 4 lines for each one, but it takes around 150us for all of that to happen 1 time, and the Saturn does this check roughly once every 16ms, or in the time it takes you to blink it's already done it more than 20 times. This can also be done faster as well

This was my test setup. MK-80100 controller. PIC16F1516 on the bread board. PicKit3 for powering the PIC and Controller. Saleae Logic for seeing what's going on, then a 16x2 LCD display that's powered from an external 5v PSU. (because I can only watch LEDs blink on a port for so long)

6Button_zps3b8c0fe7.jpg


Close up of the LCD. The second line are the buttons, first the D-pad, Up, Down, Left and Right, then Start, followed by the A,B,C,X,Y and Z buttons then the L and R shoulder buttons.

6ButtonClose_zps129a43b9.jpg


Very, very, crappy video of it working. Apologies for how awful it is, but my camera is in fact just a camera, not a video camera, and some blame to PB for resizing it, as it looks a little better in it's native resolution, but still nothing to write home about.

When a button is pressed that disappears from the LCD screen, unpressed and it's back - http://s50.beta.photobucket.com/user/RD ... 5.mp4.html

This was done on a PIC16F1516, Source code was made in MikroC PRO. The LCD portion of the code has been removed, as I doubt anyone that wants to tinker with this will want to specifically do just that, but if you have one and want to wire it all up like I did let me know and I can post up everything for how to do it.

Code:
/*******************************************************************************
SEGA Saturn 6 Button Controller Tester/Interface (Tested on the MK80116 and MK80100)

PIC16F1516 @16MHz Internal OSC

Select Bits S1 and S0, will always start at 11 and end at 11, but are never
11 while reading data from the D3, D2, D1 and D0 lines.

The Select Bit "stepping" for the MK80116 and MK80100 pads are..

11    // Waiting
10    // First half of Data1 (Byte1) on the D3, D2, D1 and D0 lines = DR, DL, DD, DU
01    // Second half of Data1 = ST, A, C, B
00    // First half of Data2 = R, X, Y, Z
11    // Second half of Data2, = L, -, -

There is roughly a 16ms interval between reading the last bits of data
and then starting over, so the controller is checked every 16ms or so
for any changes to the button states

The Saturn controllers run from a 5v power source. They can run from 3.3v at the very least, but a 5v source is recommended

2013 RDC
*******************************************************************************/

char DR, DL, DU, DD, ST, AB, CB, BB, RB, XB, YB, ZB, LB;

char TEMP_NIBBLE;
char BYTE1, BYTE2;


// Initialize the PIC
void INIT() {
OSCCON = 0b01111010;                     // 8MHz 0b01110010; // 16MHz 0b01111010;
ANSELA = 0b00000000;                     // All AN are Digital
ANSELB = 0b00000000;                     // All AN are Digital
ANSELC = 0b00000000;                     // All AN are Digital
TRISA = 0b00000000;                      // PORTA
TRISB = 0b11000000;                      // PORTB 6 and 7 reserved for ICSP
TRISC = 0b00001111;                      // PORTC
PORTC = 0b00110000;                      // Select Bits, S1 = 1 and S0 = 1
}


void main() {

  INIT();
  
  while(1){

    PORTC = 0b00100000;                      // Select Bits are 10

    TEMP_NIBBLE = PORTC & 0b00001111;        // Read lower 4 bits from PORTC

    BYTE1 = TEMP_NIBBLE <<= 4;               // Shift that data over and save

    PORTC = 0b00010000;                      // Select Bits are 01

    TEMP_NIBBLE = PORTC & 0b00001111;        // Read lower 4 bits from PORTC

    BYTE1 = BYTE1 + TEMP_NIBBLE;             // Add new data to shifted data
                                             // this makes the 8 Bits of Byte1
    PORTC = 0b00000000;                      // Select Bits are 00

    TEMP_NIBBLE = PORTC & 0b00001111;        // Read lower 4 bits from PORTC

    BYTE2 = TEMP_NIBBLE <<= 4;               // Shift that data over and save

    PORTC = 0b00110000;                      // Select Bits are 11

    TEMP_NIBBLE = PORTC & 0b00001111;        // Read lower 4 bits from PORTC

    BYTE2 = BYTE2 + TEMP_NIBBLE;             // Add new data to shifted data
                                             // this makes the 8 Bits of Byte2

// Masking to look at each bit of the Bytes individually
// The Bit is >= 1 when not pressed, or 0 when pressed

    DR = BYTE1 & 0b10000000;
    DL = BYTE1 & 0b01000000;
    DD = BYTE1 & 0b00100000;
    DU = BYTE1 & 0b00010000;
    ST = BYTE1 & 0b00001000;
    AB = BYTE1 & 0b00000100;
    CB = BYTE1 & 0b00000010;
    BB = BYTE1 & 0b00000001;

    RB = BYTE2 & 0b10000000;
    XB = BYTE2 & 0b01000000;
    YB = BYTE2 & 0b00100000;
    ZB = BYTE2 & 0b00010000;
    LB = BYTE2 & 0b00001000;
    
    
// From here on out you can code for whatever you're wanting the PIC to do
// when a button on the controller is pressed. 

// This is where some of the LCD output code was from my testing, but anything can be put here.

/******************************* EXAMPLE 1 *************************************

  if (DU == 0)     // If DU is pressed..
  {}               // ..run this code
  
  else             // Otherwise..
  {}               // ..run this code
  
******************************** EXAMPLE 2 *************************************

  PORTA = BYTE1;    // PORTS A and B display the button states
                    // LEDS would be on, then turn off with button press
  PORTB = BYTE2;

  // Alternately
  
  PORTA = ~BYTE1;   // Would make the LEDs turn on when a button is pressed
    
*******************************************************************************/

     delay_ms(15);
  
  }
}
 
Would I be right in assuming that the reason you're doing this is to use other controllers on the Saturn?
 
While the information in here could be used for that, I really did this mainly just to do it.

This here is technically the reverse of using other controllers on the Saturn. This is more for using the Saturn controllers more easily on other things as the PIC could be connected up to switch ICs, directly to another type of controller board, depending on how it's setup, or any number of things.

Using other controllers on the Saturn is kind of 'the other side of this coin' though, where you still need to know the protocol used so you can 'talk' to the Saturn correctly, but that also involves knowing the other controllers protocol as well so it can be translated into the Saturn protocol.
 
RDC said:
This here is technically the reverse of using other controllers on the Saturn. This is more for using the Saturn controllers more easily on other things as the PIC could be connected up to switch ICs, directly to another type of controller board, depending on how it's setup, or any number of things.

Ah, I'm not going to pretend to understand all this, but I know that Street Fighter 4 players are going to love you.
 
So, what're you gonna do with this information? I really like all of the work you've done, it's quite nifty.

Also, what logic sniffer do you have? I've been wanting to get one to work on a few things and whatnot.

Also this is the sort of thing I love seeing. I may ask you more questions in the future. Feel free to ask me some stuff, too, I'm an EE student and all. I've had to do some data acquisition from systems, though I'm more used to using the o-scopes in my lab, and as it stands I'm sure you know more about that than I. Butyeh.
 
Do people read threads anymore? :p

This was my test setup. MK-80100 controller. PIC16F1516 on the bread board. PicKit3 for powering the PIC and Controller. Saleae Logic for seeing what's going on, then a 16x2 LCD display that's powered from an external 5v PSU. (because I can only watch LEDs blink on a port for so long)

To elaborate some on that Logic Analyzer, it's not capable of doing anything in 'real time', like you can do with a O-scope, so if you're wanting to see where a button press is during a packet of data or whatever, then you need to do a read of the controller or whatever untouched, then again with the button held down and compare the two, but, it also doesn't cost what those that can do real time either. The Saleae Logic can capture 8 channels up to 24MHz (they also have a 16 channel one) which is fast enough for most things. It's really a good hobbyist or beginner LA, and so far I'm pleased with it.

I have no real plans to do anything specific with this information, aside form post it so others can see/understand how it all works, it's just information. I did this after I messed with the PSX controller protocol, for the neGcon, then went to the N64 and then the Saturn. Sometimes I just like to know how something works versus existing data that on the web, which gets old and lost or is in some places incomplete or incorrect.

A few years ago twistedsymphony did something similar to this to use the Saturn controller with a 360, via switch ICs. http://solid-orange.com/hacks/saturn-to ... er-adapter

I mainly did the 6 button Saturn controller as a warm up for doing the 3D controller, which I went a step further with and then Emulated, both Digital and Analog modes. viewtopic.php?f=34&t=11345

The 6 button here I've no plans to Emulate as it can be done with a couple of 74HC153 ICs anyway.
 
RDC said:
Do people read threads anymore? :p
I skimmed it...but missed that part :p

Also I wanted to ask something else that wasn't quite as ...well kinda rude I personally find, as asking SO WHAT ARE YOU GONNA USE THIS INFORMATION FOR?

But that's all pretty neat. Any other plans in the future? I'm looking to messing around with parts of the Dreamcast some time in the future when I'm not swamped with school work (most of my waking hours are at my uni). Sooo, when/if I get around to that it'd be nice to have some sort of collaboration/contact with someone who knows what they're doing when it comes to these things.
 
If I messed with the DC any it would only be on the controller side of things like I've done here, and there seems to be at least some data around on that protocol already.

The GC controllers are next on my 'hit list' as far as reading them goes, no plan to Emulate them either, but after the timing hassle of doing the N64 (they're setup the same way, just more bits of data for the GC) it remains to be seen how far I put up with it before I find something else to get into. I may just switch up to a much faster PIC there so the timings don't have to be so dead on and irritating.
 
Ah, I see. So do you have any plans outside of controllers for the future?

Also, have you posted any of your N64 controller work? I wouldn't mind looking through your data. Sorry if you posted somewhere on here, but I looked through your past posts and didn't see anything (though I did see your work on laying out the N64 mobo, good job thus far).
 
@ ProgMetalMan - Yes I have, and while it's a decent start, it's not what I want to do with the controller. I'm more interested in getting the information into the PIC, then I can do whatever with it then and not be tied to a parallel port on the PC. His pinout is his own numbering also, which isn't how the GC is labeled, so that's info that I personally don't care to have saved since it's incorrect, though I do admire the work put into it as I know it's not just a simple walk in the park thing to get into. I'm mainly taking on the GC controllers for my own amusement and knowledge, and I have a kind of back burner, side project that could possibly benefit from it.


@ Hermaphroditus - I always have more than a few projects planned, as well as juggle a few at a time, but nothing too specific past keeping up with work and all the curve balls life throws my way. Also, the number of people you can get to commit to some huge project is pretty few and far between now also. There were only 2 of us on the CGnome project, which was fine with me and I wouldn't have done it any other way, but there were many a looooong night put into that project that spanned months, on top of everything else that we each had going on.

I haven't posted any of the N64 controller work as there's already more than enough of that info floating around that's still good, aside from one person saying it couldn't be done in C because of the timing, but it can be. It's also far more work, IMHO, to put together a thread like this with decent pics and screenshots, versus all the time it takes to mess around with it and figure it out, so I really only post but a fraction of the things I've done. I don't plan to mess with the N64 controller much more than what I have already done, which was just to read all off the buttons and stick position data from it. I may revisit it at some point, but it's not high on the list.
 
1) Have you tried making the adapter to connect the Genesis joypad to the Saturn console? It's said that the Saturn supports this natively.

The adapter is probably wired like this:

Code:
Saturn    Genesis pad
pin-1     pin-5
pin-2     pin-2
pin-3     pin-1
pin-4     pin-7
pin-5     pin-9
pin-6     pin-6
pin-7     pin-4
pin-8     pin-3
pin-9     pin-9

2) When TH=TR=1, the Saturn joystick seems to output the signature D0=D1=0,D2=1. That probably allows the Saturn to differentiate from the D0=D1=1 that a Genesis joypad would send.

This sequence can detect the following Sega joystick devices:

Code:
             1      2      3      4     < cycle
            H L    H L    H L    H L    < TH level
---------------------------------------
Nothing:    f f    f f    f f    f f
3 Button:   f 3    f 3    f 3    f 3
6 Button:   f 3    f 3    f 0    f f 
Multi-tap:  3 f    3 f    3 f    3 f
Saturn std: c f    c f    c f    c f
Saturn 3D:  f f    f f    f f    f f

As you notice, rhe Saturn 3D controller is probably detected by reading FF as the first byte (that would mean "disconnected"), then lowering TR and checking if TL goes low. The 3D controller uses the Genesis Multi-tap protocol, but the header byte received by the TR/TL protocol from those two devices is this:

FFh: Genesis Multi-tap
02h: 3D controller in Digital mode
16h: 3D controller in Analog mode

I just combined all the information I got from the Net while writing a library to read the genesis joypads/multitap on the MSX computer. The real credits goes to:
- Info on Genesis Joypads: Sergio Guerrero Miralles, SegaRetro.
- Info on the Genesis Multi-tap: Raphael Assenat
- Info on the Saturn Controllers: RDC (yourself)
 
Back
Top