Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:337ad0fe7734, committed 2013-12-29
- Comitter:
- Mischa
- Date:
- Sun Dec 29 01:00:30 2013 +0000
- Commit message:
- First version.
Changed in this revision
| DMAFuncGen.cpp | Show annotated file Show diff for this revision Revisions of this file |
| DMAFuncGen.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DMAFuncGen.cpp Sun Dec 29 01:00:30 2013 +0000
@@ -0,0 +1,120 @@
+#include "assert.h"
+#include "DMAFuncGen.h"
+
+//DigitalOut led1(LED1);
+
+DMAFuncGen::DMAFuncGen(MODDMA& dma, MODDMA::CHANNELS channel) : dma(dma) {
+ conf.channelNum( channel );
+ buffer_size = 0;
+ buffer = NULL;
+}
+
+#define DAC_POWER_MODE (0 << 16) // DAC output power mode.
+
+uint16_t DMAFuncGen::operator[](const uint16_t idx) {
+ assert(buffer!=NULL);
+ assert(idx<buffer_size);
+ return buffer[idx] & 0xFFC0;
+}
+
+void DMAFuncGen::set(int idx, uint16_t x) {
+ // V = (x>>6) × ((VrefP - VrefN)/1024) + VrefN; VrefN = 0V; VrefP = 3.3V;
+ buffer[idx] = DAC_POWER_MODE | (x & 0xFFC0);
+}
+
+void DMAFuncGen::Connect() {
+ // Connect DAC to pin
+ LPC_PINCON->PINSEL1 &= ~(3UL <<20);
+ LPC_PINCON->PINSEL1 |= 2UL <<20; //AOUT
+ LPC_PINCON->PINMODE1 &= ~(3UL <<20);
+ LPC_PINCON->PINMODE1 |= (2UL <<20); // neither pull-up nor pull-down
+ LPC_PINCON->PINMODE_OD0 &= ~(1UL <<26); // normal (not open drain) mode
+}
+
+void DMAFuncGen::Disconnect() {
+ LPC_PINCON->PINSEL1 &= ~(3UL <<20);
+ LPC_PINCON->PINSEL1 |= 1UL <<20; //AD0.3, input
+ LPC_PINCON->PINMODE1 &= ~(3UL <<20);
+ LPC_PINCON->PINMODE1 |= (2UL <<20); // neither pull-up nor pull-down
+ LPC_PINCON->PINMODE_OD0 &= ~(1UL <<26); // normal (not open drain) mode
+}
+
+void DMAFuncGen::Setup(void) {
+ // Prepare the GPDMA system.
+ lli.srcAddr( (uint32_t) buffer );
+ lli.dstAddr( (uint32_t) &LPC_DAC->DACR );
+ lli.nextLLI( (uint32_t) &lli);
+ lli.control( dma.CxControl_TransferSize(buffer_size)
+ | dma.CxControl_SBSize((uint32_t)MODDMA::_1)
+ | dma.CxControl_DBSize((uint32_t)MODDMA::_1)
+ | dma.CxControl_SWidth((uint32_t)MODDMA::word)
+ | dma.CxControl_DWidth((uint32_t)MODDMA::word)
+ | dma.CxControl_SI()
+ | dma.CxControl_I() );
+
+ conf.srcMemAddr ( (uint32_t) buffer )
+ ->dstMemAddr ( MODDMA::DAC ) // unnecessary?
+ ->transferSize ( buffer_size )
+ ->transferType ( MODDMA::m2p )
+ ->dstConn ( MODDMA::DAC )
+ ->dmaLLI ( (uint32_t) &lli )
+ ->attach_tc ( this, &DMAFuncGen::TC_callback )
+ ->attach_err ( this, &DMAFuncGen::ERR_callback );
+
+ // Setup dma.
+ if (!dma.Setup( &conf )) {
+ error("Unexpected error during DMA.Setup(conf)");
+ }
+}
+
+float DMAFuncGen::Frequency() {
+ float f;
+ f=SystemCoreClock;
+ const int divisors[4] = {4,1,2,8};
+ f/=divisors[((LPC_SC->PCLKSEL0) >> 22) & 0x03];
+ f/=buffer_size;
+ f/=LPC_DAC->DACCNTVAL;
+ return f;
+}
+
+void DMAFuncGen::SetFrequency(float f) {
+ // Set the transfer frequency.
+ float cntval;
+ cntval = SystemCoreClock/(f*buffer_size);
+ const int PCLK_DAC[4] = {1,2,0,3};
+ int i=0;
+ int divisor=1;
+ while (((cntval/divisor)>65535) && (i<4)) {divisor*=2; i++; }
+ if (i==4) { divisor=8; i=3; }
+ LPC_SC->PCLKSEL0 &= ~(3UL<<22);
+ LPC_SC->PCLKSEL0 |= ((uint32_t) PCLK_DAC[i])<<22;
+ LPC_DAC->DACCNTVAL = cntval/divisor;
+}
+
+void DMAFuncGen::Start() {
+ dma.Enable( &conf );
+
+ // Enable DMA, and TC interrupt
+ LPC_DAC->DACCTRL = 3UL<<2; // DMA_ENA set, DMA_CNT set
+}
+
+void DMAFuncGen::Stop() {
+ dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS) conf.channelNum() );
+ LPC_DAC->DACCTRL = 0UL<<2;
+}
+
+// Configuration callback on TC
+void DMAFuncGen::TC_callback(void) {
+
+ // Just show sending buffer complete.
+ // led1 = !led1;
+
+ // Clear DMA IRQ flags.
+ if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
+}
+
+// Configuration callback on Error
+void DMAFuncGen::ERR_callback(void) {
+ error("Unexpected error - DMA error callback.");
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DMAFuncGen.h Sun Dec 29 01:00:30 2013 +0000
@@ -0,0 +1,63 @@
+#ifndef MBED_DMAFUNCGEN_H
+#define MBED_DMAFUNCGEN_H
+
+#include "mbed.h"
+#include "MODDMA.h"
+
+//! DMAFuncGen class generates a waveform on Analog output using Direct Memory Access alone.
+class DMAFuncGen {
+public:
+ /// Create DMAFucGen instance
+ /// @param dma The dma to use.
+ /// @param channel The dma channel to use for transferring data to the D/A converter.
+ DMAFuncGen(MODDMA& dma, MODDMA::CHANNELS channel);
+
+ /// Number of data points in the waveform. Must be set by client.
+ int buffer_size;
+ /// Buffer for the binary data that will be transferred by DMA. Must be allocated by client.
+ uint32_t* buffer;
+
+ /// Set waveform value for a specified data point.
+ /// @param idx The index of the data point in #buffer, must be in range 0..#buffer_size-1.
+ /// @param x The value for the D/A, in the range 0..65535.
+ void set(int idx, uint16_t x);
+ /// Get waveform value for a specified data point
+ /// @param idx The index of the data point in the #buffer, in the range 0..#buffer_size-1.
+ /// @returns The value for the data point, in the range 0..65535.
+ uint16_t operator[](const uint16_t idx);
+
+ /// Connect the D/A converter pin (enable output)
+ void Connect();
+ /// Disconnect the D/A converter pin (pin becomes tri-state)
+ void Disconnect();
+
+ /// Reference to the DMA instance
+ MODDMA& dma;
+
+ /// Set up the dma.
+ /// Must set #buffer and #buffer_size first.
+ void Setup(void);
+
+ /// Set waveform frequency
+ /// @note Must set #buffer_size first.
+ /// @param f Frequency of a complete cycle of the waveform (in Hz).
+ void SetFrequency(float f);
+ /// Read the actual waveform frequency that will be generated.
+ float Frequency();
+
+ /// Start generating the waveform (start dma)
+ void Start();
+ /// Stop generating the waveform (but waits for the current cycle to complete)
+ void Stop();
+
+private:
+ MODDMA_Config conf;
+ MODDMA_LLI lli;
+
+ /// ISR routine, called on Terminal Count
+ void TC_callback(void);
+ /// ISR routine, called on dma ERRor
+ void ERR_callback(void);
+};
+
+#endif