/*********************************************************************
 *
 *                  DMA  transfer example 
 *
 *********************************************************************
 * FileName:        led_txfer.c
 * Dependencies:    plib.h
 *
 * Processor:       PIC32
 *
 * Compiler:        MPLAB XC32 v1 or higher
 *                  MPLAB IDE v8 or higher
 *
 * Author:    Bruce Land           Date:   May 2014
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/*********************************************************************
 *
 * This example blinks LEDs on the MIcroStickII board using a pattern stored in flash or RAM memory.
 * It uses the DMA controller to transfer data from flash to the I/O port controlling the LEDs.
 * The DMA transfer is initiated by a timer interrupt (we use the Timer23 in this example).
 * Once the pattern is completely transferred, the process is repeated.
 *
 ********************************************************************/
#include <plib.h>        /* PIC32 peripheral library */

#ifndef _DMAC
    #error "This example needs a PIC32MX processor with DMA controller present. Aborting build!"
#endif  // _DMAC


//  Configuration Bit settings
//  System Clock = 40 MHz,  Peripherial Bus = 40 MHz
//  Internal Osc w/PLL FNOSC = FRCPLL
//  Input Divider    2x Divider FPLLIDIV
//  Multiplier      20x Multiplier FPLLMUL
//  Output divider   2x Divider FPLLODIV
//  peripherial bus divider FPBDIV = 1
//  WDT disabled
//  Other options are don't care
//
#pragma config FNOSC = FRCPLL, POSCMOD = HS, FPLLIDIV = DIV_2, FPLLMUL = MUL_20, FPBDIV = DIV_1, FPLLODIV = DIV_2
#pragma config FWDTEN = OFF

#define	SYS_FREQ	40000000		// frequency we're running at


// type in the bytes that define the pattern that will be output to the LED's
// no longer than DmaGetMaxTxferSize()
// Rate varies in bust mode from 10 MHz to 5.5 MHz within the burst

// In Flash
static const unsigned char LED_pattern0[]=
{
	0x01,	0x00,	0x01,	0x00,	0x01,	0x00,	0x01,	0x00,
	0x01,	0x00,	0x01,	0x00,	0x01,	0x00,	0x01,	0x00
};


// In RAM
unsigned char	LED_pattern1[]=
{
	0x01,	0x00,	0x01,	0x00,	0x01,	0x00,	0x01,	0x00,
	0x01,	0x00,	0x01,	0x00,	0x01,	0x00,	0x01,	0x00
};

int main(void)
{
        // the DMA channels to use
	int	dmaChn0=0, dmaChn1=1 ;
        /*==
        CHPRI<1:0>: Channel Priority bits
        11 = Channel has priority 3 (highest)
        10 = Channel has priority 2
        01 = Channel has priority 1
        00 = Channel has priority 0
        */
        // The priority of each channel
        int     dmaPri0 = 0, dmaPri1 = 1; 
        // destination size
        int Dest_size = 1;  //byte

	// first let us set the LED I/O ports as digital outputs
        // PIN 2 on 28 pin PDIP
        mPORTAClearBits(BIT_0 );		//Clear bits to ensure light is off.
        mPORTASetPinsDigitalOut(BIT_0 );    //Set port as output

        // PIN 4 (B0) and 5 (B1) on 28 pin PDIP
        mPORTBClearBits(BIT_0 | BIT_1);		//Clear bits to ensure light is off.
        mPORTBSetPinsDigitalOut(BIT_0  | BIT_1);    //Set port as output
        
        //=== Channel 0 ===================
	// Open the desired DMA channel.
	// We enable the AUTO option, we'll keep repeating the sam transfer over and over.
	DmaChnOpen(dmaChn0, dmaPri0, DMA_OPEN_AUTO);
	// set the transfer parameters: source & destination address, source & destination size, number of bytes per event
        // Setting the last parameter to one makes the DMA output one byte/interrupt
        DmaChnSetTxfer(dmaChn0, LED_pattern0, (void*)&LATA, sizeof(LED_pattern0), Dest_size, sizeof(LED_pattern0));
	// set the transfer event control: what event is to start the DMA transfer
        // In this case, timer3 
	DmaChnSetEventControl(dmaChn0, DMA_EV_START_IRQ(_TIMER_3_IRQ));

        //=== Channel 1 ===================
        // Open the desired DMA channel.
	// We enable the AUTO option, we'll keep repeating the sam transfer over and over.
	DmaChnOpen(dmaChn1, dmaPri0, DMA_OPEN_AUTO);
	// set the transfer parameters: source & destination address, source & destination size, number of bytes per event
        // Setting the last parameter to one makes the DMA output one byte/interrupt
        DmaChnSetTxfer(dmaChn1, LED_pattern1, (void*)&LATB, sizeof(LED_pattern1), Dest_size, sizeof(LED_pattern1));
	// set the transfer event control: what event is to start the DMA transfer
        // In this case, timer3
	DmaChnSetEventControl(dmaChn1, DMA_EV_START_IRQ(_TIMER_3_IRQ));
	// once we configured the DMA channel we can enable it


	// now it's ready and waiting for an timer event to occur...
	DmaChnEnable(dmaChn0);
        DmaChnEnable(dmaChn1);


	// now use the 32 bit timer to generate an interrupt to start the
        // DMA burst ever 125 ticks
        OpenTimer23(T2_ON | T2_SOURCE_INT | T2_PS_1_1, 200); //400

        // Toggle a pin on a separate port to see how DMA affects normal execution
	while(1)
	{
		//mPORTBToggleBits(BIT_0);
	}


}





