http://http://diytec.web.fc2.com/mark2r2/
Dependencies: EthernetNetIf NTPClient_NetServices mbed ConfigFile
MODDMA/example4.h@0:08a4d61cd84c, 2011-09-20 (annotated)
- Committer:
- mark2r2
- Date:
- Tue Sep 20 12:46:26 2011 +0000
- Revision:
- 0:08a4d61cd84c
V1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mark2r2 | 0:08a4d61cd84c | 1 | /* |
mark2r2 | 0:08a4d61cd84c | 2 | * Demonstrates sending a buffer repeatedly to the DAC using DMA. |
mark2r2 | 0:08a4d61cd84c | 3 | * Connect an oscilloscope to Mbed pin 18. This example doesn't |
mark2r2 | 0:08a4d61cd84c | 4 | * output anything else (nothing on any serial ports). |
mark2r2 | 0:08a4d61cd84c | 5 | */ |
mark2r2 | 0:08a4d61cd84c | 6 | #include "mbed.h" |
mark2r2 | 0:08a4d61cd84c | 7 | #include "MODDMA.h" |
mark2r2 | 0:08a4d61cd84c | 8 | |
mark2r2 | 0:08a4d61cd84c | 9 | // Make the buffer size match the number of degrees |
mark2r2 | 0:08a4d61cd84c | 10 | // in a circle since we are going to output a sinewave. |
mark2r2 | 0:08a4d61cd84c | 11 | #define BUFFER_SIZE 360 |
mark2r2 | 0:08a4d61cd84c | 12 | |
mark2r2 | 0:08a4d61cd84c | 13 | // Set DAC output power mode. |
mark2r2 | 0:08a4d61cd84c | 14 | #define DAC_POWER_MODE (1 << 16) |
mark2r2 | 0:08a4d61cd84c | 15 | |
mark2r2 | 0:08a4d61cd84c | 16 | DigitalOut led1(LED1); |
mark2r2 | 0:08a4d61cd84c | 17 | DigitalOut led3(LED3); |
mark2r2 | 0:08a4d61cd84c | 18 | DigitalOut led4(LED4); |
mark2r2 | 0:08a4d61cd84c | 19 | |
mark2r2 | 0:08a4d61cd84c | 20 | int buffer[2][BUFFER_SIZE]; |
mark2r2 | 0:08a4d61cd84c | 21 | |
mark2r2 | 0:08a4d61cd84c | 22 | AnalogOut signal(p18); |
mark2r2 | 0:08a4d61cd84c | 23 | |
mark2r2 | 0:08a4d61cd84c | 24 | MODDMA dma; |
mark2r2 | 0:08a4d61cd84c | 25 | MODDMA_Config *conf0, *conf1; |
mark2r2 | 0:08a4d61cd84c | 26 | |
mark2r2 | 0:08a4d61cd84c | 27 | void TC0_callback(void); |
mark2r2 | 0:08a4d61cd84c | 28 | void ERR0_callback(void); |
mark2r2 | 0:08a4d61cd84c | 29 | |
mark2r2 | 0:08a4d61cd84c | 30 | void TC1_callback(void); |
mark2r2 | 0:08a4d61cd84c | 31 | void ERR1_callback(void); |
mark2r2 | 0:08a4d61cd84c | 32 | |
mark2r2 | 0:08a4d61cd84c | 33 | int main() { |
mark2r2 | 0:08a4d61cd84c | 34 | volatile int life_counter = 0; |
mark2r2 | 0:08a4d61cd84c | 35 | |
mark2r2 | 0:08a4d61cd84c | 36 | // Create a sinewave buffer for testing. |
mark2r2 | 0:08a4d61cd84c | 37 | for (int i = 0; i <= 90; i++) buffer[0][i] = (512 * sin(3.14159/180.0 * i)) + 512; |
mark2r2 | 0:08a4d61cd84c | 38 | for (int i = 91; i <= 180; i++) buffer[0][i] = buffer[0][180 - i]; |
mark2r2 | 0:08a4d61cd84c | 39 | for (int i = 181; i <= 270; i++) buffer[0][i] = 512 - (buffer[0][i - 180] - 512); |
mark2r2 | 0:08a4d61cd84c | 40 | for (int i = 271; i < 360; i++) buffer[0][i] = 512 - (buffer[0][360 - i] - 512); |
mark2r2 | 0:08a4d61cd84c | 41 | |
mark2r2 | 0:08a4d61cd84c | 42 | // Adjust the sinewave buffer for use with DAC hardware. |
mark2r2 | 0:08a4d61cd84c | 43 | for (int i = 0; i < 360; i++) { |
mark2r2 | 0:08a4d61cd84c | 44 | buffer[0][i] = DAC_POWER_MODE | ((buffer[0][i] << 6) & 0xFFC0); |
mark2r2 | 0:08a4d61cd84c | 45 | buffer[1][i] = buffer[0][i]; // Just create a copy of buffer0 to continue sinewave. |
mark2r2 | 0:08a4d61cd84c | 46 | } |
mark2r2 | 0:08a4d61cd84c | 47 | |
mark2r2 | 0:08a4d61cd84c | 48 | // Prepare the GPDMA system for buffer0. |
mark2r2 | 0:08a4d61cd84c | 49 | conf0 = new MODDMA_Config; |
mark2r2 | 0:08a4d61cd84c | 50 | conf0 |
mark2r2 | 0:08a4d61cd84c | 51 | ->channelNum ( MODDMA::Channel_0 ) |
mark2r2 | 0:08a4d61cd84c | 52 | ->srcMemAddr ( (uint32_t) &buffer[0] ) |
mark2r2 | 0:08a4d61cd84c | 53 | ->dstMemAddr ( MODDMA::DAC ) |
mark2r2 | 0:08a4d61cd84c | 54 | ->transferSize ( 360 ) |
mark2r2 | 0:08a4d61cd84c | 55 | ->transferType ( MODDMA::m2p ) |
mark2r2 | 0:08a4d61cd84c | 56 | ->dstConn ( MODDMA::DAC ) |
mark2r2 | 0:08a4d61cd84c | 57 | ->attach_tc ( &TC0_callback ) |
mark2r2 | 0:08a4d61cd84c | 58 | ->attach_err ( &ERR0_callback ) |
mark2r2 | 0:08a4d61cd84c | 59 | ; // config end |
mark2r2 | 0:08a4d61cd84c | 60 | |
mark2r2 | 0:08a4d61cd84c | 61 | |
mark2r2 | 0:08a4d61cd84c | 62 | // Prepare the GPDMA system for buffer1. |
mark2r2 | 0:08a4d61cd84c | 63 | conf1 = new MODDMA_Config; |
mark2r2 | 0:08a4d61cd84c | 64 | conf1 |
mark2r2 | 0:08a4d61cd84c | 65 | ->channelNum ( MODDMA::Channel_1 ) |
mark2r2 | 0:08a4d61cd84c | 66 | ->srcMemAddr ( (uint32_t) &buffer[1] ) |
mark2r2 | 0:08a4d61cd84c | 67 | ->dstMemAddr ( MODDMA::DAC ) |
mark2r2 | 0:08a4d61cd84c | 68 | ->transferSize ( 360 ) |
mark2r2 | 0:08a4d61cd84c | 69 | ->transferType ( MODDMA::m2p ) |
mark2r2 | 0:08a4d61cd84c | 70 | ->dstConn ( MODDMA::DAC ) |
mark2r2 | 0:08a4d61cd84c | 71 | ->attach_tc ( &TC1_callback ) |
mark2r2 | 0:08a4d61cd84c | 72 | ->attach_err ( &ERR1_callback ) |
mark2r2 | 0:08a4d61cd84c | 73 | ; // config end |
mark2r2 | 0:08a4d61cd84c | 74 | |
mark2r2 | 0:08a4d61cd84c | 75 | |
mark2r2 | 0:08a4d61cd84c | 76 | // Calculating the transfer frequency: |
mark2r2 | 0:08a4d61cd84c | 77 | // By default, the Mbed library sets the PCLK_DAC clock value |
mark2r2 | 0:08a4d61cd84c | 78 | // to 24MHz. One complete sinewave cycle in each buffer is 360 |
mark2r2 | 0:08a4d61cd84c | 79 | // points long. So, for a 1Hz wave we would need to transfer 360 |
mark2r2 | 0:08a4d61cd84c | 80 | // values per second. That would be 24000000/360 which is approx |
mark2r2 | 0:08a4d61cd84c | 81 | // 66,666. But that's no good! The count val is only 16bits in size |
mark2r2 | 0:08a4d61cd84c | 82 | // so bare this in mind. If you need to go slower you will need to |
mark2r2 | 0:08a4d61cd84c | 83 | // alter PCLK_DAC from CCLK/4 to CCLK/8. |
mark2r2 | 0:08a4d61cd84c | 84 | // For our demo we are going to have the sinewave run at 1kHz. |
mark2r2 | 0:08a4d61cd84c | 85 | // That's 24000000/360000 which is approx 66. Experimentation |
mark2r2 | 0:08a4d61cd84c | 86 | // however showed 65 to get closer to 1kHz (on my Mbed and scope |
mark2r2 | 0:08a4d61cd84c | 87 | // at least). |
mark2r2 | 0:08a4d61cd84c | 88 | LPC_DAC->DACCNTVAL = 65; // 6500 for 10Hz |
mark2r2 | 0:08a4d61cd84c | 89 | |
mark2r2 | 0:08a4d61cd84c | 90 | // Prepare first configuration. |
mark2r2 | 0:08a4d61cd84c | 91 | if (!dma.Prepare( conf0 )) { |
mark2r2 | 0:08a4d61cd84c | 92 | error("Doh!"); |
mark2r2 | 0:08a4d61cd84c | 93 | } |
mark2r2 | 0:08a4d61cd84c | 94 | |
mark2r2 | 0:08a4d61cd84c | 95 | // Begin (enable DMA and counter). Note, don't enable |
mark2r2 | 0:08a4d61cd84c | 96 | // DBLBUF_ENA as we are using DMA double buffering. |
mark2r2 | 0:08a4d61cd84c | 97 | LPC_DAC->DACCTRL |= (3UL << 2); |
mark2r2 | 0:08a4d61cd84c | 98 | |
mark2r2 | 0:08a4d61cd84c | 99 | while (1) { |
mark2r2 | 0:08a4d61cd84c | 100 | // There's not a lot to do as DMA and interrupts are |
mark2r2 | 0:08a4d61cd84c | 101 | // now handling the buffer transfers. So we'll just |
mark2r2 | 0:08a4d61cd84c | 102 | // flash led1 to show the Mbed is alive and kicking. |
mark2r2 | 0:08a4d61cd84c | 103 | if (life_counter++ > 1000000) { |
mark2r2 | 0:08a4d61cd84c | 104 | led1 = !led1; // Show some sort of life. |
mark2r2 | 0:08a4d61cd84c | 105 | life_counter = 0; |
mark2r2 | 0:08a4d61cd84c | 106 | } |
mark2r2 | 0:08a4d61cd84c | 107 | } |
mark2r2 | 0:08a4d61cd84c | 108 | } |
mark2r2 | 0:08a4d61cd84c | 109 | |
mark2r2 | 0:08a4d61cd84c | 110 | // Configuration callback on TC |
mark2r2 | 0:08a4d61cd84c | 111 | void TC0_callback(void) { |
mark2r2 | 0:08a4d61cd84c | 112 | |
mark2r2 | 0:08a4d61cd84c | 113 | // Just show sending buffer0 complete. |
mark2r2 | 0:08a4d61cd84c | 114 | led3 = !led3; |
mark2r2 | 0:08a4d61cd84c | 115 | |
mark2r2 | 0:08a4d61cd84c | 116 | // Get configuration pointer. |
mark2r2 | 0:08a4d61cd84c | 117 | MODDMA_Config *config = dma.getConfig(); |
mark2r2 | 0:08a4d61cd84c | 118 | |
mark2r2 | 0:08a4d61cd84c | 119 | // Finish the DMA cycle by shutting down the channel. |
mark2r2 | 0:08a4d61cd84c | 120 | dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); |
mark2r2 | 0:08a4d61cd84c | 121 | |
mark2r2 | 0:08a4d61cd84c | 122 | // Swap to buffer1 |
mark2r2 | 0:08a4d61cd84c | 123 | dma.Prepare( conf1 ); |
mark2r2 | 0:08a4d61cd84c | 124 | |
mark2r2 | 0:08a4d61cd84c | 125 | // Clear DMA IRQ flags. |
mark2r2 | 0:08a4d61cd84c | 126 | if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); |
mark2r2 | 0:08a4d61cd84c | 127 | } |
mark2r2 | 0:08a4d61cd84c | 128 | |
mark2r2 | 0:08a4d61cd84c | 129 | // Configuration callback on Error |
mark2r2 | 0:08a4d61cd84c | 130 | void ERR0_callback(void) { |
mark2r2 | 0:08a4d61cd84c | 131 | error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); |
mark2r2 | 0:08a4d61cd84c | 132 | } |
mark2r2 | 0:08a4d61cd84c | 133 | |
mark2r2 | 0:08a4d61cd84c | 134 | // Configuration callback on TC |
mark2r2 | 0:08a4d61cd84c | 135 | void TC1_callback(void) { |
mark2r2 | 0:08a4d61cd84c | 136 | |
mark2r2 | 0:08a4d61cd84c | 137 | // Just show sending buffer1 complete. |
mark2r2 | 0:08a4d61cd84c | 138 | led4 = !led4; |
mark2r2 | 0:08a4d61cd84c | 139 | |
mark2r2 | 0:08a4d61cd84c | 140 | // Get configuration pointer. |
mark2r2 | 0:08a4d61cd84c | 141 | MODDMA_Config *config = dma.getConfig(); |
mark2r2 | 0:08a4d61cd84c | 142 | |
mark2r2 | 0:08a4d61cd84c | 143 | // Finish the DMA cycle by shutting down the channel. |
mark2r2 | 0:08a4d61cd84c | 144 | dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); |
mark2r2 | 0:08a4d61cd84c | 145 | |
mark2r2 | 0:08a4d61cd84c | 146 | // Swap to buffer0 |
mark2r2 | 0:08a4d61cd84c | 147 | dma.Prepare( conf0 ); |
mark2r2 | 0:08a4d61cd84c | 148 | |
mark2r2 | 0:08a4d61cd84c | 149 | // Clear DMA IRQ flags. |
mark2r2 | 0:08a4d61cd84c | 150 | if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); |
mark2r2 | 0:08a4d61cd84c | 151 | } |
mark2r2 | 0:08a4d61cd84c | 152 | |
mark2r2 | 0:08a4d61cd84c | 153 | // Configuration callback on Error |
mark2r2 | 0:08a4d61cd84c | 154 | void ERR1_callback(void) { |
mark2r2 | 0:08a4d61cd84c | 155 | error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); |
mark2r2 | 0:08a4d61cd84c | 156 | } |