Jared's DAC Code

Dependencies:   mbed

Dependents:   DCS_FINAL_CODE

Fork of Chemical_Sensor_DMA by Jared Baxter

Sample/dma.cpp

Committer:
baxterja
Date:
2015-10-29
Revision:
2:3771b3195c7b
Child:
3:a85b742be262

File content as of revision 2:3771b3195c7b:

/**
 *  Setup triggering for DMA2 and PortC
 */
#include "dma.h"

DigitalOut toggle_dma0(LED_RED);
DigitalOut toggle_dma1(LED_BLUE);
DigitalOut toggle_dma2(LED_GREEN);
Serial debug3(USBTX,USBRX);

//#define TOTAL_SAMPLES 30000
//#define FILENAME_SIZE 26 // this matches what is defined in DistanceFirmware's main.cpp
int len = TOTAL_SAMPLES;
uint16_t sample_array0[TOTAL_SAMPLES];
uint16_t sample_array1[TOTAL_SAMPLES];
uint16_t angle_array[TOTAL_SAMPLES+FILENAME_SIZE];
bool dma_done = false;
bool dma_half_done = false;



/*  DMA0 and DMA1 are triggered by ADC0 and ADC1 (which are triggered
 *  by the PDB).  However, DMA2 is triggered directly by the PDB.  This
 *  is becuase DMA2 is reading FTM2, which cannot trigger the DMA.   */
void dma_init()
{
    toggle_dma0 = 1;
    toggle_dma1 = 1;
    toggle_dma2 = 1;
    // Enable clock for DMAMUX and DMA
    SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
    SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;  
    SIM_SCGC6 |= SIM_SCGC6_FTM2_MASK; // make sure clock is enabled for FTM2  
            
    // Enable DMA channels and select MUX to the correct source (see page 95 of user manual
    DMAMUX_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(40); // ADC0
    DMAMUX_CHCFG1 |= DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(41); // ADC1
    DMAMUX_CHCFG2 |= DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(48); // Set trigger source to PDB (Don't set DMA Trig Enable because that is for the PIT)
    /* Source number    Source module
           40                ADC0
           41                ADC1
           48                PDB
    */
    
    
    // Enable request signal for channel 0 
    DMA_ERQ = DMA_ERQ_ERQ0_MASK | DMA_ERQ_ERQ1_MASK | DMA_ERQ_ERQ2_MASK;
    
    // select round-robin arbitration priority
    DMA_CR |= DMA_CR_ERCA_MASK;
    
    // Set memory address for source and destination for DMA0, DMA1, and DMA2
    DMA_TCD0_SADDR = (uint32_t) &ADC0_RB;
    DMA_TCD0_DADDR = (uint32_t) sample_array0;
    DMA_TCD1_SADDR = (uint32_t) &ADC1_RA;
    DMA_TCD1_DADDR = (uint32_t) sample_array1;
    DMA_TCD2_SADDR = (uint32_t) &FTM2_CNT;
    DMA_TCD2_DADDR = (uint32_t) angle_array;
    
    // Set an offset for source and destination address
    DMA_TCD0_SOFF = 0x00; // Source address offset of 2 bits per transaction
    DMA_TCD0_DOFF = 0x02; // Destination address offset of 1 bit per transaction
    DMA_TCD1_SOFF = 0x00; // Source address offset of 2 bits per transaction
    DMA_TCD1_DOFF = 0x02; // Destination address offset of 1 bit per transaction
    DMA_TCD2_SOFF = 0x00; // Source address offset of 2 bits per transaction
    DMA_TCD2_DOFF = 0x02; // Destination address offset of 1 bit per transaction
        
    // Set source and destination data transfer size
    DMA_TCD0_ATTR = DMA_ATTR_SSIZE(1) | DMA_ATTR_DSIZE(1);
    DMA_TCD1_ATTR = DMA_ATTR_SSIZE(1) | DMA_ATTR_DSIZE(1);
    DMA_TCD2_ATTR = DMA_ATTR_SSIZE(1) | DMA_ATTR_DSIZE(1);
        
    // Number of bytes to be transfered in each service request of the channel
    DMA_TCD0_NBYTES_MLNO = 0x02;
    DMA_TCD1_NBYTES_MLNO = 0x02;
    DMA_TCD2_NBYTES_MLNO = 0x02;
        
    // Current major iteration count
    DMA_TCD0_CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(len);
    DMA_TCD0_BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(len);
    DMA_TCD1_CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(len);
    DMA_TCD1_BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(len);
    DMA_TCD2_CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(len);
    DMA_TCD2_BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(len);
    
    // Adjustment value used to restore the source and destiny address to the initial value
    // After reading 'len' number of times, the DMA goes back to the beginning by subtracting len*2 from the address (going back to the original address)
    
    DMA_TCD0_SLAST = 0;      // Source address adjustment
    DMA_TCD0_DLASTSGA = -len*2;  // Destination address adjustment
    DMA_TCD1_SLAST = 0;      // Source address adjustment
    DMA_TCD1_DLASTSGA = -len*2;  // Destination address adjustment
    DMA_TCD2_SLAST = 0;      // Source address adjustment
    DMA_TCD2_DLASTSGA = -len*2;  // Destination address adjustment
    
    // Setup control and status register
    DMA_TCD0_CSR = 0;
    DMA_TCD1_CSR = 0;
    DMA_TCD2_CSR = 0;
    
    // enable interrupt call at end of major loop
    DMA_TCD0_CSR |= DMA_CSR_INTMAJOR_MASK | DMA_CSR_INTHALF_MASK;
    
    // add interrupt handlers to interrupt vector table
    NVIC_SetVector(DMA0_IRQn, (uint32_t)&DMA_IRQHandler);
    
    //enable interrupts
    NVIC_EnableIRQ(DMA0_IRQn);
    
    // dma_init takes 4.09us to run.
}

void dma_reset() {
    dma_done = false;
    dma_half_done = false;
    
    // clear all DMA interrupts
    DMA_CINT = DMA_CINT_CAIR_MASK;
    
    //enable interrupts
    NVIC_EnableIRQ(DMA0_IRQn);
}

/* The only DMA interrupt is from DMA0.  The interrupts from DMA1 and DMA2
 * are turned off because they all trigger at the same time.  Actually
 * DMA2 triggers just before DMA0 and DMA1, but it's a negligible amount 
 * of time.  By the time the PDB is turned off, the ADCs will have already
 * been triggered.  */
void DMA_IRQHandler() {
    
    DMA_CINT |= DMA_CINT_CINT(0); // clear interrupt flag
    //toggle_dma0 = 0;
    //debug3.printf("DMA ");
    if(!dma_half_done) {
        dma_half_done = true;
        //debug3.printf("half done\r\n");
        return;
    }
    //PDB0_SC &= ~PDB_SC_PDBEN_MASK;  // disable PDB
    //NVIC_DisableIRQ(DMA0_IRQn); // disable interrupt
    dma_done = true;
    //debug3.printf("done\r\n");
}














/* * * * * * * * * * * * * * For Debugging Purposes * * * * * * * * * * * * * * * * * * * * */


void dma_print_registers() {
    
    debug3.printf("SADDR0: 0x%08x\r\n",DMA_TCD0_SADDR);
    debug3.printf("DADDR0: 0x%08x\r\n",DMA_TCD0_DADDR);
    debug3.printf("SADDR1: 0x%08x\r\n",DMA_TCD1_SADDR);
    debug3.printf("DADDR1: 0x%08x\r\n",DMA_TCD1_DADDR);
    debug3.printf("SADDR2: 0x%08x\r\n",DMA_TCD2_SADDR);
    debug3.printf("DADDR2: 0x%08x\r\n",DMA_TCD2_DADDR);
    
    debug3.printf("CITER0: 0x%08x\r\n",DMA_TCD0_CITER_ELINKNO);
    debug3.printf("BITER0: 0x%08x\r\n",DMA_TCD0_BITER_ELINKNO);
    debug3.printf("CITER1: 0x%08x\r\n",DMA_TCD1_CITER_ELINKNO);
    debug3.printf("BITER1: 0x%08x\r\n",DMA_TCD1_BITER_ELINKNO);
    debug3.printf("CITER2: 0x%08x\r\n",DMA_TCD2_CITER_ELINKNO);
    debug3.printf("BITER2: 0x%08x\r\n",DMA_TCD2_BITER_ELINKNO);
    
    
    debug3.printf("DMA_CR: %08x\r\n", DMA_CR);
    debug3.printf("DMA_ES: %08x\r\n", DMA_ES);
    debug3.printf("DMA_ERQ: %08x\r\n", DMA_ERQ);
    debug3.printf("DMA_EEI: %08x\r\n", DMA_EEI);
    debug3.printf("DMA_CEEI: %02x\r\n", DMA_CEEI);
    debug3.printf("DMA_SEEI: %02x\r\n", DMA_SEEI);
    debug3.printf("DMA_CERQ: %02x\r\n", DMA_CERQ);
    debug3.printf("DMA_SERQ: %02x\r\n", DMA_SERQ);
    debug3.printf("DMA_CDNE: %02x\r\n", DMA_CDNE);
    debug3.printf("DMA_SSRT: %02x\r\n", DMA_SSRT);
    debug3.printf("DMA_CERR: %02x\r\n", DMA_CERR);
    debug3.printf("DMA_CINT: %02x\r\n", DMA_CINT);
    debug3.printf("DMA_INT: %08x\r\n", DMA_INT);
    debug3.printf("DMA_ERR: %08x\r\n", DMA_ERR);
    debug3.printf("DMA_HRS: %08x\r\n", DMA_HRS);
    
}