User Tools

Site Tools


source_code

Differences

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

Link to this comparison view

source_code [2019/04/10 12:59] (current)
hutch created
Line 1: Line 1:
 +===== Source Code =====
 +<code C wamControl.h>​
 +#ifndef WAMCONTROL_H_
 +#define WAMCONTROL_H_
  
 +#include "​wamDisplay.h"​
 +#include <​stdint.h>​
 +
 +// Call this before using any wamControl_ functions.
 +void wamControl_init();​
 +
 +// Call this to set how much time is consumed by each tick of the controlling state machine.
 +// This information makes it possible to set the awake and sleep time of moles in ms, not ticks.
 +void wamControl_setMsPerTick(uint16_t msPerTick);
 +
 +// This returns the time consumed by each tick of the controlling state machine.
 +uint16_t wamControl_getMsPerTick();​
 +
 +// Standard tick function.
 +void wamControl_tick();​
 +
 +// Returns a random value that indicates how long the mole should sleep before awaking.
 +wamDisplay_moleTickCount_t wamControl_getRandomMoleAsleepInterval();​
 +
 +// Returns a random value that indicates how long the mole should stay awake before going dormant.
 +wamDisplay_moleTickCount_t wamControl_getRandomMoleAwakeInterval();​
 +
 +// Set the maximum number of active moles.
 +void wamControl_setMaxActiveMoles(uint16_t count);
 +
 +// Get the current allowable count of active moles.
 +uint16_t wamControl_getMaxActiveMoles();​
 +
 +// Set the seed for the random-number generator.
 +void wamControl_setRandomSeed(uint32_t seed);
 +
 +// Set the maximum number of misses until the game is over.
 +void wamControl_setMaxMissCount(uint16_t missCount);
 +
 +// Use this predicate to see if the game is finished.
 +bool wamControl_isGameOver();​
 +
 +#endif /* WAMCONTROL_H_ */
 +</​code>​
 +
 +<code C wamDisplay.h>​
 +#ifndef WAMDISPLAY_H_
 +#define WAMDISPLAY_H_
 +
 +#include <​stdint.h>​
 +#include <​stdbool.h>​
 +
 +// The index used to tell the display which mole is active/​inactive.
 +typedef int16_t wamDisplay_moleIndex_t;​
 +// Mole coordinates represented by this.
 +typedef int16_t wamDisplay_coord_t;​
 +// Mole origins, whack coordinates,​ etc. are represented by this.
 +typedef struct {wamDisplay_coord_t x, y;} wamDisplay_point_t;​
 +// Represents a mole clock interval (asleep or awake).
 +typedef uint32_t wamDisplay_moleTickCount_t;​
 +
 +// Make it possible to select games with different numbers of moles.
 +// The display will determine the actual layout. Moles are always indexed by a single integer.
 +typedef enum {wamDisplay_moleCount_9,​ wamDisplay_moleCount_6,​ wamDisplay_moleCount_4} wamDisplay_moleCount_e;​
 +
 +// Provide support to set games with varying numbers of moles. This function
 +// would be called prior to calling wamDisplay_init();​
 +void wamDisplay_selectMoleCount(wamDisplay_moleCount_e moleCount);
 +
 +// Call this before using any wamDisplay_ functions.
 +void wamDisplay_init();​
 +
 +// Draw the game display with a background and mole holes.
 +void wamDisplay_drawMoleBoard();​
 +
 +// Draw the initial splash (instruction) screen.
 +void wamDisplay_drawSplashScreen();​
 +
 +// Draw the game-over screen.
 +void wamDisplay_drawGameOverScreen();​
 +
 +// Selects a random mole and activates it.
 +// Activating a mole means that the ticksUntilAwake and ticksUntilDormant counts are initialized.
 +// See the comments for wamDisplay_moleInfo_t for details.
 +// Returns true if a mole was successfully activated. False otherwise. You can
 +// use the return value for error checking as this function should always be successful
 +// unless you have a bug somewhere.
 +bool wamDisplay_activateRandomMole();​
 +
 +// This takes the provided coordinates and attempts to whack a mole. If a
 +// mole is successfully whacked, all internal data structures are updated and
 +// the display and score is updated. You can only whack a mole if the mole is awake (visible).
 +// The return value can be used during testing (you could just print which mole is
 +// whacked without having to implement the entire game).
 +wamDisplay_moleIndex_t wamDisplay_whackMole(wamDisplay_point_t* whackOrigin);​
 +
 +// This updates the ticksUntilAwake/​ticksUntilDormant clocks for all of the moles.
 +void wamDisplay_updateAllMoleTickCounts();​
 +
 +// Returns the count of currently active moles.
 +// A mole is active if it is not dormant, if:
 +// ticksUntilAwake or ticksUntilDormant are non-zero (in the moleInfo_t struct).
 +uint16_t wamDisplay_getActiveMoleCount();​
 +
 +// Sets the hit value in the score window.
 +void wamDisplay_setHitScore(uint16_t hits);
 +
 +// Gets the current hit value.
 +uint16_t wamDisplay_getHitScore();​
 +
 +// Sets the miss value in the score window.
 +void wamDisplay_setMissScore(uint16_t misses);
 +
 +// Gets the miss value.
 +// Can be used for testing and other functions.
 +uint16_t wamDisplay_getMissScore();​
 +
 +// Sets the level value on the score board.
 +void wamDisplay_incrementLevel();​
 +
 +// Retrieves the current level value.
 +// Can be used for testing and other functions.
 +uint16_t wamDisplay_getLevel();​
 +
 +// Completely draws the score screen.
 +// This function renders all fields, including the text fields for "​Hits"​ and "​Misses"​.
 +// Usually only called once when you are initializing the game.
 +void wamDisplay_drawScoreScreen();​
 +
 +// Make this function available for testing purposes.
 +void wamDisplay_incrementMissScore();​
 +
 +// Reset the scores and level to restart the game.
 +void wamDisplay_resetAllScoresAndLevel();​
 +
 +// Test function that can be called from main() to demonstrate milestone 1.
 +// Invoking this function should provide the same behavior as shown in the Milestone 1 video.
 +void wamDisplay_runMilestone1_test();​
 +
 +#endif /* WAMDISPLAY_H_ */
 +</​code>​
 +
 +<code C wamDisplay.c>​
 +#include "​supportFiles/​display.h"​
 +#include "​wamDisplay.h"​
 +#include "​wamControl.h"​
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​string.h>​
 +
 +/​********************** typedefs **********************/​
 +// This keeps track of all mole information.
 +typedef struct {
 +        wamDisplay_point_t origin; ​ // This is the origin of the hole for this mole.
 +        // A mole is active if either of the tick counts are non-zero. The mole is dormant otherwise.
 +        // During operation, non-zero tick counts are decremented at a regular rate by the control state machine.
 +        // The mole remains in his hole until ticksUntilAwake decrements to zero and then he pops out.
 +        // The mole remains popped out of his hole until ticksUntilDormant decrements to zero.
 +        // Once ticksUntilDomant goes to zero, the mole hides in his hole and remains dormant until activated again.
 +        wamDisplay_moleTickCount_t ticksUntilAwake; ​ // Mole will wake up (pop out of hole) when this goes from 1 -> 0.
 +        wamDisplay_moleTickCount_t ticksUntilDormant;​ // Mole will go dormant (back in hole) this goes 1 -> 0.
 +} wamDisplay_moleInfo_t;​
 +
 +// This will contain pointers to all of the mole info records.
 +// This will ultimately be treated as an array of pointers.
 +static wamDisplay_moleInfo_t** wamDisplay_moleInfo;​
 +
 +// Allocates the memory for wamDisplay_moleInfo_t records.
 +// Computes the origin for each mole assuming a simple row-column layout:
 +// 9 moles: 3 rows, 3 columns, 6 moles: 2 rows, 3 columns, 4 moles: 2 rows, 2 columns
 +// Also inits the tick counts for awake and dormant.
 +void wamDisplay_computeMoleInfo() {
 +    // Setup all of the moles, creates and inits mole info records.
 +    // Create the container array. It contains pointers to each of the mole-hole info records.
 +    //    wamDisplay_moleInfo =  // Need to uncomment this line and initialize this variable via malloc().
 +}
 +</​code>​
 +
 +<code C wamMain.c>​
 +#include "​wamDisplay.h"​
 +#include "​wamControl.h"​
 +#include "​supportFiles/​utils.h"​
 +#include "​supportFiles/​display.h"​
 +#include "​supportFiles/​intervalTimer.h" ​ // Modify as necessary to point to your intervalTimer.h
 +#include "​supportFiles/​leds.h"​
 +#include "​supportFiles/​interrupts.h"​
 +#include "​supportFiles/​switches.h" ​ // Modify as necessary to point to your switches.h
 +#include "​supportFiles/​buttons.h" ​  // Modify as necessary to point to your buttons.h
 +#include <​stdio.h>​
 +#include <​xparameters.h>​
 +
 +// The formula for computing the load value is based upon the formula from 4.1.1 (calculating timer intervals)
 +// in the Cortex-A9 MPCore Technical Reference Manual 4-2.
 +// Assuming that the prescaler = 0, the formula for computing the load value based upon the desired period is:
 +// load-value = (period * timer-clock) - 1
 +#define TIMER_PERIOD 50.0E-3 ​   // 50 ms.
 +#define TIMER_CLOCK_FREQUENCY (XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2)
 +#define TIMER_LOAD_VALUE ((TIMER_PERIOD * TIMER_CLOCK_FREQUENCY) - 1.0)
 +
 +#define MAX_ACTIVE_MOLES 1  // Start out with this many moles.
 +#define MAX_MISSES 50       // Game is over when there are this many misses.
 +#define FOREVER 1           // Syntactic sugar for while (1) statements.
 +#define MS_PER_TICK (TIMER_PERIOD * 1000)   // Just multiply the timer period by 1000 to get ms.
 +
 +#define SWITCH_VALUE_9 9  // Binary 9 on the switches indicates 9 moles.
 +#define SWITCH_VALUE_6 6  // Binary 6 on the switches indicates 6 moles.
 +#define SWITCH_VALUE_4 4  // Binary 9 on the switches indicates 4 moles.
 +#define SWITCH_MASK 0xf   // Ignore potentially extraneous bits.
 +
 +// Mole count is selected by setting the slide switches. The binary value for the switches
 +// determines the mole count (1001 - nine moles, 0110 - 6 moles, 0100 - 4 moles).
 +// All other switch values should default to 9 moles).
 +void wamMain_selectMoleCountFromSwitches(uint16_t switchValue) {
 +    switch(switchValue & SWITCH_MASK) {
 +    case SWITCH_VALUE_9: ​   // this switch pattern = 9 moles.
 +        wamDisplay_selectMoleCount(wamDisplay_moleCount_9);​
 +        break;
 +    case SWITCH_VALUE_6: ​   // this switch pattern = 6 moles.
 +        wamDisplay_selectMoleCount(wamDisplay_moleCount_6);​
 +        break;
 +    case SWITCH_VALUE_4: ​  // this switch pattern = 4 moles.
 +        wamDisplay_selectMoleCount(wamDisplay_moleCount_4);​
 +        break;
 +    default: ​   // Any other pattern of switches = 9 moles.
 +        wamDisplay_selectMoleCount(wamDisplay_moleCount_9);​
 +        break;
 +    }
 +}
 +
 +// Top-level control loop is implemented with while-loops in main().
 +int main() {
 +    /​************************* System Initialization Code ***********************/​
 +    switches_init(); ​ // Init the slide switches.
 +    buttons_init(); ​  // Init the push buttons.
 +    leds_init(true); ​ // You need to init the LEDs so that LD4 can function as a heartbeat.
 +    // Init all interrupts (but does not enable the interrupts at the devices).
 +    // Prints an error message if an internal failure occurs because the argument = true.
 +    interrupts_initAll(true); ​  // Init the interrupt code.
 +    interrupts_setPrivateTimerLoadValue(TIMER_LOAD_VALUE); ​ // Set the timer period.
 +    interrupts_enableTimerGlobalInts(); ​ // Enable interrupts at the timer.
 +    interrupts_startArmPrivateTimer(); ​  // Start the private ARM timer running.
 +    uint32_t personalInterruptCount = 0; // Used to compare with internal count from interrupt code.
 +    /​******************** Game-Specific Code ********************/​
 +    uint32_t randomSeed; ​   // Used to make the game seem more random.
 +    display_init(); ​        // Init the display (make sure to do it only once).
 +    wamControl_setMaxActiveMoles(MAX_ACTIVE_MOLES);​ // Start out with this many simultaneous active moles.
 +    wamControl_setMaxMissCount(MAX_MISSES); ​        // Allow this many misses before ending game.
 +    wamControl_setMsPerTick(MS_PER_TICK); ​          // Let the controller know how ms per tick..
 +    wamDisplay_drawSplashScreen(); ​ // Draw the game splash screen.
 +    while (FOREVER) {               // Endless loop.
 +        wamMain_selectMoleCountFromSwitches(switches_read()); ​ // Mole count selected via slide switches.
 +        wamDisplay_init(); ​             // Initialize the WAM display.
 +        wamControl_init(); ​             // Initialize the WAM controller.
 +        while (!display_isTouched()) {  // Wait for the user to touch the screen.
 +            randomSeed++; ​              // Increment a random seed while you wait.
 +        }
 +        while (display_isTouched()); ​           // Now wait for the user to remove their finger.
 +        wamControl_setRandomSeed(randomSeed); ​  // Set the random-seed.
 +        wamDisplay_drawMoleBoard(); ​            // Draw the WAM mole board.
 +        interrupts_enableArmInts(); ​            // Enable interrupts at the ARM.
 +        while (!wamControl_isGameOver() && !buttons_read()) {// Game runs until over or interrupted.
 +            if (interrupts_isrFlagGlobal) {     // If an interrupt occurs, time to call tick.
 +                interrupts_isrFlagGlobal = 0;   // Reset the interrupt flag.
 +                personalInterruptCount++; ​      // Count interrupts.
 +                wamControl_tick(); ​             // tick the WAM controller.
 +            }
 +        }
 +        interrupts_disableArmInts(); ​           // Game is over, turn off interrupts.
 +        // Print out the interrupt counts to ensure that you didn't miss any interrupts.
 +        printf("​isr invocation count: %ld\n\r",​ interrupts_isrInvocationCount());​
 +        printf("​internal interrupt count: %ld\n\r",​ personalInterruptCount);​
 +        wamDisplay_drawGameOverScreen(); ​       // Draw the game-over screen.
 +        while (!display_isTouched()); ​          // Wait here until the user touches the screen to try again.
 +        wamDisplay_resetAllScoresAndLevel(); ​   // Reset all game statistics so you can start over.
 +    }
 +}
 +
 +void isr_function() {
 +    // Empty for now.
 +}
 +</​code>​
source_code.txt ยท Last modified: 2019/04/10 12:59 by hutch