Decibel Express is implemented on a PIC32 microcontroller, using the Events & Services framework. There are four event-driven services running during the game, each having its own state machine:
Game Logic Service handles game state and microphone processing
Avatar Service drives the Conductor's servo
Obstacle Service drives the obstacle's servo
Display Service manages the LED matrix and game timer
Below is the breakdown of each service.
Game Logic Service handles the main mechanism of the game:
post events to scroll welcome message during idle state
sample input from the microphone for calibration and controlling the avatar as well as detect no input timeout (20 seconds)
control the token dispenser based on number of collisions (note: collision detection is done in an event checker)
Events received:
ES_START_BUTTON_PRESS from Check4Button event checker
ES_GAMEOVER_TIMEOUT from DisplayService
Events generated:
ES_ADD_CHAR to DisplayService
ES_CALIB_DONE to ObstacleService, DisplayService
ES_VOLUME_CHANGE to AvatarService
ES_NO_INPUT_TIMEOUT to GameLogicService, AvatarService, ObstacleService, DisplayService
Avatar service controls the height of our Conductor by converting the volume input from Game Logic Service to corresponding PWM signal for the servo motor. At the end of the game, the Conductor is returned to initial position.
Events received:
ES_START_BUTTON_PRESS from Check4Button event checker
ES_GAMEOVER_TIMEOUT from DisplayService
ES_NO_INPUT_TIMEOUT from GameLogicService
Obstacle service controls the rotation of the obstacle track using a continuous servo motor. At the beginning of the game after calibration is done, the service reads the potentiometer value. A single threshold is used to choose one of the two fixed speeds of the obstacle rotation. At the end of the game, the service stops the rotation.
Events received:
ES_CALIB_DONE, ES_NO_INPUT_TIMEOUT from GameLogicService
ES_GAMEOVER_TIMEOUT from DisplayService
The display service is responsible for updating the display with messages, time left, and hit count. Since the display service updates the remaining time every 1 second during the game, it also determines the game timeout (60 seconds) and posts the timeout event to the rest of the services.
Events received:
ES_ADD_CHAR, ES_CALIB_DONE, ES_NO_INPUT_TIMEOUT from GameLogicService
ES_COLLISION_DETECTED from Check4Collision event checker
Events generated:
ES_GAMEOVER_TIMEOUT to GameLogicFSM, AvatarService, ObstacleService
We check for three events:
Start button press (post ES_START_BUTTON_PRESS)
We only respond to this event if the game is in idle state.
Software debounce is used.
Potentiometer value change (post ES_POT_CHANGE)
This function is used mainly during development and debugging. In the game, the Obstacle Service reads the potentiometer value only once at the start of the game and players are not allowed to change the speed during the game.
Collision (post ES_COLLISION_DETECTED)
This function reads the IR distance sensor value every 50 ms. If the value is above a threshold, the sensor detects an object in close distance which means that our Conductor hits the obstacle. The display service then increments the hit count accordingly.
Depending on the chosen speed of the obstacle track, there is a delay period during which the sensor is inactive to ensure that we do not trigger the collision event more than once for the same obstacle.
Here we initialize all essential hardware (IO ports, PWM channels, ADC channels, SPI module, and display module).
Here we define all 4 services, corresponding timers, event types, and event checkers.
In this project, we also use the following libraries provided to the class or previously completed during lab assignments:
PIC32_SPI_HAL
PIC32_AD_Lib
PWM_PIC32
DM_Display