/*********************************************************/
/* ON Semiconductor                                      */
/* NCV7383 Evaluation KIT                                */
/*                                                       */
/* HOST.C                                                */
/* Host command processor                                */
/*                                                       */
/* Originally created by: Jozef Polak                    */
/* Modified by: Filip Brtan                              */
/* Date: 30.07.2012                                      */
/*********************************************************/

// NOTES:
// - Using a function table for command processing is quite neat.
//   Commands in the same group usually have a lot in common so they can be processed in one function with common local variables, etc.
// - There is a limitation to function pointers: Functions cannot have more parameters than will fit in registers.
//   That is why I use the global variables for the command data.

// REFERENCES:
// [1] Keil Software, Inc. Function Pointers in C51. Application Note 129.
//     http://www.keil.com/appnotes/files/apnt_129.pdf.

#include <stddef.h> 
#include <hidef.h>
/** S12X derivative information */ 
#include "mc9s12xf512.h"  
#include "typedefs.h"
#include "cpu.h"
#include "GPIO_macros.h"
#include "SCI0.h"
#include "Host.h"
#include "HostComm.h"
#include "CAN.h"
#include "FlexRay_CC.h"

/** Standard and driver types */
#include "Fr_UNIFIED_types.h"  

/** UNIFIED driver implementation */         
#include "Fr_UNIFIED.h"        
         
/** Configuration data for the FlexRay node */
#include "Fr_UNIFIED_cfg.h"

/** FlexRay CC function prototypes */
#include "FlexRay_CC.h"

/** FlexRay Bus Driver definitions*/
#include "FlexRay_BD.h"

#include "ADC.h"

#include "Interrupts.h"

#pragma DATA_SEG HOST_DATA
#pragma CODE_SEG HOST_CODE


Fr_return_type return_val;
word voltage_VBAT; // Voltage in mV


word Status_array[10];
/***********************************/
/* Communication Packet Definition */
/***********************************/

/*** Command Group ***/
#define CMG_RESERVED                   0x00 
#define CMG_GENERAL                    0x01
#define CMG_ADC                        0x02
#define CMG_BOARD                      0x03
#define CMG_FR_BD                      0x04
#define CMG_FR_CC                      0x05
#define CMG_CAN                        0x06

 

/*** Commands ***/

// Group: GENERAL
#define CMD_GENERAL_READ_SIGNATURE     0x81
#define CMD_GENERAL_READ_NODE_ADDRESS  0x82


// Group: ADC
#define CMD_ADC_VCC_Q                  0x87
#define CMD_ADC_VIO_Q                  0x88
#define CMD_ADC_VCC_BD_Q               0x89
#define CMD_ADC_VIO_BD_Q               0x8A
#define CMD_ADC_VBAT_Q                 0x8B


// Group: BOARD
#define CMD_BOARD_ADDRESS_Q            0x81
#define CMD_BOARD_LEDS_Q               0x82
#define CMD_BOARD_LEDS                 0x03
#define CMD_BOARD_RESET                0x06


// Group: FR_BD
#define CMD_SET_LOW_LEVEL_CFG          0x01
#define CMD_FR_CHANGE_MODE             0x02
#define CMD_FR_STATUS_REGISTER_Q       0x83
#define CMD_SET_PIN_STBN               0x05
#define CMD_SET_PIN_BGE                0x06
#define CMD_SET_PIN_TXEN               0x0C
#define CMD_SET_PIN_TXD                0x0D
#define CMD_FR_STATUS_DOUBLE_READ      0x0F
#define CMD_SET_PIN_CSN                0x14
#define CMD_SET_PIN_SCK                0x15
#define CMD_SPI_ENABLED                0x17


// Group: FR_CC
#define CMD_FR_CC_INIT                 0x01
#define CMD_FR_CC_START_COMM           0x02
#define CMD_FR_CC_STOP_COMM            0x03
#define CMD_FR_CC_SEND_WAKEUP          0x04
#define CMD_FR_CC_UPDATE_MB            0x05
#define CMD_FR_CC_GET_POC_STATE_Q      0x86
#define CMD_FR_CC_PORTS_INIT           0x07
#define CMD_FR_CC_STRB_SET             0x08
#define CMD_FR_CC_HW_CONFIG            0x09
#define CMD_FR_CC_LOW_LEVEL_CONFIG     0x0A
#define CMD_FR_CC_PAYLOAD_LENGTH       0x0B
#define CMD_FR_CC_PAYLOAD_DATA         0x0C
#define CMD_FR_CC_TX_BUFFER_CFG        0x0D
#define CMD_FR_CC_RX_BUFFER_CFG        0x0E
#define CMD_FR_CC_BUFFER_CFG_SET       0x0F
#define CMD_FR_CC_BUFFER_CFG           0x10
#define CMD_FR_CC_SEND_REM_WAKEUP      0x11
#define CMD_FR_CC_SEND_TSS             0x12
#define CMD_FR_CC_SEND_TSS_HIGH        0x13
#define CMD_FR_CC_SEND_TSS_LOW         0x14
#define CMD_FR_CC_SEND_TSS_HIGH_LOW    0x15
#define CMD_FR_CC_SEND_TSS_50_50       0x16
#define CMD_FR_CC_SEND_TSS_10_90       0x17
#define CMD_FR_CC_SEND_TWO_50          0x18
#define CMD_FR_CC_SEND_RWU_VALID       0x19
#define CMD_FR_CC_SEND_RWU_ALT         0x1A
#define CMD_FR_CC_SEND_RWU_SHORTED     0x1B
#define CMD_FR_CC_SEND_RWU_FRAME       0x1C
#define CMD_FR_CC_SEND_RWU_SHORT_IDLE  0x1D
#define CMD_FR_CC_SEND_RWU_LONG_IDLE   0x1E
#define CMD_FR_CC_SEND_RWU_SHORT_LOW1  0x1F
#define CMD_FR_CC_SEND_RWU_SHORT_LOW2  0x20
#define CMD_FR_CC_SEND_CURRENT_MEAS    0x21
#define CMD_FR_CC_SEND_RWU_FRAME_WRONG 0x22
#define CMD_FR_CC_SEND_HIGH            0x23
#define CMD_FR_CC_SEND_LOW             0x24
#define CMD_FR_CC_SEND_RWU_VALID_LONG  0x25


// Group: CAN
#define CMD_CAN_FIND_NODES             0x01
#define CMD_CAN_TEST_LED               0x02



/*** Command Processing Functions ***/
static void hostcomm_command_general    (byte command);
static void hostcomm_command_adc        (byte command);
static void hostcomm_command_board      (byte command);
static void hostcomm_command_fr_bd      (byte command);
static void hostcomm_command_fr_cc      (byte command);
static void hostcomm_command_can        (byte command);




// NOTE:
// I wanted to use the typedef-ed function types to directly define the functions:
//   static THOST_COMMANDGROUP hostcomm_command_spi;
// instead of the direct declaration:
//   static void hostcomm_command_spi (byte command);
// Doing so causes a number mysterious problems:
// - It is not possible to mix the typedef-ed and the direct declaration. The compiler creates different symbols for them (one has "_", one does not)
//   and the linker then isn't able to match them (unresolved external).
// - The typedef-ed declaration does weird things to local vairables of such a function. 
//   By default, they are in "x constant" mspace (nobody seems to know what that is). If declared explicitly as data, they are compiled as static variables.
// These are the reasons why I abandoned this approach.

/* Table of Command Processing Function Pointers */
// NOTE: The table must be stored in CODE space! This ensures that the compiler/linker build correct overlay tree, see [1]. 
THOST_COMMANDGROUP *host_command [] = {
  NULL,
  hostcomm_command_general,
  hostcomm_command_adc,
  hostcomm_command_board,
  hostcomm_command_fr_bd,
  hostcomm_command_fr_cc,
  hostcomm_command_can
};




/* Data for the Command Processing */
TBUFFER_DATA * host_prxdata;      // received command-specific data (see documentation) for the received command
TBUFFER_DATA * host_ptxdata;      // command-specific data (see documentation) for the response
byte           host_rxlength;     // length of received command-specific data


/**********************/
/* Command Processing */
/**********************/

/* Group: GENERAL */
static void hostcomm_command_general (byte command) {
  switch (command) {
    case CMD_GENERAL_READ_SIGNATURE :
      *host_ptxdata++ = 'O';
      *host_ptxdata++ = 'N';
      *host_ptxdata++ = 'S';
      *host_ptxdata++ = 'E';
      *host_ptxdata++ = 'M';
      *host_ptxdata++ = 'I';
      *host_ptxdata++ = 'N';
      *host_ptxdata++ = 'C';
      *host_ptxdata++ = 'V';
      *host_ptxdata++ = '7';
      *host_ptxdata++ = '3';
      *host_ptxdata++ = '8';
      *host_ptxdata++ = '3';
      *host_ptxdata++ = 'A';
      *host_ptxdata++ = 'P';
      *host_ptxdata++ = 'P';
      *host_ptxdata++ = 'V';
      *host_ptxdata++ = '1';                    
      break;

    case CMD_GENERAL_READ_NODE_ADDRESS:
      *host_ptxdata++ = SW_ADDRESS;           
      break;
      
    default: break;
  }
}

static void hostcomm_command_adc (byte command) {
  word Value = 0;
  dword Result;
  switch (command) {
    case CMD_ADC_VCC_Q :
      if (ADC_Measure(TRUE) == ERR_OK){     
        if (ADC_GetChanValue16(Voltage_VCC, &Value) == ERR_OK) {
          Result = Vref * (dword)Value;
          Result >>= 11;
        } else Result = 0xFFFF;        
        *(word *) host_ptxdata = (word)Result;        
        host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      }
      break;
    case CMD_ADC_VIO_Q :
      if (ADC_Measure(TRUE) == ERR_OK){     
        if (ADC_GetChanValue16(Voltage_VIO, &Value) == ERR_OK) {
          Result = Vref * (dword)Value;
          Result >>= 11;
        } else Result = 0xFFFF;        
        *(word *) host_ptxdata = (word)Result;        
        host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      }
      break;
    case CMD_ADC_VCC_BD_Q :
      if (ADC_Measure(TRUE) == ERR_OK){     
        if (ADC_GetChanValue16(Voltage_VCC_BD, &Value) == ERR_OK) {
          Result = Vref * (dword)Value;
          Result >>= 11;
        } else Result = 0xFFFF;        
        *(word *) host_ptxdata = (word)Result;        
        host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      }
      break;
    case CMD_ADC_VIO_BD_Q :
      if (ADC_Measure(TRUE) == ERR_OK){     
        if (ADC_GetChanValue16(Voltage_VIO_BD, &Value) == ERR_OK) {
          Result = Vref * (dword)Value;
          Result >>= 11;
        } else Result = 0xFFFF;        
        *(word *) host_ptxdata = (word)Result;        
        host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      }
      break;    
    case CMD_ADC_VBAT_Q :
      if (ADC_Measure(TRUE) == ERR_OK){     
        if (ADC_GetChanValue16(Voltage_VBAT, &Value) == ERR_OK) {
          Result = Vref * (dword)Value * RDIV_VBAT;
          Result >>= 12;
        } else Result = 0xFFFF;        
        *(word *) host_ptxdata = (word)Result;        
        host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      }
      break;  
    default: 
      Result = 0xFFFF;        
      *(word *) host_ptxdata = (word)Result;        
      host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      break;
  }
}

/* Group: BOARD */
static void hostcomm_command_board (byte command) {
  byte data;
  switch (command) {
    case CMD_BOARD_ADDRESS_Q :
      *host_ptxdata = SW_ADDRESS;           
      host_ptxdata = (TBUFFER_DATA *) (host_ptxdata + 1);
      break;
    case CMD_BOARD_LEDS_Q :
      data = 0;
      if (LED1) data |= 1;  
      if (LED2) data |= 2;  
      if (LED3) data |= 4;  
      if (LED4) data |= 8;  
      if (LED5) data |= 16;  
      if (LED6) data |= 32;  
      if (LED7) data |= 64;  
      if (LED8) data |= 128; 
      *host_ptxdata = data;           
      host_ptxdata = (TBUFFER_DATA *) (host_ptxdata + 1);
      break;
    case CMD_BOARD_LEDS :
      data = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      LED1 = ((data & 1)   != 0);
      LED2 = ((data & 2)   != 0);
      LED3 = ((data & 4)   != 0);
      LED4 = ((data & 8)   != 0);
      LED5 = ((data & 16)  != 0);
      LED6 = ((data & 32)  != 0);
      LED7 = ((data & 64)  != 0);
      LED8 = ((data & 128) != 0);             
      break;   
    case CMD_BOARD_RESET :
      // Start watchdog and do not send WD command
      _ENABLE_COP(1); 
      break;  
    default: break;
  }
}


/* Group: FR_BD */
static void hostcomm_command_fr_bd (byte command) {
  Fr_bd_status_register Status;
  Fr_bd_status_register Status2;
  Fr_BD_mode_type mode;
  Fr_channel_type channel;
  switch (command) {  
    case CMD_SET_LOW_LEVEL_CFG :
      break;
      
    case CMD_FR_CHANGE_MODE :
      mode = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      fr_bd_change_mode(channel, mode);
      break;

    case CMD_FR_STATUS_REGISTER_Q :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      Status.Flags.Word = 0;
      Status.Version.Word = 0;
      Status2.Flags.Word = 0;
      Status2.Version.Word = 0;
      switch (channel) {
        case FR_CHANNEL_A: Status = fr_bd_read_status_A(); break;
        case FR_CHANNEL_B: Status = fr_bd_read_status_B(); break;
        case FR_CHANNEL_AB: fr_bd_read_status_AB(&Status, &Status2); break;
        default: break;
      }
      
      *(word *) host_ptxdata = (word)Status.Flags.Word;        
      host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      *(word *) host_ptxdata = (word)Status.Version.Word;       
      host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      
      *(word *) host_ptxdata = (word)Status2.Flags.Word;        
      host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      *(word *) host_ptxdata = (word)Status2.Version.Word;       
      host_ptxdata = (TBUFFER_DATA *) ((word *) host_ptxdata + 1);
      
      break;
    
    case CMD_SET_PIN_STBN :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      switch (channel) {
        case FR_CHANNEL_A: FR_STBN_A = (*host_prxdata != 0); break;
        case FR_CHANNEL_B: FR_STBN_B = (*host_prxdata != 0); break;
        case FR_CHANNEL_AB: 
          FR_STBN_A = (*host_prxdata != 0);  
          FR_STBN_B = (*host_prxdata != 0);
          break;
        default: break;
      }         
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      break;    
      
    case CMD_SET_PIN_BGE :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      switch (channel) {
        case FR_CHANNEL_A: FR_BGE_A = (*host_prxdata != 0); break;
        case FR_CHANNEL_B: FR_BGE_B = (*host_prxdata != 0); break;
        case FR_CHANNEL_AB: 
          FR_BGE_A = (*host_prxdata != 0);  
          FR_BGE_B = (*host_prxdata != 0);
          break;
        default: break;
      }         
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      break; 
      
    case CMD_SET_PIN_CSN :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      switch (channel) {
        case FR_CHANNEL_A: FR_CSN_A = (*host_prxdata != 0); break;
        case FR_CHANNEL_B: FR_CSN_B = (*host_prxdata != 0); break;
        case FR_CHANNEL_AB: 
          FR_CSN_A = (*host_prxdata != 0);  
          FR_CSN_B = (*host_prxdata != 0);
          break;
        default: break;
      }         
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      break; 
    
    case CMD_SET_PIN_SCK :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      switch (channel) {
        case FR_CHANNEL_A: FR_SCK_A = (*host_prxdata != 0); break;
        case FR_CHANNEL_B: FR_SCK_B = (*host_prxdata != 0); break;
        case FR_CHANNEL_AB: 
          FR_SCK_A = (*host_prxdata != 0);  
          FR_SCK_B = (*host_prxdata != 0);
          break;
        default: break;
      }         
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      break;

    case CMD_SET_PIN_TXEN :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      switch (channel) {
        case FR_CHANNEL_A: FR_TXEN_A = (*host_prxdata != 0); break;
        case FR_CHANNEL_B: FR_TXEN_B = (*host_prxdata != 0); break;
        case FR_CHANNEL_AB: 
          FR_TXEN_A = (*host_prxdata != 0);  
          FR_TXEN_B = (*host_prxdata != 0);
          break;
        default: break;
      }         
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      break;  

    case CMD_SET_PIN_TXD :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      switch (channel) {
        case FR_CHANNEL_A: FR_TXD_A = (*host_prxdata != 0); break;
        case FR_CHANNEL_B: FR_TXD_B = (*host_prxdata != 0); break;
        case FR_CHANNEL_AB: 
          FR_TXD_A = (*host_prxdata != 0);  
          FR_TXD_B = (*host_prxdata != 0);
          break;
        default: break;
      }         
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      break;
      
    case CMD_SPI_ENABLED :
      SPI1CR1_SPE = (*host_prxdata != 0);     
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      FR_SCK_A = 0;
      FR_SCK_B = 0;
      FR_CSN_A = 1;
      FR_CSN_B = 1;
      break; 
     
    case CMD_FR_STATUS_DOUBLE_READ :
      channel = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      mode = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      Status.Flags.Word = 0;
      Status.Version.Word = 0;
      Status2.Flags.Word = 0;
      Status2.Version.Word = 0;
      switch (channel) {
        case FR_CHANNEL_A: Status = fr_bd_read_status_A();
                           wait_1us((UINT16)mode * (UINT16)20);         
                           Status2 = fr_bd_read_status_A();
                           break;
        case FR_CHANNEL_B: Status = fr_bd_read_status_B();        
                           wait_1us((UINT16)mode * (UINT16)20); 
                           Status2 = fr_bd_read_status_B();
                           break;  
        default: break;
      }
      
      Status_array[0] = Status.Flags.Word;
      Status_array[1] = Status2.Flags.Word;
            
      break;
      
    default: break;
  }
}

/* Group: FR_CC */
static void hostcomm_command_fr_cc (byte command) {
  byte data0;
  byte data1;
  byte data2;
  byte data3;
  
  word wdata1;
  word wdata2;
  word wdata3;
  word wdata4;
  int i;
  
  Fr_return_type return_value;
  Fr_POC_state_type protocol_state;
  switch (command) {  
    case CMD_FR_CC_INIT : 
      FlexRay_Init();     /* MCU port init + FlexRay module configuration */
      break;
    
    case CMD_FR_CC_START_COMM :
      
      return_value = Fr_stop_communication(FR_ABORT_COMMUNICATION);
      return_value = Fr_enter_configuration_mode();
      FlexRay_CC_configuration();         
      while(Fr_get_POC_state() != FR_POCSTATE_READY);    
      return_value = Fr_start_communication();    /* Initialize startup  */  
      *host_ptxdata = return_value;       
      host_ptxdata = (TBUFFER_DATA *) (host_ptxdata + 1);
      
      break;
      
    case CMD_FR_CC_STOP_COMM :

      switch(Fr_get_POC_state()) {
        case FR_POCSTATE_NORMAL_ACTIVE : 
        case FR_POCSTATE_NORMAL_PASSIVE : return_value = Fr_stop_communication(FR_HALT_COMMUNICATION); break;
        default : return_value = Fr_stop_communication(FR_ABORT_COMMUNICATION); break;
      }
      *host_ptxdata = return_value;       
      host_ptxdata = (TBUFFER_DATA *) (host_ptxdata + 1);
      return_value = Fr_enter_configuration_mode();
      FlexRay_CC_configuration();   
      break;
      
    case CMD_FR_CC_SEND_WAKEUP :
      return_value = Fr_send_wakeup();
      *host_ptxdata = return_value;       
      host_ptxdata = (TBUFFER_DATA *) (host_ptxdata + 1);
      break;  
      
    case CMD_FR_CC_UPDATE_MB :
      return_value = Fr_init_message_buffers();
      *host_ptxdata = return_value;       
      host_ptxdata = (TBUFFER_DATA *) (host_ptxdata + 1);
      break;

     case CMD_FR_CC_GET_POC_STATE_Q :
      protocol_state = Fr_get_POC_state();
      *host_ptxdata = (byte)protocol_state;       
      host_ptxdata = (TBUFFER_DATA *) (host_ptxdata + 1);
      break;

    case CMD_FR_CC_PORTS_INIT : 
      /* Not used anymore */
      break;
     
    case CMD_FR_CC_STRB_SET : 
      
      data0 = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      data1 = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      data2 = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      data3 = *host_prxdata;
      host_prxdata = (TBUFFER_DATA *) (host_prxdata + 1);
      
      for (i = 0; i < 82; i++) 
        STBSCR = (i<<8);
      
      STBPCR = 0;
      
      if (data0 < 82){
        STBPCR_STB0EN = 1;
        STBSCR = (data0 << 8) | (1 << 4) | 0;
      }
      if (data1 < 82){
        STBPCR_STB1EN = 1;
        STBSCR = (data1 << 8) | (1 << 4) | 1;
      }
      if (data2 < 82){
        STBPCR_STB2EN = 1;
        STBSCR = (data2 << 8) | (1 << 4) | 2;
      }
      if (data3 < 82){
        STBPCR_STB3EN = 1;
        STBSCR = (data3 << 8) | (1 << 4) | 3;
      }
      break;
      
    case CMD_FR_CC_HW_CONFIG : 
      // XX bytes
      Fr_HW_cfg_01.CC_base_address = *(uint32 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint32 *)host_prxdata + 1); 
      Fr_HW_cfg_01.CC_FlexRay_memory_base_address = *(uint32 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint32 *)host_prxdata + 1);
      Fr_HW_cfg_01.connected_HW = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);           
      Fr_HW_cfg_01.synchronization_filtering_enable = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);    
      Fr_HW_cfg_01.clock_source = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_HW_cfg_01.prescaler_value = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);        
      Fr_HW_cfg_01.MB_segment_1_data_size = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);  
      Fr_HW_cfg_01.MB_segment_2_data_size = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1); 
      Fr_HW_cfg_01.last_MB_seg_1 = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);           
      Fr_HW_cfg_01.last_MB_util = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);           
      Fr_HW_cfg_01.total_MB_number = *(uint16 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_HW_cfg_01.allow_cold_start_enable = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_HW_cfg_01.timeout = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                
      Fr_HW_cfg_01.sync_frame_table_offset = *(uint16 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1); 
      Fr_HW_cfg_01.single_channel_mode = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      break;  
    
    case CMD_FR_CC_LOW_LEVEL_CONFIG : 
      // 72 bytes
      Fr_low_level_cfg_set_01.G_COLD_START_ATTEMPTS= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_ACTION_POINT_OFFSET= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_CAS_RX_LOW_MAX= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_DYNAMIC_SLOT_IDLE_PHASE= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_MINISLOT= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_MINI_SLOT_ACTION_POINT_OFFSET= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_STATIC_SLOT= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_SYMBOL_WINDOW= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_TSS_TRANSMITTER= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_WAKEUP_SYMBOL_RX_IDLE= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_WAKEUP_SYMBOL_RX_LOW= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_WAKEUP_SYMBOL_RX_WINDOW= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_WAKEUP_SYMBOL_TX_IDLE= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.GD_WAKEUP_SYMBOL_TX_LOW= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_LISTEN_NOISE= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_MACRO_PER_CYCLE= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_MAX_WITHOUT_CLOCK_CORRECTION_PASSIVE= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_MAX_WITHOUT_CLOCK_CORRECTION_FATAL= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_NUMBER_OF_MINISLOTS= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_NUMBER_OF_STATIC_SLOTS= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_OFFSET_CORRECTION_START= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_PAYLOAD_LENGTH_STATIC= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_SYNC_NODE_MAX= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.G_NETWORK_MANAGEMENT_VECTOR_LENGTH= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_ALLOW_HALT_DUE_TO_CLOCK= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_ALLOW_PASSIVE_TO_ACTIVE= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_CHANNELS= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.PD_ACCEPTED_STARTUP_RANGE= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_CLUSTER_DRIFT_DAMPING= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_DECODING_CORRECTION= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_DELAY_COMPENSATION_CHA= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_DELAY_COMPENSATION_CHB= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.PD_LISTEN_TIMEOUT= *(uint32 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint32 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.PD_MAX_DRIFT= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_EXTERN_OFFSET_CORRECTION= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_EXTERN_RATE_CORRECTION= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_KEY_SLOT_ID= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_KEY_SLOT_USED_FOR_STARTUP= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_KEY_SLOT_USED_FOR_SYNC= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_KEY_SLOT_HEADER_CRC= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_LATEST_TX= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_MACRO_INITIAL_OFFSET_A= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_MACRO_INITIAL_OFFSET_B= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_MICRO_INITIAL_OFFSET_A= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_MICRO_INITIAL_OFFSET_B= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_MICRO_PER_CYCLE= *(uint32 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint32 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_OFFSET_CORRECTION_OUT= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_RATE_CORRECTION_OUT= *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_SINGLE_SLOT_ENABLED= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_WAKEUP_CHANNEL= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_WAKEUP_PATTERN= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_MICRO_PER_MACRO_NOM= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      Fr_low_level_cfg_set_01.P_PAYLOAD_LENGTH_DYN_MAX= *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      break;  
    
    case CMD_FR_CC_PAYLOAD_LENGTH :
      payload_length = *(uint8 *)host_prxdata;
      host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      break; 
         
    case CMD_FR_CC_PAYLOAD_DATA   :
      data0 = *(uint8 *)host_prxdata;
      host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      
      if (data0 > 4) data0 = 4;
      for (i = 0; i < 32; i++) {
        //tx_data[data0][i] = *(uint16 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);              
      }
      break;
          
    case CMD_FR_CC_TX_BUFFER_CFG  : 
      data1 = *(uint8 *)host_prxdata;
      host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);

      Fr_tx_buffer_cfg[data1].transmit_frame_ID = *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);								                     
      Fr_tx_buffer_cfg[data1].header_CRC = *(uint16 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint16 *)host_prxdata + 1);                                           
      Fr_tx_buffer_cfg[data1].payload_length = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                                        
      Fr_tx_buffer_cfg[data1].transmit_MB_buffering = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                   
      Fr_tx_buffer_cfg[data1].transmission_mode = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                      
      Fr_tx_buffer_cfg[data1].transmission_commit_mode = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);        
      Fr_tx_buffer_cfg[data1].transmit_channel_enable = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                     
      Fr_tx_buffer_cfg[data1].payload_preamble = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                                    
      Fr_tx_buffer_cfg[data1].tx_cycle_counter_filter_enable = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                      
      Fr_tx_buffer_cfg[data1].tx_cycle_counter_filter_value = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                         
      Fr_tx_buffer_cfg[data1].tx_cycle_counter_filter_mask = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                          
      Fr_tx_buffer_cfg[data1].tx_MB_interrupt_enable = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);                              
      Fr_tx_buffer_cfg[data1].tx_MB_interrupt_transmit_side_enable = *(uint8 *)host_prxdata;
          host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      break; 
         
    case CMD_FR_CC_RX_BUFFER_CFG     :
      
      break; 
         
    case CMD_FR_CC_BUFFER_CFG_SET : 
      for (i = 0; i < 6; i++){
        Fr_buffer_cfg_set_01[i] = *(uint8 *)host_prxdata;
        host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      } 
      break; 
    
    case CMD_FR_CC_BUFFER_CFG : 
      //for (i = 0; i < 6; i++){
      //  Fr_buffer_cfg_set_01[i] = *(uint8 *)host_prxdata;
      //  host_prxdata = (TBUFFER_DATA *) ((uint8 *)host_prxdata + 1);
      //} 
      break;  
     
    case CMD_FR_CC_SEND_REM_WAKEUP :
      
      read_parameters(&wdata1, &wdata2, &wdata3, &wdata4);
      switch (wdata4) {
        case 0:
          TestPatternRemoteWakeup((byte)wdata1);
          break;
        case 1:
          
          break;
        case 2:
          FR_TXD_A = 0;
          FR_TXD_B = 0;
          FR_TXEN_A = 0;
          FR_TXEN_B = 0;
          while(wdata1)wdata1--; 
          FR_TXEN_A = 1;
          FR_TXEN_B = 1;
          while(wdata2)wdata2--; 
          FR_TXEN_A = 0;
          FR_TXEN_B = 0;   
          while(wdata3)wdata3--;  
          FR_TXEN_A = 1;
          FR_TXEN_B = 1; 
          FR_TXD_A = 1;
          FR_TXD_B = 1;
          
          break; 
        case 3:
          FR_TXD_B = 0;
          FR_TXEN_B = 0;
          FR_TXEN_B = 1;
          FR_TXEN_B = 0;   
          FR_TXEN_B = 1; 
          FR_TXD_B = 1;
          
          break; 
        default: break;  
      }
      break;    
    case CMD_FR_CC_SEND_TSS  :
      data1 = *(uint8 *)host_prxdata;
      TestPatternTSS(data1);
      break;
    case CMD_FR_CC_SEND_TSS_HIGH :
      data1 = *(uint8 *)host_prxdata;
      TestPatternTSS_HIGH(data1);
      break;
    case CMD_FR_CC_SEND_TSS_LOW :
      data1 = *(uint8 *)host_prxdata;
      TestPatternTSS_LOW(data1);
      break;
    case CMD_FR_CC_SEND_TSS_HIGH_LOW :
      data1 = *(uint8 *)host_prxdata;
      TestPatternTSS_HIGH_LOW(data1);
      break;
    case CMD_FR_CC_SEND_TSS_50_50  :
      data1 = *(uint8 *)host_prxdata;
      TestPatternTSS_50_50(data1);
      break;
    case CMD_FR_CC_SEND_TSS_10_90  :
      data1 = *(uint8 *)host_prxdata;
      TestPatternTSS_10_90(data1);
      break;
    case CMD_FR_CC_SEND_TWO_50 :
      data1 = *(uint8 *)host_prxdata;
      TestPattern_Two_50_50(data1);
      break; 
    case CMD_FR_CC_SEND_RWU_VALID :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeup(data1);
      break;  
    case CMD_FR_CC_SEND_RWU_VALID_LONG :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupLong(data1);
      break;  
    case CMD_FR_CC_SEND_RWU_ALT :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupAlternative(data1);
      break;
    case CMD_FR_CC_SEND_RWU_SHORTED :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupShorted(data1);
      break;
    case CMD_FR_CC_SEND_RWU_FRAME :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupFrame(data1);
      break;
    case CMD_FR_CC_SEND_RWU_SHORT_IDLE :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupFailShortIdle(data1);
      break;
    case CMD_FR_CC_SEND_RWU_LONG_IDLE :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupFailLongIdle(data1);
      break;
    case CMD_FR_CC_SEND_RWU_SHORT_LOW1 :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupFailShortLow1(data1);
      break;
    case CMD_FR_CC_SEND_RWU_SHORT_LOW2 :
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupFailShortLow2(data1);
      break;   
    case CMD_FR_CC_SEND_CURRENT_MEAS:
      data1 = *(uint8 *)host_prxdata;
      TestPatternCurrentMeasurement(data1);
      break; 
    case CMD_FR_CC_SEND_RWU_FRAME_WRONG:
      data1 = *(uint8 *)host_prxdata;
      TestPatternRemoteWakeupFrameWrong(data1);
      break;
    case CMD_FR_CC_SEND_HIGH:
      data1 = *(uint8 *)host_prxdata;  
      TestPattern_HIGH(data1);
      break;
    case CMD_FR_CC_SEND_LOW:
      data1 = *(uint8 *)host_prxdata;
      TestPattern_LOW(data1);
      break; 
   
    default: break;
  }
}




/* Group: CAN */
static void hostcomm_command_can (byte command) {

  //byte data[5];
   
  switch (command) {  
    case CMD_CAN_FIND_NODES : 
      *host_ptxdata++ = SW_ADDRESS;  
      break;
    case CMD_CAN_TEST_LED : 
      LED_TOGGLE(LED5);  
      break;


    default: break;
  }
}




void SendCANCommand(byte Group, byte Command, word Data1, word Data2, word Data3, word Data4){
  
  TBUFFER_DATA txdata[12];  /* Transmission data buffer */
  TBUFFER_DATA rxdata[100];  /* Reception data buffer */
  byte txlen;
  byte rxlen;
  byte checksum;
  
  rxlen = 0; /* reset transmit buffer */
  txdata[0] = 2;
  txdata[1] = Group;
  txdata[2] = Command;
  txdata[3] = (byte)(Data1>>8); 
  txdata[4] = (byte)Data1; 
  txdata[5] = (byte)(Data2>>8); 
  txdata[6] = (byte)Data2; 
  txdata[7] = (byte)(Data3>>8); 
  txdata[8] = (byte)Data3; 
  txdata[9] = (byte)(Data4>>8); 
  txdata[10] = (byte)Data4; 
  txlen = 11;

  // 1. Frame-Check Layer.
  checksum = hostcomm_framecheck (txdata, txlen);
  txdata[txlen++] = checksum;
  
  hostcomm_CAN_command (txdata, txlen, rxdata, &rxlen); 
}

void SendCANCommand_bytes(byte Group, byte Command, byte Data1, byte Data2, byte Data3, byte Data4,
                                                    byte Data5, byte Data6, byte Data7, byte Data8){
  
  TBUFFER_DATA txdata[12];  /* Transmission data buffer */
  TBUFFER_DATA rxdata[100];  /* Reception data buffer */
  byte txlen;
  byte rxlen;
  byte checksum;
  
  rxlen = 0; /* reset transmit buffer */
  txdata[0] = 2;
  txdata[1] = Group;
  txdata[2] = Command;
  txdata[3] = Data1; 
  txdata[4] = Data2;
  txdata[5] = Data3; 
  txdata[6] = Data4; 
  txdata[7] = Data5; 
  txdata[8] = Data6; 
  txdata[9] = Data7; 
  txdata[10] = Data8;
  txlen = 11;

  // 1. Frame-Check Layer.
  checksum = hostcomm_framecheck (txdata, txlen);
  txdata[txlen++] = checksum;
  
  hostcomm_CAN_command (txdata, txlen, rxdata, &rxlen); 
}

void trig_pattern(void) {
  TRIG = 0;
}

void trig_scope(void) {
  TRIG_SCOPE = 0;
  TRIG_SCOPE = 1;
  TRIG_SCOPE = 1;
  TRIG_SCOPE = 0;
}

byte ADC_measure_VCC(word *voltage) {
  word Value = 0;
  dword Result;
  if (ADC_Measure(TRUE) == ERR_OK){  
    if (ADC_GetChanValue16(Voltage_VCC, &Value) == ERR_OK) {
        Result = Vref * (dword)Value;
        Result >>= 11;
        *voltage = (word)Result;
        return ERR_OK;
    } else {
      *voltage = 0xFFFF;
      return ERR_FAULT; 
    }   
  } else {
    *voltage = 0xFFFF;
    return ERR_FAULT;
  } 
}


byte ADC_measure_VIO(word *voltage) {
  word Value = 0;
  dword Result;
  if (ADC_Measure(TRUE) == ERR_OK){  
    if (ADC_GetChanValue16(Voltage_VIO, &Value) == ERR_OK) {
        Result = Vref * (dword)Value;
        Result >>= 11;
        *voltage = (word)Result;
        return ERR_OK;
    } else {
      *voltage = 0xFFFF;
      return ERR_FAULT; 
    }   
  } else {
    *voltage = 0xFFFF;
    return ERR_FAULT;
  }
}

byte ADC_measure_VCC_BD(word *voltage) {
  word Value = 0;
  dword Result;
  if (ADC_Measure(TRUE) == ERR_OK){  
    if (ADC_GetChanValue16(Voltage_VCC_BD, &Value) == ERR_OK) {
        Result = Vref * (dword)Value;
        Result >>= 11;
        *voltage = (word)Result;
        return ERR_OK;
    } else {
      *voltage = 0xFFFF;
      return ERR_FAULT; 
    }   
  } else {
    *voltage = 0xFFFF;
    return ERR_FAULT;
  } 
}


byte ADC_measure_VIO_BD(word *voltage) {
  word Value = 0;
  dword Result;
  if (ADC_Measure(TRUE) == ERR_OK){  
    if (ADC_GetChanValue16(Voltage_VIO_BD, &Value) == ERR_OK) {
        Result = Vref * (dword)Value;
        Result >>= 11;
        *voltage = (word)Result;
        return ERR_OK;
    } else {
      *voltage = 0xFFFF;
      return ERR_FAULT; 
    }   
  } else {
    *voltage = 0xFFFF;
    return ERR_FAULT;
  }
}

byte ADC_measure_VBAT(word *voltage) {
  word Value = 0;
  dword Result;
  if (ADC_Measure(TRUE) == ERR_OK){  
    if (ADC_GetChanValue16(Voltage_VBAT, &Value) == ERR_OK) {
        Result = Vref * (dword)Value * RDIV_VBAT;
        Result >>= 12;
        *voltage = (word)Result;
        return ERR_OK;
    } else {
      *voltage = 0xFFFF;
      return ERR_FAULT; 
    }   
  } else {
    *voltage = 0xFFFF;
    return ERR_FAULT;
  }
}

/* Measure all flexray bus driver supplies */
byte ADC_measure_BD_supplies(word *vio, word *vcc) {
  word Value = 0;
  dword Result;
  if (ADC_Measure(TRUE) == ERR_OK){  
    if (ADC_GetChanValue16(Voltage_VCC_BD, &Value) == ERR_OK) {
        Result = Vref * (dword)Value;
        Result >>= 11;
        *vio = (word)Result;
    } else return ERR_FAULT;
     
    if (ADC_GetChanValue16(Voltage_VIO_BD, &Value) == ERR_OK) {
        Result = Vref * (dword)Value;
        Result >>= 11;
        *vcc = (word)Result;
    } else return ERR_FAULT;
       
  } else return ERR_FAULT;
  
  return ERR_OK;
}



/* Config all mcu output signals connected to FlexRay bus driver as HIGH-Z or as output  */
void fr_bd_set_mcu_outputs(Mcu_pin_config_type mcu_pin_state){  
  switch (mcu_pin_state) {
    case HIGHZ :
      FR_SET_BGE_A_HZ();  
      FR_SET_BGE_B_HZ();  

      FR_SET_STBN_A_HZ(); 
      FR_SET_STBN_B_HZ(); 

      FR_SET_TXEN_A_HZ(); 
      FR_SET_TXEN_B_HZ(); 

      FR_SET_TXD_A_HZ();  
      FR_SET_TXD_B_HZ();  

      FR_SET_CSN_A_HZ();  
      FR_SET_CSN_B_HZ();  

      FR_SET_SCK_A_HZ();  
      FR_SET_SCK_B_HZ();     
      break;
    case OUTPUT :
      FR_SET_BGE_A_OUT(); 
      FR_SET_BGE_B_OUT(); 
 
      FR_SET_STBN_A_OUT();
      FR_SET_STBN_B_OUT();
 
      FR_SET_TXEN_A_OUT();
      FR_SET_TXEN_B_OUT();
  
      FR_SET_TXD_A_OUT(); 
      FR_SET_TXD_B_OUT(); 
  
      FR_SET_CSN_A_OUT(); 
      FR_SET_CSN_B_OUT(); 
  
      FR_SET_SCK_A_OUT(); 
      FR_SET_SCK_B_OUT();      
      break;
    default: break;
  }
}

/* Read parameters received with app test command */
void read_parameters(word *data1, word *data2, word *data3, word *data4){
  *data1 = *(word *) host_prxdata;
  host_prxdata = (TBUFFER_DATA *) ((word *)host_prxdata + 1);
  *data2 = *(word *) host_prxdata;
  host_prxdata = (TBUFFER_DATA *) ((word *)host_prxdata + 1);
  *data3 = *(word *) host_prxdata;
  host_prxdata = (TBUFFER_DATA *) ((word *)host_prxdata + 1);
  *data4 = *(word *) host_prxdata;
  host_prxdata = (TBUFFER_DATA *) ((word *)host_prxdata + 1);
}

/* Read parameters received with app test command */
void read_parameters_byte(byte *data1, byte *data2, byte *data3, byte *data4,
                          byte *data5, byte *data6, byte *data7, byte *data8){
  *data1 = * host_prxdata;
  host_prxdata++;
  *data2 = * host_prxdata;
  host_prxdata++;
  *data3 = * host_prxdata;
  host_prxdata++;
  *data4 = * host_prxdata;
  host_prxdata++;
  *data5 = * host_prxdata;
  host_prxdata++;
  *data6 = * host_prxdata;
  host_prxdata++;
  *data7 = * host_prxdata;
  host_prxdata++;
  *data8 = * host_prxdata;
  host_prxdata++;
}


#pragma CODE_SEG DEFAULT



     









