#include "xc.h"
#include "init.h"
#include "extern.h"

#ifdef INCLUDE_CAN

/* Filter and mask defines for CAN*/
/* Macros used to write filter/mask ID to Register CiRXMxSID and CiRXFxSID */
/* For example, to set up the filter to accept a value of 0x123, the macro when called as */
/* CAN_FILTERMASK2REG_SID(0x123) will write the register space to accept message with ID 0x123 */
/* Use for Standard Messages Only */
#define CAN_FILTERMASK2REG_SID(x) ((x & 0x07FF)<<5)
/* The Macro will set the MIDE bit in CiRXMxSID */
#define CAN_SETMIDE(sid) (sid|0x0008)
/* The Macro will set the EXIDE bit in CiRXFxSID to only accept extended messages */
#define CAN_FILTERXTD(sid) (sid|0x0008)
/* The macro will clear the EXIDE bit in CiRXFxSID to only accept standard messages */
#define CAN_FILTERSTD(sid) (sid & 0xFFF7)
/* Macro used to write filter/mask ID to Register CiRXMxSID, CiRXMxEID, CiRXFxSID and CiRXFxEID */
/* For example, to set up the filter to accept a value of 0x123, the macro when called as */
/* CAN_FILTERMASK2REG_SID(0x123) will write the register space to accept message with ID 0x123 */
/* Use for Extended Messages only*/
#define CAN_FILTERMASK2REG_EID0(x) (x & 0xFFFF)
#define CAN_FILTERMASK2REG_EID1(x) (((x & 0x1FFC)<<3)|(x & 0x3))



void InitCAN1()
{
    unsigned long tmp_EID;

C1CTRL1bits.REQOP=4;  //Put ECAN module in config mode
while (C1CTRL1bits.OPMODE!=4);  //Wait until it is in config mode  TODO:  Needs timeout

C1CTRL1bits.CANCKS = 0x1;


//Setup for 1Mbit/sec
//C1CFG1bits.BRP = 0;
//C1CFG1bits.SJW = 0;  /* Synchronization Jump Width set to 1 TQ */
//C1CFG2bits.SEG1PH = 0x7;  /* Phase Segment 1 time is 8 TQ */
//C1CFG2bits.SEG2PHTS = 0x1;  /* Phase Segment 2 time is set to be programmable */
//C1CFG2bits.SEG2PH = 0x7;  /* Phase Segment 2 time is 8 TQ */
//C1CFG2bits.PRSEG = 0x2;  /* Propagataion time 3 TQ */
//C1CFG2bits.SAM = 0x1;  /* Bus line is sampled three times at the sample point */

//Setup for 500kbit/sec
//C1CFG1bits.BRP = 1;
//C1CFG1bits.SJW = 0;  /* Synchronization Jump Width set to 1 TQ */
//C1CFG2bits.SEG1PH = 0x7;  /* Phase Segment 1 time is 8 TQ */
//C1CFG2bits.SEG2PHTS = 0x1;  /* Phase Segment 2 time is set to be programmable */
//C1CFG2bits.SEG2PH = 0x7;  /* Phase Segment 2 time is 8 TQ */
//C1CFG2bits.PRSEG = 0x2;  /* Propagataion time 3 TQ */
//C1CFG2bits.SAM = 0x1;  /* Bus line is sampled three times at the sample point */



//Setup for 250kbit/sec
//C1CFG1bits.BRP = 3;
//C1CFG1bits.SJW = 0;  /* Synchronization Jump Width set to 1 TQ */
//C1CFG2bits.SEG1PH = 0x7;  /* Phase Segment 1 time is 8 TQ */
//C1CFG2bits.SEG2PHTS = 0x1;  /* Phase Segment 2 time is set to be programmable */
//C1CFG2bits.SEG2PH = 0x7;  /* Phase Segment 2 time is 8 TQ */
//C1CFG2bits.PRSEG = 0x2;  /* Propagataion time 3 TQ */
//C1CFG2bits.SAM = 0x1;  /* Bus line is sampled three times at the sample point */


//Setup for 125kbit/sec
C1CFG1bits.BRP = 7;
C1CFG1bits.SJW = 0;  /* Synchronization Jump Width set to 1 TQ */
C1CFG2bits.SEG1PH = 0x7;  /* Phase Segment 1 time is 8 TQ */
C1CFG2bits.SEG2PHTS = 0x1;  /* Phase Segment 2 time is set to be programmable */
C1CFG2bits.SEG2PH = 0x7;  /* Phase Segment 2 time is 8 TQ */
C1CFG2bits.PRSEG = 0x2;  /* Propagataion time 3 TQ */
C1CFG2bits.SAM = 0x1;  /* Bus line is sampled three times at the sample point */


/* Assign 12 buffers in DMA ram*/
C1FCTRLbits.DMABS=0b100;  //Eight buffers for Tx, and four for Rx



// Enable buffers and set tx buffer priority
C1TR01CONbits.TXEN0 = 1; /* ECAN1, Buffer 0 is a Transmit Buffer */
C1TR01CONbits.TXEN1 = 1; /* ECAN1, Buffer 1 is a Transmit Buffer */
C1TR23CONbits.TXEN2 = 1; /* ECAN1, Buffer 2 is a Transmit Buffer */
C1TR23CONbits.TXEN3 = 1; /* ECAN1, Buffer 3 is a Transmit Buffer */
C1TR45CONbits.TXEN4 = 1; /* ECAN1, Buffer 4 is a Transmit Buffer */
C1TR45CONbits.TXEN5 = 1; /* ECAN1, Buffer 5 is a Transmit Buffer */
C1TR67CONbits.TXEN6 = 1; /* ECAN1, Buffer 6 is a Transmit Buffer */
C1TR67CONbits.TXEN7 = 1; /* ECAN1, Buffer 7 is a Transmit Buffer */

C1TR01CONbits.TX0PRI = 0b11; /* Message Buffer 0 Priority Level */
C1TR01CONbits.TX1PRI = 0b11; /* Message Buffer 1 Priority Level */
C1TR23CONbits.TX2PRI = 0b11; /* Message Buffer 2 Priority Level */
C1TR23CONbits.TX3PRI = 0b11; /* Message Buffer 3 Priority Level */
C1TR45CONbits.TX4PRI = 0b11; /* Message Buffer 4 Priority Level */
C1TR45CONbits.TX5PRI = 0b11; /* Message Buffer 5 Priority Level */
C1TR67CONbits.TX6PRI = 0b11; /* Message Buffer 6 Priority Level */
C1TR67CONbits.TX7PRI = 0b11; /* Message Buffer 7 Priority Level */

//Set up recieve buffers, mask, etc. for recieving extended frames
/* Enable window to access acceptance filter registers */
C1CTRL1bits.WIN = 0x1;

/* Select Acceptance Filter Mask 0 for Acceptance Filter 0 */
C1FMSKSEL1bits.F0MSK=0x00;
/* Configure Acceptance Filter Mask 0 register to care about all bits. (bits set to 0 here don't count.
Mask Bits (29-bits) : 0b0 0000 0000 0000 0000 0001 1111 1111
SID<10:0> : 0b111 1111 1111 ..SID<10:0> or EID<28:18>
EID<17:16> : 0b11
..EID<17:16>
EID<15:0> : 0b1111 1111 1111 1111 ..EID<15:0> */
C1RXM0SIDbits.SID = (0x1FFC0000) >> 18;
C1RXM0SIDbits.EID = (0x00030000) >> 16;
C1RXM0EIDbits.EID = (0x0000FFFF);

/* Configure Acceptance Filter 0 to match extended identifier, Controller ID = from #define and CMD ID = dec(10) to set mode.
Filter Bits (29-bits) : 0b0 0000 0000 0000 0000 000x xxxx xxxx
SID<10:0> : 0b00000000000 ..SID<10:0> or EID<28:18>
EID<17:16> : 0b00         ..EID<17:16>
EID<15:0> : 0b0000000xxxxxxxxx ..EID<15:0> */
tmp_EID = Assemble_packetID(CAN_SRCID, 10, 0);
C1RXF0SIDbits.SID = (tmp_EID & 0x1FFC0000) >> 18;
C1RXF0SIDbits.EID = (tmp_EID & 0x00030000) >> 16;
C1RXF0EIDbits.EID = (tmp_EID & 0x0000FFFF);

/* Acceptance Filter 0 to check for Extended Identifier */
C1RXM0SIDbits.MIDE = 0x1;
C1RXF0SIDbits.EXIDE= 0x1;

/* Acceptance Filter 0 to use Message Buffer 8 to store message */
C1BUFPNT1bits.F0BP = 0x8;
/* Enable Acceptance Filter 0 */
C1FEN1bits.FLTEN0=0x1;


/* Select Acceptance Filter Mask 1 for Acceptance Filter 1 */
C1FMSKSEL1bits.F1MSK=0x01;
/* Configure Acceptance Filter Mask 1 register to care about all bits except bottom nine of EID which is the sequence number. (bits set to 0 here don't count.
Mask Bits (29-bits) : 0b0 0000 0000 0000 0000 0001 1111 1111
SID<10:0> : 0b111 1111 1111 ..SID<10:0> or EID<28:18>
EID<17:16> : 0b11
..EID<17:16>
EID<15:0> : 0b1111 1111 1111 1111 ..EID<15:0> */
C1RXM1SIDbits.SID = (0x1FFC0000) >> 18;
C1RXM1SIDbits.EID = (0x00030000) >> 16;
C1RXM1EIDbits.EID = (0x0000FE00);  //Ignore bottom nine bits for the sequence number since this packet is coming from the power converter

/* Configure Acceptance Filter 0 to match extended identifier, Controller ID = from #define and CMD ID = dec(00) to coorespond to data packet with current in it from the power converter, and any sequence number.
Filter Bits (29-bits) : 0b0 0000 0000 0000 0000 000x xxxx xxxx
SID<10:0> : 0b00000000000 ..SID<10:0> or EID<28:18>
EID<17:16> : 0b00         ..EID<17:16>
EID<15:0> : 0b0000000xxxxxxxxx ..EID<15:0> */
tmp_EID = Assemble_packetID(POWERCONVERTER_CAN_SRCID, 00, 0);
C1RXF1SIDbits.SID = (tmp_EID & 0x1FFC0000) >> 18;
C1RXF1SIDbits.EID = (tmp_EID & 0x00030000) >> 16;
C1RXF1EIDbits.EID = (tmp_EID & 0x0000FE00);

/* Acceptance Filter 1 to check for Extended Identifier */
C1RXM1SIDbits.MIDE = 0x1;
C1RXF1SIDbits.EXIDE= 0x1;

/* Acceptance Filter 1 to use Message Buffer 9 to store message */
C1BUFPNT1bits.F1BP = 0x9;
/* Enable Acceptance Filter 1 */
C1FEN1bits.FLTEN1=0x1;



/* Clear window to access ECAN control registers */
C1CTRL1bits.WIN = 0x0;

//Put CAN1 into Normal mode
C1CTRL1bits.REQOP = 0;
while(C1CTRL1bits.OPMODE != 0);

}

void InitDma12()  //DMA channel 1 is used to transfer data to the CAN controller for subsequent transmission
                  //DMA channel 2 is used to transfer recieved data from the CAN controller to the CPU memory
{

    /* Initialize the DMA channel 0 for ECAN TX and clear the colission flags */
DMACS0bits.PWCOL1 = 0;
DMACS0bits.XWCOL1 = 0;
/* Set up Channel 1 for peripheral indirect addressing mode normal operation, word operation */
/* and select TX to peripheral */
DMA1CON = 0x2020;
/* Set up the address of the peripheral ECAN1 (C1TXD) */
DMA1PAD = 0x0442;
/* Set the data block transfer size of 8 */
DMA1CNT = 7;
/* Automatic DMA TX initiation by DMA request */
DMA1REQ = 0x0046;  //IRQ select register
/* DPSRAM atart address offset value */
DMA1STA = __builtin_dmaoffset(&ECAN1MSGBUF);
/* Enable the channel */
DMA1CONbits.CHEN = 1;  

/* Initialize DMA Channel 2 for ECAN RX and clear the collision flags */
DMACS0bits.PWCOL2 = 0;
DMACS0bits.XWCOL2 = 0;
/* Set up Channel 2 for Peripheral Indirect addressing mode (normal operation, word operation */
/* and select as RX to peripheral */
DMA2CON = 0x0020;
/* Set up the address of the peripheral ECAN1 (C1RXD) */
DMA2PAD = 0x0440;
/* Set the data block transfer size of 8 */
DMA2CNT = 7;
/* Automatic DMA Rx initiation by DMA request */
DMA2REQ = 0x0022;
/* DPSRAM atart address offset value */
DMA2STA = __builtin_dmaoffset(&ECAN1MSGBUF);
/* Enable the channel */
DMA2CONbits.CHEN = 1;  



/* Enable ECAN1 interrupt */
_C1IP = 3;
IEC2bits.C1IE = 1;
/* Enable transmit interrupt */
C1INTEbits.TBIE = 0;
/* Enable ECAN1 receive Interrupt */
C1INTEbits.RBIE = 1;

/* Enable ECAN1 Wake on bus activity Interrupt */
//C1INTEbits.WAKIE = 1;
}


#endif

void InitDma0()  //DMA channel 0 is used to transfer data at the end of the ADC conversion process
{
DMA0CONbits.AMODE = 0; // Configure DMA for Register indirect with post increment (used with conversion order mode)
DMA0CNT = NUMAIO*FILTERSAMPLES-1;

DMA0CONbits.MODE = 2; // Configure DMA for Continuous mode with ping-pong
DMA0PAD = (int)&ADC1BUF0;
DMA0REQ = 13;  //Select ADC1 convert done
DMA0STA = __builtin_dmaoffset(BufferA);
DMA0STB = __builtin_dmaoffset(BufferB);
_DMA0IP = 5;
IFS0bits.DMA0IF = 0; //Clear the DMA interrupt flag bit
IEC0bits.DMA0IE = 1; //Set the DMA interrupt enable bit
DMA0CONbits.CHEN = 1;

}



// This sets up the ADC sample and convert sequence.  This ADC is set up to run in scan mode,
// it cycles throught the specified channels.  After all are converted a DMA transfer
// occurs which transfers all values into memory locations.
// With this interrupt set to occur at xxkHz, and x channels to be scanned, new
// analog data is available at xkHz, although the samples were all taken x.xx microseconds apart.

void InitADC_WithIntrpt()
{
    AD1CON1bits.SSRC = 2;  //Clock source select
    //AD1CON1bits.ASAM = 1; //Auto-sample start bit
    AD1CON1bits.ASAM = 0; //Auto-sample start bit is set at 25Hz interrupt, and cleared after sampling is done.
    AD1CON1bits.AD12B = 1; //12 bit mode, disables simultaneous sampling
    AD1CON1bits.FORM = 2; //Report Results as un-signed Fractional.  i.e. dddd dddd dddd 0000 is the twelve bits

    AD1CON2bits.BUFM = 0;
    AD1CON2bits.CSCNA = 1;  //ScanINput Selections for CH0+ during Sample A bit
    AD1CON2bits.CHPS = 0;  //Converts CH0

    AD1CON3bits.ADCS = 1;  //Conversion clock select
    AD1CON3bits.SAMC = 0x1f;  //Auto-sample time bits

    AD1PCFGH = AIOMASK_H; // select specified analog input pins
    AD1PCFGL = AIOMASK_L; // select specified analog input pins

    AD1CSSH = ~AIOMASK_H; // Scan specified inputs
    AD1CSSL = ~AIOMASK_L; // Scan specified inputs

//Use Converson Order mode
    AD1CON1bits.ADDMABM = 1;  //DMA buffers are built in conversion order mode.
    AD1CON2bits.SMPI = NUMAIO-1;

# if FILTERSAMPLES == 1
    AD1CON4bits.DMABL = 0;
# endif
# if FILTERSAMPLES == 2
    AD1CON4bits.DMABL = 1;
# endif
# if FILTERSAMPLES == 4
    AD1CON4bits.DMABL = 2;
# endif
# if FILTERSAMPLES == 8
    AD1CON4bits.DMABL = 3;
# endif
# if FILTERSAMPLES == 16
    AD1CON4bits.DMABL = 4;
# endif
# if FILTERSAMPLES == 32
    AD1CON4bits.DMABL = 5;
# endif
# if FILTERSAMPLES == 64
    AD1CON4bits.DMABL = 6;
# endif
# if FILTERSAMPLES == 128
    AD1CON4bits.DMABL = 7;
# endif


    _AD1IF = 0;  //Clear Interrupt
    _AD1IE = 0;  //Do not Enable ADC Interrupt
    AD1CON1bits.ADON = 1;  //Enable ADC1

}


