diff --git a/SFEMP3Shield/Examples/RecorderDemo/RecorderDemo.ino b/SFEMP3Shield/Examples/RecorderDemo/RecorderDemo.ino new file mode 100644 index 0000000..a75dfce --- /dev/null +++ b/SFEMP3Shield/Examples/RecorderDemo/RecorderDemo.ino @@ -0,0 +1,280 @@ +/** + * \file RecorderDemo.ino + * + * \brief Example sketch of using the MP3Shield Arduino driver to record OGG. + * \remarks comments are implemented with Doxygen Markdown format + * + * \author Miguel Moreto + * + * This sketch listens for commands from serial. The user can start recoring, + * stop recording and play the recorded track. + * + * \note This example sketch was tested with a Teensy2.0++ board and a + * generic MP3 module with VS1053b chipset. You can configure Teensyduino + * as a mass storage device, so your SD card can be accessed in windows explorer. + * It is very slow and cannot be safely removed but it is cool! + */ +#include + +//Add the SdFat Libraries +#include +#include + + +#include + + +#include + +// Pin definition: +#define PIN_PUSH_0 5 // Pushbutton Play pin +#define PIN_PUSH_1 7 // Pushbutton Stop pin +#define PIN_PUSH_2 8 // Pushbutton Rec pin +#define PIN_LED_REC 17 // Led to indicate recording +#define PIN_LED_OK 16 // Led to indicate ok status +#define PIN_LED_ERROR 15 // Led error. +#define PIN_AMP_SHUTDOWN 13 // Output pin to turn amplifier module on or off. + + +// bounce objects to debounce buttons. +Bounce PushButtonRotary = Bounce(PIN_PUSH_0, 10); // 10 ms debounce +Bounce PushButtonStop = Bounce(PIN_PUSH_1,10); +Bounce PushButtonRec = Bounce(PIN_PUSH_2,10); + +/** + * \brief Object instancing the SdFat library. + * + * principal object for handling all SdCard functions. + */ +SdFat sd; + +// Objects: +SFEMP3Shield MP3player; + +// Using SDFatLib, limit the filenames to 8.3 format. +char trackname[] = "rec001.ogg"; + +/* + * Recorder plugin filename. This one is include in this demo folder. + * If you whant to use other profile, consult Ogg Vorbis Encoder + * application manual from VLSI: + * http://www.vlsi.fi/fileadmin/software/VS10XX/VorbisEncoder170c.pdf + * All the profile plugin files are stored in recorder_plugins.zip + * included in SFEMP3Shield library plugins folder. + */ +char pluginfilename[] = "e44k1q05.vs"; // HiFi Voice Profile number 5: typical 87kbps + +uint8_t ledstate = 0; + +void setup() { + + Serial.begin(115200); + + // Play, stop and rec buttons. + pinMode(PIN_PUSH_0, INPUT_PULLUP); + pinMode(PIN_PUSH_1, INPUT_PULLUP); + pinMode(PIN_PUSH_2, INPUT_PULLUP); + + // Output pins: + pinMode(PIN_LED_OK,OUTPUT); + pinMode(PIN_LED_REC,OUTPUT); + pinMode(PIN_LED_ERROR,OUTPUT); + pinMode(PIN_AMP_SHUTDOWN,OUTPUT); + + // Turn off the LEDs + digitalWrite(PIN_LED_OK, LOW); + digitalWrite(PIN_LED_REC, LOW); + digitalWrite(PIN_LED_ERROR, LOW); + digitalWrite(PIN_AMP_SHUTDOWN, LOW); // Turn off amplifier + + //Initialize the SdCard. + if(!sd.begin(SD_SEL, SPI_HALF_SPEED)) sd.initErrorHalt(); + if(!sd.chdir("/")) sd.errorHalt("sd.chdir"); + + StartMP3(); + + // Binds a user defined function as a handler that is + // executed at the end of recording. + MP3player.bindEndRecordHandler(endRecordingHandler); + + help(); +} + +void loop() +{ + uint16_t result = 0; + + if (PushButtonRotary.update()) { + if (PushButtonRotary.fallingEdge()){ + parse_menu('p'); + } + } + + if (PushButtonStop.update()) { + if (PushButtonStop.fallingEdge()){ + parse_menu('s'); + } + } + + if (PushButtonRec.update()) { + if (PushButtonRec.fallingEdge()){ + parse_menu('r'); + } + } + + // If recorder is active, read data blocks from VS1053b chipset and + // write them to track file. + if (MP3player.isRecording()){ + result = MP3player.doRecordOgg(); + if (result > 0){ // Toogle rec led when one or more datablock (512B) are written. + ledstate = ~ledstate; + digitalWrite(PIN_LED_REC,ledstate); // Toogle rec led. + } + //Serial.println(result); // Print the number of databloks written. + } + + // You can do something else here. + + + if(Serial.available()) { + parse_menu(Serial.read()); // get command from serial input + } + + /* add main program code here */ + +} + +/* + * MP3 Player begin function. Restart VS1053 and load the firmware update. + */ +void StartMP3(){ + uint8_t result; //result code, + result = MP3player.begin(); + //check result, see readme for error codes. + if(result != 0) { + digitalWrite(PIN_LED_ERROR, HIGH); // Turn on error led + Serial.print(F("Error code: ")); + Serial.print(result); + Serial.println(F(" when trying to start MP3 player")); + if ( result == 6 ) { + Serial.println(F("Warning: patch file not found, skipping.")); // can be removed for space, if needed. + Serial.println(F("Use the \"d\" command to verify SdCard can be read")); // can be removed for space, if needed. + } + }else{ + digitalWrite(PIN_LED_OK, HIGH); // Turn on ok led + } +} + + +//------------------------------------------------------------------------------ +/** + * \brief Decode the Menu. + * + * Parses through the characters of the users input, executing corresponding + * MP3player library functions and features then displaying a brief menu and + * prompting for next input command. + */ +void parse_menu(byte key_command) { + + static uint8_t gain = 0; + + uint8_t result; // result code from some function as to be tested at later time. + + Serial.print(F("Received command: ")); + Serial.write(key_command); + Serial.println(F(" ")); + + //if s, stop the playing or recording the current track + if(key_command == 's') { + if(MP3player.isPlaying()){ + MP3player.stopTrack(); + Serial.println("Player stoped."); + } + if (MP3player.isRecording()){ + Serial.println("Stoping recording..."); + MP3player.stopRecording(); // Command to finish recording. + digitalWrite(PIN_LED_REC,LOW); // Turn off red led. + } + digitalWrite(PIN_AMP_SHUTDOWN, LOW); // Turn off amplifier + } // 's' command + else if(key_command == 'r'){ // If 'r', start recording. + Serial.println("Start recording"); + MP3player.stopTrack(); // Stop playing if applicable. + digitalWrite(PIN_LED_OK, LOW); // Turn off "ready to play" Led. + result = MP3player.startRecordOgg(trackname, pluginfilename); // Start recording. + if (result != 0){ + Serial.print("Error starting recorder: "); + Serial.println(result); + } + } // 'r' command + else if (key_command == 'p'){ // If 'p', play recorded track. + Serial.println("Restarting VS10xx..."); + StartMP3(); // Restart MP3 in playing mode with latest patch. + result = MP3player.playMP3(trackname); + if (result != 0){ + Serial.print("Error playing track: "); + Serial.println(result); + }else{ + digitalWrite(PIN_AMP_SHUTDOWN, HIGH); // Turn on amplifier + Serial.println("Playing..."); + } + } // 'p' command + else if(key_command == 'h') { // Help + help(); + } + else if(key_command == 'G') { // Help + if (gain < 63){ + if(!MP3player.setRecGain(gain++)){ + gain--; + Serial.println("Not recording."); + }else{ + Serial.print("Gain setted to: "); + Serial.println(gain); + } + } + } + + else if(key_command == 'g') { // Help + if (gain > 0){ + if(!MP3player.setRecGain(gain--)){ + gain++; + Serial.println("Not recording."); + }else{ + Serial.print("Gain setted to: "); + Serial.println(gain); + } + } + } +} + +//------------------------------------------------------------------------------ +/** + * \brief Print Help Menu. + * + * Prints a full menu of the commands available along with descriptions. + */ +void help() { + Serial.println("Arduino SFEMP3Shield Library OGG recorder Example:"); + Serial.println("SFEMP3Shield by Bill Porter & Michael P. Flaga"); + Serial.println("Recording functions by Miguel Moreto based on VLSI docs."); + Serial.println("COMMANDS:"); + Serial.println(" [s] to stop recording or playing"); + Serial.println(" [r] start recording ogg file"); + Serial.println(" [p] play recorded track"); + Serial.println(" [G] increase gain"); + Serial.println(" [g] decrease gain"); +} + +/** + * \brief Function executed once the recording ends. + * + * A pointer to this function is passed to MP3player class by using + * the method bindEndRecordHandler(function); + */ + +void endRecordingHandler(void) +{ + Serial.println("Record finished"); + digitalWrite(PIN_LED_REC, LOW); // Turn off rec led + digitalWrite(PIN_LED_OK, HIGH); // Turn on ok led +} diff --git a/SFEMP3Shield/Examples/RecorderDemo/e08k1q05.vs b/SFEMP3Shield/Examples/RecorderDemo/e08k1q05.vs new file mode 100644 index 0000000..cc9de06 Binary files /dev/null and b/SFEMP3Shield/Examples/RecorderDemo/e08k1q05.vs differ diff --git a/SFEMP3Shield/Examples/RecorderDemo/e44k1q05.vs b/SFEMP3Shield/Examples/RecorderDemo/e44k1q05.vs new file mode 100644 index 0000000..b1f586d Binary files /dev/null and b/SFEMP3Shield/Examples/RecorderDemo/e44k1q05.vs differ diff --git a/SFEMP3Shield/SFEMP3Shield.cpp b/SFEMP3Shield/SFEMP3Shield.cpp index eeb910b..72f6502 100755 --- a/SFEMP3Shield/SFEMP3Shield.cpp +++ b/SFEMP3Shield/SFEMP3Shield.cpp @@ -59,6 +59,7 @@ state_m SFEMP3Shield::playing_state; */ uint16_t SFEMP3Shield::spiRate; + // only needed for specific means of refilling #if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer SimpleTimer timer; @@ -68,6 +69,31 @@ uint16_t SFEMP3Shield::spiRate; //buffer for music uint8_t SFEMP3Shield::mp3DataBuffer[32]; + +//------------------------------------------------------------------------------ +/** + * \brief Class constructor. + * + * Initialize variables and pointers when the class is instatiated. + */ +SFEMP3Shield::SFEMP3Shield(){ + +int _sb_amplitude = DEFAULT_BASS_AMPLITUDE; +int _sb_freqlimit = DEFAULT_BASS_FREQUENCY; +int _st_amplitude = DEFAULT_TREBLE_AMPLITUDE; +int _st_freqlimit = DEFAULT_TREBLE_FREQUENCY; + +/* + * Set pointer to Recording end handler to zero. The users should + * bind their function handler using bindEndRecordHandler function. + * + */ +EndRecHandlerFunc = 0; + +RecordingFlag = 0; + +} + //------------------------------------------------------------------------------ /** * \brief Initialize the MP3 Player shield. @@ -110,7 +136,7 @@ if (int8_t(sd.vol()->fatType()) == 0) { cs_high(); //MP3_XCS, Init Control Select to deselected dcs_high(); //MP3_XDCS, Init Data Select to deselected digitalWrite(MP3_RESET, LOW); //Put VS1053 into hardware reset - + playing_state = initialized; uint8_t result = vs_init(); @@ -175,9 +201,9 @@ uint8_t SFEMP3Shield::vs_init() { //Initialize VS1053 chip //Reset if not already - delay(100); // keep clear of anything prior + delay(10); // keep clear of anything prior digitalWrite(MP3_RESET, LOW); //Shut down VS1053 - delay(100); + delay(10); //Bring out of reset digitalWrite(MP3_RESET, HIGH); //Bring up VS1053 @@ -234,11 +260,286 @@ uint8_t SFEMP3Shield::vs_init() { if(VSLoadUserCode("patches.053")) return 6; - delay(100); // just a good idea to let settle. + delay(10); // just a good idea to let settle. return 0; // indicating all was good. } + /** + * \brief Initialize the VS10xx for recording. + * + * Reset and initialize the VS10xx chip's internal registers such as clock + * for recording operation with the SFEMP3Shield class's members. + * Upload recording profile file and start the plugin. + * Method writen by Miguel Moreto based on VS1053b Ogg Vorbis Encoder + * application manual. + * + * \param[in] fileName pointer of a char array (aka string), contianing the filename. + * + * \return Any Value other than zero indicates a problem occured. + * - 0 indicates that recorder is running. + * - error codes from VSLoadUserCode (loading plugin). + * - 10 error opening the track for writing. + * + * \note The user needs to constantly call doRecordOgg in order to read ogg + * data and store it in track file. Using HIFI voice profile 5. + * + * \see + * \ref Error_Codes + */ +uint8_t SFEMP3Shield::startRecordOgg(char* fileName, char* pluginfileName){ + + uint8_t temp; + + // Disable DREQ interrupt during recording. + detachInterrupt(MP3_DREQINT); + + /* Following VS1053 operations are according to the + VS1053b Ogg Vorbis Encoder application manual. For + details read Chapter Loading and Starting the Code. */ + + /* Set VS1053 clock to 4.5x = 55.3 MHz */ + Mp3WriteRegister(SCI_CLOCKF, 0xC000); + while(digitalRead(MP3_DREQ)==0){ // Wait for DREQ. + } + + /* Clear SCI_BASS */ + Mp3WriteRegister(SCI_BASS,0x0000); + + /* Reset VS1053 */ + Mp3WriteRegister(SCI_MODE,SM_SDINEW | SM_RESET); + while(digitalRead(MP3_DREQ)==0){ + } + + // Disable all interrupts except SCI + Mp3WriteRegister(SCI_WRAMADDR, VS1053_INT_ENABLE); + Mp3WriteRegister(SCI_WRAM, 0x2); + while(digitalRead(MP3_DREQ)==0){ + } + + /* Load the recorder application to VS1053 + This source code uses .img image files for loading. + If you use .plg files, use the source as described + in the VS1053b Ogg Vorbis Encoder application manual. */ + + /* Higher HIFI voice profile only works with arduino CPU clock + at 16MHz. With 8MHz the record is corrupted due to low writing + SPI speed to SD card. Maybe it is a SD issue, I do not tested + with a micro SD class 10, only class 4.*/ + //temp = VSLoadUserCode("e44k1q05.vs"); + temp = VSLoadUserCode(pluginfileName); + if(temp){ + // Problem loading user code + return temp; + } + +#if defined(VS_LINE1_MODE) + Mp3WriteRegister(SCI_MODE, SM_ADPCM | SM_SDINEW | SM_LINE1); +#else + Mp3WriteRegister(SCI_MODE, SM_ADPCM | SM_SDINEW); +#endif + Mp3WriteRegister(SCI_AICTRL1, 1024); //AGC + Mp3WriteRegister(SCI_AICTRL2, 0); + Mp3WriteRegister(SCI_AICTRL3, CHANNEL_CONFIG);//CHANNEL_CONFIG); + + /* Open file for writing */ + if(!track.open(fileName, O_WRITE | O_CREAT)){ + // Error opening the track. + return 10; + } + /* Activate recording from the plugin address. In the case of the Ogg + Vorbis Encoder application this address is 0x34. */ + Mp3WriteRegister(SCI_AIADDR, 0x34); + while(digitalRead(MP3_DREQ)==0){ + } + + /* Set RecordingFlag to enable DoRecording method */ + RecordingFlag = 1; + return 0; +} + + +/* + * \brief Read a data block from VS10xx and write it to file. + * + * This function do the reading of OGG data from the VS1053 chip. + * It have to be called periodically, otherwise, data will be lost + * and the resulting OGG will be corrupted. + * Method writen by Miguel Moreto based on VS1053b Ogg Vorbis Encoder + * application manual. + * + * \return The number of data blocks read from VS1053 and writen + * to the track file. + * + * \note The user needs to constantly call doRecordOgg in order to read ogg + * data and store it in track file. + */ +uint16_t SFEMP3Shield::doRecordOgg(void){ + static uint8_t state = 0; + uint16_t wordsWaiting; + uint16_t wordsToRead; + uint16_t datablockswritten = 0; + + if (RecordingFlag == 1) { + /* Check when to end recording. The flag StopRecFlag + is setted by method StopRecording() that is called by the user in + order to stop recording. */ + if (StopRecFlag && !state) { + + state = 1; + Mp3WriteRegister(SCI_AICTRL3, 1); // Send VS1053 request to stop recording + } + + /* See how many 16-bit words there are waiting in the VS1053 buffer */ + wordsWaiting = Mp3ReadRegister(SCI_HDAT1); + + /* If user has requested stopping recording, and VS1053 has + stopped recording, proceed to the next state. */ + if (state == 1 && Mp3ReadRegister(SCI_AICTRL3) & (1<<1)) { + state = 2; + /* It is important to reread the HDAT1 register once after + VS1053 has stopped. Otherwise there is the chance that + a few more words have just arrived although we just + read this register. So, do NOT optimize the following + line away! */ + wordsWaiting = Mp3ReadRegister(SCI_HDAT1); + } + + /* Read and transfer whole 512-byte (256-word) disc blocks at + the time. The only exception is when recording ends: then + allow for a non-full block. */ + // Entra aqui se wordsWaiting >= 256 caso state = 1|0 + // ou wordsWaiting >= 1 caso state seja 2 ou 3. + while (wordsWaiting >= ((state < 2) ? 256 : 1)) { + datablockswritten++; + wordsToRead = min(wordsWaiting, 256); + wordsWaiting -= wordsToRead; + + /* If this is the very last block, read one 16-bit word less, + because it will be handled later separately. */ + if (state == 2 && !wordsWaiting) + wordsToRead--; + /* Transfer one full data block, or if this is the very last + block, all data that's left except for the last word. */ + { + uint16_t t; + uint16_t i; + for (i=0; i> 8)); + track.write((uint8_t)(t & 0xFF)); + } + } + /* If this is the last data block... */ + if (wordsToRead < 256) { + uint16_t lastWord; + state = 3; + + /* ... read the very last word of the file */ + lastWord = Mp3ReadRegister(SCI_HDAT0); + /* Always write first half of the last word. */ + track.write((uint8_t)(lastWord >> 8)); + + /* Read twice SCIR_AICTRL3, then check bit 2 of latter read. */ + Mp3ReadRegister(SCI_AICTRL3); + if (!(Mp3ReadRegister(SCI_AICTRL3) & (1<<2))) { + /* Write last half of the last word only if bit 2 is clear. */ + track.write((uint8_t)(lastWord & 0xFF)); + } + datablockswritten++; + StopRecFlag = 0; + state = 0; + RecordingFlag = 0; + track.close(); + if(EndRecHandlerFunc !=0 ) { + EndRecHandlerFunc(); // Executes the handler function passed as a pointer. + // only if user binded a function. + } + Mp3WriteRegister(SCI_MODE, SM_SDINEW | SM_RESET); + return 0; + } /* if (wordsToRead < 256) */ + } /* while (wordsWaiting >= ((state < 2) ? 256 : 1)) */ + } // End if RecordingFlag + + return datablockswritten; +} + +/** + * \brief Check if a recording is in progress + * + * This function chacks if recording is active. + * Method writen by Miguel Moreto based on VS1053b Ogg Vorbis Encoder + * application manual. + * + * \return 1 if recording is active, 0 if not. + * + */ +uint8_t SFEMP3Shield::isRecording(void){ + return RecordingFlag; +} + +/** + * \brief Request to stop recording. + * + * This function signals doRecordOgg to stop recording. + * Method writen by Miguel Moreto. + * + * \note The user needs to call stopRecording in order to finish + * the recording and close the OGG track file. + */ +void SFEMP3Shield::stopRecording(void){ + StopRecFlag = 1; +} + +/** + * \brief Set the recording gain value. + * + * This function writes a multiple of 1024 to + * SCI_AICTRL1 Recording gain (1024 = 1) or 0 for automatic gain control + * Setting the gain to zero enables AGC. + * Method writen by Miguel Moreto. + * + * \param[in] gain, number from 0 to 63. + * + * \return 0 if it is not recording, 1 if success. + * + * \note Maximun gain is (65536/1024)-1 = 63. + */ +uint8_t SFEMP3Shield::setRecGain(uint8_t gain){ + if (isRecording()){ + if (gain > 63){ + gain = 63; + } + + if (gain == 0){ // If AGC, sets a Maximum autogain amplification. + Mp3WriteRegister(SCI_AICTRL2, 1024); + } + + Mp3WriteRegister(SCI_AICTRL1, ((gain << 10))); + return 1; + } + return 0; +} + +/** + * \brief Attach a handler function + * + * The pointer to a function (EndRecHandlerFunc) is assigned with + * the address of a function defined by the user (Handler). + * This Handler is executed at the end of doRecordOgg() after + * the last word wrote to ogg file. + * This way the user can define what to do just after recording ends. + * You can view this like an interrupt handler that is fired once the + * recording ends. + * Method writen by Miguel Moreto. + * + * \note The user should call this function at the beggining + * of the program. + */ +void SFEMP3Shield::bindEndRecordHandler(void (*Handler)(void)){ + EndRecHandlerFunc = Handler; +} + //------------------------------------------------------------------------------ /** * \brief load VS1xxx with patch or plugin from file on SDcard. @@ -543,8 +844,169 @@ uint16_t SFEMP3Shield::getVolume() { uint16_t MP3SCI_VOL = Mp3ReadRegister(SCI_VOL); return MP3SCI_VOL; } -// @} -// Volume_Group + +//------------------------------------------------------------------------------ +/** + * \brief Get the current Treble Frequency from the VS10xx chip + * Based on Mbed lib. + * + * \return int16_t of frequency in Hertz. + * + */ +int SFEMP3Shield::getTrebleFrequency(void) +{ + return _st_freqlimit * 1000; +} + +//------------------------------------------------------------------------------ +/** + * \brief Get the current Treble Amplitude from the VS10xx chip + * Based on Mbed lib. + * + * \return int16_t of frequency amplitude (from -8 to 7). + * + */ +int SFEMP3Shield::getTrebleAmplitude(void) +{ + return _st_amplitude; +} + +//------------------------------------------------------------------------------ +/** + * \brief Get the current Bass Frequency from the VS10xx chip + * Based on Mbed lib. + * + * \return int16_t of bass frequency in Hertz. + * + */ +int SFEMP3Shield::getBassFrequency(void) +{ + return _sb_freqlimit * 10; +} + +//------------------------------------------------------------------------------ +/** + * \brief Get the current Bass bost amplitude from the VS10xx chip + * Based on Mbed lib. + * + * \return int16_t of bass bost amplitude in dB. + * + */ +int SFEMP3Shield::getBassAmplitude(void) +{ + return _sb_amplitude; +} + +//------------------------------------------------------------------------------ +/** + * \brief Set the current Treble Frequency in VS10xx chip + * Based on Mbed lib. + * + * \param[in] Treble cutoff frequency in Hertz. + * + * \note The upper and lower limits of this parameter is checked. + */ +void SFEMP3Shield::setTrebleFrequency(int frequency) +{ + frequency /= 1000; + + if(frequency < 1) + { + frequency = 1; + } + else if(frequency > 15) + { + frequency = 15; + } + _st_freqlimit = frequency; + changeBass(); +} + +//------------------------------------------------------------------------------ +/** + * \brief Set the current Treble Amplitude in VS10xx chip + * Based on Mbed lib. + * + * \param[in] Treble amplitude in dB from -8 to 7. + * + * \note The upper and lower limits of this parameter is checked. + */ +void SFEMP3Shield::setTrebleAmplitude(int amplitude) +{ + if(amplitude < -8) + { + amplitude = -8; + } + else if(amplitude > 7) + { + amplitude = 7; + } + _st_amplitude = amplitude; + changeBass(); +} + +//------------------------------------------------------------------------------ +/** + * \brief Set the current Bass Boost Frequency cutoff in VS10xx chip + * Based on Mbed lib. + * + * \param[in] Bass Boost frequency cutof in Hertz (20Hz to 150Hz). + * + * \note The upper and lower limits of this parameter is checked. + */ +void SFEMP3Shield::setBassFrequency(int frequency) +{ + frequency /= 10; + + if(frequency < 2) + { + frequency = 2; + } + else if(frequency > 15) + { + frequency = 15; + } + _sb_freqlimit = frequency; + changeBass(); +} + +//------------------------------------------------------------------------------ +/** + * \brief Set the current Bass Boost amplitude in VS10xx chip + * Based on Mbed lib. + * + * \param[in] Bass Boost amplitude in dB (0dB to 15dB). + * + * \note The upper and lower limits of this parameter is checked. + */ +void SFEMP3Shield::setBassAmplitude(int amplitude) +{ + if(amplitude < 0) + { + amplitude = 0; + } + else if(amplitude > 15) + { + amplitude = 15; + } + _sb_amplitude = amplitude; + changeBass(); +} + +//------------------------------------------------------------------------------ +/** + * \brief Actually writes the SCI_BASS register. + * Based on Mbed lib. * + */ +void SFEMP3Shield::changeBass(void) +{ + unsigned short bassCalced = ((_st_amplitude & 0x0f) << 12) + | ((_st_freqlimit & 0x0f) << 8) + | ((_sb_amplitude & 0x0f) << 4) + | ((_sb_freqlimit & 0x0f) << 0); + + Mp3WriteRegister(SCI_BASS, bassCalced); +} //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // @{ diff --git a/SFEMP3Shield/SFEMP3Shield.h b/SFEMP3Shield/SFEMP3Shield.h index e1f662a..82d7fa2 100644 --- a/SFEMP3Shield/SFEMP3Shield.h +++ b/SFEMP3Shield/SFEMP3Shield.h @@ -434,7 +434,8 @@ extern SdFat sd; * \brief A macro of the VS_LINE1_MODE to configure either Line level or * microphone input. * - * Used by SFEMP3Shield::ADMixerLoad to determine if the SM_LINE1 of SCI_MODE being set as to + * Used by SFEMP3Shield::ADMixerLoad and SFEMP3Shield::startRecordOgg + * to determine if the SM_LINE1 of SCI_MODE being set as to * use both MICP and LINEIN1 pins as \b stereo input, at line levels. * Commenting it out, will result MICP and MICN used as differential input with * resulting \b mono signal on the left channel. @@ -442,7 +443,8 @@ extern SdFat sd; * \see SM_LINE1 */ // configure Line1 as single ended, otherwise as differential 10x gain for microphones. -#define VS_LINE1_MODE + +//#define VS_LINE1_MODE @@ -657,6 +659,37 @@ extern SdFat sd; * /@} */ + +/* Recording definitions */ +#define VS1053_INT_ENABLE 0xC01A + +#define CHANNEL1 0x0008 // Used to set bit 3 of SCI_AICTRL3. +#define CHANNEL2 0x0000 + +#define USE_INPUT_CHANNEL2 + +#if defined(USE_INPUT_CHANNEL2) +#define CHANNEL_CONFIG CHANNEL2 +#else +#define CHANNEL_CONFIG CHANNEL1 +#endif + +//------------------------------------------------------------------------------ +/** \name BassTreble_Group + * Bass and Treble group. + * /@{ + */ +/** + * \brief Default values according with the datasheet. + */ +#define DEFAULT_BASS_AMPLITUDE 0 // 0 - 15 dB +#define DEFAULT_BASS_FREQUENCY 10 // 20 - 150 Hz +#define DEFAULT_TREBLE_AMPLITUDE -2 // -8 - 7 dB +#define DEFAULT_TREBLE_FREQUENCY 5 //1000 - 15000 Hz +/** End BassTreble_Group + * /@} + */ + //------------------------------------------------------------------------------ /** * \class SFEMP3Shield @@ -664,11 +697,21 @@ extern SdFat sd; */ class SFEMP3Shield { public: + SFEMP3Shield(); // Constructor uint8_t begin(); void end(); uint8_t vs_init(); void setVolume(uint8_t, uint8_t); void setVolume(uint16_t); + int getTrebleFrequency(void); + int getTrebleAmplitude(void); + int getBassFrequency(void); + int getBassAmplitude(void); + void setTrebleFrequency(int frequency); + void setTrebleAmplitude(int amplitude); + void setBassFrequency(int frequency); + void setBassAmplitude(int amplitude); + void changeBass(void); void setPlaySpeed(uint16_t); uint16_t getPlaySpeed(); uint16_t getVolume(); @@ -705,8 +748,17 @@ class SFEMP3Shield { int8_t getVUmeter(); int8_t setVUmeter(int8_t); int16_t getVUlevel(); + uint8_t startRecordOgg(char* fileName, char* pluginfileName); + uint16_t doRecordOgg(void); + void stopRecording(void); + uint8_t isRecording(void); + uint8_t setRecGain(uint8_t gain); + void bindEndRecordHandler(void (*Handler)(void)); private: + uint8_t StopRecFlag; + uint8_t RecordingFlag; + void (*EndRecHandlerFunc)(void); static SdFile track; static void refill(); static void flush_cancel(flush_m); @@ -747,6 +799,11 @@ class SFEMP3Shield { /** \brief contains a local value of the VSdsp's master volume Right channels*/ uint8_t VolR; + + int _sb_amplitude;// DEFAULT_BASS_AMPLITUDE; + int _sb_freqlimit;// DEFAULT_BASS_FREQUENCY; + int _st_amplitude;// DEFAULT_TREBLE_AMPLITUDE; + int _st_freqlimit;// DEFAULT_TREBLE_FREQUENCY; }; //------------------------------------------------------------------------------ diff --git a/SFEMP3Shield/SFEMP3ShieldConfig.h b/SFEMP3Shield/SFEMP3ShieldConfig.h index 627eb0f..92869d2 100644 --- a/SFEMP3Shield/SFEMP3ShieldConfig.h +++ b/SFEMP3Shield/SFEMP3ShieldConfig.h @@ -169,6 +169,24 @@ Support for Arduino Leonardo is afflicted by having the SPI pins not routing the #endif // GRAVITECH #endif // none SEEEDUINO + +// If using a TEENSY 2.0++ board: +#if defined(__AVR_AT90USB1286__) + // Removing previous definition. + #undef MP3_XCS + #undef MP3_XDCS + #undef MP3_DREQ + #undef MP3_DREQINT + #undef MP3_RESET + #undef SD_SEL + #define MP3_XCS 10 //Control Chip Select Pin (for accessing SPI Control/Status registers) + #define MP3_XDCS 11 //Data Chip Select / BSYNC Pin + #define MP3_DREQ 0 //Data Request Pin: Player asks for more data + #define MP3_DREQINT 0 //Corresponding INTx for DREQ pin + #define MP3_RESET 12 //Reset is active low + #define SD_SEL 20 //select pin for SD card +#endif + //------------------------------------------------------------------------------ /** * \def USE_MP3_REFILL_MEANS diff --git a/plugins/recorder_plugins.zip b/plugins/recorder_plugins.zip new file mode 100644 index 0000000..3af715f Binary files /dev/null and b/plugins/recorder_plugins.zip differ