//#DOC Main, program entry and main loop
#include "main.h"
#include <otMath.h>
#include <otSerial.h>
#include <otPrintf.h>
#include <otTimer.h>
#include <otMalloc.h>
#include <otADS868x.h>
#include <otStatistics.h>
#include <otDisplay.h>
#include <otILI9341.h>
#include <otSpi.h>
#include <otPlot.h>

// Uncomment this define to test fast sampling
//#define FAST_ACQ
#define DTYPE otDisplay::D_7SEGMENT
//#define DTYPE otDisplay::D_NIXIE

#ifdef FAST_ACQ
    // Embedded memory is very fast but with very small size!
    #define SAMPLES     1024
    S16     buff[SAMPLES];
#else
    // Heap is very large but not fast!
    #define SAMPLES     20000
    S16     * buff;
#endif

otADS868x       adc;
otStatistics    stat;
otDisplay       dsp;
otILI9341       tft;
otPlot          plot;

char            * prtBuff;

void setup()
{
    UartEnableSignals(UART0);
    UartSetBaud(UART0, 115200);
    setStdout(1024, UART0); // printf output is now directed on UART0
    TimerSetAsCounter(TIMER0);
    TimerEnable(TIMER0, true);
    
    tft.init();
    tft.setRotation(otILI9341::IR_270);
    tft.clear();
    tft.setTextColor(RGB565_YELLOW, RGB565_BLACK);
    
    tft.setTextSize(3);
    tft.setCursor(15, 60);
    tft.writeString("V");
    tft.setTextSize(1);
   
    adc.init();
    // Set ADC range
    adc.setRange(otADS868x::BIP_12V);
    
#ifndef FAST_ACQ
    buff = (S16 *) _malloc(sizeof(S16) * SAMPLES);
#endif
    
    prtBuff = (char *) _malloc(512);
    
    // Specify data buffer, lenght and its type
    stat.setData(otStatistics::T_S16, (void *) buff, SAMPLES);
    
    dsp.init(DTYPE, 3, "%7.3f", &tft);
    //dsp.init(DTYPE, 3, "%5d", &tft);
    
    SpiSet(SA_LCD);
    plot.init(0, 120, 320, 120, &tft);
    plot.setRange(-10, 10);
}

void loop()
{
    U32     st, et;
    U32     i = 0;
    S16     p = (320 - dsp.horSize()) / 2;
    F32     v, vp;
    while(1)
    {
        st = TimerGetCounts(TIMER0);    // Grab start time
        adc.read(buff, SAMPLES);
        et = TimerGetCounts(TIMER0);    // Grab end time
        et = ElapsedTimeUs(st, et);
        stat.evaluate();
        // Case of 0!
        if(stat.min == -32768 && stat.max == 32767)
            stat.average = stat.sigma = 32767;
        v = adc.toVolt((S16) stat.average);
        //printf("[%4d] STATISTICS   : min = %8.3lfV, max = %8.3lfV, average = %8.3lfV, sigma = %8.3lfV\n",
        //        i++, adc.toVolt((S16) stat.min), adc.toVolt((S16) stat.max), v, stat.sigma * adc.lsb());
        plot.addData(v);
        
        SpiSet(SA_LCD);
        
        sprintf(prtBuff, "MIN:%8.3lf V | MAX:%8.3lf V | STD:%8.3lf V", adc.toVolt((S16) stat.min), adc.toVolt((S16) stat.max), stat.sigma * adc.lsb());
        tft.setCursor(15, 0);
        tft.writeString(prtBuff);
        
        vp = adc.toVolt((S16) stat.max) - adc.toVolt((S16) stat.min);
        sprintf(prtBuff, "VPP:%8.3lf V | RMS:%8.3lf V | ETI:%8d uS", vp, (double) vp * 0.7071, et);
        tft.setCursor(15, 10);
        tft.writeString(prtBuff);
        
        dsp.display(v, p, 40);
        plot.plot();
        SpiSet(SA_ADC);
    }
}