-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDMA.c
89 lines (77 loc) · 3.65 KB
/
DMA.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* Direct Memory Access functionality */
#include "DMA.h"
#include <xc.h>
#include <dsp.h>
// Allocate memory for Buffer A and Buffer B in DMA memory
fractional BufferA[NUM_SAMPLES] __attribute__((space(dma), aligned(256)));
fractional BufferB[NUM_SAMPLES] __attribute__((space(dma), aligned(256)));
/*******************************************************************************
* Initialise DMA Channel 4 to retrieve data from ADC in continuous ping-pong
* mode
******************************************************************************/
void initADC_DMA(void)
{
DMA_ADC_DATA_DIR = PERIPHERAL_TO_DMA; // TX from ADC to DMA
DMA_ADC_DATA_TX_SIZE = DMA_WORD; // transfer 16 bits of data
DMA_ADC_INTERRUPT_CONDITION = WHEN_ALL_DATA_MOVED;
DMA_ADC_ADDRESS_MODE = POST_INCREMENT; // DMA takes care of addressing
DMA_ADC_CH_MODE = CONTINUOUS_PING_PONG; // 2 buffers to write to
DMA4PAD = (volatile unsigned int)&ADC1BUF0; // Transfer data from ADC buffer
DMA4CNT = NUM_SAMPLES-1; // Raise DMA interrupt after every NUM_SAMPLES
DMA4REQ = DMA_IRQ_ADC1; // ADC interrupt selected for DMA IRQ
// DMA controller needs to know where in DMA memory BufferA and B start
DMA4STA = __builtin_dmaoffset(BufferA);
DMA4STB = __builtin_dmaoffset(BufferB);
// Clear interrupt flag bit and enable DMA4 interrupts
DMA_ADC_INTERRUPT_FLAG = NO_INTERRUPT;
DMA_ADC_INTERRUPT = ENABLE_INTERRUPT;
DMA_ADC_ENABLE;
}
/*******************************************************************************
* Interrupt Service Routine (ISR) for DMA Channel 4
******************************************************************************/
unsigned int DMA_buffer = BUFFER_B;
int adc_finished = 0;
void __attribute__((interrupt, no_auto_psv)) _DMA4Interrupt(void)
{
// Clear interrupt flag
DMA_ADC_INTERRUPT_FLAG = NO_INTERRUPT;
// Change the buffer to which we're storing ADC values
if (DMA_buffer == BUFFER_A)
DMA_buffer = BUFFER_B;
else
DMA_buffer = BUFFER_A;
adc_finished = 1;
}
/*******************************************************************************
* Initialise DMA Channel 5 to transfer data from memory to DAC Right channel
* peripheral
* Don't bother with this!
* couldn't get it working with ADC DMA (Marko 20/07/2015)
******************************************************************************/
void initDAC_DMA(void)
{
DMA_DAC_DATA_DIR = DMA_TO_PERIPHERAL; // TX from ADC to DMA
DMA_DAC_DATA_TX_SIZE = DMA_WORD; // transfer 16 bits of data
DMA_DAC_INTERRUPT_CONDITION = WHEN_ALL_DATA_MOVED;
DMA_DAC_ADDRESS_MODE = POST_INCREMENT; // DMA takes care of addressing
DMA_DAC_CH_MODE = CONTINUOUS_PING_PONG; // 2 buffers to write to
DMA5PAD = (volatile unsigned int)&DAC1RDAT; // Transfer data to DAC FIFO
DMA5CNT = NUM_SAMPLES-1; // Raise DMA interrupt after every NUM_SAMPLES
DMA5REQ = DMA_IRQ_DAC1_RIGHT; // DAC interrupt selected for DMA IRQ
// DMA controller needs to know where in DMA memory BufferA and B start
DMA5STA = __builtin_dmaoffset(BufferB);
DMA5STB = __builtin_dmaoffset(BufferA);
// Clear interrupt flag bit and enable DMA4 interrupts
DMA_DAC_INTERRUPT_FLAG = NO_INTERRUPT;
DMA_DAC_INTERRUPT = ENABLE_INTERRUPT;
DMA_DAC_ENABLE;
}
/*******************************************************************************
* Interrupt Service Routine (ISR) for DMA Channel 5
******************************************************************************/
void __attribute__((interrupt, no_auto_psv)) _DMA5Interrupt(void)
{
// Clear interrupt flag
DMA_DAC_INTERRUPT_FLAG = NO_INTERRUPT;
}