Continuing
Design
Start
Init ports, options,
variables, and enter
Startup state
At this point, I often prefer to set
aside my prototype’s code (still saving a
copy), and start over with a blank file.
When I first heard that some software
developers work this way, I thought it
was crazy.
Since my prototype was quickly
cobbled together without exhaustive
planning, starting over this early in the
process can actually lead to simpler
code with fewer workarounds caused
by design changes. Of course, some of
the prototype code can be reused if it
already works well.
There are many ways to set up the
main loop of a program. For any project
that has multiple modes of operation, I
like to make the main loop run all of
the common parts — such as the display
and input in this project — and then call
a different function depending on a
single variable that represents the
current state, or a high level
representation of what the device
should be doing.
This means that the code for any
state can use the values of variables
that are maintained by the common
code. The current state’s code will run
for each pass of the main loop, and
that code decides when to change to
another state.
For example, the startup sequence
of this project sets a pattern for the
display and checks the variables
representing the switches, but it lets the
main loop actually write to the display and read the pins
connected to the switches.
When a button is pressed, the startup sequence code
changes the state variable to the next state which sets up
the display randomly. That state only runs once and then
changes the state variable again to the “running” state
(which handles the game logic until the user wins).
Designing the main program can be overwhelming,
but breaking out the major states can help to simplify it. If
you are familiar with flow charts — even in the informal
way that non-programmers use them — it can be helpful
N
N
N
N
Read switch states
repeatedly & store
in scratch memory
FIGURE 3. Informal flow
chart for the main loop. I
usually sketch this out on
paper and do not follow
strict flow chart rules —
like keeping each box as
a single operation.
Update previous state
of switches & debounce
new input
Running
state?
Y
Check which
switch states
changed & toggle
display variables
as needed
Win seq
state?
Update display, if
counter is high enough,
change back to startup
display state
Y
Startup
display
state?
Update display, if key is
released, change to
game setup state Y
Game setup
state?
Read timer, reset
display & variables,
N
All LEDs
off?
Change to win
sequence state
Use display variables to update LEDs,
using counter to skip some, to make a
fading effect when necessary
to draw out a high-level view of how the software will
work. (Check out the example in Figure 3.) Or, writing out
a list of what the main program should do on paper and
drawing arrows to show loops or decisions can help in
planning.
After you have the basic flow drawn out, writing the
code to implement it becomes more mechanical, so there
is a lower chance for errors than coding on the fly. If you
come to a point where it is unclear what to do next, it can
help to just write out some instructions and step through
what should happen in different situations.
52 SERVO 06.2010