Library for VS1053 chip

Revision:
0:e97876f96d4b
Child:
1:399afe8151de
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VLSIcodec.c	Wed May 23 06:28:16 2012 +0000
@@ -0,0 +1,837 @@
+/* mbed VLSIcodec library. To access VS1053 MPEG3 codec.
+
+    Copyright (c) 2010 NXP 3790 
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+ 
+#include "mbed.h"
+#include "VLSIcodec.h"
+#include "VLSIcodec_patch.h"
+
+#ifdef __ENCODE_OGG
+#include "VLSIcodec_OGG.h"
+#endif
+
+#ifdef __PLUGINGA
+#include "VLSIcodec_pluginGA.h"
+#define cBASE   0x1800  /* Base address of X-RAM for a VS1053 */
+#endif
+
+
+//******************************************************************************
+//******************************************************************************
+// Section: Constants
+//******************************************************************************
+//******************************************************************************
+
+#define VLSI_MODE           0x00
+#define VLSI_STATUS         0x01
+#define VLSI_BASS           0x02
+#define VLSI_CLOCKF         0x03
+#define VLSI_DECODE_TIME    0x04
+#define VLSI_AUDATA         0x05
+#define VLSI_WRAM           0x06
+#define VLSI_WRAMADDR       0x07
+#define VLSI_HDAT0          0x08
+#define VLSI_HDAT1          0x09
+#define VLSI_AIADDR         0x0A
+#define VLSI_VOL            0x0B
+#define VLSI_AICTRL0        0x0C
+#define VLSI_AICTRL1        0x0D
+#define VLSI_AICTRL2        0x0E
+#define VLSI_AICTRL3        0x0F
+
+#define VLSI_STATUS_VER     0x00F0u
+#define VER_VS1001          (0u<<4)
+#define VER_VS1011          (1u<<4)
+#define VER_VS1002          (2u<<4)
+#define VER_VS1011E         (2u<<4)
+#define VER_VS1003          (3u<<4)
+#define VER_VS1053          (4u<<4)
+#define VER_VS1033          (5u<<4)
+#define VER_VS1103          (7u<<4)
+
+#define cWAIT_DREQ_1MS        wait_ms( 1); while (!_dreq);
+#define cWAIT_DREQ            while (!_dreq);
+                            
+/* VLSI 1053, MODE Register bit configuration. */
+#define SM_DIFF                0x01   
+#define SM_LAYER12            0x02   
+#define SM_RESET            0x04   
+#define SM_CANCEL            0x08   
+#define SM_EARSPEAKER_LO    0x10   
+#define SM_TESTS            0x20   
+#define SM_STREAM            0x40   
+#define SM_EARSPEAKER_HI    0x80   
+#define SM_DACT                0x100   
+#define SM_SDIORD            0x200   
+#define SM_SDISHARE            0x400   
+#define SM_SDINEW            0x800   
+#define SM_ADPCM            0x1000   
+#define SM_NOTUSE            0x2000
+#define SM_LINE1            0x4000
+#define SM_CLK_RANGE        0x8000
+
+/* SC MULT MASK CLKI */
+#define SC_MULT_0         0x0000    /* XTALI */
+#define SC_MULT_2         0x2000    /* XTALI×2.0 */
+#define SC_MULT_2_5     0x4000    /* XTALI×2.5 */
+#define SC_MULT_3         0x6000    /* XTALI×3.0 */
+#define SC_MULT_3_5     0x8000    /* XTALI×3.5 */
+#define SC_MULT_4         0xA000    /* XTALI×4.0 */
+#define SC_MULT_4_5     0xC000    /* XTALI×4.5 */
+#define SC_MULT_5         0xE000    /* XTALI×5.0 */
+
+/* 
+ SC ADD tells how much the decoder firmware is allowed to add to the multiplier specified by SC MULT
+ if more cycles are temporarily needed to decode a WMA or AAC stream. The values are:
+ SC ADD MASK Multiplier addition 
+*/
+#define SC_ADD_NOMOD    0x0000    /* No modification is allowed */
+#define SC_ADD_X1         0x0800    /* 1.0× */
+#define SC_ADD_X1_5     0x1000    /* 1.5× */
+#define SC_ADD_X2        0x1800    /* 2.0× */
+
+#define SC_FREQ            0x0000    /* 12.288 MHz clock. */
+
+/*
+*/
+#define cMODEREG_SET    ( SM_SDINEW )
+#define cCLOCK_SET        ( SC_MULT_5 | SC_ADD_X1 | SC_FREQ)
+
+#define VS1053_CS_ENABLE        _cs=0;
+#define VS1053_CS_DISABLE       _cs=1;
+#define VS1053_XDCS_ENABLE      _xdcs=0;
+#define VS1053_XDCS_DISABLE     _xdcs=1;
+#define VS1053_RST_ENABLE       _rst=0;
+#define VS1053_RST_DISABLE      _rst=1;
+
+/*
+*/
+#define cVS1053_CS_DELAY        50
+
+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) {
+    // defaults params
+    VS1053_CS_DISABLE;
+    VS1053_XDCS_DISABLE;
+}
+
+void VS1053Codec::testdreq( void){
+    while( !_dreq);
+}
+    
+void VS1053Codec::lowpower( void)
+{
+    VS1053_RST_ENABLE;
+    wait_ms( 10);
+}
+
+void VS1053Codec::init(void)
+{
+    //
+    VS1053_RST_DISABLE;
+    VS1053_CS_DISABLE;
+    VS1053_XDCS_DISABLE;
+    //
+    _spi.format( 8, 0);
+    _spi.frequency( MP3_INIT_SPEED);
+    
+    // Assert RESET
+    VS1053_RST_ENABLE;
+    wait_ms( 100);
+    
+    // Deassert RESET (active low)
+    VS1053_RST_DISABLE;
+    VS1053_CS_DISABLE;
+    VS1053_XDCS_DISABLE;
+    wait_ms( 100);
+    
+    // Wait 
+    while(!_dreq);
+    
+    // Reset the vs1053
+    writereg( VLSI_MODE, ( cMODEREG_SET | SM_RESET) );
+    wait_ms( 10);
+    
+    // Wait...
+    while(!_dreq); 
+
+    /*
+    * Write configuration MODE register in a loop to verify that the chip is
+    * connected and running correctly
+    */
+    do
+    {
+        writereg( VLSI_MODE, ( cMODEREG_SET ));
+        wait_ms( 1);
+    }while( readreg( VLSI_MODE) != ( cMODEREG_SET ));
+
+    //
+    if((readreg( VLSI_STATUS) & VLSI_STATUS_VER) == VER_VS1053)
+    {
+        // Set the clock to maximum speed (VS1053 only) to allow all audio formats
+        // to be decoded without glitching.  Note that this increases power
+        // consumption.
+        // SC_MULT = XTALI*4.5, SC_ADD = noMod, SC_FREQ = 0 (12.288MHz)
+        // VLSIWriteReg(VLSI_CLOCKF, SC_MULT_4_5 | SC_ADD_X1 | SC_FREQ);
+        
+        writereg(VLSI_CLOCKF, cCLOCK_SET);
+        
+        /* */
+        wait_ms( 2);
+        while(!_dreq);
+    }
+    else if ((readreg( VLSI_STATUS) & VLSI_STATUS_VER) == VER_VS1011E)
+    {
+        // Nothing special to do
+        ;
+    }
+    else
+    {
+        // VLSI Chip version not tested, not supported, halt program execution.
+        // This trap should be caught during the design phase.
+        while(1);
+    }
+
+    _spi.frequency( MP3_RUN_SPEED);
+}
+
+void VS1053Codec::loadpatch(void) 
+/* Questa funzione carica una patch al firmware del codec */
+{
+    int i = 0, plgin_len;
+    unsigned int addr, n, val;
+    
+    plgin_len=sizeof( plugin)/sizeof(plugin[0]);
+    while (i<plgin_len) {
+
+        addr = plugin[i++];
+        n = plugin[i++];
+        if (n & 0x8000U) { /* RLE run, replicate n samples */
+            n &= 0x7FFF;
+            val = plugin[i++];
+            while (n--) {
+                writeregnowait(addr, val); 
+                while(!_dreq); 
+            }
+        } else {           /* Copy run, copy n samples */
+            while (n--) {
+                val = plugin[i++];
+                writeregnowait(addr, val); 
+                while(!_dreq);
+            }
+        }
+    }
+    //
+    wait_ms( 1);
+    while(!_dreq);
+}
+
+#ifdef __PLUGINGA
+void VS1053Codec::loadgapatch(void) 
+/* Questa funzione carica un plugin nel codec */
+{
+    int i = 0, plgin_len;
+    unsigned int addr, n, val;
+    
+    plgin_len=sizeof( gaplugin)/sizeof(gaplugin[0]);
+    while (i<plgin_len) {
+
+        addr = gaplugin[i++];
+        n = gaplugin[i++];
+        if (n & 0x8000U) { /* RLE run, replicate n samples */
+            n &= 0x7FFF;
+            val = gaplugin[i++];
+            while (n--) {
+                writeregnowait(addr, val); 
+                while(!_dreq); 
+            }
+        } else {           /* Copy run, copy n samples */
+            while (n--) {
+                val = gaplugin[i++];
+                writeregnowait(addr, val); 
+                while(!_dreq);
+            }
+        }
+    }
+    //
+    wait_ms( 1);
+    while(!_dreq);
+}
+#endif
+
+#ifdef __ENCODE_OGG
+void VS1053Codec::loadoggpatch(void) 
+/* Questa funzione carica una patch per gestire l'encoder OGG */
+{
+    int i = 0, plgin_len;
+    unsigned int addr, n, val;
+    
+    plgin_len=sizeof( ogg_enc)/sizeof(ogg_enc[0]);
+    while (i<plgin_len) {
+
+        addr = ogg_enc[i++];
+        n = ogg_enc[i++];
+        if (n & 0x8000U) { /* RLE run, replicate n samples */
+            n &= 0x7FFF;
+            val = ogg_enc[i++];
+            while (n--) {
+                writeregnowait(addr, val); 
+                while(!_dreq); 
+            }
+        } else {           /* Copy run, copy n samples */
+            while (n--) {
+                val = ogg_enc[i++];
+                writeregnowait(addr, val); 
+                while(!_dreq);
+            }
+        }
+    }
+    //
+    wait_ms( 1);
+    while(!_dreq);
+}
+#endif
+
+#ifdef __PLUGINGA    
+void VS1053Codec::readgavalue( unsigned char *currval, unsigned char *peak)
+{
+	writereg( VLSI_WRAMADDR, cBASE+2);
+	unsigned short bands = (unsigned short)readreg( VLSI_WRAM);
+	//
+	writereg( VLSI_WRAMADDR, cBASE+4);
+	//
+	for (int i=0;i<bands;i++) {
+		short pv = readreg( VLSI_WRAM); 
+		/* current value in bits 5..0, normally 0..31
+		peak value in bits 11..6, normally 0..31 */
+		currval[i]=(unsigned char)(pv&0x003F);
+		peak[i]=(unsigned char)( (pv>>6)&0x003F);
+	}
+}
+
+unsigned short VS1053Codec::readgabands( void)
+{
+	writereg( VLSI_WRAMADDR, cBASE+2);
+	unsigned short bands = (unsigned short)readreg( VLSI_WRAM);
+	/* */
+	return bands;
+}
+
+#endif
+
+void VS1053Codec::setvmeter( void)
+{
+    unsigned short tmp;
+    
+    tmp=(unsigned short)readreg( VLSI_STATUS);
+    tmp|=(1<<9);
+    writereg( VLSI_STATUS, tmp);
+}
+
+void VS1053Codec::getvmeterval( unsigned char* left, unsigned char* right)
+{
+    unsigned short tmp;
+    
+    tmp=(unsigned short)readreg( VLSI_AICTRL3);
+    
+    *right=(unsigned char)tmp&0x00FF;
+    *left=(unsigned char)(tmp>>8);
+}
+
+/****************************************************************************
+  Function:
+    void VS1053Codec::setbassboost(BYTE bass, BYTE gfreq)
+
+  Description:
+    This function sets the bass boost.
+
+  Precondition:
+    None
+
+  Parameters:
+    BYTE bass   - Bass gain in dB, range from 0 to 15 (MSB nibble)
+    BYTE gfreq  - Limit frequency for bass boost, 10 Hz steps (range from
+                    20 to 150) (LSB nibble)
+
+  Returns:
+    None
+
+  Remarks:
+    None
+  ***************************************************************************/
+void VS1053Codec::setbassboost( unsigned char bass, unsigned char gfreq)
+{
+    unsigned char templ;
+    unsigned short tmp;
+
+    // 
+    if(bass > 15u)
+        bass = 15;
+    if(gfreq > 150u)
+        gfreq = 150;
+    if ( gfreq < 20)
+        gfreq = 20;
+        
+
+    // 
+    templ = (unsigned char)gfreq/10;
+
+    // put bass boost value into the upper 4 bit
+    templ |= (bass << 4);
+    //
+    tmp=(unsigned short)readreg( VLSI_BASS);
+    tmp &= 0xFF00;
+    tmp |= templ;
+    //
+    writereg( VLSI_BASS, tmp);
+}
+
+/****************************************************************************
+  Function:
+    void VS1053Codec::settrebleboost(BYTE bass, WORD gfreq)
+
+  Description:
+    This function sets the bass boost.
+
+  Precondition:
+    None
+
+  Parameters:
+    BYTE treble   - Bass gain in dB, range from -8 to 7 (MSB nibble)
+    WORD gfreq    - Limit frequency for bass boost, 1000 Hz steps (range from
+                    1000 to 15000) (LSB nibble)
+
+  Returns:
+    None
+
+  Remarks:
+    None
+  ***************************************************************************/
+void VS1053Codec::settrebleboost( char treble, unsigned int gfreq)
+{
+    unsigned char templ;
+    unsigned short tmp;
+
+    // 
+    if(treble > 7)
+        treble = 7;
+    if ( treble < (char)-8)
+        treble = (char)-8;
+        
+    if(gfreq > 15000u)
+        gfreq = 15000;
+    if(gfreq < 1000)
+        gfreq = 1000;
+
+    // 
+    templ = (unsigned char)gfreq/1000;
+
+    // put treble boost value into the upper 4 bit
+    templ |= (treble << 4);
+    //
+    tmp=(unsigned short)readreg( VLSI_BASS);
+    tmp &= 0x00FF;
+    tmp |= (templ << 8);
+    //
+    writereg( VLSI_BASS, tmp);
+}
+
+void VS1053Codec::getplaytime(char *playtime)
+{
+    unsigned short playTime;
+    unsigned char minutes, seconds;
+    
+    playTime = (unsigned short)readreg(VLSI_DECODE_TIME);
+    minutes = playTime/60;
+    seconds = playTime%60;
+    *playtime++=('0'+minutes/10);
+    *playtime++=('0'+minutes%10);
+    *playtime++=(':');
+    *playtime++=('0'+seconds/10);
+    *playtime++=('0'+seconds%10);
+}
+
+
+/****************************************************************************
+  Function:
+    void setvolume(unsigned char vRight, unsigned char vLeft)
+
+  Description:
+    This function set volume for analog outputs on the VLSI codec.
+
+  Precondition:
+    None
+
+  Parameters:
+    unsigned char vRight - right channel attenuation from maximum volume, 0.5dB steps
+                        (0x00 = full volume, 0xFF = muted)
+    unsigned char vLeft  - left channel attenuation from maximum volume, 0.5dB steps
+                        (0x00 = full volume, 0xFF = muted)
+
+  Returns:
+    None
+
+  Remarks:
+    None
+  ***************************************************************************/
+void VS1053Codec::setvolume(unsigned char vRight, unsigned char vLeft)
+{
+    writereg(VLSI_VOL, ((unsigned int)vLeft)<<8 | vRight);
+}
+
+
+void VS1053Codec::sinetest( unsigned char pitch)
+{
+    unsigned int i;
+    
+    while(!_dreq);
+    
+    i=(unsigned short)readreg( VLSI_MODE);
+    writereg( VLSI_MODE, ( i | SM_TESTS ));
+    
+    VS1053_XDCS_ENABLE;
+    
+    if ( pitch) {
+        // START Sine Test
+        _spi.write(0x53);
+        _spi.write(0xEF);
+        _spi.write(0x6E);
+        _spi.write( pitch);
+        _spi.write(0x00);
+        _spi.write(0x00);
+        _spi.write(0x00);
+        _spi.write(0x00);
+    } else {
+        // STOP Sine Test
+        _spi.write(0x45);
+        _spi.write(0x78);
+        _spi.write(0x69);
+        _spi.write(0x74);
+        _spi.write(0x00);
+        _spi.write(0x00);
+        _spi.write(0x00);
+        _spi.write(0x00);
+    }    
+    
+    VS1053_XDCS_DISABLE;
+
+}
+
+void VS1053Codec::writedata( unsigned char data)
+/*
+* Write data to SDI.
+*/
+{
+    int i=0;
+    
+    VS1053_XDCS_ENABLE;
+    for( i=0; i<cVS1053_CS_DELAY; i++);
+    
+    _spi.write( data);
+    
+    for( i=0; i<cVS1053_CS_DELAY; i++);
+    VS1053_XDCS_DISABLE;
+    
+}
+    
+//******************************************************************************
+//******************************************************************************
+//******************************************************************************
+// Section: Internal Functions
+//******************************************************************************
+//******************************************************************************
+//******************************************************************************
+
+
+unsigned short VS1053Codec::readreg(unsigned char vAddress)
+{
+    unsigned short wValue;
+    unsigned int i;
+    
+    VS1053_CS_ENABLE;
+    for ( i=0; i<cVS1053_CS_DELAY;i++);
+    
+    _spi.write(0x03);     // Read
+    _spi.write(vAddress); // Register address
+    ((unsigned char*)&wValue)[1] = _spi.write(0xFF);   // 8 bit value high byte
+    ((unsigned char*)&wValue)[0] = _spi.write(0xFF);   // 8 bit value low byte
+    
+    for ( i=0; i<cVS1053_CS_DELAY;i++);
+    VS1053_CS_DISABLE;
+
+    return wValue;
+}
+
+void VS1053Codec::writereg(unsigned char vAddress, unsigned int wValue)
+{
+    int i;
+    
+    while(!_dreq);
+    
+    VS1053_CS_ENABLE;
+    for ( i=0; i<cVS1053_CS_DELAY;i++);
+    
+    _spi.write(0x02);     // Write
+    _spi.write(vAddress); // Register address
+    _spi.write(((unsigned char*)&wValue)[1]);      // 8 bit value to write high byte
+    _spi.write(((unsigned char*)&wValue)[0]);      // 8 bit value to write low byte
+    
+    for ( i=0; i<cVS1053_CS_DELAY;i++);
+    VS1053_CS_DISABLE;
+    
+}
+
+
+/* */
+void VS1053Codec::reset( void)
+{
+    // Reset the vs1053
+    writereg(VLSI_MODE, ( cMODEREG_SET | SM_RESET) );
+    wait_ms( 5);
+    // Wait...
+    while(!_dreq);
+
+    // Configure CLOCK register.
+    writereg(VLSI_CLOCKF, cCLOCK_SET);
+    wait_ms( 5);
+    // Wait...
+    while(!_dreq);
+}
+    
+
+void VS1053Codec::writeregnowait(unsigned char vAddress, unsigned int wValue)
+/*
+ Write to SCI interface without waiting for the DREQ pin
+*/
+{
+    int i;
+    
+    VS1053_CS_ENABLE;
+    for ( i=0; i<cVS1053_CS_DELAY;i++);
+    
+    _spi.write(0x02);     // Write
+    _spi.write(vAddress); // Register address
+    _spi.write(((unsigned char*)&wValue)[1]);      // 8 bit value to write high byte
+    _spi.write(((unsigned char*)&wValue)[0]);      // 8 bit value to write low byte
+    
+    for ( i=0; i<cVS1053_CS_DELAY;i++);
+    VS1053_CS_DISABLE;
+    
+}
+
+#ifdef __ENCODE_OGG
+void VS1053Codec::VoggEncoding_Start( void)
+/* VorbisEncoder160c pag. 9 */
+{
+    unsigned short temp;
+    
+/* 2. vs1053b at 55.3MHz */
+    writeregnowait( VLSI_CLOCKF, 0xC000);         cWAIT_DREQ_1MS;
+/* 3. SCI_BASS to 0 */
+    writeregnowait( VLSI_BASS, 0x0000);         cWAIT_DREQ_1MS;
+/* 4. Disable user application (no wait fot DREQ pin and no delay, as from the VLSI source file example */
+/*    record.c from playercode1053-Aug2009.zip                                                             */
+    writeregnowait( VLSI_AIADDR, 0x0000); 
+/* 5. Disable all IRQ except the SCI IRQ */
+    writeregnowait( VLSI_WRAMADDR, 0xC01A);
+    writeregnowait( VLSI_WRAM, 0x0002); 
+/* 6. Load the plugin code... */
+    loadoggpatch();
+/* 7. Set bit SM_ADPCM to 1. */
+    temp = (unsigned short)readreg( VLSI_MODE);                cWAIT_DREQ_1MS;
+    temp |= SM_ADPCM;
+    writeregnowait( VLSI_MODE, temp);             cWAIT_DREQ_1MS;
+    writeregnowait( VLSI_AICTRL0, 0x0000);         cWAIT_DREQ_1MS;
+/* 8. Set recording level. Value are for conservative AGC. */
+    writeregnowait( VLSI_AICTRL1, 0x0000);         cWAIT_DREQ_1MS;
+    writeregnowait( VLSI_AICTRL2, 4096);         cWAIT_DREQ_1MS;
+/* 10. Set 0 to SCI_AICTRL3. */
+    writeregnowait( VLSI_AICTRL3, 0x0000);         cWAIT_DREQ_1MS;
+/* 11. Active the encoder... */
+    wait_ms( 5);
+    writeregnowait( VLSI_AIADDR, 0x0034); wait_ms( 1);
+/* 12. wait DREQ high. */
+    cWAIT_DREQ;                /* Loop forever. */
+
+}
+
+#if 0
+void VS1053Codec::VoggEncoding_ReadStatus( RUNTIME_VOGG_VALUE *status)
+/* VorbisEncoder160c par 2.3.4, pag. 11                 */
+/* see VLSICodec.h for RUNTIME_VOGG_VALUE struct data.  */
+{
+    unsigned short temp, temph;
+    
+    /* Recording Time */
+    writereg( VLSI_WRAMADDR, 0x0008); cWAIT_DREQ_1MS;
+    temp = (unsigned short)readreg( VLSI_WRAM);                                /* LSB recording Time */
+    temph= (unsigned short)readreg( VLSI_WRAM);                                /* MSB recording Time */
+    status->rec_time = ((unsigned long)temph << 16) | temp;    
+
+    /* Average bitrate */
+    writereg( VLSI_WRAMADDR, 0x000C); cWAIT_DREQ_1MS;
+    temp = (unsigned short)readreg( VLSI_WRAM);                                /* LSB Average bitrate */
+    temph= (unsigned short)readreg( VLSI_WRAM);                                /* MSB Average bitrate */
+    status->average_bitrate = ((unsigned long)temph << 16) | temp;    
+
+    /* Sample Counter */
+    writereg( VLSI_WRAMADDR, 0x1800); cWAIT_DREQ_1MS;
+    temp = (unsigned short)readreg( VLSI_WRAM);                                /* LSB Sample Counter */
+    temph= (unsigned short)readreg( VLSI_WRAM);                                /* MSB Average bitrate */
+    status->sample_counter = ((unsigned long)temph << 16) | temp;
+}
+#endif
+    
+    
+/*
+* Questa funzione legge il registro SCI_HDAT1 per verificare la presenza di 
+* sample disponibili. In caso ci siano li legge dal reg. SCI_HDAT0 
+* salvandoli nel puntatore passatogli. Ritorna il numero di byte copiati.
+*/
+unsigned int VS1053Codec::VoggEncoding_ReadBuffer( unsigned char *voggSample)
+/* VorbisEncoder160c pag. 10 */
+{
+    unsigned int  i;
+    unsigned short temp, sample;
+    
+    temp=0;
+    i=0;
+    sample=0;
+
+//    printf("readbuffer\r\n");
+    
+    do {
+        /* reading the sample counter... */
+        temp = (unsigned short)readreg( VLSI_HDAT1);
+        if ( temp ) {
+//            printf("sample %d\r\n", temp);
+            /* there are samples... */
+            i=0;
+            while( i < temp) {
+                /* read the sample as word */
+                sample=(unsigned short)readreg( VLSI_HDAT0);
+                /* save it into the array as single byte. */
+                *voggSample++ = (unsigned char)(sample >> 8);                /* MSB */
+                *voggSample++ = (unsigned char)(sample & 0x00FF);            /* LSB */
+                i++;
+                wait_ms( 1);
+            }    
+            
+            /* Exit the loop. */
+            break;
+        } else {
+//            printf("no sample\r\n");
+            /* Exit the loop. */
+            break;
+        }    
+    } while( 1);    
+    /* just relax... */
+    wait_ms( 1);
+    /* Return the number of byte saved. */
+    return i*2;
+}
+    
+/* 
+* Questa funzione esegue la procedura di fine encoding memorizzando i rimanenti sample
+* nel puntatore passatogli. Ritorna il numero di sample letti.
+*/
+unsigned int VS1053Codec::VoggEncoding_Stop( unsigned char *voggSample)
+/* VorbisEncoder160c pag. 11 */
+{
+    unsigned int res, i, ii;
+    unsigned short temp, sample;
+    res=0;
+    temp=0;
+    sample=0;
+    
+/* 1. set bit 0 to 1 */
+    temp = (unsigned short)readreg( VLSI_AICTRL3);
+    temp |= 0x0001;
+    writereg( VLSI_AICTRL3, temp);
+    
+/* 2. continue reading data but checking the bit 1 of VLSI_AICTRL3 reg. */
+    res=0;
+    do {
+        /* reading the sample counter... */
+        temp = (unsigned short)readreg( VLSI_HDAT1);
+        if ( temp) {
+//            printf("EncStop: %d\r\n", temp);
+            i=0;
+            while( i < temp ) {
+                /* */
+                sample = (unsigned short)readreg( VLSI_HDAT0);
+                *voggSample++ = (unsigned char)(sample >> 8);
+                *voggSample++ = (unsigned char)sample & 0x00FF;
+                i++;
+                wait_ms( 1);
+            }
+            res+=i;
+        }
+        /* just relax... */
+        wait_ms( 1);
+        temp = (unsigned short)readreg( VLSI_AICTRL3);
+        /* verify the bit 1 of VLSI_AICTRL3 reg. */
+        if ( temp & 0x0002) {
+//            printf("Encoding STOP\r\n");
+            /* encoding has finished. */
+            break;
+        }    
+    } while( 1);    /* Loop forever... */
+/* 3. write the remaining word... */
+    ii=0;
+    do {
+        temp = (unsigned short)readreg( VLSI_HDAT1);
+        if ( temp) {
+//            printf("Flush %d\r\n", temp);
+            /* there are samples... */
+            i=0;
+            while( i < temp ) {            /* con il numero precedente. */
+                /* */
+                sample = (unsigned short)readreg( VLSI_HDAT0);
+                *voggSample++ = (unsigned char)(sample >> 8);
+                *voggSample++ = (unsigned char)sample & 0x00FF;                
+                i++;
+                wait_ms( 1);
+            }    
+            res+=i;
+        } else {
+            wait_ms( 1);
+            ii++;
+        }
+    } while( ii<5);    /* Loops ... */
+/* 4. read twise AICTRL3 */
+    temp = (unsigned short)readreg( VLSI_AICTRL3);
+    temp = (unsigned short)readreg( VLSI_AICTRL3);
+//    printf("last read %d\r\n", temp);
+    if ( temp & 0x0004 ) {
+        /* remove last byte ( bits 7:0) from the last word. */
+        voggSample--;
+        *voggSample=0;
+        res=(res*2)-1;
+    } else {
+        res=res*2;
+    }
+/* 5. Reset the codec. */
+
+    /* Ritorno il numero di sample, in byte, letti. */
+    return res;    
+}    
+#endif