tapedeck-player/tapedeck-player.ino
2022-06-04 19:15:17 +02:00

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();
}