/**
 * 	\file: 	main.cpp
 *
 *  \brief 	ARM side main routine for DSP Hello World application.
 *  		The ARM sets itself up, sends a message to the DSP,
 *  		and then waits for a return message before exiting.
 *
 *     o  0
 *     | /       Copyright (c) 2005-2010
 *    (CL)---o   Critical Link, LLC
 *      \
 *       O
 */

#include "dspapp.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "ipc_inbound.h"
#include "ipc_outbound.h"

using namespace MityDSP;

// Forward declarations
int handleInboundMessage(void *Buffer, uint16_t Length, void *UserArg);

volatile bool gbDone = false;

int main(int argc, char* argv[])
{
	// tcDspApp class for booting and loading the DSP
	tcDspApp* 		lpDspApp = NULL;
	// Used to setup handling of inbound messages from DSP
	tcIPCInbound* 	lpMessageInbound  = NULL;
	// Used to send messages to the DSP
	tcIPCOutbound* 	lpMessageOutbound  = NULL;
	// Message to send to the DSP
	char			lpMessage[] = "Hello DSP";
	// Pointer to buffer obtained from dsplink
	char*			lpMessageBuffer = NULL;
	// Message from standard input
	char 			lpUsrMsg[180] = {0};

	// Check application usage
	if (argc < 2)
	{
		printf("usage: HelloWorld dsp_image.out\n");
		return -1;
	}

	// Create the DspApp object
	lpDspApp = new tcDspApp();

	// Load the DSP.out file
	printf("Loading file %s\n", argv[1]);
	lpDspApp->LoadApp(argv[1]);

	printf("Starting application.\n");

	// Create the object to handle incoming messages from the DSP
	lpMessageInbound =  new tcIPCInbound((char*)"GPPMSGQ1");

	if (NULL != lpMessageInbound)
	{
		// Register the callback for handling messages from the DSP
		lpMessageInbound->Register(handleInboundMessage, (void*)NULL);

		// Intiailize the inbound controller to create the thread that handles the callbacks
		lpMessageInbound->Initialize();
	}

	// Create the object used to send messages to the DSP
	lpMessageOutbound = new tcIPCOutbound((char*)"DSPMSGQ0");

	// Wait for the DSP to finish initialization
	while(false == gbDone);

	// Reset bool in prep for next receive message from DSP
	gbDone = false;

	// Get a buffer for a message to the DSP
	lpMessageBuffer = (char*)lpMessageOutbound->GetBuffer(strlen(lpMessage)+1);

	// Copy the message to the dsplink buffer
	strcpy(lpMessageBuffer, lpMessage);

	// Send the message to the DSP
	printf("Sending a message to the DSP.\n");
	lpMessageOutbound->SendMessage(lpMessageBuffer);

	// Wait for a message to be received from the DSP or for user to quit
	printf("Waiting for DSP response (type \'q\' to quit)...\n");
	while(gbDone == false && lpUsrMsg[0] != 'q')
	{
		fgets(lpUsrMsg, 180, stdin);
	}

	printf("Exiting application.\n");

	// Stop the DSP application from running
	lpDspApp->StopApp();

	// Cleanup
	// Commented out because deletes throw Assert errors.
	//delete lpDspApp;
	//delete lpMessageInbound;
	//delete lpMessageOutbound;

	return 0;
}

/**
 *	Handle inbound messages from the DSP.
 *
 *	\param apBuffer		Pointer to the buffer containing the message.
 *	\param anLength 	The length of the message.
 *	\param apUserArg	User defined argument.
 *
 *	\return 0.
 */
int handleInboundMessage(void *apBuffer, uint16_t anLength, void *apUserArg)
{
	printf("ARM received a message from the DSP:\n");

	// Print the message we received
	printf("\tDSP Message = \"%s\"\n", (char *)apBuffer);

	// Notify the main function that we have received a message from the DSP and are done
	gbDone = true;

	return 0;
}

