/******************************************************************************
 \file asihpiassert.c

  Test Hardware Programming Interface (HPI) using HPI functions

  Usage: thpilinux <adapter number> <audio filenames, ...>
  With no parameters, opens adapter 0 and attempts to play file0.wav file1.wav file2.wav file3.wav

Copyright (C) 1997-2017 AudioScience, Inc. All rights reserved.

This software is provided 'as-is', without any express or implied warranty.
In no event will AudioScience Inc. be held liable for any damages arising
from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgment in the product documentation would be
   appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.
3. This copyright notice and list of conditions may not be altered or removed
   from any source distribution.

AudioScience, Inc. <support@audioscience.com>

( This license is GPL compatible see http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses )

******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <hpi.h>
#include <time.h>

// local protos
static void HandleError(hpi_err_t err);

/************************************** MAIN ***********************/
int main(int argc, char *argv[])
{
	hpi_hsubsys_t *hSubSys;
	hpi_err_t err = 0;
	uint32_t dwVersion = 0;
	uint32_t adapter_index = 0;
	int numAdapters = 0;
	uint32_t dwAdapterIndex;
	uint16_t wAdapterType;

	uint32_t i = 0;
	struct timespec req;
	struct tm thetm;
	time_t thetime;
	char s[40];

	printf("********************************************************************\n");
	printf("**      Report HPI asserts                                        **\n");
	printf("**      Press ctrl-C  to exit                                     **\n");

	// open subsystem and find adapters
	printf("********************************************************************\n");
	printf("HPI_SubSysCreate\n");
	hSubSys = HPI_SubSysCreate();
	if (hSubSys == NULL) {
		printf("hSubSys==NULL\n");
		exit(1);
	}

	err = HPI_SubSysGetVersionEx(hSubSys, &dwVersion);
	HandleError(err);
	printf("HPI_SubSysGetVersion=%x\n", dwVersion);

	err = HPI_SubSysGetNumAdapters(hSubSys, &numAdapters);
	HandleError(err);
	printf("HPI_SubSysGetNumAdapters NumberAdapters=%d\n", numAdapters);
	for (i = 0; i < numAdapters; i++) {
		err =  HPI_SubSysGetAdapter(hSubSys,
				i, &dwAdapterIndex, &wAdapterType);
		printf(" %d=%X\n", dwAdapterIndex, wAdapterType);

		err = HPI_AdapterOpen(hSubSys, dwAdapterIndex);
		HandleError(err);

		err = HPI_AdapterTestAssert(hSubSys, dwAdapterIndex, dwAdapterIndex + 1);
		HandleError(err);
	}
	printf("\n");

	if (argc > 1)		// generate some more asserts, but dont read them
		goto THPIExit;

	req.tv_sec = 0;
	req.tv_nsec = 250 * 1000000;	// 250ms delay

	while (1) {
		/* check for asserts    */
		uint16_t nMaxLoops;
		uint16_t assert_count;
		uint16_t dsp_index;
		uint32_t param1 = 0;
		uint32_t param2 = 0;
		uint32_t dsp_msg_addr = 0;
		char szAssert[100] = { "test\0" };

		for (i = 0; i < numAdapters; i++) {
			err =  HPI_SubSysGetAdapter(hSubSys,
				i, &adapter_index, &wAdapterType);

			assert_count = 1;
			nMaxLoops = 20;
			err = 0;
			// if adapter does not support asserts err returns an error
			while (assert_count && !err && nMaxLoops--) {
				err = HPI_AdapterGetAssert2(hSubSys,
					adapter_index,
					&assert_count,
					szAssert, &param1, &param2, &dsp_msg_addr, &dsp_index);
				// not all adapters handle asserts !
				if ((err != 0)
					&& (err != HPI_ERROR_INVALID_FUNC))
					HandleError(err);

				if (assert_count && !err) {
					time(&thetime);
					localtime_r(&thetime, &thetm);
					strftime(s, 40, "%j %T", &thetm);

					if (dsp_index)
						printf("%s Adap%1d DSP#%1d %s 0x%08X 0X%08X\n", s, adapter_index, dsp_index, szAssert, param1, param2);
					else
						printf("%s Adap%1d %s 0x%08X 0X%08X\n", s, adapter_index, szAssert, param1, param2);
				}
			}
		}
		if (nanosleep(&req, 0))
			break;
	}

THPIExit:
	HPI_SubSysFree(hSubSys);
	return 0;
}

/****************************** HandleError **********************/
static void HandleError(hpi_err_t err)
{
	char szError[256];
	char nK = 0;

	if (err) {
		HPI_GetErrorText(err, szError);
		printf("ERROR %d %s\n", err, szError);
		printf("press a key, <!> to exit...\n");
		nK = getchar();
		if (nK == '!')
			exit(0);
	}
}
