// include SPI, MP3 and SD libraries
#define TEST
#ifdef TEST
// Do not use the swpcific hardware to play sound
// use Serial.println() instead
#else
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
// define the pins used
//#define CLK 13 // SPI Clock, shared with SD card
//#define MISO 12 // Input data, from VS1053/SD card
//#define MOSI 11 // Output data, to VS1053/SD card
// Connect CLK, MISO and MOSI to hardware SPI pins.
// See http://arduino.cc/en/Reference/SPI "Connections"
// These are the pins used for the breakout example
#define BREAKOUT_RESET 9 // VS1053 reset pin (output)
#define BREAKOUT_CS 10 // VS1053 chip select pin (output)
#define BREAKOUT_DCS 8 // VS1053 Data/command select pin (output)
// These are the pins used for the music maker shield
#define SHIELD_RESET -1 // VS1053 reset pin (unused!)
#define SHIELD_CS 7 // VS1053 chip select pin (output)
#define SHIELD_DCS 6 // VS1053 Data/command select pin (output)
// These are common pins between breakout and shield
#define CARDCS 4 // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3 // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
// create breakout-example object!
//Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);
// create shield-example object!
Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
#endif
// Structure that holds the relevant playlist data
// It provides the functions to increment the index
// and to restart from the beginning
struct PlayListType {
String Name; // Name of the playlist (for humans)
int StartFileNo; // The number of the first file in the list
int MaxFiles; // The numbers of sequential files in the list
int LastFilePlayed; // The last index (offset to StartFileNo) played
void Increment(); // Function that increments the index and avoids "overflow"
void Restart(); // Function to reset the index to zero
};
// This defines what the Increment() function does
// Inside this function the variables of the struct
// can be used directly
void PlayListType::Increment(){
LastFilePlayed += 1;
if (LastFilePlayed >= MaxFiles) { LastFilePlayed = 0;};
}
// Just to avoid that you have to cope with struct content
// in your sketch directly.
// MainTitle.Reset();
// is identical to
// MainTitle.LastFilePlayed = 0;
void PlayListType::Restart(){
LastFilePlayed = 0;
}
// Now the declaration of the playlists with
// PlayListType PlayListName {"Name", StartFileNo, MaxFiles, LastFilePlayed};
PlayListType ShieldKlingon {"ShieldsKlingon", 8, 2 , 0};
PlayListType ViewScreen {"ViewScreen", 1, 2, 0};
PlayListType Astrogator {"Astrogator", 3, 2, 0};
PlayListType SensorTrack {"SensorTrack", 17, 4, 0};
PlayListType SickbayTrack {"SickbayTrack", 21, 4, 0};
PlayListType EngineeringTrack {"EngineeringTrack", 31, 4, 0};
PlayListType TransporterTrack {"TransporterTrack", 25, 3, 0};
PlayListType DestructTrack {"DestructTrack", 35, 4, 0};
PlayListType MainTitle {"MainTitle", 28, 3, 0};
PlayListType MusicTrack {"MusicTrack", 39, 22, 0};
PlayListType BridgeTrack {"BridgeTrack", 9, 8, 0};
// This function takes one of those playlist structures and
// creates the appropriate filename "online"
// and uses the common function startPlayingFile()
void playList(PlayListType &pl, boolean restart){
if (restart) pl.Restart();
playFile(pl.StartFileNo+pl.LastFilePlayed);
pl.Increment();
}
// Begin of Struct to handle the switches
struct SwitchType {
byte No;
byte pin;
boolean state = false;
void setPin(byte aPin);
boolean changed();
unsigned long lastChange = 0;
byte lastState;
bool changeOk = false;
};
//define the Switch Type
void SwitchType::setPin(byte aPin){
pin = aPin;
pinMode(pin,INPUT_PULLUP);
lastState = digitalRead(pin);
}
//Define the SwitchType changed
boolean SwitchType::changed(){
byte actState = digitalRead(pin);
if (lastState != actState) {
lastState = actState;
lastChange = millis();
changeOk = true;
}
if (millis()-lastChange > 30 && changeOk){
changeOk = false;
state = !state;
return true;
} else return false;
}
// End of Struct to handle the switches
// Definition of Switches
const byte NoOfSwitches = 8;
SwitchType Switch[NoOfSwitches]; // Declaration of the switches
byte SwitchPin[NoOfSwitches] = {31, 33 ,35, 37, 39, 41, 43, 45}; // pins of the switches
enum {Red, Yellow, Blue, White, LtBlue, Green, Gray, Black}; // Enumeration that keeps track of the human switch naming
// Variable for the LEDs used
int leds[9] = {26,28,30,32,34,36,38,40,42};
int OPStatus = LOW;
void setup(){
Serial.begin(115200);
Serial.println("Adafruit VS1053 Simple Test");
#ifdef TEST
// No musicplayer, no SD card required
#else
if (! musicPlayer.begin()) { // initialise the music player
Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
while (1);
}
Serial.println(F("VS1053 found"));
if (!SD.begin(CARDCS)) {
Serial.println(F("SD failed, or not present"));
while (1); // don't do anything more
}
if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
Serial.println(F("DREQ pin is not an interrupt pin"));
#endif
// put your setup code here, to run once:
// setup Pin Modes
for (int i=0; i<NoOfSwitches;i++){
Switch[i].No = i+1;
Switch[i].setPin(SwitchPin[i]);
}
for (int jj; jj<sizeof(leds)/sizeof(int);jj++){
pinMode(leds[jj],OUTPUT);
delay(10);
}
}
void loop() {
handleSwitchRed();
handleSwitchYellow();
handleSwitchBlue();
handleSwitchWhite();
handleSwitchLtBlue();
handleSwitchGreen();
handleSwitchGray();
handleSwitchBlack();
if (Switch[Red].state) blinkLEDs();
else setLEDsTo(HIGH);
}
void setLEDsTo(byte state){
for (int i=0;i<sizeof(leds)/sizeof(int);i++)
digitalWrite(leds[i],state);
}
void blinkLEDs(){
static long int delayTime = 0;
static long int lastSwitchTime = 0;
static byte state = HIGH;
if (millis()-lastSwitchTime > delayTime) {
lastSwitchTime = millis();
delayTime = random(25,1000);
digitalWrite(leds[random(0,sizeof(leds)/sizeof(int))],state);
state = !state;
}
}
void playFile(int Number){
char aFilename[80];
sprintf(aFilename,"track%03d.mp3", Number);
#ifdef TEST
Serial.print("Playing ");
Serial.println(aFilename);
#else
if (musicPlayer.playingMusic) musicPlayer.stopPlaying();
musicPlayer.startPlayingFile(aFilename);
musicPlayer.setVolume(1,1);
#endif
}
void playFullFile(int Number){
char aFilename[80];
sprintf(aFilename,"track%03d.mp3", Number);
#ifdef TEST
Serial.print("Playing Fullfile ");
Serial.println(aFilename);
delay(5000); // Simulates a playbacktime of 5 seconds ...
#else
musicPlayer.playFullFile(aFilename);
#endif
}
void handleSwitchRed(){
if (Switch[Red].changed()) {
if (Switch[Red].state ) playFullFile(61);
else playFile(62);
};
}
void handleSwitchYellow(){
if (Switch[Yellow].changed()){
if (Switch[Yellow].state) {
if (Switch[Red].state) playList(ViewScreen,false);
else playList(ShieldKlingon,false);
}
else {
playFile(62);
}
}
}
void handleSwitchBlue(){
if (Switch[Blue].changed()){
if (Switch[Blue].state) {
if (Switch[Red].state) playList(Astrogator,false);
else playFile(5);
}
else {
playFile(62);
}
}
}
void handleSwitchWhite(){
if (Switch[White].changed()){
if (Switch[White].state) {
if (Switch[Red].state) playList(SensorTrack,false);
else playFile(6);
}
else {
playFile(62);
}
}
}
void handleSwitchLtBlue(){
if (Switch[LtBlue].changed()){
if (Switch[LtBlue].state) {
if (Switch[Red].state) playList(SickbayTrack,false);
else playList(EngineeringTrack,false);
}
else {
playFile(62);
}
}
}
void handleSwitchGreen(){
if (Switch[Green].changed()){
if (Switch[Green].state) {
if (Switch[Red].state) playList(TransporterTrack,false);
else playList(DestructTrack,false);
}
else {
playFile(62);
}
}
}
void handleSwitchGray(){
if (Switch[Gray].changed()){
if (Switch[Gray].state) {
if (Switch[Red].state) playList(MusicTrack,false);
else playList(MainTitle,false);
}
else {
playFile(62);
}
}
}
void handleSwitchBlack(){
if (Switch[Black].changed()){
if (Switch[Black].state) {
playList(BridgeTrack, false);
}
else {
playFile(62);
}
}
}