#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(); } if (last_button_check + 10 < millis() || last_button_check > millis()) { handle_buttons(); last_button_check = millis(); } if (last_position_save + 10000 < millis() || last_position_save > millis()) { current_playlist.save_current_position(audio.getFilePos()); last_position_save = millis(); //Serial.println(pm->pp_to_String().c_str()); } } void Controller::handle_buttons() { if (is_button_pressed(PIN_BTN_VOL_UP)) { log_i("BTN_VOL_UP pressed"); uint8_t vol = min(audio.getVolume()+2, 21); log_d("Setting new volume %d", vol); audio.setVolume(vol); } else if (is_button_pressed(PIN_BTN_VOL_DOWN)) { log_i("BTN_VOL_DOWN pressed"); uint8_t vol; if ((vol = audio.getVolume()) >= 3) { vol -= 2; } else { vol = 1; } log_d("Setting new volume %d", vol); audio.setVolume(vol); } else if (is_button_pressed(PIN_BTN_TRACK_NEXT)) { log_i("BTN_TRACK_NEXT pressed"); next_track(); } else if (is_button_pressed(PIN_BTN_TRACK_PREV)) { log_i("BTN_TRACK_PREV pressed"); 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); String data = read_rfid_data(); play(s_uid, data.indexOf("[random]")>=0); } rfid->PICC_HaltA(); } } } } String Controller::read_rfid_data() { log_v("read_rfid_data() running..."); MFRC522::StatusCode status; MFRC522::PICC_Type type = rfid->PICC_GetType(rfid->uid.sak); uint16_t pageStart = 0; uint16_t pages = 4; uint16_t pageSize = 1; switch(type) { case MFRC522Constants::PICC_TYPE_MIFARE_MINI: case MFRC522Constants::PICC_TYPE_MIFARE_1K: case MFRC522Constants::PICC_TYPE_MIFARE_4K: { log_v("Trying to authenticate Mifare card."); MFRC522::MIFARE_Key key = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; status = rfid->PCD_Authenticate(MFRC522Constants::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &rfid->uid); if (status == MFRC522Constants::STATUS_OK) { log_v("Authentication succeeded."); } else { log_v("Authentication failed. Trying to read anyway."); } pageStart = 4; break; } case MFRC522Constants::PICC_TYPE_MIFARE_UL: log_v("PICC type is Mifare Ultralight. No authentication necessary."); pages = 16; pageSize = 4; break; default: log_v("Unexpected rfid card type %s. Trying to read anyway.", MFRC522Debug::PICC_GetTypeName(type)); } String data = ""; for (uint8_t block=pageStart; blockMIFARE_Read(block, buffer, &byte_count); if (status != MFRC522Constants::STATUS_OK) { log_d("MIFARE_Read() failed: %s\n", String(MFRC522Debug::GetStatusCodeName(status)).c_str()); continue; } for (int i=0; i<16; i++) { if (buffer[i]>=0x20 && buffer[i]<0x7F) data.concat((char)buffer[i]); } } rfid->PCD_StopCrypto1(); log_v("Read rfid data: '%s'", data.c_str()); return data; } void Controller::play(String rfid_id, bool shuffle) { if (!rfid_id.equals(current_playlist.get_rfid_id())) { if (pm->has_playlist(rfid_id)) { current_playlist = pm->get_playlist(rfid_id); if (shuffle) { log_i("Shuffling the playlist."); current_playlist.shuffle(); } play(); } else { Serial.printf("There is no playlist for rfid_id %s\n", rfid_id.c_str()); // This is working more or less, but downloading files is really, REALLY slow. (About 4 minutes for 10 MBytes). //download_album(rfid_id); audio.connecttoFS(SD, "/system/sys_unknown_card.mp3"); } } else { if (!audio.isRunning()) { play(); } } } void Controller::play() { String file = current_playlist.get_current_file_name(); if (file.startsWith("/")) { log_i("Playing file %s via connecttoFS", file.c_str()); audio.connecttoFS(SD, file.c_str(), current_playlist.get_current_time()); } else if (file.startsWith("http")) { log_i("Playing URL %s via connecttohost", file.c_str()); audio.connecttoFS(SD, "/system/sys_connecting.mp3"); while (audio.isRunning()) { yield(); audio.loop(); } audio.connecttohost(file.c_str()); } } void Controller::next_track() { if (current_playlist.next_track()) { play(); } } void Controller::prev_track() { uint32_t time = audio.getAudioCurrentTime(); log_d("prev_track() called. getAudioCurrentTime() returns %d", time); if (time >= 5) { log_d("Restarting current track."); current_playlist.restart(); play(); } else { if (current_playlist.prev_track()) { play(); } } } void Controller::stop() { if (audio.isRunning()) { current_playlist.set_current_time(audio.stopSong()); } } bool Controller::is_button_pressed(uint8_t pin) { //log_d("Button %d state is %d", pin, digitalRead(pin)); if (!digitalRead(pin)) { // Button is pressed - let's debounce it. if (button_pressed == pin) { if (button_pressed_since + 150 < millis() && !button_already_processed) { button_already_processed = true; return true; } } else { button_pressed = pin; button_pressed_since = millis(); button_already_processed = false; } } else { if (button_pressed == pin) { button_pressed = 0; } } return false; } void Controller::eof_mp3(String info) { log_d("Handling eof. Keep playing until the file is finished."); while(audio.isRunning()) { audio.loop(); yield; } if (info.startsWith("sys_")) { log_d("File ending was a system audio file. Not running next_track."); } else { next_track(); } }