/*******************************************************************************
********************************************************************************
**
**  Copyright(c) 2022, Alliance for Automotive Innovation
**  Used only under license from the Alliance for Automotive Innovation. All Rights Reserved.
**
**  Project:  J1699-3
**  FileName: ClearCodes.c
**  Author:   EnGenius
**  Date:     2/25/2022
**  Email:    <support@autosinnovate.org>
**
**  Purpose:  SAE J1699-3 Vehicle OBD II Compliance Test Cases Source Code.
**            This source code is intended to run the tests described in
**            the SAE J1699-3 document in an automated manner, when compiled
**            and used with an SAE J2534-compatible pass-thru device.
**
**            File j1699.c contains information on building and running this test.
**
**  Description:
**
**  Modifications:  12/07/2022  Initial Version
**
********************************************************************************
*******************************************************************************/

#include <stdio.h>    // C Library input and output declarations
#include <stdlib.h>   // C Library general function declarations
#include <time.h>     // C Library time and date declarations
#include <windows.h>  // Windows API declarations
#include "j2534.h"    // j1699 project j2534 declarations
#include "j1699.h"    // j1699 project general declarations


// Function Prototypes
extern void DisplayPid01 ( BYTE EcuIdx, BOOL bCC );


/******************************************************************************
**
**  Function:  ClearCodes
**
**  Purpose:   Clear OBD diagnostic information
**
*******************************************************************************/
STATUS ClearCodes ( void )
{
	REQ_MSG        stReqMsg;
	BYTE           EcuIdx;
	STATUS         eRetCode = PASS;  // saves the return code from function calls

	unsigned short IMReadinessCount = 0;
	unsigned short IMRPosAckCount = 0;
	unsigned short PositiveAckCount = 0;


	// Reset the global DTC data
	gbDTCPending = FALSE;
	gbDTCStored  = FALSE;

	IMReadinessCount = 0;
	IMRPosAckCount   = 0;
	PositiveAckCount = 0;

	// Send SID 4 request
	stReqMsg.SID    = 0x04;
	stReqMsg.NumIds = 0;
	if ( (eRetCode = RequestSid ( &stReqMsg, REQ_MSG_ALLOW_NO_RESPONSE )) != FAIL )
	{
		eRetCode = PASS;  // mark it as PASS, since ERROR can get here too

		if ( gNumOfECUsResp == 0 )
		{
			if ( gbEngineRunning == FALSE )
			{
				Log ( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				      "No response to SID $04 request\n" );
				eRetCode = FAIL;
			}
			else
			{
				Log ( WARNING, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				      "No response to SID $04 request\n" );
			}
		}
		else
		{
			// all ECUs must respond with the same ackowledgement (positive or negative) with engine running
			for ( EcuIdx = 0;
			      EcuIdx < gNumOfECUs;
			      EcuIdx++ )
			{
				if ( (gstEcuSIDData[EcuIdx].Pid01.Data[1] & 0x03) != 0x00 ||
				     (gstEcuSIDData[EcuIdx].Pid01.Data[2] & 0xFF) != 0x00 )
				{
					IMReadinessCount++;
				}

				if ( gstResponse[EcuIdx].ClrDTCSize > 0 &&
				     gstResponse[EcuIdx].ClrDTC[0] == 0x44 )
				{
					if ( gbEngineRunning == TRUE  &&
					     ( (gstEcuSIDData[EcuIdx].Pid01.Data[1] & 0x03) != 0x00 ||
					       (gstEcuSIDData[EcuIdx].Pid01.Data[2] & 0xFF) != 0x00 ) )
					{
						IMRPosAckCount++;
					}
					else
					{
						PositiveAckCount++;
					}
					Log ( INFORMATION, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
					      "ECU %X  Positive response to SID $04 request\n",
					     GetEcuId ( EcuIdx ) );
				}

				if ( gbEngineRunning == TRUE &&
				     (gstEcuSIDData[EcuIdx].Pid01.Data[1] != 0x00 ||
				      gstEcuSIDData[EcuIdx].Pid01.Data[2] != 0x00) )
				{
					DisplayPid01 ( EcuIdx, TRUE );
				}
			}

			// IF the number of responding ECUs is greater than the user entered number
			// OR there are no responding ECUs.
			if ( gNumOfECUsResp > gUserNumOfECUs  ||
			     gNumOfECUsResp == 0 )
			{
				Log ( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				      "Incorrect number of responses to SID $04 request\n" );
				eRetCode = FAIL;
			}

			// Check that all ECUs with IM Readiness response the same
			// (all positive or all negative) with engine running
			if ( gstUserInput.eComplianceType != CNOBD_NO_IUMPR )
			{
				if ( gbEngineRunning == TRUE &&
				     IMReadinessCount != 0 &&
				     ((PositiveAckCount != 0 ||
				       IMRPosAckCount != 0) &&
				      IMReadinessCount != IMRPosAckCount) )
				{
					Log ( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
					      "Received both positive and negative responses from ECUs containing IM Readiness.\n" );
					eRetCode = FAIL;
				}
				else if ( gbEngineRunning == FALSE &&
				          gNumOfECUsResp != (unsigned long)(PositiveAckCount + IMRPosAckCount) )
				{
					Log ( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
					      "Not all ECU responses positive.\n" );
					eRetCode = FAIL;
				}
			}
		}
	}

	// Delay after request to allow time for codes to clear
	Sleep ( 2000 );

	return eRetCode;
}
