//********************************************************************************************* // verifySequence_runTest() // Tests the verifySequence state machine. // It prints instructions to the touch-screen. The user responds by tapping the // correct colors to match the sequence. // Users can test the error conditions by waiting too long to tap a color or // by tapping an incorrect color. //********************************************************************************************* void verifySequence_runTest() { display_init(); // Always must do this. buttons_init(); // Need to use the push-button package so user can quit. int16_t sequenceLength = ONE; // Start out with a sequence length of 1. verifySequence_printInstructions(sequenceLength, false); // Tell the user what to do. utils_msDelay(MESSAGE_WAIT_MS); // Give them a few seconds to read the instructions. simonDisplay_drawAllButtons() // Now, draw the buttons. // Set the test sequence and it's length. globals_setSequence(verifySequence_testSequence, MAX_TEST_SEQUENCE_LENGTH); globals_setSequenceIterationLength(sequenceLength); // Enable the verifySequence state machine. verifySequence_enable(); // Everything is interlocked, so first enable the machine. while (!(buttons_read() & BTN0))// Need to hold button until it quits as you might be stuck in a delay. { // verifySequence uses the buttonHandler state machine so you need to "tick" both of them. verifySequence_tick(); // Advance the verifySequence state machine. simonbuttonHandler_tick(); // Advance the buttonHandler state machine. utils_msDelay(ONE_MS); // Wait 1 ms. // If the verifySequence state machine has finished, check the result, otherwise just keep ticking both machines. if (verifySequence_isComplete()) { if (verifySequence_isTimeOutError()) { // Was the user too slow? verifySequence_printInfoMessage(user_time_out_e); // Yes, tell the user that they were too slow. } else if (verifySequence_isUserInputError()) { // Did the user tap the wrong color? verifySequence_printInfoMessage(user_wrong_sequence_e); // Yes, tell them so. } else { verifySequence_printInfoMessage(user_correct_sequence_e); // User was correct if you get here. } utils_msDelay(MESSAGE_WAIT_MS); // Allow the user to read the message. sequenceLength = incrementSequenceLength(sequenceLength); // Increment the sequence. globals_setSequenceIterationLength(sequenceLength); // Set the length for the verifySequence state machine. verifySequence_printInstructions(sequenceLength, V_ENABLED); // Print the instructions. utils_msDelay(MESSAGE_WAIT_MS); // Let the user read the instructions. verifySequence_drawButtons(); // Draw the buttons. verifySequence_disable(); // Interlock: first step of handshake. verifySequence_tick(); // Advance the verifySequence machine. utils_msDelay(ONE_MS); // Wait for 1 ms. verifySequence_enable(); // Interlock: second step of handshake. utils_msDelay(ONE_MS); // Wait 1 ms. } } verifySequence_printInfoMessage(user_quit_e); // Quitting, print out an informational message. }
// I used a busy-wait delay (utils_msDelay) that uses a for-loop and just blocks until the time has passed. // When you implement the game, you CANNOT use this function as we discussed in class. Implement the delay // using the non-blocking state-machine approach discussed in class. void simonDisplay_runTest(uint16_t touchCount) { display_init(); // Always initialize the display. char str[MAX_STR]; // Enough for some simple printing. uint8_t regionNumber; uint16_t touches = 0; // Write an informational message and wait for the user to touch the LCD. display_fillScreen(DISPLAY_BLACK); // clear the screen. display_setCursor(0, display_height()/2); // display_setTextSize(TEXT_SIZE); display_setTextColor(DISPLAY_RED, DISPLAY_BLACK); sprintf(str, "Touch and release to start the Simon demo."); display_println(str); display_println(); sprintf(str, "Demo will terminate after %d touches.", touchCount); display_println(str); while (!display_isTouched()); // Wait here until the screen is touched. while (display_isTouched()); // Now wait until the touch is released. display_fillScreen(DISPLAY_BLACK); // Clear the screen. simonDisplay_drawAllButtons(); // Draw all of the buttons. bool touched = false; // Keep track of when the pad is touched. int16_t x, y; // Use these to keep track of coordinates. uint8_t z; // This is the relative touch pressure. while (touches < touchCount) { // Run the loop according to the number of touches passed in. if (!display_isTouched() && touched) { // user has stopped touching the pad. simonDisplay_drawSquare(regionNumber, true); // Erase the square. simonDisplay_drawButton(regionNumber); // DISPLAY_REDraw the button. touched = false; // Released the touch, set touched to false. } else if (display_isTouched() && !touched) { // User started touching the pad. touched = true; // Just touched the pad, set touched = true. touches++; // Keep track of the number of touches. display_clearOldTouchData(); // Get rid of data from previous touches. // Must wait this many milliseconds for the chip to do analog processing. utils_msDelay(TOUCH_PANEL_ANALOG_PROCESSING_DELAY_IN_MS); display_getTouchedPoint(&x, &y, &z); // After the wait, get the touched point. regionNumber = simonDisplay_computeRegionNumber(x, y);// Compute the region number. simonDisplay_drawSquare(regionNumber, false); // Draw the square (erase = false). } } // Done with the demo, write an informational message to the user. display_fillScreen(DISPLAY_BLACK); // clear the screen. display_setCursor(0, display_height()/2); // Place the cursor in the middle of the screen. display_setTextSize(2); // Make it readable. display_setTextColor(DISPLAY_RED, DISPLAY_BLACK); // red is foreground color, black is background color. sprintf(str, "Simon demo terminated"); // Format a string using sprintf. display_println(str); // Print it to the LCD. sprintf(str, "after %d touches.", touchCount); // Format the rest of the string. display_println(str); // Print it to the LCD. }
// Just clears the screen and draws the four buttons used in Simon. void verifySequence_drawButtons() { display_fillScreen(DISPLAY_BLACK); simonDisplay_drawAllButtons(); // Draw the four buttons. }
void simonControl_tick() { SC_debugStatePrint(); /// //ACTIONS*********************************************************************** switch(SC_State) { case SC_init_st: //do nothing break; case SC_instructions_st: display_setTextColor(DISPLAY_WHITE); display_setCursor(SC_INSTRUCTION_CURSORX,SC_INSTRUCTION_CURSORY); display_setTextSize(SC_INSTRUCTION_TEXTSIZE); display_println(SC_INSTRUCTIONS); break; case SC_wait_first_touch_st: // do nothing break; case SC_get_sequence_st: SC_currentScore = 0; //reset SC_setSequence(); break; case SC_flash_sequence_st: //do nothing break; case SC_verify_sequence_st: //do nothing break; case SC_error_st: errorTimer++; if (verifySequence_isTimeOutError()) // user didn't press { display_setTextSize(SC_TEXTSIZE); display_println(ERROR_MESSAGE_TIMEOUT); } else if (verifySequence_isUserInputError()) //pressed wrong input { display_setTextSize(SC_TEXTSIZE); display_println(ERROR_MESSAGE_INPUT); } verifySequence_disable(); //set this here so we can read these flags. disable resets the error flags break; case SC_print_score_st: sprintf(maxScoreString, SC_HIGHSCORE_MESSAGE, SC_maxScore); display_setTextSize(SC_TEXTSIZE); //decrease text size display_println(maxScoreString); //reset scores, index, and sequence SC_currentIndex = 1; //reset to 1. since this is sequence length, when we setSequence, don't put to zero SC_maxScore = 0; //reset errorTimer = 0; //reset timer lvlMessageTimer = 0; break; case SC_level_complete_st: lvlMessageTimer++; if(printFlag) //set a flag so it doesn't keep being printed { display_println(SC_LVL_MESSAGE); printFlag = false; //switch flag } break; default: printf(SC_ERROR_MESSAGE); //invalid state break; } //TRANSITIONS*********************************************************************** switch(SC_State) { case SC_init_st: SC_State = SC_instructions_st; //just go to instructions break; case SC_instructions_st: SC_State = SC_wait_first_touch_st; //go wait after drawing. break; case SC_wait_first_touch_st: if (display_isTouched()) //if touched, move ahead { SC_State = SC_get_sequence_st; display_fillScreen(DISPLAY_BLACK); //clear screen of instructions } break; case SC_get_sequence_st: SC_State = SC_flash_sequence_st; flashSequence_enable(); break; case SC_flash_sequence_st: if (flashSequence_completed()) { SC_State = SC_verify_sequence_st; //go to verify flashSequence_disable(); //disable flash machine simonDisplay_drawAllButtons(); //draw the buttons upon exit verifySequence_enable(); } break; case SC_verify_sequence_st: if (verifySequence_isComplete()) //done verifying { //if there a time out error or wrong input error if (verifySequence_isTimeOutError() || verifySequence_isUserInputError()) //no errors { SC_State = SC_error_st; display_fillScreen(DISPLAY_BLACK); //clear buttons off screen } //level complete else if (globals_getSequenceIterationLength() == SC_sequence_length) { SC_sequence_length++; SC_State = SC_level_complete_st; verifySequence_disable(); display_fillScreen(DISPLAY_BLACK); //clear buttons off screen SC_currentIndex = 1; //reset SC_maxScore = SC_currentScore; } else { SC_State = SC_flash_sequence_st; flashSequence_enable(); SC_currentIndex++; //how many to flash? globals_setSequenceIterationLength(SC_currentIndex); //udate how many to falsh verifySequence_disable(); display_fillScreen(DISPLAY_BLACK); //clear buttons off screen SC_currentScore++; if (SC_currentScore > SC_maxScore) //before first level is complete, maxScore doesn't get set { SC_maxScore = SC_currentScore; //this mostly before first level is complete } } } break; case SC_error_st: if (errorTimer >= SC_ERROR_EXPIRE) { SC_State = SC_print_score_st; //print highest score display_fillScreen(DISPLAY_BLACK); } break; case SC_print_score_st: SC_State = SC_instructions_st; SC_maxScore = 0; //reset the maxScore! sequenceSeed++; //change the seed break; case SC_level_complete_st: if (lvlMessageTimer > SC_LVL_MESSAGE_EXPIRE) //timed out { SC_State = SC_print_score_st; } else if (display_isTouched()) { SC_State = SC_instructions_st; display_fillScreen(DISPLAY_BLACK); // clear screen sequenceSeed++; //change the seed printFlag = true; //rest print flag } break; default: printf(SC_ERROR_MESSAGE); break; } }