Library for VS1053 chip

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VLSIcodec.c Source File

VLSIcodec.c

00001 /** mbed VLSIcodec library. To access VS1053 MPEG3 codec.
00002 
00003     Copyright (c) 2010 NXP 3790 
00004  
00005     Permission is hereby granted, free of charge, to any person obtaining a copy
00006     of this software and associated documentation files (the "Software"), to deal
00007     in the Software without restriction, including without limitation the rights
00008     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009     copies of the Software, and to permit persons to whom the Software is
00010     furnished to do so, subject to the following conditions:
00011  
00012     The above copyright notice and this permission notice shall be included in
00013     all copies or substantial portions of the Software.
00014  
00015     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021     THE SOFTWARE.
00022 */
00023  
00024 #include "mbed.h"
00025 #include "VLSIcodec.h"
00026 #include "VLSIcodec_patch.h"
00027 
00028 #ifdef __ENCODE_OGG
00029 #include "VLSIcodec_OGG.h"
00030 #endif
00031 
00032 #ifdef __PLUGINGA
00033 #include "VLSIcodec_pluginGA.h"
00034 #define cBASE   0x1800  /* Base address of X-RAM for a VS1053 */
00035 #endif
00036 
00037 
00038 //******************************************************************************
00039 //******************************************************************************
00040 // Section: Constants
00041 //******************************************************************************
00042 //******************************************************************************
00043 
00044 #define VLSI_MODE           0x00
00045 #define VLSI_STATUS         0x01
00046 #define VLSI_BASS           0x02
00047 #define VLSI_CLOCKF         0x03
00048 #define VLSI_DECODE_TIME    0x04
00049 #define VLSI_AUDATA         0x05
00050 #define VLSI_WRAM           0x06
00051 #define VLSI_WRAMADDR       0x07
00052 #define VLSI_HDAT0          0x08
00053 #define VLSI_HDAT1          0x09
00054 #define VLSI_AIADDR         0x0A
00055 #define VLSI_VOL            0x0B
00056 #define VLSI_AICTRL0        0x0C
00057 #define VLSI_AICTRL1        0x0D
00058 #define VLSI_AICTRL2        0x0E
00059 #define VLSI_AICTRL3        0x0F
00060 
00061 #define VLSI_STATUS_VER     0x00F0u
00062 #define VER_VS1001          (0u<<4)
00063 #define VER_VS1011          (1u<<4)
00064 #define VER_VS1002          (2u<<4)
00065 #define VER_VS1011E         (2u<<4)
00066 #define VER_VS1003          (3u<<4)
00067 #define VER_VS1053          (4u<<4)
00068 #define VER_VS1033          (5u<<4)
00069 #define VER_VS1103          (7u<<4)
00070 
00071 #define cWAIT_DREQ_1MS        wait_ms( 1); while (!_dreq);
00072 #define cWAIT_DREQ            while (!_dreq);
00073                             
00074 /* VLSI 1053, MODE Register bit configuration. */
00075 #define SM_DIFF                0x01   
00076 #define SM_LAYER12            0x02   
00077 #define SM_RESET            0x04   
00078 #define SM_CANCEL            0x08   
00079 #define SM_EARSPEAKER_LO    0x10   
00080 #define SM_TESTS            0x20   
00081 #define SM_STREAM            0x40   
00082 #define SM_EARSPEAKER_HI    0x80   
00083 #define SM_DACT                0x100   
00084 #define SM_SDIORD            0x200   
00085 #define SM_SDISHARE            0x400   
00086 #define SM_SDINEW            0x800   
00087 #define SM_ADPCM            0x1000   
00088 #define SM_NOTUSE            0x2000
00089 #define SM_LINE1            0x4000
00090 #define SM_CLK_RANGE        0x8000
00091 
00092 /* SC MULT MASK CLKI */
00093 #define SC_MULT_0         0x0000    /* XTALI */
00094 #define SC_MULT_2         0x2000    /* XTALI×2.0 */
00095 #define SC_MULT_2_5     0x4000    /* XTALI×2.5 */
00096 #define SC_MULT_3         0x6000    /* XTALI×3.0 */
00097 #define SC_MULT_3_5     0x8000    /* XTALI×3.5 */
00098 #define SC_MULT_4         0xA000    /* XTALI×4.0 */
00099 #define SC_MULT_4_5     0xC000    /* XTALI×4.5 */
00100 #define SC_MULT_5         0xE000    /* XTALI×5.0 */
00101 
00102 /* 
00103  SC ADD tells how much the decoder firmware is allowed to add to the multiplier specified by SC MULT
00104  if more cycles are temporarily needed to decode a WMA or AAC stream. The values are:
00105  SC ADD MASK Multiplier addition 
00106 */
00107 #define SC_ADD_NOMOD    0x0000    /* No modification is allowed */
00108 #define SC_ADD_X1         0x0800    /* 1.0× */
00109 #define SC_ADD_X1_5     0x1000    /* 1.5× */
00110 #define SC_ADD_X2        0x1800    /* 2.0× */
00111 
00112 #define SC_FREQ            0x0000    /* 12.288 MHz clock. */
00113 
00114 /*
00115 */
00116 #define cMODEREG_SET    ( SM_SDINEW )
00117 #define cCLOCK_SET        ( SC_MULT_5 | SC_ADD_X1 | SC_FREQ)
00118 
00119 #define VS1053_CS_ENABLE        _cs=0;
00120 #define VS1053_CS_DISABLE       _cs=1;
00121 #define VS1053_XDCS_ENABLE      _xdcs=0;
00122 #define VS1053_XDCS_DISABLE     _xdcs=1;
00123 #define VS1053_RST_ENABLE       _rst=0;
00124 #define VS1053_RST_DISABLE      _rst=1;
00125 
00126 /*
00127 */
00128 #define cVS1053_CS_DELAY        50
00129 
00130 /** VS1053Codec
00131 */
00132 VS1053Codec::VS1053Codec(  PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dreq, PinName rst, PinName xdcs) : _spi( mosi, miso, sclk), _cs( cs), _dreq( dreq), _rst( rst), _xdcs( xdcs) {
00133     // defaults params
00134     VS1053_CS_DISABLE;
00135     VS1053_XDCS_DISABLE;
00136 }
00137 
00138 /** Wait untile the dreq is released
00139 * @param none
00140 * @retval none
00141 */
00142 void VS1053Codec::testdreq( void){
00143     while( !_dreq);
00144 }
00145    
00146 /** Put the VS1053 in low power mode (RESET)
00147 * 
00148 * @param none
00149 * @retval none
00150 */ 
00151 void VS1053Codec::lowpower( void)
00152 {
00153     VS1053_RST_ENABLE;
00154     wait_ms( 10);
00155 }
00156 
00157 /** Initialize the VS1053
00158 */
00159 void VS1053Codec::init(void)
00160 {
00161     //
00162     VS1053_RST_DISABLE;
00163     VS1053_CS_DISABLE;
00164     VS1053_XDCS_DISABLE;
00165     //
00166     _spi.format( 8, 0);
00167     _spi.frequency( MP3_INIT_SPEED);
00168     
00169     // Assert RESET
00170     VS1053_RST_ENABLE;
00171     wait_ms( 100);
00172     
00173     // Deassert RESET (active low)
00174     VS1053_RST_DISABLE;
00175     VS1053_CS_DISABLE;
00176     VS1053_XDCS_DISABLE;
00177     wait_ms( 100);
00178     
00179     // Wait 
00180     while(!_dreq);
00181     
00182     // Reset the vs1053
00183     writereg( VLSI_MODE, ( cMODEREG_SET | SM_RESET) );
00184     wait_ms( 10);
00185     
00186     // Wait...
00187     while(!_dreq); 
00188 
00189     /*
00190     * Write configuration MODE register in a loop to verify that the chip is
00191     * connected and running correctly
00192     */
00193     do
00194     {
00195         writereg( VLSI_MODE, ( cMODEREG_SET ));
00196         wait_ms( 1);
00197     }while( readreg( VLSI_MODE) != ( cMODEREG_SET ));
00198 
00199     //
00200     if((readreg( VLSI_STATUS) & VLSI_STATUS_VER) == VER_VS1053)
00201     {
00202         // Set the clock to maximum speed (VS1053 only) to allow all audio formats
00203         // to be decoded without glitching.  Note that this increases power
00204         // consumption.
00205         // SC_MULT = XTALI*4.5, SC_ADD = noMod, SC_FREQ = 0 (12.288MHz)
00206         // VLSIWriteReg(VLSI_CLOCKF, SC_MULT_4_5 | SC_ADD_X1 | SC_FREQ);
00207         
00208         writereg(VLSI_CLOCKF, cCLOCK_SET);
00209         
00210         /* */
00211         wait_ms( 2);
00212         while(!_dreq);
00213     }
00214     else if ((readreg( VLSI_STATUS) & VLSI_STATUS_VER) == VER_VS1011E)
00215     {
00216         // Nothing special to do
00217         ;
00218     }
00219     else
00220     {
00221         // VLSI Chip version not tested, not supported, halt program execution.
00222         // This trap should be caught during the design phase.
00223         while(1);
00224     }
00225 
00226     _spi.frequency( MP3_RUN_SPEED);
00227 }
00228 
00229 void VS1053Codec::loadpatch(void) 
00230 /* Questa funzione carica una patch al firmware del codec */
00231 {
00232     int i = 0, plgin_len;
00233     unsigned int addr, n, val;
00234     
00235     plgin_len=sizeof( plugin)/sizeof(plugin[0]);
00236     while (i<plgin_len) {
00237 
00238         addr = plugin[i++];
00239         n = plugin[i++];
00240         if (n & 0x8000U) { /* RLE run, replicate n samples */
00241             n &= 0x7FFF;
00242             val = plugin[i++];
00243             while (n--) {
00244                 writeregnowait(addr, val); 
00245                 while(!_dreq); 
00246             }
00247         } else {           /* Copy run, copy n samples */
00248             while (n--) {
00249                 val = plugin[i++];
00250                 writeregnowait(addr, val); 
00251                 while(!_dreq);
00252             }
00253         }
00254     }
00255     //
00256     wait_ms( 1);
00257     while(!_dreq);
00258 }
00259 
00260 #ifdef __PLUGINGA
00261 void VS1053Codec::loadgapatch(void) 
00262 /* Questa funzione carica un plugin nel codec */
00263 {
00264     int i = 0, plgin_len;
00265     unsigned int addr, n, val;
00266     
00267     plgin_len=sizeof( gaplugin)/sizeof(gaplugin[0]);
00268     while (i<plgin_len) {
00269 
00270         addr = gaplugin[i++];
00271         n = gaplugin[i++];
00272         if (n & 0x8000U) { /* RLE run, replicate n samples */
00273             n &= 0x7FFF;
00274             val = gaplugin[i++];
00275             while (n--) {
00276                 writeregnowait(addr, val); 
00277                 while(!_dreq); 
00278             }
00279         } else {           /* Copy run, copy n samples */
00280             while (n--) {
00281                 val = gaplugin[i++];
00282                 writeregnowait(addr, val); 
00283                 while(!_dreq);
00284             }
00285         }
00286     }
00287     //
00288     wait_ms( 1);
00289     while(!_dreq);
00290 }
00291 #endif
00292 
00293 #ifdef __ENCODE_OGG
00294 void VS1053Codec::loadoggpatch(void) 
00295 /* Questa funzione carica una patch per gestire l'encoder OGG */
00296 {
00297     int i = 0, plgin_len;
00298     unsigned int addr, n, val;
00299     
00300     plgin_len=sizeof( ogg_enc)/sizeof(ogg_enc[0]);
00301     while (i<plgin_len) {
00302 
00303         addr = ogg_enc[i++];
00304         n = ogg_enc[i++];
00305         if (n & 0x8000U) { /* RLE run, replicate n samples */
00306             n &= 0x7FFF;
00307             val = ogg_enc[i++];
00308             while (n--) {
00309                 writeregnowait(addr, val); 
00310                 while(!_dreq); 
00311             }
00312         } else {           /* Copy run, copy n samples */
00313             while (n--) {
00314                 val = ogg_enc[i++];
00315                 writeregnowait(addr, val); 
00316                 while(!_dreq);
00317             }
00318         }
00319     }
00320     //
00321     wait_ms( 1);
00322     while(!_dreq);
00323 }
00324 #endif
00325 
00326 #ifdef __PLUGINGA    
00327 void VS1053Codec::readgavalue( unsigned char *currval, unsigned char *peak)
00328 {
00329     writereg( VLSI_WRAMADDR, cBASE+2);
00330     unsigned short bands = (unsigned short)readreg( VLSI_WRAM);
00331     //
00332     writereg( VLSI_WRAMADDR, cBASE+4);
00333     //
00334     for (int i=0;i<bands;i++) {
00335         short pv = readreg( VLSI_WRAM); 
00336         /* current value in bits 5..0, normally 0..31
00337         peak value in bits 11..6, normally 0..31 */
00338         currval[i]=(unsigned char)(pv&0x003F);
00339         peak[i]=(unsigned char)( (pv>>6)&0x003F);
00340     }
00341 }
00342 
00343 unsigned short VS1053Codec::readgabands( void)
00344 {
00345     writereg( VLSI_WRAMADDR, cBASE+2);
00346     unsigned short bands = (unsigned short)readreg( VLSI_WRAM);
00347     /* */
00348     return bands;
00349 }
00350 
00351 #endif
00352 
00353 void VS1053Codec::setvmeter( void)
00354 {
00355     unsigned short tmp;
00356     
00357     tmp=(unsigned short)readreg( VLSI_STATUS);
00358     tmp|=(1<<9);
00359     writereg( VLSI_STATUS, tmp);
00360 }
00361 
00362 void VS1053Codec::getvmeterval( unsigned char* left, unsigned char* right)
00363 {
00364     unsigned short tmp;
00365     
00366     tmp=(unsigned short)readreg( VLSI_AICTRL3);
00367     
00368     *right=(unsigned char)tmp&0x00FF;
00369     *left=(unsigned char)(tmp>>8);
00370 }
00371 
00372 /****************************************************************************
00373   Function:
00374     void VS1053Codec::setbassboost(BYTE bass, BYTE gfreq)
00375 
00376   Description:
00377     This function sets the bass boost.
00378 
00379   Precondition:
00380     None
00381 
00382   Parameters:
00383     BYTE bass   - Bass gain in dB, range from 0 to 15 (MSB nibble)
00384     BYTE gfreq  - Limit frequency for bass boost, 10 Hz steps (range from
00385                     20 to 150) (LSB nibble)
00386 
00387   Returns:
00388     None
00389 
00390   Remarks:
00391     None
00392   ***************************************************************************/
00393 void VS1053Codec::setbassboost( unsigned char bass, unsigned char gfreq)
00394 {
00395     unsigned char templ;
00396     unsigned short tmp;
00397 
00398     // 
00399     if(bass > 15u)
00400         bass = 15;
00401     if(gfreq > 150u)
00402         gfreq = 150;
00403     if ( gfreq < 20)
00404         gfreq = 20;
00405         
00406 
00407     // 
00408     templ = (unsigned char)gfreq/10;
00409 
00410     // put bass boost value into the upper 4 bit
00411     templ |= (bass << 4);
00412     //
00413     tmp=(unsigned short)readreg( VLSI_BASS);
00414     tmp &= 0xFF00;
00415     tmp |= templ;
00416     //
00417     writereg( VLSI_BASS, tmp);
00418 }
00419 
00420 /****************************************************************************
00421   Function:
00422     void VS1053Codec::settrebleboost(BYTE bass, WORD gfreq)
00423 
00424   Description:
00425     This function sets the bass boost.
00426 
00427   Precondition:
00428     None
00429 
00430   Parameters:
00431     BYTE treble   - Bass gain in dB, range from -8 to 7 (MSB nibble)
00432     WORD gfreq    - Limit frequency for bass boost, 1000 Hz steps (range from
00433                     1000 to 15000) (LSB nibble)
00434 
00435   Returns:
00436     None
00437 
00438   Remarks:
00439     None
00440   ***************************************************************************/
00441 void VS1053Codec::settrebleboost( char treble, unsigned int gfreq)
00442 {
00443     unsigned char templ;
00444     unsigned short tmp;
00445 
00446     // 
00447     if(treble > 7)
00448         treble = 7;
00449     if ( treble < (char)-8)
00450         treble = (char)-8;
00451         
00452     if(gfreq > 15000u)
00453         gfreq = 15000;
00454     if(gfreq < 1000)
00455         gfreq = 1000;
00456 
00457     // 
00458     templ = (unsigned char)gfreq/1000;
00459 
00460     // put treble boost value into the upper 4 bit
00461     templ |= (treble << 4);
00462     //
00463     tmp=(unsigned short)readreg( VLSI_BASS);
00464     tmp &= 0x00FF;
00465     tmp |= (templ << 8);
00466     //
00467     writereg( VLSI_BASS, tmp);
00468 }
00469 
00470 void VS1053Codec::getplaytime(char *playtime)
00471 {
00472     unsigned short playTime;
00473     unsigned char minutes, seconds;
00474     
00475     playTime = (unsigned short)readreg(VLSI_DECODE_TIME);
00476     minutes = playTime/60;
00477     seconds = playTime%60;
00478     *playtime++=('0'+minutes/10);
00479     *playtime++=('0'+minutes%10);
00480     *playtime++=(':');
00481     *playtime++=('0'+seconds/10);
00482     *playtime++=('0'+seconds%10);
00483 }
00484 
00485 
00486 /****************************************************************************
00487   Function:
00488     void setvolume(unsigned char vRight, unsigned char vLeft)
00489 
00490   Description:
00491     This function set volume for analog outputs on the VLSI codec.
00492 
00493   Precondition:
00494     None
00495 
00496   Parameters:
00497     unsigned char vRight - right channel attenuation from maximum volume, 0.5dB steps
00498                         (0x00 = full volume, 0xFF = muted)
00499     unsigned char vLeft  - left channel attenuation from maximum volume, 0.5dB steps
00500                         (0x00 = full volume, 0xFF = muted)
00501 
00502   Returns:
00503     None
00504 
00505   Remarks:
00506     None
00507   ***************************************************************************/
00508 void VS1053Codec::setvolume(unsigned char vRight, unsigned char vLeft)
00509 {
00510     writereg(VLSI_VOL, ((unsigned int)vLeft)<<8 | vRight);
00511 }
00512 
00513 
00514 void VS1053Codec::sinetest( unsigned char pitch)
00515 {
00516     unsigned int i;
00517     
00518     while(!_dreq);
00519     
00520     i=(unsigned short)readreg( VLSI_MODE);
00521     writereg( VLSI_MODE, ( i | SM_TESTS ));
00522     
00523     VS1053_XDCS_ENABLE;
00524     
00525     if ( pitch) {
00526         // START Sine Test
00527         _spi.write(0x53);
00528         _spi.write(0xEF);
00529         _spi.write(0x6E);
00530         _spi.write( pitch);
00531         _spi.write(0x00);
00532         _spi.write(0x00);
00533         _spi.write(0x00);
00534         _spi.write(0x00);
00535     } else {
00536         // STOP Sine Test
00537         _spi.write(0x45);
00538         _spi.write(0x78);
00539         _spi.write(0x69);
00540         _spi.write(0x74);
00541         _spi.write(0x00);
00542         _spi.write(0x00);
00543         _spi.write(0x00);
00544         _spi.write(0x00);
00545     }    
00546     
00547     VS1053_XDCS_DISABLE;
00548 
00549 }
00550 
00551 void VS1053Codec::writedata( unsigned char data)
00552 /*
00553 * Write data to SDI.
00554 */
00555 {
00556     int i=0;
00557     
00558     VS1053_XDCS_ENABLE;
00559     for( i=0; i<cVS1053_CS_DELAY; i++);
00560     
00561     _spi.write( data);
00562     
00563     for( i=0; i<cVS1053_CS_DELAY; i++);
00564     VS1053_XDCS_DISABLE;
00565     
00566 }
00567     
00568 //******************************************************************************
00569 //******************************************************************************
00570 //******************************************************************************
00571 // Section: Internal Functions
00572 //******************************************************************************
00573 //******************************************************************************
00574 //******************************************************************************
00575 
00576 
00577 unsigned short VS1053Codec::readreg(unsigned char vAddress)
00578 {
00579     unsigned short wValue;
00580     unsigned int i;
00581     
00582     VS1053_CS_ENABLE;
00583     for ( i=0; i<cVS1053_CS_DELAY;i++);
00584     
00585     _spi.write(0x03);     // Read
00586     _spi.write(vAddress); // Register address
00587     ((unsigned char*)&wValue)[1] = _spi.write(0xFF);   // 8 bit value high byte
00588     ((unsigned char*)&wValue)[0] = _spi.write(0xFF);   // 8 bit value low byte
00589     
00590     for ( i=0; i<cVS1053_CS_DELAY;i++);
00591     VS1053_CS_DISABLE;
00592 
00593     return wValue;
00594 }
00595 
00596 void VS1053Codec::writereg(unsigned char vAddress, unsigned int wValue)
00597 {
00598     int i;
00599     
00600     while(!_dreq);
00601     
00602     VS1053_CS_ENABLE;
00603     for ( i=0; i<cVS1053_CS_DELAY;i++);
00604     
00605     _spi.write(0x02);     // Write
00606     _spi.write(vAddress); // Register address
00607     _spi.write(((unsigned char*)&wValue)[1]);      // 8 bit value to write high byte
00608     _spi.write(((unsigned char*)&wValue)[0]);      // 8 bit value to write low byte
00609     
00610     for ( i=0; i<cVS1053_CS_DELAY;i++);
00611     VS1053_CS_DISABLE;
00612     
00613 }
00614 
00615 
00616 /* */
00617 void VS1053Codec::reset( void)
00618 {
00619     // Reset the vs1053
00620     writereg(VLSI_MODE, ( cMODEREG_SET | SM_RESET) );
00621     wait_ms( 5);
00622     // Wait...
00623     while(!_dreq);
00624 
00625     // Configure CLOCK register.
00626     writereg(VLSI_CLOCKF, cCLOCK_SET);
00627     wait_ms( 5);
00628     // Wait...
00629     while(!_dreq);
00630 }
00631     
00632 
00633 void VS1053Codec::writeregnowait(unsigned char vAddress, unsigned int wValue)
00634 /*
00635  Write to SCI interface without waiting for the DREQ pin
00636 */
00637 {
00638     int i;
00639     
00640     VS1053_CS_ENABLE;
00641     for ( i=0; i<cVS1053_CS_DELAY;i++);
00642     
00643     _spi.write(0x02);     // Write
00644     _spi.write(vAddress); // Register address
00645     _spi.write(((unsigned char*)&wValue)[1]);      // 8 bit value to write high byte
00646     _spi.write(((unsigned char*)&wValue)[0]);      // 8 bit value to write low byte
00647     
00648     for ( i=0; i<cVS1053_CS_DELAY;i++);
00649     VS1053_CS_DISABLE;
00650     
00651 }
00652 
00653 #ifdef __ENCODE_OGG
00654 void VS1053Codec::VoggEncoding_Start( void)
00655 /* VorbisEncoder160c pag. 9 */
00656 {
00657     unsigned short temp;
00658     
00659 /* 2. vs1053b at 55.3MHz */
00660     writeregnowait( VLSI_CLOCKF, 0xC000);         cWAIT_DREQ_1MS;
00661 /* 3. SCI_BASS to 0 */
00662     writeregnowait( VLSI_BASS, 0x0000);         cWAIT_DREQ_1MS;
00663 /* 4. Disable user application (no wait fot DREQ pin and no delay, as from the VLSI source file example */
00664 /*    record.c from playercode1053-Aug2009.zip                                                             */
00665     writeregnowait( VLSI_AIADDR, 0x0000); 
00666 /* 5. Disable all IRQ except the SCI IRQ */
00667     writeregnowait( VLSI_WRAMADDR, 0xC01A);
00668     writeregnowait( VLSI_WRAM, 0x0002); 
00669 /* 6. Load the plugin code... */
00670     loadoggpatch();
00671 /* 7. Set bit SM_ADPCM to 1. */
00672     temp = (unsigned short)readreg( VLSI_MODE);                cWAIT_DREQ_1MS;
00673     temp |= SM_ADPCM;
00674     writeregnowait( VLSI_MODE, temp);             cWAIT_DREQ_1MS;
00675     writeregnowait( VLSI_AICTRL0, 0x0000);         cWAIT_DREQ_1MS;
00676 /* 8. Set recording level. Value are for conservative AGC. */
00677     writeregnowait( VLSI_AICTRL1, 0x0000);         cWAIT_DREQ_1MS;
00678     writeregnowait( VLSI_AICTRL2, 4096);         cWAIT_DREQ_1MS;
00679 /* 10. Set 0 to SCI_AICTRL3. */
00680     writeregnowait( VLSI_AICTRL3, 0x0000);         cWAIT_DREQ_1MS;
00681 /* 11. Active the encoder... */
00682     wait_ms( 5);
00683     writeregnowait( VLSI_AIADDR, 0x0034); wait_ms( 1);
00684 /* 12. wait DREQ high. */
00685     cWAIT_DREQ;                /* Loop forever. */
00686 
00687 }
00688 
00689 #if 0
00690 void VS1053Codec::VoggEncoding_ReadStatus( RUNTIME_VOGG_VALUE *status)
00691 /* VorbisEncoder160c par 2.3.4, pag. 11                 */
00692 /* see VLSICodec.h for RUNTIME_VOGG_VALUE struct data.  */
00693 {
00694     unsigned short temp, temph;
00695     
00696     /* Recording Time */
00697     writereg( VLSI_WRAMADDR, 0x0008); cWAIT_DREQ_1MS;
00698     temp = (unsigned short)readreg( VLSI_WRAM);                                /* LSB recording Time */
00699     temph= (unsigned short)readreg( VLSI_WRAM);                                /* MSB recording Time */
00700     status->rec_time = ((unsigned long)temph << 16) | temp;    
00701 
00702     /* Average bitrate */
00703     writereg( VLSI_WRAMADDR, 0x000C); cWAIT_DREQ_1MS;
00704     temp = (unsigned short)readreg( VLSI_WRAM);                                /* LSB Average bitrate */
00705     temph= (unsigned short)readreg( VLSI_WRAM);                                /* MSB Average bitrate */
00706     status->average_bitrate = ((unsigned long)temph << 16) | temp;    
00707 
00708     /* Sample Counter */
00709     writereg( VLSI_WRAMADDR, 0x1800); cWAIT_DREQ_1MS;
00710     temp = (unsigned short)readreg( VLSI_WRAM);                                /* LSB Sample Counter */
00711     temph= (unsigned short)readreg( VLSI_WRAM);                                /* MSB Average bitrate */
00712     status->sample_counter = ((unsigned long)temph << 16) | temp;
00713 }
00714 #endif
00715     
00716     
00717 /*
00718 * Questa funzione legge il registro SCI_HDAT1 per verificare la presenza di 
00719 * sample disponibili. In caso ci siano li legge dal reg. SCI_HDAT0 
00720 * salvandoli nel puntatore passatogli. Ritorna il numero di byte copiati.
00721 */
00722 unsigned int VS1053Codec::VoggEncoding_ReadBuffer( unsigned char *voggSample)
00723 /* VorbisEncoder160c pag. 10 */
00724 {
00725     unsigned int  i;
00726     unsigned short temp, sample;
00727     
00728     temp=0;
00729     i=0;
00730     sample=0;
00731 
00732 //    printf("readbuffer\r\n");
00733     
00734     do {
00735         /* reading the sample counter... */
00736         temp = (unsigned short)readreg( VLSI_HDAT1);
00737         if ( temp ) {
00738 //            printf("sample %d\r\n", temp);
00739             /* there are samples... */
00740             i=0;
00741             while( i < temp) {
00742                 /* read the sample as word */
00743                 sample=(unsigned short)readreg( VLSI_HDAT0);
00744                 /* save it into the array as single byte. */
00745                 *voggSample++ = (unsigned char)(sample >> 8);                /* MSB */
00746                 *voggSample++ = (unsigned char)(sample & 0x00FF);            /* LSB */
00747                 i++;
00748                 wait_ms( 1);
00749             }    
00750             
00751             /* Exit the loop. */
00752             break;
00753         } else {
00754 //            printf("no sample\r\n");
00755             /* Exit the loop. */
00756             break;
00757         }    
00758     } while( 1);    
00759     /* just relax... */
00760     wait_ms( 1);
00761     /* Return the number of byte saved. */
00762     return i*2;
00763 }
00764     
00765 /* 
00766 * Questa funzione esegue la procedura di fine encoding memorizzando i rimanenti sample
00767 * nel puntatore passatogli. Ritorna il numero di sample letti.
00768 */
00769 unsigned int VS1053Codec::VoggEncoding_Stop( unsigned char *voggSample)
00770 /* VorbisEncoder160c pag. 11 */
00771 {
00772     unsigned int res, i, ii;
00773     unsigned short temp, sample;
00774     res=0;
00775     temp=0;
00776     sample=0;
00777     
00778 /* 1. set bit 0 to 1 */
00779     temp = (unsigned short)readreg( VLSI_AICTRL3);
00780     temp |= 0x0001;
00781     writereg( VLSI_AICTRL3, temp);
00782     
00783 /* 2. continue reading data but checking the bit 1 of VLSI_AICTRL3 reg. */
00784     res=0;
00785     do {
00786         /* reading the sample counter... */
00787         temp = (unsigned short)readreg( VLSI_HDAT1);
00788         if ( temp) {
00789 //            printf("EncStop: %d\r\n", temp);
00790             i=0;
00791             while( i < temp ) {
00792                 /* */
00793                 sample = (unsigned short)readreg( VLSI_HDAT0);
00794                 *voggSample++ = (unsigned char)(sample >> 8);
00795                 *voggSample++ = (unsigned char)sample & 0x00FF;
00796                 i++;
00797                 wait_ms( 1);
00798             }
00799             res+=i;
00800         }
00801         /* just relax... */
00802         wait_ms( 1);
00803         temp = (unsigned short)readreg( VLSI_AICTRL3);
00804         /* verify the bit 1 of VLSI_AICTRL3 reg. */
00805         if ( temp & 0x0002) {
00806 //            printf("Encoding STOP\r\n");
00807             /* encoding has finished. */
00808             break;
00809         }    
00810     } while( 1);    /* Loop forever... */
00811 /* 3. write the remaining word... */
00812     ii=0;
00813     do {
00814         temp = (unsigned short)readreg( VLSI_HDAT1);
00815         if ( temp) {
00816 //            printf("Flush %d\r\n", temp);
00817             /* there are samples... */
00818             i=0;
00819             while( i < temp ) {            /* con il numero precedente. */
00820                 /* */
00821                 sample = (unsigned short)readreg( VLSI_HDAT0);
00822                 *voggSample++ = (unsigned char)(sample >> 8);
00823                 *voggSample++ = (unsigned char)sample & 0x00FF;                
00824                 i++;
00825                 wait_ms( 1);
00826             }    
00827             res+=i;
00828         } else {
00829             wait_ms( 1);
00830             ii++;
00831         }
00832     } while( ii<5);    /* Loops ... */
00833 /* 4. read twise AICTRL3 */
00834     temp = (unsigned short)readreg( VLSI_AICTRL3);
00835     temp = (unsigned short)readreg( VLSI_AICTRL3);
00836 //    printf("last read %d\r\n", temp);
00837     if ( temp & 0x0004 ) {
00838         /* remove last byte ( bits 7:0) from the last word. */
00839         voggSample--;
00840         *voggSample=0;
00841         res=(res*2)-1;
00842     } else {
00843         res=res*2;
00844     }
00845 /* 5. Reset the codec. */
00846 
00847     /* Ritorno il numero di sample, in byte, letti. */
00848     return res;    
00849 }    
00850 #endif