Joypads, teamtaps and other controllers
Posted 26 October 2009 - 10:46 AM
// Then, somewhere when we want interrupt to start, we need to use the set_timer firunction, in order to program an automatic call of rotary() :
set_timer(200<<16 | 360,rotary);
Great post Fadest
(better late than never for me to comment this thread )
The magic values correspond to PIT0 and PIT1 values
The frequency of the interrupt is computed as follows:
Frq = (Clock / (PIT0+1)) / (PIT1+1)
The set_timer function takes thus as first parameter the long word equal to (PIT0<<16)|(PIT1)
The system clock is approximately 26.5 MHz (SCPCD or Zerosquare, could you please recall us the exact value?)
Thus, in your case, you generate an interruption at a frequency of about 26500000/201/361 = 365,209961 Hz ie about every 2 ms
(compare to a VBL which is every 20 ms for 50 Hz display)
Maybe I should add some words about this in the documentation of my library
Posted 26 October 2009 - 08:48 PM
« Soit A un niveau d'absurdité, il existe un post N tel que... » – Azrael et al., 2006
Posted 24 July 2010 - 07:05 PM
Recently I've been messing around with Jagpad input and while I sorted it out easily, I wanted to add support for the teamtap as well. Not wanting to reinvent the wheel, I asked around for some advice on the matter. Zerosquare of CVSD pointed me to two solutions for this.
One was to use heuristics (i.e. make the user press a jagpad button and see if the button press is shadowed on other pads on the same port - if yes, the user most certainly doesn't have one installed), and the other was in fact a method by Matthias Domin, which reads a seemingly unused bit on the jagpad matrix on jagpad #4. Matthias claimed that if this bit (C1 on the jaguar docs) is inactive (at least on Falcon, jagpad bits are all set to 1 when the user doesn't press any button on the pad), then there's a teamtap installed.
That was just what I needed! So I quickly wrote a test program in GFA Basic and sent it to SH3 (I forgot to mention that I don't own a teamtap ). And that didn't work 100%. It turns out that this bit can change if there's no teamtap installed and the user presses the pause button. Fortunately we noticed that only bit C1 changes when you insert the teamtap in the port. So Matthias' claim was partly correct. The check that works 100% is:
- if (bit c1 in jagpad #4)=set and (bit c2 in jagpad #4)=set then the user is using a single jagpad without teamtap and pressing pause
- if (bit c1 in jagpad #4)=unset and (bit c2 in jagpad #4)=set then we have a teamtap! (the trick here is that when a teamtap is installed, then if jagpad #1 pause is set, you don't have any shadowing to the other pads)
- if (bit c1 in jagpad #4)=unset and (bit c2 in jagpad #4)=unset then we have a normal jagpad, pause is not pressed
(note: "unset" means that the bit is in it's natural state and "set" means it's changed. As I mentioned, on the Falcon it's 1 for unset and 0 for set )
(note #2: there's a 4th combination of bits, but I don't think it's possible to achieve this with a normal teamtap, so it's left out)
I hope I didn't screw anything up - after all, I tested at blind (sh3 was my eyes ). If you find any inaccuracies, please mention them to me so I'll fix the text
Addendum: The shitty GFA program I used to test all of the above. It's not anything brainblasting, but at least it works (it's for port #1 btw) and it displays all ports' pad bits in the same screen.
PRINT "teamtap port a"
PRINT "teamtap port b"
PRINT "teamtap port c"
PRINT "teamtap port d"
PRINT "C1=";BTST(x1%,0);", C2=";BTST(x2%,0);", C3=";BTST(x3%,0)
IF BTST(x1%,0)=1 AND BTST(x2%,0)=0
PRINT "you have a teamtap installed!"
PRINT "you DO NOT have a teamtap installed!"
LOOP UNTIL INKEY$<>""
Posted 25 July 2010 - 11:49 AM
There should be a diode connecting pin 6 to the pause button, but someone forgot to include it (or decided it wasn't necessary) and it was never spotted in testing, because how many people hold pause when games start and do their TeamTap/Controller detection?
As you found out, assuming nobody is holding pause, the state of C1 should be that normally it's high, and the only time it is ever low is on socket 3 (player 4) of a TeamTap, which sets it low as an identifier. Seems a terrible waste of a bit to me, but it's not really significant I guess.
Btw, on the subject of the C2/C3 bits, everything Atari says about their use can safely be ignored. They should be used for controller-type identification. In other words, different combinations of C2/C3 indicate different controllers. The normal pad has them both high all the time (except when pause is pressed it seems), the Rotary was meant to have one high and one low, but nobody who made rotaries has ever implemented that (we leave them high like normal pads), and on top of that Tempest 2000 does not appear to support auto-detection of them using C2/C3 anyway. The ONLY advanced controller Atari ever made that actually (we assume) follows the spec is the VR head-mounted tracker, and there are precisely two of them, so it doesn't seem worth supporting them (especially since most of it is still undocumented).
Incidentally, on the subject of controllers: There are precisely three Jaguar games* which support non-standard controllers. One is the aforementioned Missile Command VR, supporting the head-tracker. The next is Tempest 2000, supporting Rotary Controllers, but not following the spec on them. The last is BattleSphere Gold, which supports Analog Joysticks, but only on early models of the Jaguar which still have the ADC chips onboard. Atari wrote a nice spec for how to interface them digitally, but it's not been implemented in BSG, which just reads variable voltages off two pins directly. They presumably don't check for C2/C3 either. I believe STe's and Falcons have the ADC chips for Analog Joysticks too.
*I believe Starcats point-and-click will have support for bus (Atari) mice, when it comes out. Also there is the Balloons light gun demo, but guns read differently again.
On the subject of Rotary Controllers, the Atari spec is awkward and has never been implemented in full. It requires the knob-movement to be encoded on the left and right pins of socket 1 (i.e. player 2 on a TeamTap). No buttons are on socket 1, and a "pass-thru connector" should be used, which will respond to socket 0 codes and have an ordinary controller plugged in. This is ugly as all hell, and thankfully was never made that way. EVERY controller anyone ever made responds simply on socket 0 codes, and just has the left and right buttons replaced with the rotary encoder (usually losing up and down at the same time). The encoders produce a 2-bit grey code, which consists of a pair of square waves, 90' offset from each other. Each "step" of revolution changes an edge on one of the lines, enabling you to tell direction, and naturally the rate of change lets you know speed. In this they are identical to how Atari mice work (although I'm not sure how bus mice appear to the system, there might be a processor on the keyboard to help with them).
The best, and only reliable way to detect a Rotary is to watch for the situation where both left and right are simultaneously depressed. You can add that check to your standard controller-reading routines, and need not have an actual "detection" phase before launching the main menu. As people try to navigate the menu, or launch the game, they will rotate the knob, and you will see both buttons depressed at once (it happens 1/4 of the time), at which point you can adjust for a Rotary input. It helps to update the speed at which you poll the controller, to up the sample rate and avoid the situation where the user twists the knob more than 1 position in between the times you're reading it. Yak does it under interrupt from Jerry's PIT signal, and reads rotaries 8 times as often as normal pads. From what I can see of reading/searching through his source, he never once looks at socket 1 (player 2 on TT) and thus cannot be following the spec. He reads them just as we've been building them, which does beg the question of why Atari wrote the spec in the arse-backwards way they did.
Mouse detection is another anomaly, in that the only mouse adaptors people have hooked up are simple wire-crossing affairs which take no account of the 4 different common wires the Jaguar uses, and thus always output x1, x2, y1, y2, left and right, regardless of which row you're reading. They can be detected that way, or by the same method as Rotary detection, only you can check for up and down both being depressed at the same time as well as left and right, thus doubling your chances of detecting the controller quickly, before the aberrant signals cause unwanted button pushes.
If you don't have the dev docs, I'd be happy to upload them for you, they're an invaluable tool, although not exactly the most complete or intuitive docs to read.
P.s. Sorry for the wall of text, I like to be complete where I can be.
P.p.s. Feel free to copy/pasta this elsewhere if it is useful to people.
Posted 25 July 2010 - 05:46 PM
More like 6 YEARS really, but let's not split hairs here
Yes, the ADC chips do exist on STE/Falcon.
One question though: Does BSG support the same rotary controllers as those you build or are they different? I'd assume that the wiring and mode of operation is totally different.
No worries, the Falcon is my primary target anyway
P.S. Mods, there is another thread on the rotary in this forum. Maybe we should merge both threads into a bigger one that talks about all kinds of inputs on the Jaguar?
Posted 25 July 2010 - 06:15 PM
I've also merged Fadest's topic about rotary controllers, and an old topic by GT Turbo about detecting teamtaps.
« Soit A un niveau d'absurdité, il existe un post N tel que... » – Azrael et al., 2006
Posted 19 December 2011 - 10:21 PM
It's also explained in the Jaguar developer docs, in the section about controllers. According to this, the sequences are :
Clockwise rotation is : none, right, left AND right, left.
Anticlockwise rotation is : none, left, left AND right, right.
Personally, my code is similar to this :
unsigned long dataJoypad;
unsigned long ph0, ph1, ph0_old, ph1_old; // ph0_old and ph1_old must be initialized, and preserved between calls to the routine
dataJoypad = joypads->j1; // we only manage jagpad 1 for this demonstration routine
ph0 = !(dataJoypad & JOYPAD_LEFT);
ph1 = !(dataJoypad & JOYPAD_RIGHT);
if (ph0 ^ ph0_old ^ ph1 ^ ph1_old)
if (ph0 ^ ph1_old)
// do whatever you need to move anticlockwise
// do whatever you need to move clockwise
ph0_old = ph0;
ph1_old = ph1;
(I've not tested it on the Jaguar, it's possible both directions are swapped)
Okay, it took some time to verify this (actually I waited till I have a rotary on my hands!), but there's a small problem with the above code. Unless I'm really reading it wrong of course (some C specifics elude me).
Anyway, I transcribed the above code to GFA Basic on the Falcon for testing some time back and while it worked 100% for one of the two movements (anticlockwise IIRC), on the other one the code was alternating between clockwise and anticlockwise every two ticks (I think - not that it matters too much ). I traced the problem to the way ph0 and ph1 are calculated; i.e. reading the jagpad, masking for specific bits and NOTting the result. What I did was to convert this to give me $ff for one state and $00 for the other state for both ph0 and ph1. After this it worked perfectly .
Reply to this topic
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users