www.pudn.com > ucosii_block.rar > AIO.C


/* 
********************************************************************************************************* 
*                                          Analog I/O Module 
* 
*                            (c) Copyright 1999, Jean J. Labrosse, Weston, FL 
*                                          All Rights Reserved 
* 
* Filename   : AIO.C 
* Programmer : Jean J. Labrosse 
********************************************************************************************************* 
*/ 
 
/* 
********************************************************************************************************* 
*                                           INCLUDE FILES 
********************************************************************************************************* 
*/ 
 
#define   AIO_GLOBALS 
#include "includes.h" 
 
/* 
********************************************************************************************************* 
*                                          LOCAL VARIABLES 
********************************************************************************************************* 
*/ 
 
static  OS_STK      AIOTaskStk[AIO_TASK_STK_SIZE]; 
static  OS_EVENT   *AIOSem; 
 
/* 
********************************************************************************************************* 
*                                      LOCAL FUNCTION PROTOTYPES 
********************************************************************************************************* 
*/ 
 
        void        AIOTask(void *data); 
 
static  void        AIInit(void); 
static  void        AIUpdate(void); 
 
static  void        AOInit(void); 
static  void        AOUpdate(void); 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                 CONFIGURE THE CALIBRATION PARAMETERS OF AN ANALOG INPUT CHANNEL 
* 
* Description : This function is used to configure an analog input channel. 
* Arguments   : n        is the analog input channel to configure: 
*               gain     is the calibration gain 
*               offset   is the calibration offset 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog input channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AICfgCal (INT8U n, FP32 gain, FP32 offset) 
{ 
    INT8U err; 
    AIO  *paio; 
 
 
    if (n < AIO_MAX_AI) { 
        paio               = &AITbl[n];               /* Point to Analog Input structure               */ 
        OSSemPend(AIOSem, 0, &err);                   /* Obtain exclusive access to AI channel         */ 
        paio->AIOCalGain   = gain;                    /* Store new cal. gain and offset into struct    */ 
        paio->AIOCalOffset = offset; 
        paio->AIOGain      = paio->AIOCalGain   * paio->AIOConvGain;      /* Compute overall gain      */ 
        paio->AIOOffset    = paio->AIOCalOffset + paio->AIOConvOffset;    /* Compute overall offset    */ 
        OSSemPost(AIOSem);                                                /* Release AI channel        */ 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                    CONFIGURE THE CONVERSION PARAMETERS OF AN ANALOG INPUT CHANNEL 
* 
* Description : This function is used to configure an analog input channel. 
* Arguments   : n        is the analog channel to configure (0..AIO_MAX_AI-1). 
*               gain     is the conversion gain 
*               offset   is the conversion offset 
*               pass     is the value for the pass counts 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog input channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AICfgConv (INT8U n, FP32 gain, FP32 offset, INT8U pass) 
{ 
    INT8U err; 
    AIO  *paio; 
 
 
    if (n < AIO_MAX_AI) { 
        paio                = &AITbl[n];              /* Point to Analog Input structure               */ 
        OSSemPend(AIOSem, 0, &err);                   /* Obtain exclusive access to AI channel         */ 
        paio->AIOConvGain   = gain;                   /* Store new conv. gain and offset into struct   */ 
        paio->AIOConvOffset = offset; 
        paio->AIOGain       = paio->AIOCalGain   * paio->AIOConvGain;     /* Compute overall gain      */ 
        paio->AIOOffset     = paio->AIOCalOffset + paio->AIOConvOffset;   /* Compute overall offset    */ 
        paio->AIOPassCnts   = pass; 
        OSSemPost(AIOSem);                                                /* Release AI channel        */ 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                      CONFIGURE THE SCALING PARAMETERS OF AN ANALOG INPUT CHANNEL 
* 
* Description : This function is used to configure the scaling parameters associated with an analog 
*               input channel. 
* Arguments   : n        is the analog input channel to configure (0..AIO_MAX_AI-1). 
*               arg      is a pointer to arguments needed by the scaling function 
*               fnct     is a pointer to a scaling function 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog input channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AICfgScaling (INT8U n, void (*fnct)(AIO *paio), void *arg) 
{ 
    AIO *paio; 
 
 
    if (n < AIO_MAX_AI) { 
        paio                  = &AITbl[n];            /* Faster to use a pointer to the structure      */ 
        OS_ENTER_CRITICAL(); 
        paio->AIOScaleFnct    = (void (*)())fnct; 
        paio->AIOScaleFnctArg = arg; 
        OS_EXIT_CRITICAL(); 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                GET THE VALUE OF AN ANALOG INPUT CHANNEL 
* 
* Description : This function is used to get the currect value of an analog input channel (in engineering 
*               units). 
* Arguments   : n     is the analog input channel (0..AIO_MAX_AI-1). 
*               pval  is a pointer to the destination engineering units of the analog input channel 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog input channel number. 
*                        In this case, the destination is not changed. 
********************************************************************************************************* 
*/ 
 
INT8U  AIGet (INT8U n, FP32 *pval) 
{ 
    AIO  *paio; 
 
 
    if (n < AIO_MAX_AI) { 
        paio  = &AITbl[n]; 
        OS_ENTER_CRITICAL();           /* Obtain exclusive access to AI channel                        */ 
        *pval = paio->AIOEU;           /* Get the engineering units of the analog input channel        */ 
        OS_EXIT_CRITICAL();            /* Release AI channel                                           */ 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                     ANALOG INPUTS INITIALIZATION 
* 
* Description : This function initializes the analog input channels. 
* Arguments   : None 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
static  void  AIInit (void) 
{ 
    INT8U   i; 
    AIO    *paio; 
 
 
    paio = &AITbl[0]; 
    for (i = 0; i < AIO_MAX_AI; i++) { 
        paio->AIOBypassEn     =  FALSE;           /* Analog channel is not bypassed                     */ 
        paio->AIORaw          =  0x0000;          /* Raw counts of ADC or DAC                           */ 
        paio->AIOEU           = (FP32)0.0;        /* Engineering units of AI channel                    */ 
        paio->AIOGain         = (FP32)1.0;        /* Total gain                                         */ 
        paio->AIOOffset       = (FP32)0.0;        /* Total offset                                       */ 
        paio->AIOLim          =       0; 
        paio->AIOPassCnts     =       1;          /* Pass counts                                        */ 
        paio->AIOPassCtr      =       1;          /* Pass counter                                       */ 
        paio->AIOCalGain      = (FP32)1.0;        /* Calibration gain                                   */ 
        paio->AIOCalOffset    = (FP32)0.0;        /* Calibration offset                                 */ 
        paio->AIOConvGain     = (FP32)1.0;        /* Conversion gain                                    */ 
        paio->AIOConvOffset   = (FP32)0.0;        /* Conversion offset                                  */ 
        paio->AIOScaleIn      = (FP32)0.0;        /* Input  to scaling function                         */ 
        paio->AIOScaleOut     = (FP32)0.0;        /* Output of scaling function                         */ 
        paio->AIOScaleFnct    = (void *)0;        /* No function to execute                             */ 
        paio->AIOScaleFnctArg = (void *)0;        /* No arguments to scale function                     */ 
        paio++; 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                   ANALOG I/O MANAGER INITIALIZATION 
* 
* Description : This function initializes the analog I/O manager module. 
* Arguments   : None 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
void  AIOInit (void) 
{ 
    INT8U   err; 
 
 
    AIInit(); 
    AOInit(); 
    AIOInitIO(); 
    AIOSem = OSSemCreate(1);                     /* Create a mutual exclusion semaphore for AIOs       */ 
    OSTaskCreateExt(AIOTask, (void *)0, &AIOTaskStk[AIO_TASK_STK_SIZE], AIO_TASK_PRIO, 
                    AIO_TASK_PRIO, &AIOTaskStk[0], AIO_TASK_STK_SIZE, (void *)0, OS_TASK_OPT_SAVE_FP); 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                      ANALOG I/O MANAGER TASK 
* 
* Description : This task is created by AIOInit() and is responsible for updating the analog inputs and 
*               analog outputs. 
*               AIOTask() executes every AIO_TASK_DLY milliseconds. 
* Arguments   : None. 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
void  AIOTask (void *data) 
{ 
    INT8U err; 
 
 
    data = data;                                 /* Avoid compiler warning                             */ 
    for (;;) { 
        OSTimeDlyHMSM(0, 0, 0, AIO_TASK_DLY);    /* Delay between execution of AIO manager             */ 
 
        OSSemPend(AIOSem, 0, &err);              /* Obtain exclusive access to AI channels             */ 
        AIUpdate();                              /* Update all AI channels                             */ 
        OSSemPost(AIOSem);                       /* Release AI channels (Allow high prio. task to run) */ 
 
        OSSemPend(AIOSem, 0, &err);              /* Obtain exclusive access to AO channels             */ 
        AOUpdate();                              /* Update all AO channels                             */ 
        OSSemPost(AIOSem);                       /* Release AO channels (Allow high prio. task to run) */ 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                           SET THE STATE OF THE BYPASSED ANALOG INPUT CHANNEL 
* 
* Description : This function is used to set the engineering units of a bypassed analog input channel. 
*               This function is used to simulate the presense of the sensor.  This function is only 
*               valid if the bypass 'switch' is open. 
* Arguments   : n     is the analog input channel (0..AIO_MAX_AI-1). 
*               val   is the value of the bypassed analog input channel: 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog input channel number. 
*               2        if AIOBypassEn was not set to TRUE 
********************************************************************************************************* 
*/ 
 
INT8U  AISetBypass (INT8U n, FP32 val) 
{ 
    AIO   *paio; 
 
 
    if (n < AIO_MAX_AI) { 
        paio = &AITbl[n];                        /* Faster to use a pointer to the structure           */ 
        if (paio->AIOBypassEn == TRUE) {         /* See if the analog input channel is bypassed        */ 
            OS_ENTER_CRITICAL(); 
            paio->AIOEU = val;                   /* Yes, then set the new value of the channel         */ 
            OS_EXIT_CRITICAL(); 
            return (0); 
        } else { 
            return (2); 
        } 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                  SET THE STATE OF THE BYPASS SWITCH 
* 
* Description : This function is used to set the state of the bypass switch.  The analog input channel is 
*               bypassed when the 'switch' is open (i.e. AIOBypassEn is set to TRUE). 
* Arguments   : n      is the analog input channel (0..AIO_MAX_AI-1). 
*               state  is the state of the bypass switch: 
*                         FALSE disables the bypass (i.e. the bypass 'switch' is closed) 
*                         TRUE  enables  the bypass (i.e. the bypass 'switch' is open) 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog input channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AISetBypassEn (INT8U n, BOOLEAN state) 
{ 
    if (n < AIO_MAX_AI) { 
        AITbl[n].AIOBypassEn = state; 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                   UPDATE ALL ANALOG INPUT CHANNELS 
* 
* Description : This function processes all of the analog input channels. 
* Arguments   : None. 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
static  void  AIUpdate (void) 
{ 
    INT8U   i; 
    AIO    *paio; 
 
 
    paio = &AITbl[0];                            /* Point at first analog input channel                */ 
    for (i = 0; i < AIO_MAX_AI; i++) {           /* Process all analog input channels                  */ 
        if (paio->AIOBypassEn == FALSE) {        /* See if analog input channel is bypassed            */ 
            paio->AIOPassCtr--;                  /* Decrement pass counter                             */ 
            if (paio->AIOPassCtr == 0) {         /* When pass counter reaches 0, read and scale AI     */ 
                paio->AIOPassCtr = paio->AIOPassCnts;                /* Reload pass counter            */ 
                paio->AIORaw     = AIRd(i);                          /* Read ADC for this channel      */ 
                paio->AIOScaleIn = ((FP32)paio->AIORaw + paio->AIOOffset) * paio->AIOGain; 
                if ((void *)paio->AIOScaleFnct != (void *)0) {       /* See if function defined        */ 
                    (*paio->AIOScaleFnct)(paio);                     /* Yes, execute function          */ 
                } else { 
                    paio->AIOScaleOut = paio->AIOScaleIn;            /* No,  just copy data            */ 
                } 
                paio->AIOEU = paio->AIOScaleOut;                     /* Output of scaling fnct to E.U. */ 
            } 
        } 
        paio++;                                                      /* Point at next AI channel       */ 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                 CONFIGURE THE CALIBRATION PARAMETERS OF AN ANALOG OUTPUT CHANNEL 
* 
* Description : This function is used to configure an analog output channel. 
* Arguments   : n        is the analog output channel to configure (0..AIO_MAX_AO-1) 
*               gain     is the calibration gain 
*               offset   is the calibration offset 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog output channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AOCfgCal (INT8U n, FP32 gain, FP32 offset) 
{ 
    INT8U  err; 
    AIO   *paio; 
 
 
    if (n < AIO_MAX_AO) { 
        paio               = &AOTbl[n];               /* Point to Analog Output structure              */ 
        OSSemPend(AIOSem, 0, &err);                   /* Obtain exclusive access to AO channel         */ 
        paio->AIOCalGain   = gain;                    /* Store new cal. gain and offset into struct    */ 
        paio->AIOCalOffset = offset; 
        paio->AIOGain      = paio->AIOCalGain   * paio->AIOConvGain;      /* Compute overall gain      */ 
        paio->AIOOffset    = paio->AIOCalOffset + paio->AIOConvOffset;    /* Compute overall offset    */ 
        OSSemPost(AIOSem);                                                /* Release AO channel        */ 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                    CONFIGURE THE CONVERSION PARAMETERS OF AN ANALOG OUTPUT CHANNEL 
* 
* Description : This function is used to configure an analog output channel. 
* Arguments   : n        is the analog channel to configure (0..AIO_MAX_AO-1). 
*               gain     is the conversion gain 
*               offset   is the conversion offset 
*               pass     is the value for the pass counts 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog output channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AOCfgConv (INT8U n, FP32 gain, FP32 offset, INT16S lim, INT8U pass) 
{ 
    INT8U err; 
    AIO  *paio; 
 
 
    if (n < AIO_MAX_AO) { 
        paio                = &AOTbl[n];              /* Point to Analog Output structure              */ 
        OSSemPend(AIOSem, 0, &err);                   /* Obtain exclusive access to AO channel         */ 
        paio->AIOConvGain   = gain;                   /* Store new conv. gain and offset into struct   */ 
        paio->AIOConvOffset = offset; 
        paio->AIOGain       = paio->AIOCalGain   * paio->AIOConvGain;     /* Compute overall gain      */ 
        paio->AIOOffset     = paio->AIOCalOffset + paio->AIOConvOffset;   /* Compute overall offset    */ 
        paio->AIOLim        = lim; 
        paio->AIOPassCnts   = pass; 
        OSSemPost(AIOSem);                                                /* Release AO channel        */ 
        return (0); 
    } else { 
        return (1); 
    } 
} 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                      CONFIGURE THE SCALING PARAMETERS OF AN ANALOG OUTPUT CHANNEL 
* 
* Description : This function is used to configure the scaling parameters associated with an analog 
*               output channel. 
* Arguments   : n        is the analog output channel to configure (0..AIO_MAX_AO-1). 
*               arg      is a pointer to arguments needed by the scaling function 
*               fnct     is a pointer to a scaling function 
* Returns     : 0        if successfull. 
*               1        if you specified an invalid analog output channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AOCfgScaling (INT8U n, void (*fnct)(AIO *paio), void *arg) 
{ 
    AIO *paio; 
 
 
    if (n < AIO_MAX_AO) { 
        paio                  = &AOTbl[n];            /* Faster to use a pointer to the structure      */ 
        OS_ENTER_CRITICAL(); 
        paio->AIOScaleFnct    = (void (*)())fnct; 
        paio->AIOScaleFnctArg = arg; 
        OS_EXIT_CRITICAL(); 
        return (0); 
    } else { 
        return (1); 
    } 
} 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                     ANALOG OUTPUTS INITIALIZATION 
* 
* Description : This function initializes the analog output channels. 
* Arguments   : None 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
static  void  AOInit (void) 
{ 
    INT8U   i; 
    AIO    *paio; 
 
 
    paio = &AOTbl[0]; 
    for (i = 0; i < AIO_MAX_AO; i++) { 
        paio->AIOBypassEn     = FALSE;           /* Analog channel is not bypassed                     */ 
        paio->AIORaw          = 0x0000;          /* Raw counts of ADC or DAC                           */ 
        paio->AIOEU           =  (FP32)0.0;      /* Engineering units of AI channel                    */ 
        paio->AIOGain         =  (FP32)1.0;      /* Total gain                                         */ 
        paio->AIOOffset       =  (FP32)0.0;      /* Total offset                                       */ 
        paio->AIOLim          =      0;          /* Maximum count of an analog output channel          */ 
        paio->AIOPassCnts     =      1;          /* Pass counts                                        */ 
        paio->AIOPassCtr      =      1;          /* Pass counter                                       */ 
        paio->AIOCalGain      =  (FP32)1.0;      /* Calibration gain                                   */ 
        paio->AIOCalOffset    =  (FP32)0.0;      /* Calibration offset                                 */ 
        paio->AIOConvGain     =  (FP32)1.0;      /* Conversion gain                                    */ 
        paio->AIOConvOffset   =  (FP32)0.0;      /* Conversion offset                                  */ 
        paio->AIOScaleIn      =  (FP32)0.0;      /* Input  to scaling function                         */ 
        paio->AIOScaleOut     =  (FP32)0.0;      /* Output of scaling function                         */ 
        paio->AIOScaleFnct    = (void *)0;       /* No function to execute                             */ 
        paio->AIOScaleFnctArg = (void *)0;       /* No arguments to scale function                     */ 
        paio++; 
    } 
} 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                SET THE VALUE OF AN ANALOG OUTPUT CHANNEL 
* 
* Description : This function is used to set the currect value of an analog output channel 
*               (in engineering units). 
* Arguments   : n     is the analog output channel (0..AIO_MAX_AO-1). 
*               val   is the desired analog output value in Engineering Units 
* Returns     : 0     if successfull. 
*               1     if you specified an invalid analog output channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AOSet (INT8U n, FP32 val) 
{ 
    if (n < AIO_MAX_AO) { 
        OS_ENTER_CRITICAL(); 
        AOTbl[n].AIOEU = val;          /* Set the engineering units of the analog output channel       */ 
        OS_EXIT_CRITICAL(); 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                           SET THE STATE OF THE BYPASSED ANALOG OUTPUT CHANNEL 
* 
* Description : This function is used to set the engineering units of a bypassed analog output channel. 
* Arguments   : n     is the analog output channel (0..AIO_MAX_AO-1). 
*               val   is the value of the bypassed analog output channel: 
* Returns     : 0     if successfull. 
*               1     if you specified an invalid analog output channel number. 
*               2     if AIOBypassEn is not set to TRUE 
********************************************************************************************************* 
*/ 
 
INT8U  AOSetBypass (INT8U n, FP32 val) 
{ 
    AIO *paio; 
 
 
    if (n < AIO_MAX_AO) { 
        paio = &AOTbl[n];                        /* Faster to use a pointer to the structure           */ 
        if (paio->AIOBypassEn == TRUE) {         /* See if the analog output channel is bypassed       */ 
            OS_ENTER_CRITICAL(); 
            paio->AIOScaleIn = val;              /* Yes, then set the new value of the channel         */ 
            OS_EXIT_CRITICAL(); 
            return (0); 
        } else { 
            return (2); 
        } 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                  SET THE STATE OF THE BYPASS SWITCH 
* 
* Description : This function is used to set the state of the bypass switch.  The analog output channel 
*               is bypassed when the 'switch' is open (i.e. AIOBypassEn is set to TRUE). 
* Arguments   : n      is the analog output channel (0..AIO_MAX_AO-1). 
*               state  is the state of the bypass switch: 
*                         FALSE disables the bypass (i.e. the bypass 'switch' is closed) 
*                         TRUE  enables  the bypass (i.e. the bypass 'switch' is open) 
* Returns     : 0      if successfull. 
*               1      if you specified an invalid analog output channel number. 
********************************************************************************************************* 
*/ 
 
INT8U  AOSetBypassEn (INT8U n, BOOLEAN state) 
{ 
    INT8U err; 
 
 
    if (n < AIO_MAX_AO) { 
        AOTbl[n].AIOBypassEn = state; 
        return (0); 
    } else { 
        return (1); 
    } 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                   UPDATE ALL ANALOG OUTPUT CHANNELS 
* 
* Description : This function processes all of the analog output channels. 
* Arguments   : None. 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
static  void  AOUpdate (void) 
{ 
    INT8U     i; 
    AIO      *paio; 
    INT16S    raw; 
 
 
    paio = &AOTbl[0];                            /* Point at first analog output channel               */ 
    for (i = 0; i < AIO_MAX_AO; i++) {           /* Process all analog output channels                 */ 
        if (paio->AIOBypassEn == FALSE) {        /* See if analog output channel is bypassed           */ 
            paio->AIOScaleIn = paio->AIOEU;      /* No                                                 */ 
        } 
        paio->AIOPassCtr--;                      /* Decrement pass counter                             */ 
        if (paio->AIOPassCtr == 0) {             /* When pass counter reaches 0, read and scale AI     */ 
            paio->AIOPassCtr = paio->AIOPassCnts;          /* Reload pass counter                      */ 
            if ((void *)paio->AIOScaleFnct != (void *)0) { /* See if function defined                  */ 
                (*paio->AIOScaleFnct)(paio);               /* Yes, execute function                    */ 
            } else { 
                paio->AIOScaleOut = paio->AIOScaleIn;      /* No,  bypass scaling function             */ 
            } 
            raw = (INT16S)(paio->AIOScaleOut * paio->AIOGain + paio->AIOOffset); 
            if (raw > paio->AIOLim) {                      /* Never output > maximum DAC counts        */ 
                raw = paio->AIOLim; 
            } else if (raw < 0) {                          /* DAC counts must always be >= 0           */ 
                raw = 0; 
            } 
            paio->AIORaw = raw; 
            AOWr(i, paio->AIORaw);                         /* Write counts to DAC                      */ 
        } 
        paio++;                                            /* Point at next AO channel                 */ 
    } 
} 
 
/*$PAGE*/ 
#ifndef CFG_C 
/* 
********************************************************************************************************* 
*                                      INITIALIZE PHYSICAL I/Os 
* 
* Description : This function is called by AIOInit() to initialize the physical I/O used by the AIO 
*               driver. 
* Arguments   : None. 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
void  AIOInitIO (void) 
{ 
    /* This is where you will need to put you initialization code for the ADCs and DACs                */ 
    /* You should also consider initializing the contents of your DAC(s) to a known value.             */ 
} 
 
/* 
********************************************************************************************************* 
*                                         READ PHYSICAL INPUTS 
* 
* Description : This function is called to read a physical ADC channel.  The function is assumed to 
*               also control a multiplexer if more than one analog input is connected to the ADC. 
* Arguments   : ch     is the ADC logical channel number (0..AIO_MAX_AI-1). 
* Returns     : The raw ADC counts from the physical device. 
********************************************************************************************************* 
*/ 
 
INT16S  AIRd (INT8U ch) 
{ 
    /* This is where you will need to provide the code to read your ADC(s).                            */ 
    /* AIRd() is passed a 'LOGICAL' channel number.  You will have to convert this logical channel     */ 
    /* number into actual physical port locations (or addresses) where your MUX. and ADCs are located. */ 
    /* AIRd() is responsible for:                                                                      */ 
    /*     1) Selecting the proper MUX. channel,                                                       */ 
    /*     2) Waiting for the MUX. to stabilize,                                                       */ 
    /*     3) Starting the ADC,                                                                        */ 
    /*     4) Waiting for the ADC to complete its conversion,                                          */ 
    /*     5) Reading the counts from the ADC and,                                                     */ 
    /*     6) Returning the counts to the calling function.                                            */ 
 
    return (ch); 
} 
 
/*$PAGE*/ 
/* 
********************************************************************************************************* 
*                                       UPDATE PHYSICAL OUTPUTS 
* 
* Description : This function is called to write the 'raw' counts to the proper analog output device 
*               (i.e. DAC).  It is up to this function to direct the DAC counts to the proper DAC if more 
*               than one DAC is used. 
* Arguments   : ch     is  the DAC logical channel number (0..AIO_MAX_AO-1). 
*               cnts   are the DAC counts to write to the DAC 
* Returns     : None. 
********************************************************************************************************* 
*/ 
 
void  AOWr (INT8U ch, INT16S cnts) 
{ 
    ch   = ch; 
    cnts = cnts; 
 
    /* This is where you will need to provide the code to update your DAC(s).                          */ 
    /* AOWr() is passed a 'LOGICAL' channel number.  You will have to convert this logical channel     */ 
    /* number into actual physical port locations (or addresses) where your DACs are located.          */ 
    /* AOWr() is responsible for writing the counts to the selected DAC based on a logical number.     */ 
} 
#endif