States: LED_IDLE, LED_PLAYING, LED_WRITING
Module Variables:
currentHit // global, starts at 0
currentTimeLeft = GAME_DURATION (60)
DeferralQueue // for deferred ES_ADD_CHAR events
Init
set MyPriority = given priority
set CurrentState = LED_IDLE
post ES_INIT to DisplayService
Post
enqueue ThisEvent to DisplayService’s queue
Run
switch(CurrentState)
case LED_IDLE:
if ThisEvent is ES_ADD_CHAR
ch = event parameter
scroll display buffer by 1 character width
add ch to right side of display buffer
set CurrentState = LED_WRITING
post ES_UPDATE_DISPLAY to DisplayService with param = 0 // will return to IDLE
end if
if ThisEvent is ES_CALIB_DONE
clear display buffer
// show "HIT:XX" using currentHit
draw "HIT:" label
draw currentHit as two digits after "HIT:"
// show "TIME:XX" using currentTimeLeft
draw "TIME:" label
draw currentTimeLeft as two digits after "TIME:"
set CurrentState = LED_WRITING
post ES_UPDATE_DISPLAY to DisplayService with param = 1 // will return to PLAYING
start DISPLAY_TIMER for 1 second
end if
case LED_PLAYING:
if ThisEvent is ES_TIMEOUT for DISPLAY_TIMER
if currentTimeLeft == 0
post ES_GAMEOVER_TIMEOUT to GameLogicFSM
post ES_GAMEOVER_TIMEOUT to AvatarService
post ES_GAMEOVER_TIMEOUT to ObstacleService
reset currentTimeLeft to GAME_DURATION
clear display buffer
draw "GAMEOVER" text
set CurrentState = LED_WRITING
post ES_UPDATE_DISPLAY to DisplayService with param = 0 // go back to IDLE
else
decrement currentTimeLeft by 1
update the two time digits on the display to show currentTimeLeft
set CurrentState = LED_WRITING
post ES_UPDATE_DISPLAY to DisplayService with param = 1 // go back to PLAYING
restart DISPLAY_TIMER for 1 second
end if
end if
if ThisEvent is ES_COLLISION_DETECTED
increment currentHit by 1
update the two hit digits on the display to show currentHit
set CurrentState = LED_WRITING
post ES_UPDATE_DISPLAY to DisplayService with param = 1 // go back to PLAYING
end if
if ThisEvent is ES_NO_INPUT_TIMEOUT
reset currentTimeLeft to GAME_DURATION
clear display buffer
draw "NO INPUT" text
set CurrentState = LED_WRITING
post ES_UPDATE_DISPLAY to DisplayService with param = 0 // go back to IDLE
end if
case LED_WRITING:
if ThisEvent is ES_ADD_CHAR
// don't interrupt animation; save for later
defer ThisEvent into DeferralQueue
end if
if ThisEvent is ES_UPDATE_DISPLAY
// advance display refresh by one step (one row / slice)
finished = DM_TakeDisplayUpdateStep()
if finished == false
// still more rows to update; keep animating
repost ES_UPDATE_DISPLAY to DisplayService with same param
else
if param == 0
set CurrentState = LED_IDLE
recall any deferred events from DeferralQueue
else if param == 1
set CurrentState = LED_PLAYING
end if
end if
end if