Open source Rapid-fire X360 Project
1: The Hardware
2: Methods and game-speed limitations
4: Programming the 12F683
This is a document of the process of developing an open-source code for the
XBOX360 controllers using the Microchip PIC12F683. The intent was to give the public
a decent and working code in order to program their own chips instead of paying
$30+USD on EBay for what I considered substandard code. I believe I have completed
what I set out to do, with the exception that only the code has reached the public with no
background as to what the problems are facing the unwary. I have already witnessed
results of people using the code the wrong way and having poor results. For example,
people are burning chips and wiring everything completely wrong, the complaining that
there is something wrong with the code. Since this project has no official home/base of
support (and I have no intention of ‘supporting’ this project any longer), I am drawing
this document so people will realize the extent of what went into this code and how to
avoid problems in the future if they attempt (and I hope they do) to modify the code to
make it better/more personal.
1: The Hardware: Even if you have seen this info before, do not skip this section. The
current state of the X360 market is now leaning toward the wireless controllers, so the
scope of the project will only deal with those. Now, there are two types of wireless
controllers: The Matrix and the CG (Common Ground). The first generation of wireless
controllers used the Matrix PCB boards. It is called the Matrix because it uses a matrix
for determining how to monitor the button presses. The controller pulses the 4 buttons at
a time and depending on which buttons are pressed, can determine the state of each
button in turn. This allows the controller to use 8 I/O to read 16 buttons. The following
picture shows how this is implemented on the controller (picture provided by RDC at X-S
I am assuming that each group of four buttons gets pulsed at different times.
However, I will show the effects of dealing with this later.
The 2nd generation controller is the CG (common ground), named by the fact that
the controller now simply uses 16 I/O with all the inputs held ‘high’ so that pressing a
button will pull the input to ground. This style of controller is much easier to work with
from a design perspective since a microcontroller can be directly connected to these
inputs and ground them without extra hardware.
To determine which controller you have, the following pictures show the
differences between PCBs, and also a comparison of how to tell without opening the
controller. The following pictures were provided by RDC at X-S forums.
The above pictures show the differences between controllers by viewing them
through the battery pack compartments.
I have heard reports that there are different Matrix boards where the big chip has
the shield on it, and some do not. All pictures I have seen appear to have identical PCB
boards. I can only assume that there were no functional differences and that the
differences in these controllers were due to changing of manufacturing processes and not
the actual board design. In layman terms, they did not change how the controller works.
2: Methods and game-speed limitations: So basically what is desired is to create a
quick reoccurring pulse to be over-laid onto the firing button in order to simulate ‘Rapid-
fire’. The most common ‘fire’ button for most games is the Right Trigger. Additionally,
some games also use the Left Trigger in what is called Dual Mode (where you are
holding a weapon in each hand). From a basic programming standpoint, this means just
creating a simple timed pulse will give you what you want.
One other consideration is the speed of the pulse. It has already been well
established that certain games already have automatic firing of weapons, but by applying
just the right timed pulse will make the weapon more accurate and reduce the recoil. This
is especially prevalent on Halo 3.
There are two methods by which to apply the pulse onto these triggers: Rapid-fire
(just the original name of the modification) where the rapid-fire is activated by pressing a
separately installed button on the bottom of the controller, and Sleeper-fire where the
pulse is active when the original Trigger is pulled (and thus no need for an external
button). The Sleeper method has become more popular due to the idea that no external
buttons have to be installed, and the controller looks as factory stock, or ‘stealth’. This
method requires a way to turn the rapid-fire on and off so that the controller can regain
the original control of the trigger function for games that do not use rapid-fire.
Lastly, there is good reason to have some form of indicator to give the user the
ability to determine when the rapid-fire is on or off. If a single chip will have more than
one firing speed, this is more of a requirement than a bonus feature.
This all leads to the following design requirements:
A single chip that can easily work with both old and new PCB controllers (Matrix
Should work as either Rapid-fire or Sleeper-fire.
Have multiple firing rates for different games w/ ability to switch these rates.
Have LED indicator.
Be able to store the current rate in non-volatile memory.
Control both triggers separately as each fire-rate will be game specific.
3: Discoveries: Before I even got a chance to writing code, I looked at what was
currently was available out on the net for open code. It was not very pretty. About 90% of
what people were peddling was the following:
If (button press)
Wait X time
Wait X time
This is not very inventive. For starters, there is no way to change how fast the output is. It
also does not allow the ability to turn off rapid-fire or regain control of the trigger if
needed. Also, of dual trigger method is desired the lines were generally just copied
meaning that if both buttons were pressed then the firing on both triggers would be active
at half the intended speed. Most designs compensated for this by wiring a single output to
both triggers. But now, there is no longer selectable control of the rapid-fire. The only
thing worse would be wiring to the player LED trick that only works on the Matrix. The
PWM pulse is actually faster than any programmed chip and the fire-rate is completely
uncontrollable and sloppy. It does not even work for any game other than COD.
Let us begin with how the hardware of the triggers work, since this is one of the
hardest parts of the design aspect: The triggers are analog inputs. They are 10k
potentiometers. As you pres the trigger, the wiper of the pot goes from one end to the
other, varying the voltage on the wiper pin linearly. The pots are being provided with a
1.5V regulated bus provided by the Microsoft chip as power, and grounded at the other
end. The wiper of the pot goes directly into the Microsoft chip as an analog signal. What
makes things more interesting is that the Matrix and the CG work completely backwards
from each other. In the ‘released’ state of the triggers, the Matrix has 1.4V on the wiper
where the CG has 0.3V. When the triggers are pressed, the Matrix will now have 0.3V
whereas the CG will have 1.4V.
I am assuming that the reason for using a 1.5V regulated bus to supply the pots
was a design consideration by MS so that degrading battery strength would not change
the performance of the analog signals. I should also state that all 6 analog controls are all
tied to this 1.5V bus (each trigger, and both joysticks X and Y axis pots). This causes a
potential problem. The analog signals feed directly back to the custom made ASIC chip.
It is undoubtedly looking for a 1.5 - 0V signal at its A2D converter input. It would also be
safe to assume that the 1.5V generated by the chip is also used as its voltage reference for
the ADC. It is very likely that applying a 3V digital signal to the wiper of any of the
analog pots will possibly overload the ADC over time and damage the analog input by
applying twice the rated voltage. Only Microsoft knows the tolerance of this input. But
any Electrical Engineer knows not to exceed an analog signal like this.
The first solution to the problem is simple: Use a transistor. A transistor can be
used like a switch that is turned on by voltage. A lot of open designs out there already use
transistors to get by the problems of interfacing to both controllers. I decided the best way
to handle the different interfaces was to do the same thing, but better: Opto-isolators.
Opto-isolators are photo-transistors, transistors turned on by light instead of voltage. This
light is provided by an internal LED. The most common reason is to isolate your control
chip from the output voltages. Not only would using the optos keep the analog inputs
safe, but they also made it possible to have a single program for any kind of controller.
You would simply have different wiring for which controller and which method (rapid
vs. sleeper). Having a single code was very important. It would reduce confusion as to
which code to program for which type of setup was desired. You would only be soldering
once. You could be reprogramming the chip many times as the code was improved and
Another important feature is that using an opto instead of a transistor reduced the
problem of leakage current. This is where a transistor fails to turn off if its input is not
properly grounded. If you were to use a transistor for the above schematic for the CG
Rapid configuration, your transistors Emitter would be tied to the wiper. In order to turn
off the transistor, your voltage on the Base would have to be lower than the emitter
without being too low. If you simply let the Base float, you can get leakage current from
the Collector to the Base that keeps the transistor in the ON state and will not release.
Unfortunately, this idea was not well received. There were many complaints
about having to use any extra hardware, and my concerns fell on deaf ears. There was
also a small downfall to using the optos. They generally require 10mA to run, and would
reduce the lifespan of the batteries. Back to the drawing board. But the good thing was
this: In two of the configurations, it was possible to accomplish the same thing directly
with the PICs output by latching the output as a low signal (making it a ground) and
toggling the output on and off. This could easily be done by changing the pin from an
output to an input (where the pin would then ‘float’). So now the only thing to do is find
an easy solution for the other two configurations.
One thing to go over at this point: Switch-able power supply points. The CG
(again) has an easy 3V supply point that is completely turned off with the controller. This
is shown here:
But the Matrix does not have a 3V switched power supply. Even though the same
point on the Matrix provides 3V when on, it does not completely turn off with the
controller and will keep powering the PIC if used. What the Matrix does have is a 2V
switched power supply:
This has an effect over the next design problem. In order to keep 3V from the
analog input, we look at how the trigger works more closely.
This is the CG trigger when released. The wiper
will show anywhere from 0.1-0.3V. The
mechanical linkage to the pot is not necessarily
calibrated by MS. Apparently they just need to get
the wiper somewhere in the middle so the voltage
swing does not go completely through the entire
range of the potentiometer. So the resistance on
one end can be anywhere from 500 Ohms to 2k
Ohms. I measured 2k Ohms on mine (and
consequently had 0.3V on the wiper). The easiest
way to bring the wiper up to 1.5V while the trigger is still released is to use a resistor to
bring it up. But we also have 3V being supplied by the PICs output. So, if we have 3V
supply and we know that the average resistance on this side of the wiper is roughly 1.5k
Ohms, we can use a 1.5k Ohm resistor to create a new voltage divider that will cut the 3V
output from the PIC to 1.5V. In reality though, there are 5 other pots in parallel and what
I found was that a 2k Ohm resistor worked better for my controller. This provided the
1.5V just right (and is a more common value). If the pots resistance is lower on other
controllers, it will only lower the voltage on the wiper by a few hundred mV and would
still be adequate voltage for switching. Also, this method is not so power hungry. The
current running through the output of the PIC is only 1.5mA which is almost 10 times
less than using the optos.
This method gives us the ability to
implement the Rapid-fire version
(external buttons) on the CG. The
flaw in this design is that if
someone presses the rapid-fire
button at the same time as pressing
the trigger, then the wiper voltage
will climb right up to 3V. Even
though there is no reason to pull
both triggers, it is a possibility.
This leaves us with how to do this with the Matrix Sleeper configuration. Since
the basic pot circuit is the same, we just do the same thing except we now have a 2V
power supply. On the controller I had, trial and error led me to 330 Ohm resistors on the
triggers. This means that my pots have a resistance of 1k Ohms when pulled.
So now we have easy ways of implementing a rapid pulse on all four
configurations. It requires a resistor for only two of them. All four use the tri-state
method for implementing the pulse. Depending on what config, you keep the output
latched as a high or low, and you toggle the I/O to create the pulse. The nice thing with
the sleeper is that the signal is always present on the wiper, but when the trigger is
released, the voltage is set so that it does not change. Only when the trigger is pulled does
the output of the PIC have an effect on the wiper.
The only problem with not using optos is that we lose the ability to have a single
code for all 4 configs. I could have made two codes, but naming them would be a pain
and it was easy to see that this would cause problems. So the best solution was to
sacrifice a pin to determine which config was used and have the controller soldered that
way to keep the single code solution. This way, people would not program their chips and
have the wrong code for their setup.
The next problem found was how to change programmed modes. The stealth
design requirement means we need to find a button that can change the modes but not
affect gameplay. The most popular choice has been the SYNC button. If this button is
only tapped, the controller does not go through its sync process, and the button has no
affect on the game. This design works like a treat with the CG (again). It already has a
pull-up in place so you do not even have to enable the PICs weak pull-ups. But the matrix
is another matter. At first, it seemed the sync button worked the same. But it was quickly
found that other buttons would give false button presses to the PIC. In other words,
pressing the X or Right Shoulder buttons would also have the same affect as pressing the
sync as far as the PIC was concerned. I have also seen some feedback where wiring in
different ways to the Matrix sync button would cause the controller to begin its
synchronization routine if any of those buttons were held down.
At first, to use the sync button for both controllers it was simply a matter of
wiring directly to the sync button and have the PIC inputs not use the internal weak pull-
ups. When the problem was found on the Matrix, I first tried to use a simple 1k Ohm
pull-up resistor. It did not work. So I put a scope on the Matrix sync point (I never did get
any pictures of the scope display, and at his time my Matrix is wired for a different setup.
You will just have to trust me or get someone else to take pictures of an oscilloscope
readout). Basically, the sync pin is held high and the controller pulses the sync low at a
rate of around 10 kHz. If you use a simple multi-meter, you can only see the high voltage.
But the waveform looked more like, well, ‘waves’. The voltage was not stable in the high
state. It sloped back up. When the sync button was pressed, it showed the opposite effect.
The voltage was held low, with 10 kHz high pulses. But these pulses were much
different. They looked like spikes rather than sloped waves. As was shown in the
hardware section, there are basically 4 outputs pulsing all of the buttons, and 4 inputs
reading what affect those pulses have. The downward pulses when the sync was not
pressed were from one output, and the high spiked pulses when the sync was pressed was
from a different output. Placing the scope on the Right Shoulder button showed the same
‘wavy’ signal, and putting the scope on the Left Joystick button when it was pressed
showed the other ‘Spike’ pulses. So literally, there was no way to use the sync without
contamination from the other buttons. But then I stumbled upon something by complete
accident. I had decided to take another look at the ‘wavy’ pulse before completely giving
up on the sync button. By that time, I had already started a new version of code that
changed pinouts of the PIC. Before, I was using the Pin 4 (GPIO3) that is the only ‘input
only’ pin on the chip. It does not have the ability to use the PICs internal weak pull-ups
(and it was not needed at the time since the sync already seems to have a pull-up
anyway). But my code used Pin 3 (GPIO4) and I setup the PICs weak pull-up so not to
install another resistor into the circuit. By using the PICs internal weak pull-ups, the sync
buttons waveform has completely changed. The signal was no longer ‘wavy’; it was now
‘spiked’ to ground instead. When pressing the other X and RS buttons, the waveform was
changed to a more ramped/sloped waveform. By using a proper button debounce routine
in the PIC, I was no longer getting contamination from the sync button. After three hours
of pressing and holding all of the other buttons and even making the controller resync,
there was no cross contamination found.
So in conclusion regarding the Matrix sync button: By using the PICs internal
weak pull-ups and a proper button debounce routine, you can use the sync button.
Another design issue is using the player LED indicators. On the CG, the LEDs are
commonly tied to ground and sourced by the MS ASIC with a 1.9VDC source. The only
consideration is to use a proper current limiting resistor to make sure we do not over-volt
the LED when wiring to the PICs output. The Matrix LEDs are all commonly tied to the
supply voltage, and the MS ASIC provides a PWM signal to ground them to turn them
on. The one problem found with the Matrix LEDs is that by running them through the
PICs output through a resistor, the LED would stay on just a little when the controller
was off. It was able to pull enough leakage current to turn on slightly. This current was
measured around 120mA. That would drain the battery quickly while the controller was
off. By using a 1N4148 (common small signal diode) in series with the resistor, the LED
current was reduced to less than 10mA while the controller was off. Without any
modifications done, the current draw from the batteries normally is about 100mA. The
added current draw using the 1N4148 diode is negligible. Now, in order to make the code
work for both controllers, I used a square wave pulse. It is the same as using a 50% duty-
cycle PWM pulse. Since each type of controller needs the exact opposite end of the pulse
to turn on, this fits both controllers. In order to turn the LED off, simply change the PICs
output into an input (tri-state). In theory, you should not have to use a resistor with this
square-wave pulse. But the idea of this code is to have people evolve it and experiment.
Without having the resistor in place, it is possible to have the code hang-up (if it gets
altered) and it only takes 1 second of putting the full 3V on the LED and it is gone for
good. The resistor does not do any harm.
4: Programming the 12F683: Now that the hardware has been evaluated, lets talk about
code. In order to get complete independent signals for both triggers, I started with using
the TIMER 2 modules hardware interrupt. The chip uses the internal 4MHz oscillator,
giving us 1 MHz instruction cycle. Setting the TIMER 2 module with a 1:4 pre-scaler and
loading a value of 250 into PR2 (what the Timer uses as a compare value) causes a
hardware interrupt at exactly 1ms. During this interrupt is where the code will change
output states depending on what the system flags/program states were set at in the main
code. This way, you do not have simple loops that cut the fire-rate in half in order to
activate both triggers.
The LED output also uses the interrupt to create a 50Hz square-wave signal. One
problem I discovered was the READ-MODIFY-WRITE bug that is inherent with all 8bit
PICs. When using the Pin 4 as a controller identifier I was using it to determine what
state the trigger outputs should be at the start of the program. But when the interrupt was
changing states of the LED, the code would read the voltage on the pin, modify the bit for
the LED pin, and write that back onto the latches. What this means is that during the
short time of the triggers being tri-stated (inputs), writing to the LED pin would cause the
output latches to change state just as the triggers would reach half-way. In order to get by
this, the trigger outputs needed to be refreshed on every interrupt cycle. So the code reads
Pin 4 to determine the output latch state, and sets an internal software FLAG bit
(TRIGOUT). This bit is then used to refresh the output latch on every interrupt cycle that
has the trigger outputs active.
Changing fire-rates is accomplished by using a General Purpose Register
(STATER) to store the current programmed state. This number is an 8 bit word that has a
maximum value of 255. The first state is value 0. By adding 64 to this register, you get
four states that cycle back to 0. If viewed in hex and binary, the values are: 0x00 =
b’00000000’, 0x40 = b’01000000’, 0x80 = b’10000000’, and 0xC0 = b’11000000’. As
can be seen, the last 2 bits toggle in binary by doing this, and makes an easy test to
determine what state you are currently in. In the main code, a simple button polling
routine is used to determine the pressing of the sync button to change states (and thus
change fire-rates). In the BurnMeUp2.asm code, this can also be tested for to have dual
trigger outputs selective to the program state individually.
Last consideration is using the EEPROM for storing the last state used. Since
STATER is the byte used to determine what fire-rate is being used, I simply used the
PICs internal EEPROM to store this information and have it brought back during power-
up. This way, the user does not have to keep pressing the program button to get to which
rate was used last every time the controller is powered back on.
The Code and the differences: My first attempt used opto-isolators and the code was
merrily dismissed. I wiped out any trace of it since people were actually programming
chips and happily wiring the PICs outputs direct to the wiper. They completely ignored
the wiring schematics and were unhappy that the controller rapid fire was ‘on all the
The second attempt using the output resistors was called BurnMeUp.asm. I called
it that since there is a good chance that people will be burning up their controllers if they
had such complete disregard for what they were doing. I was right. People to this very
day are actually programming chips with different revisions of this code without any
knowledge of how to wire it up and are heating up their battery packs and burning out
LEDs. Then they want to wire the trigger direct to different parts of the controller trying
to find another way to do the player LED indicator trick. The over-whelming evidence
that people desire a rapid-fire controller and cannot be bothered with wiring it correctly is
the main reason why I am drawing up this document. I have already evidenced people
using this code and saying it doesn’t work when I know full well the reason has nothing
to do with the code, but the fact that they did not even have a wiring diagram to begin
with (if they even bothered to find it).
BurnMeUp could be wired as either Rapid or Sleeper fire, and had four modes:
Halo 3 speed, COD speed, COD insane speed, and off. The sync button was used to
change modes, and the player 3 LED was sued to see changing of states. The LED would
simply toggle on or off as the controller changed states, but not tell you what state you
were in. Also, Pin 3 was used for determining controller type and Pin 4 was sued for the
sync button. This code does not work with the Matrix controller sync button.
BurnMeUp2 was the successor. At that time I had found a good speed for Halo3,
the player indicator would blink to show you what state you were in, and pins 3 and 4
were swapped in order to use the weak pull-ups in order to use the Matrix Sync button
with no contamination. This was meant to replace the BrunMeUp design altogether.
A new version was made at request of a couple of people who said that actual
gameplay would be a better design. Instead of using the sync button to turn the rapid-fire
on or off, it was better to have the RF turn on/off more quickly and dynamically by using
an external button. This means using the Sleeper design so RF was active on the trigger,
but you could quickly turn RF off while playing in-game for different weapons (Halo
laser was used as an example). To make the design universal, Dual trigger RF should be
individually turned on/off for each trigger. Two external buttons to individually turn RF
on/off quickly. In order to save I/O pins, it was suggested to use one of these buttons to
change fire rates by holding it down for a few seconds. And thus was born the
GameplayRF.asm. Holding down the right external button for 4 seconds will change
program states and the right player 4 LED will blink that many times to tell you what
mode you are in. I even made the chip show you what state was loaded on power-up too
(this can be seen right when the batteries are inserted since the switched power supply
points are not off when the batteries are first inserted). The player 3 LED was sued to
show if the left trigger RF was on/off. In order to get enough pins to do this version, I
needed a new way to find out what controller type the chip was soldered to. In the code
you will find that the trigger output pins are first used as analog inputs to read the voltage
on the triggers. Since each controller has different voltage present on the wiper, I use this
value to set the TRIGOUT Flag bit on power-on. If you hold the triggers down during
power-up, the code will use the wrong output latch state and rapid-fire will be on all the
time. You will need to pop out the battery pack and turn on the controller again in order
to reset the output latch.
This is the final product of what I plan to do with this project. It now has several
different functionalities that can be used if people want to make their own versions of
code. It is setup so that you can just dump new values in the declared variables to change
the fire-rates. To me this is important since it is narrow minded to believe hard-coding
speeds for a single game will make a controller mod useless in less than a year. For
instance, this mod will most likely not work when COD4 comes out, and people will
switch over to playing that game when it is released. There will not be enough people
playing COD3 anymore. This will be true for all games. To get the most out of a rapid-
fire controller, the speeds must be able to be programmed over time. Also, who wants to
have a single controller for every single game that can use rapid-fire?
To conclude, the files for this project can be found here:
The schematics are included in the zip files. I will no longer be doing anything more with
this as I really don’t have time and seem to be just making ‘adjustments’ for people every
week. This was meant to be an open-source project, which means others get involved in
changing it for the better. I ask that if someone wants something changed, they at least try
to find out on their own. If they cannot, then the public posting of this project was started
at http://forum.microchip.com/tm.aspx?m=353574&mpage=11 and there are people there
that should be able to help you customize the code to your liking.