Library for VS1053 chip
Diff: VLSIcodec.c
- 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