The code for this program can be divided into three distinct section: initialization, user input via PuTTY (or other serial terminal), and gameplay.
Our program first defines both the hardcoded programs and empty arrays to hold user-inputted training regimes. Additionally, arrays are initialized to hold the training results. Following this, the ADC is configured to use the 5V reference voltage, and the ADC clock is set to a prescalar of 64 to maximize accuracy of readings given the time insensitivity of our project. Only the top 8 bits are used, in order to ease storage constraints upon gameplay.
Timer0’s overflow ISR is also initialized to increment various timing variables for both reaction time, timing constraints, and “global” program time. Timer0 is then set to a prescalar of 1, and its overflow interrupt is enable, along with all other interrupts. At this point, the program moves on to its serial interface.
The stdout and stdin of the program are both defined to be the same UART location, in our case the UART pins, which are connected to a UART to USB cable, which spoofs a serial COM port for the computer. The user can then send and receive messages with any properly configured serial terminal.
The program first welcomes the user and then prompts them to select their training regimen. Currently, three different hardcoded programs of variable difficulty are featured, as well as a self-programmed option. All of these programs consist of a series of punches with “release” and “deadline” time defined relative to the previous timing constraint. This methodology prevents the user from inputting an “impossible” combination.
Once the user is finished inputting their combination, which can be up to 100 punches (a challenging round for most amateur boxers), the program prompts to see if the user would like to store their program into EEPROM. Given the limited size of EEPROM, a user can only save one program at a time. Once the program is finalized, the head of the arrays for punch location, release time, and deadline time are all stored to be iterated additionally. Additionally, the number of punches is stored as the loop iterator. As a quick confirmation, the entire training regimen, with timings is printed to the user prior to starting.
The gameplay occurs primarily within a single for loop which iterates through each punch, and its respective parameters. First, the virtual timer used for timing constraints is set to 0, and the program waits until the time has passed the defined release time before continuing to the next section. Each force sensing pad is wired to a distinct analog-digital converter line. . For a given punch, we consider only the ADC channel corresponding to the force pad to be punched- that is, striking any other (non-prompted) pad will not cause any effect. The position of the punch to be thrown by the user is loaded by the program, and used to define both the current ADC channel, via ADMUX, and to light the corresponding LED strip, via a MOSFET gated by a PORTB pin
At this point, the code enters a do-while loop where the selected ADC channel is constantly polled. The ending conditions of the loop are if either a punch is detected or if the deadline time expires. Within the do section, as soon as the ADC passes a predefined value, in our case 25/255 was used because it was found to be large enough that ADC noise never accidentally triggered the device while still low enough that a light jab can still register as a hit. Following this, the peak value of the ADC is determined by constantly saving max(previous max, current reading). We introduced a bit of hysteresis into the system and do not consider the punch to be completed until the ADC value falls below 20/255. This prevents small fluctuations about the threshold from prematurely ending the punch before its true maximum voltage is detected. At this point, the program will print out a line for each punch. For a hit, it will give the user reaction time, global time, and the reading of the ADC, comically labeled “SPI” for Soviet Punching Index. For a miss, the user will be informed of the hit window timeframe, as well as the global time at the conclusion of the miss.
Finally, some statistics are returned to the user in order to improve their future boxing experiences. The program calculates the user’s accuracy for each pad, as well as the average reaction time for each pad. The information is displayed as quantities within an ASCII diagram of the device sensors. Following the report printing, the user is asked if they wish to play again, at which point the game restarts from the beginning.
While the overall software design is not extremely hard to comprehend, the method allows for easy extensibility. First, because all menus are constructed with serial print statements, all it takes is an “if” statement for a new menu. Additionally, given the easy of altering the user interface, additional programs can be easily added for more tailored training. Plus, punch programs are parameterized perfectly to prevent painful programming.
Moving forward, possible improvements include introducing more advanced reporting systems. Possibilities include correlating pads with reaction time and “force”. This would provide a more thorough view of a user’s strong and weak offensive zones. A possible format would be to graph force against reaction time for all of the pads to allow a user to further granulize their boxing prowess. More aggressive software improvements include finding ways to distinguish between various punches’ “signal” given that a hook and a jab have very different contact profiles.