diff --git a/include/controller.h b/include/controller.h index 7b56efe..b615ad0 100644 --- a/include/controller.h +++ b/include/controller.h @@ -1,13 +1,25 @@ #pragma once #include +#include +#include +#include "esmp3.h" +#include "playlist.h" class Controller { private: void handle_buttons(); void handle_rfid(); + bool is_button_pressed(uint8_t pin); + Playlist current_playlist; + bool is_rfid_present = false; + unsigned long last_rfid_check = 0; public: void handle(); - + void next_track(); + void prev_track(); + void play(); + void play(String rfid_id); + void stop(); }; \ No newline at end of file diff --git a/include/esmp3.h b/include/esmp3.h index d17af5d..ad39985 100644 --- a/include/esmp3.h +++ b/include/esmp3.h @@ -1,11 +1,26 @@ #pragma once -#include "controller.h" -#define PIN_CS_SD 16 -#define PIN_CS_RFID 17 +#include "controller.h" +#include "playlist_manager.h" +#include + +#define PIN_CS_SD 22 +#define PIN_CS_RFID 21 + +#define PIN_BTN_VOL_UP 32 +#define PIN_BTN_VOL_DOWN 33 +#define PIN_BTN_TRACK_NEXT 34 +#define PIN_BTN_TRACK_PREV 35 #define I2S_DOUT 25 -#define I2S_BCLK 27 -#define I2S_LRC 26 +#define I2S_BCLK 26 +#define I2S_LRC 27 -extern Controller controller; \ No newline at end of file +class Controller; + +extern Controller controller; +extern Audio audio; +extern PlaylistManager* pm; +extern MFRC522* rfid; + +void save_audio_current_time(); \ No newline at end of file diff --git a/include/playlist.h b/include/playlist.h index 73691e3..4bd5731 100644 --- a/include/playlist.h +++ b/include/playlist.h @@ -7,9 +7,19 @@ class Playlist { private: std::vector files; uint8_t current_file = 0; - uint16_t current_time = 0; + uint32_t current_time = 0; + void set_current_position(uint8_t file, uint32_t position=0); + String rfid_id; public: + Playlist(String rfid_id=""); void add_file(String filename); void sort(); + String get_rfid_id(); + String get_current_file_name(); + bool next_track(); + bool prev_track(); + void restart(); + void set_current_time(uint32_t time); + uint32_t get_current_time(); }; diff --git a/include/playlist_manager.h b/include/playlist_manager.h index 551c40a..f8f5b31 100644 --- a/include/playlist_manager.h +++ b/include/playlist_manager.h @@ -16,6 +16,7 @@ class PlaylistManager { std::vector dirs; std::map map; Playlist get_playlist(String rfid_id); + bool has_playlist(String rfid_id); Playlist current_playlist; void set_audio_current_time(uint32_t time); }; \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 64fddb3..7b81aee 100644 --- a/platformio.ini +++ b/platformio.ini @@ -18,14 +18,16 @@ lib_deps = platform = espressif32 board = esp-wrover-kit framework = arduino -upload_speed = 115200 -build_flags = !./build_version.sh +upload_speed = 921600 +build_flags = -DCORE_DEBUG_LEVEL=5 -DCONFIG_ARDUHAL_LOG_COLORS=1 ; !./build_version.sh lib_deps = ${extra.lib_deps} esphome/ESP32-audioI2S@^2.1.0 -upload_port = 10.10.2.108 + computer991/Arduino_MFRC522v2@^2.0.1 +;upload_port = 10.10.2.108 monitor_speed = 115200 monitor_port = /dev/cu.usbserial-0001 +monitor_filters = time, esp32_exception_decoder [env:deploy] platform = espressif32 @@ -34,5 +36,6 @@ framework = arduino lib_deps = ${extra.lib_deps} esphome/ESP32-audioI2S@^2.1.0 + computer991/Arduino_MFRC522v2@^2.0.1 board_build.embed_txtfiles = src/index.html board_build.partitions = partitions.csv diff --git a/src/controller.cpp b/src/controller.cpp index f2e476d..9618c3e 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -1,13 +1,100 @@ #include "controller.h" +#include "esmp3.h" void Controller::handle() { - + if (last_rfid_check + 500 < millis() || last_rfid_check > millis()) { + handle_rfid(); + last_rfid_check = millis(); + } } void Controller::handle_buttons() { - + if (is_button_pressed(PIN_BTN_VOL_UP)) { + audio.setVolume(min(audio.getVolume()+1, 21)); + } else if (is_button_pressed(PIN_BTN_VOL_DOWN)) { + audio.setVolume(max(audio.getVolume()-1, 1)); + } else if (is_button_pressed(PIN_BTN_TRACK_NEXT)) { + next_track(); + } else if (is_button_pressed(PIN_BTN_TRACK_PREV)) { + prev_track(); + } } void Controller::handle_rfid() { - + if (is_rfid_present) { + byte buffer[2]; + byte buffer_size = 2; + MFRC522Constants::StatusCode status = rfid->PICC_WakeupA(buffer, &buffer_size); + if (status == MFRC522Constants::STATUS_OK) { + // Card is still present. + rfid->PICC_HaltA(); + } else { + Serial.printf("RFID status is %s\n", MFRC522Debug::GetStatusCodeName(status)); + is_rfid_present = false; + Serial.println("No more RFID card.\n"); + stop(); + } + } else { + if (rfid->PICC_IsNewCardPresent()) { + if (rfid->PICC_ReadCardSerial()) { + uint32_t uid = rfid->uid.uidByte[0]<<24 | rfid->uid.uidByte[1]<<16 | rfid->uid.uidByte[2]<<8 | rfid->uid.uidByte[3]; + Serial.printf("Found new rfid card with uid %x\n", uid); + is_rfid_present = true; + if (uid > 0) { + String temp = String(uid, HEX); + String s_uid = ""; + for (int i=0; i<(8-temp.length()); i++) { + s_uid.concat("0"); + } + s_uid.concat(temp); + play(s_uid); + } + rfid->PICC_HaltA(); + } + } + } +} + +void Controller::play(String rfid_id) { + if (!rfid_id.equals(current_playlist.get_rfid_id())) { + if (pm->has_playlist(rfid_id)) { + current_playlist = pm->get_playlist(rfid_id); + play(); + } else { + Serial.printf("There is no playlist for rfid_id %s\n", rfid_id.c_str()); + } + } else { + if (!audio.isRunning()) { + play(); + } + } +} + +void Controller::play() { + String file = current_playlist.get_current_file_name(); + Serial.printf("Playing file: %s\n", file.c_str()); + audio.connecttoFS(SD, file.c_str(), current_playlist.get_current_time()); +} + +void Controller::next_track() { + if (current_playlist.next_track()) { + play(); + } +} + +void Controller::prev_track() { + if (audio.getAudioCurrentTime() <= 5) { + current_playlist.restart(); + play(); + } else { + if (current_playlist.prev_track()) { + play(); + } + } +} + +void Controller::stop() { + if (audio.isRunning()) { + current_playlist.set_current_time(audio.stopSong()); + } } \ No newline at end of file diff --git a/src/esmp3.cpp b/src/esmp3.cpp index 1e3b830..96dfa3e 100644 --- a/src/esmp3.cpp +++ b/src/esmp3.cpp @@ -7,33 +7,53 @@ #include #include "esmp3.h" #include +#include +#include +#include +#include +#include +#include Controller controller; Audio audio; -Ticker ticker_save_audio_current_time; PlaylistManager* pm; +MFRC522* rfid; void setup() { + pinMode(PIN_CS_SD, OUTPUT); digitalWrite(PIN_CS_SD, HIGH); + pinMode(PIN_CS_RFID, OUTPUT); digitalWrite(PIN_CS_RFID, HIGH); Serial.begin(115200); WiFi.begin("Schlenz", "1410WischlingenPanda"); - Serial.print("Connecting to WiFi..."); + log_i("Connecting to WiFi..."); + uint8_t i=9; while(WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(500); + Serial.print(i); + Serial.print("... "); + delay(1000); + i--; + if (i==0) { + Serial.println("Could not connect to WiFi. Restarting in 1s."); + delay(1000); + ESP.restart(); + } } Serial.println(); Serial.print("Connected to WiFi. IP address: "); Serial.println(WiFi.localIP()); - ArduinoOTA.begin(); + Serial.println("Waiting for OTA..."); + for(int i=0; i<20; i++) { + ArduinoOTA.handle(); + delay(100); + } Serial.println("Initializing SPI..."); SPI.begin(); - SPI.setHwCs(false); - SPIMaster::initialize(); + //SPI.setHwCs(false); + //SPIMaster::initialize(); Serial.print("Initializing SD card..."); - SPIMaster::enable_sd(); - while(!SD.begin(14, SPI, 25000000)) { + //SPIMaster::enable_sd(); + while(!SD.begin(PIN_CS_SD, SPI, 25000000)) { for(int i=0; i<10; i++) { if(SPI.transfer(0xFF)==0xFF) break; delay(10); @@ -46,15 +66,29 @@ void setup() { Serial.println("Initializing PlaylistManager..."); pm = new PlaylistManager(); + Serial.println("Setting up rfid reader..."); + pinMode(PIN_CS_RFID, OUTPUT); + MFRC522DriverPin* pin = new MFRC522DriverPinSimple(PIN_CS_RFID); + MFRC522Driver* spi = new MFRC522DriverSPI(*pin); + rfid = new MFRC522(*spi); + rfid->PCD_Init(); + MFRC522Debug::PCD_DumpVersionToSerial(*rfid, Serial); + + Serial.println("Setting up buttons..."); + pinMode(PIN_BTN_VOL_UP, INPUT_PULLUP); + pinMode(PIN_BTN_VOL_DOWN, INPUT_PULLUP); + pinMode(PIN_BTN_TRACK_NEXT, INPUT_PULLUP); + pinMode(PIN_BTN_TRACK_PREV, INPUT_PULLUP); + Serial.println("Setting up audio..."); audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); audio.setVolume(15); audio.forceMono(true); - Serial.println("Setting up tickers..."); - ticker_save_audio_current_time.attach(5, save_audio_current_time); - Serial.println("Setup finished."); + + audio.setVolume(3); + audio.connecttospeech("Die Papabox ist nun einsatzbereit!", "de_DE"); } void loop() { @@ -63,6 +97,34 @@ void loop() { audio.loop(); } -void save_audio_current_time() { - pm->set_audio_current_time(audio.getAudioCurrentTime()); -} \ No newline at end of file +void audio_info(const char *info){ + Serial.print("info "); Serial.println(info); +} +void audio_id3data(const char *info){ //id3 metadata + Serial.print("id3data ");Serial.println(info); +} +void audio_eof_mp3(const char *info){ //end of file + Serial.print("eof_mp3 ");Serial.println(info); + controller.next_track(); +} +void audio_showstation(const char *info){ + Serial.print("station ");Serial.println(info); +} +void audio_showstreamtitle(const char *info){ + Serial.print("streamtitle ");Serial.println(info); +} +void audio_bitrate(const char *info){ + Serial.print("bitrate ");Serial.println(info); +} +void audio_commercial(const char *info){ //duration in sec + Serial.print("commercial ");Serial.println(info); +} +void audio_icyurl(const char *info){ //homepage + Serial.print("icyurl ");Serial.println(info); +} +void audio_lasthost(const char *info){ //stream URL played + Serial.print("lasthost ");Serial.println(info); +} +void audio_eof_speech(const char *info){ + Serial.print("eof_speech ");Serial.println(info); +} diff --git a/src/playlist.cpp b/src/playlist.cpp index d59c75e..4553afc 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -1,9 +1,61 @@ #include "playlist.h" +Playlist::Playlist(String id) { + rfid_id = id; +} + +String Playlist::get_rfid_id() { + return rfid_id; +} + void Playlist::add_file(String filename) { files.push_back(filename); } void Playlist::sort() { std::sort(files.begin(), files.end()); +} + +void Playlist::set_current_position(uint8_t file, uint32_t seconds) { + current_file = file; + current_time = seconds; +} + +String Playlist::get_current_file_name() { + if (current_file >= files.size()) { + Serial.printf("Requested a file number %d, which is not available in this playlist. Starting over.\n", current_file); + set_current_position(0); + } + return files[current_file]; +} + +bool Playlist::next_track() { + if (files.size() <= current_file + 1) { + Serial.println("next_track does not exist. Resetting playlist and returning false."); + set_current_position(0, 0); + return false; + } + set_current_position(current_file + 1, 0); + return true; +} + +bool Playlist::prev_track() { + if (current_file == 0) { + return false; + } + + set_current_position(current_file - 1, 0); + return true; +} + +void Playlist::restart() { + current_time = 0; +} + +void Playlist::set_current_time(uint32_t pos) { + current_time = pos; +} + +uint32_t Playlist::get_current_time() { + return current_time; } \ No newline at end of file diff --git a/src/playlist_manager.cpp b/src/playlist_manager.cpp index dc9f3da..1b4c2ee 100644 --- a/src/playlist_manager.cpp +++ b/src/playlist_manager.cpp @@ -64,18 +64,18 @@ Playlist PlaylistManager::get_playlist(String rfid_id) { Serial.printf("No known playlist for id %s.\n", rfid_id); return current_playlist; } else { - current_playlist = Playlist(); - String entry = map[rfid_id]; - if (entry.startsWith("/")) { - File dir = SD.open(entry); + current_playlist = Playlist(rfid_id); + String path = map[rfid_id]; + if (path.startsWith("/")) { + File dir = SD.open(path); while(File entry = dir.openNextFile()) { String filename = entry.name(); String ext = filename.substring(filename.length()-4); if (!entry.isDirectory() && !filename.startsWith(".") && ext.equals(".mp3")) { - Serial.printf("Adding %s to the list of files\n", filename); - current_playlist.add_file(filename); + Serial.printf("Adding %s to the list of files\n", (path + "/" + filename).c_str()); + current_playlist.add_file(path + "/" + filename); } entry.close(); } @@ -90,4 +90,8 @@ Playlist PlaylistManager::get_playlist(String rfid_id) { void PlaylistManager::set_audio_current_time(uint32_t time) { audio_current_time = time; +} + +bool PlaylistManager::has_playlist(String rfid_id) { + return map.count(rfid_id) == 1; } \ No newline at end of file