320 lines
8.2 KiB
C++
Executable File
320 lines
8.2 KiB
C++
Executable File
// === OVERVIEW ===
|
|
// Tape Deck player replacement
|
|
//
|
|
// VU meter --> OLED display
|
|
// Cassette player --> MP3 player
|
|
|
|
// === MP3 PLAYER ===
|
|
/***************************************************
|
|
DFPlayer - A Mini MP3 Player For Arduino
|
|
<https://www.dfrobot.com/product-1121.html>
|
|
|
|
***************************************************
|
|
This example shows the basic function of library for DFPlayer.
|
|
|
|
Created 2016-12-07
|
|
By [Angelo qiao](Angelo.qiao@dfrobot.com)
|
|
|
|
GNU Lesser General Public License.
|
|
See <http://www.gnu.org/licenses/> for details.
|
|
All above must be included in any redistribution
|
|
****************************************************/
|
|
|
|
/***********Notice and Trouble shooting***************
|
|
1.Connection and Diagram can be found here
|
|
<https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
|
|
2.This code is tested on Arduino Uno, Leonardo, Mega boards.
|
|
****************************************************/
|
|
|
|
#include "Arduino.h"
|
|
#include "SoftwareSerial.h"
|
|
#include "DFRobotDFPlayerMini.h"
|
|
#include "EEPROM.h"
|
|
|
|
#define PIN_EQ A1
|
|
#define PIN_CHROME 6
|
|
#define PIN_FORWARD 10
|
|
#define EEPROM_SONG_INDEX 1
|
|
#define SKIP_LIMIT 250
|
|
#define EEPROM_SKIP 2
|
|
|
|
SoftwareSerial mySoftwareSerial(9, 8); // RX, TX
|
|
DFRobotDFPlayerMini myDFPlayer;
|
|
void printDetail(uint8_t type, int value);
|
|
|
|
int song_index = 0;
|
|
unsigned long song_started = 0;
|
|
int files_max = -1;
|
|
bool skipping = false;
|
|
|
|
void setup_player()
|
|
{
|
|
pinMode(PIN_EQ, INPUT);
|
|
pinMode(PIN_CHROME, INPUT);
|
|
pinMode(PIN_FORWARD, INPUT);
|
|
analogReference(DEFAULT);
|
|
|
|
Serial.begin(9600);
|
|
while (!Serial && millis() < 2000) { delay(10); }
|
|
|
|
song_index = EEPROM.read(EEPROM_SONG_INDEX);
|
|
unsigned int song_skip = EEPROM.read(EEPROM_SKIP);
|
|
if (song_skip > SKIP_LIMIT) {
|
|
song_skip = 0;
|
|
}
|
|
song_index += song_skip;
|
|
if (song_index >= 255) {
|
|
song_index = 0;
|
|
}
|
|
|
|
Serial.println();
|
|
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
|
|
mySoftwareSerial.begin(9600);
|
|
if (!myDFPlayer.begin(mySoftwareSerial)) {
|
|
Serial.println(F("Unable to begin:"));
|
|
Serial.println(F("1.Please recheck the connection!"));
|
|
Serial.println(F("2.Please insert the SD card!"));
|
|
while(true){
|
|
delay(0);
|
|
}
|
|
}
|
|
Serial.println(F("DFPlayer Mini online."));
|
|
|
|
myDFPlayer.volume(20); //Set volume value. From 0 to 30
|
|
myDFPlayer.play(song_index+1); //Play the first mp3
|
|
do {
|
|
delay(100);
|
|
files_max = myDFPlayer.readFileCounts();
|
|
} while (files_max <= -1);
|
|
|
|
if (digitalRead(PIN_FORWARD) == 1) {
|
|
// FastForward
|
|
skipping = true;
|
|
while (true) {
|
|
delay(500);
|
|
if (digitalRead(PIN_FORWARD) == 1) {
|
|
song_skip = min(song_skip + 1, SKIP_LIMIT);
|
|
EEPROM.update(EEPROM_SKIP, song_skip);
|
|
Serial.print("Skipping +1 ... ");
|
|
} else {
|
|
Serial.print("Skipping +0 ... ");
|
|
}
|
|
if (song_index + song_skip >= files_max) {
|
|
song_index = 0;
|
|
song_skip = 0;
|
|
}
|
|
myDFPlayer.play(song_index + song_skip + 1);
|
|
}
|
|
}
|
|
|
|
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
|
|
|
|
if (files_max > 0 && song_index >= files_max) {
|
|
Serial.println("Song index out of bounds, skipping to next.");
|
|
nextSong();
|
|
}
|
|
|
|
song_started = millis();
|
|
}
|
|
|
|
int eq_now = DFPLAYER_EQ_NORMAL;
|
|
|
|
void loop_player()
|
|
{
|
|
static unsigned long eq_timer = millis();
|
|
|
|
if (millis() - eq_timer > 100) {
|
|
eq_timer = millis();
|
|
int eq_next = eq_now;
|
|
int eqChrome = digitalRead(PIN_CHROME);
|
|
if (eqChrome == 0) {
|
|
//analogReference(DEFAULT);
|
|
int eqRaw = analogRead(PIN_EQ);
|
|
//Serial.print("EQ: ");
|
|
//Serial.println(eqRaw);
|
|
if (eqRaw < 512) {
|
|
eq_next = DFPLAYER_EQ_BASS;
|
|
//Serial.println("EQ: Bass");
|
|
} else if (eqRaw < 900) {
|
|
eq_next = DFPLAYER_EQ_NORMAL;
|
|
//Serial.println("EQ: Normal");
|
|
} else {
|
|
eq_next = DFPLAYER_EQ_POP;
|
|
//Serial.println("EQ: POP");
|
|
}
|
|
} else {
|
|
eq_next = DFPLAYER_EQ_ROCK;
|
|
//Serial.println("EQ: Rock");
|
|
}
|
|
if (eq_now != eq_next) {
|
|
eq_now = eq_next;
|
|
myDFPlayer.EQ(eq_now);
|
|
}
|
|
}
|
|
|
|
if (myDFPlayer.available()) {
|
|
printDetail(myDFPlayer.readType(), myDFPlayer.read());
|
|
}
|
|
}
|
|
|
|
void nextSong() {
|
|
int files_max = myDFPlayer.readFileCounts();
|
|
song_index = (song_index + 1) % files_max;
|
|
EEPROM.update(EEPROM_SONG_INDEX, song_index);
|
|
EEPROM.update(EEPROM_SKIP, 0);
|
|
myDFPlayer.play(song_index + 1);
|
|
song_started = millis();
|
|
Serial.println("Next song...");
|
|
}
|
|
|
|
void printDetail(uint8_t type, int value){
|
|
switch (type) {
|
|
case TimeOut:
|
|
Serial.println(F("Time Out!"));
|
|
break;
|
|
case WrongStack:
|
|
Serial.println(F("Stack Wrong!"));
|
|
break;
|
|
case DFPlayerCardInserted:
|
|
Serial.println(F("Card Inserted!"));
|
|
break;
|
|
case DFPlayerCardRemoved:
|
|
Serial.println(F("Card Removed!"));
|
|
myDFPlayer.stop();
|
|
break;
|
|
case DFPlayerCardOnline:
|
|
Serial.println(F("Card Online!"));
|
|
myDFPlayer.start();
|
|
break;
|
|
case DFPlayerUSBInserted:
|
|
Serial.println("USB Inserted!");
|
|
break;
|
|
case DFPlayerUSBRemoved:
|
|
Serial.println("USB Removed!");
|
|
break;
|
|
case DFPlayerPlayFinished:
|
|
Serial.print(F("Number:"));
|
|
//Serial.print(value);
|
|
Serial.println(F(" Play Finished!"));
|
|
nextSong();
|
|
break;
|
|
case DFPlayerError:
|
|
Serial.print(F("DFPlayerError:"));
|
|
switch (value) {
|
|
case Busy:
|
|
Serial.println(F("Card not found"));
|
|
break;
|
|
case Sleeping:
|
|
Serial.println(F("Sleeping"));
|
|
break;
|
|
case SerialWrongStack:
|
|
Serial.println(F("Get Wrong Stack"));
|
|
break;
|
|
case CheckSumNotMatch:
|
|
Serial.println(F("Check Sum Not Match"));
|
|
break;
|
|
case FileIndexOut:
|
|
Serial.println(F("File Index Out of Bound"));
|
|
delay(1000);
|
|
song_index = 0;
|
|
myDFPlayer.play(song_index + 1);
|
|
break;
|
|
case FileMismatch:
|
|
Serial.println(F("Cannot Find File"));
|
|
break;
|
|
case Advertise:
|
|
Serial.println(F("In Advertise"));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// === DISPLAY ===
|
|
#include <SPI.h>
|
|
#include <Wire.h>
|
|
#include <Adafruit_GFX.h>
|
|
#include <Adafruit_SH110X.h>
|
|
|
|
#define PIN_VU A0
|
|
#define VU_SCALE 1
|
|
#define VU_WARN 700
|
|
#define VU_CRIT 900
|
|
#define VU_SLOWDOWN 10
|
|
#define VU_ATTACK 1
|
|
|
|
/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
|
|
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
|
|
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
|
|
|
|
#define SCREEN_WIDTH 128 // OLED display width, in pixels
|
|
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
|
|
#define OLED_RESET -1 // QT-PY / XIAO
|
|
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
|
|
|
void setup_display() {
|
|
//Serial.begin(9600);
|
|
|
|
delay(250); // wait for the OLED to power up
|
|
display.begin(i2c_Address, true); // Address 0x3C default
|
|
display.setContrast (0); // dim display
|
|
|
|
// Clear the buffer.
|
|
display.clearDisplay();
|
|
display.display();
|
|
|
|
display.setTextSize(2);
|
|
display.setTextColor(SH110X_WHITE);
|
|
display.setCursor(0, 20);
|
|
display.println(" UNIVERSUM");
|
|
display.setTextSize(1);
|
|
display.display();
|
|
delay(500);
|
|
display.clearDisplay();
|
|
}
|
|
|
|
void loop_display()
|
|
{
|
|
display.clearDisplay();
|
|
|
|
display.setTextSize(2);
|
|
display.setTextColor(SH110X_WHITE);
|
|
display.setCursor(35, 20);
|
|
unsigned long song_time = (millis() - song_started) / 1000;
|
|
char song_time_text[16];
|
|
sprintf(song_time_text, "%02d", song_time / 60);
|
|
display.print(song_time_text);
|
|
display.print(":");
|
|
sprintf(song_time_text, "%02d", song_time % 60);
|
|
display.println(song_time_text);
|
|
|
|
display.setTextSize(1);
|
|
display.setCursor(37, 50);
|
|
char song_index_text[16];
|
|
sprintf(song_index_text, "%03d", song_index+1);
|
|
display.print(song_index_text);
|
|
display.print(" / ");
|
|
char song_count_text[16];
|
|
sprintf(song_count_text, "%03d", files_max);
|
|
display.print(song_count_text);
|
|
|
|
display.display();
|
|
}
|
|
|
|
// === MAIN ===
|
|
|
|
void setup() {
|
|
setup_player();
|
|
setup_display();
|
|
}
|
|
|
|
void loop() {
|
|
loop_player();
|
|
loop_display();
|
|
}
|