/**
  * \file waveformMaker.cpp
  * \author Blanc.O & Chardes.C
  * \version 0.1
  * \date 11 janvier 2010
  */

#include "waveformMaker.h"

/**
 * @brief waveformMaker::waveformMaker
 * @param thisConsole
 * @param sRate
 * @param bSize
 * @param parent
 */
waveformMaker::waveformMaker (qConsole *thisConsole,  int sRate, int bSize, QWidget *parent)
    :QWidget(parent), bufferSize(bSize), samplingRate(sRate), periodByBuffer (1),phaseLag(0.0),
    amplitude(5.0), offset(0.0), console(thisConsole)
{

    maxFrequency = (bufferSize/2)*samplingRate; //nyquist Theorem;
    frequency = samplingRate/bufferSize;

    //defining the different type of waveform to generate
    QStringList waveformList;
    waveformList<<"Sinusoidal"<<"SawTooth"<<"Step Func tion"<<"Continuous Voltage";

    //wfTypeL implementation
    wfTypeL = new QLabel("Choose the waveform you want");

    //wfTypeCB implementation
    wfTypeCB = new QComboBox ();
    wfTypeCB->setWhatsThis("waveFormType");
    wfTypeCB->addItems(waveformList);

    //frequencyL implementation
    frequencyL = new QLabel((QString("WaveForm's' frequency : ")+=QString::number(frequency)).append("  Hz"));

    //frequencySB implementation
    periodByBufferSB = new QSpinBox();
    periodByBufferSB->setRange(1, maxFrequency);
    periodByBufferSB->setSingleStep(1);
    periodByBufferSB->setPrefix("nbPeriod       ");
    periodByBufferSB->setValue(1);
    periodByBufferSB->setWhatsThis("periodByBuffer");

    //amplitudeL implementation
    amplitudeL = new QLabel ("set the amplitude of the waveform in volt");

    //amplitudeSB implementation
    amplitudeSB = new QDoubleSpinBox();
    amplitudeSB->setLocale(QLocale::English);
    amplitudeSB->setRange (minVoltage, maxVoltage);
    amplitudeSB->setDecimals (4);
    amplitudeSB->setSingleStep (0.5);
    amplitudeSB->setPrefix ("amplitude       ");
    amplitudeSB->setSuffix ("  (Volt)");
    amplitudeSB->setValue(5.0);
    amplitudeSB->setWhatsThis("amplitude");

    //offsetL implementation
    offsetL = new QLabel("set the offset of the waveform in volt");

    //offsetSB implementation
    offsetSB = new QDoubleSpinBox();
    offsetSB->setLocale(QLocale::English);
    offsetSB->setRange(minVoltage, maxVoltage);
    offsetSB->setDecimals(4);
    offsetSB->setSingleStep(0.05);
    offsetSB->setPrefix("Offset         ");
    offsetSB->setSuffix("  (Volt)");
    offsetSB->setValue(0.0);
    offsetSB->setWhatsThis("offset");

    //phaseLagL implementation
    phaseLagL = new QLabel ("set the phase lag in rad");

    //phaseLagSB implementation
    phaseLagSB = new QDoubleSpinBox();
    phaseLagSB->setLocale(QLocale::English);
    phaseLagSB->setRange(-1*pi, pi);
    phaseLagSB->setDecimals(3);
    phaseLagSB->setSingleStep(pi/100);
    phaseLagSB->setPrefix("phase        ");
    phaseLagSB->setSuffix("  (rad)");
    phaseLagSB->setWhatsThis("phase");

    QGridLayout *layout = new QGridLayout();
    layout->addWidget(wfTypeL, 0 , 0 , 1, 1);
    layout->addWidget(wfTypeCB, 1 , 0, 1, 1);
    layout->addWidget(frequencyL, 2 , 0 , 1, 1);
    layout->addWidget(periodByBufferSB, 3 , 0 , 1, 1);
    layout->addWidget(amplitudeL, 4 , 0 , 1, 1);
    layout->addWidget(amplitudeSB, 5 , 0 , 1, 1);
    layout->addWidget(phaseLagL, 6 , 0 , 1, 1);
    layout->addWidget(phaseLagSB, 7 , 0 , 1, 1);
    layout->addWidget(offsetL, 8, 0 , 1, 1);
    layout->addWidget(offsetSB, 9, 0 , 1, 1);

    setLayout(layout);

    connect(periodByBufferSB, SIGNAL(valueChanged(int)), this, SLOT(changeFrequency()));
    connect(amplitudeSB, SIGNAL(valueChanged(double)), this, SLOT(changeAmplitude(double)));
    connect(offsetSB, SIGNAL(valueChanged(double)), this, SLOT(changeOffset(double)));
    connect(phaseLagSB, SIGNAL(valueChanged(double)), this, SLOT(changePhaseLag(double)));
}


/**
 * @brief waveformMaker::~waveformMaker
 */
waveformMaker::~waveformMaker()
{
}

/**
 * @brief waveformMaker::makeBuffer
 * @param buff
 * @return
 */
float64 *waveformMaker::makeBuffer(float64 *buff)
{
    int periodSize = 0;
    int slope = 1;
    int j  =0, n, lag, n0 = 0;

    periodSize = round(bufferSize/periodByBuffer);
    lag = (periodSize/2)*phaseLag/(pi/180);

    buffer = new float64 [bufferSize];

    switch (wfTypeCB->currentIndex())
    {
    case 0 : //sinusoidal waveform
        for (int i = 0 ; i<bufferSize ; i++)
        {
            buffer [i] = amplitude/2*sin(i*2.0*pi*periodByBuffer/bufferSize+phaseLag)+offset;
            if (buffer[i]> maxVoltage) buffer[i] = maxVoltage;
            if (buffer[i]< minVoltage) buffer[i] = minVoltage;
        }
        break;

    case 1 : //sawtooth waveform (triangle)
        for (int i = 0 ; i<bufferSize; i ++)
        {
            n = (i+lag)%(periodSize/2);
            ++j;
            if (n == 0)
            {
                slope =-1*slope;
                //n0 = n;
                j = 0;
            }           
                buffer [i] = slope*j*amplitude/(periodSize/2)-slope*amplitude/2+offset;
                if (buffer[i]> maxVoltage) buffer[i] = maxVoltage;
                if (buffer[i]< minVoltage) buffer[i] = minVoltage;
                qDebug()<<buffer[i];
        }
        break;

    case 2 : //Step oscillation (creneau)
        {
            for (int i = 0 ; i<bufferSize; i ++)
            {
                n = round((i+lag)/(periodSize/2));
                if (n > n0)
                {
                    slope =-1*slope;
                    n0 = n;
                }
                buffer [i] = slope*amplitude-slope*amplitude/2+offset;
                if (buffer[i]> maxVoltage) buffer[i] = maxVoltage;
                if (buffer[i]< minVoltage) buffer[i] = minVoltage;
                qDebug()<<buffer[i];
            }
        }
        break;

    case 3 : //continuous voltage
        for (int i = 0; i<bufferSize; i++)
        {
            buffer [i] = offset;            
            //useless in principle
            if (buffer[i]> maxVoltage) buffer[i] = maxVoltage;
            if (buffer[i]< minVoltage) buffer[i] = minVoltage;
        }
        //*console<<offset;
        break;
    }
//    buff = buffer;
    return buffer;
}

/**
 * @brief waveformMaker::changeFrequency
 */
void waveformMaker::changeFrequency()
{
    periodByBuffer = periodByBufferSB->value();
    frequency = double(periodByBuffer)*double(samplingRate)/double(bufferSize);
    QString text = "WaveForm's' frequency :  ";
    text += QString::number(double(frequency));
    text.append("   (Hz)");
    frequencyL->setText(text);
}

/**
 * @brief waveformMaker::changeAmplitude
 * @param amp
 */
void waveformMaker::changeAmplitude(double amp)
{
    amplitude = amp;

}

/**
 * @brief waveformMaker::changeOffset
 * @param off
 */
void waveformMaker::changeOffset(double off)
{
    offset = off;
}

/**
 * @brief waveformMaker::changePhaseLag
 * @param lag
 */
void waveformMaker::changePhaseLag(double lag)
{
    phaseLag = lag;
}

/**
 * @brief waveformMaker::setSamplingRate
 * @param sRate
 */
void waveformMaker::setSamplingRate(int sRate)
{
    samplingRate = sRate;
    maxFrequency = (bufferSize/2)*samplingRate; //nyquist Theorem;
    frequency = samplingRate/bufferSize;
    this->changeFrequency();
}

/**
 * @brief waveformMaker::setBufferSize
 * @param bSize
 */
void waveformMaker::setBufferSize(int bSize)
{
    bufferSize = bSize;
    maxFrequency = (bufferSize/2)*samplingRate; //nyquist Theorem;
    frequency = samplingRate/bufferSize;
    this->changeFrequency();
}

/**
 * @brief waveformMaker::getWFParameters
 * @param map
 */
void waveformMaker::getWFParameters(QMap<QString, QString> &map)
{
    map.insert("waveformType", wfTypeCB->currentText());
    map.insert("frequency", QString::number(frequency));
    map.insert("nbPeriod", QString::number(periodByBuffer));
    map.insert("amplitude", QString::number(amplitude));
    map.insert("phase", QString::number(phaseLag));
    map.insert("offset", QString::number(offset));
}
