/******************************************************************************
*
* Data Device Corporation
* 105 Wilbur Place
* Bohemia N.Y. 11716
* 
* Modified for additional functionality by RTips Technologies
* (www.rtipsonline.com)
*
* Filename: bcasync3.c
*
* AceXtreme 'C' Run Time Library Toolbox
*
* Copyright (c) 2010 Data Device Corporation
*
*******************************************************************************
* Non-Disclosure Statement
* ------------------------
* This software is the sole property of Data Device Corporation. All
* rights, title, ownership, or other interests in the software remain
* the property of Data Device Corporation. This software may be used
* in accordance with applicable licenses. Any unauthorized use,
* duplication, transmission, distribution, or disclosure is expressly
* forbidden.
*
* This non-disclosure statement may not be removed or modified without
* prior written consent of Data Device Corporation.
*******************************************************************************
* Module Description:
*
*   This application is a modified version of DDC's bcasync2 sample. In addition 
*   to the functionality of bcasync2, this application sends mode code 2 to RT 10
*   and broadcasts mode code 17.  
*
*   Function used in this example:
*
*       aceInitialize
*       aceFree
*       aceGetLibVersion
*       aceErrorStr
*       aceGetMsgTypeString
*       aceCmdWordParse
*       aceGetBSWErrString
*       aceDataBlkCreate
*       aceBCMsgCreateBCtoRT
*       aceBCAsyncMsgCreateBCtoRT
*       aceBCAsyncMsgCreateRTtoBC
*       aceBCAsyncMsgCreateRTtoRT
*       aceBCAsyncMsgCreateMode
*       aceBCAsyncMsgCreateBcstMode
*       aceBCSendAsyncMsgHP
*       aceBCGetMsgFromIDDecoded
*       aceBCOpCodeCreate
*       aceBCFrameCreate
*       aceBCStart
*       aceBCStop
******************************************************************************/

/* include files */
#ifdef WIN32
#include <windows.h>
#include <conio.h>
#endif

#include "stdemace.h"


/* define data blocks */
#define DBLK1   1
#define DBLK2   2
#define DBLK3   3
#define DBLK4   4
#define DBLK5   5
#define DBLK6   6

/* define message constants */
#define MSG1    1
#define MSG2    2
#define MSG3    3
#define MSG4    4
#define MSG5    5
#define MSG6    6

/* define opcodes */
#define OP1     1
#define OP2     2

/* define frame constants */
#define MNR1    1
#define MJR     3

/* Change this to change your Frame Time */
#define wFrmTime    100

static S16BIT DevNum = 0x0000;              /* Logical Device 0 */
int index = 0;
U16BIT u16Buffer[64] =
{
    0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888,
    0x9999, 0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD, 0xEEEE, 0xFFFF, 0x0000,
    0x1234, 0x5678, 0x9ABC, 0xDEF0, 0x1234, 0x5678, 0x9ABC, 0xDEF0,
    0x1234, 0x5678, 0x9ABC, 0xDEF0, 0x1234, 0x5678, 0x9ABC, 0xDEF0
};
/*******************************************************************************
 * 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("BCAsync3.c BC operations [Asynchronous Demo]*\n");
    printf("*********************************************\n\n");

    printf(" This program wil continuously send messages to RT1/SA1,\n");
    printf(" with 10 data words: 0x0001 - 0x000A\n");
    printf("\n");
    printf(" Then 7 Asynchronous Messages will be sent out in High Priority Mode:\n");
    printf("\n");
    printf("   BC --> RT2/SA1        5 Data Words\n");
    printf("   RT2/SA1 --> BC        10 Data Words\n");
    printf("   BC --> RT2/SA1        20 Data Words\n");
    printf("   Mode Code 2 to RT10\n");
    printf("   Mode Code 17 broadcast\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:   DisplayDecodedMsg
 *
 * Description:
 *
 *      This function displays the information of a MSGSTRUCT tothe display.
 *
 * In   nMsgNum     Number of the message
 * In   pMsg        Relavant information of the message
 * Out  none
 ******************************************************************************/
static void DisplayDecodedMsg
(
    S16BIT nMsgNum,
    MSGSTRUCT *pMsg
)
{
    U16BIT i;
    char szBuffer[100];
    U16BIT wRT, wTR1, wTR2, wSA, wWC;

    /* Display message header info */
    printf("MSG #%04d.  TIME = %08dus    BUS %c   TYPE%d: %s ", nMsgNum,
        pMsg->wTimeTag * 2, pMsg->wBlkSts & ACE_MT_BSW_CHNL ? 'B' : 'A',
        pMsg->wType, aceGetMsgTypeString(pMsg->wType));

    /* Display command word info */
    aceCmdWordParse(pMsg->wCmdWrd1, &wRT, &wTR1, &wSA, &wWC);
    sprintf(szBuffer, "%02d-%c-%02d-%02d", wRT, wTR1 ? 'T' : 'R', wSA, wWC);
    printf("\n            CMD1 %04X --> %s", pMsg->wCmdWrd1, szBuffer);
    if (pMsg->wCmdWrd2Flg)
    {
        aceCmdWordParse(pMsg->wCmdWrd2, &wRT, &wTR2, &wSA, &wWC);
        sprintf(szBuffer, "%02d-%c-%02d-%02d", wRT, wTR2 ? 'T' : 'R', wSA, wWC);
        printf("\n        CMD2 %04X --> %s", pMsg->wCmdWrd2, szBuffer);
    }

    /* Display transmit status words */
    if ((wTR1 == 1) || (pMsg->wBlkSts & ACE_MT_BSW_RTRT))
    {
        if (pMsg->wStsWrd1Flg)
        {
            printf("\n            STA1 %04X", pMsg->wStsWrd1);
        }
    }

    /* Display Data words */
    for (i = 0; i < pMsg->wWordCount; i++)
    {
        if (i == 0)
        {
            printf("\n            DATA ");
        }

        printf("%04X  ", pMsg->aDataWrds[i]);

        if ((i % 8) == 7)
        {
            printf("\n                 ");
        }
    }

    /* Display receive status words */
    if ((wTR1 == 0) && !(pMsg->wBlkSts & ACE_MT_BSW_RTRT))
    {
        if (pMsg->wStsWrd1Flg)
        {
            printf("\n            STA1 %04X", pMsg->wStsWrd1);
        }
    }

    if (pMsg->wStsWrd2Flg)
    {
        printf("\n            STA2 %04X", pMsg->wStsWrd2);
    }

    /* Display Error information */
    if (pMsg->wBlkSts & ACE_MT_BSW_ERRFLG)
    {
        printf("\n ERROR: %s", aceGetBSWErrString(ACE_MODE_MT, pMsg->wBlkSts));
    }

    printf("\n\n");
}

/*******************************************************************************
 * Name:    GetBCMsgsFromID
 *
 * Description:
 *
 *      This function reads all messages from the EMACE and outputs to
 *      the display.
 *
 * In   DevNum - the device number of the hardware to be accessed
 * Out  none
 ******************************************************************************/
static void GetBCMsgsFromID
(
    S16BIT DevNum
)
{
    /* Variables */
    U16BIT wMsgCount = 0x0000;
    MSGSTRUCT sMsg;
    S16BIT wResult = 0x0000;
#if (DDC_SAMPLE_USER_INPUT == 0)
    U16BIT wRepeatCount = 100;
#endif
    U32BIT dwCurCount = 0x00000000;
	S16BIT nResult;
    
    U16BIT wBuffer2[64] =
    {
        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
        0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
        0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
    };
	U32BIT dwHBufLost = 0x00000000;
    U32BIT dwMsgCount = 0x00000000;
    //U32BIT dwCurCount = 0x00000000;

    /* Start BC */
    aceBCStart(DevNum, MJR, -1);

    /* Run Information */
    printf("\n** BC Device Number %d, press <ENTER> to stop **\n\n", DevNum);
#if DDC_SAMPLE_USER_INPUT
    getch();
#endif
    /* Send out asynchronous message */
    wResult = aceBCSendAsyncMsgHP(DevNum, MSG2, 1000);

    if (wResult)
    {
        PrintOutError(wResult);
    }

    /* Send out asynchronous message */
    wResult = aceBCSendAsyncMsgHP(DevNum, MSG3, wFrmTime);

    if (wResult)
    {
        PrintOutError(wResult);
    }
	for(index=0;index<32;index++)
	{
		u16Buffer[index]= 0X1943;
	}
	Sleep(1000);

	nResult = aceBCDataBlkWrite(0, DBLK2, u16Buffer, 32, 0);
	if (nResult)
    {
        printf("Error writing aceBCDataBlkWrite buffer\n");
    }
	 /* Send out asynchronous message */
    wResult = aceBCSendAsyncMsgHP(DevNum, MSG2, 1000);

    if (wResult)
    {
        PrintOutError(wResult);
    }

	Sleep(1000);

	for(index=0;index<32;index++)
	{
		u16Buffer[index]= 0X1372;
	}

	nResult = aceBCDataBlkWrite(0, DBLK2, u16Buffer, 32, 0);
	if (nResult)
    {
        printf("Error writing aceBCDataBlkWrite buffer\n");
    }

	 /* Send out asynchronous message */
    wResult = aceBCSendAsyncMsgHP(DevNum, MSG2, 1000);

    if (wResult)
    {
        PrintOutError(wResult);
    }
    /* Create Asynchronous Message while the bc is running */
    wResult = aceBCAsyncMsgCreateBCtoRT(
        DevNum,             /* Device number                    */
        MSG4,               /* Message ID to create             */
        DBLK4,              /* Data Block ID                    */
        2,                  /* RT address                       */
        1,                  /* RT subaddress                    */
        20,                 /* Word Count                       */
        0,                  /* Devault Message Timer            */
        ACE_BCCTRL_CHL_A,   /* use chl A options                */
        wBuffer2);          /* Data words for the async message */

    /* Send out asynchronous message */
    wResult = aceBCSendAsyncMsgHP(DevNum, MSG4, wFrmTime);

    if (wResult)
    {
        PrintOutError(wResult);
    }

    /* Send out asynchronous mode code message */
    wResult = aceBCSendAsyncMsgHP(DevNum, MSG5, wFrmTime);

    if (wResult)
    {
        PrintOutError(wResult);
    }

    /* Send out asynchronous mode code message */
    wResult = aceBCSendAsyncMsgHP(DevNum, MSG6, wFrmTime);

    if (wResult)
    {
        PrintOutError(wResult);
    }
    printf("\n\n");


#if DDC_SAMPLE_USER_INPUT 
    while (!kbhit())
#else
    while (dwCurCount < wRepeatCount)
#endif /* DDC_SAMPLE_USER_INPUT */
    {
        /* Check for MSG2 in EMACE RAM */
		/*nResult = aceBCGetHBufMsgDecoded(DevNum, &sMsg, &wMsgCount, &dwHBufLost, ACE_BC_MSGLOC_NEXT_PURGE);
		if (wMsgCount)
		{
			DisplayDecodedMsg(wMsgCount, &sMsg);
		}*/

        if (aceBCGetMsgFromIDDecoded(DevNum, MSG2, &sMsg, TRUE) == 1)
        {
            /* Display MSG2 to screen */
            wMsgCount++;
            DisplayDecodedMsg(wMsgCount, &sMsg);
        }

        /* Check for MSG3 in EMACE RAM */
        if (aceBCGetMsgFromIDDecoded(DevNum, MSG3, &sMsg, TRUE) == 1)
        {
            /* Display MSG3 to screen */
            wMsgCount++;
            DisplayDecodedMsg(wMsgCount, &sMsg);
        }

        /* Check for MSG4 in EMACE RAM */
        if (aceBCGetMsgFromIDDecoded(DevNum, MSG4, &sMsg, TRUE) == 1)
        {
            /* Display MSG4 to screen */
            wMsgCount++;
            DisplayDecodedMsg(wMsgCount, &sMsg);
        }

        /* Check for MSG5 in EMACE RAM */
        if (aceBCGetMsgFromIDDecoded(DevNum, MSG5, &sMsg, TRUE) == 1)
        {
            /* Display MSG5 to screen */
            wMsgCount++;
            DisplayDecodedMsg(wMsgCount, &sMsg);
        }

        /* Check for MSG6 in EMACE RAM */
        if (aceBCGetMsgFromIDDecoded(DevNum, MSG6, &sMsg, TRUE) == 1)
        {
            /* Display MSG6 to screen */
            wMsgCount++;
            DisplayDecodedMsg(wMsgCount, &sMsg);
        }
        
        dwCurCount++;
    }

    printf("BC: Total msgs captured: %d  ", (int)wMsgCount);

#if DDC_SAMPLE_USER_INPUT     
    /* Throw away key */
    getch();
#endif
    /* Stop BC */
    aceBCStop(DevNum);

    printf("\n");
}

/*******************************************************************************
 * Name:    main
 *
 * Description:
 *
 *      Program entry point.
 *
 * In   none
 * Out  none
 ******************************************************************************/
#ifndef VX_WORKS
int main
(
    void
)
#else

/* ========================================================================== */
/* ========================================================================== */
int bcasync3
(
    void
)
#endif
{
    /* Variables */
    S16BIT wResult = 0x0000;
    S16BIT aOpCodes[10] = { 0x0000 };

    U16BIT wBuffer[64] =
    {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
        0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf, 0x10,
        0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
        0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
    };

    U16BIT wBuffer2[64] =
    {
        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
        0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
        0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
    };

    U16BIT wBuffer3[64] =
    {
        0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
        0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
        0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
        0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60
    };

#ifdef WIN32
    DDC_HANDLE hConsole = NULL;

    /* Setup Windows Console Screen */
    hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTitle("DDC Enhanced Mini-ACE RTL [BcAsync2.c - Console App BC Demo]");
#endif

    /* Print out sample header */
    PrintHeader();

    /* Get Logical Device # */
    printf("\nSelect BC Logical Device Number (0-31):\n");
    printf("> ");
#if DDC_SAMPLE_USER_INPUT
    scanf("%hd", &DevNum);
#else
    DevNum = 0;
    printf("%d", DevNum);
#endif /* DDC_SAMPLE_USER_INPUT */

    /* Determine if using HBUF or GetMsgFromID */
    printf("\n Messages will be processed via MessageID \n");

    /* Initialize Device */
    wResult = aceInitialize(DevNum, ACE_ACCESS_CARD, ACE_MODE_BC, 0, 0, 0);
    if (wResult)
    {
        printf("Initialize ");
        PrintOutError(wResult);
#if DDC_SAMPLE_USER_INPUT
        getch();
#endif 
        return 0;
    }

    /* Enable high priority asynchronous mode */
    wResult = aceBCConfigure(DevNum, ACE_BC_ASYNC_HMODE);

    if (wResult)
    {
        printf("Configure ");
        PrintOutError(wResult);
#if DDC_SAMPLE_USER_INPUT
        getch();
#endif 
        return 0;
    }

    /* Create 3 data blocks */
    aceBCDataBlkCreate(DevNum, DBLK1, 32, wBuffer, 32);

    /* Create message block */
    aceBCMsgCreateBCtoRT(
        DevNum,              /* Device number                    */
        MSG1,                /* Message ID to create             */
        DBLK1,               /* Message will use this data block */
        2,                   /* RT address                       */
        1,                   /* RT subaddress                    */
        10,                  /* Word count                       */
        0,                   /* Default message timer            */
        ACE_BCCTRL_CHL_A);   /* use chl A options                */

    /* This message is only used in order to properly initialize the minor frame  */
    /* This message will never be transmitted (ACE_CNDTST_NEVER)                  */
    /* Create XEQ opcode that will use msg block                                  */
    aceBCOpCodeCreate(DevNum, OP1, ACE_OPCODE_XEQ, ACE_CNDTST_ALWAYS, MSG1, 0, 0);

    /* Create CAL opcode that will call mnr frame from major */
    aceBCOpCodeCreate(DevNum, OP2, ACE_OPCODE_CAL, ACE_CNDTST_ALWAYS, MNR1, 0, 0);

    /* Create Minor Frame */
    aOpCodes[0] = OP1;
    aceBCFrameCreate(DevNum, MNR1, ACE_FRAME_MINOR, aOpCodes, 1, 0, 0);

    /* Create Major Frame */
    aOpCodes[0] = OP2;
    aceBCFrameCreate(DevNum, MJR, ACE_FRAME_MAJOR, aOpCodes, 1, wFrmTime, 0);

    /* Create Asynchronous Op Code */
    aceBCAsyncMsgCreateBCtoRT(
        DevNum,             /* Device number                    */
        MSG2,               /* Message ID to create             */
        DBLK2,              /* Data Block ID                    */
        1,                  /* RT address                       */
        1,                  /* RT subaddress                    */
        5,                  /* Word Count                       */
        0,                  /* Default Message Timer            */
        ACE_BCCTRL_CHL_A,   /* use chl A options                */
        wBuffer2);          /* Data words for the async message */

    /* Create Asynchronous Op Code */
    aceBCAsyncMsgCreateRTtoBC(
        DevNum,             /* Device number                    */
        MSG3,               /* Message ID to create             */
        DBLK3,              /* Data Block ID                    */
        2,                  /* RT address                       */
        1,                  /* RT subaddress                    */
        10,                 /* Word Count                       */
        0,                  /* Default Message Timer            */
        ACE_BCCTRL_CHL_A,   /* use chl A options                */
        wBuffer3);          /* Data words for the async message */

    /* Create Asynchronous Op Code */
    aceBCAsyncMsgCreateMode(
        DevNum,             /* Device number                    */
        MSG5,               /* Message ID to create             */
        DBLK5,              /* Data Block ID                    */
        10,                  /* RT address                       */
        ACE_TX_CMD,         /* T/R                              */
        0x02,               /* Mode Code 2, Transmit Status Word*/
        0,                  /* Default Message Timer            */
        ACE_BCCTRL_CHL_A | ACE_MSGOPT_MODE_SA31,   /* use chl A & SA31 instead of default 0 options */
        wBuffer3);          /* Data words for the async message */

    aceBCAsyncMsgCreateBcstMode(
        DevNum,             /* Device number                    */
        MSG6,               /* Message ID to create             */
        DBLK6,              /* Data Block ID                    */
        ACE_RX_CMD,         /* T/R                              */
        0x11,               /* Mode Code 17, Sync with Data     */
        0,                  /* Default Message Timer            */
        ACE_BCCTRL_CHL_A,   /* use chl A options                */
        wBuffer3);          /* Data words for the async message */

    GetBCMsgsFromID(DevNum);

    /* Free all resources */
    wResult = aceFree(DevNum);

    if (wResult)
    {
        printf("Free ");
        PrintOutError(wResult);
        return 0;
    }

    /* Pause before program exit */
    printf(" Exit BCASYNC2 \n");

    return 0;
}
