//***************************************************************************** // // This task manages the scurrying about of a spider. // //***************************************************************************** static void SpiderTask(void *pvParameters) { uint32_t ui32Dir, ui32Image, ui32Temp; int32_t i32X, i32Y, i32Spider; // // Get the spider number from the parameter. // i32Spider = (long)pvParameters; // // Add the current tick count to the random entropy pool. // RandomAddEntropy(xTaskGetTickCount()); // // Reseed the random number generator. // RandomSeed(); // // Indicate that this spider is alive. // HWREGBITW(&g_ui32SpiderAlive, i32Spider) = 1; // // Indicate that this spider is not dead yet. // HWREGBITW(&g_ui32SpiderDead, i32Spider) = 0; // // Get a local copy of the spider's starting position. // i32X = g_pi32SpiderX[i32Spider]; i32Y = g_pi32SpiderY[i32Spider]; // // Choose a random starting direction for the spider. // ui32Dir = RandomNumber() >> 29; // // Start by displaying the first of the two spider animation images. // ui32Image = 0; // // Loop forever. // while(1) { // // See if this spider has been killed. // if(HWREGBITW(&g_ui32SpiderDead, i32Spider) == 1) { // // Wait for 2 seconds. // vTaskDelay((1000 / portTICK_RATE_MS) * 2); // // Clear the spider from the display. // DisplayImage(i32X - (SPIDER_WIDTH / 2), i32Y - (SPIDER_HEIGHT / 2), g_pui8SpiderBlankImage); // // Indicate that this spider is not alive. // HWREGBITW(&g_ui32SpiderAlive, i32Spider) = 0; // // Delete the current task. This should never return. // vTaskDelete(NULL); // // In case it does return, loop forever. // while(1) { } } // // Enter a critical section while the next move for the spider is // determined. Having more than one spider trying to move at a time // (via preemption) would make the collision detection check fail. // taskENTER_CRITICAL(); // // Move the spider. // i32X += g_pi32SpiderStepX[ui32Dir]; i32Y += g_pi32SpiderStepY[ui32Dir]; // // See if the spider has cross the boundary of its area, if it has // collided with another spider, or if random chance says that the // spider should turn despite not having collided with anything. // if((i32X < SPIDER_MIN_X) || (i32X > SPIDER_MAX_X) || (i32Y < SPIDER_MIN_Y) || (i32Y > SPIDER_MAX_Y) || (SpiderCollide(i32Spider, i32X, i32Y) != -1) || (RandomNumber() < 0x08000000)) { // // Undo the previous movement of the spider. // i32X -= g_pi32SpiderStepX[ui32Dir]; i32Y -= g_pi32SpiderStepY[ui32Dir]; // // Get a random number to determine the turn to be made. // ui32Temp = RandomNumber(); // // Determine how to turn the spider based on the random number. // Half the time the spider turns to the left and half the time it // turns to the right. Of each half, it turns a quarter of a turn // 12.5% of the time and an eighth of a turn 87.5% of the time. // if(ui32Temp < 0x10000000) { ui32Dir = (ui32Dir + 2) & 7; } else if(ui32Temp < 0x80000000) { ui32Dir = (ui32Dir + 1) & 7; } else if(ui32Temp < 0xf0000000) { ui32Dir = (ui32Dir - 1) & 7; } else { ui32Dir = (ui32Dir - 2) & 7; } } // // Update the position of the spider. // g_pi32SpiderX[i32Spider] = i32X; g_pi32SpiderY[i32Spider] = i32Y; // // Exit the critical section now that the spider has been moved. // taskEXIT_CRITICAL(); // // Have the display task draw the spider at the new position. Since // there is a one pixel empty border around all the images, and the // position of the spider is incremented by only one pixel, this also // erases any traces of the spider in its previous position. // DisplayImage(i32X - (SPIDER_WIDTH / 2), i32Y - (SPIDER_HEIGHT / 2), g_ppui8SpiderImage[(ui32Dir * 2) + ui32Image]); // // Toggle the spider animation index. // ui32Image ^= 1; // // Delay this task for an amount of time based on the direction the // spider is moving. // vTaskDelay(g_pui32SpiderDelay[ui32Dir & 1]); // // Add the new tick count to the random entropy pool. // RandomAddEntropy(xTaskGetTickCount()); // // Reseed the random number generator. // RandomSeed(); } }
//***************************************************************************** // // Handles the SysTick timeout interrupt. // //***************************************************************************** void SysTickIntHandler(void) { unsigned long ulData, ulDelta; // // Increment the tick count. // g_ulTickCount++; // // Indicate that a timer interrupt has occurred. // HWREGBITW(&g_ulFlags, FLAG_CLOCK_TICK) = 1; // // Increment the screen update count. // g_ucScreenUpdateCount++; // // See if 1/30th of a second has passed since the last screen update. // if(g_ucScreenUpdateCount == (CLOCK_RATE / 30)) { // // Restart the screen update count. // g_ucScreenUpdateCount = 0; // // Request a screen update. // HWREGBITW(&g_ulFlags, FLAG_UPDATE) = 1; } // // Update the music/sound effects. // AudioHandler(); // // Increment the application update count. // g_ucAppUpdateCount++; // // See if 1/100th of a second has passed since the last application update. // if(g_ucAppUpdateCount != (CLOCK_RATE / 100)) { // // Return without doing any further processing. // return; } // // Restart the application update count. // g_ucAppUpdateCount = 0; // // Run the Ethernet handler. // EnetTick(10); // // Read the state of the push buttons. // ulData = (GPIOPinRead(GPIO_PORTE_BASE, (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)) | (GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1) << 3)); // // Determine the switches that are at a different state than the debounced // state. // ulDelta = ulData ^ g_ucSwitches; // // Increment the clocks by one. // g_ucSwitchClockA ^= g_ucSwitchClockB; g_ucSwitchClockB = ~g_ucSwitchClockB; // // Reset the clocks corresponding to switches that have not changed state. // g_ucSwitchClockA &= ulDelta; g_ucSwitchClockB &= ulDelta; // // Get the new debounced switch state. // g_ucSwitches &= g_ucSwitchClockA | g_ucSwitchClockB; g_ucSwitches |= (~(g_ucSwitchClockA | g_ucSwitchClockB)) & ulData; // // Determine the switches that just changed debounced state. // ulDelta ^= (g_ucSwitchClockA | g_ucSwitchClockB); // // See if any switches just changed debounced state. // if(ulDelta) { // // Add the current tick count to the entropy pool. // RandomAddEntropy(g_ulTickCount); } // // See if the select button was just pressed. // if((ulDelta & 0x10) && !(g_ucSwitches & 0x10)) { // // Set a flag to indicate that the select button was just pressed. // HWREGBITW(&g_ulFlags, FLAG_BUTTON_PRESS) = 1; } }