Embedded system Fun Blog
























































Find out all the best information, libraries and circuit about the latest Embedded systems.

Saturday, 7 January 2012

VS1011 MP3 Decoder Module: source pack 4

.f:rom: http://people.ece.cornell.edu/land/courses/ece4760/FinalProjects/s2011/yl478_clt67/yl478_clt67/yl478_clt67_files/displaycontrol/mp3_VS1011E.c

/* Functions for VS1011E-L MP3 decoder
   modified from the VS1033D decoder demo at http://frank.circleofcurrent.com/musicclock/
   we changed the functions so that playback will not block in a while loop, but the 
   VS_playfile function is called repeatedly from main.c
   We also changed the values that are written into the registers of the VS1011E-L
   Our SPI speeds are also different as we are using a 16 MHz clock for the microcontroller
   as compared to the demo's 8 MHz clocked microcontroller.
  
   This file is free software; you can redistribute it and/or modify
   it under the terms of either the GNU General Public License version 2
   or the GNU Lesser General Public License version 2.1, both as
   published by the Free Software Foundation.
 */

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdio.h>
#include "fatfs/ff.h"
#include "fatfs/diskio.h"
#include "uart.h"
#include "SDcard_audio.h"

typedef enum {
    MP3_REG_MODE = 0x00,
    MP3_REG_CLOCKF = 0x03,
    MP3_REG_VOL = 0x0B,
} mp3_register_t;

//wait for the decoder to be ready
inline void mp3_waitReady(uint8_t cnt) {
    for(uint8_t i = 0; i < cnt; i++)
 {
  _delay_us(10);
  if (bit_is_clear(MP3_PORTINPUT, MP3_PIN_DREQ)) break;
 }
 loop_until_bit_is_set(MP3_PORTINPUT, MP3_PIN_DREQ);
}

inline uint8_t mp3_spi(uint8_t data)
{
    SPDR = data; // send
    loop_until_bit_is_set(SPSR, SPIF); // wait until sent
    return SPDR; // get reply
}

//write data in to register addr
void mp3_writeReg(mp3_register_t addr, uint16_t data) {
    spi_slow();

    MP3_PORTOUTPUT &= ~_BV(MP3_PIN_CS); // select

    mp3_spi(0b00000010); // write command
    mp3_spi(addr); // send address
    mp3_spi((data & 0xFF00) >> 8); // send data MSB first
    mp3_spi(data & 0x00FF);

    MP3_PORTOUTPUT |= _BV(MP3_PIN_CS); // deselect

    spi_fast();

    mp3_waitReady(10);
}

//send a packet of MP3 data from the buffer on the microcontroller to the VS1011E-L
void mp3_playPacket(uint8_t* buffer, uint8_t length) {
    spi_slow();
    loop_until_bit_is_set(MP3_PORTINPUT, MP3_PIN_DREQ); // wait for ready
    MP3_PORTOUTPUT &= ~_BV(MP3_PIN_DCS); // select
    for (uint8_t i = 0; i < length; i++)
    {
        mp3_spi(buffer[i]);
    }
    MP3_PORTOUTPUT |= _BV(MP3_PIN_DCS); // deselect
    spi_fast();
}

//play the file
mp3_playStatus_t VS_playfile(FIL* file) {
    uint8_t buff[32];
    UINT read;
 //fprintf(stdout,"VS DREQ %d\r\n", MP3_PORTINPUT & _BV(MP3_PIN_DREQ));
 if (MP3_PORTINPUT & _BV(MP3_PIN_DREQ)) {
     f_read(file, buff, 32, &read); // read the file
     mp3_playPacket(buff, read); // play the sound
     if (read != 32) return PLAYSTATUS_ENDOFFILE;
 } else return PLAYSTATUS_BUSY;
    return PLAYSTATUS_OK;
}

//initialize the VS-1011E-L by writing settings to its registers
void init_VS() {
    spi_slow();
    // DREQ is input, no pull-up
    MP3_PORTOUTPUT &= ~_BV(MP3_PIN_DREQ);
    _delay_ms(100); // slight delay, let VS1011 finish boot initialization
    MP3_PORTOUTPUT |= _BV(MP3_PIN_RST); // bring out of reset, get ready
    mp3_waitReady(10);
 mp3_writeReg(MP3_REG_MODE, 0b0000100000000010); // the mode setting for the decoder
 mp3_writeReg(MP3_REG_CLOCKF, 0x9800); // this is 12.288MHz XTALI with clock doubler
 mp3_writeReg(MP3_REG_VOL, 0); // attenuation = 0 for maximum volume
} 
 
 



No comments:

Post a Comment