I have a variety of settings that are user-adjustable in my code:
setting name / possible settings:
gamePoints / 5, 11, 21
matchSize / 3, 5, 7, 9
playerSides / random, red-green, green-red
servingSide / random, left, right
sound / on, off
Currently, I am building this project as a state-machine, and I broke out each setting into a state, for example:
boolean sOSelectGamePoints = false; (sO is my notation for "state of")
boolean sOSelectMatchSize = false;
...
and I'm using arbitrary number values to represent the different setting values, for example:
byte gamePoints = 1;
// 0=5, 1=11, 2=21
As a result, I end up with a lot of different but nearly identical functions, for example:
selectGamePoints()
selectMatchSize()
...
Here is the relevant code:
// *** libraries to include ****
#include <EEPROM.h> // so we can save settings
// *** global variables ***
// pin declarations:
const byte chooseSettingButton = 2; // arduino pin 2
const byte adjustSettingButton = 3; // arduino pin 3
const byte startButton = 4; // arduino pin 4
// *** variables for the state-machine ***
boolean sOIntro = false;
boolean sOSelectGamePoints = false;
boolean sOSelectMatchSize = false;
boolean sOSelectPlayerSides = false;
boolean sOSelectServingSide = false;
boolean sOSelectSound = false;
// setting variables (default values):
byte gamePoints = 1;
// 0=5, 1=11, 2=21
// if modified, saved as byte #0 in EEPROM
byte matchSize = 1;
// 0=3, 1=5, 2=7, 3=9
// if modified, saved as byte #1 in EEPROM
byte playerSides = 0;
// 0=random, 1=red/green, 2=green/red
// if modified, saved as byte #2 in EEPROM
byte servingSide = 0;
// 0=random, 1=left, 2=right
// if modified, saved as byte #3 in EEPROM
byte sound = 0;
// 0=ON, 1=OFF
// if modified, saved as byte #4 in EEPROM
void setup() {
// set up pins:
pinMode(chooseSettingButton, INPUT);
pinMode(adjustSettingButton, INPUT);
pinMode(startButton, INPUT);
// prepping EEPROM (if need be):
// *** user adjustable ***
byte saveByte = 57; // a location within EEPROM
// must be >10 because we reserve those spots for user-settings
// *** user adjustable ***
byte saveByteValue = 137; // a random value to check for
// Change this value to ensure a flush of EEPROM
// check if this is the very first time running this program,
// and if so, flush EEPROM:
if(EEPROM.read(saveByte) != saveByteValue){
// then this is the first time we are running this code,
// and we need to default all other bytes:
for(int i=0; i< EEPROM.length(); i++){
EEPROM.write(i, 255); // 255 is default value
}
// set the saveByte:
EEPROM.write(saveByte, saveByteValue);
// this ensures that next time through the eeprom won't
// be flushed.
}
// load-in any saved settings if we have any:
if(EEPROM.read(0) != 255) // 255 = nope, anything else = yep
{
// load that saved option:
gamePoints = EEPROM.read(0);
}
if(EEPROM.read(1) != 255)
{
// load that saved option:
matchSize = EEPROM.read(1);
}
if(EEPROM.read(2) != 255)
{
// load that saved option:
playerSides = EEPROM.read(2);
}
if(EEPROM.read(3) != 255)
{
// load that saved option:
servingSide = EEPROM.read(3);
}
if(EEPROM.read(4) != 255)
{
// load that saved option:
sound = EEPROM.read(4);
}
// start us off:
sOIntro = true;
} // end of setup()
void loop() {
// Different States of the State-Machine:
// intro:
if(sOIntro) {
intro();
sOIntro = false;
}
// selectGamePoints:
if(sOSelectGamePoints) {
selectGamePoints();
sOSelectGamePoints = false;
}
// selectMatchSize:
if(sOSelectMatchSize) {
selectMatchSize();
sOSelectMatchSize = false;
}
// selectPlayerSides:
if(sOSelectPlayerSides) {
selectPlayerSides();
sOSelectPlayerSides = false;
}
// selectServingSide:
if(sOSelectServingSide) {
selectServingSide();
sOSelectServingSide = false;
}
// selectSound:
if(sOSelectSound) {
selectSound();
sOSelectSound = false;
}
} // end of loop()
void intro(){
// while the "choose setting", "start", and player button(s)
// remain un-pressed:
while (1){
// if the chooseSettingButton is pressed:
if(buttonEdgeDetectLow(chooseSettingButton)){
// go to:
// (change the state of)
sOSelectGamePoints = true;
// get out of the while-loop:
break;
}
}
} // end of intro
void selectGamePoints(){
// while the "choose setting" and "start" button remains
// un-pressed:
while (1){
// each time the adjustSetting button is pressed:
if(buttonEdgeDetectLow(adjustSettingButton)){
// cycle through the options:
// 0=5, 1=11, 2=21
// check if we are already at the end of the line:
if(gamePoints == 2){
// back to the start:
gamePoints = 0;
}
else{
// increment:
gamePoints ++;
}
}
// if the chooseSetting button is pressed:
if(buttonEdgeDetectLow(chooseSettingButton)){
// save to appropriate eeprom address:
EEPROM.write(0, gamePoints);
// go to:
// (change the state of)
sOSelectMatchSize = true;
// get out of the while-loop:
break;
}
// if the startButton is pressed:
if(buttonEdgeDetectLow(startButton)){
// save to appropriate eeprom address:
EEPROM.write(0, gamePoints);
// go to:
// (change the state of)
sOIntro = true;
// get out of the while-loop:
break;
}
}
} // end of selectGamePoints
void selectMatchSize(){
// while the "choose setting" and "start" button remains
// un-pressed:
while (1){
// each time the adjustSetting button is pressed:
if(buttonEdgeDetectLow(adjustSettingButton)){
// cycle through the options:
// 0=3, 1=5, 2=7, 3=9
// check if we are already at the end of the line:
if(matchSize == 3){
// back to the start:
matchSize = 0;
}
else{
// increment:
matchSize ++;
}
}
// if the chooseSetting button is pressed:
if(buttonEdgeDetectLow(chooseSettingButton)){
// save to appropriate eeprom address:
EEPROM.write(1, matchSize);
// go to:
// (change the state of)
sOSelectPlayerSides = true;
// get out of the while-loop:
break;
}
// if the startButton is pressed:
if(buttonEdgeDetectLow(startButton)){
// save to appropriate eeprom address:
EEPROM.write(1, matchSize);
// go to:
// (change the state of)
sOIntro = true;
// get out of the while-loop:
break;
}
}
} // end of selectMatchSize
// similar functions for all other user-adjustable settings.
My question to you guys:
Is there a better way for me to be writing this code, such that I don't have as much repetition?
Maybe the more streamlined solution involves structs, or typedef's, or pointers (?)
Maybe it involves consolidating my different states of settings into a single "setting" state?