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.
SecurityUnlockDemo-Animation.cpp@3:0e554d8d5a19, 2019-06-03 (annotated)
- 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?
User | Revision | Line number | New 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 |