ELEC2645 (2018/19) / Mbed 2 deprecated el17st

Dependencies:   mbed FATFileSystem

WDplayer/WDplayer.cpp

Committer:
rottenegg
Date:
2019-05-10
Revision:
26:716bcd47f3ca
Parent:
21:f3b0ce18b44f

File content as of revision 26:716bcd47f3ca:

#include "WDplayer.h"
Ticker ISR;

//Constructor
WDplayer::WDplayer(PinName buzzer) 
    : _dac(new PwmOut(buzzer)) {
    buffer = (unsigned char *)malloc(1);
}

//Deconstructor
WDplayer::~WDplayer() {
    free(buffer);
    free(cache);
    delete _dac;
}

void WDplayer::intWD(const char *path, bool allocate) {
    _fptr = fopen(path,"r");
    //Get Riff Information
    unsigned int samplerate;
    fseek(_fptr,24,SEEK_SET);
    fread(&samplerate,4,1,_fptr);
    fseek(_fptr,0,SEEK_END);
    unsigned int len = ftell(_fptr);
    //Set Private Variables
    _pwmfreq = (1.0f / samplerate);
    _path = path;
    _length = len - 44;
    _tck = 0;
    lock = false;
    vtck = 4000;
    _dac->period( _pwmfreq / 4.0f);
    if (allocate) {
        cache = (unsigned char*)std::calloc(4000,sizeof(unsigned char));
    }
    fclose(_fptr);
    _fptr = NULL;
};

//Inline Functions (Operates using main MCU)

void WDplayer::WDplay() {
    _fptr = fopen(_path,"r");
    fseek(_fptr,44,SEEK_SET);
    //Sampling Loop- Sample Byte by Byte
    //CORE ENGINE
    for (_tck = _length; _tck > 1; _tck--) {
        fread(buffer,1,1,_fptr);
        _dac->write((float)buffer[0] / 255.00f);
        wait(_pwmfreq / 2.0f);        
    }
    fclose(_fptr);
    _fptr = NULL;
    _tck = 0;
};

void WDplayer::WDtck() {
    //To Loop the Music File When it Ends
    if (_fptr == NULL) {
    _fptr = fopen(_path,"r");
    fseek(_fptr,44,SEEK_SET);
    }
    //end of file reset
    if (_tck == _length) {
        fclose(_fptr);
        _fptr = NULL;
        _tck = 0;
    } else {
        //Plays One Sample
        fread(buffer,1,1,_fptr);
        _dac->write( (int)buffer[0] / 255.00 );
        _tck++;
    }
};

//Outline Functions (Uses ISR to operate)

void WDplayer::ISRpreload() {
    //File Reset
    if (_fptr == NULL) {
        _fptr = fopen(_path,"r");
        fseek(_fptr,44,SEEK_SET);
        //Reset State and Locational Variables
        lock = false;
        vtck = 4000;
        _tck = 0;
    }
    //CORE ENGINE - Opertes on a two data Block system one to read from and one to write to.
    if (_tck + 2000 >= _length) {
        fclose(_fptr);
        _fptr = NULL;
        _tck = 0;
        vtck = 0;
    } else if (vtck > 2001 && !lock) { //updates dependent on where Vtck is in reading 0 to 1999 is block 1 and 2001 to 4000 block 2
        this->UpdateBlock1();
    } else if (vtck < 1999 && lock) {
        this->UpdateBlock2();
    } 
}

void WDplayer::UpdateBlock2() {
    //Block 2 Update
    for (int i = 2001; i <= 4000; i++) {
        fread(buffer,1,1,_fptr);
        cache[i] = ((int)buffer[0]);
    }
    lock = false;
    _tck = _tck + 2000;
}

void WDplayer::UpdateBlock1() {
    //Block 1 Update
    for (int i = 0; i <= 2000; i++) {
        fread(buffer,1,1,_fptr);
        cache[i] = ((unsigned char)buffer[0]);
    }
    lock = true;
    _tck = _tck + 2000;
}

void WDplayer::ISRset() {
    this->ISRpreload();
    ISR.attach(callback(this,&WDplayer::ISRtck),_pwmfreq);
}

void WDplayer::ISRpause() {
    ISR.detach();
}

void WDplayer::ISRresume() {
    ISR.attach(callback(this,&WDplayer::ISRtck),_pwmfreq);
}

void WDplayer::ISRreset() {
    ISR.detach();
    fclose(_fptr);
    _fptr = NULL;
    free(cache);
    lock = false;
    vtck = 4000;
    _tck = 0;
}

//ISR attached Function
void WDplayer::ISRtck() {
    _dac->write( cache[vtck] / 255.00 );
    if (vtck == 4000) {
        vtck = -1;
    }
    vtck++;
};


float WDplayer::get_pwmfreq() {
    return _pwmfreq;
};