/*◄■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ NMRA_DCC.h ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■► */

/* 
 * File       : NMRA_DCC.h
 * Author     : JWDarsow
 * See        : NMRA_DCC.c for title information
 * Created on : Tuesday, October 27, 2015
 */

#ifndef NMRA_DCC_H
#define	NMRA_DCC_H

/*═════════════════════════════════ INCLUDEs ═════════════════════════════════*/
#include "JWD-NHR_Common.h"       // Standard Defines & Generic Type Defs

/*═══════════════════════════ CONSTANT DECLARATIONS ══════════════════════════*/
// <editor-fold defaultstate="collapsed" desc="Constant Declarations">

#define HARD 1                         // Reset to factory settings
#define SOFT 0                         // Clear to known state
#define MAX_DCC_MESSAGE_LEN 6          // including XOR-Byte
#define ALL_STOP_MASK       0b01110001 // Mask for stop packet

/* This is the NMRA DCC Manufacturer Id Code that is used in DIY projects. This value is to be used for CV8  */
#define MAN_ID_DIY                     0x0D      // me, myself & I, Railway Co
/* This is Product/Version Id Codes for projects. This value is to be used for CV7 */
#define PROD_ID_DIY                    0x01      // First kind

/* This defines the default address initialized to in CV1 & CV9 */
#define INIT_DECODER_ADDRESS_LSB       1    // CV1 NMRA default value, 6 LSB of accessory address
#define INIT_DECODER_ADDRESS_MSB       0    // CV9 NMRA default value, 3[5] MSB of accessory address [+ 2 bit Ext]

/* This defines what kind of accessory decoder This(µChip) is initialized to in CV29 */
#define BIDIRECTIONAL_COMM             0b00001000     // CV 29/541 bit 3
#define EXTENDED_ACCESSORY_DECODER     0b00100000     // CV 29/541 bit 5
#define OUTPUT_ADDRESS_MODE		      0b01000000     // CV 29/541 bit 6
#define DCC_ACCESSORY_DECODER	         0b10000000     // CV 29/541 bit 7
#define INIT_CV29_VALUE                DCC_ACCESSORY_DECODER | OUTPUT_ADDRESS_MODE | EXTENDED_ACCESSORY_DECODER

// Mandatory Accessory Decoder CV Addresses
#define CV_ACCESSORY_DECODER_ADDRESS_LSB       1 // [M]
#define CV_ACCESSORY_DECODER_ADDRESS_MSB       9 // [M] 
#define CV_VERSION_ID                          7 // [M] Read ONLY
#define CV_MANUFACTURER_ID                     8 // [M] Read ONLY a write with 8 resets to mfg default
#define CV_29_CONFIG                          29 // [M]
#define MAXCV                    0x7ff //XEEPROMSIZE - 1 // the upper limit of External EEPROM.

// </editor-fold>

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

//typedef enum                           // The parts of a DCC Packet [S9.2]
//{                                      // Packet bit sequences to wait to finish
//  LookingFor_PREAMBLE,                 // Seeking Preamble
//  LookingFor_DATA_BIT,                 // Address or Data byte
//  LookingFor_START_END_BIT,            // Bit following Address or Data byte
//} 
//DccRxWaitState_t;

typedef enum                           // Command, Instruction or ... Packet Type S-9.2 S-9.2.1
{
   ERROR_PCKT,
   IDLE_PCKT,
   RESET_PCKT,
   STOP_PCKT,
   BASIC_CTRL_PCKT,
   BASIC_CV_PCKT,
   EXTND_CTRL_PCKT,
   EXTND_CV_PCKT
} 
PacketTypes_t;

typedef struct DccMsg_s                // Structure for Packet buffer
{
	uInt8	PreambleBits;                 // Number of PreambleBits [DeBuging]
	uInt8	Size;                         // Number of bytes in buffer
	Byte  Data[MAX_DCC_MESSAGE_LEN];    // Array for upto 6 bytes of data
}
DccMsg_t;

//typedef struct DccRx_s                 // Packet Reception structure
//{
//  DccRxWaitState_t State;              // enum 0-3 for interrupt, bit sequence
//  Byte             DataReady;          // Packet ready, bool
//  uInt8            BitCount;           // bit sequence count
//  uInt8            TempByte;           // Byte for collecting bits
//  DccMsg_t         PacketBuf;          // The Packet
//  DccMsg_t         PacketCopy;         // a copy for comparing duplicates ?
//}DccRx_t;


typedef struct DccProcState_s          // Structure for link
{
   union                          // StateFlags
   {
      Byte byte;
      struct {// Bits
         unsigned ThisDecoder   :1;       // bit 0 Broadcast or This Decoders address
      /*
         0 = Broadcast
         1 = This Decoders address
      */
         unsigned HardReset     :1;       // bit 1 ReSet Type
      /*
         0 = Soft
         1 = Hard
      */
         unsigned               :1;       // bit 2 
      /*
         0 = 
         1 = 
      */
         unsigned               :1;       // bit 3 
      /*
         0 = 
         1 = 
      */
         unsigned               :1;       // bit 4 ?+ServiceMode for MF decoders
      /*
         0 = 
         1 = 
      */
         unsigned AccyDcdrType  :1;       // bit 5 Accessory Decoder Type CV 29/541 bit 5
      /*
         0 = Basic Accessory Decoder
         1 = Extended Accessory Decoder
      */
         unsigned AddrMethod    :1;       // bit 6 Addressing Method CV 29/541 bit 6
      /*
         0 = Decoder Address method
         1 = Output Address method
      */
         unsigned DcdrType      :1;       // bit 7 Decoder Type MF or Accy CV 29/541 bit 7 ALLWAYS 1
      /*
         0 = Multifunction Decoder
         1 = Accessory Decoder
      */
      }Bits;
   } StateFlags;
   
   PacketTypes_t   PacketType;          // Packet Type
   uInt16          Address;             // All parts of 9 or 11 bit address
   bool            AccyPosition;        // 1=On=Normal 0=Off=Revers, bit3 of Byte2 of 9bit Addr,
   uInt8           OutputControl;       // bit0-2 of Byte2 of 9 bit Addr / bit0-4 of Byte2 of 11 bit Addr
   uInt8           CVinstType;          // CV Access Instruction type
   uInt16          CVaddr;              // CV addr for CV Access Instruction
   uInt8           CVvalue;             // CV value for CV Access Instruction
   uInt8           DuplicateCount;      // Duplicate Packet Count
   DccMsg_t        LastMsg;             // For Duplicate Packet comparison
//#ifdef DCC_DEBUG
   uInt8           IntCount;
   uInt8           TickCount;
//#endif
}DccProcState_t;

typedef struct CVPair_s                // CV number,value pair
{
  uInt16  CV;                          // CVnumber
  uInt8   Value;
}CVPair_t;

typedef union                          // CV29 type
{
   Byte byte;
   struct {// Multifunction Decoder
      unsigned Direction     :1;       // bit 0 Locomotive Direction
   /*
      0 = normal
      1 = reversed
      This bit controls the locomotive's forward and backward direction in digital mode only. Directional sensitive
      functions, such as headlights (FL and FR), will also be reversed so that they line up with the locomotive’s 
      new forward direction. See S-9.1.1 for more information.
   */
      unsigned FL_location   :1;       // bit 1 FL location
   /*
      0 = bit 4 in Speed and Direction instructions control FL
      1 = bit 4 in function group one instruction controls FL
      See S-9.2.1 for more information.
   */
      unsigned PwrSrcConv    :1;       // bit 2 Power Source Conversion
   /*
      0 = NMRA Digital Only
      1 = Power Source Conversion Enabled
      See CV#12 for more information.
   */
      unsigned BiDirCom      :1;       // bit 3 Bi-Directional Communications
   /*
      0 = Bi-Directional Communications disabled
      1 = Bi-Directional Communications enabled
      See S-9.3.2 for more information.
   */
      unsigned SpeedTable    :1;       // bit 4 Speed Table
   /*
      0 = speed table set by configuration variables #2,#5, and #6
      1 = Speed Table set by configuration variables #66-#95
   */
      unsigned AddrSize      :1;       // bit 5 number of bytes for addressing
   /*
      0 = one byte addressing
      1 = two byte addressing (also known as extended addressing)
   */
      unsigned               :1;       // bit 6 Reserved for future use
      unsigned AccDecoder    :1;       // bit 7 Accessory Decoder
   /*
      0 = Multifunction Decoder
      1 = Accessory Decoder (see CV #541 for a description of assignments for bits 0-6)
   */
   }MFDecoder;
   struct {// Accessory Decoder
      unsigned               :3;       // bits 0:2 Reserved for future use.
      unsigned BiDirCom      :1;       // bit 3 Bi-Directional Communications
   /*
      0 = Bi-Directional Communications disabled
      1 = Bi-Directional Communications enabled
      See S-9.3.2 for more information
   */
      unsigned               :1;       // bit 4 Reserved for future use.
      unsigned Extended      :1;       // bit 5 Decoder Type
   /*
      0 = Basic Accessory Decoder packet format 
      1 = Extended Accessory Decoder packet format 
   */
      unsigned Output        :1;       // bit 6 Addressing Method for Basic packet format (DDD)
   /*
      0 = Decoder Address method
      1 = Output Address method
   */
      unsigned AccDecoder    :1;       // bit 7 Accessory Decoder
   /*
      0 = Multifunction Decoder (See CV-29 for description of bit Assignments for bits 0-6)
      1 = Accessory Decoder
      If bit 7 = 1, then the decoder may ignore the two most-significant bits of the CV number in
      Service Mode only. Using this feature CV513 becomes CV1, etc. Decoders which perform the
      translation must clearly document the feature in their manual.
   */
   }AccDecoder;
} CV29_t;

// </editor-fold>

/*═══════════════════════════ VARIABLE DECLARATIONS ══════════════════════════*/
// <editor-fold defaultstate="collapsed" desc="Variable Declarations">
DccMsg_t       DccPacket ;
DccMsg_t       DccRxPacket;
DccProcState_t DccProcState;
CV29_t         CV29;
// </editor-fold>

/*═══════════════════════════ FUNCTION DECLARATIONS ══════════════════════════*/
// <editor-fold defaultstate="collapsed" desc="Function Declarations">

/*──────────────────────────── Initialize Decoder ─────────────────────────────*/
void Dcc_Initialize();

/*─────────────────────────────── Check Packet ───────────────────────────────*/
uInt8 Dcc_ProcessPacket(void);

/*──────────────────────── Get This decoders Address ─────────────────────────*/
uInt16 DCC_ThisAddr(void);

/*────────────────────────────────── Read CV ─────────────────────────────────*/
uInt8 DCC_readCV(uInt16 CV);

/*───────────────────────────────── Write CV ─────────────────────────────────*/
uInt8 DCC_writeCV(uInt16 CV, uInt8 Value);

/*─────────────────────────────── Acknowledge CV ───────────────────────────────*/
void ackCV(void);

/*──────────────────────────── Check CV Validity ─────────────────────────────*/
uInt8 validCV(uInt16 CV, uInt8 Writable);

/*───────────────────────────── Clear DCC State ──────────────────────────────*/
void clearDccProcState(void);

/*─────────────────────────────── Reset Memory ───────────────────────────────*/
void Dcc_ResetMemory(void);

/*============================ DCC Debug Routines ============================*/
// #define DCC_DEBUG
#ifdef DCC_DEBUG
/*─────────────────────────────────── ¿?¿? ───────────────────────────────────*/
	uInt8 getIntCount(void);
/*─────────────────────────────────── ¿?¿? ───────────────────────────────────*/
	uInt8 getTickCount(void);
/*─────────────────────────────────── ¿?¿? ───────────────────────────────────*/
	uInt8 getBitCount(void);
/*─────────────────────────────────── ¿?¿? ───────────────────────────────────*/
	uInt8 getState(void);
#endif

// </editor-fold>// Functions Definitions

#endif	/* NMRA_DCC_H */
