void start_fpga(NiFpga_Session* session, NiFpga_Status* status)
{
	// must be called before any other calls 
	*status = NiFpga_Initialize();
	printf("initializing FPGA read AI AO\n");
	printf("bitfile expected at:\n");
	printf(NiFpga_FPGA_read_ai_ao_Bitfile);
	printf("\n");
	
    //printf("Current working dir: %s\n", strcat(cwd, '../labview_fpga_lib/read_ai_ao/'));
	if (NiFpga_IsNotError(*status))
	{
		// opens a session, downloads the bitstream, and runs the FPGA 
		NiFpga_MergeStatus(status, NiFpga_Open(NiFpga_FPGA_read_ai_ao_Bitfile,
												NiFpga_FPGA_read_ai_ao_Signature,
												"RIO0",
												NiFpga_OpenAttribute_NoRun,
												session));
		if (NiFpga_IsNotError(*status))
		{
			// run the FPGA application 
			NiFpga_MergeStatus(status, NiFpga_Run(*session, 0));
		}
		else{
			// print warning
			printf("error occurred at FPGA open");
			printf("%d", *status);
			
		}
	}
	
	fflush(stdout);
	
}
void stop_fpga(NiFpga_Session* session, NiFpga_Status* status)
{
	// close the session now that we're done 
	NiFpga_MergeStatus(status, NiFpga_Close(*session, 0));

	// must be called after all other calls 
	NiFpga_MergeStatus(status, NiFpga_Finalize());
}
Beispiel #3
0
// Closes the FPGA session
void FPGA_Close(void)
{
	// close the session now that we're done 
	printf("Closing the session...");
	if (NiFpga_IsNotError(FPGA_Status))
	{
		NiFpga_MergeStatus(&FPGA_Status, NiFpga_Close(FPGA_Session, 0));
	}
	// must be called after all other calls
	printf("Finalizing...");

	NiFpga_MergeStatus(&FPGA_Status, NiFpga_Finalize());
}
Beispiel #4
0
void FPGA_SetPIDdt(uint16_t dt) {
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteU16(FPGA_Session,NiFpga_mainFPGA_ControlU16_PIDdt, dt));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Set PID dt failed");
    }
}
int16_t read_AI2(NiFpga_Session* session, NiFpga_Status* status)
{
	int16_t value;

	NiFpga_MergeStatus(status, NiFpga_ReadI16(*session,NiFpga_FPGA_read_ai_ao_IndicatorI16_Connector1AI2,&value));
	return value;
}
Beispiel #6
0
void FPGA_setLPIDIntGain(int16_t gain) {
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteI16(FPGA_Session,NiFpga_mainFPGA_ControlI16_LPIDIntGain,gain));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Set left PID integral gain failed");
    }
}
Beispiel #7
0
// Sets the sabertooth address
void FPGA_setSabertoothAddress(uint8_t address) {
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteU8(FPGA_Session,NiFpga_mainFPGA_ControlU8_SerialAddress, address));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Failed to set Sabertooth Address");
    }
}
Beispiel #8
0
void FPGA_setMaxPIDSpeed(uint16_t max) {
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteU16(FPGA_Session,NiFpga_mainFPGA_ControlU16_maxPIDSpeedTicksPerDt, max));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Set max PID speed failed");
    }
}
Beispiel #9
0
void FPGA_setRPIDDerGain(int16_t gain) {
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteI16(FPGA_Session,NiFpga_mainFPGA_ControlI16_RPIDDerGain,gain));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Set right PID derivative gain failed");
    }
}
Beispiel #10
0
int16_t FPGA_GetCRIOVLineRead() {
    int16_t retval;
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadI16(FPGA_Session,NiFpga_mainFPGA_IndicatorI16_cRIOVMonitormV,&retval));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Get cRIOV Line Read Failed.");
    }
    return retval;
}
Beispiel #11
0
uint16_t FPGA_GetRCCH3() {
    uint16_t retval;
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadU16(FPGA_Session,NiFpga_mainFPGA_IndicatorU16_C3Mode,&retval));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Get RC CH3  Read Failed.");
    }
    return retval;
}
Beispiel #12
0
int16_t FPGA_GetVersion()
{
	int16_t version;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadI16(FPGA_Session,NiFpga_mainFPGA_IndicatorI16_FPGAVersion,&version));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get FPGA Version Failed.");
	}
	return version;
}
Beispiel #13
0
void FPGA_SetMotorStatus(int value)
{
	if(value)
	{
		NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteBool(FPGA_Session,NiFpga_mainFPGA_ControlBool_enableMotors,NiFpga_True));
		if (NiFpga_IsError(FPGA_Status))
		{
			LOG.ERR("Set Motor Status Failed.");
		}
	}
	else
	{
		NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteBool(FPGA_Session,NiFpga_mainFPGA_ControlBool_enableMotors,NiFpga_False));
		if (NiFpga_IsError(FPGA_Status))
		{
			LOG.ERR("Set Motor Status Failed.");
		}
	}
}
Beispiel #14
0
int32_t FPGA_GetGPSArrayData(uint8_t * data, uint32_t length)
{

	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadArrayU8(FPGA_Session, NiFpga_mainFPGA_IndicatorArrayU8_GPSPOSBytes, data, length));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("GetArrayFailed");
	}
	return 0;
}
Beispiel #15
0
// Returns the tick value of the right motor
int32_t FPGA_GetRightMotorTicks()
{
	int32_t ticks;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadI32(FPGA_Session,NiFpga_mainFPGA_IndicatorI32_RPosMotor,&ticks));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get Right Motor Ticks Failed.");
	}
	return ticks;
}
Beispiel #16
0
int16_t FPGA_GetYawRef()
{
	int16_t value;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadI16(FPGA_Session,NiFpga_mainFPGA_IndicatorI16_YawRefmV,&value));
        if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get Yaw Ref Failed.");
	}
	LOG.DATA("YawRef = %d",value);
	return value;
}
Beispiel #17
0
// Returns the tick value on the right wheel
int32_t FPGA_GetRightWheelTicks()
{
	int32_t ticks;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadI32(FPGA_Session,NiFpga_mainFPGA_IndicatorI32_RPosWheel,&ticks));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get Right Wheel Ticks Failed.");
	}
	LOG.DATA("RwT  = %d",ticks);
	return ticks;
}
Beispiel #18
0
// Returns the velocity of the left motor
float FPGA_GetLeftMotorVelocity()
{
	int16_t ticks;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadI16(FPGA_Session,NiFpga_mainFPGA_IndicatorI16_LeftMotorVTicksPerDt,&ticks));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get Left Motor Velocity Failed.");
	}
	float Speed =  ticks /leftWheelConversionConstant;
	LOG.DATA("LMV = %f",Speed);
	return Speed;
}
Beispiel #19
0
float FPGA_GetCompassHeading(void)
{
	uint32_t current;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadU32(FPGA_Session,NiFpga_mainFPGA_IndicatorU32_HeadingFloat,&current));
	if(NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get Compass Heading Failed");
	}
	float out;
	out = *((float *)&current);
	LOG.DATA("Compass %f",out);
	return out;
}
Beispiel #20
0
/**
 * Sets options for the encoder configuration register.
 *
 * @param[in]  channel  A struct containing the registers on the encoder channel
 *                      to modify.
 * @param[in]  mask     Array of flags that indicate which of the configure
 *                      settings are valid.
 * @param[in]  settings Array of flags that indicate the configuration settings.
 */
void Encoder_Configure(MyRio_Encoder* channel, Encoder_ConfigureMask mask,
                       Encoder_ConfigureSettings settings)
{
    NiFpga_Status status;
    uint8_t cnfgValue;

    /*
     * Get the current value of the configure register.
     *
     * The returned NiFpga_Status value is stored for error checking.
     */
    status = NiFpga_ReadU8(myrio_session, channel->cnfg, &cnfgValue);

    /*
     * Check if there was an error reading from the encoder registers.
     *
     * If there was an error then the rest of the function cannot complete
     * correctly so print an error message to stdout and return from the
     * function early.
     */
    MyRio_ReturnIfNotSuccess(status,
        "Could not read from the encoder configure registers!")

    /*
     * Clear the value of the masked bits in the configure register. This is
     * done so that the correct value can be set later on.
     */
    cnfgValue = cnfgValue & (~mask);

    /*
     * Set the value of the settings in the configure register. If the
     * value to set is 0 this operation would not work unless the bit was
     * previously cleared.
     */
    cnfgValue = cnfgValue | settings;


    /*
     * Write the new value of the configure register to the device.
     */
    NiFpga_MergeStatus(&status,
            NiFpga_WriteU8(myrio_session, channel->cnfg, cnfgValue));

    /*
     * Check if there was an error writing to encoder configure registers.
     *
     * If there was an error then print an error message to stdout.
     */
    MyRio_ReturnIfNotSuccess(status,
            "Could not write to the encoder configure registers!")
}
Beispiel #21
0
uint32_t FPGA_IsGPSNew(void)
{
	uint32_t current;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadU32(FPGA_Session,NiFpga_mainFPGA_IndicatorU32_GPSPOSCount,&current));
	if(NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get GPS Counter Failed");
	}
	if(current != FPGA_IsGPSNewPrevious)
	{
            FPGA_IsGPSNewPrevious = current;
            return 1;
	}
	return 0;
}
Beispiel #22
0
uint32_t FPGA_IsCompassNew(void)
{
	uint32_t current;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadU32(FPGA_Session,NiFpga_mainFPGA_IndicatorU32_CompassResponseCount,&current));
	if(NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get Compass Counter Failed");
	}
	if(current != FPGA_IsCompassNewPrevious)
	{
		current = FPGA_IsCompassNewPrevious;
		return 1;
	}
	return 0;
}
Beispiel #23
0
// Sets the left wheel velocity
void FPGA_SetLeftWheelVelocity(float MetersPerSecond)
{
	/* Check if NAN */
	if (MetersPerSecond != MetersPerSecond)
	{
		MetersPerSecond = 0.0;
		LOG.ERR("Left Wheel command was NaN. Sending 0 instead");
	}

	int16_t ticks = MetersPerSecond * leftWheelConversionConstant;
	LOG.DATA("LwT Commanded: %d for %f", ticks, MetersPerSecond);
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteI16(FPGA_Session,NiFpga_mainFPGA_ControlI16_PIDLCmdTicksPerDt,ticks));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Setting Left Wheel Velocity Failed.");
	}
}
Beispiel #24
0
uint8_t FPGA_GetRCESTOP() {
    NiFpga_Bool rcestop;
    NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadBool(FPGA_Session,NiFpga_mainFPGA_IndicatorBool_RCeSTOP,&rcestop));
    if (NiFpga_IsError(FPGA_Status))
    {
            LOG.ERR("Get RCEStop Failed.");
    }
    if(rcestop == NiFpga_False)
    {
            LOG.DATA("RCEstop  = False");
            return 0;
    }
    else
    {
            LOG.DATA("RCEStop  = True");
            return 1;
    }
}
Beispiel #25
0
uint8_t FPGA_GetESTOPTriggered()
{
	NiFpga_Bool  ReStopTriggered;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadBool(FPGA_Session,NiFpga_mainFPGA_IndicatorBool_eSTOPTriggered,&ReStopTriggered));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get EStop Status Failed.");
	}
	if(ReStopTriggered == NiFpga_False)
	{
		LOG.DATA("EStopTriggered  = False");
		return 0;
	}
	else
	{
		LOG.DATA("EStopTriggered  = True");
		return 1;
	}
	return 0;
}
Beispiel #26
0
uint8_t FPGA_GetRCOn()
{
	NiFpga_Bool  RC;
	NiFpga_MergeStatus(&FPGA_Status,NiFpga_ReadBool(FPGA_Session,NiFpga_mainFPGA_IndicatorBool_RCOn,&RC));
	if (NiFpga_IsError(FPGA_Status))
	{
		LOG.ERR("Get RCon Status Failed.");
	}
	if(RC == NiFpga_False)
	{
		LOG.DATA("RCOn  = False");

		return 0;
	}
	else
	{
		LOG.DATA("RCOn  = True");
		return 1;
	}
	return 0;
}
Beispiel #27
0
//  Initializes the FPGA, the sabertooth and the mototrs
void FPGA_Boot(void)
{
	LOG.INFO("Initializing FPGA...");
	FPGA_Status = NiFpga_Initialize();
	if (NiFpga_IsNotError(FPGA_Status))
	{
		// opens a session, downloads the bitstream, and runs the FPGA.
		LOG.INFO("Opening a session FPGA...");

		NiFpga_MergeStatus(&FPGA_Status, NiFpga_Open(NiFpga_mainFPGA_Bitfile,
					NiFpga_mainFPGA_Signature,
					"RIO0",
					NiFpga_OpenAttribute_NoRun,
					&FPGA_Session));
		if (NiFpga_IsNotError(FPGA_Status))
		{
			LOG.INFO("ReDownloading the FPGA");
			NiFpga_MergeStatus(&FPGA_Status,NiFpga_Download(FPGA_Session));
			if (NiFpga_IsNotError(FPGA_Status))
			{
				LOG.INFO("Restarting the FPGA");
				NiFpga_MergeStatus(&FPGA_Status,NiFpga_Reset(FPGA_Session));
				if (NiFpga_IsNotError(FPGA_Status))
				{
					LOG.INFO("Running the FPGA");
					NiFpga_MergeStatus(&FPGA_Status,NiFpga_Run(FPGA_Session, 0));

					if (NiFpga_IsNotError(FPGA_Status))
					{
					}
					else
					{
						LOG.ERR("FPGA Fail to run  fpga %d ",FPGA_Status);
					}

				}
				else
				{
					LOG.ERR("FPGA Fail to redownload fpga %d ",FPGA_Status);
				}
			}
			else
			{
				LOG.ERR("FPGA Fail to redownload fpga %d ",FPGA_Status);
			}
		}
		else
		{
			LOG.ERR("FPGA Fail to  open a session. Error Code %d ",FPGA_Status);
		}
	}
	LOG.VERBOSE("Reading Constants for the fpga");

	if(fileExists("config/odometry.ini"))
	{
		dictionary* config = iniparser_load("config/odometry.ini");
		leftWheelConversionConstant  = 1/(iniparser_getdouble(config,"MotorEncoderConstant:MeterPerTickLeft",0)) * PIDUpdateRateInMs/1000;
		rightWheelConversionConstant = 1/(iniparser_getdouble(config,"MotorEncoderConstant:MeterPerTickRight",0)) * PIDUpdateRateInMs/1000;
		iniparser_freedict(config);
		LOG.VERBOSE("Odometry Ini file loaded for fpga!");

	}
	else
	{
		LOG.ERR("!!!!!!!!!!!!!!!!odomentry.ini was not found!!!!!!!!!!!!!!!!!!!!!!");
	}

        if(fileExists("config/pid.ini")) {
            dictionary* config = iniparser_load("config/pid.ini");
            max_pid_speed = (uint16_t) iniparser_getint(config, "Both:MaxSpeedTicksPerDt", 0);
            left_pid_pro_gain = iniparser_getint(config, "LeftPID:ProportionalGain",0);
            left_pid_int_gain = iniparser_getint(config, "LeftPID:IntegralGain",0);
            left_pid_der_gain = iniparser_getint(config, "LeftPID:DerivativeGain", 0);
            right_pid_pro_gain = iniparser_getint(config, "RightPID:ProportionalGain",0);
            right_pid_int_gain = iniparser_getint(config, "RightPID:IntegralGain",0);
            right_pid_der_gain = iniparser_getint(config, "RightPID:DerivativeGain",0);
            iniparser_freedict(config);
            LOG.VERBOSE("PID INI file loaded for FPGA");
        }
        else {
            LOG.ERR("PID.ini was not found");
        }

        if(fileExists("config/CRIO.ini")) {
            dictionary* config = iniparser_load("config/CRIO.ini");
            sabertooth_address = (uint8_t) iniparser_getint(config, "Sabertooth:Address", 130);
            iniparser_freedict(config);
            LOG.VERBOSE("Sabertooth address loaded for FPGA");            
        }
        else {
            LOG.ERR("Unable to load Sabertooth address");
        }

        NiFpga_MergeStatus(&FPGA_Status,NiFpga_WriteU8(FPGA_Session,NiFpga_mainFPGA_ControlU8_SlewRateControl, 10));
        if (NiFpga_IsError(FPGA_Status))
        {
                LOG.ERR("Failed to set Sabertooth slew rate");
        }

        FPGA_SetPIDdt(PIDUpdateRateInMs * 1000);
        FPGA_setMaxPIDSpeed(max_pid_speed);
        FPGA_setLPIDProGain(left_pid_pro_gain);
        FPGA_setLPIDIntGain(left_pid_int_gain);
        FPGA_setLPIDDerGain(left_pid_der_gain);
        FPGA_setRPIDProGain(right_pid_pro_gain);
        FPGA_setRPIDIntGain(right_pid_int_gain);
        FPGA_setRPIDDerGain(right_pid_der_gain);
        FPGA_setSabertoothAddress(sabertooth_address);

	    // This logs the version number
        LOG.INFO("FPGA VERSION =  %d",FPGA_GetVersion());

	LOG.INFO("Turning on the motors");
	FPGA_SetMotorStatus(1);
}
Beispiel #28
0
uint32_t FPGA_GetSonarPing_5() {
	uint32_t value;
	NiFpga_MergeStatus(&FPGA_Status, NiFpga_ReadU32(FPGA_Session, NiFpga_mainFPGA_IndicatorU32_Sonar5PWM, &value)); 
	LOG.DATA("SonarPing 5= %d", value);
	return value;
}
void set_AO7(int16_t value, NiFpga_Session* session, NiFpga_Status* status)
{
	NiFpga_MergeStatus(status, NiFpga_WriteI16(*session,NiFpga_FPGA_read_ai_ao_ControlI16_Connector1AO7,value));
}
/**
 * Reserve the interrupt from FPGA and configure DI IRQ.
 *
 * @param[in]  irqChannel   A structure containing the registers and settings
                                for a particular analog IRQ I/O to modify.
 * @param[in]  irqContext   IRQ context under which you need to reserve.
 * @param[in]  irqNumber    The IRQ number (IRQNO_MIN-IRQNO_MAX).
 * @param[in]  count        The incremental times that you use to trigger the interrupt.
 * @param[in]  type         The trigger type that you use to increment the count.
 * @return the configuration status.
 */
int32_t Irq_RegisterDiIrq(MyRio_IrqDi* irqChannel, 
                          NiFpga_IrqContext* irqContext,
                          uint8_t irqNumber, 
                          uint32_t count, 
                          Irq_Dio_Type type)
{
    int32_t status;
    uint8_t cnfgValue;
    uint16_t typeValue;

    /*
     * Reserve an IRQ context. IRQ contexts are single-threaded; only one thread
     * can wait with a particular context at any given time. To minimize jitter
     * when first waiting on IRQs, reserve as many contexts as the application requires.
     * If a context is successfully reserved, you must unreserve it later.
     * Otherwise a memory leak will occur.
     */
    status = NiFpga_ReserveIrqContext(myrio_session, irqContext);

    /*
     * Check if there was an error when you reserved an IRQ.
     *
     * If there was an error, print an error message to stdout and return the configuration status.
     */
    MyRio_ReturnStatusIfNotSuccess(status,
            "A required NiFpga_IrqContext was not reserved.")

    /*
     * Limit the IRQ number within a range,
     * if the entered value is out of range, print an error message.
     */
    if (irqNumber > IRQNO_MAX || irqNumber < IRQNO_MIN)
    {
        printf("The specified IRQ Number is out of range.\n");
        return NiMyrio_Status_IrqNumberNotUsable;
    }

    /*
     * Check if the IRQ number or channel value already exists in the resource list,
     * return the configuration status and print error message.
     */
    status = Irq_CheckReserved(irqChannel->dioChannel, irqNumber);
    if (status == NiMyrio_Status_IrqNumberNotUsable)
    {
        printf("You have already registered an interrupt with the same interrupt number.\n");
        return status;
    }
    else if (status == NiMyrio_Status_IrqChannelNotUsable)
    {
        printf("You have already registered an interrupt with the same channel name.\n");
        return status;
    }

    /*
     * Write the value to the DI IRQ number register.
     */
    status = NiFpga_WriteU8(myrio_session, irqChannel->dioIrqNumber, irqNumber);

    /*
     * Check if there was an error when your wrote to the DI IRQ number register.
     *
     * If there was an error, print an error message to stdout and return the configuration status.
     */
    MyRio_ReturnStatusIfNotSuccess(status,
            "Could not write to DI IRQ number register!")

    /*
     * Write the value to the DI IRQ count register.
     */
    status = NiFpga_WriteU32(myrio_session, irqChannel->dioCount, count);

    /*
     * Check if there was an error when you reserved an IRQ.
     *
     * If there was an error, print an error message to stdout and return the configuration status.
     */
    MyRio_ReturnStatusIfNotSuccess(status,
            "Could not write to DI IRQ count register!")

    /*
     * Get the current value of the DI rising-configure register.
     */
    status = NiFpga_ReadU8(myrio_session, irqChannel->dioIrqRisingEdge, &cnfgValue);
    typeValue = (uint16_t) cnfgValue;

    /*
     * Get the current value of the DI falling-configure register.
     * Merge it with the rising-configure register and write to typeValue.
     */
    NiFpga_MergeStatus(&status,
            NiFpga_ReadU8(myrio_session, irqChannel->dioIrqFallingEdge, &cnfgValue));
    typeValue = typeValue | (cnfgValue << 8);

    /*
     * Check if there was an error reading from the DI rising/falling configure registers.
     *
     * If there was an error, the rest of the function cannot execute successfully, print 
     * an error message to stdout and return the configuration status from the earlier 
     * execution of the function.
     */
    MyRio_ReturnStatusIfNotSuccess(status,
            "Could not read from the DI rise/fall configure registers!")

    /*
     * Get the current value of the DI configure register.
     */
    status = NiFpga_ReadU8(myrio_session, irqChannel->dioIrqEnable, &cnfgValue);

    /*
     * Check if there was an error when you reserved an IRQ.
     *
     * If there was an error, print an error message to stdout and return the configuration status.
     */
    MyRio_ReturnStatusIfNotSuccess(status,
            "Could not read from the DI configure register!")

    /*
     * Configure the IRQ triggered-type for the particular digital IRQ I、O.
     */
    if (irqChannel->dioChannel == Irq_Dio_A0)
    {
        /*
         * Clear the value of the masked bits in the DI configure register, then
         * set which IO is enabled.
         */
        cnfgValue = cnfgValue & (~Irq_Dio_A0_Enable);
        cnfgValue = cnfgValue | Irq_Dio_A0_Enable;

        /*
         * Clear the value of the masked bits in the DI configure register and set the I/O to enable.
         */
        typeValue = typeValue & (~Irq_Dio_A0_Edge);
        if (type == Irq_Dio_RisingEdge)
        {
            typeValue = typeValue | Irq_Dio_A0_RisingEdge;
        }
        else if (type == Irq_Dio_FallingEdge)
        {
            typeValue = typeValue | Irq_Dio_A0_FallingEdge;
        }
        else if (type == Irq_Dio_Edge)
        {
            typeValue = typeValue | Irq_Dio_A0_Edge;
        }
    }
    else if (irqChannel->dioChannel == Irq_Dio_A1)
    {
        /*
         * Clear the value of the masked bits in the DI configure register, then
         * set which IO is enabled.
         */
        cnfgValue = cnfgValue & (~Irq_Dio_A1_Enable);
        cnfgValue = cnfgValue | Irq_Dio_A1_Enable;

        /*
         * Clear the value of the masked bits in the DI configure register, then
         * set the triggered type.
         */
        typeValue = typeValue & (~Irq_Dio_A1_Edge);
        if (type == Irq_Dio_RisingEdge)
        {
            typeValue = typeValue | Irq_Dio_A1_RisingEdge;
        }
        else if (type == Irq_Dio_FallingEdge)
        {
            typeValue = typeValue | Irq_Dio_A1_FallingEdge;
        }
        else if (type == Irq_Dio_Edge)
        {
            typeValue = typeValue | Irq_Dio_A1_Edge;
        }
    }
    else if (irqChannel->dioChannel == Irq_Dio_A2)
    {
        /*
         * Clear the value of the masked bits in the DI configure register, then
         * set which IO is enabled.
         */
        cnfgValue = cnfgValue & (~Irq_Dio_A2_Enable);
        cnfgValue = cnfgValue | Irq_Dio_A2_Enable;

        /*
         * Clear the value of the masked bits in the DI configure register, then
         * set the triggered type.
         */
        typeValue = typeValue & (~Irq_Dio_A2_Edge);
        if (type == Irq_Dio_RisingEdge)
        {
            typeValue = typeValue | Irq_Dio_A2_RisingEdge;
        }
        else if (type == Irq_Dio_FallingEdge)
        {
            typeValue = typeValue | Irq_Dio_A2_FallingEdge;
        }
        else if (type == Irq_Dio_Edge)
        {
            typeValue = typeValue | Irq_Dio_A2_Edge;
        }
    }
    else if (irqChannel->dioChannel == Irq_Dio_A3)
    {
        /*
         * Clear the value of the masked bits in the DI configure register, then
         * set which IO is enabled.
         */
        cnfgValue = cnfgValue & (~Irq_Dio_A3_Enable);
        cnfgValue = cnfgValue | Irq_Dio_A3_Enable;

        /*
         * Clear the value of the masked bits in the DI configure register, then
         * set the triggered type.
         */
        typeValue = typeValue & (~Irq_Dio_A3_Edge);
        if (type == Irq_Dio_RisingEdge)
        {
            typeValue = typeValue | Irq_Dio_A3_RisingEdge;
        }
        else if (type == Irq_Dio_FallingEdge)
        {
            typeValue = typeValue | Irq_Dio_A3_FallingEdge;
        }
        else if (type == Irq_Dio_Edge)
        {
            typeValue = typeValue | Irq_Dio_A3_Edge;
        }
    }

    /*
     * Write the new value of the DI enable configure register to the device.
     */
    status = NiFpga_WriteU8(myrio_session, irqChannel->dioIrqEnable, cnfgValue);

    /*
     * Check if there was an error writing to DI enable configure registers.
     *
     * If there was an error then print an error message to stdout and return configuration status.
     */
    MyRio_ReturnStatusIfNotSuccess(status,
            "Could not write to the DI enable configure registers!")

    /*
     * Write the new value of the DI rise-configure register to the device.
     */
    status = NiFpga_WriteU8(myrio_session, irqChannel->dioIrqRisingEdge, (uint8_t) typeValue);

    /*
     * Write the new value of the DI fall-configure register to the device.
     */
    NiFpga_MergeStatus(&status,
            NiFpga_WriteU8(myrio_session, irqChannel->dioIrqFallingEdge, (uint8_t)(typeValue >> 8)));

    /*
     * Check if there was an error writing to DI rise/fall configure registers.
     *
     * If there was an error then print an error message to stdout.
     */
    MyRio_ReturnStatusIfNotSuccess(status,
            "Could not write to the DI rise/fall configure registers!")

    /*
     * Add the channel value and IRQ number in the list.
     */
    Irq_AddReserved(irqChannel->dioChannel, irqNumber);

    return NiMyrio_Status_Success;
}