/**
Vision Coach for Arduino.
Select the button asigned to the lit LED:
After starting the simulation, click anywhere in the diagram to focus it.
Then press any key between 1 and 8 to play the buttons (1 is the lowest note,
8 is the highest).
Copyright (C) 2024, Mark Fogliani. Released under the MIT License.
*/
#include "pitches.h"
#define SPEAKER_PIN 7
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
const uint8_t ledPins[] = {8, 9, 10, 11, 12, 13};
const uint16_t ledIndexes[] = {23, 22, 21, 13, 12, 11}; // Led indexes. 1st digit = row, 2nd digit = column
const uint8_t buttonPins[] = { 2 };
const int buttonTones[] = {
NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4,
NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5
};
const int numTones = sizeof(buttonPins) / sizeof(buttonPins[0]);
// Define game programs
uint8_t gameProgramKeys[] = {1, 2, 3};
uint16_t gameIndexes1[] = {11, 12, 13}; // insert a game as an array of pin indexes
uint16_t gameindexes2[] = {13, 12, 11, 12, 13};
uint16_t gameIndexes3[] = {11, 22, 13, 23, 12, 21};
struct GAMES
{
uint16_t *gameIndexes;
uint16_t numElements;
};
int gameKeys[] = {1, 2, 3}; // number to enter to run a game gameKey minus 1
GAMES gameMatrix[] =
{
{gameIndexes1, NUMELEMENTS(gameIndexes1)},
{gameindexes2, NUMELEMENTS(gameindexes2)},
{gameIndexes3, NUMELEMENTS(gameIndexes3)},
};
// Function below requires debugging
uint16_t* mapIndexesToPins(const uint8_t* pinMap, const uint16_t* indexesMap, const uint16_t* indexesSequence,
uint16_t nIndexesSequence, uint16_t nPins) {
uint16_t* pinsSequence = new uint16_t[nIndexesSequence];
//Serial.print("Number of elements in index sequence is ");
//Serial.println(nIndexesSequence);
//Serial.print("Number of elements in index map is ");
//Serial.println(nPins);
for (uint16_t iSeq = 0; iSeq < nIndexesSequence; iSeq++) {
bool found = false;
//Serial.print("Current index in sequence is ");
//Serial.println(indexesSequence[iSeq]);
for (uint16_t iMap = 0; iMap < nPins; iMap++) {
//Serial.print(" Current index in map is ");
//Serial.println(indexesMap[iMap]);
if (indexesSequence[iSeq] == indexesMap[iMap]) {
pinsSequence[iSeq] = pinMap[iMap];
found = true;
break;
}
}
if (!found) {
Serial.print("Sequence pin index = ");
Serial.print(indexesSequence[iSeq]);
Serial.println(" was not found in the pin map");
delete[] pinsSequence;
return nullptr;
}
}
return pinsSequence;
}
// SETUP
void setup() {
Serial.begin(9600);
for (uint8_t i = 0; i < 6; i++) {
pinMode(ledPins[i], OUTPUT);
}
pinMode(buttonPins[0], INPUT_PULLUP);
pinMode(SPEAKER_PIN, OUTPUT);
/* debug here
Serial.println(sizeof(game1));
Serial.println(sizeof(game2));
gameMatrix[gameKey].numElements
*/
uint16_t gameKey = 1;
uint16_t* gamePins = mapIndexesToPins(ledPins, ledIndexes, gameMatrix[gameKey].gameIndexes,
gameMatrix[gameKey].numElements, NUMELEMENTS(ledPins));
Serial.println("LED pins:");
for (uint16_t i = 0; i < NUMELEMENTS(ledPins); i++){
Serial.println(ledPins[i]);
}
Serial.println("game index - game pin:");
for (uint16_t i = 0; i < gameMatrix[gameKey].numElements; i++){
Serial.print("index: ");
Serial.print(gameMatrix[gameKey].gameIndexes[i]);
Serial.print(" - pin:");
Serial.println(gamePins[i]);
}
} // end setup
/**
Plays a hooray sound whenever the user finishes a level
*/
void playLevelUpSound() {
tone(SPEAKER_PIN, NOTE_E4);
delay(150);
tone(SPEAKER_PIN, NOTE_G4);
delay(150);
tone(SPEAKER_PIN, NOTE_E5);
delay(150);
tone(SPEAKER_PIN, NOTE_C5);
delay(150);
tone(SPEAKER_PIN, NOTE_D5);
delay(150);
tone(SPEAKER_PIN, NOTE_G5);
delay(150);
noTone(SPEAKER_PIN);
};
/**
Lights the given LED and plays a suitable tone
*/
void lightLedAndPlayTone(byte ledIndex) {
digitalWrite(ledPins[ledIndex], HIGH);
tone(SPEAKER_PIN, buttonTones[ledIndex]);
delay(300);
/**digitalWrite(ledPins[ledIndex], LOW);*/
noTone(SPEAKER_PIN);
};
/**
Waits until the user pressed one of the buttons,
and returns the index of that button
*/
byte readButtons(byte ledOn) {
while (true) {
if (digitalRead(2) == HIGH) {
digitalWrite(ledPins[ledOn], LOW);
return;
}
}
delay(500);
};
/**
The main loop
*/
void loop() {
// Read game key from the keypad here
// Play a game
if (gameKey > 0){
gameIndex = gameKey - 1;
gameKey = 0
}
byte ledOn = 2;
lightLedAndPlayTone(ledOn);/**Turns on light and plays a tone*/
readButtons(ledOn);/** Stays in this routine until the correct button is pressed*/
Serial.println("Correct Button"); /** Prints message when correct button pressed*/
playLevelUpSound(); /** Plays tune when correct button pressed */
delay(500);
//The program will get trapped in this while(1) loop forever.
while(1) {
//do nothing in here
};
}