/*
 * Can.c
 *
 *  Author: Gasha
 *  The CAN driver for 320F2837x family of DSPs (28377 and 28379)
 *  Which use CAN D controller
 */
//#include "F2837xD_driverlib_can.h"  // copied from C2000Ware_4_01_00_00\driverlib\f2837xd\driverlib\can.h and renamed
#include <F2837xD_device.h>
#include "Func.h"
#include "C1_Can.h"
#include "C1_Struct.h"
#include "C1_Vars.h"

#define GUI_ADDR        0x55ul
#define DSP_ALL         0x66ul
#define DSP_C1          0x22ul

#define DSPtoGUI(me, cmd)  (0xA4000000 | (cmd << 16) | (GUI_ADDR << 8) | me)
#define GUItoDSP(me, cmd)  (0xA4000000 | (cmd << 16) | (me   << 8) | GUI_ADDR)

const TS_CAN_MsgBoxConfig ConfigCanMailBoxes[CAN_NUMBER_OF_GUI_MAILBOXES] =
// mb_number msg_len_bytes msg_id                    msg_id_mask   msg_dir
{{    1,        8,         GUItoDSP(DSP_ALL, 0x30ul), 0x1FFFFFFF,     0},   // rx GUI Command
 {    2,        8,         GUItoDSP(DSP_ALL, 0x31ul), 0x1FFFFFFF,     0},   // rx GUI float msg
 {    3,        8,         GUItoDSP(DSP_C1,  0x40ul), 0x1FFFFFFF,     0},   // rx DAC1 Address
 {    4,        8,         GUItoDSP(DSP_C1,  0x41ul), 0x1FFFFFFF,     0},   // rx DAC1 Gain
 {    5,        8,         GUItoDSP(DSP_C1,  0x42ul), 0x1FFFFFFF,     0},   // rx DAC2 Address
 {    6,        8,         GUItoDSP(DSP_C1,  0x43ul), 0x1FFFFFFF,     0},   // rx DAC2 Gain
 {    7,        8,         GUItoDSP(DSP_C1,  0x44ul), 0x1FFFFFFF,     0},   // rx DAC3 Address
 {    8,        8,         GUItoDSP(DSP_C1,  0x45ul), 0x1FFFFFFF,     0},   // rx DAC3 Gain
 {    9,        8,         GUItoDSP(DSP_C1,  0x46ul), 0x1FFFFFFF,     0},   // rx DAC4 Address - NOT USED on TI eval board. It has 3 DACs
 {   10,        8,         GUItoDSP(DSP_C1,  0x47ul), 0x1FFFFFFF,     0},   // rx DAC4 Gain - NOT USED on TI eval board. It has 3 DACs
 {   11,        8,         GUItoDSP(DSP_C1,  0x10ul), 0x1FFFFFFF,     0},   // rx DebugArray
 {   12,        8,         GUItoDSP(DSP_C1,  0x11ul), 0x1FFFFFFF,     0},   // rx DebugRW

 {   13,        8,         DSPtoGUI(DSP_C1,  0x11ul), 0x1FFFFFFF,     1},   // tx DebugRW
 {   14,        8,         DSPtoGUI(DSP_C1,  0x12ul), 0x1FFFFFFF,     1},   // tx DebugArray10
 {   15,        8,         DSPtoGUI(DSP_C1,  0x13ul), 0x1FFFFFFF,     1},   // tx DebugArray32
 {   16,        8,         DSPtoGUI(DSP_C1,  0x14ul), 0x1FFFFFFF,     1},   // tx DebugArray54
 {   17,        8,         DSPtoGUI(DSP_C1,  0x40ul), 0x1FFFFFFF,     1},   // tx Faults
 {   18,        8,         DSPtoGUI(DSP_C1,  0x30ul), 0x1FFFFFFF,     1},   // tx Status
 {   19,        8,         DSPtoGUI(DSP_C1,  0x31ul), 0x1FFFFFFF,     1},   // tx Feedback0
 {   20,        8,         DSPtoGUI(DSP_C1,  0x32ul), 0x1FFFFFFF,     1},   // tx Feedback1
 {   21,        8,         DSPtoGUI(DSP_C1,  0x33ul), 0x1FFFFFFF,     1},   // tx Feedback2
 {   22,        8,         DSPtoGUI(DSP_C1,  0x34ul), 0x1FFFFFFF,     1},   // tx Feedback3
 {   23,        8,         DSPtoGUI(DSP_C1,  0x35ul), 0x1FFFFFFF,     1}};  // tx Feedback4

const unsigned int DbgArrayMsgBoxID[3] = { (unsigned int)CAN_DEBUG_ARRAY_RESP_10_MB_IDX,
                                           (unsigned int)CAN_DEBUG_ARRAY_RESP_32_MB_IDX,
                                           (unsigned int)CAN_DEBUG_ARRAY_RESP_54_MB_IDX };

TS_CAN_MsgObj            MsgRxBox;
TS_CAN_MsgObj            MsgTxBox;

union GUI_CommandUnion   GuiCmd;
float                    GuiFloat1;
float                    GuiFloat2;
union DAC_MessageUnion   DAC[4];       // TI eval board has three DACs only, GE controllers have 4 DACs
struct DebugArrayStruct  DebugArray[6];
unsigned int             CAN_Counter;  // Counts background cycles that runs at 100Hz;
unsigned int             VersionSwitch;
unsigned int             NewGuiCmdFlag;

// extern declaration for variables used in CAN messages

void InitCANA(void)
{
   /*
       Set the bit clock source and then enable it for the specific channel
       Without the CAN peripheral clock on, the address bus does not update the
       CAN memory/registers.
   */

   // CONFIGURE CAN A
   EALLOW;
   CanaRegs.CAN_CTL.bit.Init = 1;              // CAN is inactive during the initialization

   ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0;  // PERx.SYSCLK (default on reset)
   CpuSysRegs.PCLKCR10.bit.CAN_A = 1;          // Module clock is turned-on
   CanaRegs.CAN_CTL.bit.Init = 1;              // hold can channel in init (bus-off) state
   CanaRegs.CAN_CTL.bit.SWR = 1;               // reset the CAN peripheral
   while (CanaRegs.CAN_CTL.bit.SWR == 1)        // wait for the peripheral to reset
      ;

   CanaRegs.CAN_RAM_INIT.all = CAN_RAM_INIT_UNLOCKED_KEY;
   CanaRegs.CAN_RAM_INIT.bit.CAN_RAM_INIT = 1;  // reset all of Message RAM
   while (CanaRegs.CAN_RAM_INIT.bit.CAN_RAM_INIT == 0) // wait for message RAM to init
      ;

   CanaRegs.CAN_CTL.bit.CCE = 1;      // enable config change
   CanaRegs.CAN_CTL.bit.PMD = 0;      // enable parity
   CanaRegs.CAN_CTL.bit.DAR = 1;      // enable retransmit
   CanaRegs.CAN_CTL.bit.ABO = 1;      // enable auto bus off recovery
   CanaRegs.CAN_ABOTR = 200000000;    // after 1 second (200MHz clokc)

   CanaRegs.CAN_BTR.bit.BRPE = 0;
   CanaRegs.CAN_BTR.bit.BRP = 24;     // BRP = 24 => CAN_CLK = 200 / (24 + 1) = 8MHz
   CanaRegs.CAN_BTR.bit.TSEG1 = 8;    // Baud rate: 8MHz / (9 + 6 + 1) = 500kHz
   CanaRegs.CAN_BTR.bit.TSEG2 = 5;
   CanaRegs.CAN_BTR.bit.SJW = 3;

   while (CanaRegs.CAN_IF1CMD.bit.Busy != 0u)   // ensure the mailbox interface is not busy
      ;

   // Configure Mail Boxes
   for (int i = 0; i < CAN_NUMBER_OF_GUI_MAILBOXES; i++) {
      CanaRegs.CAN_IF1CMD.all = 0;  // now 'reset' interface registers
      CanaRegs.CAN_IF1MSK.all = 0;
      CanaRegs.CAN_IF1ARB.all = 0;
      CanaRegs.CAN_IF1MCTL.all = 0u;

      /* setup the transfer of the IF1 register sets to the message object */
      CanaRegs.CAN_IF1CMD.bit.Control = 1;                         //
      CanaRegs.CAN_IF1CMD.bit.Arb = 1;
      CanaRegs.CAN_IF1CMD.bit.Mask = 1;
      CanaRegs.CAN_IF1CMD.bit.DIR = CAN_IF_DIR_WRITE;

      CanaRegs.CAN_IF1ARB.bit.MsgVal = 1;                          // mailbox is enabled.
      CanaRegs.CAN_IF1ARB.bit.Xtd = 1u;                            // 29-bit ("extended") Identifier is used for this message object
      CanaRegs.CAN_IF1ARB.bit.Dir = ConfigCanMailBoxes[i].msg_dir; // set message direction
      CanaRegs.CAN_IF1ARB.bit.ID = ConfigCanMailBoxes[i].msg_id;   // set 29 bit message ID

      CanaRegs.CAN_IF1MSK.bit.MDir = 1;                            // The message direction bit is used for acceptance filtering
      CanaRegs.CAN_IF1MSK.bit.MXtd = 1;                            // The extended identifier bit (Xtd) is used for acceptance filtering
      CanaRegs.CAN_IF1MSK.bit.Msk = 0x1FFFFFFF;                    // all address bits are compared

      CanaRegs.CAN_IF1MCTL.bit.DLC = ConfigCanMailBoxes[i].msg_len_bytes; // set message length in bytes
      CanaRegs.CAN_IF1MCTL.bit.EoB = 1;                             // must be set to 1

      CanaRegs.CAN_IF1CMD.bit.MSG_NUM = ConfigCanMailBoxes[i].mb_number; // trigger message object in RAM to be written to
   }
   CanaRegs.CAN_CTL.bit.CCE = 0;    // disable config change
   CanaRegs.CAN_CTL.bit.Init = 0;   // CAN module processes messages normally
   EDIS;

   MsgRxBox.mailbox_num = 0;
   MsgRxBox.Data.Int.I0 = 0;
   MsgRxBox.Data.Int.I1 = 0;
   MsgRxBox.Data.Int.I2 = 0;
   MsgRxBox.Data.Int.I3 = 0;

   for (int i = 0; i < 5; i++) {
      for (int j = 0; j < 4; j++) {
         GuiGainBitPerUnit[i][j] = __divf32(32767.0, Cal.GuiGain[i][j] );  // 2^15 - 1 = 32767.0
      }
   }

   CAN_Counter = 0;
}

void ReadMsgCANA(TS_CAN_MsgObj* p_rx_msg_obj)
{
    /* setup the command to have the data/status of mailbox read into IF2 regs */
    CanaRegs.CAN_IF2CMD.all = 0;
    CanaRegs.CAN_IF2CMD.bit.Control = 1; // message control bits moved from the MsgBox addressed by message number (Bits [7:0]) to IF1 register set.
    CanaRegs.CAN_IF2CMD.bit.DATA_A = 1;  // move data bytes 3 to 0
    CanaRegs.CAN_IF2CMD.bit.DATA_B = 1;  // move data bytes 7 to 4

    /* trigger the write to the IF2 regs from the Message RAM */
    CanaRegs.CAN_IF2CMD.bit.MSG_NUM = p_rx_msg_obj->mailbox_num;

    while (CanaRegs.CAN_IF2CMD.bit.Busy != 0) /* wait for read to finish */
       ;

    p_rx_msg_obj->Data.Int.I0 = (CanaRegs.CAN_IF2DATB.bit.Data_6 << 8) | (CanaRegs.CAN_IF2DATB.bit.Data_7 & 0x00FF);
    p_rx_msg_obj->Data.Int.I1 = (CanaRegs.CAN_IF2DATB.bit.Data_4 << 8) | (CanaRegs.CAN_IF2DATB.bit.Data_5 & 0x00FF);
    p_rx_msg_obj->Data.Int.I2 = (CanaRegs.CAN_IF2DATA.bit.Data_2 << 8) | (CanaRegs.CAN_IF2DATA.bit.Data_3 & 0x00FF);
    p_rx_msg_obj->Data.Int.I3 = (CanaRegs.CAN_IF2DATA.bit.Data_0 << 8) | (CanaRegs.CAN_IF2DATA.bit.Data_1 & 0x00FF);

    /* clear out the new data flag if it was new data */
    CanaRegs.CAN_IF2CMD.bit.TxRqst = 1;
    /* trigger the write to the Message RAM to clear bit */
    CanaRegs.CAN_IF2CMD.bit.MSG_NUM = p_rx_msg_obj->mailbox_num;
}

void SendMsgCANA(TS_CAN_MsgObj* p_tx_msg_obj)
{
    while (CanaRegs.CAN_IF1CMD.bit.Busy != 0u)  // Make sure the cmd register is not currently active
       ;

    CanaRegs.CAN_IF1CMD.all = 0u;               // clear the command register

    CanaRegs.CAN_IF1DATB.bit.Data_7 = (bp_16)(p_tx_msg_obj->Data.Int.I0);
    CanaRegs.CAN_IF1DATB.bit.Data_6 = (bp_16)(p_tx_msg_obj->Data.Int.I0 >> 8);
    CanaRegs.CAN_IF1DATB.bit.Data_5 = (bp_32)(p_tx_msg_obj->Data.Int.I1);
    CanaRegs.CAN_IF1DATB.bit.Data_4 = (bp_32)(p_tx_msg_obj->Data.Int.I1 >> 8);
    CanaRegs.CAN_IF1DATA.bit.Data_3 = (bp_16)(p_tx_msg_obj->Data.Int.I2);
    CanaRegs.CAN_IF1DATA.bit.Data_2 = (bp_16)(p_tx_msg_obj->Data.Int.I2 >> 8);
    CanaRegs.CAN_IF1DATA.bit.Data_1 = (bp_32)(p_tx_msg_obj->Data.Int.I3);
    CanaRegs.CAN_IF1DATA.bit.Data_0 = (bp_32)(p_tx_msg_obj->Data.Int.I3 >> 8);

     /* prepare the command */
    CanaRegs.CAN_IF1CMD.bit.DIR = CAN_IF_DIR_WRITE;
    CanaRegs.CAN_IF1CMD.bit.DATA_A = 1;
    CanaRegs.CAN_IF1CMD.bit.DATA_B = 1;
    CanaRegs.CAN_IF1CMD.bit.TXRQST = 1;

    /* trigger the write to the Message RAM */
    CanaRegs.CAN_IF1CMD.bit.MSG_NUM = (bp_16)p_tx_msg_obj->mailbox_num;
}

void RxCANA(void)
{
   unsigned int NewMsg = CanaRegs.CAN_NDAT_21;  // take lower 16 bits since receive MsgBoxes are 1 to 12, D[11..0];

   if (NewMsg == 0) {  // If there are no new messages, return immediately.
      return;
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_GUI_BROADCAST_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx GUI Command
      ReadMsgCANA(&MsgRxBox);
      GuiCmd.Int.I0 = MsgRxBox.Data.Int.I0;
      GuiCmd.Int.I1 = MsgRxBox.Data.Int.I1;
      GuiCmd.Int.I2 = MsgRxBox.Data.Int.I2;
      GuiCmd.Int.I3 = MsgRxBox.Data.Int.I3;
      NewGuiCmdFlag = 1;
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_GUI_FLOAT_BROADCAST_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx GUI float msg
      ReadMsgCANA(&MsgRxBox);
      GuiFloat2 = MsgRxBox.Data.Float.F0;
      GuiFloat1 = MsgRxBox.Data.Float.F1;
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC1_MEM_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC1 Address
      ReadMsgCANA(&MsgRxBox);
      DAC[0].Int.I0 = MsgRxBox.Data.Int.I0;
      DAC[0].Int.I1 = MsgRxBox.Data.Int.I1;
      DAC[0].Int.I2 = MsgRxBox.Data.Int.I2;
      DAC[0].Int.I3 = MsgRxBox.Data.Int.I3;
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC1_GAIN_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC1 Gain
      ReadMsgCANA(&MsgRxBox);
      DAC[0].Bit.Offset = -MsgRxBox.Data.Float.F0;   // F0 = min, F1 = max
      DAC[0].Bit.Gain = __divf32(4095.0, (MsgRxBox.Data.Float.F1 - MsgRxBox.Data.Float.F0));
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC2_MEM_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC2 Address
      ReadMsgCANA(&MsgRxBox);
      DAC[1].Int.I0 = MsgRxBox.Data.Int.I0;
      DAC[1].Int.I1 = MsgRxBox.Data.Int.I1;
      DAC[1].Int.I2 = MsgRxBox.Data.Int.I2;
      DAC[1].Int.I3 = MsgRxBox.Data.Int.I3;
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC2_GAIN_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC2 Gain
      ReadMsgCANA(&MsgRxBox);
      DAC[1].Bit.Offset = -MsgRxBox.Data.Float.F0;   // F0 = min, F1 = max
      DAC[1].Bit.Gain = __divf32(4095.0, (MsgRxBox.Data.Float.F1 - MsgRxBox.Data.Float.F0));
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC3_MEM_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC3 Address
      ReadMsgCANA(&MsgRxBox);
      DAC[2].Int.I0 = MsgRxBox.Data.Int.I0;
      DAC[2].Int.I1 = MsgRxBox.Data.Int.I1;
      DAC[2].Int.I2 = MsgRxBox.Data.Int.I2;
      DAC[2].Int.I3 = MsgRxBox.Data.Int.I3;
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC3_GAIN_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC3 Gain
      ReadMsgCANA(&MsgRxBox);
      DAC[2].Bit.Offset = -MsgRxBox.Data.Float.F0;   // F0 = min, F1 = max
      DAC[2].Bit.Gain = __divf32(4095.0, (MsgRxBox.Data.Float.F1 - MsgRxBox.Data.Float.F0));
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC4_MEM_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC4 Address
      ReadMsgCANA(&MsgRxBox);
      DAC[3].Int.I0 = MsgRxBox.Data.Int.I0;
      DAC[3].Int.I1 = MsgRxBox.Data.Int.I1;
      DAC[3].Int.I2 = MsgRxBox.Data.Int.I2;
      DAC[3].Int.I3 = MsgRxBox.Data.Int.I3;
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DAC4_GAIN_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DAC4 Gain
      ReadMsgCANA(&MsgRxBox);
      DAC[3].Bit.Offset = -MsgRxBox.Data.Float.F0;   // F0 = min, F1 = max
      DAC[3].Bit.Gain = __divf32(4095.0, (MsgRxBox.Data.Float.F1 - MsgRxBox.Data.Float.F0));
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DEBUG_ARRAY_REQ_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {  // rx DebugArray
      register unsigned int index;
      ReadMsgCANA(&MsgRxBox);
      index = MsgRxBox.Data.Int.I2;
      if (index < 6) {
         if (MsgRxBox.Data.Int.I3 <= 5 )
         DebugArray[index].Type = MsgRxBox.Data.Int.I3;
         DebugArray[index].Address = MsgRxBox.Data.Long.L0;
      }
   }
   MsgRxBox.mailbox_num = ConfigCanMailBoxes[CAN_DEBUG_RW_REQ_MB_IDX].mb_number;
   if (NewMsg & (1 << (MsgRxBox.mailbox_num - 1))) {   // rx DebugRW
      union DebugRWUnion Msg;

      ReadMsgCANA(&MsgRxBox);
      Msg.Int.I0 = MsgRxBox.Data.Int.I0;
      Msg.Int.I1 = MsgRxBox.Data.Int.I1;
      Msg.Int.I2 = MsgRxBox.Data.Int.I2;
      Msg.Int.I3 = MsgRxBox.Data.Int.I3;
      if (Msg.Bit.RnW == 0) {  // write - readback
         switch (Msg.Bit.Type) {
         case UNSIGNED_16:
         case SIGNED_16:
            *(unsigned int*)Msg.Bit.Addr = (unsigned int)Msg.Bit.Data;
            break;
         case IEEE_FLOAT:
         case UNSIGNED_32:
         case SIGNED_32:
            *(unsigned long*)Msg.Bit.Addr = Msg.Bit.Data;
            break;
         default:
            break;
         }
      }
      Msg.Bit.RnW = 0;
      switch (Msg.Bit.Type) {
      case UNSIGNED_16:
      case SIGNED_16:
         Msg.Bit.Data = *(unsigned int*)Msg.Bit.Addr;
         break;
      case IEEE_FLOAT:
      case UNSIGNED_32:
      case SIGNED_32:
         Msg.Bit.Data = *(unsigned long*)Msg.Bit.Addr;
         break;
      default:
         break;
      }
      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_DEBUG_RW_RESP_MB_IDX].mb_number;
      MsgTxBox.Data.Int.I0 = Msg.Int.I0;
      MsgTxBox.Data.Int.I1 = Msg.Int.I1;
      MsgTxBox.Data.Int.I2 = Msg.Int.I2;
      MsgTxBox.Data.Int.I3 = Msg.Int.I3;
      SendMsgCANA(&MsgTxBox);
   }
}

// Can_Tx runs in the DSP background at 10ms (100Hz) rate
void TxCANA(void)
{
   //  tx DebugArrays run at 10 ms rate
   for (unsigned int i = 0; i < 3; i++) {
      unsigned int j = 2*i;

      MsgTxBox.mailbox_num = 0;
      switch (DebugArray[j].Type) {
      case IEEE_FLOAT:
      case SIGNED_32:
      case UNSIGNED_32:
         MsgTxBox.mailbox_num = ConfigCanMailBoxes[DbgArrayMsgBoxID[i]].mb_number;
         MsgTxBox.Data.Long.L0 = *(unsigned long*)(DebugArray[j].Address);
         break;
      case UNSIGNED_16:
      case SIGNED_16:
         MsgTxBox.mailbox_num = ConfigCanMailBoxes[DbgArrayMsgBoxID[i]].mb_number;
         MsgTxBox.Data.Int.I0 = *(unsigned int*)(DebugArray[j].Address);
         break;
      case DO_NOT_USE:
      default:
         MsgTxBox.Data.Long.L0 = 0;
         break;
      }
      j++;
      switch (DebugArray[j].Type) {
      case IEEE_FLOAT:
      case SIGNED_32:
      case UNSIGNED_32:
         MsgTxBox.mailbox_num = ConfigCanMailBoxes[DbgArrayMsgBoxID[i]].mb_number;
         MsgTxBox.Data.Long.L1 = *(unsigned long*)(DebugArray[j].Address);
         break;
      case UNSIGNED_16:
      case SIGNED_16:
         MsgTxBox.mailbox_num = ConfigCanMailBoxes[DbgArrayMsgBoxID[i]].mb_number;
         MsgTxBox.Data.Int.I1 = *(unsigned int*)(DebugArray[j].Address);
         break;
      case DO_NOT_USE:
      default:
         MsgTxBox.Data.Long.L1 = 0;
         break;
      }
      if (MsgTxBox.mailbox_num != 0) {
         SendMsgCANA(&MsgTxBox);
      }
   }
   // All other messages run at 250 ms
   switch (CAN_Counter) {
   case (0): // tx Faults 0x40
      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_FAULT_MB_IDX].mb_number;
      MsgTxBox.Data.Long.L0 = FaultCode.All;  // MiniEAU uses 32 bit FaultCode
      MsgTxBox.Data.Long.L1 = 0;
      SendMsgCANA(&MsgTxBox);
      break;
   case (1): // tx Status 0x30
      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_STATUS_MB_IDX].mb_number;
      MsgTxBox.Data.Int.I0 = DiscreteIO.All;
      MsgTxBox.Data.Int.I1 = 0;
      if (VersionSwitch != 0) {
         MsgTxBox.Data.Int.I2 = 0x8000;
         VersionSwitch = 0;
      }
      else {
         MsgTxBox.Data.Int.I2 = SoftwareVersion & 0x7FFF;
         VersionSwitch = 1;
      }
      MsgTxBox.Data.Int.I3 = State << 8 | Mode;
      SendMsgCANA(&MsgTxBox);
      break;
   case (2): // tx Feedback0  0x31
      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_FEEDBACK0_MB_IDX].mb_number;
      MsgTxBox.Data.Int.I0 = (int)__fsat(((Vdc       * GuiGainBitPerUnit[0][0])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I1 = (int)__fsat(((IindDqo.d * GuiGainBitPerUnit[0][1])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I2 = (int)__fsat(((IindDqo.q * GuiGainBitPerUnit[0][2])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I3 = (int)__fsat(((IindDqo.o * GuiGainBitPerUnit[0][3])), 32767.0, -32767.0);
      SendMsgCANA(&MsgTxBox);
      break;
   case (3): // tx Feedback1 0x32
      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_FEEDBACK1_MB_IDX].mb_number;
      MsgTxBox.Data.Int.I0 = (int)__fsat(((VdcOut * GuiGainBitPerUnit[1][0])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I1 = (int)__fsat(((Iext  * GuiGainBitPerUnit[1][1])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I2 = (int)__fsat(((1.0 * GuiGainBitPerUnit[1][2])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I3 = (int)__fsat(((2.0 * GuiGainBitPerUnit[1][3])), 32767.0, -32767.0);
      SendMsgCANA(&MsgTxBox);
      break;
   case (4): // tx Feedback2 0x33
      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_FEEDBACK2_MB_IDX].mb_number;
      MsgTxBox.Data.Long.L0 = RunTime;
      MsgTxBox.Data.Int.I2 = (int)__fsat(((GuiFloat2 * GuiGainBitPerUnit[2][2])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I3 = (int)__fsat(((GuiFloat1 * GuiGainBitPerUnit[2][3])), 32767.0, -32767.0);
      SendMsgCANA(&MsgTxBox);
      break;
//   case (5): // tx Feedback3 0x34
//      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_FEEDBACK3_MB_IDX].mb_number;
//      MsgTxBox.Data.Int.I0 = (int)__fsat(((Var * GuiGainBitPerUnit[3][0])), 32767.0, -32767.0);
//      MsgTxBox.Data.Int.I1 = (int)__fsat(((Var * GuiGainBitPerUnit[3][1])), 32767.0, -32767.0);
//      MsgTxBox.Data.Int.I2 = (int)__fsat(((Var * GuiGainBitPerUnit[3][2])), 32767.0, -32767.0);
//      MsgTxBox.Data.Int.I3 = (int)__fsat(((Var * GuiGainBitPerUnit[3][3])), 32767.0, -32767.0);
//      SendMsgCANA(&MsgTxBox);
//      break;
   case (6): // tx Feedback4 0x35 -- Toolbar blue field number has fixed address (0x35.I3) and GainBitPerUnit of 1
      MsgTxBox.mailbox_num = ConfigCanMailBoxes[CAN_FEEDBACK4_MB_IDX].mb_number;
      MsgTxBox.Data.Int.I0 = 0; //(int)__fsat(((Var * GuiGainBitPerUnit[4][0])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I1 = 0; //(int)__fsat(((Var * GuiGainBitPerUnit[4][1])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I2 = 0; //(int)__fsat(((Var * GuiGainBitPerUnit[4][2])), 32767.0, -32767.0);
      MsgTxBox.Data.Int.I3 = (int)__fsat(GuiFloat1, 32767.0, -32767.0); //(int)__fsat(((Var * GuiGainBitPerUnit[4][3])), 32767.0, -32767.0);
      SendMsgCANA(&MsgTxBox);
      break;
   default:
      break;
   }

   CAN_Counter++;
   if (CAN_Counter >= 25) {
      CAN_Counter = 0;
   }
}
