You are here: Analog Inputs > Analog Input Sample Timing
STX104 Reference Manual
ContentsIndexHome
PreviousUpNext
Analog Input Sample Timing

The example below illustrates various methods of setting up analog input sample timing. There are two primary parameters needed to setup timing: time between frames, and time between samples (i.e. ADC-burst timing). 

 

One must call the STX104_AI_Time_Settling_Minimum() function to determine the minimum timing possible between samples or the intra-sample timing or minimum ADC-burst timing. 

 

The functions within the example code below will compute and configure the proper analog input timing registers based on firmware revision level. If only 8254 timers are used, then resolution is fixed to 1uSec. In the case of using the Analog Input Frame Timer and the Analog Input Burst Timer, resolution is improved to 25 nanoseconds. 

 

When using the triggering subystem, to synchronize analog input sampling to the trigger-start event, set the SAIFTTS bit in the Analog Input General Configuration Register. 

 

 

Method for configuring the Analog Input Frame Timer and the Analog Input Burst Timer registers. 

 

a) Our assumption is that ADC-burst mode will always be enabled, and is acceptable for all situations. 

 

b) First calculate the time between samples (i.e. intra-sample time) in the the ADC-burst mode. The timing can be as short as 5uSec or longer. The timing is based on multiplexer settling time. 

 

If you have a sensor with a source resistance of 10Kohms and a cable with a total capacitance of 100pF, then the minimum time between samples will be approximately 11 * 10Kohms * 100pF = 11,000 nSec. In other words, the minimum settling time is eleven RC time constants. 

 

ai_time_intra_sample_ns = AIBT_Register_Value * ( 25 nSec ) + ( 5000 nSec ). 

 

AIBT_Register_Value = ( ai_time_intra_sample_ns / ( 25 nSec ) ) - 200 

 

c) The minimum frame time will be: 

 

minimum_ai_time_frame_ns = ( last_channel - first_channel + 1 ) * ai_time_intra_sample_ns. 

 

d) The frame time can now be computed: 

 

ai_time_frame_ns = ( AIFT_Register_Value + 1 ) * ( 25 nSec ) 

 

AIFT_Register_Value = ai_time_frame_ns * ( 25 nSec ) - 1 

 

The above example is a summary of the example source code below.

#define STX104_INTRA_SAMPLE_TIMING           5000  /* nanoseconds */
#define STX104_TIME_RESOLUTION               25    /* nanoseconds */


#define STX104_REVISION_080214   0x1008
#define STX104_REVISION_080407   0x1008
#define STX104_REVISION_090115   0x1009


/*##################################################################################
*                                                      ANALOG INPUT TIMING FUNCTIONS
*/

/*****************************************************************
/                               ANALOG INPUT MINIMUM SETTLING TIME
*/
static unsigned long STX104_AI_Time_Settling_Minimum( float ai_capacitance_pf, float ai_resistance_ohms )
{
    unsigned long settle_time_ns;

    //settle_time = ai_resistance_ohms * ai_capacitance_pf * pow10(-12) * 16 * ln(2) * pow10(9)
    settle_time_ns = (unsigned long) ( ai_resistance_ohms * ai_capacitance_pf * pow10(-3) * 16 * log(2) );

    return( settle_time_ns );
}
/*****************************************************************
/                                         ANALOG INPUT 8254 TIMING
*/
static void STX104_AI_Timing_8254_Set( int board, long time_interval_ns )
{
    long high_count;
    long low_count;
    unsigned int octet;

    STX104_Set_Bank( board, 0 );

    /* assumes 10MHz clock (i.e. no 1MHz jumper) */
    low_count  = 10L; /* 1 microsecond intervals */

    high_count = time_interval_ns / 1000;
    while ( high_count > 65536L )
    {
        high_count = high_count >> 1;
        low_count  = low_count << 1;
    }
    while ( high_count < 2L )
    {
        high_count = high_count << 1;
        low_count  = low_count >> 1;
    }
    /* set counter/timer 2  */
    outportb( stx104_base_address[board] + STX104_CT_CONFIGURATION, 0xB4 );
    octet = ((unsigned int) high_count) & 0x00FF;
    outp( stx104_base_address[board] + STX104_CT2_DATA, octet );
    octet = ((unsigned int) high_count) >> 8;
    outp( stx104_base_address[board] + STX104_CT2_DATA, octet );
    /* set counter/timer 1  */
    outportb( stx104_base_address[board] + STX104_CT_CONFIGURATION, 0x74 );
    octet = ((unsigned int) low_count) & 0x00FF;
    outp( stx104_base_address[board] + STX104_CT1_DATA, octet );
    octet = ((unsigned int) low_count) >> 8;
    outp( stx104_base_address[board] + STX104_CT1_DATA, octet );
}

/*****************************************************************
/                                      ANALOG INPUT GENERAL TIMING
*/
static void STX104_AI_Timing_Set( int board, unsigned long ai_time_frame_ns, unsigned long ai_time_intra_sample_ns )
{
    unsigned int adc_burst_channel_count;

    switch ( stx104_revision[board] )
    {
       case STX104_REVISION_080214:  /* same as version 080407 */
       case STX104_REVISION_090115:
            STX104_Set_Bank( board, 1 );
            STX104_Write_Indexed_Data_Byte( board, STX104_BURST_FUNCTION_ENABLE_INDEXED, 0x40 );
            STX104_Write_Indexed_Data_Byte( board, STX104_BURST_MODE_ENABLE_INDEXED,     0x40 );
            STX104_Write_Indexed_Data_Byte( board, STX104_CONVERSION_DISABLE_INDEXED,    0x00 );
            adc_burst_channel_count = (unsigned char)( 0x0F & ( stx104_ai_channel_last[board] - stx104_ai_channel_first[board] ) );
            adc_burst_channel_count = adc_burst_channel_count << 4;
            outp( stx104_base_address[board] + STX104_PACER_CLOCK_CONTROL, adc_burst_channel_count );
            /* the following registers require the number of 25nSec intervals to achieve the selected timing */
            STX104_Write_Indexed_Data_Dword( board, STX104_ANALOG_INPUT_FRAME_TIMER, ( ai_time_frame_ns/STX104_TIME_RESOLUTION ) );
            STX104_Write_Indexed_Data_Dword( board, STX104_ANALOG_INPUT_BURST_TIMER, ( (ai_time_intra_sample_ns - STX104_INTRA_SAMPLE_TIMING) / STX104_TIME_RESOLUTION ) );
            break;
        default:
            if ( ai_time_intra_sample_ns > STX104_INTRA_SAMPLE_TIMING /*nS*/ )
            { /* cannot use adc-burst mode */
                STX104_AI_Timing_8254_Set( board, ai_time_intra_sample_ns );
                outp( stx104_base_address[board] + STX104_BURST_FUNCTION,         0x00 );
                outp( stx104_base_address[board] + STX104_BURST_MODE_ENABLE,      0x00 );
                outp( stx104_base_address[board] + STX104_CONVERSION_DISABLE,     0x00 );
            }
            else
            { /* utilize adc-burst mode */
                STX104_AI_Timing_8254_Set( board, ai_time_frame_ns );
                outp( stx104_base_address[board] + STX104_BURST_FUNCTION,         0x40 );
                outp( stx104_base_address[board] + STX104_BURST_MODE_ENABLE,      0x40 );
                outp( stx104_base_address[board] + STX104_CONVERSION_DISABLE,     0x00 );
                adc_burst_channel_count = (unsigned char)( 0x0F & ( stx104_ai_channel_last[board] - stx104_ai_channel_first[board] ) );
                adc_burst_channel_count = adc_burst_channel_count << 4;
                outp( stx104_base_address[board] + STX104_PACER_CLOCK_CONTROL, adc_burst_channel_count );
           }
    }
}
Copyright © 2009 by Apex Embedded Systems. All rights reserved. Updated on Thursday, October 08, 2009.
What do you think about this topic? Send feedback!