User Tools

Site Tools


buttonhandler_description_and_code

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

buttonhandler_description_and_code [2019/04/10 11:20] (current)
hutch created
Line 1: Line 1:
 +===== Writing the buttonHandler =====
 +
 +The ''​buttonHandler''​ state machine and associated code abstract the "​buttons"​ from the user. The ''​buttonHandler''​ state machine draws the buttons, draws a larger square over the button when a touch is detected, provides a function that can be called to detect when a release has been detected (really, a touch followed by a release) and the necessary ''​enable()''​ and ''​disable()''​ functions. During normal usage, you would call ''​buttonHandler_enable()''​ to start the state machine. Next you would continuously check to see if a button was touched and then released by calling ''​buttonHandler_releaseDetected()''​. If this function returns true, you would invoke ''​buttonHandler_getRegionNumber()''​ to find out what region/​color was touched. You would call ''​buttonHandler_disable()''​ to stop the state machine and allow it to return to its initial state. This process would begin again by calling ''​buttonHandler_enable()''​.
 +
 +**Note: because time-out (when the user takes too long to touch a colored button on the screen) is detected by verifySequence,​ it is possible to leave the buttonHandler hanging in a state (waiting for a touch, for example) if verifySequence detects a time-out. So, you need to design your state machine so that, no matter what state it is in, it will jump back to the proper beginning state anytime the enable/​disable flag becomes false. For example, if verifySequence detects time-out while the buttonHandler state-machine is waiting for the user to touch the display, verifySequence would invoke button_handler_disable(). When this happens, the button_handler state-machine must return to the state that it would normally return to if it had completely detected a touch-noTouch sequence.**
 +
 +I provide you with the ''​buttonHandler.h''​ file and the code for ''​buttonHandler_runTest()''​. Place runTest() function in your ''​buttonHandler.c''​ file so that it can access the necessary functions. You can see how ''​buttonHandler_runTest()''​ operates by watching the video below.
 +
 +**Note: the buttonHandler test code (and ultimately the simonControl code) draws the buttons the first time as the game is started. This simplifies the buttonHander state-machine. So, your buttonHandler does not need to draw the buttons when the game first starts up. You will do that in the simonControl code. Once the buttons are drawn for the first time, the buttonHandler will keep the display properly updated, as shown in the buttonHandler_runTest code.**
 +
 +=== buttonHandler_runTest() Video ===
 +
 +{{youtube>​wTtFDRLLhfc|?​rel=0&​allowfullscreen&​noborder&​560x315}}
 +
 +----
 +
 +<code C buttonHandler.h>​
 +#ifndef BUTTONHANDLER_H_
 +#define BUTTONHANDLER_H_
 +#include <​stdint.h>​
 +// Get the simon region numbers. See the source code for the region numbering scheme.
 +uint8_t buttonHandler_getRegionNumber();​
 +
 +// Turn on the state machine. Part of the interlock.
 +void buttonHandler_enable();​
 +
 +// Turn off the state machine. Part of the interlock.
 +void buttonHandler_disable();​
 +
 +// The only thing this function does is return a boolean flag set by the buttonHandler state machine. To wit:
 +// Once enabled, the buttonHandler state-machine first waits for a touch. Once a touch is detected, the
 +// buttonHandler state-machine computes the region-number for the touched area. Next, the buttonHandler
 +// state-machine waits until the player removes their finger. At this point, the state-machine should
 +// set a bool flag that indicates the the player has removed their finger. Once the buttonHandler() ​
 +// state-machine is disabled, it should clear this flag.
 +// All buttonHandler_releasedDetected() does is return the value of this flag. 
 +// As such, the body of this function should only contain a single line of code.
 +// If this function does more than return a boolean set by the buttonHandler state machine, you are going about
 +// this incorrectly.
 +bool buttonHandler_releaseDetected();​
 +
 +// Initialize the state machine
 +void buttonHandler_init();​
 +
 +// Standard tick function.
 +void buttonHandler_tick();​
 +
 +// This tests the functionality of the buttonHandler state machine.
 +// buttonHandler_runTest(int16_t touchCount) runs the test until
 +// the user has touched the screen touchCount times. It indicates
 +// that a button was pushed by drawing a large square while
 +// the button is pressed and then erasing the large square and
 +// redrawing the button when the user releases their touch.
 +void buttonHandler_runTest(int16_t touchCount);​
 +
 +#endif /* BUTTONHANDLER_H_ */
 +
 +</​code>​
 +
 +<code C buttonHandler_runTest.c>​
 +#define RUN_TEST_TERMINATION_MESSAGE1 "​buttonHandler_runTest()" ​ // Info message.
 +#define RUN_TEST_TERMINATION_MESSAGE2 "​terminated." ​             // Info message.
 +#define RUN_TEST_TEXT_SIZE 2            // Make text easy to see.
 +#define RUN_TEST_TICK_PERIOD_IN_MS 100  // Assume a 100 ms tick period.
 +#define TEXT_MESSAGE_ORIGIN_X 0                  // Text is written starting at the right, and
 +#define TEXT_MESSAGE_ORIGIN_Y (DISPLAY_HEIGHT/​2) // middle.
 +
 +// buttonHandler_runTest(int16_t touchCount) runs the test until
 +// the user has touched the screen touchCount times. It indicates
 +// that a button was pushed by drawing a large square while
 +// the button is pressed and then erasing the large square and
 +// redrawing the button when the user releases their touch.
 +
 +void buttonHandler_runTest(int16_t touchCountArg) {
 +    int16_t touchCount = 0;                 // Keep track of the number of touches.
 +    display_init(); ​                        // Always have to init the display.
 +    display_fillScreen(DISPLAY_BLACK); ​     // Clear the display.
 +    // Draw all the buttons for the first time so the buttonHandler doesn'​t need to do this in an init state.
 +    // Ultimately, simonControl will do this when the game first starts up.
 +    simonDisplay_drawAllButtons(); ​         ​
 +    buttonHandler_init(); ​                  // Initialize the button handler state machine
 +    buttonHandler_enable();​
 +    while (touchCount < touchCountArg) {    // Loop here while touchCount is less than the touchCountArg
 +        buttonHandler_tick(); ​              // Advance the state machine.
 +        utils_msDelay(RUN_TEST_TICK_PERIOD_IN_MS);​
 +        if (buttonHandler_releaseDetected()) {  // If a release is detected, then the screen was touched.
 +            touchCount++; ​                      // Keep track of the number of touches.
 +            // Get the region number that was touched.
 +            printf("​button released: %d\n\r",​ buttonHandler_getRegionNumber());​
 +            // Interlocked behavior: handshake with the button handler (now disabled).
 +            buttonHandler_disable();​
 +            utils_msDelay(RUN_TEST_TICK_PERIOD_IN_MS);​
 +            buttonHandler_tick(); ​              // Advance the state machine.
 +            buttonHandler_enable(); ​            // Interlocked behavior: enable the buttonHandler.
 +            utils_msDelay(RUN_TEST_TICK_PERIOD_IN_MS);​
 +            buttonHandler_tick(); ​              // Advance the state machine.
 +        }
 +    }
 +    display_fillScreen(DISPLAY_BLACK); ​       // clear the screen.
 +    display_setTextSize(RUN_TEST_TEXT_SIZE); ​ // Set the text size.
 +    display_setCursor(TEXT_MESSAGE_ORIGIN_X,​ TEXT_MESSAGE_ORIGIN_Y);​ // Move the cursor to a rough center point.
 +    display_println(RUN_TEST_TERMINATION_MESSAGE1);​ // Print the termination message on two lines.
 +    display_println(RUN_TEST_TERMINATION_MESSAGE2);​
 +}
 +</​code>​
  
buttonhandler_description_and_code.txt ยท Last modified: 2019/04/10 11:20 by hutch