Fork of Andy Kirkham's MODDMA GPDMA Controller for Mbed OS 6
Read MODDMA for more info.
example4.h@20:01d0a680e45a, 22 months ago (annotated)
- 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?
User | Revision | Line number | New 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 | } |