/******************************************************************************
 *
 * RTips Technologies, Bangalore (www.rtipsonline.com)
 *
 * This sample demonstrates a technique to setup AceXtreme boards to auto 
 * increment a data word value of a specific message using ACE_OPCODE_INC opcode.
 *
 * Many portions of this file are adapted from samples provided in
 * the AceXtreme SDK (BU-69092Sx) of M/s. Data Device Corporation
 *
 * Author: Ganesh Okade
 * Last updated: Apr 13, 2026
 ******************************************************************************/
#pragma warning(disable : 4996)
#define DEVNUM		0
#define MAX_MSG		10		/* number of messages per frame */
#define LOOPS		-1		/* number of major frames */
#define FRAME_TIME	5		/* 500 microseconds */

/* Include Files */
#include <windows.h>
#include "stdemace.h"
#include <conio.h>


/* define Memory Words and Objects */
#define MEM_OBJ_DBLK		1		/* Will point to DBLK1 */
#define MEM_OBJ_MSGBLK		2		/* Will point to MSG1 */

/* data block IDs increment from here */
#define DBLK1		1

/* message IDs increment from here */
#define MSG1		1

/* define frame constants */
#define MJR			1
#define MNR			2

/* define opcodes */
#define OP_MSG1    	10

#define OP_MNR		200

#define OP_INC1		100

U16BIT wBuffer[64] =
{  0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};

MSGSTRUCT globalmsg;

static void DisplayDecodedMsg(U32BIT nMsgNum,MSGSTRUCT *pMsg);

/*-----------------------------------------------------------------------
Name:          PressAKey()

Description:   Allows application to pause to allow screen contents to be read.

In             none
Out            none
------------------------------------------------------------------------*/
static void PressAKey(void)
{
   printf("\nPress <ENTER> to continue...");
   getch();
}

/*-----------------------------------------------------------------------
Name:          PrintHeader

Description:   Prints the sample program header.

In             none
Out            none
------------------------------------------------------------------------*/
static void PrintHeader(void)
{
   U16BIT     wLibVer;

   wLibVer = aceGetLibVersion();
   printf("*********************************************\n");
   printf("Enhanced Mini-ACE 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("Copyright (c) 2007 Data Device Corporation  *\n");
   printf("*********************************************\n");
   printf("BCDemo.c BC operations [Basic Op Demo]      *\n");
   printf("*********************************************\n\n");
}

/*-----------------------------------------------------------------------
Name:          PrintOutError

Description:   This function prints out errors returned from library functions.

In             nResult = 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 to
               the screen.

In             nMsgNum = The number of the message.
In             pMsg    = The relavant information of the message.
Out            none
------------------------------------------------------------------------*/
static void DisplayDecodedMsg(U32BIT nMsgNum,MSGSTRUCT *pMsg)
{
   U16BIT i;
   char szBuffer[100];
   U16BIT wRT,wTR1,wTR2,wSA,wWC;

   /* Display message header info */
   printf("BC 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("\nBC            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("\nBC        CMD2 %04X --> %s",pMsg->wCmdWrd2,szBuffer);
   }

   /* Display transmit status words */
   if((wTR1==1) || (pMsg->wBlkSts&ACE_MT_BSW_RTRT))
   {
      if(pMsg->wStsWrd1Flg)
         printf("\nBC            STA1 %04X",pMsg->wStsWrd1);
   }

   /* Display Data words */
   for(i=0; i<pMsg->wWordCount; i++)
   {
      if(i==0)
         printf("\nBC            DATA ");

      printf("%04X  ",pMsg->aDataWrds[i]);

      if((i%8)==7)
         printf("\nBC                 ");
   }

   /* Display receive status words */
   if((wTR1==0)  && !(pMsg->wBlkSts&ACE_MT_BSW_RTRT))
   {
      if(pMsg->wStsWrd1Flg)
         printf("\nBC            STA1 %04X",pMsg->wStsWrd1);
   }
   if(pMsg->wStsWrd2Flg)
      printf("\nBC            STA2 %04X",pMsg->wStsWrd2);

   /* Display Error information */
   if(pMsg->wBlkSts & ACE_MT_BSW_ERRFLG)
      printf("\nBC ERROR: %s",aceGetBSWErrString(ACE_MODE_MT,pMsg->wBlkSts));
   printf("\n\n");
}

/*-----------------------------------------------------------------------
Name:          main

Description:   Program entry point.

In             none
Out            none
------------------------------------------------------------------------*/
int main(void)
{
    /* Variables */
	S16BIT DevNum	       = 1;
    S16BIT wResult		   = 0;
    S16BIT aOpCodes[100]   = {0};
    U32BIT dwHBufLost	   = 0;
    U32BIT dwMsgCount	   = 0;
    U32BIT dwCurCount	   = 0;
	char s = 0;
    int i = 0;

    /* Print out sample header */
    PrintHeader();

	/* Get Logical Device # */
	printf("\nSelect BC Logical Device Number (0-31):\n");
	printf("> ");

	scanf("%hd", &DevNum);

    /* Initialize Device */
    wResult = aceInitialize(DevNum, ACE_ACCESS_CARD, ACE_MODE_BC,0, 0, 0);
    if(wResult)
    {
        printf("Initialize ");
        PrintOutError(wResult);
        PressAKey();
        return 0;
    }


	/* Create Host Buffer */
    aceBCInstallHBuf(DevNum,(MAX_MSG)*40*256);

	/* Create data blocks */
	aceBCDataBlkCreate(DevNum, DBLK1,32, wBuffer, 32);

	/* Create message blocks, etc */
	aceBCMsgCreateBCtoRT(
		DevNum,				/* Device number                    */
		MSG1, 				/* Message ID to create             */
		DBLK1,				/* Message will use this data block */
		1,					/* RT address                       */
		1, 					/* RT subaddress                    */
		32,					/* Word count                       */
		0, 					/* Default message timer            */
		ACE_BCCTRL_CHL_A);

   	/* Create XEQ opcode for messages */
	aceBCOpCodeCreate(DevNum, OP_MSG1, ACE_OPCODE_XEQ, ACE_CNDTST_ALWAYS, MSG1, 0, 0);

	/* Create Memory Object on the 1st word in data block ID 1 */
	acexBCMemObjCreate(DevNum, MEM_OBJ_DBLK, DBLK1, ACEX_BC_MEMITEM_DATA, 0);	

	/* Create opcodes for incrementing memory object */
    aceBCOpCodeCreate(DevNum, OP_INC1, ACE_OPCODE_INC, ACE_CNDTST_ALWAYS, MEM_OBJ_DBLK, 0, 0);       /* Increment value of first word in DBLK1 */

	aOpCodes[i++] = OP_MSG1;			/* Send Message 1 */
	aOpCodes[i++] = OP_INC1;            /* Increment data word */
    
	aceBCFrameCreate(DevNum, MNR, ACE_FRAME_MINOR, aOpCodes, i, 0,0);

   	/* Create CAL opcode that will call minor frame from major */
	aceBCOpCodeCreate(DevNum, OP_MNR, ACE_OPCODE_CAL, ACE_CNDTST_ALWAYS, MNR, 0, 0);

	/* Create Major Frame */
   	aOpCodes[0] = OP_MNR;
	aceBCFrameCreate(DevNum, MJR, ACE_FRAME_MAJOR, aOpCodes, 1, FRAME_TIME, 0);

	printf("\nThe BC (DevNum %d) will now run a frame with two messages until stopped by the user. \n", DevNum, LOOPS);

   	/* Start BC */
   	aceBCStart(DevNum,MJR,LOOPS);
	Sleep(1);

	printf("\n");
   
	while(s != 'q')
    {
		printf("Enter a 1 to skip Msg1 or a 0 to send it (default) and 'q' to exit. \n");
		printf(">");
		s = getch();

		if( (s != 'q') && ( wBuffer[0] != s))
		{
			wBuffer[0] = (s - '0');
			wResult = aceBCDataBlkWrite(DevNum, DBLK1,wBuffer, 32, 0);
			if(wResult)
			{
				printf("Error write to data block\n");
			}			
			
			getchar();
			printf("\n");
		}
        Sleep(1);		

    }

	/* Stop BC */
   	aceBCStop(DevNum);

   	/* Free all resources */
   	wResult = aceFree(DevNum);
   	if(wResult)
   	{
    	printf("Free ");
      	PrintOutError(wResult);
      	return 0;
   	}

   	return 0;
}

