I am using vs1063 for recording audio but iam unable to identify the data stored is in correct format or not.
Here iam using SPI for configuring VS1063 and the controller iam using is ESP32.
Please find the below code which iam using for storing the recorded data in the buffer
Please let me know what is the mistake in this.
Code: Select all
#include <Arduino.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "player1063.h"
#include <spi.h>
#include <SPIFFS.h>
#include "vs1063.h"
#include "vs10xx_uc.h"
#include "vs1063a-patches.plg"
#define FILE_BUFFER_SIZE 512
#define REC_BUFFER_SIZE 512
#define REPORT_INTERVAL 4096
#define min(a,b) (((a)<(b))?(a):(b))
char arr[30000]; // Array holds the Data Collected from CoDec - used inside the Record Function
enum AudioFormat {
afUnknown,
afRiff,
afOggVorbis,
afMp1,
afMp2,
afMp3,
afAacMp4,
afAacAdts,
afAacAdif,
afFlac,
afWma,
} audioFormat = afUnknown;
const char *afName[] = {
"unknown",
"RIFF",
"Ogg",
"MP1",
"MP2",
"MP3",
"AAC MP4",
"AAC ADTS",
"AAC ADIF",
"FLAC",
"WMA",
};
/*
Read 32-bit increasing counter value from addr.
Because the 32-bit value can change while reading it,
read MSB's twice and decide which is the correct one.
*/
u_int32 ReadVS10xxMem32Counter(u_int16 addr) {
u_int16 msbV1, lsb, msbV2;
u_int32 res;
WriteSci(SCI_WRAMADDR, addr+1);
msbV1 = ReadSci(SCI_WRAM);
WriteSci(SCI_WRAMADDR, addr);
lsb = ReadSci(SCI_WRAM);
msbV2 = ReadSci(SCI_WRAM);
if (lsb < 0x8000U) {
msbV1 = msbV2;
}
res = ((u_int32)msbV1 << 16) | lsb;
return res;
}
/*
Read 32-bit non-changing value from addr.
*/
u_int32 ReadVS10xxMem32(u_int16 addr) {
u_int16 lsb;
WriteSci(SCI_WRAMADDR, addr);
lsb = ReadSci(SCI_WRAM);
return lsb | ((u_int32)ReadSci(SCI_WRAM) << 16);
}
/*
Read 16-bit value from addr.
*/
u_int16 ReadVS10xxMem(u_int16 addr) {
WriteSci(SCI_WRAMADDR, addr);
return ReadSci(SCI_WRAM);
}
/*
Write 16-bit value to given VS10xx address
*/
void WriteVS10xxMem(u_int16 addr, u_int16 data) {
WriteSci(SCI_WRAMADDR, addr);
WriteSci(SCI_WRAM, data);
}
/*
Write 32-bit value to given VS10xx address
*/
void WriteVS10xxMem32(u_int16 addr, u_int32 data) {
WriteSci(SCI_WRAMADDR, addr);
WriteSci(SCI_WRAM, (u_int16)data);
WriteSci(SCI_WRAM, (u_int16)(data>>16));
}
/*
Loads a plugin.
This is a slight modification of the LoadUserCode() example
provided in many of VLSI Solution's program packages.
*/
void LoadPlugin(const u_int16 *d, u_int16 len) {
int i = 0;
while (i<len) {
unsigned short addr, n, val;
addr = d[i++];
n = d[i++];
if (n & 0x8000U) { /* RLE run, replicate n samples */
n &= 0x7FFF;
val = d[i++];
while (n--) {
WriteSci(addr, val);
}
} else { /* Copy run, copy n samples */
while (n--) {
val = d[i++];
WriteSci(addr, val);
}
}
}
}
enum PlayerStates {
psPlayback = 0,
psUserRequestedCancel,
psCancelSentToVS10xx,
psStopped
} playerState;
int WriteSdi(uint8_t *d, const u_int8 n)
{
u_int8 i;
char *k;
k=(char*) d;
if(n>32)
return -1;
while(!digitalRead(VS_DREQ));
vs_select_data();
for(i=0;i<32;i++)
//SPI.transfer(*d++);
SPI.transfer(*k++);
vs_deselect_data();
return 0;
}
/*
This function records an audio file in Ogg, MP3, or WAV formats.
If recording in WAV format, it updates the RIFF length headers
after recording has finished.
*/
//void VS1063RecordFile(File writeFp) // Commented by MUNI, is not require because no files systems is used here
void VS1063RecordFile()
{
unsigned int rec=0;
char recBuf[REC_BUFFER_SIZE];
//char arr[30000];
int volLevel = ReadSci(SCI_VOL) & 0xFF;
int c;
printf("VS1063Record()Entered\n");
printf("VS1063 Initialization Started\n");
/* Initialize recording */
/* This clock is high enough for both Ogg and MP3. */
WriteSci(SCI_CLOCKF, HZ_TO_SC_FREQ(12288000) | SC_MULT_53_50X | SC_ADD_53_00X); //commented by team //430|e000|0000-->58416,xtali=9.72MHZ
WriteVS10xxMem32(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. */
WriteSci(SCI_RECRATE, 48000); //SCI_AICTRL0. set sample rate
WriteSci(SCI_RECGAIN, 1024); //modified by team from 1024 to 0 /* 1024 = gain 1 = best quality */ //SCI_AICTRL1 set encoding gain
WriteSci(SCI_AICTRL3, RM_63_FORMAT_MP3 | RM_63_ADC_MODE_JOINT_AGC_STEREO); //SCI_AICTRL3 channel selection,codec format
/* Example of CBR mode */
WriteSci(SCI_RECQUALITY, RQ_MODE_CBR | RQ_MULT_1000 | 160); /* 160 kbps */
audioFormat = afMp3;
WriteSci(SCI_MODE, ReadSci(SCI_MODE) | SM_LINE1 | SM_ENCODE); //SM_LINE1->for line1 selection,SM_ENCODE ->to start encoding
WriteSci(SCI_AIADDR, 0x0050); /* Activate recording! */
int n;
rec=0;
delay(800);
int loop_count=0;
int loop_count1=0;
while ((n = ReadSci(SCI_RECWORDS)) > 0)
{
int i;
int flag=0;
loop_count++;
for (i=0; i<n; i++)
{
u_int16 w =ReadSci(SCI_RECDATA); //SCI_HDAT0
recBuf[rec++]= (u_int8)(w >> 8);
recBuf[rec++]= (u_int8)(w & 0xFF);
}
if(rec >=300)
{
if(flag==0)
{
WriteSci(SCI_MODE, ReadSci(SCI_MODE) | SM_CANCEL); //SM_CANCEL is for stop encoding
delay(100);
flag=1;
loop_count1++;
}
//printf("Total Bytes recorded are: %d \t and N = %d and Loop Count = %d \n\n", rec-1, n, loop_count);
}
//printf("Total Bytes recorded are: %d \t and N = %d and Loop Count = %d \n\n", rec-1, n, loop_count);
}
printf("Total Bytes recorded are: %d \t and N = %d and Loop Count = %d and Loop_Count1 = %d \n\n", rec-1, n, loop_count, loop_count1);
delay(5000);
/* while (playerState != psStopped) */
/* We need to check whether the file had an odd length.
That information is available in the MSB of PAR_END_FILL_BYTE.
In that case, the 8 LSB's are the missing byte, so we'll add
it to the output file. */
u_int16 lastByte;
lastByte = ReadVS10xxMem(PAR_END_FILL_BYTE);
if (lastByte & 0x8000U)
{ //if MSB(15th bit) is 1 ->odd length otherwise even length recording
//writeFp.println(lastByte&0xFF); //send 0to 7 bits to file
//fputc(lastByte&0xFF, writeFp);
arr[rec] = lastByte&0xFF;
printf("\nOdd length recording\n");
}
else
{
printf("\nEven length recording\n");
}
//WriteSci(PAR_END_FILL_BYTE,0x0000); //writing 0 to endFillByte
/* Finally, reset the VS10xx software, including realoading the
patches package, to make sure everything is set up properly. */
//VSTestInitSoftware(); //reset
printf("Record Done and VS1063 reset Done\n");
for(int i=0;i<rec;i++)
Serial.print(arr[i]);
}
/*
Hardware Initialization for VS1063.
*/
/* Write here your microcontroller code which puts VS10xx in hardwarereset anc back (set xRESET to 0 for at least a few clock cycles then to 1). */
int VSTestInitHardware(void) {
digitalWrite(VS_XRESET,0); //XRESET=0
delay(200);
digitalWrite(VS_XRESET,1);//XRESET=1
delay(200);
Serial.println("hardware initialisation done \n ");
return 0;
}
/* Note: code SS_VER=2 is used for both VS1002 and VS1011e */
const u_int16 chipNumber[16] = {
1001, 1011, 1011, 1003, 1053, 1033, 1063, 1103,
0, 0, 0, 0, 0, 0, 0, 0
};
/*
Software Initialization for VS1063.
Note that you need to check whether SM_SDISHARE should be set in
your application or not.
*/
int VSTestInitSoftware(void) {
u_int16 ssVer;
/* Start initialization with a dummy read, which makes sure our
microcontoller chips selects and everything are where they
are supposed to be and that VS10xx's SCI bus is in a known state. */
ReadSci(SCI_MODE); //should return 0x0800 i.e default value
/* First real operation is a software reset. After the software
reset we know what the status of the IC is. You need, depending
on your application, either set or not set SM_SDISHARE. See the
Datasheet for details. */
WriteSci(SCI_MODE, SM_SDINEW|SM_SDISHARE|SM_TESTS|SM_RESET);//SM_SDINEW->spi mode selection,SM_SDISHARE->xcs,xdcs sharing 1 means xdcs not used,SM_RESET->software reset,SM_TESTS->for different tests
/* A quick sanity check: write to two registers, then test if we
get the same results. Note that if you use a too high SPI
speed, the MSB is the most likely to fail when read again. */
WriteSci(SCI_AICTRL1, 0xABAD); // control linear encoding gain
WriteSci(SCI_AICTRL2, 0x7E57); //controls maximum AGC gain
if (ReadSci(SCI_AICTRL1) != 0xABAD || ReadSci(SCI_AICTRL2) != 0x7E57) {
printf("There is something wrong with VS10xx SCI registers\n");
return 1;
}
WriteSci(SCI_AICTRL1, 0); //linear encoding gain control 0-for using AGC
WriteSci(SCI_AICTRL2, 0); //AGC control ->maximum AGC gau==in 65535 uswd
/* Check VS10xx type */
ssVer = ((ReadSci(SCI_STATUS) >> 4) & 15); // 7-4 bits return version
if (chipNumber[ssVer]) {
printf("Chip is VS%d\n", chipNumber[ssVer]);
if (chipNumber[ssVer] != 1063) {
printf("Incorrect chip\n");
return 1;
}
} else {
printf("Unknown VS10xx SCI_MODE field SS_VER = %d\n", ssVer);
return 1;
}
/* Set the clock. Until this point we need to run SPI slow so that
we do not exceed the maximum speeds mentioned in
Chapter SPI Timing Diagram in the Datasheet. */
WriteSci(SCI_CLOCKF,HZ_TO_SC_FREQ(12288000) | SC_MULT_53_40X | SC_ADD_53_15X); //commented by team
/* Set volume level at -6 dB of maximum */
WriteSci(SCI_VOL, 0x0c0c);
/* Now it's time to load the proper patch set. */
LoadPlugin(plugin, sizeof(plugin)/sizeof(plugin[0]));
/* We're ready to go. */
return 0;
}
/*
Main function that activates either playback or recording.
*/
int VSTestHandleFile(const char *fileName, int record) {
//VS1063RecordFile(fp);
VS1063RecordFile();
return 0;
}
void setup()
{
Serial.begin(9600);//ESP32 UART serial port baudrate
vs_setup();//Set ESP32 module pins interfaced to CoDec VS1063
SPI.begin();//SPI initialization esp32
SPI.setBitOrder(MSBFIRST);//MSB order esp32
SPI.setDataMode(SPI_MODE0);//SPI mode esp32
if (VSTestInitHardware() || VSTestInitSoftware()) //hardware,software reset functions
{
printf("Failed initializing VS10xx, exiting\n");
exit(EXIT_FAILURE);
}
Serial.println("End of the setup");
}
void loop() {
VSTestHandleFile("/MyPlayFile.mp3", 1); //to enter into record file function
Serial.println("Record end");
while(1);
}