diff --git a/include/controller.h b/include/controller.h index e36bf6e..21216c9 100644 --- a/include/controller.h +++ b/include/controller.h @@ -15,6 +15,10 @@ private: uint32_t _last_rfid_card_uid = 0; Player* _player; unsigned long _last_rfid_scan_at = 0; + String _serial_buffer = String(); + void _execute_serial_command(String cmd); + void _execute_command_ls(String path); + void _execute_command_help(); public: Controller(Player* p); void loop(); diff --git a/include/player.h b/include/player.h index 8f6592f..f8bd5aa 100644 --- a/include/player.h +++ b/include/player.h @@ -34,6 +34,7 @@ private: uint8_t index; uint32_t position; }; + void _check_system_sound(String filename); void _reset(); void _init(); void _wait(); @@ -45,7 +46,8 @@ private: void _refill(); bool _refill_needed(); void _flush_and_cancel(); - void _flush(uint bytes); + int8_t _get_endbyte(); + void _flush(uint count, int8_t fill_byte); void _set_last_track(const char* album, uint8_t track, uint32_t position); std::map _last_tracks; void _play_file(String filename, uint32_t offset); @@ -64,8 +66,9 @@ private: uint8_t _buffer[32]; String _playing_album; uint8_t _playing_index; + uint8_t _playing_album_songs; + uint32_t _current_play_position; uint _refills; - int8_t _end_byte; uint8_t _volume; uint16_t _stop_delay; uint32_t _skip_to; @@ -82,4 +85,5 @@ public: void stop(); bool loop(); void set_volume(uint8_t vol, bool save = true); + std::list ls(String path); }; diff --git a/src/controller.cpp b/src/controller.cpp index 651d5fc..5f7cd38 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -6,10 +6,13 @@ Controller::Controller(Player* p) { _rfid = new MFRC522(PIN_RC522_CS, MFRC522::UNUSED_PIN); SPIMaster::enable(PIN_RC522_CS); - Serial.println("Initializing MFRC522..."); + DEBUG("Initializing RC522..."); _rfid->PCD_Init(); - _rfid->PCD_DumpVersionToSerial(); + #ifdef SHOW_DEBUG + _rfid->PCD_DumpVersionToSerial(); + #endif SPIMaster::disable(); + INFO("RC522 initialized.\n"); } void Controller::loop() { @@ -38,39 +41,78 @@ uint32_t Controller::_get_rfid_card_uid() { void Controller::_check_rfid() { uint32_t uid = _get_rfid_card_uid(); - //Serial.printf("Found card: %08x\n", uid); if (uid != _last_rfid_card_uid) { - if (uid > 0) { - Serial.printf("New RFID card uid: %08x\n", uid); - // Play - String s_uid = String(uid, HEX); - _player->play_album(s_uid); - } else { - Serial.println("No more RFID card."); - // Stop - _player->stop(); - } - _last_rfid_card_uid = uid; + if (uid > 0) { + INFO("New RFID card uid: %08x\n", uid); + String s_uid = String(uid, HEX); + _player->play_album(s_uid); + } else { + INFO("No more RFID card."); + _player->stop(); + } + _last_rfid_card_uid = uid; } } void Controller::_check_serial() { if (Serial.available() > 0) { char c = Serial.read(); - if (c == 'n') { - _player->track_next(); - } else if (c=='p') { - _player->track_prev(); - } else if (c=='s') { - _player->stop(); - } else if (c=='+') { - _player->vol_up(); - } else if (c=='-') { - _player->vol_down(); - } else if (c==' ') { - _player->play_album("12345678"); - } else if (c=='q') { - _player->play_system_sound("12345678/Biene Maja.mp3"); + Serial.printf("%c", c); + if (c==10 || c==13) { + if (_serial_buffer.length()>0) { + _execute_serial_command(_serial_buffer); + _serial_buffer = String(); + } + } else { + _serial_buffer.concat(c); } } } + +void Controller::_execute_serial_command(String cmd) { + DEBUG("Executing command: %s", cmd.c_str()); + + if (cmd.equals("ls")) { + _execute_command_ls("/"); + } else if (cmd.startsWith("ls ")) { + _execute_command_ls(cmd.substring(3)); + } else if (cmd.startsWith("play ")) { + _player->play_album(cmd.substring(5)); + } else if (cmd.startsWith("sys ")) { + _player->play_system_sound(cmd.substring(4)); + } else if (cmd.equals("stop")) { + _player->stop(); + } else if (cmd.equals("help")) { + _execute_command_help(); + } else if (cmd.equals("-")) { + _player->vol_down(); + } else if (cmd.equals("+")) { + _player->vol_up(); + } else if (cmd.equals("p")) { + _player->track_prev(); + } else if (cmd.equals("n")) { + _player->track_next(); + } else { + ERROR("Unknown command: %s\n", cmd.c_str()); + } + return; +} + +void Controller::_execute_command_ls(String path) { + INFO("Listing contents of %s:\n", path.c_str()); + std::list files = _player->ls(path); + for(std::list::iterator it=files.begin(); it!=files.end(); it++) { + INFO(" %s\n", (*it).c_str()); + } +} + +void Controller::_execute_command_help() { + INFO("Valid commands are:"); + INFO(" help - Displays this help\n"); + INFO(" ls [dir] - Lists the contents of [dir] or, if not given, of /\n"); + INFO(" play [id] - Plays the album with the given id\n"); + INFO(" sys [file]- Plays the file as system sound\n"); + INFO(" stop - Stops playback\n"); + INFO(" - / + - Decrease or increase the volume\n"); + INFO(" p / n - Previous or next track\n"); +} diff --git a/src/main.cpp b/src/main.cpp index ed884b6..f0c7efe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,23 +12,26 @@ Player* player; void setup() { delay(500); Serial.begin(74880); - Serial.println("Starting."); + INFO("Starting.\n"); + INFO("Initializing...\n"); - Serial.println("Setting up SPI..."); + DEBUG("Setting up SPI...\n"); SPI.begin(); SPIMaster::init(); + INFO("SPI initialized.\n"); + DEBUG("Setting up SD card...\n"); SPIMaster::enable(PIN_SD_CS); if (SD.begin(PIN_SD_CS)) { - Serial.println("SD card initialized."); + INFO("SD card initialized.\n"); } else { - Serial.println("Could not initialize SD card. Halting."); + ERROR("Could not initialize SD card. Halting.\n"); while(1); } player = new Player(); controller = new Controller(player); - - //player->play_album("12345678"); + + INFO("Initialization completed.\n"); } void loop() { diff --git a/src/player.cpp b/src/player.cpp index 57c57af..2e4fcc4 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -27,22 +27,22 @@ void Player::_init() { _reset(); uint16_t result = _read_control_register(SCI_MODE); - Serial.printf("SCI_MODE: 0x%04X\n", result); + DEBUG("SCI_MODE: 0x%04X\n", result); if (result != 0x4800) { - Serial.printf("Error: SCI_MODE was 0x%04X, expected was 0x4800.\n", result); + ERROR("SCI_MODE was 0x%04X, expected was 0x4800.\n", result); return; } result = _read_control_register(SCI_STATUS); - Serial.printf("SCI_STATUS: 0x%04X\n", result); + DEBUG("SCI_STATUS: 0x%04X\n", result); if (result != 0x0040 && result != 0x0048) { - Serial.printf("Error: SCI_STATUS was 0x%04X, expected was 0x0040 or 0x0048.\n", result); + ERROR("SCI_STATUS was 0x%04X, expected was 0x0040 or 0x0048.\n", result); return; } result = _read_control_register(SCI_CLOCKF); - Serial.printf("SCI_CLOCKF: 0x%04X\n", result); + DEBUG("SCI_CLOCKF: 0x%04X\n", result); - Serial.println("VS1053 Init looking good."); - Serial.println("Upping VS1053 multiplier..."); + DEBUG("VS1053 Init looking good.\n"); + DEBUG("Upping VS1053 multiplier...\n"); _write_control_register(SCI_CLOCKF, 0x6000); delay(10); @@ -50,20 +50,35 @@ void Player::_init() { _spi_settings = &_spi_settings_fast; result = _read_control_register(SCI_CLOCKF); - Serial.printf("SCI_CLOCKF: 0x%04X\n", result); + DEBUG("SCI_CLOCKF: 0x%04X\n", result); if (result != 0x6000) { - Serial.printf("Error: SCI_CLOCKF was 0x%04X, expected was 0x6000.\n", result); + ERROR("Error: SCI_CLOCKF was 0x%04X, expected was 0x6000.\n", result); return; } - _end_byte = (int8_t)(_read_wram(ADDR_ENDBYTE) & 0xFF); - set_volume(VOLUME_DEFAULT); - Serial.println("VS1053 initialization completed."); + INFO("VS1053 initialization completed.\n"); + + INFO("Checking system sounds...\n"); + SPIMaster::enable(PIN_SD_CS); + _check_system_sound("no_prev_song.mp3"); + _check_system_sound("no_next_song.mp3"); + _check_system_sound("volume_max.mp3"); + _check_system_sound("volume_min.mp3"); + _state = idle; } +void Player::_check_system_sound(String filename) { + String path = String("/system/") + filename; + if (!SD.exists(path)) { + ERROR("System sound %s is missing on the sd card!\n", path.c_str()); + } else { + DEBUG("%s found.\n", path.c_str()); + } +} + inline void Player::_wait() { while(!digitalRead(DREQ)); } @@ -110,58 +125,103 @@ void Player::_write_data(uint8_t* buffer) { } uint16_t Player::_read_wram(uint16_t address) { - Serial.printf("Reading WRAM address 0x%04X... ", address); + DEBUG("Reading WRAM address 0x%04X...\n", address); _write_control_register(SCI_WRAMADDR, address); uint16_t r1 = _read_control_register(SCI_WRAM); _write_control_register(SCI_WRAMADDR, address); uint16_t r2 = _read_control_register(SCI_WRAM); - Serial.printf("Got 0x%04X and 0x%04X.\n", r1, r2); - return r1; + if (r1 == r2) return r1; + DEBUG("Reading WRAM resulted in different values: 0x%04X and 0x%04X.\n", r1, r2); + _write_control_register(SCI_WRAMADDR, address); + r1 = _read_control_register(SCI_WRAM); + if (r1 == r2) return r1; + DEBUG("Reading WRAM resulted in different values: 0x%04X and 0x%04X.\n", r1, r2); + _write_control_register(SCI_WRAMADDR, address); + r2 = _read_control_register(SCI_WRAM); + if (r1 == r2) return r1; + DEBUG("Reading WRAM resulted in different values: 0x%04X and 0x%04X.\n", r1, r2); + DEBUG("Returning last value (0x%04X)...\n", r2); + return r2; } +int8_t Player::_get_endbyte() { + int8_t endbyte = _read_wram(ADDR_ENDBYTE) & 0xFF; + DEBUG("Endbyte is 0x%02X.\n", endbyte); + return endbyte; +} + + void Player::set_volume(uint8_t vol, bool save) { if (save) { _volume = vol; } - Serial.printf("Setting volume to 0x%02X\n", vol); + INFO("Setting volume to %d\n", vol); vol = 0xFF - vol; if (vol==0xFF) vol=0xFE; uint16_t value = (vol<<8)|vol; - Serial.printf("Setting volume register to 0x%04X\n", value); + DEBUG("Setting volume register to 0x%04X\n", value); _write_control_register(SCI_VOL, value); } void Player::vol_up() { - if (_volume + VOLUME_STEP > VOLUME_MAX) set_volume(VOLUME_MAX); + if (_volume == VOLUME_MAX) play_system_sound("volume_max.mp3"); + else if (_volume + VOLUME_STEP > VOLUME_MAX) set_volume(VOLUME_MAX); else set_volume(_volume + VOLUME_STEP); } void Player::vol_down() { if (_volume >= VOLUME_MIN + VOLUME_STEP) set_volume(_volume - VOLUME_STEP); + else if (_volume == VOLUME_MIN) play_system_sound("volume_min.mp3"); else set_volume(VOLUME_MIN); } void Player::_mute() { - Serial.println("Muting."); + INFO("Muting."); set_volume(0, false); } void Player::_unmute() { - Serial.println("Unmuting."); + INFO("Unmuting."); set_volume(_volume, false); } void Player::track_next() { if (_state != playing) return; + if (_playing_index + 1 >= _playing_album_songs) { + play_system_sound("no_next_song.mp3"); + return; + } stop(); play_song(_playing_album, _playing_index + 1); } void Player::track_prev() { if (_state != playing) return; - if (_playing_index == 0) _playing_index=1; - stop(); - play_song(_playing_album, _playing_index - 1); + if (_current_play_position > 100000) { + stop(); + play_song(_playing_album, _playing_index); + } else { + if (_playing_index == 0) { + play_system_sound("no_prev_song.mp3"); + return; + } + stop(); + play_song(_playing_album, _playing_index - 1); + } +} + +std::list Player::ls(String path) { + SPIMaster::enable(PIN_SD_CS); + std::list result; + if (!SD.exists(path)) return result; + File dir = SD.open(path); + File entry; + while (entry = dir.openNextFile()) { + String filename = entry.name(); + if (entry.isDirectory()) filename.concat("/"); + result.push_back(filename); + } + return result; } String Player::_find_album_dir(String id) { @@ -181,7 +241,7 @@ String Player::_find_album_dir(String id) { } std::list Player::_files_in_dir(String path) { - Serial.printf("Examining folder %s...\n", path.c_str()); + DEBUG("Examining folder %s...\n", path.c_str()); if (!path.startsWith("/")) path = String("/") + path; if (!path.endsWith("/")) path.concat("/"); std::list result; @@ -197,10 +257,10 @@ std::list Player::_files_in_dir(String path) { filename.endsWith(".wma") || filename.endsWith(".mp4") || filename.endsWith(".mpa"))) { - //Serial.printf("Adding file %s\n", filename.c_str()); + DEBUG(" Adding entry %s\n", filename.c_str()); result.push_back(path + filename); } else { - //Serial.printf("Ignoring entry %s\n", filename.c_str()); + DEBUG(" Ignoring entry %s\n", filename.c_str()); } entry.close(); } @@ -213,24 +273,25 @@ std::list Player::_files_in_dir(String path) { bool Player::play_album(String album) { //if (_state==playing) stop(); album_state s = _last_tracks[album.c_str()]; - Serial.printf("Last index for album %s was %d,%d\n", album.c_str(), s.index, s.position); + DEBUG("Last index for album %s was %d,%d\n", album.c_str(), s.index, s.position); return play_song(album, s.index, s.position); } bool Player::play_song(String album, uint8_t index, uint32_t skip_to) { if (_state != idle) return false; - Serial.printf("Trying to play song at index %d, offset %d of album %s\n", index, skip_to, album.c_str()); + DEBUG("Trying to play song at index %d, offset %d of album %s\n", index, skip_to, album.c_str()); String path = _find_album_dir(album); if (path.length()==0) { - Serial.println("Could not find album."); + ERROR("Could not find album.\n"); return false; } else { - Serial.printf("Found album in dir '%s'.\n", path.c_str()); + INFO("Found album in dir '%s'.\n", path.c_str()); } std::list files = _files_in_dir(path); - Serial.printf("Found %d songs in album\n", files.size()); + _playing_album_songs = files.size(); + DEBUG("Found %d songs in album\n", files.size()); if (index >= files.size()) { - Serial.println("No matching file found - not playing."); + ERROR("No matching file found - not playing.\n"); return false; } //std::list::iterator it = files.begin(); @@ -248,7 +309,7 @@ void Player::play_system_sound(String filename) { //String file = String("/system/") + filename; String file = filename; if (!SD.exists(file)) { - Serial.printf("File %s does not exist!\n", file.c_str()); + ERROR("File %s does not exist!\n", file.c_str()); return; } if (_state == playing) { @@ -261,37 +322,39 @@ void Player::play_system_sound(String filename) { } void Player::_play_file(String file, uint32_t file_offset) { - Serial.printf("play_file('%s', %d)\n", file.c_str(), file_offset); + INFO("play_file('%s', %d)\n", file.c_str(), file_offset); _file = SD.open(file); if (!_file) return; - Serial.println("Resetting SCI_DECODE_TIME..."); + DEBUG("Resetting SCI_DECODE_TIME...\n"); _write_control_register(SCI_DECODE_TIME, 0); - Serial.println("Resetting SS_DO_NOT_JUMP..."); + DEBUG("Resetting SS_DO_NOT_JUMP...\n"); _write_control_register(SCI_STATUS, _read_control_register(SCI_STATUS) & ~SS_DO_NOT_JUMP); delay(100); _refills = 0; + _current_play_position = 0; _skip_to = file_offset; if (_skip_to>0) _mute(); - Serial.println("Now playing."); + INFO("Now playing.\n"); } -void Player::_flush(uint bytes) { +void Player::_flush(uint count, int8_t byte) { SPIMaster::enable(XDCS); SPI.beginTransaction(*_spi_settings); - for(uint i=0; i 2048) { @@ -339,17 +394,17 @@ void Player::_finish_stopping() { if (_file) { _file.close(); } - Serial.println("Stopped."); + INFO("Stopped.\n"); } void Player::_refill() { SPIMaster::enable(PIN_SD_CS); _refills++; - if (_refills % 1000 == 0) Serial.print("."); + if (_refills % 1000 == 0) DEBUG("."); uint8_t result = _file.read(_buffer, sizeof(_buffer)); if (result == 0) { // File is over. - Serial.println("EOF reached."); + DEBUG("EOF reached.\n"); _finish_playing(); if (_state == system_sound_while_playing) { _finish_stopping(); @@ -367,14 +422,15 @@ void Player::_refill() { } return; } + _current_play_position+=result; _write_data(_buffer); if (_skip_to > 0) { if (_skip_to > _file.position()) { uint16_t status = _read_control_register(SCI_STATUS); if ((status & SS_DO_NOT_JUMP) == 0) { - Serial.printf("Skipping to %d.\n", _skip_to); - _flush(2048); + DEBUG("Skipping to %d.\n", _skip_to); + _flush(2048, _get_endbyte()); _file.seek(_skip_to); _skip_to = 0; _unmute(); @@ -402,6 +458,6 @@ bool Player::loop() { } void Player::_set_last_track(const char* album, uint8_t index, uint32_t position) { - Serial.printf("Setting _last_track[%s]=%d,%d.\n", album, index, position); + DEBUG("Setting _last_track[%s]=%d,%d.\n", album, index, position); _last_tracks[album] = {index, position}; }