modified for VS1033

Dependents:   11U68_MP3Player with TFTLCD 11U68_MP3Player-with-TFTLCD Mp3_1

Fork of VS1033 by en 129

VS1053.cpp

Committer:
nameless129
Date:
2015-07-24
Revision:
10:a8594af40a50
Parent:
9:1dd0ecaac8e5
Child:
11:da08a7b0947d

File content as of revision 10:a8594af40a50:

// ==================================================== Dec 21 2013, kayeks ==
// VS1053.cpp
// ===========================================================================
// Just a simple library for VLSI's mp3/midi codec chip
//   - Minimal and simple implementation (and dirty too)

#include "mbed.h"
#include "VS1053.h"

/** Constructor of class VS1053. */
VS1053::VS1053(PinName mosiPin, PinName misoPin, PinName sckPin,
               PinName csPin, PinName dcsPin, PinName dreqPin,
               PinName rstPin, uint32_t spiFrequency)
:
    spi(mosiPin, misoPin, sckPin),
    cs(csPin),
    dcs(dcsPin),
    dreq(dreqPin),
    rst(rstPin)
{
    useSpiFreq = spiFrequency;

    // Initialize outputs
    cs = 1;
    dcs = 1;
    rst = 1;
}

/** Destructor of class VS1053. */
VS1053::~VS1053() {
}

//SCI enable
void VS1053::sci_en(void)
{
    dcs = 1;
    cs = 0;
}

//SCI disable
void VS1053::sci_dis(void)
{
    dcs = 1;
    cs = 1;
}

//SDI enable
void VS1053::sdi_en(void)
{
    cs = 1;
    dcs = 0;
}

//SDI disable
void VS1053::sdi_dis(void)
{
    cs = 1;
    dcs = 1;
}

/** Make a hardware reset by hitting VS1053's RESET pin. */
void VS1053::hardwareReset() {
    rst = 0;
    wait(0.1);
    rst = 1;
    wait(0.1);
}

//Serial Command Interface(SCI) init
void VS1053::sci_init()
{
    spi.format(8, 0);
    spi.frequency(1000000);

    cs = 0;
    for(int i=0; i<4; i++)
    {
        spi.write(0xFF);                        //clock the chip a bit
    }
    cs = 1;
    dcs = 1;
    wait_us(5);
    writeReg(SCI_MODE,(SM_SDINEW));
    writeReg(SCI_CLOCKF, 0x9800);
}

//Serial Data Interface(SDI) init
void VS1053::sdi_init()
{
    spi.format(8, 0);
    spi.frequency(useSpiFreq);

    writeReg(SCI_CLOCKF, 0xc000);  // SC_MULT=6 (4.0x)
    wait(0.01);

    cs = 1;
    dcs = 1;
}

void VS1053::VolControl(uint16_t vol)
{
    writeReg(SCI_VOL,vol);
}


/** SDI Send a data byte to VS1053. */
void VS1053::sendDataByte(uint8_t data) {
    sdi_en();

    while (!dreq);
    spi.write(data);

    sdi_dis();
}

bool VS1053::checkDREQ()
{
    bool dreq_return = 0;
    dreq_return = dreq;
    return dreq_return;
}

/** SDI Send a data block specified as a pointer to VS1053.
 *  @return Data length successfully sent.
 */
size_t VS1053::sendDataBlock(uint8_t* data, size_t length) {
    size_t n, sizeSent = 0;
    
    if (!data || !length) return 0;
    sdi_en();
    while (length) {
        n = length < 32 ? length : 32;
        for (uint32_t i = 0; i < n; i++)
        {
            while (!dreq);
            spi.write(*data++);
            sizeSent++; length--;
        }
    }
    sdi_dis();
    return sizeSent;
}

/** Send cancel request to VS1053.
 *  @return Zero at failure, non-zero at success.
 */
bool VS1053::sendCancel() {
    uint16_t reg;
    
    // Set SM_CANCEL bit
    reg = readReg(SCI_MODE);
    if (reg & 0x0008) {
        // Abort if SM_CANCEL is still set
        return false;
    }
    writeReg(SCI_MODE, reg | 0x0008);
    return true;
}

/** Attempt a termination of playing.
 *  Please call this repeatedly during data stream tramsission until it successes.
 *  @return Zero at failure, non-zero at success.
 */
bool VS1053::stop() {
    size_t   n, length;
       
    // Send 0 2056 times
    length = 257;
    sdi_en();
    while (length) {
        n = length < 32 ? length : 32;
        for (uint32_t i = 0; i < n; i++) {
            while (!dreq);
            spi.write(0x00);
            length--;
        }
    }
    sdi_dis();
    // Check if both HDAT0 and HDAT1 are cleared
    return readReg(SCI_HDAT0) == 0x0000 && readReg(SCI_HDAT1) == 0x0000;
}

/** Write to an SCI (Serial Control Interface) register entry. */
void VS1053::writeReg(uint8_t addr, uint16_t word) {
    // If addr is out-of-range, do nothing
    if (addr > 0x0f) {
        return;
    }
    sci_en();
    while (!dreq);
    spi.write(0x02);         // Send a "Write SCI" instruction (02h),
    spi.write(addr);         // target address,
    spi.write(word >> 8);    // high byte,
    spi.write(word & 0xff);  // then low byte
    sci_dis();
}

/** Read an SCI (Serial Control Interface) register entry.
 *  @return Register value or 0000h when invalid address was specified.
 */
uint16_t VS1053::readReg(uint8_t addr) {
    uint16_t word;
    
    // If addr is out-of-range, return 0000h
    if (addr > 0x0f) {
        return 0x0000;
    }
    sci_en();
    while (!dreq);
    spi.write(0x03);              // Send a "Read SCI" instruction (03h)
    spi.write(addr);              // and target address
    word = spi.write(0xff) << 8;  // Receive high byte with dummy data FFh
    word |= spi.write(0xff);      // Receive low byte
    sci_dis();
    return word;
}

void VS1053::sine_test_activate(unsigned char wave)
{
    hardwareReset();
    spi.format(8, 0);
    spi.frequency(1000000);
    writeReg(SCI_MODE,(SM_SDINEW+SM_TESTS));
    sdi_en();

    while(dreq == 0)
    {
    }                          //wait unitl data request is high
    spi.write(0x53);                        //SDI write
    spi.write(0xEF);                        //SDI write
    spi.write(0x6E);                        //SDI write
    spi.write(wave);                        //SDI write
    spi.write(0x00);                        //filler byte
    spi.write(0x00);                        //filler byte
    spi.write(0x00);                        //filler byte
    spi.write(0x00);                        //filler byte
 
    sdi_dis();
}
void VS1053::sine_test_deactivate(void)
{
    sdi_en();

    while(dreq == 0)
    {
    }
    spi.write(0x45);                        //SDI write
    spi.write(0x78);                        //SDI write
    spi.write(0x69);                        //SDI write
    spi.write(0x74);                        //SDI write
    spi.write(0x00);                        //filler byte
    spi.write(0x00);                        //filler byte
    spi.write(0x00);                        //filler byte
    spi.write(0x00);                        //filler byte
    
    sdi_dis();
}