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:
Tue Jun 04 22:51:25 2019 +0000
Revision:
4:5c70a30d6757
Parent:
3:0e554d8d5a19
Additional comments, no actual code changes.;

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 4:5c70a30d6757 130 // Note that we do not attempt to store the original pixel's color
Damotclese 4:5c70a30d6757 131 // value before writing it with a new value, so we can not restore
Damotclese 4:5c70a30d6757 132 // the pixel once the sprite moves off of it. This is a stark
Damotclese 4:5c70a30d6757 133 // divergence from real spite automation which restores the original,
Damotclese 4:5c70a30d6757 134 // but we are demo code, not a real project, so we don't even try.
Damotclese 4:5c70a30d6757 135 //
Damotclese 1:316582aec4fb 136 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 137 static void AnimationDrawOrEraseSpriteAtThisLocation(uint16_t u16_thisX, uint16_t u16_thisY, bool b_drawSprite)
Damotclese 1:316582aec4fb 138 {
Damotclese 1:316582aec4fb 139 uint8_t u8_lineCount = 0;
Damotclese 1:316582aec4fb 140 uint16_t u16_currentX = u16_thisX;
Damotclese 1:316582aec4fb 141 uint16_t u16_currentY = u16_thisY;
Damotclese 1:316582aec4fb 142 uint8_t u8_currentPixel = 0;
Damotclese 1:316582aec4fb 143 uint32_t u32thisColor = LCD_COLOR_BLUE;
Damotclese 1:316582aec4fb 144
Damotclese 1:316582aec4fb 145 // Record where we are placing the sprite this time
Damotclese 1:316582aec4fb 146 u16_spriteCurrentX = u16_thisX;
Damotclese 1:316582aec4fb 147 u16_spriteCurrentY = u16_thisY;
Damotclese 1:316582aec4fb 148
Damotclese 1:316582aec4fb 149 // Place the sprite on the screen pixel by pixel
Damotclese 1:316582aec4fb 150 for (u8_lineCount = 0; u8_lineCount < SPRITE_HEIGHT_IN_PIXELS; u8_lineCount++)
Damotclese 1:316582aec4fb 151 {
Damotclese 1:316582aec4fb 152 for (u8_currentPixel = 0;
Damotclese 1:316582aec4fb 153 u8_currentPixel < strlen(pau8_mushroomMap[u8_lineCount]);
Damotclese 1:316582aec4fb 154 u8_currentPixel++)
Damotclese 1:316582aec4fb 155 {
Damotclese 1:316582aec4fb 156 // Are we drawing the sprite rather than erasing it?
Damotclese 1:316582aec4fb 157 if (true == b_drawSprite)
Damotclese 1:316582aec4fb 158 {
Damotclese 1:316582aec4fb 159 // Find out what the color of this pixel should be
Damotclese 1:316582aec4fb 160 switch(pau8_mushroomMap[u8_lineCount][u8_currentPixel])
Damotclese 1:316582aec4fb 161 {
Damotclese 1:316582aec4fb 162 case 'w':
Damotclese 1:316582aec4fb 163 case 'W':
Damotclese 1:316582aec4fb 164 {
Damotclese 1:316582aec4fb 165 u32thisColor = LCD_COLOR_WHITE;
Damotclese 1:316582aec4fb 166 break;
Damotclese 1:316582aec4fb 167 }
Damotclese 1:316582aec4fb 168 case 'b':
Damotclese 1:316582aec4fb 169 case 'B':
Damotclese 1:316582aec4fb 170 {
Damotclese 1:316582aec4fb 171 u32thisColor = LCD_COLOR_BLUE;
Damotclese 1:316582aec4fb 172 break;
Damotclese 1:316582aec4fb 173 }
Damotclese 1:316582aec4fb 174 case 'g':
Damotclese 1:316582aec4fb 175 case 'G':
Damotclese 1:316582aec4fb 176 {
Damotclese 1:316582aec4fb 177 u32thisColor = LCD_COLOR_GREEN;
Damotclese 1:316582aec4fb 178 break;
Damotclese 1:316582aec4fb 179 }
Damotclese 1:316582aec4fb 180 case 'r':
Damotclese 1:316582aec4fb 181 case 'R':
Damotclese 1:316582aec4fb 182 {
Damotclese 1:316582aec4fb 183 u32thisColor = LCD_COLOR_RED;
Damotclese 1:316582aec4fb 184 break;
Damotclese 1:316582aec4fb 185 }
Damotclese 1:316582aec4fb 186 case 'k':
Damotclese 1:316582aec4fb 187 case 'K':
Damotclese 1:316582aec4fb 188 {
Damotclese 1:316582aec4fb 189 u32thisColor = LCD_COLOR_BLACK;
Damotclese 1:316582aec4fb 190 break;
Damotclese 1:316582aec4fb 191 }
Damotclese 1:316582aec4fb 192 case 'y':
Damotclese 1:316582aec4fb 193 case 'Y':
Damotclese 1:316582aec4fb 194 {
Damotclese 1:316582aec4fb 195 u32thisColor = LCD_COLOR_YELLOW;
Damotclese 1:316582aec4fb 196 break;
Damotclese 1:316582aec4fb 197 }
Damotclese 1:316582aec4fb 198 }
Damotclese 1:316582aec4fb 199 }
Damotclese 1:316582aec4fb 200 else
Damotclese 1:316582aec4fb 201 {
Damotclese 1:316582aec4fb 202 // Since we are erasing the sprite, the color is white
Damotclese 1:316582aec4fb 203 u32thisColor = LCD_COLOR_WHITE;
Damotclese 1:316582aec4fb 204 }
Damotclese 1:316582aec4fb 205
Damotclese 1:316582aec4fb 206 // Place the pixel on the screen with the correct color
Damotclese 1:316582aec4fb 207 st_lcd.DrawPixel(u16_currentX, u16_currentY, u32thisColor);
Damotclese 1:316582aec4fb 208
Damotclese 1:316582aec4fb 209 // Next pixel
Damotclese 1:316582aec4fb 210 u16_currentX++;
Damotclese 1:316582aec4fb 211 }
Damotclese 1:316582aec4fb 212
Damotclese 1:316582aec4fb 213 // Start working on the next line
Damotclese 1:316582aec4fb 214 u16_currentY++;
Damotclese 1:316582aec4fb 215
Damotclese 1:316582aec4fb 216 u16_currentX = u16_thisX;
Damotclese 1:316582aec4fb 217 }
Damotclese 1:316582aec4fb 218 }
Damotclese 1:316582aec4fb 219
Damotclese 1:316582aec4fb 220 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 221 // AnimationGetANewDirectionToTravel()
Damotclese 1:316582aec4fb 222 //
Damotclese 1:316582aec4fb 223 // We acquire a "random" direction to travel. Note that the mbed random
Damotclese 1:316582aec4fb 224 // number generator is highly flawed, it produces the same numbers
Damotclese 1:316582aec4fb 225 // despite how hard one seeds it. We could utilize an ununsed analog
Damotclese 1:316582aec4fb 226 // input and use the noise that might be found there, but for purposes
Damotclese 1:316582aec4fb 227 // of demonstrating animation, we'll just use what mben provided.
Damotclese 1:316582aec4fb 228 //
Damotclese 1:316582aec4fb 229 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 230 static uint8_t AnimationGetANewDirectionToTravel(void)
Damotclese 1:316582aec4fb 231 {
Damotclese 1:316582aec4fb 232 uint8_t u8_newDirection = 5;
Damotclese 1:316582aec4fb 233
Damotclese 1:316582aec4fb 234 // Keep looking for a "random" number until one is valid
Damotclese 1:316582aec4fb 235 while(5 == u8_newDirection ||
Damotclese 1:316582aec4fb 236 u8_newDirection < SPRITE_DIRECTION_LEFT_UP ||
Damotclese 1:316582aec4fb 237 u8_newDirection > SPRITE_DIRECTION_RIGHT_DOWN)
Damotclese 1:316582aec4fb 238 {
Damotclese 1:316582aec4fb 239 // Get a new direction to tavel
Damotclese 1:316582aec4fb 240 u8_newDirection = (rand() % SPRITE_DIRECTION_RIGHT_DOWN);
Damotclese 1:316582aec4fb 241 }
Damotclese 1:316582aec4fb 242
Damotclese 1:316582aec4fb 243 // Return the new direction of travel
Damotclese 1:316582aec4fb 244 return u8_newDirection;
Damotclese 1:316582aec4fb 245 }
Damotclese 1:316582aec4fb 246
Damotclese 1:316582aec4fb 247 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 248 // AnimationInit()
Damotclese 1:316582aec4fb 249 //
Damotclese 1:316582aec4fb 250 // Initializes any locally-held data and performs all other start-up
Damotclese 1:316582aec4fb 251 // functionality required for the animated functionality, if any.
Damotclese 1:316582aec4fb 252 //
Damotclese 1:316582aec4fb 253 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 254 void AnimationInit(void)
Damotclese 1:316582aec4fb 255 {
Damotclese 1:316582aec4fb 256 // Initialize locally-held data
Damotclese 1:316582aec4fb 257 u16_spriteCurrentX = 0;
Damotclese 1:316582aec4fb 258 u16_spriteCurrentY = 0;
Damotclese 1:316582aec4fb 259 b_animationThreadRunning = false;
Damotclese 1:316582aec4fb 260 u8_spriteCurrentDirection = AnimationGetANewDirectionToTravel();
Damotclese 1:316582aec4fb 261 u8_teleportCounter = 0;
Damotclese 1:316582aec4fb 262 u16_teleportMessageRemovalCountDown = 0;
Damotclese 1:316582aec4fb 263 }
Damotclese 1:316582aec4fb 264
Damotclese 1:316582aec4fb 265 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 266 // AnimationMoveSprite()
Damotclese 1:316582aec4fb 267 //
Damotclese 2:444eeedb41f0 268 // This function is the one that performs the actual move by 1 pixel
Damotclese 2:444eeedb41f0 269 // of the sprite. The sprite is erased from the screen and then the
Damotclese 2:444eeedb41f0 270 // new location is computed. If that places the sprite outside of the
Damotclese 2:444eeedb41f0 271 // boundaries, a new direction is selected and then the proposed
Damotclese 2:444eeedb41f0 272 // new location is selected.
Damotclese 2:444eeedb41f0 273 //
Damotclese 2:444eeedb41f0 274 // Once there is a new sprite location proposed, it gets re-drawn.
Damotclese 1:316582aec4fb 275 //
Damotclese 1:316582aec4fb 276 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 277 static void AnimationMoveSprite(void)
Damotclese 1:316582aec4fb 278 {
Damotclese 1:316582aec4fb 279 uint16_t u16_proposedX = u16_spriteCurrentX;
Damotclese 1:316582aec4fb 280 uint16_t u16_proposedY = u16_spriteCurrentY;
Damotclese 1:316582aec4fb 281 int8_t i8_proposedOffsetX = 0;
Damotclese 1:316582aec4fb 282 int8_t i8_proposedOffsetY = 0;
Damotclese 1:316582aec4fb 283 bool b_haveNewLocation = false;
Damotclese 1:316582aec4fb 284
Damotclese 1:316582aec4fb 285 // Did we teleport and display a message indicating that we did?
Damotclese 1:316582aec4fb 286 if (u16_teleportMessageRemovalCountDown > 0)
Damotclese 1:316582aec4fb 287 {
Damotclese 1:316582aec4fb 288 // Yes, so count down the timer / counter and see if it expired
Damotclese 1:316582aec4fb 289 if (0 == --u16_teleportMessageRemovalCountDown)
Damotclese 1:316582aec4fb 290 {
Damotclese 1:316582aec4fb 291 // Clear the message line
Damotclese 1:316582aec4fb 292 st_lcd.ClearStringLine(4);
Damotclese 1:316582aec4fb 293 }
Damotclese 1:316582aec4fb 294 }
Damotclese 1:316582aec4fb 295
Damotclese 1:316582aec4fb 296 // Erase the entire sprite from where it currently exists
Damotclese 1:316582aec4fb 297 AnimationDrawOrEraseSpriteAtThisLocation(u16_spriteCurrentX, u16_spriteCurrentY, false);
Damotclese 1:316582aec4fb 298
Damotclese 1:316582aec4fb 299 // We loop until we have a new location to move the sprite to.
Damotclese 1:316582aec4fb 300 // We look for a valid location more than once since we may
Damotclese 1:316582aec4fb 301 // run in to a boundary and have to change our direction of travel
Damotclese 1:316582aec4fb 302 while(false == b_haveNewLocation)
Damotclese 1:316582aec4fb 303 {
Damotclese 1:316582aec4fb 304 // Compute the new location of the sprite
Damotclese 1:316582aec4fb 305 switch(u8_spriteCurrentDirection)
Damotclese 1:316582aec4fb 306 {
Damotclese 1:316582aec4fb 307 // Extract the proposed offsets for X and Y
Damotclese 1:316582aec4fb 308 case SPRITE_DIRECTION_LEFT_UP:
Damotclese 1:316582aec4fb 309 {
Damotclese 1:316582aec4fb 310 i8_proposedOffsetX = i8_movementMatrix[0][0];
Damotclese 1:316582aec4fb 311 i8_proposedOffsetY = i8_movementMatrix[0][1];
Damotclese 1:316582aec4fb 312 break;
Damotclese 1:316582aec4fb 313 }
Damotclese 1:316582aec4fb 314 case SPRITE_DIRECTION_UP:
Damotclese 1:316582aec4fb 315 {
Damotclese 1:316582aec4fb 316 i8_proposedOffsetX = i8_movementMatrix[0][2];
Damotclese 1:316582aec4fb 317 i8_proposedOffsetY = i8_movementMatrix[0][3];
Damotclese 1:316582aec4fb 318 break;
Damotclese 1:316582aec4fb 319 }
Damotclese 1:316582aec4fb 320 case SPRITE_DIRECTION_RIGHT_UP:
Damotclese 1:316582aec4fb 321 {
Damotclese 1:316582aec4fb 322 i8_proposedOffsetX = i8_movementMatrix[0][4];
Damotclese 1:316582aec4fb 323 i8_proposedOffsetY = i8_movementMatrix[0][5];
Damotclese 1:316582aec4fb 324 break;
Damotclese 1:316582aec4fb 325 }
Damotclese 1:316582aec4fb 326 case SPRITE_DIRECTION_LEFT:
Damotclese 1:316582aec4fb 327 {
Damotclese 1:316582aec4fb 328 i8_proposedOffsetX = i8_movementMatrix[1][0];
Damotclese 1:316582aec4fb 329 i8_proposedOffsetY = i8_movementMatrix[1][1];
Damotclese 1:316582aec4fb 330 break;
Damotclese 1:316582aec4fb 331 }
Damotclese 1:316582aec4fb 332 case SPRITE_DIRECTION_RIGHT:
Damotclese 1:316582aec4fb 333 {
Damotclese 1:316582aec4fb 334 i8_proposedOffsetX = i8_movementMatrix[1][4];
Damotclese 1:316582aec4fb 335 i8_proposedOffsetY = i8_movementMatrix[1][5];
Damotclese 1:316582aec4fb 336 break;
Damotclese 1:316582aec4fb 337 }
Damotclese 1:316582aec4fb 338 default:
Damotclese 1:316582aec4fb 339 case SPRITE_DIRECTION_NOT_VALID:
Damotclese 1:316582aec4fb 340 {
Damotclese 1:316582aec4fb 341 // We should never be able to get here
Damotclese 1:316582aec4fb 342 return;
Damotclese 1:316582aec4fb 343 }
Damotclese 1:316582aec4fb 344 case SPRITE_DIRECTION_LEFT_DOWN:
Damotclese 1:316582aec4fb 345 {
Damotclese 1:316582aec4fb 346 i8_proposedOffsetX = i8_movementMatrix[2][0];
Damotclese 1:316582aec4fb 347 i8_proposedOffsetY = i8_movementMatrix[2][1];
Damotclese 1:316582aec4fb 348 break;
Damotclese 1:316582aec4fb 349 }
Damotclese 1:316582aec4fb 350 case SPRITE_DIRECTION_DOWN:
Damotclese 1:316582aec4fb 351 {
Damotclese 1:316582aec4fb 352 i8_proposedOffsetX = i8_movementMatrix[2][2];
Damotclese 1:316582aec4fb 353 i8_proposedOffsetY = i8_movementMatrix[2][3];
Damotclese 1:316582aec4fb 354 break;
Damotclese 1:316582aec4fb 355 }
Damotclese 1:316582aec4fb 356 case SPRITE_DIRECTION_RIGHT_DOWN:
Damotclese 1:316582aec4fb 357 {
Damotclese 1:316582aec4fb 358 i8_proposedOffsetX = i8_movementMatrix[2][4];
Damotclese 1:316582aec4fb 359 i8_proposedOffsetY = i8_movementMatrix[2][5];
Damotclese 1:316582aec4fb 360 break;
Damotclese 1:316582aec4fb 361 }
Damotclese 1:316582aec4fb 362 }
Damotclese 1:316582aec4fb 363
Damotclese 1:316582aec4fb 364 // Apply the proposed offsets to the proposed new coordinates
Damotclese 1:316582aec4fb 365 u16_proposedX += i8_proposedOffsetX;
Damotclese 1:316582aec4fb 366 u16_proposedY += i8_proposedOffsetY;
Damotclese 1:316582aec4fb 367
Damotclese 1:316582aec4fb 368 // Are the proposed coordinates within the bounds of where we
Damotclese 1:316582aec4fb 369 // want the sprite to move within?
Damotclese 1:316582aec4fb 370 if (u16_proposedX < SPRITE_MINIMUM_X || u16_proposedX > SPRITE_MAXIMUM_X ||
Damotclese 1:316582aec4fb 371 u16_proposedY < SPRITE_MINIMUM_Y || u16_proposedY > SPRITE_MAXIMUM_Y)
Damotclese 1:316582aec4fb 372 {
Damotclese 1:316582aec4fb 373 // We have encountered a boundary so we must choose
Damotclese 1:316582aec4fb 374 // a new location and then try again
Damotclese 1:316582aec4fb 375 u8_spriteCurrentDirection = AnimationGetANewDirectionToTravel();
Damotclese 1:316582aec4fb 376
Damotclese 1:316582aec4fb 377 // Increment the teleport counter and see if it's time to teleport
Damotclese 1:316582aec4fb 378 if (++u8_teleportCounter == 10)
Damotclese 1:316582aec4fb 379 {
Damotclese 1:316582aec4fb 380 // It is time to teleport, pick a new "random" location
Damotclese 1:316582aec4fb 381 u16_proposedX = (rand() % LCD_WIDTH);
Damotclese 1:316582aec4fb 382 u16_proposedY = (rand() % LCD_HEIGHT);
Damotclese 1:316582aec4fb 383
Damotclese 1:316582aec4fb 384 // Start counting for the next teleport
Damotclese 1:316582aec4fb 385 u8_teleportCounter = 0;
Damotclese 1:316582aec4fb 386
Damotclese 1:316582aec4fb 387 // Report that we teleported!
Damotclese 1:316582aec4fb 388 st_lcd.DisplayStringAt(1, LINE(4), (uint8_t *)"Teleported!", CENTER_MODE);
Damotclese 1:316582aec4fb 389
Damotclese 1:316582aec4fb 390 // After a while we will remove that message so this is a timer/counter
Damotclese 1:316582aec4fb 391 u16_teleportMessageRemovalCountDown = 40;
Damotclese 1:316582aec4fb 392 }
Damotclese 1:316582aec4fb 393 else
Damotclese 1:316582aec4fb 394 {
Damotclese 1:316582aec4fb 395 // Start over from where we currently are
Damotclese 1:316582aec4fb 396 u16_proposedX = u16_spriteCurrentX;
Damotclese 1:316582aec4fb 397 u16_proposedY = u16_spriteCurrentY;
Damotclese 1:316582aec4fb 398 }
Damotclese 1:316582aec4fb 399
Damotclese 1:316582aec4fb 400 // Try for a new location
Damotclese 1:316582aec4fb 401 continue;
Damotclese 1:316582aec4fb 402 }
Damotclese 1:316582aec4fb 403
Damotclese 1:316582aec4fb 404 // We have a new proposed location
Damotclese 1:316582aec4fb 405 b_haveNewLocation = true;
Damotclese 1:316582aec4fb 406 }
Damotclese 1:316582aec4fb 407
Damotclese 1:316582aec4fb 408 // Place the sprite at the new location
Damotclese 1:316582aec4fb 409 AnimationDrawOrEraseSpriteAtThisLocation(u16_proposedX, u16_proposedY, true);
Damotclese 1:316582aec4fb 410 }
Damotclese 1:316582aec4fb 411
Damotclese 1:316582aec4fb 412 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 413 // AnimationThread()
Damotclese 1:316582aec4fb 414 //
Damotclese 2:444eeedb41f0 415 // This is the main thread for the animation functionality. The thread
Damotclese 2:444eeedb41f0 416 // usually runs forever however there is a mechanism for terminating
Damotclese 2:444eeedb41f0 417 // it provided in this module.
Damotclese 2:444eeedb41f0 418 //
Damotclese 2:444eeedb41f0 419 // The thread wakes up about 40 times a second so that the animation
Damotclese 2:444eeedb41f0 420 // can move fairly quickly and smoothly.
Damotclese 1:316582aec4fb 421 //
Damotclese 1:316582aec4fb 422 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 423 void AnimationThread(void)
Damotclese 1:316582aec4fb 424 {
Damotclese 1:316582aec4fb 425 // This thread will run until it gets terminated upon request
Damotclese 1:316582aec4fb 426 while(true)
Damotclese 1:316582aec4fb 427 {
Damotclese 1:316582aec4fb 428 // Wake up 40 times a second
Damotclese 1:316582aec4fb 429 wait(0.025);
Damotclese 1:316582aec4fb 430
Damotclese 1:316582aec4fb 431 // Move ths sprite in the cirrent direction of travel
Damotclese 1:316582aec4fb 432 AnimationMoveSprite();
Damotclese 1:316582aec4fb 433 }
Damotclese 1:316582aec4fb 434 }
Damotclese 1:316582aec4fb 435
Damotclese 1:316582aec4fb 436 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 437 // AnimationPerformAnimation()
Damotclese 1:316582aec4fb 438 //
Damotclese 2:444eeedb41f0 439 // This function is called when it is time to start animating the
Damotclese 2:444eeedb41f0 440 // sprite. It checks to make sure that the animation thread is not
Damotclese 2:444eeedb41f0 441 // yet started before it starts the animation.
Damotclese 1:316582aec4fb 442 //
Damotclese 1:316582aec4fb 443 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 444 void AnimationPerformAnimation(uint32_t u32_randomSeeder)
Damotclese 1:316582aec4fb 445 {
Damotclese 1:316582aec4fb 446 // Are we currently not running the animation?
Damotclese 1:316582aec4fb 447 if (false == b_animationThreadRunning)
Damotclese 1:316582aec4fb 448 {
Damotclese 1:316582aec4fb 449 // Place the sprite on to the screen
Damotclese 1:316582aec4fb 450 AnimationDrawOrEraseSpriteAtThisLocation(LCD_WIDTH / 2, LCD_HEIGHT / 2, true);
Damotclese 1:316582aec4fb 451
Damotclese 1:316582aec4fb 452 // Start the animation thread
Damotclese 1:316582aec4fb 453 st_animationThread.start(AnimationThread);
Damotclese 1:316582aec4fb 454
Damotclese 1:316582aec4fb 455 // Flag the fact that the thread is running
Damotclese 1:316582aec4fb 456 b_animationThreadRunning = true;
Damotclese 2:444eeedb41f0 457
Damotclese 2:444eeedb41f0 458 // In an effort to add more "randomness," read some of the
Damotclese 2:444eeedb41f0 459 // analog inputs and add their values, if any, to the seed
Damotclese 2:444eeedb41f0 460 u32_randomSeeder = (st_analog1 * 100) + (st_analog2 * 100) + (st_analog3 * 100);
Damotclese 1:316582aec4fb 461
Damotclese 1:316582aec4fb 462 // In order to "seed" the random number generator, we acquire
Damotclese 1:316582aec4fb 463 // and discard up to 2000 random numbers
Damotclese 1:316582aec4fb 464 u32_randomSeeder %= 2000;
Damotclese 1:316582aec4fb 465
Damotclese 1:316582aec4fb 466 // Acquire up to 2000 random numbers
Damotclese 1:316582aec4fb 467 while (u32_randomSeeder-- > 0)
Damotclese 1:316582aec4fb 468 {
Damotclese 1:316582aec4fb 469 // Acquire the number and then discard it
Damotclese 1:316582aec4fb 470 (void)AnimationGetANewDirectionToTravel();
Damotclese 1:316582aec4fb 471 }
Damotclese 1:316582aec4fb 472 }
Damotclese 1:316582aec4fb 473 }
Damotclese 1:316582aec4fb 474
Damotclese 1:316582aec4fb 475 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 476 // AnimationStopAnimation()
Damotclese 1:316582aec4fb 477 //
Damotclese 2:444eeedb41f0 478 // In the event the animation thread needs to be stopped, this function
Damotclese 2:444eeedb41f0 479 // may be called to terminate the animation thread.
Damotclese 1:316582aec4fb 480 //
Damotclese 1:316582aec4fb 481 // ----------------------------------------------------------------------
Damotclese 1:316582aec4fb 482 void AnimationStopAnimation(void)
Damotclese 1:316582aec4fb 483 {
Damotclese 1:316582aec4fb 484 // Is the animation thread running?
Damotclese 1:316582aec4fb 485 if (true == b_animationThreadRunning)
Damotclese 1:316582aec4fb 486 {
Damotclese 1:316582aec4fb 487 // Stop the animation thread
Damotclese 1:316582aec4fb 488 st_animationThread.terminate();
Damotclese 1:316582aec4fb 489
Damotclese 1:316582aec4fb 490 // Flag the fact that animation is no longer running
Damotclese 1:316582aec4fb 491 b_animationThreadRunning = false;
Damotclese 1:316582aec4fb 492 }
Damotclese 1:316582aec4fb 493 }
Damotclese 1:316582aec4fb 494
Damotclese 1:316582aec4fb 495 // End of file
Damotclese 1:316582aec4fb 496