/***********************************************************************/
/*                    Demo source for esd NTCAN-API                    */
/*                                                                     */
/*       Copyright by Shanghai ESD Electric Technology Co., Ltd.       */
/*---------------------------------------------------------------------*/
/*         Filename:      autoanswer.c                                 */
/*         Date:          2022-1-5                                     */
/*         Language:      ANSI C                                       */
/*         Targetsystem:  Windows 10, Linux                            */
/*         Purpose:       Demostrate auto answer transmitting CAN      */
/*                        message, triggered by receiving desired      */
/*                        rtr message, with NTCAN TX Obj Mode.         */
/*         Author:        Bob Tu                                       */
/*---------------------------------------------------------------------*/ 
/* Revision history:                                                   */
/*---------------------------------------------------------------------*/
/* v1.0    Birth of module                                             */
/* v1.1    (1)Check if the interface supports NTCAN_FEATURE_SCHEDULING */
/*         (2)Check if the interface supports canIdRegionAdd(). If not,*/ 
/*         use canIdAdd() instead.                                     */
/***********************************************************************/

#include <stdio.h>
#include "ntcan.h"

int main()
{
  int net=0; /* logical net number */
  uint32_t mode=0; /* mode bits for canOpen */
  int32_t txqueuesize=8; /* maximum number of messages to transmit */
  int32_t rxqueuesize=8; /* maximum number of messages to receive */
  int32_t txtimeout=1000; /* timeout for transmit in ms */
  int32_t rxtimeout=10000; /* timeout for receiving data in ms */
  NTCAN_HANDLE rxhandle; /* can handle returned by canOpen() */
  NTCAN_RESULT retvalue; /* return values of NTCAN API calls */
  uint32_t baud=NTCAN_BAUD_1000; /* configured CAN baudrate */
  int32_t lenRcv;
  CMSG cmsgAutoAnswer; 
  CMSG cmsgRcv; 
  uint32_t idCnt = 0x800; 
  uint32_t id;
  CAN_IF_STATUS cstatus;
/* ############################################################### */
  retvalue = canOpen(net,
                      mode,
                      txqueuesize,
                      rxqueuesize,
                      txtimeout,
                      rxtimeout,
                      &rxhandle);
  if (retvalue != NTCAN_SUCCESS)
  {
    printf("canOpen() failed with error %d!\n", retvalue);
    return(-1);
  }
/* ############################### ################################ */
  retvalue = canSetBaudrate(rxhandle, baud);
  if (retvalue != NTCAN_SUCCESS)
  {
    printf("canSetBaudrate() failed with error %d!\n", retvalue);
    canClose(rxhandle);
    return(-1);
  }

/* ############################### ################################ */
  retvalue = canStatus(rxhandle, &cstatus);
	if (retvalue != NTCAN_SUCCESS)
	{
		printf("canStatus() failed with error %d!\n", retvalue);
		canClose(rxhandle);
		return(-1);
	}
	if (cstatus.features & NTCAN_FEATURE_SCHEDULING)
		printf("NTCAN_FEATURE_SCHEDULING is supported!\n");
	else{
		printf("NTCAN_FEATURE_SCHEDULING is NOT supported!\n");
		canClose(rxhandle);
		return(-1);
	}
/* ############################################################### */
/* All 11-bit ID CAN messages can be received */
  if(cstatus.features & NTCAN_FEATURE_SMART_ID_FILTER)
  {
    printf("canIdRegionAdd() is used!\n");
    retvalue = canIdRegionAdd(rxhandle, 0, &idCnt);
    if (retvalue != NTCAN_SUCCESS)
    {
      printf("canIdRegionAdd() failed with error %d!\n", retvalue);
      canClose(rxhandle);
      return(-1);
    }
  } else {
    printf("canIdAdd() is used!\n");
    for (id=0;id<0x800;id++)
      retvalue = canIdAdd(rxhandle, id);
    if (retvalue != NTCAN_SUCCESS)
    {
      printf("canIdAdd() failed with error %d!\n", retvalue);
      canClose(rxhandle);
      return(-1);
    }
  }
/* ############################################################### */  
  cmsgAutoAnswer.id=0x3; /*rtr message with ID=0x3 will be auto answered.*/
  cmsgAutoAnswer.len=1; 
  cmsgAutoAnswer.data[0]=0x00;

  retvalue = canIoctl(rxhandle, NTCAN_IOCTL_TX_OBJ_CREATE, &cmsgAutoAnswer);
  if (retvalue != NTCAN_SUCCESS)
    printf("NTCAN_IOCTL_TX_OBJ_CREATE fail!\n");

  retvalue = canIoctl(rxhandle, NTCAN_IOCTL_TX_OBJ_AUTOANSWER_ON, &cmsgAutoAnswer); 
  if (retvalue != NTCAN_SUCCESS)
    printf("NTCAN_IOCTL_TX_OBJ_AUTOANSWER_ON fail!\n");

  printf("Send CAN msg with 11-bit ID to: \n");
  printf("ID=0: \t\tExit program\n");
  printf("ID=1: \t\tSwitch ON auto answer\n");
  printf("ID=2: \t\tSwitch OFF auto answer\n");
  printf("ID=3 + RTR: \tGet auto answered CAN msg recording\n");
  printf("\t\tthe total number of received CAN msgs. \n\n");

  while(1)
  {
    lenRcv = 1;
    retvalue = canRead(rxhandle, &cmsgRcv, &lenRcv, NULL);
    if (retvalue == NTCAN_RX_TIMEOUT)
    {
      printf("canRead() returned timeout\n");
      continue;
    }
    else if(retvalue != NTCAN_SUCCESS)
    {
      printf("canRead() failed with error %d!\n", retvalue);
    }
    else
    {    
      printf("Id of received message :%x!\n", cmsgRcv.id);
      if (cmsgRcv.id == 0){
        printf("Exit program!\n");
        break;
      }

      if (cmsgRcv.id == 1){
        retvalue = canIoctl(rxhandle, NTCAN_IOCTL_TX_OBJ_AUTOANSWER_ON, &cmsgAutoAnswer); 
        if (retvalue != NTCAN_SUCCESS)
          printf("NTCAN_IOCTL_TX_OBJ_AUTOANSWER_ON fail!\n");
        else
          printf("Auto answer switched ON!\n");
      }
      
      if (cmsgRcv.id == 2){
        retvalue = canIoctl(rxhandle, NTCAN_IOCTL_TX_OBJ_AUTOANSWER_OFF, &cmsgAutoAnswer);
        if (retvalue != NTCAN_SUCCESS)
          printf("NTCAN_IOCTL_TX_OBJ_AUTOANSWER_OFF failed with error %d!\n", retvalue);
        else
          printf("Auto answer switched OFF!\n");
      }
      
      /* Update cmsgAutoAnswer.data[0] with the value of the total number of 
      received CAN messages by the program. */
      if (cmsgAutoAnswer.data[0] == 0xff)
      {
        cmsgAutoAnswer.data[0] = 0;          
        printf("Reset auto answered msg data!\n");
      }else{
        cmsgAutoAnswer.data[0] += (uint8_t) lenRcv;
      }
      
      retvalue = canIoctl(rxhandle, NTCAN_IOCTL_TX_OBJ_UPDATE, &cmsgAutoAnswer);
      if (retvalue != NTCAN_SUCCESS)
        printf("NTCAN_IOCTL_TX_OBJ_UPDATE failed with error %d!\n", retvalue);
    }
  }  
/* ############################################################### */
  retvalue = canIdRegionDelete(rxhandle, 0 , &idCnt);
  if (retvalue != NTCAN_SUCCESS)
	  printf("canIdRegionDelete() failed with error %d!\n", retvalue);
/* ############################################################### */
  retvalue = canClose (rxhandle);
  if (retvalue != NTCAN_SUCCESS)
	  printf("canClose() failed with error %d!\n", retvalue);
/* ############################################################### */
  return(0);
}
