/*******************************************************************************
 *
 * RTips Technologies
 * Bangalore, India
 * www.rtipsonline.com
 *
 * Filename: mtiirq.c
 *
 * Copyright (c) 2025 RTips Technologies
 *
 *******************************************************************************
 * Module Description:
 *
 *      This application demonstrates the use of Trigger functionality of Multi
 *  Function boards along with MTi mode to generate interrupts on the receipt of 
 * 	specified command words. The sample derives code from multiple samples and 
 * code snippets provided by DDC.
 * 
 * - This sample uses Triggers with MTi mode for command word match and links the 
 * ACEX_TRG_EVENT_INTERRUPT event to the trigger.
 * - General Purpose Trigger 1 and 2 are used to demonstrate comparison of two 
 * command words. This may be extended to up to 16 command words.
 * - Upon receipt of a message with a matching command word, the board raises an 
 * interrupt that is handled by an interrupt service routine.
 * - The ISR obtains the source of interrupt by reading the trigger status and 
 * IRQ status using acexTRGGetStatus and prints an appropriate message.
 * - The sample may be extended to perform data word matching instead of command word.
 * To test this sample, two DDC 1553 boards are needed. One, to run this sample 
 * as an MTi which must be a multi-function card and another to generate the BC 
 * traffic (this may be a single function board as well).
 ******************************************************************************/


/*Include Files */
#ifdef WIN32
#include <windows.h>
#include <conio.h>
#include <time.h>
#endif

#include "stdemace.h"

static S16BIT wResult = 0x0000;
static U16BIT quit = 0;
static S16BIT DevNum = 0x0000;

U16BIT firstCmdWordToMatch = 0x0820;
U16BIT secondCmdWordToMatch = 0x1060;

/*******************************************************************************
 * Name:    myTrgIsr
 *
 * Description:
 *
 *      This function is the Interrrupt Service Routine that gets called when.
 *      the MTi generates an interrupt
 * 
 * In   DevNum - The LDN that generated this interrupt
 * In   status - Additional info on the interrupt
 ******************************************************************************/
void myTrgIsr(S16BIT Devnum, U32BIT status)
{
    S16BIT nResult;
    U32BIT u32TrgStatus = 0;
    U32BIT u32IrqStatus = 0;

    /* Get trigger and IRQ status. */
    nResult = acexTRGGetStatus(0, /* LDN */
        &u32TrgStatus, /* Trigger status */
        &u32IrqStatus); /* IRQ Status */
    if (nResult)
            printf("acexTRGGetStatus Error : Code % d\n", nResult);

    printf("ISR Trig Status = 0x%08x Irq Status = 0x%08x\n", u32TrgStatus, u32IrqStatus);
    if (u32IrqStatus & 0x00000004)
        printf("Msg 0x%04X detected\n", firstCmdWordToMatch);
    else if (u32IrqStatus & 0x00000008)
        printf("Msg 0x%04X detected\n", secondCmdWordToMatch);

    printf("\n");
}


/*******************************************************************************
 * Name:    PrintHeader
 *
 * Description:
 *
 *      Prints the sample program header.
 *
 * In   none
 * Out  none
 ******************************************************************************/
static void PrintHeader
()
{
    U16BIT wLibVer;

    wLibVer = aceGetLibVersion();

    printf("*********************************************\n");
    printf("AceXtreme Integrated 1553 Terminal          *\n");
    printf("BU-69092 1553 Runtime Library               *\n");
    printf("Release Rev %d.%d.%d                           *\n",
        (wLibVer >> 8),             /* Major*/
        (wLibVer & 0xF0) >> 4,      /* Minor*/
        (wLibVer & 0xF));           /* Devel*/

    if ((wLibVer & 0xF) != 0)
    {
        printf("=-=-=-=-=-=-=-INTERIM VERSION-=-=-=-=-=-=-=-*\n");
    }

    printf("Copyright (c) 2010 Data Device Corporation  *\n");
    printf("*********************************************\n");
    printf("IrigDemo.c MTi IRIG Demo                    *\n");
    printf("*********************************************\n\n");
}

/*******************************************************************************
 * Name:    PrintOutError
 *
 * Description:
 *
 *      This function prints out errors returned from library functions.
 *
 * In   result - the error number
 * Out  none
 ******************************************************************************/
static void PrintOutError
(
    S16BIT nResult
)
{
    char buf[80];

    aceErrorStr(nResult, buf, 80);
    printf("RTL Function Failure-> %s.\n", buf);
}

/*******************************************************************************
 * Name:    TriggerConfigure
 *
 * Description:
 *
 *      Configure trigger and events.
 *
 * In   s16DevNum       number associated with the hardware (0-31)
 * In   u16TrgId        trigger ID
 * In   u16Events       events to test
 * In   s16Direction    direction
 * In   cmdWordToMatch  the command word to be matched for firing trigger
 * Out  return          error condition
 ******************************************************************************/
S16BIT TriggerConfigure(S16BIT s16DevNum, U16BIT u16TrgId, U16BIT u16Events, U16BIT cmdWordToMatch)
{		
    U8BIT   u8InTrg;

    S16BIT s16Result = 0;

    ACEX_TRG_CONFIG  sTrgConfig;
    memset(&sTrgConfig,0, sizeof(ACEX_TRG_CONFIG));

    /* set events */
    s16Result = acexTRGEventSelect(s16DevNum, u16TrgId, u16Events, ACEX_TRG_EVENT_TRG);
    if(s16Result)
    {
        printf("acexTRGEventSelect ");
        PrintOutError(s16Result);
        return s16Result;
    }

    /* set trigger for commmand match*/
	u8InTrg = ACEX_TRG_IN_START;

	sTrgConfig.u.sGpt.u8InGptTrg = u8InTrg;

	sTrgConfig.u.sGpt.bSet           = 0;			    /* do not set trigger                           */
		
	sTrgConfig.u.sGpt.bClrNotMatched = 0;               /* do not clr                                   */
	sTrgConfig.u.sGpt.bClrAuto       = 1;               /* auto clr                                     */
	sTrgConfig.u.sGpt.bClrNewMsg     = 0;               /* do not clr                                   */

	sTrgConfig.u.sGpt.bBcCmdEn       = 1;               /* match BC cmd                                 */
	sTrgConfig.u.sGpt.bBcDataEn      = 0;               /* do not match BC Data                         */
	sTrgConfig.u.sGpt.bRtStatusEn    = 0;               /* do not match RT Status                       */
	sTrgConfig.u.sGpt.bRtDataEn      = 0;               /* do not match RT Data                         */
	sTrgConfig.u.sGpt.bBswEn         = 0;               /* do not match BSW                             */

	sTrgConfig.u.sGpt.bBusAEn        = 1;               /* match on Bus A                               */
	sTrgConfig.u.sGpt.bBusBEn        = 0;               /* do not match on Bus B                        */

	sTrgConfig.u.sGpt.u8DataCnt      = 0;               /* data 0 - cmd                                 */

	sTrgConfig.u.sGpt.u8TrgCnt       = 0;               /* 2 = Trigger with every 4th occurance, 0 - based. */

	sTrgConfig.u.sGpt.u16Mask        = 0xFFFF;          /* Mask bits for to check for                   */
	sTrgConfig.u.sGpt.u16Data        = cmdWordToMatch;  /* COMMAND WORD THAT WILL GENERATE THE TRIGGER  */

    /* configure trigger */
    s16Result = acexTRGConfigure(s16DevNum, u16TrgId, sTrgConfig);
    if(s16Result)
    {
        if (s16Result ==ACE_ERR_PARAMETER)
        {
            printf("%d: Parameter ERROR\n", s16DevNum);
        }

        return s16Result;
    }

	/* enable events */
	s16Result = acexTRGEventEnable(s16DevNum, u16Events);
	if (s16Result)
	{
		printf("acexTRGEventEnable ");
		PrintOutError(s16Result);
		return s16Result;
	}

	/* enable a trigger */
	s16Result = acexTRGEnable(s16DevNum, u16TrgId);
	if (s16Result)
	{
		printf("acexTRGDisable ");
		PrintOutError(s16Result);
		return s16Result;
	}
    else
    {
        printf("Enabled trigger ID 0x%04x to generate interrupt upon CW 0x%04X\n", u16TrgId, cmdWordToMatch);
    }

    return ACE_ERR_SUCCESS;
}


/*******************************************************************************
 * Name:   main
 *
 * Description:
 *
 *      Program entry point.
 *
 * In   none
 * Out  none
 ******************************************************************************/
#ifndef VX_WORKS
int main
(
    void
)
#else

 /* ========================================================================== */
 /* ========================================================================== */
int mtiirq
(
    void
)
#endif
{
    /* Variable Definition */
    HWVERSIONINFO structHWVersionInfo;

#if (DDC_SAMPLE_USER_INPUT == 0)
    U32BIT iCounter = 500;
#endif

#ifdef WIN32
    DDC_HANDLE hConsole = NULL;
#endif

    S32BIT dwPktPoolSize = 0x2000;

    /* Setup Windows Console Screen */
#ifdef WIN32
    hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTitle("DDC AceXtreme RTL [mtiirq.c - Console App MTi IRQ demo]");
#endif

    wResult = 0x0000;
    quit = 0;
    DevNum = 0x0000;

    /* Print out sample header */
    PrintHeader();

    /* Get Logical Device # */
    printf("\nSelect MTi Logical Device Number (0-31):\n");
    printf("> ");

#if DDC_SAMPLE_USER_INPUT    
    scanf("%hd", &DevNum);
#else
    DevNum = 0;
    printf("%d \n", DevNum);
#endif    

    aceInitialize(DevNum, ACE_ACCESS_CARD, ACE_MODE_TEST, 0, 0, 0);

    /* check to see if this device is ACEX capable */
    wResult = aceGetHwVersionInfo(DevNum, &structHWVersionInfo);

    aceFree(DevNum);

    if ( (structHWVersionInfo.dwCapabilities & HWVER_CAPABILITY_MF) == 0) 
    {
        printf("\nERROR: This device is not Multi-Function. MTi IRQ requires trigger support which is available in Multi-Function devices only. Exiting...\n");
#if DDC_SAMPLE_USER_INPUT        
        getch();
#endif 
        return(1);
    }

    /* Initialize Device */
    wResult = aceInitialize(DevNum, ACE_ACCESS_CARD, ACE_MODE_MTI + ACE_NO_TT_RESET, 0, 0, 0);

    if (wResult)
    {
        printf("aceInitialize Failed!");
        PrintOutError(wResult);
#if DDC_SAMPLE_USER_INPUT        
        getch();
#endif 
        return(1);
    }

    wResult = aceMTIConfigure(DevNum,       /* logical device number                                                            */
        MTI_DEVBUF_SIZE_128K,                     /* Dev byte size set to 512 KB                                                      */
        8,                                  /* number of available buffers to hold ch10 packets                                 */
        dwPktPoolSize,                      /* size in bytes of each ch10 packet buffer - bufsize                               */
        0,                                  /* FALSE since user supplied buffer is used in Chapter 10 packet management         */
        (dwPktPoolSize / 2),                /* num of words in packet - applies if MTI_NUM_WORDS enabled. set < (bufsize - 256) */
        100,                                /* number of messages in packet - applies if MTI_NUM_MSGS enabled                   */
        1000,                               /* time interval per packet - applies if MTI_TIME_INT enabled                       */
        MTI_HOST_INT,
        0,                                  /* Ch10 Channel ID                                                                  */
        0, 0, 0,                            /* reserved for futeure devlopment                                                  */
        0
    );

    if (wResult != ACE_ERR_SUCCESS)
    {
        printf("aceMTIConfigure Failed!");
        PrintOutError(wResult);
        goto EndSample;
    }

    /* reset  triggers */
    wResult = acexTRGReset(DevNum);
    Sleep(10);

    /* Setup triggers to fire upon matching command words. Up to 16 words can be matched. Each will require 
       a different GPT trigger to be used. Call the below function once for every command word to be matched, 
       using a different trigger ID (e.g. ACEX_TRG_ID_GPT1) each time. The sample demonstrates matching two 
       command words */
    firstCmdWordToMatch = 0x0820;       // 01-R-01-00
    secondCmdWordToMatch = 0x1060;      // 02-R-03-00
    TriggerConfigure(DevNum, ACEX_TRG_ID_GPT1, ACEX_TRG_EVENT_INTERRUPT, firstCmdWordToMatch);
    TriggerConfigure(DevNum, ACEX_TRG_ID_GPT2, ACEX_TRG_EVENT_INTERRUPT, secondCmdWordToMatch);

    /* set interrupt service -- will be callled when trigger occurs */
    wResult = aceSetIrqConditions(DevNum, TRUE, ACE_IMR2_BIT_TRIGGER, myTrgIsr);
    if (wResult != ACE_ERR_SUCCESS)
    {
        printf("aceSetIrqConditions ");
        PrintOutError(wResult);
        goto EndSample;
    }

    printf("Starting MTi and waiting for messages ...\n\n");
    /* Start MTi */
    wResult = aceMTIStart(DevNum);

    if (wResult != ACE_ERR_SUCCESS)
    {
        printf("aceMTIStart Failed!");
        PrintOutError(wResult);
        goto EndSample;
    }

    /* Waiting for Packets */
    while (1)
    {
        /* wait for 100 ms */
        DDC_MSLEEP(100);
#if DDC_SAMPLE_USER_INPUT
        if (kbhit())
#else
        iCounter--;
        if (!iCounter)
#endif    
        {
            printf("Quit = 1 \n");
            quit = 1;
            break;
        }

    }
    DDC_MSLEEP(1000);
#if DDC_SAMPLE_USER_INPUT        
    getch();
#endif 

EndSample:

    /* Stop MTi */
    wResult = aceMTIStop(DevNum);
    if (wResult != ACE_ERR_SUCCESS)
    {
        printf("aceMTIStop Failed!");
        PrintOutError(wResult);
    }

    /* free the card */
    wResult = aceFree(DevNum);
    if (wResult)
    {
        printf("aceFree failed!");
        PrintOutError(wResult);
#if DDC_SAMPLE_USER_INPUT        
        getch();
#endif 
        return(1);
    }

    printf("EXIT mtiirq demo\n");

    return(0);
}
