vs1063 : g711/722 full duplex example

Writing software for systems that use VLSI Solution's devices as slave codecs to a host microcontroller.
chitarrastonata
User
Posts: 9
Joined: Wed 2019-10-16 23:35

vs1063 : g711/722 full duplex example

Post by chitarrastonata » Thu 2019-10-17 0:30

My project have to read UDP packet from ethernet and play them with vs1063.
In the meantime it has to read audio from vs1063 and send back to ethernet (like a VoiceIP, ethernet telephone)

I'm not able to find any example how to initialize vs1063 to have full duplex functionality (g.711/722)
till now i have only implemented an example how to play mp3....

can anybody send me some example?
Thanks...

PS: HW is made with : PIC32MX for ethernet and vs1063 for audio

User avatar
pasi
VLSI Staff
Posts: 1621
Joined: Thu 2010-07-15 16:04

Re: vs1063 : g711/722 full duplex example

Post by pasi » Thu 2019-10-17 10:16

Codec mode (full duplex) is part of the encoding mode, so start with just the encoding. You can find encoding mode examples here: http://www.vlsi.fi/en/support/software/ ... tware.html

For best results you would use the vs1063a patches package (from http://www.vlsi.fi/en/support/software/ ... tches.html ). It corrects some issues with encoding, adds a few more features, and also gives a few new samplerates for the codec mode.

Basically,
1. Reset vs1063a.
2. Upload the suitable patch code - e.g. vs1063a-encpatches.plg
3. Configure the encoder (through AICTRL registers, including the codec mode bit, with a samplerate the codec mode supports), start encoder.
4. Read the available encoded data, send to the other end.
5. Receive from the other end, write to vs1063a (SDI), repeat from 4.

By default the encoder and codec decoder use a RIFF WAV header. If the two units can be turned on and off at different times, then it's probably best to also set the "NORIFF" mode (in AICTRL3, see datasheet).
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

chitarrastonata
User
Posts: 9
Joined: Wed 2019-10-16 23:35

Re: vs1063 : g711/722 full duplex example

Post by chitarrastonata » Thu 2019-10-17 17:45

Hi,
Before implement a real full duplex, I trying to implement record a playback in two different functions.
I porting exaclty the souce code from 'vs1063an_playrec.zip'
Unfortunately when i write (SCI_AIADDR, 0x0050) to start recording the PIN DREQ never go logic '1'
Any idea?
Thaks
Luca

this is my implementation for PIC32MX:
case APP_LUCA_TEST1: // REC BUFFER : it blocks when I call (SCI_AIADDR, 0x0050);
case APP_LUCA_TEST2: // PLAY BUFFER : never tried, but it is like PLAY MP3, so i should work fine
case APP_LUCA_TEST3: // PLAY MP3 : it is working fine


case APP_LUCA_TEST1: //REC BUFFER
{
unsigned char *p;
unsigned int i, j, n, w;
LED_D6On();
// This clock is high enough for both Ogg and MP3.
vs_write_register(SCI_CLOCKF, HZ_TO_SC_FREQ(12288000) | SC_MULT_53_50X | SC_ADD_53_00X);
// The serial number field is used only by the Ogg Vorbis encoder,
// and even then only if told to used the field. If you use to
// encode Ogg Vorbis, use a randomizer or other function that creates
// a different serial number for each file
vs_write_wramaddr32(PAR_ENC_SERIAL_NUMBER, 0x87654321);
// Example definitions for MP3 recording.
// For best quality, record at 48 kHz.
// If you must use CBR, set bitrate to at least 160 kbit/s. Avoid 128 kbit/s.
// Preferably use VBR mode, which generally gives better results for a
// given bitrate
vs_write_register(SCI_RECRATE, 48000);
vs_write_register(SCI_RECGAIN, 1024); // 1024=gain 1=best quality
vs_write_register(SCI_RECMODE, RM_63_FORMAT_MP3 | RM_63_ADC_MODE_JOINT_AGC_STEREO);
// vs_write_register(SCI_RECQUALITY, RQ_MODE_VBR | RQ_MULT_1000 | 160); // ~160 kbps VBR mode
vs_write_register(SCI_RECQUALITY, RQ_MODE_CBR | RQ_MULT_1000 | 160); // 160 kbps CBR mode

// start recording
n = vs_read_register(SCI_MODE);
vs_write_register(SCI_MODE, n | SM_LINE1 | SM_ENCODE);
vs_write_register(SCI_AIADDR, 0x0050); // Activate recording **** NEVER RETURN !!!! ******

j = 0;
do {
// See if there is some data available
if((n = vs_read_register(SCI_RECWORDS)) > 0) {
n = min(n, sizeof(bufferAudio) / 2);
for(i = 0; i < n; i++) {
w = vs_read_register(SCI_RECDATA);
bufferAudio[j++] = (w >> 8);
bufferAudio[j++] = (w & 0xFF);
DRV_SPI_Tasks(sysObj.spiObjectIdx0);
}
} else {
DRV_SPI_Tasks(sysObj.spiObjectIdx0);

/* The following read from SCI_RECWORDS may appear redundant.
But it's not: SCI_RECWORDS needs to be rechecked AFTER we
have seen that SM_CANCEL have cleared.
if (playerState != psPlayback && !(ReadSci(SCI_MODE) & SM_CANCEL) && !ReadSci(SCI_RECWORDS)) {
playerState = psStopped;
}
*/
}
} while(j < sizeof(bufferAudio));

// stop recording
n = vs_read_register(SCI_MODE);
vs_write_register(SCI_MODE, n | SM_CANCEL);

LED_D6Off();
appData.state = APP_STATE_SERVICE_TASKS;
break;
}

case APP_LUCA_TEST2: // PLAY BUFFER
{
unsigned char *p;
unsigned int i;
LED_D6On();
p = bufferAudio; // Point "p" to the beginning of array
for (i = 0; i < sizeof(bufferAudio); i++) {
while (!VS_DREQStateGet()) {
// MP3 buffer is full, time to do something else...
while(!VS_DREQStateGet()); // Wait until SPI transfer is completed
VS_XDCSOn(); // Release the SDI bus
// You can do something else here, the bus is free...
DRV_SPI_Tasks(sysObj.spiObjectIdx0);
// Maybe set the volume or whatever...
}
VS_XDCSOff(); // Pull XDCS low
// You can actually send 32 bytes here before checking for DREQ again
vs_write_data(*p++);
}
// End of file - send zeros before next file
VS_XDCSOff();
for (i = 0; i < 4096; i++) {
while (!VS_DREQStateGet()) ; // wait here until DREQ is high again
vs_write_data(0);
}
while(!VS_DREQStateGet()); // Wait until SPI transfer is completed
VS_XDCSOn();
vs_soft_reset();
LED_D6Off();
appData.state = APP_STATE_SERVICE_TASKS;
break;
}

case APP_LUCA_TEST3: // PLAY MP3
{
unsigned char *p;
unsigned int i;
LED_D6On();
p = hello_mp3; // Point "p" to the beginning of array
for (i = 0; i < sizeof(hello_mp3); i++) {
while (!VS_DREQStateGet()) {
// MP3 buffer is full, time to do something else...
VS_XDCSOn(); // Release the SDI bus
// You can do something else here, the bus is free...
DRV_SPI_Tasks(sysObj.spiObjectIdx0);
// Maybe set the volume or whatever...
}
VS_XDCSOff(); // Pull XDCS low
// You can actually send 32 bytes here before checking for DREQ again
vs_write_data_n(p, 32); p += 32;
}
// End of file - send zeros before next file
VS_XDCSOff();
for (i = 0; i < 4096; i++) {
while (!VS_DREQStateGet()) ; // wait here until DREQ is high again
vs_write_data(0);
}
while(!VS_DREQStateGet()); // Wait until SPI transfer is completed
VS_XDCSOn();
vs_soft_reset();
LED_D6Off();
appData.state = APP_STATE_SERVICE_TASKS;
break;
}

=============

// write VS10xx 16-bit SCI registers
void vs_write_register(uint8_t address, uint16_t value)
{
VS_XCSOff();
while(!VS_DREQStateGet());

spiTxBuffer[0] = VS_WRITE_COMMAND;
spiTxBuffer[1] = address;
spiTxBuffer[2] = value >> 8;
spiTxBuffer[3] = value & 0x00ff;
bufHandle = DRV_SPI_BufferAddWrite(spiHandle, spiTxBuffer, 4, 0, 0);

// PIX32 SPI driver is asyncrounous, so wait that SPI has completed
do { DRV_SPI_Tasks(sysObj.spiObjectIdx0);
} while(!(DRV_SPI_BUFFER_EVENT_COMPLETE & DRV_SPI_BufferStatus(bufHandle)));

VS_XCSOn();
while(!VS_DREQStateGet()); **** when i call (SCI_AIADDR, 0x0050) NEVER RETURN !!!! ******
}

User avatar
pasi
VLSI Staff
Posts: 1621
Joined: Thu 2010-07-15 16:04

Re: vs1063 : g711/722 full duplex example

Post by pasi » Fri 2019-10-18 11:17

Have you loaded the vs1063a patches anywhere?

Writing 0x0050 to AIADDR restarts the patch. Without the patch you start encoding mode by triggering a software reset from SCI_MODE with SM_ENCODE set.
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

chitarrastonata
User
Posts: 9
Joined: Wed 2019-10-16 23:35

Re: vs1063 : g711/722 full duplex example

Post by chitarrastonata » Fri 2019-10-18 13:08

nice!
REC and PLAY in two different functions is working fine.
I made 2 errors: patch not loaded and heather info with size not updated.
I'm so sorry...
Now last step, fullduplex!
I'll keep you update.

chitarrastonata
User
Posts: 9
Joined: Wed 2019-10-16 23:35

Re: vs1063 : g711/722 full duplex example

Post by chitarrastonata » Fri 2019-10-18 15:48

Code is written but when I start full duplex the output audio is coming from input and not from DAC internal buffer.
I suppose that I have to set correctly PLAY_MODE, AD_MIXER, PCM_MIXER but even after reading datasheet I'm still confused.
can you kindly tell me the value to use for these register in full duplex operation?
Thanks
Luca

chitarrastonata
User
Posts: 9
Joined: Wed 2019-10-16 23:35

Re: vs1063 : g711/722 full duplex example

Post by chitarrastonata » Fri 2019-10-18 15:57

do {
// See if there is some data available
if((n = vs_read_register(SCI_RECWORDS)) > 0) {
for(i = 0; i < n; i++) {
w = vs_read_register(SCI_RECDATA);
bufferAudio[bufferWrite++] = (w >> 8);
bufferAudio[bufferWrite++] = (w & 0xFF);
bufferWrite &= BUF_MASK;
DRV_SPI_Tasks(sysObj.spiObjectIdx0);
}
} else {
VS_XDCSOff(); // Pull XDCS low
vs_write_data_n(&bufferAudio[bufferRead], 32);
bufferRead = (bufferRead + 32) & BUF_MASK;
VS_XDCSOn();
DRV_SPI_Tasks(sysObj.spiObjectIdx0);
}
} while(1);

chitarrastonata
User
Posts: 9
Joined: Wed 2019-10-16 23:35

Re: vs1063 : g711/722 full duplex example

Post by chitarrastonata » Sun 2019-10-20 19:11

ohps, i simply forgot to set RM_63_CODEC in SCI_RECMODE.... :lol:

Now it seems that codec has two different transfer rates.
I have a circular buffer (now size is 16384 byte, my hope is to reduce it to 64)
Read ponter starts ad beginner of buffer, write ponter starts in the midle of buffer (8k).
It seems that after a while a pointer reach the other one and pass it.

I set the register for REC in this way : SCI_RECMODE = RM_63_FORMAT_G722_ADPCM | RM_63_ADC_MODE_MONO | RM_63_CODEC
there is any setting to do define the PLAY mode?

Regards
Luca

User avatar
pasi
VLSI Staff
Posts: 1621
Joined: Thu 2010-07-15 16:04

Re: vs1063 : g711/722 full duplex example

Post by pasi » Mon 2019-10-21 10:48

The codec mode playback function by default reads and interprets a WAV header and gets the format, samplerate, and number of channels from there. If you feed back what you received from the encoder, it should work.

Your problem may be that you read too much at once from the encoder, and the decoder starves and needs to insert zero samples. You need to read the codec decoder's fill state more often so that it does not run out of data.
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

chitarrastonata
User
Posts: 9
Joined: Wed 2019-10-16 23:35

Re: vs1063 : g711/722 full duplex example

Post by chitarrastonata » Mon 2019-10-21 20:45

correct!
play buffer was underrun. I changed code and now is perfect.
Thanks a lot!
Just a last queston:
My initial expectation was that when I send data to the decoder in the same SPI frame I read the encoded data.
is it possible to set this modality?
it will reduce dramatically the SPI access!
Luca

Post Reply