Simple Latency Measurement Application for Head Mounted Display. This project handles LED and light sensor to measure the latency from blinking to showing on the display.

Dependencies:   mbed-dsp mbed

main.cpp

Committer:
mfurukawa
Date:
2014-09-23
Revision:
2:4ec0fc856963
Parent:
0:f6d58666cdc3

File content as of revision 2:4ec0fc856963:

// 
// Latency Checker rev 0.1
//
// Author  : Masahiro Furukawa
// Mail    : m.furukawa@ist.osaka-u.ac.jp
// Created : Sept 22, 2014
// Updated : Sept 23, 2014
//
// Purpose     : Latency Measurement between Camera and Display (HMD)
// Requirement : Serial Terminal to show result
// 
// Pin Assign  : P16   ---   LED Anode
//               P18   ---   Cross point btwn AD in (PT600T) and register

#include "mbed.h"
#include "dsp.h"

#define BUF_SIZE 2000
#define H_TO_L      1
#define L_TO_H     -1

InterruptIn button(p5);
AnalogIn adc_in(p18);
DigitalOut led(LED1);
DigitalOut flash(p16);
 
float32_t  threshold = 0.0;
float32_t  ad[BUF_SIZE];
int cycle = 0;

Ticker adc_grabber;

void show_credit()
{
    printf("\n\r Latency Checker rev 0.1\n\r\n\r");
    printf(" Author  : Masahiro Furukawa\n\r");
    printf(" Mail    : m.furukawa@ist.osaka-u.ac.jp\n\r");
    printf(" Created : Sept 22, 2014\n\r");
    printf(" Updated : \n\r\n\r");
}

void show_menu()
{
    printf("[a] start AUTO mode\n\r");
    //printf("[s] start\n\r");
    
    //printf("\n\r");
    //printf("\n\r");
}

void init_cnt()
{
    cycle = 0;
}
void init()
{
    threshold = 0.0;
    init_cnt();
}
void get_ad()
{
    ad[cycle] = 0;
    ad[cycle] = adc_in.read();
    cycle ++;
}
void get_mean_stdev(float32_t *mean, float32_t *stdev)
{
    // clear counter : cycle
    init_cnt();
    
    // blocking sequence to grab adc result per 500 micro-second
    adc_grabber.attach_us(&get_ad, 500); // 500 us
    wait(0.5); // = 500 ms = 500,000 us = 1000 cycle
    adc_grabber.detach();

    arm_mean_f32( ad , cycle , mean );
    arm_std_f32 ( ad , cycle , stdev );
}

void count_up()
{
    cycle ++;
}
void get_edge_us(float32_t *edge_us, int direction)
{
    // clear counter : cycle
    init_cnt();
    
    // toggle LED
    if(direction == H_TO_L){ flash = 1;  wait(1); flash = 0;  }
    else
    if(direction == L_TO_H){ flash = 0;  wait(1); flash = 1;  }
        
    // start grabbing adc result per 500 micro-second
    adc_grabber.attach_us(&count_up, 500); // 500 us
    
    // wait for over threshold
    if(direction == H_TO_L) while( adc_in.read() > threshold ){}
    else 
    if(direction == L_TO_H) while( adc_in.read() < threshold ){}
    
    // stop timer
    adc_grabber.detach();

    *edge_us = cycle * 500.0;
   // printf("cycle (%d)",cycle);
}

struct result{
    float32_t mean;
    float32_t stdev;
} ;

int get_threshold()
{
    struct result dark, bright;
    int ret;
    
    // LED OFF
    flash = 0;    
    wait(1);
    
    // get adc
    get_mean_stdev( &dark.mean, &dark.stdev );
    
    // LED ON
    flash = 1;    
    wait(1);
    
    // get adc
    get_mean_stdev( &bright.mean, &bright.stdev );
    
    // show fractuation notice
    if(dark.stdev * 3.3 > 0.1 || bright.stdev * 3.3 > 0.1 )
    {
        printf("*** CAUTION *** : LCD Backlight Flicker Detected(stdev > 0.1V). brightness shuold be max. \n\r");
        ret = -2;
        threshold = -1;
    }
    else if(dark.stdev * 3.3 > 0.01 || bright.stdev * 3.3 > 0.01 )
    {
        printf("(NOTICE) : LCD Backlight Flicker Detected (stdev > 0.01V). brightness shuold be max.\n\r");
        ret = -1;
        threshold = -1;
    }else
    {
        printf(" great!  ");
        ret = 0;
        
        // 50% threshold
        threshold = (bright.mean - dark.mean) / 2.0 ;
    }
    
    // show result
    printf("Drk avg %1.5lf (SD %1.5lf) / ",   dark.mean * 3.3 ,   dark.stdev * 3.3);
    printf("Brght avg %1.5lf (SD %1.5lf)\r\n", bright.mean * 3.3 , bright.stdev * 3.3);
    
    return ret;
}

#define CHECK_TIMES 5
void get_latency()
{
    float32_t latency_us_up[CHECK_TIMES], latency_us_down[CHECK_TIMES];
    struct result up, down;
    
    if( threshold == -1 ) 
    {
        printf(" Thredhold value error(-1). Latency measurement fault. \n\r ");
    }else
    {
        //printf(" latency check started ! wait a while ");wait(0.5);
    }
    
    // measure latency
    for(int i=0; i<CHECK_TIMES; i++)
    {
        //printf(".");
        get_edge_us(&latency_us_down[i], H_TO_L ); 
        get_edge_us(&latency_us_up[i],   L_TO_H );
    }
    
    arm_mean_f32( latency_us_down , CHECK_TIMES , &down.mean );
    arm_mean_f32( latency_us_up   , CHECK_TIMES ,   &up.mean );
    arm_std_f32 ( latency_us_down , CHECK_TIMES , &down.stdev );
    arm_std_f32 ( latency_us_up   , CHECK_TIMES ,   &up.stdev );
    
    // show result
    printf("\n\r\n\r [RESULT] ");
    printf("H to L avg %3.2lf ms (SD %3.2lf) / ",  down.mean / 1000.0,  down.stdev / 1000.0);
    printf("L to H avg %3.2lf ms (SD %3.2lf)",       up.mean / 1000.0,    up.stdev / 1000.0);
    printf(" / Threshold %1.5lf V\r\n\r\n", threshold * 3.3 );
}
    
 
int main() 
{
    show_credit();
    get_threshold();
    
    while(1) 
    {
        while( get_threshold() != 0 ){}
        
        get_latency();
        
    }
}