Signal Generator

Dependencies:   IniManager RA8875 Watchdog mbed-rtos mbed

Fork of speaker_demo_Analog by jim hamblen

Revision:
3:d22f3e52d06a
Parent:
2:8f71b71fce1b
Child:
4:10281ddb673d
--- a/SignalGenDAC.cpp	Sun Jan 15 03:11:22 2017 +0000
+++ b/SignalGenDAC.cpp	Mon Jan 16 04:33:06 2017 +0000
@@ -12,9 +12,11 @@
     uint32_t  control;    /// DMACCxControl register
 } LinkListItem_t;    
 
-/// The signal memory, which is DMA sent to the DAC to play the waveform
+/// The DACsignal memory, which is DMA sent to the DAC to play the waveform,
+/// produced by scaling the VoltSignal array
 ///
-float /*signed long*/ signal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0")));
+float VoltSignal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0")));
+signed long DACsignal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0")));
 
 /// The linked list item record, used by the DMA engine to decide how to play
 ///
@@ -30,9 +32,15 @@
 }
 
 void SignalGenDAC::Start(bool oneShot) {
+    printf("Start(%d)\r\n", oneShot ? 1 : 0);
+    LPC_GPDMACH0->DMACCLLI       = (oneShot) ? 0 : (uint32_t) &llio;
+    isOn = (oneShot) ? false : true;
 }
 
 void SignalGenDAC::Stop(void) {
+    printf("Stop()\r\n");
+    LPC_GPDMACH0->DMACCLLI       = 0;
+    isOn = false;
 }
 
 
@@ -57,12 +65,11 @@
             for (x=0; x<numSamples; x++) {
                 if (x < dcCount) {
                     v = offset + voltage/2 * sin(x * 1 * PI / dcCount);
-                    v = rangelimit(v, minV, maxV);
                 } else {
                     v = offset - voltage/2 * sin((x - dcCount) * 1 * PI / (numSamples-dcCount));
-                    v = rangelimit(v, minV, maxV);
                 }
-                signal[x] = v;
+                v = rangelimit(v, minV, maxV);
+                VoltSignal[x] = v;
             }
             break;
         case SG_SQUARE:
@@ -72,39 +79,96 @@
                 } else {
                     v = rangelimit(offset - voltage/2, minV, maxV);
                 }
-                signal[x] = v;
+                VoltSignal[x] = v;
             }
             break;
         case SG_TRIANGLE:
             for (x=0; x<numSamples; x++) {
                 if (x < firstQtr) {
-                    v = (float)x/(firstQtr) * mid + mid;
+                    v = voltage/2 * (float)x/(firstQtr);
+                    v += offset;
                 } else if (x < dcCount) {
-                    v = upp - (float)(x-firstQtr)/(dcCount - firstQtr) * mid;
+                    v = voltage/2 * (float)x/(firstQtr);
+                    v = voltage - (v - offset);
                 } else if (x < lastQtr) {
-                    v = mid - (float)(x-dcCount)/(lastQtr - dcCount) * mid;
+                    v = voltage * (float)(x - dcCount)/(numSamples - dcCount);
+                    v = offset - v;
                 } else {
-                    v = (float)(x-lastQtr)/(numSamples - lastQtr) * mid;
+                    v = voltage * (float)(x - dcCount)/(numSamples - dcCount);
+                    v = v + offset - voltage;
                 }
-                signal[x] = v;
+                VoltSignal[x] = v;
             }
             break;
         case SG_SAWTOOTH:
             for (x=0; x<numSamples; x++) {
                 if (x < dcCount) {
-                    v = (float)x/dcCount * (upp - low)/2 + low;
+                    v = offset - voltage/2 + (float)x/dcCount * voltage/2;
                 } else {
-                    v = (float)(x - dcCount)/(numSamples - dcCount) * (upp - low)/2 + (upp - low)/2;
+                    v = offset + (float)(x - dcCount)/(numSamples - dcCount) *  voltage/2;
                 }
-                signal[x] = v;
+                v = rangelimit(v, minV, maxV);
+                VoltSignal[x] = v;
             }
             break;
         case SG_USER:
             break;
     }
+    //printf("DAC Data %3.2f %3.2f\r\n", voltage, offset);
     for (x=0; x<numSamples; x++) {
-        printf("%3d, %5.3f\r\n", x, signal[x]);
+        DACsignal[x] = ((uint16_t)(VoltSignal[x]/maxV * 1023) << 6) | (1 << 16);
+        //printf("%3d, %5.3f, %d\r\n", x, VoltSignal[x], DACsignal[x]);
     }
+    llio.source = (uint32_t)&DACsignal;
+    llio.destination = (uint32_t)&LPC_DAC->DACR;
+    llio.next = (uint32_t)&llio;
+    llio.control = (1<<26) | (2<<21) | (2<<18) | numSamples;
+
+    LPC_SC->PCONP |= (1<<29);
+
+    /* Enable GPDMA  and sync logic */
+    LPC_GPDMA->DMACConfig = 1;
+    LPC_GPDMA->DMACSync          = (1<<6); 
+
+    /* Load DMA Channel0 */
+    LPC_GPDMACH0->DMACCSrcAddr   = (uint32_t) &DACsignal[0];
+    LPC_GPDMACH0->DMACCDestAddr  = (uint32_t) &LPC_DAC->DACR;
+
+    // Free Running
+    LPC_GPDMACH0->DMACCLLI       = (uint32_t) &llio;
+    // One-Shot
+//    LPC_GPDMACH0->DMACCLLI       = 0;
+    
+    LPC_DAC->DACCNTVAL = numSamples   // transfer size (0 - 11) = 64
+                  | (0 << 12)         // source burst size (12 - 14) = 1
+                  | (0 << 15)         // destination burst size (15 - 17) = 1
+                  | (2 << 18)         // source width (18 - 20) = 32 bit
+                  | (2 << 21)         // destination width (21 - 23) = 32 bit
+                  | (0 << 24)         // source AHB select (24) = AHB 0
+                  | (0 << 25)         // destination AHB select (25) = AHB 0
+                  | (1 << 26)         // source increment (26) = increment
+                  | (0 << 27)         // destination increment (27) = no increment
+                  | (0 << 28)         // mode select (28) = access in user mode
+                  | (0 << 29)         // (29) = access not bufferable
+                  | (0 << 30)         // (30) = access not cacheable
+                  | (0 << 31);        // terminal count interrupt disabled
+
+    LPC_GPDMA->DMACConfig = 1
+                  | (0 << 1)          // source peripheral (1 - 5) = none
+                  | (7 << 6)          // destination peripheral (6 - 10) = DAC
+                  | (1 << 11)         // flow control (11 - 13) = mem to per
+                  | (0 << 14)         // (14) = mask out error interrupt
+                  | (0 << 15)         // (15) = mask out terminal count interrupt
+                  | (0 << 16)         // (16) = no locked transfers
+                  | (0 << 18);        // (27) = no HALT
+
+    /* DACclk = 25 MHz, so 10 usec interval */
+    LPC_DAC->DACCNTVAL = 250;               // 16-bit reload value
+    /* DMA, timer running, dbuff */
+    LPC_DAC->DACCTRL = 
+        1<<3            // DMA_ENA dma burst is enabled
+        | 1<<2          // CNT_ENA Timeout couner is enabled
+        | 1<<1;         // DBLBUF_ENA double-buffering enabled
 }
 
 float SignalGenDAC::rangelimit(float value, float min, float max) {