Hi to everyone,
I would like to run a MP3 encoder IC (VS1003) with a Tiva Launchpad (EK-TM4C123GXL). I've attached the IC to SSI1 peripheral and have started to write drive. For some reason I can't get the uC to receive data from the VS1003.
So what have I done so far:
I've written an init function (uint8_t VS10xxInit(void)) which is supposed to init the hardware (Line 848 to 901) first. After that I write a test value to one of the available register inside the VS1003. After that I try to read out this register to check that the write/read procedure works (Line 926,927). I can see on the oscilloscope that the data gets send to the VS1003. I can also see as soon as the software gets to the point to write a dummy byte to trigger VS1003 to send data that it puts the just written register value out on the Rx line. For some reason the SSIDataGet (Line 318, 319) function doesn't not receive it and always writes "0" to the variable passed into it.
I hope anyone can help me on this.
Thank you very much!
/*
VLSI Solution generic microcontroller example player / recorder for
VS1003.
v1.00 2012-11-28 HH First release
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/gpio.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "grlib/grlib.h"
#include "utils/uartstdio.h"
#include "VS10xx.h"
//*****************************************************************************
//
//! \addtogroup dac_api
//! @{
//
//*****************************************************************************
#define FILE_BUFFER_SIZE 512
#define SDI_MAX_TRANSFER_SIZE 32
#define SDI_END_FILL_BYTES 2050
#define REC_BUFFER_SIZE 512
/***************************************************
* Peripheral definitions for VS1003 SPI interface
* *************************************************/
// SSI port
#define VS1003_SSI_BASE SSI1_BASE
#define VS1003_SSI_SYSCTL_PERIPH SYSCTL_PERIPH_SSI1
// GPIO for SSI pins
#define VS1003_SSI_GPIO_PORT_BASE GPIO_PORTF_BASE
#define VS1003_SSI_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOF
#define VS1003_SSI_RX GPIO_PIN_0
#define VS1003_SSI_TX GPIO_PIN_1
#define VS1003_SSI_CLK GPIO_PIN_2
#define VS1003_SSI_PINS (VS1003_SSI_RX | VS1003_SSI_TX | VS1003_SSI_CLK)
//#define VS1003_SSI_PINS (VS1003_SSI_TX | VS1003_SSI_CLK)
//*****************************************************************************
//
// Defines the GPIO pin configuration macros for the pins that are used for
// the SSI function.
//
//*****************************************************************************
#define VS1003_PINCFG_SSICLK GPIO_PF2_SSI1CLK
#define VS1003_PINCFG_SSIRX GPIO_PF0_SSI1RX
#define VS1003_PINCFG_SSITX GPIO_PF1_SSI1TX
// GPIO for xRST, BSYNC, DREQ pins
#define VS1003_CTL_GPIO_PORT_BASE GPIO_PORTC_BASE
#define VS1003_CTL_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOC
#define VS1003_xRST GPIO_PIN_4
#define VS1003_xDCS GPIO_PIN_5
#define VS1003_xCS GPIO_PIN_7
#define VS1003_DREQ GPIO_PIN_6
#define VS1003_CTL_PINS (VS1003_xRST | VS1003_xDCS | VS1003_xCS)
#define VS1003_SSI_CLOCK 3000000 // Set SSI1 clock to 6MHz
/* How many transferred bytes between collecting data.
A value between 1-8 KiB is typically a good value.
If REPORT_ON_SCREEN is defined, a report is given on screen each time
data is collected. */
#define REPORT_INTERVAL 4096
#define REPORT_INTERVAL_MIDI 512
#define min(a,b) (((a)<(b))?(a):(b))
enum AudioFormat {
afUnknown,
afRiff,
afMp3,
afMidi,
} audioFormat = afUnknown;
const char *afName[] = {
"unknown",
"RIFF",
"MP3",
"MIDI",
};
enum PlayerStates {
psPlayback = 0,
psUserRequestedCancel,
psCancelSentToVS10xx,
psStopped
} playerState;
uint8_t adpcmHeader[60] = {
'R', 'I', 'F', 'F',
0xFF, 0xFF, 0xFF, 0xFF,
'W', 'A', 'V', 'E',
'f', 'm', 't', ' ',
0x14, 0, 0, 0, /* 20 */
0x11, 0, /* IMA ADPCM */
0x1, 0, /* chan */
0x0, 0x0, 0x0, 0x0, /* sampleRate */
0x0, 0x0, 0x0, 0x0, /* byteRate */
0, 1, /* blockAlign */
4, 0, /* bitsPerSample */
2, 0, /* byteExtraData */
0xf9, 0x1, /* samplesPerBlock = 505 */
'f', 'a', 'c', 't', /* subChunk2Id */
0x4, 0, 0, 0, /* subChunk2Size */
0xFF, 0xFF, 0xFF, 0xFF, /* numOfSamples */
'd', 'a', 't', 'a',
0xFF, 0xFF, 0xFF, 0xFF
};
//*****************************************************************************
//
//! Plays back an audio file.
//!
//! \param readFp is the offset to the register to write.
//!
//! This function records an audio file in Ogg, MP3, or WAV formats.e
//! If recording in WAV format, it updates the RIFF length headers
//! after recording has finished.
//!
//! \return None.
//
//*****************************************************************************
void Set32(uint8_t *d, uint32_t n) {
int i;
for (i=0; i<4; i++) {
*d++ = (uint8_t)n;
n >>= 8;
}
}
//*****************************************************************************
//
//! Plays back an audio file.
//!
//! \param readFp is the offset to the register to write.
//!
//! This function records an audio file in Ogg, MP3, or WAV formats.e
//! If recording in WAV format, it updates the RIFF length headers
//! after recording has finished.
//!
//! \return None.
//
//*****************************************************************************
void Set16(uint8_t *d, uint16_t n) {
int i;
for (i=0; i<2; i++) {
*d++ = (uint8_t)n;
n >>= 8;
}
}
//*****************************************************************************
//
//! Writes a register in the DS3231 RTC.
//!
//! \param ucRegister is the offset to the register to write.
//! \param ulData is the data to be written to the DAC register.
//!
//! This function will write the register passed in ucAddr with the value
//! passed in to ulData. The data in ulData is actually 9 bits and the
//! value in ucAddr is interpreted as 7 bits.
//!
//! \return True on success or false on error.
//
//*****************************************************************************
void VS10xxSciWrite(uint8_t addr, uint16_t data)
{
//
// Set xDCS pin to high state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xDCS, VS1003_xDCS);
//
// Set xCS pin to low state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xCS, 0);
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Send write code
//
SSIDataPut(VS1003_SSI_BASE, WRITE_CODE);
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Send register adress
//
SSIDataPut(VS1003_SSI_BASE, addr);
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Send high byte to VS1003
//
SSIDataPut(VS1003_SSI_BASE, (uint8_t) (data >> 8));
//SSIDataPut(VS1003_SSI_BASE, (uint8_t) data);
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Send low byte to VS1003
//
SSIDataPut(VS1003_SSI_BASE, (uint8_t) data);
//SSIDataPut(VS1003_SSI_BASE, (uint8_t) (data >> 8));
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Set xCS pin to high state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xCS, VS1003_xCS);
//
// Wait until DREQ becomes high state and execution has been compleated
//
while (!GPIOPinRead(VS1003_CTL_GPIO_PORT_BASE, VS1003_DREQ));
}
//*****************************************************************************
//
//! Writes a register in the DS3231 RTC.
//!
//! \param ucRegister is the offset to the register to write.
//! \param ulData is the data to be written to the DAC register.
//!
//! This function will write the register passed in ucAddr with the value
//! passed in to ulData. The data in ulData is actually 9 bits and the
//! value in ucAddr is interpreted as 7 bits.
//!
//! \return True on success or false on error.
//
//*****************************************************************************
uint16_t VS10xxSciRead(uint8_t addr)
{
uint32_t ui8ByteHigh;
uint32_t ui8ByteLow;
//
// Set xCS pin to low state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xCS, 0);
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Set VS1003 into read mode
//
SSIDataPut(VS1003_SSI_BASE, READ_CODE); // READ_CODE: 0x03 (00000011)
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Send register address
//
SSIDataPut(VS1003_SSI_BASE, addr);
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Read high byte
//
SSIDataPut(VS1003_SSI_BASE, 0); // write dummy byte
SSIDataGet(VS1003_SSI_BASE, &ui8ByteHigh); // read data frm rx fifo
//SSIDataGetNonBlocking(VS1003_SSI_BASE, &ui8ByteHigh); // read data frm rx fifo
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Read low byte
//
SSIDataPut(VS1003_SSI_BASE, 0); // write dummy data
SSIDataGet(VS1003_SSI_BASE, &ui8ByteLow); // read data frm rx fifo
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Set xCS pin to high state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xCS, VS1003_xCS);
return ( (uint16_t) ((ui8ByteHigh << 8) | ui8ByteLow) );
}
//*****************************************************************************
//
//! Writes a register in the DS3231 RTC.
//!
//! \param ucRegister is the offset to the register to write.
//! \param ulData is the data to be written to the DAC register.
//!
//! This function will write the register passed in ucAddr with the value
//! passed in to ulData. The data in ulData is actually 9 bits and the
//! value in ucAddr is interpreted as 7 bits.
//!
//! \return True on success or false on error.
//
//*****************************************************************************
int VS10xxSdiWrite(const uint8_t *data, uint8_t bytes)
{
uint8_t ui8i;
//
// Check max. number of bytes to be transfered
//
if(bytes > 32)
{
return -1; // Error: Too many bytes to transfer
}
//
// Set xCS pin to high state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xCS, VS1003_xCS);
//
// Set xDCS pin to low state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xDCS, 0);
//
// Send data array to VS1003
//
for (ui8i = 0; ui8i < bytes; ui8i++)
{
//
// Wait until DREQ becomes high state
//
while (!GPIOPinRead(VS1003_CTL_GPIO_PORT_BASE, VS1003_DREQ));
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Send one byte to VS1003
//
SSIDataPut(VS1003_SSI_BASE, data[ui8i]);
}
//
// Wait for any previous SSI operation to finish.
//
while(SSIBusy(VS1003_SSI_BASE)){}
//
// Set BSYNC pin to high state
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xDCS, VS1003_xDCS);
return 0;
}
//*****************************************************************************
//
//! Writes a register in the DS3231 RTC.
//!
//! \param ucRegister is the offset to the register to write.
//! \param ulData is the data to be written to the DAC register.
//!
//! This function will write the register passed in ucAddr with the value
//! passed in to ulData. The data in ulData is actually 9 bits and the
//! value in ucAddr is interpreted as 7 bits.
//!
//! \return True on success or false on error.
//
//*****************************************************************************
void VS10xxSwReset(void)
{
VS10xxSciWrite(SCI_MODE, SM_SDINEW | SM_RESET);
}
//*****************************************************************************
//
//! Plays back an audio file.
//!
//! \param readFp is the offset to the register to write.
//!
//! This function records an audio file in Ogg, MP3, or WAV formats.e
//! If recording in WAV format, it updates the RIFF length headers
//! after recording has finished.
//!
//! \return None.
//
//*****************************************************************************
void VS10xxFilePlay(FILE *readFp)
{
static uint8_t playBuf[FILE_BUFFER_SIZE];
uint32_t bytesInBuffer; // How many bytes in buffer left
uint32_t pos=0; // File position
long nextReportPos=0; // File pointer where to next collect/report
int i;
int c;
int volLevel;
/*
#ifdef PLAYER_USER_INTERFACE
int volLevel = VS10xxSciRead(SCI_VOL) & 0xFF; // Assume both channels at same level
int c;
#endif
*/
playerState = psPlayback; // Set state to normal playback
VS10xxSciWrite(SCI_DECODE_TIME, 0); // Reset DECODE_TIME
/******************************************************************************************
* Main playback loop
******************************************************************************************/
while ((bytesInBuffer = fread(playBuf, 1, FILE_BUFFER_SIZE, readFp)) > 0 && playerState != psStopped)
{
uint8_t *bufP = playBuf;
while (bytesInBuffer && playerState != psStopped)
{
{
int t = min(SDI_MAX_TRANSFER_SIZE, bytesInBuffer);
// This is the heart of the algorithm: on the following line
// actual audio data gets sent to VS10xx.
VS10xxSdiWrite(bufP, t);
bufP += t;
bytesInBuffer -= t;
pos += t;
}
/* If the user has requested cancel, set VS10xx SM_OUTOFWAV bit */
if (playerState == psUserRequestedCancel) {
if (audioFormat == afMp3 || audioFormat == afUnknown) {
playerState = psStopped;
} else {
unsigned short oldMode;
playerState = psCancelSentToVS10xx;
UARTprintf("\nSetting SM_OUTOFWAV at file offset %ld\n", pos);
oldMode = VS10xxSciRead(SCI_MODE);
VS10xxSciWrite(SCI_MODE, oldMode | SM_OUTOFWAV);
}
}
/* If VS10xx SM_OUTOFWAV bit has been set, see if it has gone
through. If it is, it is time to stop playback. */
if (playerState == psCancelSentToVS10xx) {
unsigned short mode = VS10xxSciRead(SCI_MODE);
if (!(mode & SM_OUTOFWAV)) {
UARTprintf("SM_OUTOFWAV has cleared at file offset %ld\n", pos);
playerState = psStopped;
}
}
/* If playback is going on as normal, see if we need to collect and
possibly report */
if (playerState == psPlayback && pos >= nextReportPos) {
#ifdef REPORT_ON_SCREEN
uint16_t sampleRate;
uint16_t h1 = VS10xxSciRead(SCI_HDAT1);
#endif
nextReportPos += (audioFormat == afMidi || audioFormat == afUnknown) ?
REPORT_INTERVAL_MIDI : REPORT_INTERVAL;
#ifdef REPORT_ON_SCREEN
if (h1 == 0x7665) {
audioFormat = afRiff;
} else if (h1 == 0x4d54) {
audioFormat = afMidi;
} else if ((h1 & 0xffe6) == 0xffe2) {
audioFormat = afMp3;
} else {
audioFormat = afUnknown;
}
sampleRate = VS10xxSciRead(SCI_AUDATA);
UARTprintf("\r%ldKiB "
"%1ds %dHz %s %s"
" %04x ",
pos/1024,
VS10xxSciRead(SCI_DECODE_TIME),
sampleRate & 0xFFFE, (sampleRate & 1) ? "stereo" : "mono",
afName[audioFormat], h1
);
fflush(stdout);
#endif /* REPORT_ON_SCREEN */
}
} /* if (playerState == psPlayback && pos >= nextReportPos) */
/* User interface. This can of course be completely removed and
basic playback would still work. */
#ifdef PLAYER_USER_INTERFACE
/* GetUICommand should return -1 for no command and -2 for CTRL-C */
// c = GetUICommand();
switch (c) {
/* Volume adjustment */
case '-':
if (volLevel < 255) {
volLevel++;
VS10xxSciWrite(SCI_VOL, volLevel*0x101);
}
break;
case '+':
if (volLevel) {
volLevel--;
VS10xxSciWrite(SCI_VOL, volLevel*0x101);
}
break;
/* Show some interesting registers */
case '_':
UARTprintf("\nvol %1.1fdB, MODE %04x, ST %04x, "
"HDAT1 %04x HDAT0 %04x\n",
-0.5*volLevel,
VS10xxSciRead(SCI_MODE),
VS10xxSciRead(SCI_STATUS),
VS10xxSciRead(SCI_HDAT1),
VS10xxSciRead(SCI_HDAT0));
break;
/* Ask player nicely to stop playing the song. */
case 'q':
if (playerState == psPlayback)
playerState = psUserRequestedCancel;
break;
/* Forceful and ugly exit. For debug uses only. */
case 'Q':
//RestoreUIState();
UARTprintf("\n");
exit(EXIT_SUCCESS);
break;
/* Toggle differential mode */
case 'd':
{
uint16_t t = VS10xxSciRead(SCI_MODE) ^ SM_DIFF;
UARTprintf("\nDifferential mode %s\n", (t & SM_DIFF) ? "on" : "off");
VS10xxSciWrite(SCI_MODE, t);
}
break;
/* Show help */
case '?':
UARTprintf("\nInteractive VS1003 file player keys:\n"
"- +\tVolume down / up\n"
"_\tShow current settings\n"
"q Q\tQuit current song / program\n"
"d\tToggle Differential\n"
);
break;
/* Unknown commands or no command at all */
default:
if (c < -1) {
UARTprintf("Ctrl-C, aborting\n");
fflush(stdout);
//RestoreUIState();
exit(EXIT_FAILURE);
}
if (c >= 0) {
UARTprintf("\nUnknown char '%c' (%d)\n", isprint(c) ? c : '.', c);
}
break;
} /* switch (c) */
#endif /* PLAYER_USER_INTERFACE */
} /* while ((bytesInBuffer = fread(...)) > 0 && playerState != psStopped) */
#ifdef PLAYER_USER_INTERFACE
//RestoreUIState();
#endif /* PLAYER_USER_INTERFACE */
UARTprintf("\nSending %d footer %d's... ", SDI_END_FILL_BYTES, 0);
fflush(stdout);
/* Earlier we collected endFillByte. Now, just in case the file was
broken, or if a cancel playback command has been given, write
lots of endFillBytes. */
memset(playBuf, 0, sizeof(playBuf));
for (i=0; i<SDI_END_FILL_BYTES; i+=SDI_MAX_TRANSFER_SIZE) {
VS10xxSdiWrite(playBuf, SDI_MAX_TRANSFER_SIZE);
}
/* If SM_OUTOFWAV is on at this point, there is some weirdness going
on. Reset the IC just in case. */
if (VS10xxSciRead(SCI_MODE) & SM_OUTOFWAV) {
VS10xxSwReset();
}
/* That's it. Now we've played the file as we should, and left VS10xx
in a stable state. It is now safe to call this function again for
the next song, and again, and again... */
UARTprintf("ok\n");
}
//*****************************************************************************
//
//! Records a file
//!
//! \param ucRegister is the offset to the register to write.
//! \param ulData is the data to be written to the DAC register.
//!
//! This function records an audio file in Ogg, MP3, or WAV formats.e
//! If recording in WAV format, it updates the RIFF length headers
//! after recording has finished.
//!
//! \return None.
//
//*****************************************************************************
void VS10xxFileRecord(FILE *writeFp) {
static uint8_t recBuf[REC_BUFFER_SIZE];
uint32_t nextReportPos=0; // File pointer where to next collect/report
uint32_t fileSize = 0;
int volLevel = VS10xxSciRead(SCI_VOL) & 0xFF;
int c;
uint32_t adpcmBlocks = 0;
uint16_t sampleRate;
uint16_t divReg;
playerState = psPlayback;
UARTprintf("VS1003RecordFile\n");
/* Initialize recording */
/* Set clock to a known, high value. */
VS10xxSciWrite(SCI_CLOCKF, HZ_TO_SC_FREQ(12288000) | SC_MULT_03_40X | SC_ADD_03_00X);
/* Voice quality ADPCM recording at 8 kHz.
This will result in a 32.44 kbit/s bitstream. */
sampleRate = 8000;
/* Calculate closest possible value for divider register */
divReg = (int)((4.0*12288000)/256/sampleRate+0.5);
/* Calculate back what sample rate we actually got */
sampleRate = 4*12288000/(256*divReg);
VS10xxSciWrite(SCI_RECRATE, divReg);
VS10xxSciWrite(SCI_RECGAIN, 0); /* 1024 = gain 1, 0 = AGC */
/* Values according to VS1003b Datasheet Chapter "Adding a RIFF Header" */
Set32(adpcmHeader+24, sampleRate);
Set32(adpcmHeader+28, (uint32_t)sampleRate*256/505);
fwrite(adpcmHeader, sizeof(adpcmHeader), 1, writeFp);
fileSize = sizeof(adpcmHeader);
/* Start the encoder */
VS10xxSciWrite(SCI_MODE, VS10xxSciRead(SCI_MODE) | SM_ADPCM | SM_RESET);
#ifdef RECORDER_USER_INTERFACE
//SaveUIState();
#endif /* RECORDER_USER_INTERFACE */
while (playerState != psStopped) {
int n;
#ifdef RECORDER_USER_INTERFACE
{
//c = GetUICommand();
switch(c) {
case 'q':
UARTprintf("\nSwitching encoder off...\n");
playerState = psStopped;
break;
case '-':
if (volLevel < 255) {
volLevel++;
VS10xxSciWrite(SCI_VOL, volLevel*0x101);
}
break;
case '+':
if (volLevel) {
volLevel--;
VS10xxSciWrite(SCI_VOL, volLevel*0x101);
}
break;
case '_':
UARTprintf("\nvol %4.1f\n", -0.5*volLevel);
break;
case '?':
UARTprintf("\nInteractive VS1003 file recorder keys:\n"
"- +\tVolume down / up\n"
"_\tShow current settings\n"
"q\tQuit recording\n"
);
break;
default:
if (c < -1) {
UARTprintf("Ctrl-C, aborting\n");
fflush(stdout);
//RestoreUIState();
exit(EXIT_FAILURE);
}
if (c >= 0) {
UARTprintf("\nUnknown char '%c' (%d)\n", isprint(c) ? c : '.', c);
}
break;
}
}
#endif /* RECORDER_USER_INTERFACE */
/* See if there is some data available */
if ((n = VS10xxSciRead(SCI_RECWORDS)) > REC_BUFFER_SIZE) {
int i;
uint8_t *rbp = recBuf;
/* Always writes one or two IMA ADPCM block(s) at a time */
n = REC_BUFFER_SIZE/2;
adpcmBlocks += 2;
for (i=0; i<n; i++) {
uint16_t w = VS10xxSciRead(SCI_RECDATA);
*rbp++ = (uint8_t)(w >> 8);
*rbp++ = (uint8_t)(w & 0xFF);
}
fwrite(recBuf, 1, 2*n, writeFp);
fileSize += 2*n;
}
if (fileSize - nextReportPos >= REPORT_INTERVAL) {
nextReportPos += REPORT_INTERVAL;
UARTprintf("\r%ldKiB ", fileSize/1024);
UARTprintf("%uHz mono RIFF ", sampleRate);
fflush(stdout);
}
} /* while (playerState != psStopped) */
/* Update file sizes according to VS1003b Datasheet Chapter
"Adding a RIFF Header" */
fseek(writeFp, 0, SEEK_SET);
Set32(adpcmHeader+4, fileSize-8);
Set32(adpcmHeader+48, adpcmBlocks*505);
Set32(adpcmHeader+56, fileSize-60);
fwrite(adpcmHeader, sizeof(adpcmHeader), 1, writeFp);
#ifdef RECORDER_USER_INTERFACE
// RestoreUIState();
#endif /* RECORDER_USER_INTERFACE */
/* Finally, reset the VS10xx software, including realoading the
patches package, to make sure everything is set up properly. */
//VSTestInitSoftware();
UARTprintf("ok\n");
}
//*****************************************************************************
//
//! Writes a register in the DS3231 RTC.
//!
//! \param ucRegister is the offset to the register to write.
//! \param ulData is the data to be written to the DAC register.
//!
//! This function will write the register passed in ucAddr with the value
//! passed in to ulData. The data in ulData is actually 9 bits and the
//! value in ucAddr is interpreted as 7 bits.
//!
//! \return True on success or false on error.
//
//*****************************************************************************
uint8_t VS10xxInit(void)
{
//
// Enable the peripherals used by this driver
//
SysCtlPeripheralEnable(VS1003_SSI_SYSCTL_PERIPH);
SysCtlPeripheralEnable(VS1003_SSI_GPIO_SYSCTL_PERIPH);
SysCtlPeripheralEnable(VS1003_CTL_GPIO_SYSCTL_PERIPH);
// PD2 f�r SSI1Rx
//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
//GPIOPinConfigure(GPIO_PD2_SSI1RX);
//GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0);
//
// Select the SSI function for the appropriate pins
//
GPIOPinConfigure(VS1003_PINCFG_SSICLK);
GPIOPinConfigure(VS1003_PINCFG_SSIRX);
GPIOPinConfigure(VS1003_PINCFG_SSITX);
//
// Configure the pins for the SSI function
//
GPIOPinTypeSSI(VS1003_SSI_GPIO_PORT_BASE, VS1003_SSI_PINS);
//
// Configure VS1003 xRST ,xDCS and xCS control pins as GPIO output
//
GPIOPinTypeGPIOOutput(VS1003_CTL_GPIO_PORT_BASE, VS1003_CTL_PINS);
//
// Configure VS1003 DREQ control pins as GPIO output
//
GPIOPinTypeGPIOInput(VS1003_CTL_GPIO_PORT_BASE, VS1003_DREQ);
//
// Disable VS1003
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xRST, 0);
//
// Configure the SSI port
//
//
SSIDisable(VS1003_SSI_BASE);
SSIConfigSetExpClk( VS1003_SSI_BASE,
SysCtlClockGet(),
SSI_FRF_MOTO_MODE_3,
SSI_MODE_MASTER,
VS1003_SSI_CLOCK,
8);
SSIEnable(VS1003_SSI_BASE);
//
// Enable VS1003
//
GPIOPinWrite(VS1003_CTL_GPIO_PORT_BASE, VS1003_xRST, VS1003_xRST);
uint16_t ret; // Test variable
/* 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. */
VS10xxSciRead(SCI_MODE);
/* 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);
VS10xxSciWrite(SCI_MODE, SM_SDINEW | SM_RESET);
/* 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. */
//VS10xxSciWrite(SCI_HDAT0, 0xABAD); // 10101011 10101101 00001000
//ret = VS10xxSciRead(SCI_HDAT0);
//VS10xxSciWrite(SCI_HDAT1, 0x1DEA); // 00011101 11101010 00001001
VS10xxSciWrite(SCI_BASS, 0x020A); // 00000010 00000010 00001000
ret = VS10xxSciRead(SCI_BASS);
/*
if (ReadSci(SCI_HDAT0) != 0xABAD || ReadSci(SCI_HDAT1) != 0x1DEA) {
UARTprintf("There is something wrong with VS10xx\n");
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. */
VS10xxSciWrite(SCI_CLOCKF, HZ_TO_SC_FREQ(12288000) | SC_MULT_03_30X | SC_ADD_03_10X);
/* Now when we have upped the VS10xx clock speed, the microcontroller
SPI bus can run faster. Do that before you start playing or
recording files. */
/* Set volume level at -6 dB of maximum */
VS10xxSciWrite(SCI_VOL, 0x0c0c);
/* We're ready to go. */
return 0;
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
/***************************************************************
****************************************************************/
/*
Main function that activates either playback or recording.
*/
/*
int VSTestHandleFile(const char *fileName, int record) {
if (!record) {
FILE *fp = fopen(fileName, "rb");
UARTprintf("Play file %s\n", fileName);
if (fp) {
VS1003PlayFile(fp);
} else {
UARTprintf("Failed opening %s for reading\n", fileName);
return -1;
}
} else {
FILE *fp = fopen(fileName, "wb");
UARTprintf("Record file %s\n", fileName);
if (fp) {
VS1003RecordFile(fp);
} else {
UARTprintf("Failed opening %s for writing\n", fileName);
return -1;
}
}
return 0;
}
*/