Fork of Andy Kirkham's MODDMA GPDMA Controller for Mbed OS 6

Read MODDMA for more info.

Committer:
hudakz
Date:
Mon Dec 12 15:08:37 2022 +0000
Revision:
20:01d0a680e45a
Parent:
19:bf3ae4c3635d
Fork of Andy Kirkham's MODDMA GPDMA Controller for Mbed OS 6.; The examples are updated in order to compile with Mbed OS 6.

Who changed what in which revision?

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