ADC performance check

Dependencies:  

Fork of GR-PEACH_test_wo_rtos by Kenji Arai

main.cpp

Committer:
kenjiArai
Date:
2015-01-11
Revision:
7:c87a84872d85
Parent:
6:849caec97744

File content as of revision 7:c87a84872d85:

/*
 * mbed Application program for the mbed
 *      Test program for GR-PEACH
 *
 * Copyright (c) 2014 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created: November  29th, 2014
 *      Revised: January   11th, 2015
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//  Include ---------------------------------------------------------------------------------------
#include    "mbed.h"

//  Definition ------------------------------------------------------------------------------------
#define USE_COM         // use Communication with PC(UART)

// Com
#ifdef  USE_COM
#define BAUD(x)             pcx.baud(x)
#define GETC(x)             pcx.getc(x)
#define PUTC(x)             pcx.putc(x)
#define PRINTF(...)         pcx.printf(__VA_ARGS__)
#define READABLE(x)         pcx.readable(x)
#else
#define BAUD(x)             {;}
#define GETC(x)             {;}
#define PUTC(x)             {;}
#define PRINTF(...)         {;}
#define READABLE(x)         {;}
#endif

// Use TL431ACZ-AP
//      Akizuki NJM431 (equivalent)
//          http://akizukidenshi.com/catalog/g/gI-00431/
#define VREF                (2.478f)    // measured data (not Typ. data)

#if defined(TARGET_RZ_A1H)
//#define ADC_BUF_SIZE        (4096 * 40)
#define ADC_BUF_SIZE        (1024)
#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
#define ADC_BUF_SIZE        (1024)
#elif defined(TARGET_K64F)
#define ADC_BUF_SIZE        (1024)
#endif


//  Object ----------------------------------------------------------------------------------------
// com
#ifdef USE_COM
Serial      pcx(USBTX, USBRX);      // Communication with Host
#endif
// Analog
AnalogIn    adc0(A0);   // Connect TL431ACZ-AP
AnalogIn    adc1(A1);
AnalogIn    adc2(A2);
AnalogIn    adc3(A3);
AnalogIn    adc4(A4);
AnalogIn    adc5(A5);
// timer
Timer       timer;

//  RAM -------------------------------------------------------------------------------------------
static char linebuf[64];

typedef struct {
    float     adc0;
    float     adc1;
    float     adc2;
    float     adc3;
    float     adc4;
    float     adc5;
    int       a0_time;
    int       a1_time;
    int       a2_time;
    int       a3_time;
    int       a4_time;
    int       a5_time;
    uint32_t  n;
} ADC_DataTypeDef;

ADC_DataTypeDef data_buffer[ADC_BUF_SIZE];

// avarage & max.min
uint32_t d_max_min[2];

double ave_adc0;
double ave_adc1;
double ave_adc2;
double ave_adc3;
double ave_adc4;
double ave_adc5;
float d_max_min0[2];
float d_max_min1[2];
float d_max_min2[2];
float d_max_min3[2];
float d_max_min4[2];
float d_max_min5[2];

//  ROM / Constant data ---------------------------------------------------------------------------
#if defined(TARGET_RZ_A1H)
static char *const mon_msg = "ADC checking program for GR-PEACH mbed, created on "__DATE__"";
#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
static char *const mon_msg = "ADC checking program for Nucleo mbed, created on "__DATE__"";
#elif defined(TARGET_K64F)
static char *const mon_msg = "ADC checking program for K64F mbed, created on "__DATE__"";
#endif

//  Function prototypes ---------------------------------------------------------------------------

//  Function prototypes ---------------------------------------------------------------------------
void msg_hlp (void);
void reset_max_min(uint32_t *bf);
void check_max_min(uint32_t dt, uint32_t *bf);
void reset_f_max_min(void);
void check_f_max_min(float dt, float *bf);
void get_line (char *buff, int len);
void blink(void const *n);
void put_rn ( void );
void put_r ( void );
int xatoi (char **str, int32_t *res);

//-------------------------------------------------------------------------------------------------
//  Control Program
//-------------------------------------------------------------------------------------------------
int main(void)
{
    char *ptr;
    float dt;
    uint32_t i;
    uint32_t t;

    BAUD(9600);
    put_rn();
    put_rn();
    PRINTF("%s [Help:'?' key]", mon_msg);
    put_rn();
    for (;;) {
        put_r();
        PUTC('>');
        ptr = linebuf;
        get_line(ptr, sizeof(linebuf));
        switch (*ptr++) {
                //---------------------------------------------------------------------------------------------
                //  Save ADC data into RAM
                //---------------------------------------------------------------------------------------------
            case 's' :
                for (i = 0; i < ADC_BUF_SIZE; i++) {
                    timer.reset();
                    timer.start();
                    dt = adc0.read();
                    t = timer.read_us();
                    data_buffer[i].adc0 = dt;
                    data_buffer[i].a0_time = t;

                    timer.reset();
                    timer.start();
                    dt = adc1.read();
                    t = timer.read_us();
                    data_buffer[i].adc1 = dt;
                    data_buffer[i].a1_time = t;

                    timer.reset();
                    timer.start();
                    dt = adc2.read();
                    t = timer.read_us();
                    data_buffer[i].adc2 = dt;
                    data_buffer[i].a2_time = t;

                    timer.reset();
                    timer.start();
                    dt = adc3.read();
                    t = timer.read_us();
                    data_buffer[i].adc3 =  dt;
                    data_buffer[i].a3_time = t;

                    timer.reset();
                    timer.start();
                    dt =adc4.read();
                    t = timer.read_us();
                    data_buffer[i].adc4 =  dt;
                    data_buffer[i].a4_time = t;

                    timer.reset();
                    dt = adc5.read();
                    t = timer.read_us();
                    data_buffer[i].adc5 =  dt;
                    data_buffer[i].a5_time = t;

                    data_buffer[i].n = i + 1;
                    if (i%100 == 0) {
                        put_rn();
                        PRINTF("%d", i);
                        put_rn();
                    } else {
                        PUTC('.');
                    }
                    if ( READABLE() ) {
                        put_rn();
                        GETC();
                        break;
                    }
                }
                data_buffer[i + 1].n = 0;
                put_rn();
                PRINTF("Finished at %d", i);
                put_rn();
                break;
                //---------------------------------------------------------------------------------------------
                //  Display saved ADC data
                //---------------------------------------------------------------------------------------------
            case 'd' :
                put_rn();
                PRINTF("Show all saved data");
                put_rn();
                for (i = 0; (i < ADC_BUF_SIZE) && (data_buffer[i].n != 0) ; i++) {
                    PRINTF("No.%5d, ", i);
                    PRINTF("A0= %4.4f , A1= %4.4f , ", data_buffer[i].adc0, data_buffer[i].adc1);
                    PRINTF("A2= %4.4f , A3= %4.4f , ", data_buffer[i].adc2, data_buffer[i].adc3);
                    PRINTF("A4= %4.4f , A5= %4.4f , ", data_buffer[i].adc4, data_buffer[i].adc5);
                    PRINTF("Time/0= %d /1= %d /2= %d /3= %d /4= %d /5= %d [uS]",
                           data_buffer[i].a0_time, data_buffer[i].a1_time, data_buffer[i].a2_time,
                           data_buffer[i].a3_time, data_buffer[i].a4_time, data_buffer[i].a5_time);
                    put_rn();
                    if ( READABLE() ) {
                        GETC();
                        break;
                    }
                }
                break;
                //---------------------------------------------------------------------------------------------
                //  Check convertion time
                //---------------------------------------------------------------------------------------------
            case 't' :
                uint32_t time_all = 0;

                put_r();
                reset_max_min(d_max_min);
                for (i = 0; (i < ADC_BUF_SIZE) && (data_buffer[i].n != 0) ; i++) {
                    time_all += (data_buffer[i].a0_time + data_buffer[i].a1_time +data_buffer[i].a2_time
                                 + data_buffer[i].a3_time + data_buffer[i].a4_time + data_buffer[i].a5_time);
                    check_max_min(data_buffer[i].a0_time, d_max_min);
                    check_max_min(data_buffer[i].a1_time, d_max_min);
                    check_max_min(data_buffer[i].a2_time, d_max_min);
                    check_max_min(data_buffer[i].a3_time, d_max_min);
                    check_max_min(data_buffer[i].a4_time, d_max_min);
                    check_max_min(data_buffer[i].a5_time, d_max_min);
                }
                PRINTF("Conversion time/ave =  %f [uS], Number of sample %d, Max %d [uS], Min %d [uS]",
                       (double)time_all / (i * 6), i, d_max_min[1], d_max_min[0]);
                put_rn();
                break;
                //---------------------------------------------------------------------------------------------
                //  Analysis saved data
                //---------------------------------------------------------------------------------------------
            case 'a' :
                put_r();
                reset_f_max_min();
                for (i = 0; (i < ADC_BUF_SIZE) && (data_buffer[i].n != 0) ; i++) {
                    ave_adc0 += data_buffer[i].adc0;
                    ave_adc1 += data_buffer[i].adc1;
                    ave_adc2 += data_buffer[i].adc2;
                    ave_adc3 += data_buffer[i].adc3;
                    ave_adc4 += data_buffer[i].adc4;
                    ave_adc5 += data_buffer[i].adc5;
                    check_f_max_min(data_buffer[i].adc0, d_max_min0);
                    check_f_max_min(data_buffer[i].adc1, d_max_min1);
                    check_f_max_min(data_buffer[i].adc2, d_max_min2);
                    check_f_max_min(data_buffer[i].adc3, d_max_min3);
                    check_f_max_min(data_buffer[i].adc4, d_max_min4);
                    check_f_max_min(data_buffer[i].adc5, d_max_min5);
                }
                PRINTF("Number of sample %d", i);
                put_rn();                
                PRINTF("ADC0/ave =  %f , Max %f , Min %f , Dif %f",
                 ave_adc0 / i, d_max_min0[1], d_max_min0[0], d_max_min0[1] - d_max_min0[0]);
                put_rn(); 
                PRINTF("ADC1/ave =  %f , Max %f , Min %f , Dif %f",
                 ave_adc1 / i, d_max_min1[1], d_max_min1[0], d_max_min1[1] - d_max_min1[0]);
                put_rn(); 
                PRINTF("ADC2/ave =  %f , Max %f , Min %f , Dif %f",
                 ave_adc2 / i, d_max_min2[1], d_max_min2[0], d_max_min2[1] - d_max_min2[0]);
                put_rn(); 
                PRINTF("ADC3/ave =  %f , Max %f , Min %f , Dif %f",
                 ave_adc3 / i, d_max_min3[1], d_max_min3[0], d_max_min3[1] - d_max_min3[0]);
                put_rn(); 
                PRINTF("ADC4/ave =  %f , Max %f , Min %f , Dif %f",
                 ave_adc4 / i, d_max_min4[1], d_max_min4[0], d_max_min4[1] - d_max_min4[0]);
                put_rn(); 
                PRINTF("ADC5/ave =  %f , Max %f , Min %f , Dif %f",
                 ave_adc5 / i, d_max_min5[1], d_max_min5[0], d_max_min5[1] - d_max_min5[0]);
                put_rn();
                break;
                //---------------------------------------------------------------------------------------------
                //  Buffer information
                //---------------------------------------------------------------------------------------------
            case 'b' :
                put_r();
                PRINTF("Buffer information", i);
                put_rn();                
                PRINTF("Start address: 0x%08x", &data_buffer[0]);
                put_rn(); 
                PRINTF("End address:   0x%08x", &data_buffer[ADC_BUF_SIZE - 1]);
                put_rn();
                PRINTF("Size of Buf:   %d (0x%x)", sizeof(data_buffer), sizeof(data_buffer));
                put_rn();
                break;
                //---------------------------------------------------------------------------------------------
                //  Check Vcc
                //---------------------------------------------------------------------------------------------
            case 'v' :
                put_r();
                PRINTF("This is special function only if A0 conneceted 2.5V Shunt reg. e.g. TL431, NJM431.");
                put_rn();                
                PRINTF("Please make sure #define VREF as your condition.");
                put_rn(); 
                while(true){
                    PRINTF("Vcc= %4.4f [v]", VREF / adc0.read());
                    put_rn();
                    if ( READABLE() ) {
                        GETC();
                        break;
                    }
                    wait(0.5);
                }
                break;
                //---------------------------------------------------------------------------------------------
                //  help
                //---------------------------------------------------------------------------------------------
            case '?' :
                put_r();
                msg_hlp();
                break;
        }
    }
}

//  Help Massage
void msg_hlp (void)
{
    PRINTF(mon_msg);
    put_rn();
    PRINTF("s - Save ADC data into RAM");
    put_rn();
    PRINTF("d - Display saved ADC data");
    put_rn();
    PRINTF("t - Check convertion time");
    put_rn();
    PRINTF("a - Analysis saved data");
    put_rn();
    PRINTF("b - Buffer information");
    put_rn();
    PRINTF("v - Check Vcc");
    put_rn();
}

void reset_max_min(uint32_t *bf)
{
    *(bf + 1) = 0;
    *bf = 0xffffffff;
}

void check_max_min(uint32_t dt, uint32_t *bf)
{
    if (dt > *(bf + 1)){
        *(bf + 1) = dt;
    } else if (dt < *bf){
        *bf = dt;
    }
}

void reset_f_max_min(void)
{
    d_max_min0[0] = 1.0f;
    d_max_min0[1] = 0.0f;
    d_max_min1[0] = 1.0f;
    d_max_min1[1] = 0.0f;
    d_max_min2[0] = 1.0f;
    d_max_min2[1] = 0.0f;
    d_max_min3[0] = 1.0f;
    d_max_min3[1] = 0.0f;
    d_max_min4[0] = 1.0f;
    d_max_min4[1] = 0.0f;
    d_max_min5[0] = 1.0f;
    d_max_min5[1] = 0.0f;
}

void check_f_max_min(float dt, float *bf)
{
    if (dt > *(bf + 1)){
        *(bf + 1) = dt;
    } else if (dt < *bf){
        *bf = dt;
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  Get key input data
void get_line (char *buff, int len)
{
    char c;
    int idx = 0;

    for (;;) {
        c = GETC();
        //    Added by Kenji Arai / JH1PJL   May 9th, 2010
        if (c == '\r') {
            buff[idx++] = c;
            break;
        }
        if ((c == '\b') && idx) {
            idx--;
            PUTC(c);
            PUTC(' ');
            PUTC(c);
        }
        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
            buff[idx++] = c;
            PUTC(c);
        }
    }
    buff[idx] = 0;
    PUTC('\n');
}

//  Put \r\n
void put_rn ( void )
{
    PUTC('\r');
    PUTC('\n');
}

//  Put \r
void put_r ( void )
{
    PUTC('\r');
}

int xatoi (char **str, int32_t *res)
{
    unsigned long val;
    unsigned char c, radix, s = 0;

    while ((c = **str) == ' ') (*str)++;
    if (c == '-') {
        s = 1;
        c = *(++(*str));
    }
    if (c == '0') {
        c = *(++(*str));
        if (c <= ' ') {
            *res = 0;
            return 1;
        }
        if (c == 'x') {
            radix = 16;
            c = *(++(*str));
        } else {
            if (c == 'b') {
                radix = 2;
                c = *(++(*str));
            } else {
                if ((c >= '0')&&(c <= '9')) {
                    radix = 8;
                }   else {
                    return 0;
                }
            }
        }
    } else {
        if ((c < '1')||(c > '9')) {
            return 0;
        }
        radix = 10;
    }
    val = 0;
    while (c > ' ') {
        if (c >= 'a') c -= 0x20;
        c -= '0';
        if (c >= 17) {
            c -= 7;
            if (c <= 9) return 0;
        }
        if (c >= radix) return 0;
        val = val * radix + c;
        c = *(++(*str));
    }
    if (s) val = -val;
    *res = val;
    return 1;
}