Added recording mode to detect volumes.
This commit is contained in:
parent
2d1f049444
commit
48c93ed043
@ -4,7 +4,6 @@
|
|||||||
#include <SD.h>
|
#include <SD.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <Adafruit_MCP23017.h>
|
|
||||||
#include "spi_master.h"
|
#include "spi_master.h"
|
||||||
|
|
||||||
#define SCI_MODE 0x00
|
#define SCI_MODE 0x00
|
||||||
@ -15,20 +14,28 @@
|
|||||||
#define SCI_VOL 0x0B
|
#define SCI_VOL 0x0B
|
||||||
#define SCI_WRAMADDR 0x07
|
#define SCI_WRAMADDR 0x07
|
||||||
#define SCI_WRAM 0x06
|
#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_WRITE 0x02
|
||||||
#define CMD_READ 0x03
|
#define CMD_READ 0x03
|
||||||
|
|
||||||
#define ADDR_ENDBYTE 0x1E06
|
#define ADDR_ENDBYTE 0x1E06
|
||||||
|
|
||||||
|
#define SM_RESET 0x0004
|
||||||
#define SM_CANCEL 0x0008
|
#define SM_CANCEL 0x0008
|
||||||
|
#define SM_ADPCM 0x1000
|
||||||
#define SS_DO_NOT_JUMP 0x8000
|
#define SS_DO_NOT_JUMP 0x8000
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
private:
|
private:
|
||||||
enum state { uninitialized, idle, playing, stopping,
|
enum state { uninitialized, idle, playing, stopping,
|
||||||
system_sound_while_playing, system_sound_while_stopped,
|
system_sound_while_playing, system_sound_while_stopped,
|
||||||
sleeping };
|
sleeping, recording };
|
||||||
struct album_state {
|
struct album_state {
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
uint32_t position;
|
uint32_t position;
|
||||||
@ -39,6 +46,7 @@ private:
|
|||||||
void _wait();
|
void _wait();
|
||||||
uint16_t _read_control_register(uint8_t address);
|
uint16_t _read_control_register(uint8_t address);
|
||||||
void _write_control_register(uint8_t address, uint16_t value);
|
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);
|
void _write_data(uint8_t* data);
|
||||||
uint16_t _read_wram(uint16_t address);
|
uint16_t _read_wram(uint16_t address);
|
||||||
state _state = state::uninitialized;
|
state _state = state::uninitialized;
|
||||||
@ -58,6 +66,8 @@ private:
|
|||||||
void _unmute();
|
void _unmute();
|
||||||
void _sleep();
|
void _sleep();
|
||||||
void _wakeup();
|
void _wakeup();
|
||||||
|
void _record();
|
||||||
|
void _patch_adpcm();
|
||||||
void _speaker_off();
|
void _speaker_off();
|
||||||
void _speaker_on();
|
void _speaker_on();
|
||||||
|
|
||||||
|
@ -108,12 +108,25 @@ void Player::_wakeup() {
|
|||||||
set_volume(_volume, false);
|
set_volume(_volume, false);
|
||||||
_write_control_register(SCI_AUDATA, 0x0000);
|
_write_control_register(SCI_AUDATA, 0x0000);
|
||||||
_write_control_register(SCI_CLOCKF, 0x6000);
|
_write_control_register(SCI_CLOCKF, 0x6000);
|
||||||
|
_write_control_register(SCI_MODE, 0x4800 | SM_RESET);
|
||||||
delay(10);
|
delay(10);
|
||||||
//_speaker_on();
|
//_speaker_on();
|
||||||
_spi_settings = &_spi_settings_fast;
|
_spi_settings = &_spi_settings_fast;
|
||||||
_state = idle;
|
_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) {
|
void Player::_check_system_sound(String filename) {
|
||||||
String path = String("/system/") + filename;
|
String path = String("/system/") + filename;
|
||||||
if (!SD.exists(path)) {
|
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) {
|
void Player::_write_control_register(uint8_t address, uint16_t value) {
|
||||||
uint8_t b1 = value >> 8;
|
|
||||||
uint8_t b2 = value & 0xFF;
|
|
||||||
_wait();
|
_wait();
|
||||||
_spi->select_vs1053_xcs();
|
_spi->select_vs1053_xcs();
|
||||||
SPI.beginTransaction(*_spi_settings);
|
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(CMD_WRITE);
|
||||||
SPI.transfer(address);
|
SPI.transfer(target);
|
||||||
SPI.transfer(b1);
|
SPI.transfer(value >> 8);
|
||||||
SPI.transfer(b2);
|
SPI.transfer(value & 0xFF);
|
||||||
_wait();
|
_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.endTransaction();
|
||||||
_spi->select_vs1053_xcs(false);
|
_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) {
|
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;
|
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());
|
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);
|
String path = _find_album_dir(album);
|
||||||
@ -573,8 +627,22 @@ bool Player::loop() {
|
|||||||
return true;
|
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) {
|
if (_state == idle && _stopped_at < millis() - VS1053_SLEEP_DELAY) {
|
||||||
_sleep();
|
//_sleep();
|
||||||
|
_record();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user