/*******************************************************************************
*  (c) synertronixx GmbH
*  Vahrenwalder Str. 7
*  D-30165 Hannover
*  Tel. : 0511 / 93 57 670
*  Fax. : 0511 / 93 57 679
*  Web  : www.synertronixx.de
*  eMail: info@synertronixx.de
* ----------------------------
* Name          : cptest.c
* Version       : 1.01
* Datum         : 17.03.2008
* Author        : Blaschke
* Description   : Example for CAN2Web-Professinoal for using synertronixx
*                 CAN2Web-Professional CAN driver:
*                 N CAN messages will be send at a baudrate of rate kBit/s 
*                 and all incomming messages wil be displayed.
*                 When N is negativ program runs until -N Messages have been received,
*                 no messages will be send 
* program call  : cptest.exe N rate ; e.g.: cptest.exe 23 100 (send 23 messages at 100 kBit/s) 
* *****************************************************************************/

//LINUX-Header
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

// CAN2Web-Professional Header
#include "can_driver.h"


// CAN settings
int fd_can;                             // file descriptor for CAN kernel driver
unsigned int      can_baudrate = 100;   // baudrate 
unsigned long int can_mask=0x1FFFFFFFL; // CAN-mask-register (0x00..0x7FF) for CAN 2.0A
                                        // and (0x00000000..0x1FFFFFFF)    for CAN 2.0B
unsigned long int can_code=0x1FFFFFFFL; // CAN-Code-Register (0x00..0x7FF) for CAN 2.0A
                                        // and (0x00000000..0x1FFFFFFF)    for CAN 2.0B
int               can_extended=1;         // CAN mode: 0=CAN2.0A, 1=CAN2.0B
int               can_btr_on=0;           // 1=direct access to baudrate register 
unsigned int      can_btr;              // value for baudrate register


char* appl_name="CAN2Web Professional Test";  // Application name for debug messages

// for sending/receiving CAN-Messages
struct TCANMsg  can_out;                 // CAN-Message-stucture for sending data
struct TCANMsgT can_in;                  // CAN-Message-stucture for receiving data

unsigned char     can_error;             // Buffer for CAN error state
long int n=1;                            // Loop counter
int i;                                   // counter
int m;                                   // counter
long int n_old;                          // counter
unsigned int nr_msgs;                    // nr. of messages in receive buffer 



/******************************************************************************
Function:    CANPrintMsgT
Description: print a CAN msg. type TCANMsgT
Parameter:   can_msg: ptr to struct TCANMsg
Return:      none
Date:        11.10.2005
Changes:     
******************************************************************************/
void
CANPrintMsgT(struct TCANMsgT* can_msg)
{
  int nr=0;
  char str[200], str2[20];
 
  sprintf(str,"%10ld.%06ld  ID:%08lX RTR:%d Len:%d ", can_msg->TIMES, can_msg->TIMEUS,
          can_msg->ID, can_msg->RTR, can_msg->LEN);

  if (can_msg->RTR==0)
  { 
    for (nr=0;nr<=can_msg->LEN-1;nr++)
    { 
      sprintf(str2, " %02X", can_msg->DATA[nr]);
      strcat(str,str2);
    }
  }
  strcat(str,"\n");
  printf(str);

}

/******************************************************************************
Function:    CANSetParameter
Description: set parameter for CAN-bus
Parameter:   none
Return:      1, when setting was sucessfull
             -1, otherwise
Date:        19.10.2005
Changes:     
******************************************************************************/
int
CANSetParameter(void)
{ // Init CAN-Bus
  int ret_value;
  struct CANSettings cs;
 
  // copy data to CANSettings structure
  cs.mode            = (unsigned char)can_extended;              
  if(can_btr_on==1)
    cs.baudrate        = can_btr; 
  else
    cs.baudrate        = can_baudrate;          
  cs.baudrate_to_btr = (unsigned char)can_btr_on;  
  cs.mask            = can_mask;               
  cs.code            = can_code;                                                 

  // call kernel driver
  ret_value = ioctl(fd_can, CAN_SET_SETTINGS, &cs);

  return ret_value;
}

/******************************************************************************
Function:    CANSetOnOff
Description: switch CAN-bus on/off
Parameter:   state: 0 CAN off, 1 CAN on
Return:       1, when setting was sucessfull
             -1, otherwise
Date:        19.10.2005
Changes:     
******************************************************************************/
int
CANSetOnOff(int state)
{                                   
  return ioctl(fd_can, CAN_SET_ON_OFF, state);
}


/******************************************************************************
Function:    CANGetDriverInfo
Description: get some information from CAN driver
Parameter:   none
Return:       1, when reading was sucessfull
             -1, otherwise
Date:        19.10.2005
Changes:     
******************************************************************************/
int
CANGetDriverInfo(void)
{ 
  int ret_value;
  struct DriverInfo dinfo;

  ret_value = ioctl(fd_can, CAN_GET_DRIVER_INFO, &dinfo);
  usleep(500000);
  if(ret_value==1)
  { 
    printf("\nDriver info:\n");
    printf("Name: '%s'\n",  dinfo.version);
    printf("Received since last parameter setting :%lu\n",   dinfo.total_rcv);
    printf("Send since last parameter setting     :%lu\n",   dinfo.total_snd);
    printf("CAN-msg. Receive buffer size          :%lu\n",   dinfo.rcv_buffer_size);
    printf("CAN-msg. Send buffer size             :%lu\n\n", dinfo.snd_buffer_size);
  }
  else
    printf("CAN driver Info not available\n");
 usleep(1000000);
  return ret_value;
}

/******************************************************************************
Function:    CANGetSettings
Description: get the actual settings from CAN driver
Parameter:   none
Return:      1, when reading was sucessfull
             0, otherwise
Date:        01.09.2005
Changes:     
******************************************************************************/
int
CANGetSettings(void)
{ 
  int ret_value;
  struct CANSettings cs;

  ret_value = ioctl(fd_can, CAN_GET_SETTINGS, &cs);
  usleep(500000);
  if(ret_value==1)
    printf("Baudrate=%d BTR=%d mode=%d mask=0x%08X code=0x%08X\n", 
           cs.baudrate, cs.baudrate_to_btr, cs.mode, cs.mask, cs.code);
  else
    printf("CAN settings not available\n");
  usleep(500000);
  return ret_value;
}

int CANSetDebugMode(unsigned long int debug) {
	int ret_value;

	ret_value = ioctl(fd_can, CAN_SET_DEBUGMODE, debug);
	if (ret_value == 1) {
		if (debug == 0)
			printf("Debug Mode disabled!\n");
		else
			printf("Debug Mode enabled!\n");
	}

	return ret_value;
}


/*******************************************************************************
* M A I N
*******************************************************************************/

int main(int argc, char *argv[])
{
  int result, i;
  int debug = 0;

  printf("\n\n%s: start of test program for CAN bus!\n", appl_name);

  // get nr. of CAN-Messages to send and baudrate from arguments
  if (argc==2) {
    if (sscanf (argv[1], "%ld", &debug) == 1)
      if (debug == 1)
        printf("Debug on\n");
      else
        printf("Debug off\n");
  } else {
    printf("arguments error! call: test 'debug on/off' exit program!\n");
    exit(1);
  }

   // open CAN devices   
  fd_can = open("/dev/can0", O_RDWR);
  if (fd_can<0)
  {
    printf("can't open CAN device, errno=%d %s, Exit program\n", errno, strerror(errno));
    close(fd_can);
    exit(1);
  }

  printf("Setting Debug Mode\n");
  result = CANSetDebugMode((unsigned long int)debug);
  printf("Set Debug Mode result = %d\n", result);
  if (result != 1) {
    printf("can't set Debug Mode, Exit program\n");
    close(fd_can);
    exit(1);
  }
  
  printf("\n%s: shutdown program\n", appl_name);

  close(fd_can);

  printf("%s: end of program\n", appl_name);

  return 0;
}





