i tried restructuring your code and partially testing it on my laptop
- the start/done button is used to start the test as well as indicate when setting the cell pattern is complete
- it uses a single byte value to represent the 6-bit braille cell
- a table associates button pins with optional LED pins
- button presses toggle bits in a single byte value representing the braille cell value as well as the corresponding LED
- the braille cell value for the selected character and pattern set by the buttons is a simple comparision
- the single byte braille cell value could be used to drive a shift register but i believe there are more than enough pins available
- button and LED code is substantially reduced and those files eliminated
- the ordering of functions is such that they are defined before use, hence loop() and setup() are at the bottom
void initDtmf ()
void playDTMF (uint8_t number, long duration) {
void chimeAll () {
void sendCommand ()
void playNext ()
void playTrack (int soundTrack) //play a selected track
void playbackVolume (int vol)
void resetLEDs ()
chkButs () {
void loop ()
void setup ()
i believe these changes changes both simplifiy (remove redunancy), make the code code easier to read (once you grok it) and make it easier to maintain
// braille game
// press button to start
// set 6 cell LEDs with 6 buttons
// press button when done or wait 12sec
#include <Arduino.h>
#include "SoftwareSerial.h"
SoftwareSerial Serial2 (9, 10); // RX, TX with voltage divider pin 10
// -----------------------------------------------------------------------------
// define button/led associations, 0 indicates no LED
enum { Off = HIGH, On = LOW };
struct ButLed {
byte PinBut;
byte PinLed;
byte butState;
}
butLeds [] = {
{ 2, A0 },
{ 3, A1 },
{ 4, A2 },
{ 5, A3 },
{ 6, A4 },
{ 7, A5 },
{ 8, 0 },
};
const int NbutLed = sizeof(butLeds)/sizeof(ButLed);
const int DoneBut = 6;
// -----------------------------------------------------------------------------
const unsigned long msecGameTime = 12500;
unsigned long msecGameStart;;
int gameMode;
int brailleChar;
struct Braille {
unsigned char cell;
char c;
}
braille [] = {
{ 0x01, 'a' },
{ 0x03, 'b' },
{ 0x09, 'c' },
{ 0x19, 'd' },
{ 0x11, 'e' },
{ 0x0B, 'f' },
{ 0x1B, 'g' },
{ 0x13, 'h' },
{ 0x0A, 'i' },
{ 0x1A, 'j' },
{ 0x05, 'k' },
{ 0x07, 'l' },
{ 0x0D, 'm' },
{ 0x1D, 'n' },
{ 0x15, 'o' },
{ 0x0F, 'p' },
{ 0x1F, 'q' },
{ 0x17, 'r' },
{ 0x0E, 's' },
{ 0x1E, 't' },
{ 0x25, 'u' },
{ 0x27, 'v' },
{ 0x3A, 'w' },
{ 0x2D, 'x' },
{ 0x3D, 'y' },
{ 0x35, 'z' },
{ 0x2F, '[' },
{ 0x3F, '\\' },
{ 0x37, ']' },
{ 0x2E, '^' },
};
const int Nbraille = sizeof(braille)/sizeof(Braille);
// -----------------------------------------------------------------------------
#include <Tone.h>
Tone freq1;
Tone freq2;
// Dial numbers 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 (To align with array 0)
const int DTMF_freq1[] = {
1209, 1336, 1477, 1209, 1336, 1477, 1209, 1336, 1477, 1336 };
const int DTMF_freq2[] = {
697, 697, 697, 770, 770, 770, 852, 852, 852, 941 };
// -------------------------------------
void initDtmf ()
{
freq1.begin (13); // 560 ohm resistor - resistor not used
freq2.begin (12); // 560 ohm resistor - resistor not used
}
// -------------------------------------
void playDTMF (uint8_t number, long duration) {
// printf (" %s: %d\n", __func__, number);
freq1.play (DTMF_freq1[number], duration);
freq2.play (DTMF_freq2[number], duration);
}
// -------------------------------------
void chimeAll () {
printf (" %s:\n", __func__);
uint8_t phone_number[] = { 0, 1, 2, 3, 4, 5, };
for (unsigned i = 0; i < sizeof (phone_number); i++) {
playDTMF (phone_number[i], 500);
delay (600);
}
}
// -----------------------------------------------------------------------------
byte commandLength; //length in bytes of command being sent
byte command[6]; //array that stores the bytes of the command
int16_t checkSum = 0; //checksum of command
// -------------------------------------
void sendCommand ()
{
printf (" %s:", __func__);
for (int q = 0; q < commandLength; q++) {
Serial2.write (command[q]);
#if 1
Serial.print (command[q], HEX);
#else
printf (" %02X", command[q]);
#endif
}
printf ("\n");
}
// -------------------------------------
void playNext ()
{
printf (" %s:\n", __func__);
command[0] = 0xAA; //first byte says it's a command
command[1] = 0x06;
command[2] = 0x00;
command[3] = 0xB0;
commandLength = 4;
sendCommand ();
}
// -------------------------------------
void playTrack (int soundTrack) //play a selected track
{
printf (" %s: %d\n", __func__, soundTrack);
//select track
command[0] = 0xAA; //first byte says it's a command
command[1] = 0x07;
command[2] = 0x02;
command[3] = (soundTrack >> 8) & 0xFF; //snh...track HIGH bit
command[4] = soundTrack & 0xFF; //SNL... track low bit
checkSum = 0;
for (int q = 0; q < 5; q++) {
checkSum += command[q];
}
command[5] = (checkSum & 0xFF); //SM check bit... low bit of the sum of all previous values
commandLength = 6;
sendCommand ();
}
// -------------------------------------
//sets the device volume...0 - 30
void playbackVolume (int vol)
{
printf (" %s:\n", __func__);
if (vol > 30) { //check within limits
vol = 30;
}
command[0] = 0xAA; //first byte says it's a command
command[1] = 0x13;
command[2] = 0x01;
command[3] = vol; //volume
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = (checkSum & 0xFF); //SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand ();
}
// -----------------------------------------------------------------------------
void resetLEDs ()
{
printf (" %s:\n", __func__);
for (int n = 0; n < NbutLed; n++) {
if (0 != butLeds [n].PinLed)
digitalWrite (butLeds [n].PinLed, Off);
}
}
// -----------------------------------------------------------------------------
// button monitor routine that toggles LED state and sets cellPattern
const int NoBut = -1;
int cellState;
int
chkButs () {
printf (" %s:\n", __func__);
for (int n = 0; n < NbutLed; n++) {
byte but = digitalRead (butLeds [n].PinBut);
if (butLeds [n].butState != but) { // state change
butLeds [n].butState = but;
delay (20); // debounce
if (LOW == but) { // pressed
int dot = 1 << n;
cellState ^= dot; // toggle dot
// set led to current dot state
digitalWrite (butLeds [n].PinLed, cellState & dot);
printf (" %s: %d pressed\n", __func__, n);
return n;
}
else
printf (" %s: %d released\n", __func__, n);
}
}
return NoBut;
}
// -----------------------------------------------------------------------------
void loop ()
{
printf ("loop: gameMode %d\n", gameMode);
unsigned long msec = millis ();
switch (gameMode) {
case 0: // start
resetLEDs ();
if (DoneBut == chkButs ())
gameMode = 1;
break;
case 1: // choose random braille letter
randomSeed (msec);
brailleChar = random (30);
printf (" braille char %d\n", brailleChar);
playTrack (brailleChar +1);
msecGameStart = msec;
gameMode = 3;
break;
case 3:
#define TrkCountdown 31
playTrack (TrkCountdown); // keeps repeating?
// wait until done or timeout
if (msec - msecGameStart >= msecGameTime || DoneBut == chkButs ())
gameMode = 4;
break;
case 4:
if (cellState == braille [brailleChar].cell)
playTrack (random (32, 41)); // play random success sound
else
playTrack (random (42, 51)); // play random fail sound
delay (8000); // wait for sound to finish
gameMode = 0;
break;
default:
break;
}
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
Serial2.begin (9600); // Start Software Serial
initDtmf ();
for (int n = 0; n < NbutLed; n++) {
// configure and capture each button state
pinMode (butLeds [n].PinBut, INPUT_PULLUP);
butLeds [n].butState = digitalRead (butLeds [n].PinBut);
// check if valid LED
if (0 == butLeds [n].PinLed)
continue;
// configure and show the each LED works
pinMode (butLeds [n].PinLed, OUTPUT);
digitalWrite (butLeds [n].PinLed, On);
delay (500);
digitalWrite (butLeds [n].PinLed, Off);
delay (200);
}
}