FLAC File Format Decoding Issues (VS1053B)

Writing software for systems that use VLSI Solution's devices as slave codecs to a host microcontroller.
Post Reply
smalo0
User
Posts: 2
Joined: Wed 2017-06-28 16:20

FLAC File Format Decoding Issues (VS1053B)

Post by smalo0 » Wed 2017-06-28 16:52

Setup:
- PCB that I designed
- Fresscale KL15Z64 ARM processor
- VS1053B decoder, using VS1053B-PATCHES-FLAC.PLG revision 2.4
- FATFS revision 29000 (R0.10a)
- IAR EWARM 8.11.1 compiler
- SPI baud rate of 12 MHz
- FLAC files encoded using the standard command line encoder https://xiph.org/flac/

Problems:
When decoding FLAC files and skipping through them fairly quickly (waiting 1 second after each starts), eventually the decoder will stop outputting audio. Doing this with MP3 files or WAV files works fine. If I wait 10 seconds or more, suddenly the audio will come back.

I have created a band-aid for this problem by resetting the decoder after each file, and it does work. Unfortunately this takes time and also causes some audible pops when switching tracks. So I would like to figure out what I am doing wrong in my code or if there is a problem with the decoder plugin.

Below is the code I use to interact with the decoder itself. Any help would be appreciated!
Thanks,
Steve

Code: Select all

//------------------------------------------------------------------------------
// kl15z32_set_spi0_br
//------------------------------------------------------------------------------
void kl15z32_set_spi0_br(boolean fast) {
	if(fast) {
		// set baud rate divisors
		// baud rate = (bus clock / prescaler) / bad rate divider = (24 MHz / 1) / 2 = 12 MHz
		SPI0_BR = (0 << 4) | // SPPR - spi baud rate prescale divisor (divide by 1)
				  (0 << 0);  // SPR - spi baud rate divisor (divide by 2)

	}
	else {
		// set baud rate divisors
		// baud rate = (bus clock / prescaler) / bad rate divider = (24 MHz / 2) / 4 = 3 MHz
		SPI0_BR = (1 << 4) | // SPPR - spi baud rate prescale divisor (divide by 2)
				  (1 << 0);  // SPR - spi baud rate divisor (divide by 4)
	}
}
//------------------------------------------------------------------------------
// vs1053_cancel_playback
//
// When a file is currently playing and needs to be cancelled.
//------------------------------------------------------------------------------
void vs1053_cancel_playback(void) {
    uint_32 index;
	uint_32 eindex;
	uint_8 endfillbyte;
    FRESULT fres;
    uint_8 read_buff[32];
	uint_32 read_buff_size;

	// set SM_CANCEL
	vs1053_set_cancel();

    // continue sending audio file in 32 bit pieces
    for(eindex = 0; eindex < 384; eindex++) {
        #ifdef WATCHDOG_ON
			// disable interrupts while feeding to prevent misfeeds
			__disable_interrupt();

			// service cop register - feed watchdog
			SIM_SRVCOP = 0x55;
			SIM_SRVCOP = 0xAA;

			__enable_interrupt();
		#endif

        fres = f_read(&g_s.sfptr, read_buff, 32, &read_buff_size);
        if(fres == FR_OK) {
            for(index = 0; index < read_buff_size; index++)	vs1053_sdi_write(read_buff[index]);

            // if EOF
            if(read_buff_size < 32) {
                // close the file
                f_close(&g_s.sfptr);

                // flush and complete
                vs1053_complete_playback();
                return;
            }
        }
        else {
            f_close(&g_s.sfptr);
            vs1053_init();
            return;
        }

        // check cancel; if still set, repeat; otherwise go on
		if(!vs1053_read_cancel()) break;
    }

    // close the file
    f_close(&g_s.sfptr);

    // if still not cancelled, do a software reset
	if(vs1053_read_cancel()) vs1053_init();
	else {
		// read endfillbyte
        endfillbyte = vs1053_read_endfillbyte();

        // write endfillbyte
		for(index = 0; index < 12288; index++) {
            #ifdef WATCHDOG_ON
                // disable interrupts while feeding to prevent misfeeds
                __disable_interrupt();

                // service cop register - feed watchdog
                SIM_SRVCOP = 0x55;
                SIM_SRVCOP = 0xAA;

                __enable_interrupt();
            #endif

            vs1053_sdi_write(endfillbyte);
        }

		// if HDAT0 or HDAT1 are high, software reset
		if(vs1053_read_hdat()) vs1053_init();
	}
}
//------------------------------------------------------------------------------
// vs1053_complete_playback
//
// When a file has reached the end.
//------------------------------------------------------------------------------
void vs1053_complete_playback(void) {
	uint_32 index;
	uint_32 eindex;
	uint_8 endfillbyte;

	// read endfillbyte
	endfillbyte = vs1053_read_endfillbyte();

    // write it to flush the decoder
    for(eindex = 0; eindex < 12228; eindex++) {
        #ifdef WATCHDOG_ON
			// disable interrupts while feeding to prevent misfeeds
			__disable_interrupt();

			// service cop register - feed watchdog
			SIM_SRVCOP = 0x55;
			SIM_SRVCOP = 0xAA;

			__enable_interrupt();
		#endif

        vs1053_sdi_write(endfillbyte);
    }

	// set SM_CANCEL
	vs1053_set_cancel();

	// send up to 12288 bytes of endfillbyte and check cancel
	for(eindex = 0; eindex < 384; eindex++) {
        #ifdef WATCHDOG_ON
			// disable interrupts while feeding to prevent misfeeds
			__disable_interrupt();

			// service cop register - feed watchdog
			SIM_SRVCOP = 0x55;
			SIM_SRVCOP = 0xAA;

			__enable_interrupt();
		#endif

        // send at least 32 bytes of endfillbyte
		for(index = 0; index < 32; index++) vs1053_sdi_write(endfillbyte);

		// check cancel; if still set, repeat; otherwise go on
		if(!vs1053_read_cancel()) break;
	}

	if(vs1053_read_cancel() || vs1053_read_hdat()) vs1053_init();
}
//------------------------------------------------------------------------------
// vs1053_init
//------------------------------------------------------------------------------
void vs1053_init(void) {
	uint_16 data;

	// mute the headphone outputs to stop pops
	GPIO_HP1_ENA_CLR;
	GPIO_HP2_ENA_CLR;

	// set SPI0 to talk slow
	kl15z32_set_spi0_br(FALSE);

	// reset chip
	GPIO_VS_RST_SET;
	kl15z32_delay(10);

	// wait for it to boot
	GPIO_VS_RST_CLR;
	while(!GPIO_VS_DREQ);

	// write to mode register
	data = (0 << 0) | 	// SM_DIFF
		   (0 << 1) | 	// SM_LAYER12
		   (0 << 2) | 	// SM_RESET
		   (0 << 3) | 	// SM_CANCEL
		   (0 << 4) | 	// SM_EARSPEAKER_LO
		   (0 << 5) | 	// SM_TESTS
		   (0 << 6) | 	// SM_STREAM
		   (0 << 7) | 	// SM_EARSPEAKER_HI
		   (0 << 8) | 	// SM_DACT - data read on rising edge
		   (0 << 9) | 	// SM_SDIORD - bytes read on SDI are MSB first
		   (1 << 10) | 	// SM_SDISHARE - share SCI/SDI chip select
		   (1 << 11) |  // SM_SDINEW - native mode (new mode)
		   (0 << 12) |  // SM_ADPCM - recording active (no)
		   (0 << 14) |  // SM_LINE1 - mic/line selector
		   (0 << 15);	// SM_CLK_RANGE - clock from 12 to 13 MHz

	vs1053_sci_write(0x0, data);

	// write clock frequency multiplier
	// clock mult to 3 after reset for typical values; 55.3 MHz is the maxium, typical is 36.864 MHz
	data = (5 << 13) | // SC_MULT -> XTALI * 4 = 49.152 MHz
		   (0 << 11) | // SC_ADD  -> no modification allowed
		   (0 << 0);   // SC_FREQ - not needed, running at 12.288 MHz

	vs1053_sci_write(0x3, data);

	// wait for clock change to go into effect
	kl15z32_delay(1);

	// set GPIO direction register - set GPIO to outputs to enable I2S out
	// write to WRAMADDR the address
	data = 0xC017;
	vs1053_sci_write(0x7, data);

	// now write the direction to WRAM
	data = 0xf0;
	vs1053_sci_write(0x6, data);

	// set I2S_CONFIG
	// first write to set the WRAMADDR address to I2S_CONFIG
	data = 0xC040;
	vs1053_sci_write(0x7, data);

	// next write the value into SCI_WRAM
	data = (0 << 0) | // I2S_CF_SRATE - 48 kHz I2S rate
		   (1 << 2) | // I2S_CF_ENA - enables I2S
		   (1 << 3);  // I2S_CF_MCLK_ENA - enables MCLK output at 12.288 MHz

	vs1053_sci_write(0x6, data);

	// set SPI0 to talk fast
	kl15z32_set_spi0_br(TRUE);

	// patch the decoder to fix bugs and add FLAC decoding
	vs1053_patch();

	// enable headphone out (use muting in DSP for normal tasks)
    kl15z32_delay(10);
    if(!g_s.dip_single_output) {
        GPIO_HP1_ENA_SET;
        GPIO_HP2_ENA_SET;
    }
    else {
        if(g_s.single_output == 0) GPIO_HP1_ENA_SET;
        else if(g_s.single_output == 1) GPIO_HP2_ENA_SET;
    }
}
//------------------------------------------------------------------------------
// vs1053_patch
//
// Load the patch data into the VS1053 to fix bugs and enable additional format
// decoding. This function provided in the patch.
//------------------------------------------------------------------------------
void vs1053_patch(void) {
	int_32 i = 0;
	uint_8 addr;
	uint_16 n, val;

	while(i < sizeof(plugin)/sizeof(plugin[0])) {
		addr = (uint_8)plugin[i++];
		n = plugin[i++];
		if(n & 0x8000U) {
			// RLE run, replicate n samples
			n &= 0x7FFF;
			val = plugin[i++];
			while(n--) vs1053_sci_write(addr, val);
		}
		else {
			// copy run, copy n samples
			while (n--) {
				val = plugin[i++];
				vs1053_sci_write(addr, val);
			}
		}
	}
}
//------------------------------------------------------------------------------
// vs1053_read_cancel
//------------------------------------------------------------------------------
boolean vs1053_read_cancel(void) {
	uint_16 data;

	// read MODE register
	vs1053_sci_read(0x00, &data);

	if((data >> 3) & 0x1) return TRUE;
	else return FALSE;
}
//------------------------------------------------------------------------------
// vs1053_read_endfillbyte
//
// Located in X memory at 0x1e06.
//------------------------------------------------------------------------------
uint_8 vs1053_read_endfillbyte(void) {
    uint_16 data1 = 1;
	uint_16 data2 = 2;

	while(data1 != data2) {
		// write the endfillbyte register address to the WRAMADDR address register
		data1 = 0x1e06;
		vs1053_sci_write(0x7, data1);

		// read the endfillbyte from the WRAM register
		vs1053_sci_read(0x6, &data1);

		// do it a second time
		// write the endfillbyte register address to the WRAMADDR address register
		data2 = 0x1e06;
		vs1053_sci_write(0x7, data2);

		// read the endfillbyte from the WRAM register
		vs1053_sci_read(0x6, &data2);
	}

	return (uint_8)(data1 & 0xFF);
}
//------------------------------------------------------------------------------
// vs1053_read_hdat
//------------------------------------------------------------------------------
boolean vs1053_read_hdat(void) {
	uint_16 hdat0;
	uint_16 hdat1;

	// read the HDAT stream header data
	vs1053_sci_read(0x8, &hdat0);
	vs1053_sci_read(0x9, &hdat1);

	if(hdat0 | hdat1) return TRUE;
	else return FALSE;
}
//------------------------------------------------------------------------------
// vs1053_sci_read
//------------------------------------------------------------------------------
void vs1053_sci_read(uint_8 address, uint_16_ptr data) {
	uint_8 garbage;

	// check that DREQ is high before sending data
	while(!GPIO_VS_DREQ);

	// wait for SPTEF (spi transmit buffer empty flag) - MUST check this register for every write
	while(!(SPI0_S & SPI_S_SPTEF_MASK));

	// set the chip select
	GPIO_VS_XCS_SET;

	// transmit 'read' instruction
	SPI0_D = 0x03;

	// wait for SPRF data available in receive buffer and toss it
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	// transmit address
	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = address;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	// read 16 bit data
	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = 0xFF;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	*data = SPI0_D << 8;

	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = 0xFF;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	*data |= SPI0_D;

	// clear the chip select
	GPIO_VS_XCS_CLR;
}
//------------------------------------------------------------------------------
// vs1053_sci_write
// serial bus protocol for the SCI interface is an instruction byte, address
// byte, and one 16 bit data word
//------------------------------------------------------------------------------
void vs1053_sci_write(uint_8 address, uint_16 data) {
	uint_8 garbage;

	// check that DREQ is high before sending data
	while(!GPIO_VS_DREQ);

	// wait for SPTEF (spi transmit buffer empty flag) - MUST check this register for every write
	while(!(SPI0_S & SPI_S_SPTEF_MASK));

	// set the chip select
	GPIO_VS_XCS_SET;

	// transmit 'write' instruction
	SPI0_D = 0x02;

	// wait for SPRF data available in receive buffer and toss it
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	// transmit address
	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = address;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	// transmit 16 bit data
	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = (data >> 8) & 0xFF;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = data & 0xFF;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	// clear the chip select
	GPIO_VS_XCS_CLR;
}
//------------------------------------------------------------------------------
// vs1053_sdi_write
//
// Write music data to the decoder 'data' interface.
//------------------------------------------------------------------------------
void vs1053_sdi_write(uint_8 data) {
	uint_8 garbage;

	// check that DREQ is high before sending data
	while(!GPIO_VS_DREQ);

	// wait for SPTEF (spi transmit buffer empty flag) - MUST check this register for every write
	while(!(SPI0_S & SPI_S_SPTEF_MASK));

	// set the data chip select
	GPIO_VS_XDCS_SET;

	// transmit data
	SPI0_D = data;

	// wait for SPRF data available in receive buffer and toss it
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	GPIO_VS_XDCS_CLR;
}
//------------------------------------------------------------------------------
// vs1053_set_cancel
//
// Set SM_CANCEL to trigger the stop of playback; necessary when switching file
// formats.
//------------------------------------------------------------------------------
void vs1053_set_cancel(void) {
	uint_16 data;

	// write to mode register to set SM_CANCEL
	data = (0 << 0) | 	// SM_DIFF
		   (0 << 1) | 	// SM_LAYER12
		   (0 << 2) | 	// SM_RESET
		   (1 << 3) | 	// SM_CANCEL
		   (0 << 4) | 	// SM_EARSPEAKER_LO
		   (0 << 5) | 	// SM_TESTS
		   (0 << 6) | 	// SM_STREAM
		   (0 << 7) | 	// SM_EARSPEAKER_HI
		   (0 << 8) | 	// SM_DACT - data read on rising edge
		   (0 << 9) | 	// SM_SDIORD - bytes read on SDI are MSB first
		   (1 << 10) | 	// SM_SDISHARE - share SCI/SDI chip select
		   (1 << 11) |  // SM_SDINEW - native mode (new mode)
		   (0 << 12) |  // SM_ADPCM - recording active (no)
		   (0 << 14) |  // SM_LINE1 - mic/line selector
		   (0 << 15);	// SM_CLK_RANGE - clock from 12 to 13 MHz

	vs1053_sci_write(0x0, data);
}
//------------------------------------------------------------------------------
// decoder_state_machine
//
// The state machine for interfacing with the SD card and the VS1053 decoder.
//------------------------------------------------------------------------------
void decoder_state_machine(void) {
	DSTATUS dstat;
	FRESULT fres;
	uint_32 index;

	// audio read buffer
	uint_8 read_buff[512];
	uint_32 read_buff_size;

	switch(g_s.decoder_state) {
	case NO_CARD:
		// status LED is off
		g_s.status_led_counts = 0;
		GPIO_STATUS_LED_CLR;

		// check to see if a card is inserted and try to mount file system
		dstat = disk_status(0);
		if((dstat & STA_NOINIT) && (!(dstat & STA_NODISK)) && (!(dstat & STA_PROTECT))) {
			fres = f_mount(&fatfs, "", 1);
			if(fres != FR_OK) {
				// can't mount file system - card is bad
				f_mount(0, "", 0);
				g_s.decoder_state = BAD_CARD;
                break;
			}

            g_s.decoder_state = MOUNTED;
		}
		break;
	case BAD_CARD:
		// status LED is ON
		g_s.status_led_counts = 0;
		GPIO_STATUS_LED_SET;

		// card present but unable to mount file system; wait for card to be removed
		dstat = disk_status(0);
		if(dstat & STA_NODISK) g_s.decoder_state = NO_CARD;
		break;
	case UNMOUNT:
		f_close(&g_s.sfptr);
		f_mount(0, "", 0);
		vs1053_complete_playback();
		g_s.decoder_state = NO_CARD;
		break;
	case MOUNTED:
		// make sure card still present
		dstat = disk_status(0);
		if(dstat & STA_NODISK) {
            g_s.decoder_state = UNMOUNT;
            break;
        }

        // file system mounted and volume is present; open files
        fres = decoder_open_file(DECODER_FILE_FIRST, &g_s.sfptr);
        if(fres != FR_OK) {
            // no files present - unmount and stay in bad card
            f_mount(0, "", 0);
            g_s.decoder_state = BAD_CARD;
        }
        else {
            // file opened - start playing or wait to be triggered to play
            if(g_s.dip_continuous_play) g_s.decoder_state = PLAY;
            else g_s.decoder_state = STOPPED;
        }
		break;
	case PLAY:
		// set status led to blink fast
		g_s.status_led_counts = PIT_PLAY_COUNT;

		dstat = disk_status(0);
		if(dstat & STA_NODISK) {
            g_s.decoder_state = UNMOUNT;
            break;
        }

        // read into buffer
        fres = f_read(&g_s.sfptr, read_buff, 512, &read_buff_size);
        if(fres != FR_OK) {
            g_s.decoder_state = UNMOUNT;
            break;
        }

        // transfer to decoder
        for(index = 0; index < read_buff_size; index++)	vs1053_sdi_write(read_buff[index]);

        // check for end of file
        if(read_buff_size < 512) {
            // instruct the decoder to complete playback
            f_close(&g_s.sfptr);
            vs1053_complete_playback();

            // continuous play - just keep playing
            if(g_s.dip_continuous_play) g_s.decoder_state = NEXT;
            else {
                // otherwise, check if at the last file
                fres = decoder_open_file(DECODER_FILE_IS_LAST, &g_s.sfptr);

                if(fres == FR_OK) {
                    // if so, select first file and stop
                    g_s.decoder_state = MOUNTED;
                }
                else {
                    // if not, play the next file
                    g_s.decoder_state = NEXT;
                }
            }
        }
		break;
	case NEXT:
    case NEXT_WHILE_PLAYING:
		dstat = disk_status(0);
		if(dstat & STA_NODISK) {
            g_s.decoder_state = UNMOUNT;
            break;
        }

        // cancel play back
        if(g_s.decoder_state == NEXT_WHILE_PLAYING) vs1053_cancel_playback();

        fres = decoder_open_file(DECODER_FILE_NEXT, &g_s.sfptr);
        if(fres != FR_OK) {
            // no files present - unmount and stay in bad card
            f_mount(0, "", 0);
            g_s.decoder_state = BAD_CARD;
        }
        else {
            // file opened - start playing
            g_s.decoder_state = PLAY;
        }
		break;
    case PREV_WHILE_PLAYING:
		dstat = disk_status(0);
		if(dstat & STA_NODISK) {
            g_s.decoder_state = UNMOUNT;
            break;
        }

        // cancel play back
        vs1053_cancel_playback();

        fres = decoder_open_file(DECODER_FILE_PREV, &g_s.sfptr);
        if(fres != FR_OK) {
            // no files present - unmount and stay in bad card
            f_mount(0, "", 0);
            g_s.decoder_state = BAD_CARD;
            break;
        }

        // file opened - start playing
        g_s.decoder_state = PLAY;
		break;
	case STOP:
		// set status led to blink slow for stopped; unless in customer mode, blink fast
		if(!g_s.cust_mode) g_s.status_led_counts = PIT_STOP_COUNT;
		else g_s.status_led_counts = PIT_CUSTOMER_COUNT;

		dstat = disk_status(0);
		if(dstat & STA_NODISK) {
            g_s.decoder_state = UNMOUNT;
            break;
        }

        // cancel playback
        vs1053_cancel_playback();

        // open current file for playing
        fres = decoder_open_file(DECODER_FILE_CURRENT, &g_s.sfptr);
        if(fres != FR_OK) {
            // no files present - unmount and stay in bad card
            f_mount(0, "", 0);
            g_s.decoder_state = BAD_CARD;
            break;
        }

        g_s.decoder_state = STOPPED;
		break;
	case STOPPED:
		// do nothing but check to unmount
		dstat = disk_status(0);
		if(dstat & STA_NODISK) g_s.decoder_state = UNMOUNT;
		break;
	}
}

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

Re: FLAC File Format Decoding Issues (VS1053B)

Post by pasi » Thu 2017-06-29 11:28

Do you have other devices in the SPI bus?

You seem to use different chip selects for SCI and SDI, but you are still setting the SM_SHARED bit, which ignores xDCS and uses the inverse of xCS as SDI chip select.

The decoder can potentially decide to skip a lot of data if you perform a song switch during the FLAC header decode and the endfillbyte value replaces some size fields. But you seem to be continuing to send the original file data after setting SM_CANCEL, so that would only happen if some of the metadata sections are larger than 12288 bytes. (Btw, you have 12228 in a few places, although it probably does not matter.)

Maybe you could check for SCI_STATUS register bit DO_NOT_JUMP. Does its state correlate with the occurrance of the no-cancel issue?
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

smalo0
User
Posts: 2
Joined: Wed 2017-06-28 16:20

Re: FLAC File Format Decoding Issues (VS1053B)

Post by smalo0 » Thu 2017-06-29 14:20

I do not have any other devices on that SPI bus - there are two on the chip.

It turns out that the problem appears to be that I was reading and writing at 12 MHz to the chip! Since you can write a CLK/4 I did not notice that you can only read at CLK/7.

CLK/4 = 12.288 MHz
CLK/7 = 7.02 MHz

I changed my read routine to set the baud rate down before reading and back up after reading, and it appears to have fixed this issue.

Do you see a place where I am unnecessarily sending too much data to cancel or complete playback?

Thanks very much for your time and response!

Code: Select all

//------------------------------------------------------------------------------
// vs1053_sci_read
//------------------------------------------------------------------------------
void vs1053_sci_read(uint_8 address, uint_16_ptr data) {
	uint_8 garbage;

    // slow down the baud rate for reads; max is CLK/7 or 7 MHz
    kl15z32_set_spi0_br(FALSE);

	// check that DREQ is high before sending data
	while(!GPIO_VS_DREQ);

	// wait for SPTEF (spi transmit buffer empty flag) - MUST check this register for every write
	while(!(SPI0_S & SPI_S_SPTEF_MASK));

	// set the chip select
	GPIO_VS_XCS_SET;

	// transmit 'read' instruction
	SPI0_D = 0x03;

	// wait for SPRF data available in receive buffer and toss it
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	// transmit address
	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = address;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	garbage = SPI0_D;

	// read 16 bit data
	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = 0xFF;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	*data = SPI0_D << 8;

	while(!(SPI0_S & SPI_S_SPTEF_MASK));
	SPI0_D = 0xFF;
	while(!(SPI0_S & SPI_S_SPRF_MASK));
	*data |= SPI0_D;

	// clear the chip select
	GPIO_VS_XCS_CLR;

    // set baud rate back to maximum
    kl15z32_set_spi0_br(TRUE);
}
//------------------------------------------------------------------------------

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

Re: FLAC File Format Decoding Issues (VS1053B)

Post by pasi » Thu 2017-06-29 15:22

smalo0 wrote:
Thu 2017-06-29 14:20
I changed my read routine to set the baud rate down before reading and back up after reading, and it appears to have fixed this issue.
Great! You probably saw the CANCEL bit cleared when it was still set, and that caused the problems.
smalo0 wrote:
Thu 2017-06-29 14:20
Do you see a place where I am unnecessarily sending too much data to cancel or complete playback?
Not too much, because 12228 is less than 12288. For cancel, if checking CANCEL and HDAT works correctly and you send in 32-byte chunks, the code should send only just about what's necessary. (For end of file, send the 12288 endfillbytes to make sure the decoder has read everything, then cancel. It seemed fine, although I didn't look too closely.)
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

Post Reply

Who is online

Users browsing this forum: No registered users