This is a demonstration program which draws a keypad on the LCD and uses the touch screen to allow an operator to key-in an access code. Two possible codes are allowed to grant to different levels of access. Additionally the push button is used to allow an operator to send Moorse Code pulses in to the device which is checked against two characters to determine if there was a match, and if so, access is granted.

Dependencies:   LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI mbed-os BSP_DISCO_F429ZI

Also draws a mushroom on the screen and animates it.

Committer:
Damotclese
Date:
Mon Jun 03 21:56:36 2019 +0000
Revision:
3:0e554d8d5a19
Parent:
2:444eeedb41f0
Child:
4:5c70a30d6757
When the keypad keys are touched, they flash YELLOW for a quarter of a second now;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Damotclese 1:316582aec4fb 1
Damotclese 1:316582aec4fb 2 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 3 // SecurityUnlockDemo-Animation.cpp
Damotclese 1:316582aec4fb 4 //
Damotclese 1:316582aec4fb 5 // Fredric L. Rice, June 2019
Damotclese 1:316582aec4fb 6 //
Damotclese 2:444eeedb41f0 7 // This module draws a mushroom on the display and then animates it as
Damotclese 2:444eeedb41f0 8 // the mushroom moves around "randomly." Every 10 moves or so it will
Damotclese 2:444eeedb41f0 9 // "teleport" to a "random" place on the screen.
Damotclese 2:444eeedb41f0 10 //
Damotclese 2:444eeedb41f0 11 // The random number generator provided by mbed is not very good
Damotclese 2:444eeedb41f0 12 // so we attempt to use the analog inputs on PF_3, PF_4, PF_5 to help
Damotclese 2:444eeedb41f0 13 // drive some randomness.
Damotclese 2:444eeedb41f0 14 //
Damotclese 3:0e554d8d5a19 15 // Conceivably more than one sprite could be animated merely by
Damotclese 3:0e554d8d5a19 16 // making some of the data elements arrays -- and of course using C++
Damotclese 3:0e554d8d5a19 17 // to instantiate objects and then animating them is the correct way
Damotclese 3:0e554d8d5a19 18 // to do such things. This is a concept demonstration projjct, so we
Damotclese 3:0e554d8d5a19 19 // do not expect to make a proper class and allow any number of them
Damotclese 3:0e554d8d5a19 20 // to be instantiated and get automated.
Damotclese 3:0e554d8d5a19 21 //
Damotclese 3:0e554d8d5a19 22 // That would be neat but that's something for another project.
Damotclese 3:0e554d8d5a19 23 //
Damotclese 1:316582aec4fb 24 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 25
Damotclese 1:316582aec4fb 26 #include "mbed.h" // The mbed operating system
Damotclese 1:316582aec4fb 27 #include "LCD_DISCO_F429ZI.h" // For controlling the LCD
Damotclese 1:316582aec4fb 28 #include "TS_DISCO_F429ZI.h" // For controlling the touch screen
Damotclese 1:316582aec4fb 29 #include "SecurityUnlockDemo-Main.h" // For the main module's prototypes
Damotclese 1:316582aec4fb 30 #include "SecurityUnlockDemo-Animation.h" // Always include our own header
Damotclese 1:316582aec4fb 31
Damotclese 1:316582aec4fb 32 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 33 // Describe data which is defined externally that we may access
Damotclese 1:316582aec4fb 34 //
Damotclese 1:316582aec4fb 35 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 36
Damotclese 1:316582aec4fb 37 // We may be accessing the LCD
Damotclese 1:316582aec4fb 38 extern LCD_DISCO_F429ZI st_lcd;
Damotclese 1:316582aec4fb 39
Damotclese 1:316582aec4fb 40 // We may be accessing the touch screen
Damotclese 1:316582aec4fb 41 extern TS_DISCO_F429ZI st_touchScreen;
Damotclese 1:316582aec4fb 42
Damotclese 1:316582aec4fb 43 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 44 // Define local data storage
Damotclese 1:316582aec4fb 45 //
Damotclese 1:316582aec4fb 46 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 47
Damotclese 1:316582aec4fb 48 // We define a "sprite" like entity consisting of a bit map showing
Damotclese 1:316582aec4fb 49 // the colors of pixes that will display a mushroom which we will
Damotclese 1:316582aec4fb 50 // move around the screen. The sprite consists of 22 pixes across
Damotclese 1:316582aec4fb 51 // and 17 pixels down so it's a small graphic. The letters describe
Damotclese 1:316582aec4fb 52 // the color of each pixel.
Damotclese 1:316582aec4fb 53 static char * pau8_mushroomMap[SPRITE_HEIGHT_IN_PIXELS] =
Damotclese 1:316582aec4fb 54 { // 1234567890123456789012
Damotclese 1:316582aec4fb 55 "wwwwwwwwwbbbbbbwwwwwww", // 1
Damotclese 1:316582aec4fb 56 "wwwwwwwbbbwggwbbbwwwww", // 2
Damotclese 1:316582aec4fb 57 "wwwwwwbbwwggwwwbbwwwww", // 3
Damotclese 1:316582aec4fb 58 "wwwwwbbgwwggggwwbbwwww", // 4
Damotclese 1:316582aec4fb 59 "wwwwwbwgggggggggggbwww", // 5
Damotclese 1:316582aec4fb 60 "wwwwbbwwggwwwwggwwbbww", // 6
Damotclese 1:316582aec4fb 61 "wwwwbwwwgwwwwwwgwwwbww", // 7
Damotclese 1:316582aec4fb 62 "wwwwbwwwgwwwwwwgwwwbww", // 8
Damotclese 1:316582aec4fb 63 "wwwwbwwggwwwwwwwggwwbw", // 9
Damotclese 1:316582aec4fb 64 "wwwwbwwggwwwwwwwggwwbw", // 10
Damotclese 1:316582aec4fb 65 "wwwwbgggggwwwwwgggggbw", // 11
Damotclese 1:316582aec4fb 66 "wwwwbggbbbbbbbbbbbggbw", // 12
Damotclese 1:316582aec4fb 67 "wwwwbbbbwwbwwbwwbbbbbw", // 13
Damotclese 1:316582aec4fb 68 "wwwwwwbwwwbwwbwwwwbwww", // 14
Damotclese 1:316582aec4fb 69 "wwwwwwbwwwwwwwwwwwbwww", // 15
Damotclese 1:316582aec4fb 70 "wwwwwwbbwwwwwwwwwbbwww", // 16
Damotclese 1:316582aec4fb 71 "wwwwwwwbbbbbbbbbbbwwww"
Damotclese 1:316582aec4fb 72 } ;
Damotclese 1:316582aec4fb 73
Damotclese 1:316582aec4fb 74 // There are 8 different directions that this animation supports,
Damotclese 1:316582aec4fb 75 // the coordinate offsets to add/subtract from the current pixel
Damotclese 1:316582aec4fb 76 // position depending upon the direction is mapped here.
Damotclese 1:316582aec4fb 77 //
Damotclese 1:316582aec4fb 78 // Directions:
Damotclese 1:316582aec4fb 79 // 1 2 3 Left up, Up, Right Up
Damotclese 1:316582aec4fb 80 // 4 6 Left, N/A, Right
Damotclese 1:316582aec4fb 81 // 7 8 9 Right Down, Down, Right Down
Damotclese 1:316582aec4fb 82 static int8_t i8_movementMatrix[3][6] =
Damotclese 1:316582aec4fb 83 {
Damotclese 1:316582aec4fb 84 -1, -1, -1, 0, -1, 1,
Damotclese 1:316582aec4fb 85 -1, 0, 0, 0, 1, 0,
Damotclese 1:316582aec4fb 86 -1, 1, 0, 1, 1, 1
Damotclese 1:316582aec4fb 87 } ;
Damotclese 1:316582aec4fb 88
Damotclese 1:316582aec4fb 89 // We maintain local data indicating where the sprite was last drawn
Damotclese 1:316582aec4fb 90 static uint16_t u16_spriteCurrentX;
Damotclese 1:316582aec4fb 91 static uint16_t u16_spriteCurrentY;
Damotclese 1:316582aec4fb 92 static uint8_t u8_spriteCurrentDirection;
Damotclese 1:316582aec4fb 93
Damotclese 1:316582aec4fb 94 // When we are first asked to start animation, we launch
Damotclese 1:316582aec4fb 95 // a thread to continue the animation forever
Damotclese 1:316582aec4fb 96 static Thread st_animationThread;
Damotclese 1:316582aec4fb 97
Damotclese 1:316582aec4fb 98 // To know whether animation is running, we maintain this boolean
Damotclese 1:316582aec4fb 99 static bool b_animationThreadRunning;
Damotclese 1:316582aec4fb 100
Damotclese 1:316582aec4fb 101 // After every 10 movements along a given direction, rather than
Damotclese 1:316582aec4fb 102 // pick a direction and then move toward it we will "teleport"
Damotclese 1:316582aec4fb 103 // the sprite to a "random" location on the screen and maintain
Damotclese 1:316582aec4fb 104 // the direction -- unless we're up against a boundary, then a
Damotclese 1:316582aec4fb 105 // new direction will be selected
Damotclese 1:316582aec4fb 106 static uint8_t u8_teleportCounter;
Damotclese 1:316582aec4fb 107
Damotclese 1:316582aec4fb 108 // When we teleport, we display a message indicating that/
Damotclese 1:316582aec4fb 109 // After about 1 second we want to remove that message from
Damotclese 1:316582aec4fb 110 // the screen so we maintain this count down timer
Damotclese 1:316582aec4fb 111 static uint16_t u16_teleportMessageRemovalCountDown;
Damotclese 2:444eeedb41f0 112
Damotclese 2:444eeedb41f0 113 // In an effort to assist the random number generator we will read
Damotclese 2:444eeedb41f0 114 // vaues from some of the analog inputs which should be near zero
Damotclese 2:444eeedb41f0 115 // but perhaps not entirely
Damotclese 2:444eeedb41f0 116 static AnalogIn st_analog1(PF_3);
Damotclese 2:444eeedb41f0 117 static AnalogIn st_analog2(PF_4);
Damotclese 2:444eeedb41f0 118 static AnalogIn st_analog3(PF_5);
Damotclese 1:316582aec4fb 119
Damotclese 1:316582aec4fb 120 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 121 // AnimationDrawSpriteAtThisLocation()
Damotclese 1:316582aec4fb 122 //
Damotclese 2:444eeedb41f0 123 // This function will draw or erase the sprite at the X and Y
Damotclese 2:444eeedb41f0 124 // coordinate position passed to it, or it will erase the sprite
Damotclese 2:444eeedb41f0 125 // depending upon the argument passed to it.
Damotclese 2:444eeedb41f0 126 //
Damotclese 2:444eeedb41f0 127 // The colors that are supported are described in the sprite's
Damotclese 2:444eeedb41f0 128 // bit mapping.
Damotclese 1:316582aec4fb 129 //
Damotclese 1:316582aec4fb 130 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 131 static void AnimationDrawOrEraseSpriteAtThisLocation(uint16_t u16_thisX, uint16_t u16_thisY, bool b_drawSprite)
Damotclese 1:316582aec4fb 132 {
Damotclese 1:316582aec4fb 133 uint8_t u8_lineCount = 0;
Damotclese 1:316582aec4fb 134 uint16_t u16_currentX = u16_thisX;
Damotclese 1:316582aec4fb 135 uint16_t u16_currentY = u16_thisY;
Damotclese 1:316582aec4fb 136 uint8_t u8_currentPixel = 0;
Damotclese 1:316582aec4fb 137 uint32_t u32thisColor = LCD_COLOR_BLUE;
Damotclese 1:316582aec4fb 138
Damotclese 1:316582aec4fb 139 // Record where we are placing the sprite this time
Damotclese 1:316582aec4fb 140 u16_spriteCurrentX = u16_thisX;
Damotclese 1:316582aec4fb 141 u16_spriteCurrentY = u16_thisY;
Damotclese 1:316582aec4fb 142
Damotclese 1:316582aec4fb 143 // Place the sprite on the screen pixel by pixel
Damotclese 1:316582aec4fb 144 for (u8_lineCount = 0; u8_lineCount < SPRITE_HEIGHT_IN_PIXELS; u8_lineCount++)
Damotclese 1:316582aec4fb 145 {
Damotclese 1:316582aec4fb 146 for (u8_currentPixel = 0;
Damotclese 1:316582aec4fb 147 u8_currentPixel < strlen(pau8_mushroomMap[u8_lineCount]);
Damotclese 1:316582aec4fb 148 u8_currentPixel++)
Damotclese 1:316582aec4fb 149 {
Damotclese 1:316582aec4fb 150 // Are we drawing the sprite rather than erasing it?
Damotclese 1:316582aec4fb 151 if (true == b_drawSprite)
Damotclese 1:316582aec4fb 152 {
Damotclese 1:316582aec4fb 153 // Find out what the color of this pixel should be
Damotclese 1:316582aec4fb 154 switch(pau8_mushroomMap[u8_lineCount][u8_currentPixel])
Damotclese 1:316582aec4fb 155 {
Damotclese 1:316582aec4fb 156 case 'w':
Damotclese 1:316582aec4fb 157 case 'W':
Damotclese 1:316582aec4fb 158 {
Damotclese 1:316582aec4fb 159 u32thisColor = LCD_COLOR_WHITE;
Damotclese 1:316582aec4fb 160 break;
Damotclese 1:316582aec4fb 161 }
Damotclese 1:316582aec4fb 162 case 'b':
Damotclese 1:316582aec4fb 163 case 'B':
Damotclese 1:316582aec4fb 164 {
Damotclese 1:316582aec4fb 165 u32thisColor = LCD_COLOR_BLUE;
Damotclese 1:316582aec4fb 166 break;
Damotclese 1:316582aec4fb 167 }
Damotclese 1:316582aec4fb 168 case 'g':
Damotclese 1:316582aec4fb 169 case 'G':
Damotclese 1:316582aec4fb 170 {
Damotclese 1:316582aec4fb 171 u32thisColor = LCD_COLOR_GREEN;
Damotclese 1:316582aec4fb 172 break;
Damotclese 1:316582aec4fb 173 }
Damotclese 1:316582aec4fb 174 case 'r':
Damotclese 1:316582aec4fb 175 case 'R':
Damotclese 1:316582aec4fb 176 {
Damotclese 1:316582aec4fb 177 u32thisColor = LCD_COLOR_RED;
Damotclese 1:316582aec4fb 178 break;
Damotclese 1:316582aec4fb 179 }
Damotclese 1:316582aec4fb 180 case 'k':
Damotclese 1:316582aec4fb 181 case 'K':
Damotclese 1:316582aec4fb 182 {
Damotclese 1:316582aec4fb 183 u32thisColor = LCD_COLOR_BLACK;
Damotclese 1:316582aec4fb 184 break;
Damotclese 1:316582aec4fb 185 }
Damotclese 1:316582aec4fb 186 case 'y':
Damotclese 1:316582aec4fb 187 case 'Y':
Damotclese 1:316582aec4fb 188 {
Damotclese 1:316582aec4fb 189 u32thisColor = LCD_COLOR_YELLOW;
Damotclese 1:316582aec4fb 190 break;
Damotclese 1:316582aec4fb 191 }
Damotclese 1:316582aec4fb 192 }
Damotclese 1:316582aec4fb 193 }
Damotclese 1:316582aec4fb 194 else
Damotclese 1:316582aec4fb 195 {
Damotclese 1:316582aec4fb 196 // Since we are erasing the sprite, the color is white
Damotclese 1:316582aec4fb 197 u32thisColor = LCD_COLOR_WHITE;
Damotclese 1:316582aec4fb 198 }
Damotclese 1:316582aec4fb 199
Damotclese 1:316582aec4fb 200 // Place the pixel on the screen with the correct color
Damotclese 1:316582aec4fb 201 st_lcd.DrawPixel(u16_currentX, u16_currentY, u32thisColor);
Damotclese 1:316582aec4fb 202
Damotclese 1:316582aec4fb 203 // Next pixel
Damotclese 1:316582aec4fb 204 u16_currentX++;
Damotclese 1:316582aec4fb 205 }
Damotclese 1:316582aec4fb 206
Damotclese 1:316582aec4fb 207 // Start working on the next line
Damotclese 1:316582aec4fb 208 u16_currentY++;
Damotclese 1:316582aec4fb 209
Damotclese 1:316582aec4fb 210 u16_currentX = u16_thisX;
Damotclese 1:316582aec4fb 211 }
Damotclese 1:316582aec4fb 212 }
Damotclese 1:316582aec4fb 213
Damotclese 1:316582aec4fb 214 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 215 // AnimationGetANewDirectionToTravel()
Damotclese 1:316582aec4fb 216 //
Damotclese 1:316582aec4fb 217 // We acquire a "random" direction to travel. Note that the mbed random
Damotclese 1:316582aec4fb 218 // number generator is highly flawed, it produces the same numbers
Damotclese 1:316582aec4fb 219 // despite how hard one seeds it. We could utilize an ununsed analog
Damotclese 1:316582aec4fb 220 // input and use the noise that might be found there, but for purposes
Damotclese 1:316582aec4fb 221 // of demonstrating animation, we'll just use what mben provided.
Damotclese 1:316582aec4fb 222 //
Damotclese 1:316582aec4fb 223 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 224 static uint8_t AnimationGetANewDirectionToTravel(void)
Damotclese 1:316582aec4fb 225 {
Damotclese 1:316582aec4fb 226 uint8_t u8_newDirection = 5;
Damotclese 1:316582aec4fb 227
Damotclese 1:316582aec4fb 228 // Keep looking for a "random" number until one is valid
Damotclese 1:316582aec4fb 229 while(5 == u8_newDirection ||
Damotclese 1:316582aec4fb 230 u8_newDirection < SPRITE_DIRECTION_LEFT_UP ||
Damotclese 1:316582aec4fb 231 u8_newDirection > SPRITE_DIRECTION_RIGHT_DOWN)
Damotclese 1:316582aec4fb 232 {
Damotclese 1:316582aec4fb 233 // Get a new direction to tavel
Damotclese 1:316582aec4fb 234 u8_newDirection = (rand() % SPRITE_DIRECTION_RIGHT_DOWN);
Damotclese 1:316582aec4fb 235 }
Damotclese 1:316582aec4fb 236
Damotclese 1:316582aec4fb 237 // Return the new direction of travel
Damotclese 1:316582aec4fb 238 return u8_newDirection;
Damotclese 1:316582aec4fb 239 }
Damotclese 1:316582aec4fb 240
Damotclese 1:316582aec4fb 241 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 242 // AnimationInit()
Damotclese 1:316582aec4fb 243 //
Damotclese 1:316582aec4fb 244 // Initializes any locally-held data and performs all other start-up
Damotclese 1:316582aec4fb 245 // functionality required for the animated functionality, if any.
Damotclese 1:316582aec4fb 246 //
Damotclese 1:316582aec4fb 247 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 248 void AnimationInit(void)
Damotclese 1:316582aec4fb 249 {
Damotclese 1:316582aec4fb 250 // Initialize locally-held data
Damotclese 1:316582aec4fb 251 u16_spriteCurrentX = 0;
Damotclese 1:316582aec4fb 252 u16_spriteCurrentY = 0;
Damotclese 1:316582aec4fb 253 b_animationThreadRunning = false;
Damotclese 1:316582aec4fb 254 u8_spriteCurrentDirection = AnimationGetANewDirectionToTravel();
Damotclese 1:316582aec4fb 255 u8_teleportCounter = 0;
Damotclese 1:316582aec4fb 256 u16_teleportMessageRemovalCountDown = 0;
Damotclese 1:316582aec4fb 257 }
Damotclese 1:316582aec4fb 258
Damotclese 1:316582aec4fb 259 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 260 // AnimationMoveSprite()
Damotclese 1:316582aec4fb 261 //
Damotclese 2:444eeedb41f0 262 // This function is the one that performs the actual move by 1 pixel
Damotclese 2:444eeedb41f0 263 // of the sprite. The sprite is erased from the screen and then the
Damotclese 2:444eeedb41f0 264 // new location is computed. If that places the sprite outside of the
Damotclese 2:444eeedb41f0 265 // boundaries, a new direction is selected and then the proposed
Damotclese 2:444eeedb41f0 266 // new location is selected.
Damotclese 2:444eeedb41f0 267 //
Damotclese 2:444eeedb41f0 268 // Once there is a new sprite location proposed, it gets re-drawn.
Damotclese 1:316582aec4fb 269 //
Damotclese 1:316582aec4fb 270 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 271 static void AnimationMoveSprite(void)
Damotclese 1:316582aec4fb 272 {
Damotclese 1:316582aec4fb 273 uint16_t u16_proposedX = u16_spriteCurrentX;
Damotclese 1:316582aec4fb 274 uint16_t u16_proposedY = u16_spriteCurrentY;
Damotclese 1:316582aec4fb 275 int8_t i8_proposedOffsetX = 0;
Damotclese 1:316582aec4fb 276 int8_t i8_proposedOffsetY = 0;
Damotclese 1:316582aec4fb 277 bool b_haveNewLocation = false;
Damotclese 1:316582aec4fb 278
Damotclese 1:316582aec4fb 279 // Did we teleport and display a message indicating that we did?
Damotclese 1:316582aec4fb 280 if (u16_teleportMessageRemovalCountDown > 0)
Damotclese 1:316582aec4fb 281 {
Damotclese 1:316582aec4fb 282 // Yes, so count down the timer / counter and see if it expired
Damotclese 1:316582aec4fb 283 if (0 == --u16_teleportMessageRemovalCountDown)
Damotclese 1:316582aec4fb 284 {
Damotclese 1:316582aec4fb 285 // Clear the message line
Damotclese 1:316582aec4fb 286 st_lcd.ClearStringLine(4);
Damotclese 1:316582aec4fb 287 }
Damotclese 1:316582aec4fb 288 }
Damotclese 1:316582aec4fb 289
Damotclese 1:316582aec4fb 290 // Erase the entire sprite from where it currently exists
Damotclese 1:316582aec4fb 291 AnimationDrawOrEraseSpriteAtThisLocation(u16_spriteCurrentX, u16_spriteCurrentY, false);
Damotclese 1:316582aec4fb 292
Damotclese 1:316582aec4fb 293 // We loop until we have a new location to move the sprite to.
Damotclese 1:316582aec4fb 294 // We look for a valid location more than once since we may
Damotclese 1:316582aec4fb 295 // run in to a boundary and have to change our direction of travel
Damotclese 1:316582aec4fb 296 while(false == b_haveNewLocation)
Damotclese 1:316582aec4fb 297 {
Damotclese 1:316582aec4fb 298 // Compute the new location of the sprite
Damotclese 1:316582aec4fb 299 switch(u8_spriteCurrentDirection)
Damotclese 1:316582aec4fb 300 {
Damotclese 1:316582aec4fb 301 // Extract the proposed offsets for X and Y
Damotclese 1:316582aec4fb 302 case SPRITE_DIRECTION_LEFT_UP:
Damotclese 1:316582aec4fb 303 {
Damotclese 1:316582aec4fb 304 i8_proposedOffsetX = i8_movementMatrix[0][0];
Damotclese 1:316582aec4fb 305 i8_proposedOffsetY = i8_movementMatrix[0][1];
Damotclese 1:316582aec4fb 306 break;
Damotclese 1:316582aec4fb 307 }
Damotclese 1:316582aec4fb 308 case SPRITE_DIRECTION_UP:
Damotclese 1:316582aec4fb 309 {
Damotclese 1:316582aec4fb 310 i8_proposedOffsetX = i8_movementMatrix[0][2];
Damotclese 1:316582aec4fb 311 i8_proposedOffsetY = i8_movementMatrix[0][3];
Damotclese 1:316582aec4fb 312 break;
Damotclese 1:316582aec4fb 313 }
Damotclese 1:316582aec4fb 314 case SPRITE_DIRECTION_RIGHT_UP:
Damotclese 1:316582aec4fb 315 {
Damotclese 1:316582aec4fb 316 i8_proposedOffsetX = i8_movementMatrix[0][4];
Damotclese 1:316582aec4fb 317 i8_proposedOffsetY = i8_movementMatrix[0][5];
Damotclese 1:316582aec4fb 318 break;
Damotclese 1:316582aec4fb 319 }
Damotclese 1:316582aec4fb 320 case SPRITE_DIRECTION_LEFT:
Damotclese 1:316582aec4fb 321 {
Damotclese 1:316582aec4fb 322 i8_proposedOffsetX = i8_movementMatrix[1][0];
Damotclese 1:316582aec4fb 323 i8_proposedOffsetY = i8_movementMatrix[1][1];
Damotclese 1:316582aec4fb 324 break;
Damotclese 1:316582aec4fb 325 }
Damotclese 1:316582aec4fb 326 case SPRITE_DIRECTION_RIGHT:
Damotclese 1:316582aec4fb 327 {
Damotclese 1:316582aec4fb 328 i8_proposedOffsetX = i8_movementMatrix[1][4];
Damotclese 1:316582aec4fb 329 i8_proposedOffsetY = i8_movementMatrix[1][5];
Damotclese 1:316582aec4fb 330 break;
Damotclese 1:316582aec4fb 331 }
Damotclese 1:316582aec4fb 332 default:
Damotclese 1:316582aec4fb 333 case SPRITE_DIRECTION_NOT_VALID:
Damotclese 1:316582aec4fb 334 {
Damotclese 1:316582aec4fb 335 // We should never be able to get here
Damotclese 1:316582aec4fb 336 return;
Damotclese 1:316582aec4fb 337 }
Damotclese 1:316582aec4fb 338 case SPRITE_DIRECTION_LEFT_DOWN:
Damotclese 1:316582aec4fb 339 {
Damotclese 1:316582aec4fb 340 i8_proposedOffsetX = i8_movementMatrix[2][0];
Damotclese 1:316582aec4fb 341 i8_proposedOffsetY = i8_movementMatrix[2][1];
Damotclese 1:316582aec4fb 342 break;
Damotclese 1:316582aec4fb 343 }
Damotclese 1:316582aec4fb 344 case SPRITE_DIRECTION_DOWN:
Damotclese 1:316582aec4fb 345 {
Damotclese 1:316582aec4fb 346 i8_proposedOffsetX = i8_movementMatrix[2][2];
Damotclese 1:316582aec4fb 347 i8_proposedOffsetY = i8_movementMatrix[2][3];
Damotclese 1:316582aec4fb 348 break;
Damotclese 1:316582aec4fb 349 }
Damotclese 1:316582aec4fb 350 case SPRITE_DIRECTION_RIGHT_DOWN:
Damotclese 1:316582aec4fb 351 {
Damotclese 1:316582aec4fb 352 i8_proposedOffsetX = i8_movementMatrix[2][4];
Damotclese 1:316582aec4fb 353 i8_proposedOffsetY = i8_movementMatrix[2][5];
Damotclese 1:316582aec4fb 354 break;
Damotclese 1:316582aec4fb 355 }
Damotclese 1:316582aec4fb 356 }
Damotclese 1:316582aec4fb 357
Damotclese 1:316582aec4fb 358 // Apply the proposed offsets to the proposed new coordinates
Damotclese 1:316582aec4fb 359 u16_proposedX += i8_proposedOffsetX;
Damotclese 1:316582aec4fb 360 u16_proposedY += i8_proposedOffsetY;
Damotclese 1:316582aec4fb 361
Damotclese 1:316582aec4fb 362 // Are the proposed coordinates within the bounds of where we
Damotclese 1:316582aec4fb 363 // want the sprite to move within?
Damotclese 1:316582aec4fb 364 if (u16_proposedX < SPRITE_MINIMUM_X || u16_proposedX > SPRITE_MAXIMUM_X ||
Damotclese 1:316582aec4fb 365 u16_proposedY < SPRITE_MINIMUM_Y || u16_proposedY > SPRITE_MAXIMUM_Y)
Damotclese 1:316582aec4fb 366 {
Damotclese 1:316582aec4fb 367 // We have encountered a boundary so we must choose
Damotclese 1:316582aec4fb 368 // a new location and then try again
Damotclese 1:316582aec4fb 369 u8_spriteCurrentDirection = AnimationGetANewDirectionToTravel();
Damotclese 1:316582aec4fb 370
Damotclese 1:316582aec4fb 371 // Increment the teleport counter and see if it's time to teleport
Damotclese 1:316582aec4fb 372 if (++u8_teleportCounter == 10)
Damotclese 1:316582aec4fb 373 {
Damotclese 1:316582aec4fb 374 // It is time to teleport, pick a new "random" location
Damotclese 1:316582aec4fb 375 u16_proposedX = (rand() % LCD_WIDTH);
Damotclese 1:316582aec4fb 376 u16_proposedY = (rand() % LCD_HEIGHT);
Damotclese 1:316582aec4fb 377
Damotclese 1:316582aec4fb 378 // Start counting for the next teleport
Damotclese 1:316582aec4fb 379 u8_teleportCounter = 0;
Damotclese 1:316582aec4fb 380
Damotclese 1:316582aec4fb 381 // Report that we teleported!
Damotclese 1:316582aec4fb 382 st_lcd.DisplayStringAt(1, LINE(4), (uint8_t *)"Teleported!", CENTER_MODE);
Damotclese 1:316582aec4fb 383
Damotclese 1:316582aec4fb 384 // After a while we will remove that message so this is a timer/counter
Damotclese 1:316582aec4fb 385 u16_teleportMessageRemovalCountDown = 40;
Damotclese 1:316582aec4fb 386 }
Damotclese 1:316582aec4fb 387 else
Damotclese 1:316582aec4fb 388 {
Damotclese 1:316582aec4fb 389 // Start over from where we currently are
Damotclese 1:316582aec4fb 390 u16_proposedX = u16_spriteCurrentX;
Damotclese 1:316582aec4fb 391 u16_proposedY = u16_spriteCurrentY;
Damotclese 1:316582aec4fb 392 }
Damotclese 1:316582aec4fb 393
Damotclese 1:316582aec4fb 394 // Try for a new location
Damotclese 1:316582aec4fb 395 continue;
Damotclese 1:316582aec4fb 396 }
Damotclese 1:316582aec4fb 397
Damotclese 1:316582aec4fb 398 // We have a new proposed location
Damotclese 1:316582aec4fb 399 b_haveNewLocation = true;
Damotclese 1:316582aec4fb 400 }
Damotclese 1:316582aec4fb 401
Damotclese 1:316582aec4fb 402 // Place the sprite at the new location
Damotclese 1:316582aec4fb 403 AnimationDrawOrEraseSpriteAtThisLocation(u16_proposedX, u16_proposedY, true);
Damotclese 1:316582aec4fb 404 }
Damotclese 1:316582aec4fb 405
Damotclese 1:316582aec4fb 406 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 407 // AnimationThread()
Damotclese 1:316582aec4fb 408 //
Damotclese 2:444eeedb41f0 409 // This is the main thread for the animation functionality. The thread
Damotclese 2:444eeedb41f0 410 // usually runs forever however there is a mechanism for terminating
Damotclese 2:444eeedb41f0 411 // it provided in this module.
Damotclese 2:444eeedb41f0 412 //
Damotclese 2:444eeedb41f0 413 // The thread wakes up about 40 times a second so that the animation
Damotclese 2:444eeedb41f0 414 // can move fairly quickly and smoothly.
Damotclese 1:316582aec4fb 415 //
Damotclese 1:316582aec4fb 416 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 417 void AnimationThread(void)
Damotclese 1:316582aec4fb 418 {
Damotclese 1:316582aec4fb 419 // This thread will run until it gets terminated upon request
Damotclese 1:316582aec4fb 420 while(true)
Damotclese 1:316582aec4fb 421 {
Damotclese 1:316582aec4fb 422 // Wake up 40 times a second
Damotclese 1:316582aec4fb 423 wait(0.025);
Damotclese 1:316582aec4fb 424
Damotclese 1:316582aec4fb 425 // Move ths sprite in the cirrent direction of travel
Damotclese 1:316582aec4fb 426 AnimationMoveSprite();
Damotclese 1:316582aec4fb 427 }
Damotclese 1:316582aec4fb 428 }
Damotclese 1:316582aec4fb 429
Damotclese 1:316582aec4fb 430 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 431 // AnimationPerformAnimation()
Damotclese 1:316582aec4fb 432 //
Damotclese 2:444eeedb41f0 433 // This function is called when it is time to start animating the
Damotclese 2:444eeedb41f0 434 // sprite. It checks to make sure that the animation thread is not
Damotclese 2:444eeedb41f0 435 // yet started before it starts the animation.
Damotclese 1:316582aec4fb 436 //
Damotclese 1:316582aec4fb 437 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 438 void AnimationPerformAnimation(uint32_t u32_randomSeeder)
Damotclese 1:316582aec4fb 439 {
Damotclese 1:316582aec4fb 440 // Are we currently not running the animation?
Damotclese 1:316582aec4fb 441 if (false == b_animationThreadRunning)
Damotclese 1:316582aec4fb 442 {
Damotclese 1:316582aec4fb 443 // Place the sprite on to the screen
Damotclese 1:316582aec4fb 444 AnimationDrawOrEraseSpriteAtThisLocation(LCD_WIDTH / 2, LCD_HEIGHT / 2, true);
Damotclese 1:316582aec4fb 445
Damotclese 1:316582aec4fb 446 // Start the animation thread
Damotclese 1:316582aec4fb 447 st_animationThread.start(AnimationThread);
Damotclese 1:316582aec4fb 448
Damotclese 1:316582aec4fb 449 // Flag the fact that the thread is running
Damotclese 1:316582aec4fb 450 b_animationThreadRunning = true;
Damotclese 2:444eeedb41f0 451
Damotclese 2:444eeedb41f0 452 // In an effort to add more "randomness," read some of the
Damotclese 2:444eeedb41f0 453 // analog inputs and add their values, if any, to the seed
Damotclese 2:444eeedb41f0 454 u32_randomSeeder = (st_analog1 * 100) + (st_analog2 * 100) + (st_analog3 * 100);
Damotclese 1:316582aec4fb 455
Damotclese 1:316582aec4fb 456 // In order to "seed" the random number generator, we acquire
Damotclese 1:316582aec4fb 457 // and discard up to 2000 random numbers
Damotclese 1:316582aec4fb 458 u32_randomSeeder %= 2000;
Damotclese 1:316582aec4fb 459
Damotclese 1:316582aec4fb 460 // Acquire up to 2000 random numbers
Damotclese 1:316582aec4fb 461 while (u32_randomSeeder-- > 0)
Damotclese 1:316582aec4fb 462 {
Damotclese 1:316582aec4fb 463 // Acquire the number and then discard it
Damotclese 1:316582aec4fb 464 (void)AnimationGetANewDirectionToTravel();
Damotclese 1:316582aec4fb 465 }
Damotclese 1:316582aec4fb 466 }
Damotclese 1:316582aec4fb 467 }
Damotclese 1:316582aec4fb 468
Damotclese 1:316582aec4fb 469 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 470 // AnimationStopAnimation()
Damotclese 1:316582aec4fb 471 //
Damotclese 2:444eeedb41f0 472 // In the event the animation thread needs to be stopped, this function
Damotclese 2:444eeedb41f0 473 // may be called to terminate the animation thread.
Damotclese 1:316582aec4fb 474 //
Damotclese 1:316582aec4fb 475 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 476 void AnimationStopAnimation(void)
Damotclese 1:316582aec4fb 477 {
Damotclese 1:316582aec4fb 478 // Is the animation thread running?
Damotclese 1:316582aec4fb 479 if (true == b_animationThreadRunning)
Damotclese 1:316582aec4fb 480 {
Damotclese 1:316582aec4fb 481 // Stop the animation thread
Damotclese 1:316582aec4fb 482 st_animationThread.terminate();
Damotclese 1:316582aec4fb 483
Damotclese 1:316582aec4fb 484 // Flag the fact that animation is no longer running
Damotclese 1:316582aec4fb 485 b_animationThreadRunning = false;
Damotclese 1:316582aec4fb 486 }
Damotclese 1:316582aec4fb 487 }
Damotclese 1:316582aec4fb 488
Damotclese 1:316582aec4fb 489 // End of file
Damotclese 1:316582aec4fb 490