Tmode is a function where LEDs in a fightstick are turned off. There are many ways to implement this but we have decided on enabling/disabling by holding buttons for a certain time. To understand this we look at how the Kaimana works:
* The kaimana is "stuck" in an eternal loop while it listens for a button to be pressed
* If a button is pressed it turns on the led and keeps it on if held
The two main problems are the following:
- How does the Kaimana know about time? It does not have timekeeping installed
- How do we switch between tournament mode on/off?
How does the Kaimana know about time?
There should be a way to have the kaimana understand that buttons have been pressed down for a certain amount of time. This is possible by creating a new global variable that keeps track of the number of times the Kaimana runs its loop and from that we can derive roughly how much time passes.
int holdTimeout = 0;
We use a small trick with the variable, we update it only when the buttons we want are pressed. Then we compare the current value to a number we assign and if they match we trigger our new state. In the example below I am matching this to the Start button and additionally trigger an animation to visually indicate when Tmode has been enabled.
if(!digitalRead(PIN_START)) { //Button hold to start tourneymode holdTimeout += 1; if(holdTimeout == 2000) { tournamentMode = true; tourneyModeActivate(); } // switch is active if(iLED[LED_START] == true) { //maintain color while switch is active iLED[LED_START] = true; } else { // select new color when switch is first activated holdTimeout = 0; setLEDRandomColor(LED_START); iLED[LED_START] = true; } } else { // switch is inactive kaimana.setLED(LED_START, BLACK); iLED[LED_START] = false; }
To disable Tmode, the same approach is used but we change the state variable to its opposite value.
How do we switch between on/off? How do we track the state?
We already saw in the previous example how we enable tournament mode after the button has been held. This works by using another global variable that keeps track of the state of Tmode:
tournamentMode = true;
But this alone does not tell the Kaimana anything, we need to indicate that when the above is true LEDS will not light up. The approach we use is to wrap the main functionality in the example.ino with an IF that checks if the variable is false
while( true) { // active -- poll switches and update leds if (tournamentMode != true) { if( pollSwitches() != 0 ) { // some switches were active so reset idle timeout to now + some seconds ulTimeout = millis() + ( (unsigned long)IDLE_TIMEOUT_SECONDS * 1000 ); } else { // no switches active so test for start of idle timeout if( millis() > ulTimeout ) { animation_idle(); } } }
This will call the pollswitches() function where all of the button detecting/illumination logic appears. However, once we flip our state to true an issue will arise, we cannot detecting anything or switch back! Again this is because of the way the code base is built. We then created a secondary detection function by copying the original pollswitches() and remove all the LED logic from it, thus leaving us with the button detection logic and our holding logic. The last step is to switch the state value to false to let the kaimana know it can go back to its original configuration:
if(!digitalRead(PIN_START)) { // switch is active //Button hold to stop tourneymode holdTimeout += 1; if(holdTimeout == 2000) { tournamentMode = false; tourneyModeDeactivate(); } if(iLED[LED_START] == true) { //maintain color while switch is active iLED[LED_START] = true; } else { // select new color when switch is first activated holdTimeout = 0; iLED[LED_START] = true; } } else { // switch is inactive iLED[LED_START] = false; }
You can find the full implementation in my GitHub page along with the libraries required to make it work. Please note this is for an 8-button stick,