/*◄■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ LCC_ecan.h ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■►*/

/* 
 * File        : LCC_ecan.h
 * Author      : JWDarsow
 * µChip       : PIC18F26K80
 * Created on  : Tuesday, February 28, 2017
 * ECAN
 */

#ifndef _ECAN_H
#define _ECAN_H

/*═════════════════════════════════ INCLUDEs ═════════════════════════════════*/
#include <xc.h>                        // include processor files.  
#include "eeMemory.h"
#include "JWD-NHR_Common.h"

/*═══════════════════════════════ DEFINITIONs ════════════════════════════════*/
// <editor-fold defaultstate="collapsed" desc="Definitions">

#define _XTAL_FREQ      16000000       // Fosc for delay functions Check With ChipDefs.h! Here for Lib Compialation
#define INFO_ADDR       0x010          // Stsrt of node information

// States MUST match those in LCCnodex.h
#define sIDLE           0              // just kicking back waiting
#define sCID            1              // set and waiting for tOut for Checking SNIDA & reserving it

// States that must be observed
#define CRID_ABORT      0              // Check/Reserve ID Abort
#define CRID_FIRST      1              // Check/Reserve ID First get Random ID
#define CRID_CONT       2              // Check/Reserve ID Continue

// CAN Modes
#define CAN_MODE_CONFIG    0b100       // CAN Configuration mode
#define CAN_MODE_LISTEN    0b011       // CAN Listen Only mode
#define CAN_MODE_LOOPBACK  0b010       // CAN Loopback mode
#define CAN_MODE_SLEEP     0b001       // CAN Disable/Sleep mode
#define CAN_MODE_NORMAL    0b000       // CAN Normal mode

// CAN idType
#define CAN_REGISTERS      0X00        // Raw CAN Registers
#define STANDARD_CAN_ID    0x01        // 11bit header
#define EXTENDED_CAN_ID    0x02        // 29bit header

// LCC prefix bits 27:28
#define LCC_MESSAGE        0b11        // LCC Message
#define LCC_CAN_MESSAGE    0b10        // LCC CAN Control Message
#define JWD_NHR_MESSAGE    0b01        // JWD-NHR Message
#define OTHER_NOT_USED     0b00        // Not used

// Multi Frame Flags
#define MFF_Only           0b0000      // Only frame
#define MFF_First          0b0001      // First frame of more than one
#define MFF_Last           0b0010      // Last frame of more than one
#define MFF_Middle         0b0011      // Middle frame of more than 2.

// Frame Type
#define CAN_CTRL_MSG       0b000       // LCC/CAN Control messages
#define LCC_FT_GA_MTI      0b001       // Global & Addressed MTI
#define LCC_FT_DGC         0b010       // Datagram complete in frame
#define LCC_FT_DGF         0b011       // Datagram first frame
#define LCC_FT_DGM         0b100       // Datagram middle frame
#define LCC_FT_DGL         0b101       // Datagram final frame
#define LCC_FT_SD_         0b111       // Stream Data

#define LCC_CAN_CTRL_PFT   0b10000     //0x10 LCC CAN Control Message, LCC_CAN_MESSAGE + CAN_CTRL_MSG
// LCC/CAN Control message  Protocol
#define CCM_RID            0x700       // Reserve ID (RID) frame
#define CCM_AMD            0x701       // Alias Map Definition (AMD) frame
#define CCM_AME            0x702       // Alias Map Enquiry (AME) frame
#define CCM_AMR            0x703       // Alias Map Reset (AMR) frame
#define CCM_EIR0           0x710       // Error Information Report 0
#define CCM_EIR1           0x711       // Error Information Report 1
#define CCM_EIR2           0x712       // Error Information Report 2
#define CCM_EIR3           0x713       // Error Information Report 3

#define LCC_GA_MTI_PFT     0b11001     //0x19 Global & Addressed MTI w/ Prefix, LCC_MESSAGE + LCC_FT_GA_MTI
// LCC message  Protocol
#define LCC_IC_FS          0x100       // Initialization Complete, Full Protocol + Full Source Node ID
#define LCC_IC_SS          0x101       // Initialization Complete, Simple-set Sufficient + Full Source Node ID
#define LCC_VNA            0x488       // Verify Node ID, Addressed + fddd, Optional Full Node ID
#define LCC_VNG            0x490       // Verify Node ID, Global + Optional Full Node ID
#define LCC_VdN_FS         0x170       // Verified Node ID, Full-set Prorocol + Full Source Node ID
#define LCC_VdN_SS         0x171       // Verified Node ID, Simple-set Sufficient + Full Source Node ID
#define LCC_OIR            0x068       // Optional Interaction Rejected + fddd, error, optional info
#define LCC_TDE            0x0A8       // Terminate Due to Error + fddd, error, optional info
#define LCC_PSI            0x828       // Protocol Support Inquiry + fddd
#define LCC_PSR            0x668       // Protocol Support Reply + fddd, Protocol flags
#define ETP_IEG            0x970       // Identify Events, SN Global
#define ETP_IEA            0x968       // Identify Events, Addressed

// Event Transport Protocol
#define EVENT_BIT          0x004       // Event message mask bit, except ETP_IEG & ETP_IEA
#define ETP_PCER           0x5B4       // Producer/Consumer Event Report
#define ETP_IC             0x8F4       // Identify Consumer
#define ETP_CIV            0x4C4       // Consumer Identified, Valid
#define ETP_CII            0x4C5       // Consumer Identified, Identified
#define ETP_CIU            0x4C7       // Consumer Identified, Unknown
#define ETP_CRI            0x4A4       // Consumer Range Identified
#define ETP_IP             0x914       // Identify Producer
#define ETP_PIV            0x544       // Producer Identified, Valid
#define ETP_PII            0x545       // Producer Identified, Invalid
#define ETP_PIU            0x547       // Producer Identified, Unknown
#define ETP_PIR            0x524       // Producer Identified Range
#define ETP_LE             0x594       // Learn Event

// LCC Protocol Flags
   // Byte 1
#define SS_Protocol          0x80 // Simple Protocol subset                       
#define DG_Protocol          0x40 // Datagram Protocol                            
#define Strm_Protocol        0x20 // Stream Protocol                              
#define MC_Protocol          0x10 // Memory Configuration Protocol                
#define Res_Protocol         0x08 // Reservation Protocol                         
#define EE_Protocol          0x04 // Event Exchange (Producer/Consumer) Protocol  
#define ID_Protocol          0x02 // Identification Protocol                      
#define TLC_Protocol         0x01 // Teaching/Learning Configuration Protocol     
   // Byte 2
#define RB_Protocol          0x80 // Remote Button Protocol                       
#define AD_CDI_Protocol      0x40 // Abbreviated Default CDI Protocol             
#define Disp_Protocol        0x20 // Display Protocol                             
#define SNI_Protocol         0x10 // Simple Node Information Protocol             
#define CDI_Protocol         0x08 // Configuration Description Information (CDI)  
#define TCT_Protocol         0x04 // Traction Control Protocol (Train Protocol)   
#define FDI_Protocol         0x02 // Function Description Information (FDI)       
#define DCC_CS_Protocol      0x01 // DCC Command Station Protocol                 
   // Byte 3
#define STNI_Protocol        0x80 // Simple Train Node Information Protocol       
#define FuncConfg_Protocol   0x40 // Function Configuration                       
#define FU_Protocol          0x20 // Firmware Upgrade Protocol                    
#define FUA_Protocol         0x10 // Firmware Upgrade Active                      

// LCC Simple Node Information Protocol
#define SP_SNIRq            0xDE8       // Simple Node Information Request
#define SP_SNIRp            0x594       // Simple Node Information Reply

//Definitions </editor-fold>

/*═════════════════════════════ TYPE DECLARATIONs ════════════════════════════*/
// <editor-fold defaultstate="collapsed" desc="Type Declarations">

/*───────────────────────── CAN prefix & Frame Type ──────────────────────────*/
typedef union      // CAN prefix & Frame Type Bit-fields
{
   struct      // CAN prefix & Frame Type Bit-fields
   {
      unsigned FrameType          :3;       //0:2 <26:24> LCC Frame Type or Frame Sequence Number
   /*
      111 = Stream Data                LCC_FT_SD_
      110 = (Reserved)
      101 = Datagram final frame       LCC_FT_DGL
      100 = Datagram middle frame      LCC_FT_DGM
      011 = Datagram first frame       LCC_FT_DGF
      010 = Datagram complete in frame LCC_FT_DGC
      001 = Global & Addressed MTI     LCC_FT_GA_MTI
      000 = (Reserved)                 CAN_CTRL_MSG
   */
      unsigned Prefix             :2;       //3:4 <28:27> CAN prefix
   /*
      11 = LCC_MESSAGE        LCC Message
      10 = LCC_CAN_MESSAGE    LCC CAN Control Message
      01 = JWD_NHR_MESSAGE    :) you could
      00 = Other CAN Frame
   */
      unsigned                    :3;       //5:7 Not Used <31:29>
   } ;
   Byte byte;
} PrefixFramet;              // CAN prefix & Frame Type <28:24>

/*─────────────────────── LCC Message Type Indicators ────────────────────────*/
////typedef union      // MTI Bit-fields
////{
////   struct
////   {
////      unsigned Modifier           :2;       //0:1   Message-specific extra information
////      unsigned Event              :1;       //2     1=This message has an event-field
////      unsigned Address            :1;       //3     1 = This message has a destination address-field
////      unsigned Simple             :1;       //4     1 = This message should be handled by simple nodes
////      unsigned PType              :5;       //5:9   Minor priority determination
////   /*
////      1 = s
////   */
////      unsigned Priority           :2;       //10:11 Gross priority of message
////   /*
////      11 = is lowest priority
////      00 = is highest priority
////   */
////      unsigned StreamDatagram     :1;       //12    Stream or Datagram
////   /*
////      1 = Stream or Datagram message
////      0 = Regular message
////   */
////      unsigned Special            :1;       //13    Operationally special
////   /*
////      1 = do not forward through Gateways
////      0 = forward through Gateways
////   */
////      unsigned Reserved1          :2;       //14:15 Reserved for future use, send and check as zero.
////   } MTIbits;
////   Word word;
////} LCCMTIt;              // LCC Message Type Indicators

/*─────────────── LCC, CAN, CANregisters or Byte Array Message ───────────────*/
typedef union 
{         // CAN Message 
   struct {             // As CAN Frame bit header & 8 bytes
      Byte              idType;   //0    Standard=0x01, Extended ID=0x02 or Registers=0x00
      DWord             id;       //1:4  Standard 11bit or Extended 29bit ID header (PFT, MTI & SNID combined)
      Byte              dlc;      //5    Data Length Count register
      Byte              Data[8];  //6:13 Data array
   } asCAN;

   struct {             //As LCC/OpenLCB Message
      PrefixFramet      PFT;      //0     LCC prefix & Frame Type/Sequence Number
      Word              MTI;      //1:2   LCC-MTI or Destination Node Alias
      Word              SNID;     //3:4   Source Node ID Alias
      Byte              dlc;      //5     Data Length Count register
      Byte              Data[8];  //6:13  Data array
   } asLCC;

   struct {             // As Raw Registers Transmit/Receive
      Byte              idType;   //0  = REGISTERS_CAN
      Byte              XBnSIDH;  //1  Standard Low Identifier register
      Byte              XBnSIDL;  //2  Standard High Identifier register
      Byte              XBnEIDH;  //3  Extended Low Identifier register
      Byte              XBnEIDL;  //4  Extended High Identifier register
      Byte              XBnDLC;   //5  Data Length Count register
      Byte              XBnD0;    //6  Data Byte register
      Byte              XBnD1;    //7  Data Byte register
      Byte              XBnD2;    //8  Data Byte register
      Byte              XBnD3;    //9  Data Byte register
      Byte              XBnD4;    //10 Data Byte register
      Byte              XBnD5;    //11 Data Byte register
      Byte              XBnD6;    //12 Data Byte register
      Byte              XBnD7;    //13 Data Byte register
   } asRegister;

   Byte asArray[14];    // CAN Tx/Rx Registers, CAN Message & LCC/OLCB Message Buffer size
} CANMsgt;

/*────────────────────────── LCC Unique Identifiers ──────────────────────────*/
typedef union {
   struct {                  // 48-bit unique identifier in 6 bytes
      Byte UID1;             // macro group assignment (MSB)
      Byte UID2;
      Byte UID3;
      Byte UID4;
      Byte UID5;
      Byte UID6;
   } UID;
   Byte array[6];
} LCCUIDt;              // LCC Unique Identifiers

/*──────────────────────── Alias & Full Node Address ─────────────────────────*/
typedef struct
{
   Word    Alias;
   Byte    Full[6];
   Byte    Stat;
} AFaddrt;

/*────────────────────────────── Event Message ───────────────────────────────*/
typedef union 
{         // CAN Message 
   struct {             //As LCC/OpenLCB Message
      Byte              UNID[6];  //1:6 Unique ID 
      uInt16            Event;    //7:8 Event Suffix
   } ;
   Byte DataBlock[8];             // Message Data block
} EventIDt;

//Type Declarations </editor-fold>

/*════════════════════════ GLOBAL VARIABLE DEFINITIONS ═══════════════════════*/
// <editor-fold defaultstate="collapsed" desc="Global Variable Definitions">
AFaddrt            AFaddr[47];              // Alias/Full address list
uInt8              AFlistEnd = 0;           // The empty end
//Global Variable Definitions </editor-fold>

/*══════════════════════════════════ MACROs ══════════════════════════════════*/
/*─♦─ Get 16bit Timer 3 ─♦─ Upper half + Lower Half */
#define TIMER3_WORD     ((TMR3H << 8) | TMR3L)

/*═══════════════════════════ FUNCTION DECLARATIONS ══════════════════════════*/

// <editor-fold defaultstate="collapsed" desc="External Declearations">

/*──────────────────────────── Service Event Number ──────────────────────────*/
extern void consumeEventNumber(uInt16 EventNo);                // in main.h
extern void ObserveEventNumber(EventIDt * IDEvent);              // in main.h

//External Declarations </editor-fold>

/*════════♦ ♦ ♦ ♦ ♦═════════♦ LCC/OpenLCB Functions ♦════════♦ ♦ ♦ ♦ ♦════════*/
// <editor-fold defaultstate="collapsed" desc="LCC/OpenLCB Functions">

/*───────────────────────────── Process LCC Event ────────────────────────────*/
void processEvent(CANMsgt * pTempMsg);

/*──────────────────────────── Process LCC Message ───────────────────────────*/
void processLCC(CANMsgt * pTempMsg);

/*──────────────────── Send Global & Addressed MTI Message ───────────────────*/
void sendLCC(Word MTI, Byte * pData, uInt8 dlc);

/*──────────────────────────────── Send Event ────────────────────────────────*/
void sendEvent(Byte * aUNID, uInt16 eventNo);

/*────────────────────────── Send Node Information ───────────────────────────*/
void sendNodeInfo(Word toSNIDA, Word DataAddr);

/*────────────────────────────── LCC Transmit ────────────────────────────────*/
/**
    @Summary       LCC frame transmit
    @Description
        Transmits LCC_MSG after translating to CANMsg via CAN_transmit()
        Defined in main program Node1 (Bridge Node Multiple LCC/OpenLCB Connections)
        or Node2 Common Node Single LCC/OpenLCB Connection
    @Param         Pointer to a LCCMsg
    @Example
        <code>
        LCC_MSG txMessage;
        LCC_transmit(&txMessage);  
        </code>                                                                             
*/
void LCC_transmit(CANMsgt * pLCCMsg);

//LCC/OpenLCB Functions </editor-fold>

/*══════♦ ♦ ♦ ♦ ♦═══════♦ CAN Frame Transfer Functions ♦══════♦ ♦ ♦ ♦ ♦═══════*/
// <editor-fold defaultstate="collapsed" desc="CAN Frame Transfer Functions">

/*────────────────────────── Process CAN Message ─────────────────────────────*/
void processCANMessage(CANMsgt * tempMsg);                     // in LCCnode_.h

/*────────────────────── Process LCC CAN Control Message ─────────────────────*/
void processLCC_CAN(CANMsgt * pTempMsg);

/*────────────────────────── Reserve a Node ID alias ─────────────────────────*/
void ReserveNodeIDalias(uInt8 aCID, uInt8 * tState);

/*────────────────────────── Generate Node ID Alias ──────────────────────────*/
/* Algorithm for generating unique Node ID aliases (See TN-9.7.2.1 section 6
   Preferred Alias Allocation Method) always returns same number. */
Word CAN_Generate_Alias(Byte * LCCNID);

/*─────────────────────────── Save Alias & Full ID ───────────────────────────*/
void updateNodeList(Byte * UID, Word SNIDA, Byte Status);
   
/*──────────────────────────── Display Node List ─────────────────────────────*/
void displayNodeList(void);

//CAN Frame Transfer Functions </editor-fold>

/*══════════♦ ♦ ♦ ♦ ♦══════════♦ CAN  Functions ♦═════════♦ ♦ ♦ ♦ ♦═══════════*/
// <editor-fold defaultstate="collapsed" desc="CAN Functions">

/*────────────────────────────── Initialize CAN ──────────────────────────────*/
void ECAN_Initialize(void);                 // Initializes the ECAN module.

/*─────────────────────────────── CAN Transmit ───────────────────────────────*/
/**
   @Summary       CAN frame transmit
   @Description
      Transmits CANMsg through the first available buffer
   @Param         Pointer to a CANMsg
   @Returns       True or False if message was loaded to transmit buffer 
   @Example
      <code>
      uCAN_MSG txMessage;
      CAN_transmit(&txMessage);  
      </code>                                                                             
*/
Byte CAN_transmit(CANMsgt * tempCanMsg);

/*────────────────────────── LCC Message to CAN ID ───────────────────────────*/
CANMsgt *  CAN_LCC2CAN(CANMsgt * aCANMsg);

/*────────────────────────── CAN ID to LCC Message ───────────────────────────*/
CANMsgt * CAN_CAN2LCC(CANMsgt * pCANMsg);

/*─────────────────────────── Register to CAN ID ─────────────────────────────*/
/**
	@Summary		    Clean up Rx buffer header
	@Description
	   Takes fractured header data in Rx buffer that's in raw register byte format and
      makes it contiguous in a DWord, id field of CANMsg
	@Param		    Pointer to temporary CAN message
*/
CANMsgt * CAN_Reg2CAN(CANMsgt * pCANMsg);

/*─────────────────────────── CAN ID to Registers ────────────────────────────*/
CANMsgt * CAN_CAN2Reg(CANMsgt * pCANMsg);

/*────────────────────────────── String to CAN ───────────────────────────────*/
/**
	@Summary		    Convert JMRI formated String to CAN message
	@Description
	   Convert JMRI formated String ":<X | S><header><N | R><data bytes>;" to CAN message 
      
	@Param		   Pointer to String, Pointer to CAN message
   @Returns       Pointer to CAN message
   @Example
      <code>
      CANMsg aCANMsg;
      Char aString[];
      sendtoCANbus(String2CAN(aString, aCANMsg));  
 * or
      String2CAN(aString, aCANMsg);
      </code>                                                                             
*/
CANMsgt * String2CAN(Char * aCANstring, CANMsgt * apCanMsg);

/*────────────────────────────── CAN to String ───────────────────────────────*/
/**
	@Summary		    Convert CAN message to JMRI formated String
	@Description
	   Convert CANMsg to JMRI formated String ":<X | S><header><N | R><data bytes>;"
	@Param		   Pointer to CAN message, Pointer to String
   @Returns       Pointer to String
   @Example
      <code>
      CANMsg aCANMsg;
      Char aString[];
      sendtoSerialPort(CAN2String(&CANMsg, aString));
 * or
        CAN2String(&CANMsg, aString);
      </code>                                                                             
*/
Char * CAN2String(CANMsgt * pCanMsg, Char * aCANstring);

/*──────────────────────── are CAN Messages In Buffer ────────────────────────*/
/**
	@Summary		    CAN_messagesInBuffer
	@Description
		Checks to see how many messages are in the buffer
	@Param		    None
	@Returns		    Returns total number of messages in all the buffers
	@Example
		<code>
		Byte nrMsg;
		nrMsg = CAN_messagesInBuffer();  
		</code>                                                                            
*/
Byte CAN_messagesInBuffer(void);

/*──────────────────────────────── CAN Sleep ─────────────────────────────────*/
void CAN_sleep(void);                       // Puts the CAN module to sleep

/*────────────────────────────── CAN is Bus Off ──────────────────────────────*/
/**
	@Summary		    CAN_isBusOff
	@Description
 		Checks to see if module is busoff
	@Param		    None
	@Returns		    True if module is in Busoff, False is if it is not
	@Example
		<code>
		Byte busOff;
		busOff = CAN_isBusOff();  
		</code> 
*/
Byte CAN_isBusOff(void);

/*────────────────────────── CAN is RX Error Passive ─────────────────────────*/
/**
	@Summary		    CAN_isRXErrorPassive
	@Description
		Checks to see if module is RX Error Passive
	@Param		    None
	@Returns 		 True if module is in RX Error Passive, False is if it is not                                                    
 	@Example
		<code>
		Byte errRxPasive;
		errRxPasive = CAN_isRXErrorPassive();
		</code>     
 */
Byte CAN_isRXErrorPassive(void);

/*────────────────────────── CAN is TX Error Passive ─────────────────────────*/
/**
	@Summary		    CAN_isTXErrorPassive
	@Description
		Checks to see if module is TX Error Passive
	@Param		    None
	@Returns		    True if module is in TX Error Passive, False is if it is not
	@Example
		<code>
		Byte errTxPasive;
		errTxPasive = CAN_isTXErrorPassive();  
		</code>       
*/
Byte CAN_isTXErrorPassive(void);
//CAN Functions </editor-fold>

/*════════♦ ♦ ♦ ♦ ♦═══════♦ Other & Utility Functions ♦═══════♦ ♦ ♦ ♦ ♦═══════*/
// <editor-fold defaultstate="collapsed" desc="Other & Utility Functions">

/*─────────────────── LCCUID 6 bytes to 1of4 1½ bytes words ──────────────────*/
Word UNID2part(uInt8 frameNo, Byte * LCCUID);

/*───────────────────── UNID byte array data to String ───────────────────────*/
Char * UNID2String(Byte * aUNID, Char * IDstring);

/*───────────────────── UNID in Message data to String ───────────────────────*/
Char * msgUNID2String(CANMsgt * pCANmsg, Char * IDstring);

/*───────────────────────────── String to UNID ───────────────────────────────*/
void String2UNID(Byte * UNID, Char * str);

/*────────────────────────────── Event String ────────────────────────────────*/
Char * Event2String(EventIDt * pEvent, Char * Estring);

/*───────────────────────── Print LCC or CAN Message ─────────────────────────*/
void printMsg(CANMsgt * pTempMsg);

//Other & Utility Functions </editor-fold>

#endif // _ECAN_H
