Added recording mode to detect volumes.
This commit is contained in:
		| @@ -4,7 +4,6 @@ | ||||
| #include <SD.h> | ||||
| #include <list> | ||||
| #include <map> | ||||
| #include <Adafruit_MCP23017.h> | ||||
| #include "spi_master.h" | ||||
|  | ||||
| #define SCI_MODE 0x00 | ||||
| @@ -15,20 +14,28 @@ | ||||
| #define SCI_VOL 0x0B | ||||
| #define SCI_WRAMADDR 0x07 | ||||
| #define SCI_WRAM 0x06 | ||||
| #define SCI_HDAT0 0x08 | ||||
| #define SCI_HDAT1 0x09 | ||||
| #define SCI_AICTRL0 0x0C | ||||
| #define SCI_AICTRL1 0x0D | ||||
| #define SCI_AICTRL2 0x0E | ||||
| #define SCI_AICTRL3 0x0F | ||||
|  | ||||
| #define CMD_WRITE 0x02 | ||||
| #define CMD_READ 0x03 | ||||
|  | ||||
| #define ADDR_ENDBYTE 0x1E06 | ||||
|  | ||||
| #define SM_RESET 0x0004 | ||||
| #define SM_CANCEL 0x0008 | ||||
| #define SM_ADPCM 0x1000 | ||||
| #define SS_DO_NOT_JUMP 0x8000 | ||||
|  | ||||
| class Player { | ||||
| private: | ||||
| 	enum state { uninitialized, idle, playing, stopping, | ||||
| 		system_sound_while_playing, system_sound_while_stopped, | ||||
| 		sleeping }; | ||||
| 		sleeping, recording }; | ||||
| 	struct album_state { | ||||
| 		uint8_t index; | ||||
| 		uint32_t position; | ||||
| @@ -39,6 +46,7 @@ private: | ||||
| 	void _wait(); | ||||
| 	uint16_t _read_control_register(uint8_t address); | ||||
| 	void _write_control_register(uint8_t address, uint16_t value); | ||||
| 	void _write_direct(uint8_t address, uint16_t value); | ||||
| 	void _write_data(uint8_t* data); | ||||
| 	uint16_t _read_wram(uint16_t address); | ||||
| 	state _state = state::uninitialized; | ||||
| @@ -58,6 +66,8 @@ private: | ||||
| 	void _unmute(); | ||||
| 	void _sleep(); | ||||
| 	void _wakeup(); | ||||
| 	void _record(); | ||||
| 	void _patch_adpcm(); | ||||
| 	void _speaker_off(); | ||||
| 	void _speaker_on(); | ||||
|  | ||||
|   | ||||
| @@ -108,12 +108,25 @@ void Player::_wakeup() { | ||||
| 	set_volume(_volume, false); | ||||
| 	_write_control_register(SCI_AUDATA, 0x0000); | ||||
| 	_write_control_register(SCI_CLOCKF, 0x6000); | ||||
| 	_write_control_register(SCI_MODE, 0x4800 | SM_RESET); | ||||
| 	delay(10); | ||||
| 	//_speaker_on(); | ||||
| 	_spi_settings = &_spi_settings_fast; | ||||
| 	_state = idle; | ||||
| } | ||||
|  | ||||
| void Player::_record() { | ||||
| 	_write_control_register(SCI_AICTRL0, 8000U); // Sampling rate 8000 Hz | ||||
| 	_write_control_register(SCI_AICTRL1, 2048U); // Manual gain, 2x | ||||
| 	_write_control_register(SCI_AICTRL2, 2048U); // Maximum gain for autogain - ignored | ||||
| 	_write_control_register(SCI_AICTRL3, 6); // 2 (left channel) + 4 (PCM) | ||||
| 	uint16_t mode = _read_control_register(SCI_MODE); | ||||
| 	mode = mode | SM_RESET | SM_ADPCM; | ||||
| 	_write_control_register(SCI_MODE, mode); | ||||
| 	_patch_adpcm(); | ||||
| 	_state = recording; | ||||
| } | ||||
|  | ||||
| void Player::_check_system_sound(String filename) { | ||||
| 	String path = String("/system/") + filename; | ||||
| 	if (!SD.exists(path)) { | ||||
| @@ -144,16 +157,57 @@ uint16_t Player::_read_control_register(uint8_t address) { | ||||
| } | ||||
|  | ||||
| void Player::_write_control_register(uint8_t address, uint16_t value) { | ||||
| 	uint8_t b1 = value >> 8; | ||||
| 	uint8_t b2 = value & 0xFF; | ||||
| 	_wait(); | ||||
| 	_spi->select_vs1053_xcs(); | ||||
| 	SPI.beginTransaction(*_spi_settings); | ||||
| 	_write_direct(address, value); | ||||
| 	SPI.endTransaction(); | ||||
| 	_spi->select_vs1053_xcs(false); | ||||
| } | ||||
|  | ||||
| void Player::_write_direct(uint8_t target, uint16_t value) { | ||||
| 	SPI.transfer(CMD_WRITE); | ||||
| 	SPI.transfer(address); | ||||
| 	SPI.transfer(b1); | ||||
| 	SPI.transfer(b2); | ||||
| 	SPI.transfer(target); | ||||
| 	SPI.transfer(value >> 8); | ||||
| 	SPI.transfer(value & 0xFF); | ||||
| 	_wait(); | ||||
| } | ||||
|  | ||||
| void Player::_patch_adpcm() { | ||||
| 	_spi->select_vs1053_xcs(); | ||||
| 	SPI.beginTransaction(*_spi_settings); | ||||
| 	_write_direct(SCI_WRAMADDR, 0x8010); | ||||
| 	_write_direct(SCI_WRAM, 0x3e12); | ||||
| 	_write_direct(SCI_WRAM, 0xb817); | ||||
| 	_write_direct(SCI_WRAM, 0x3e14); | ||||
| 	_write_direct(SCI_WRAM, 0xf812); | ||||
| 	_write_direct(SCI_WRAM, 0x3e01); | ||||
| 	_write_direct(SCI_WRAM, 0xb811); | ||||
| 	_write_direct(SCI_WRAM, 0x0007); | ||||
| 	_write_direct(SCI_WRAM, 0x9717); | ||||
| 	_write_direct(SCI_WRAM, 0x0020); | ||||
| 	_write_direct(SCI_WRAM, 0xffd2); | ||||
| 	_write_direct(SCI_WRAM, 0x0030); | ||||
| 	_write_direct(SCI_WRAM, 0x11d1); | ||||
| 	_write_direct(SCI_WRAM, 0x3111); | ||||
| 	_write_direct(SCI_WRAM, 0x8024); | ||||
| 	_write_direct(SCI_WRAM, 0x3704); | ||||
| 	_write_direct(SCI_WRAM, 0xc024); | ||||
| 	_write_direct(SCI_WRAM, 0x3b81); | ||||
| 	_write_direct(SCI_WRAM, 0x8024); | ||||
| 	_write_direct(SCI_WRAM, 0x3101); | ||||
| 	_write_direct(SCI_WRAM, 0x8024); | ||||
| 	_write_direct(SCI_WRAM, 0x3b81); | ||||
| 	_write_direct(SCI_WRAM, 0x8024); | ||||
| 	_write_direct(SCI_WRAM, 0x3f04); | ||||
| 	_write_direct(SCI_WRAM, 0xc024); | ||||
| 	_write_direct(SCI_WRAM, 0x2808); | ||||
| 	_write_direct(SCI_WRAM, 0x4800); | ||||
| 	_write_direct(SCI_WRAM, 0x36f1); | ||||
| 	_write_direct(SCI_WRAM, 0x9811); | ||||
| 	_write_direct(SCI_WRAMADDR, 0x8028); | ||||
| 	_write_direct(SCI_WRAM, 0x2a00); | ||||
| 	_write_direct(SCI_WRAM, 0x040e); | ||||
| 	SPI.endTransaction(); | ||||
| 	_spi->select_vs1053_xcs(false); | ||||
| } | ||||
| @@ -354,7 +408,7 @@ bool Player::play_album(String album) { | ||||
| } | ||||
|  | ||||
| bool Player::play_song(String album, uint8_t index, uint32_t skip_to) { | ||||
| 	if (_state == sleeping) _wakeup(); | ||||
| 	if (_state == sleeping || _state == recording) _wakeup(); | ||||
| 	if (_state != idle) return false; | ||||
| 	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); | ||||
| @@ -573,8 +627,22 @@ bool Player::loop() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	if (_state == recording) { | ||||
| 		uint16_t samples_available = _read_control_register(SCI_HDAT1); | ||||
| 		if (samples_available >= 500) { | ||||
| 			unsigned long sum = 0; | ||||
| 			for (int i=0; i<500; i++) { | ||||
| 				uint16_t sample = _read_control_register(SCI_HDAT0); | ||||
| 				sum += sample * sample; | ||||
| 			} | ||||
| 			double result = sqrt(sum / 500); | ||||
| 			DEBUG("Loudness: %f", result); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (_state == idle && _stopped_at < millis() - VS1053_SLEEP_DELAY) { | ||||
| 		_sleep(); | ||||
| 		//_sleep(); | ||||
| 		_record(); | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user