Signal Generator

Dependencies:   IniManager RA8875 Watchdog mbed-rtos mbed

Fork of speaker_demo_Analog by jim hamblen

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Sat May 20 19:52:23 2017 +0000
Parent:
5:49dd0c647a40
Commit message:
Signal Generator - a work in process as the need arises.

Changed in this revision

RA8875.lib Show annotated file Show diff for this revision Revisions of this file
SignalGenDAC.cpp Show annotated file Show diff for this revision Revisions of this file
SignalGenDAC.h Show annotated file Show diff for this revision Revisions of this file
SignalGenDefs.h Show annotated file Show diff for this revision Revisions of this file
SignalGenDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
SignalGenDisplay.h Show annotated file Show diff for this revision Revisions of this file
SignalGenModel.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/RA8875.lib	Mon Jan 16 22:57:59 2017 +0000
+++ b/RA8875.lib	Sat May 20 19:52:23 2017 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/WiredHome/code/RA8875/#33ca352755a2
+http://mbed.org/users/WiredHome/code/RA8875/#e872d65a710d
--- a/SignalGenDAC.cpp	Mon Jan 16 22:57:59 2017 +0000
+++ b/SignalGenDAC.cpp	Sat May 20 19:52:23 2017 +0000
@@ -1,8 +1,11 @@
+//
+// Signal Generate DAC Driver
+//
+// Derived from AN10917: Memory to DAC data transfers using the LPC1700's DMA
+// 
 
 #include "SignalGenDAC.h"
 
-DigitalOut led(LED1);
-
 #define PI 3.14159      // for the sine-wave
 
 /// The linked list structure used to control the DMA transfer
@@ -36,13 +39,7 @@
 void SignalGenDAC::Start(bool oneShot) {
     printf("Start(%d) w/%d samples\r\n", oneShot ? 1 : 0, numSamples);
     isOn = (oneShot) ? false : true;
-    led = 1;
     
-    for (int x=0; x<numSamples; x++) {
-        DACsignal[x] = ((uint16_t)(VoltSignal[x]/maxV * 1023) << 6);
-        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;
@@ -57,9 +54,10 @@
     /* Load DMA Channel0 */
     LPC_GPDMACH0->DMACCSrcAddr   = (uint32_t)DACsignal;
     LPC_GPDMACH0->DMACCDestAddr  = (uint32_t)&LPC_DAC->DACR;
-    LPC_GPDMACH0->DMACCLLI       = (uint32_t)&llio;
+    LPC_GPDMACH0->DMACCLLI       = (oneShot) ? 0 : (uint32_t)&llio;
 
-    LPC_GPDMACH0->DMACCControl = numSamples   // transfer size (0 - 11) = 64
+    int playSampleCount = numSamples + oneShot;
+    LPC_GPDMACH0->DMACCControl = playSampleCount  // 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
@@ -83,7 +81,7 @@
                   | (0 << 18);        // (27) = no HALT
 
     /* DACclk = 25 MHz, so 10 usec interval */
-    LPC_DAC->DACCNTVAL = 20;               // 16-bit reload value
+    LPC_DAC->DACCNTVAL = 18;               // 16-bit reload value
     /* DMA, timer running, dbuff */
     LPC_DAC->DACCTRL = 
           1<<3          // DMA_ENA dma burst is enabled
@@ -98,11 +96,10 @@
         wait_ms(1);
     aout->write(offset / maxV);
     isOn = false;
-    led = 0;
 }
 
 
-void SignalGenDAC::PrepareWaveform(SG_Mode mode, float _frequency, float _dutycycle, float _voltage, float _offset) {
+void SignalGenDAC::PrepareWaveform(SG_Waveform mode, float _frequency, float _dutycycle, float _voltage, float _offset) {
     int x, dcCount, firstQtr, lastQtr;
     frequency = _frequency;
     dutycycle = _dutycycle;
@@ -112,7 +109,7 @@
     float mid = rangelimit(offset, minV, maxV);
     float low = rangelimit(offset - voltage/2, minV, maxV);
     float v;
-    numSamples = 32;    // Ideally, compute this based on the frequency for good resolution
+    numSamples = 128;    // Ideally, compute this based on the frequency for good resolution
     dcCount = dutycycle/100.0 * numSamples;
     firstQtr = dcCount / 2;
     lastQtr = dcCount + (numSamples - dcCount)/2;
@@ -133,16 +130,20 @@
                 v = rangelimit(v, minV, maxV);
                 VoltSignal[x] = v;
             }
+            VoltSignal[numSamples] = rangelimit(offset, minV, maxV);
             break;
         case SG_SQUARE:
             for (x=0; x<numSamples; x++) {
-                if (x < dcCount) {
+                if (0 && x == 0) {
+                    v = rangelimit(offset, minV, maxV);                    
+                } else if (x < dcCount) {
                     v = rangelimit(offset + voltage/2, minV, maxV);
                 } else {
                     v = rangelimit(offset - voltage/2, minV, maxV);
                 }
                 VoltSignal[x] = v;
             }
+            VoltSignal[numSamples] = rangelimit(offset, minV, maxV);
             break;
         case SG_TRIANGLE:
             for (x=0; x<numSamples; x++) {
@@ -161,6 +162,7 @@
                 }
                 VoltSignal[x] = v;
             }
+            VoltSignal[numSamples] = rangelimit(offset, minV, maxV);
             break;
         case SG_SAWTOOTH:
             for (x=0; x<numSamples; x++) {
@@ -172,12 +174,13 @@
                 v = rangelimit(v, minV, maxV);
                 VoltSignal[x] = v;
             }
+            VoltSignal[numSamples] = rangelimit(offset, minV, maxV);
             break;
         case SG_USER:
             break;
     }
     //printf("DAC Data %3.2f %3.2f\r\n", voltage, offset);
-    for (x=0; x<numSamples; x++) {
+    for (x=0; x<=numSamples; x++) {
         DACsignal[x] = ((uint16_t)(VoltSignal[x]/maxV * 1023) << 6);
         printf("%3d, %5.3f, %d\r\n", x, VoltSignal[x], DACsignal[x]);
     }
--- a/SignalGenDAC.h	Mon Jan 16 22:57:59 2017 +0000
+++ b/SignalGenDAC.h	Sat May 20 19:52:23 2017 +0000
@@ -1,7 +1,9 @@
-
+//
+// Signal Generator DAC Driver
 //
 // Derived from AN10917: Memory to DAC data transfers using the LPC1700's DMA
 //
+// 
 #ifndef SIGNALGENDAC_H
 #define SIGNALGENDAC_H
 
@@ -12,6 +14,24 @@
 
 #define SIGNAL_MEM_ENTRIES 2048     // size of the DAC buffer
 
+/// The Signal Generator DAC Driver
+///
+/// This class provides the interface to first configure the DAC hardware characteristics,
+/// and then to define and control the DAC output.
+///
+/// A choice of waveforms is available (Sine, Square, Triangle, Sawtooth, and User Defined.
+///
+/// @todo add support for User Defined waveform.
+///
+/// @code
+/// SignalGenDAC g_signal;            // defaults to LPC1768 mbed module (p18 and 3.3v)
+/// 
+/// g_signal.PrepareWaveform(SG_SINE, 1000, 50, 2.2, 1.5);
+/// g_signal.Start();
+/// wait_ms(1000);
+/// g_signal.Stop();
+/// @endcode
+///
 class SignalGenDAC {
 
 public:
@@ -40,7 +60,7 @@
     /// @param[in] voltage is the peak-to-peak voltage, and it range limited to 0 to 3.0.
     /// @param[in] offset is the offset voltage, and is range limited to 0 to 3.0.
     ///
-    void PrepareWaveform(SG_Mode mode, float frequency, float dutycycle, float voltage, float offset);
+    void PrepareWaveform(SG_Waveform mode, float frequency, float dutycycle, float voltage, float offset);
 
     /// Start the signal, in either a oneshot, or continuous mode.
     ///
--- a/SignalGenDefs.h	Mon Jan 16 22:57:59 2017 +0000
+++ b/SignalGenDefs.h	Sat May 20 19:52:23 2017 +0000
@@ -16,6 +16,6 @@
     SG_USER,        ///< User defined waveform
     SG_KEYPAD,      ///< This is an internal value, not for applications
     SG_START,       ///< This is the start/stop/pulse button
-} SG_Mode;
+} SG_Waveform;
 
 #endif // SIGNALGENDEFS_H
--- a/SignalGenDisplay.cpp	Mon Jan 16 22:57:59 2017 +0000
+++ b/SignalGenDisplay.cpp	Sat May 20 19:52:23 2017 +0000
@@ -93,7 +93,7 @@
     { BTN_MODE_X+4*(BTN_W+BTN_S),BTN_MODE_Y,  BTN_MODE_X+4*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H },
 };
 static const int ModeCount = sizeof(ModeButtons)/sizeof(ModeButtons[0]);
-static const SG_Mode UI_ModeList[] = {
+static const SG_Waveform UI_ModeList[] = {
     SG_SINE,
     SG_SQUARE,
     SG_TRIANGLE,
@@ -317,6 +317,7 @@
                         for (int i=0; i<radio_CyclesCount; i++) {
                             if (lcd->Intersect(radio_Cycles[i], point)) {
                                 pulseMode = i;
+                                SaveSettings(OM_PULSE);
                                 signal->Stop();
                                 ShowCyclesControl();
                             }
@@ -346,7 +347,7 @@
         ini.ReadString("Signal", "Waveform", buf, sizeof(buf), ModeNames[0]);
         for (int i=0; i<ModeCount; i++) {
             if (strcmp(ModeNames[i], buf) == 0) {
-                mode = (SG_Mode)i;
+                mode = (SG_Waveform)i;
                 printf("Read ini mode is %d\r\n", mode);
                 break;
             }
@@ -761,7 +762,7 @@
     return ret;
 }
 
-bool SignalGenDisplay::SetWaveformMode(SG_Mode _mode, bool force) {
+bool SignalGenDisplay::SetWaveformMode(SG_Waveform _mode, bool force) {
     if (/* _mode >= SG_SINE && */ _mode <= SG_USER) {
         mode = _mode;
         printf("mode is %d\r\n", mode);
@@ -949,7 +950,7 @@
 //           .             |    |          \ /     /    |
 //            ++           +----+           +     +     +
 //
-void SignalGenDisplay::DrawWaveform(rect_t r, SG_Mode mode, color_t color, bool drawPure) {
+void SignalGenDisplay::DrawWaveform(rect_t r, SG_Waveform mode, color_t color, bool drawPure) {
     loc_t x,y;
     loc_t y0 = (r.p1.y + r.p2.y)/2;
     dim_t w = r.p2.x - r.p1.x;
@@ -1165,7 +1166,7 @@
     }
 }
 
-void SignalGenDisplay::DrawButton(rect_t r, bool pressed, SG_Mode mode, bool enable, int label) {
+void SignalGenDisplay::DrawButton(rect_t r, bool pressed, SG_Waveform mode, bool enable, int label) {
     rect_t wave;
     color_t buttonface = UI_BUTTON_FACE_DISABLED;
     color_t buttonshadow = UI_BUTTON_SHADOW_DISABLED;
@@ -1273,10 +1274,12 @@
         printf("SaveSettings - timeout [%02X]\r\n", Changes);
         if (Changes & OM_MODE) {
             Changes &= ~ OM_MODE;
+            printf("  Signal:Waveform=%s\r\n", ModeNames[mode]);
             ini.WriteString("Signal", "Waveform", ModeNames[mode]);
         }
         if (Changes & OM_PULSE) {
             Changes &= ~ OM_PULSE;
+            printf("  Signal:Pulse Mode=%s\r\n", PulseModeLabels[pulseMode]);
             ini.WriteString("Signal", "Pulse Mode", PulseModeLabels[pulseMode]);
         }
         if (Changes & OM_FREQ) {
--- a/SignalGenDisplay.h	Mon Jan 16 22:57:59 2017 +0000
+++ b/SignalGenDisplay.h	Sat May 20 19:52:23 2017 +0000
@@ -169,7 +169,7 @@
     /// @param[in] force as true will force it to set the mode, redrawing the screen
     /// @returns true if the value was accepted
     ///
-    bool SetWaveformMode(SG_Mode mode, bool force = false);
+    bool SetWaveformMode(SG_Waveform mode, bool force = false);
     
     /// Operating mode changes
     ///
@@ -226,7 +226,7 @@
         VS_Settings,
     } VisualScreen;
     VisualScreen vis;
-    SG_Mode mode;       ///< signal mode
+    SG_Waveform mode;       ///< signal mode
     float frequency;    ///< selected frequency
     float dutycycle;    ///< selected duty cycle
     float voltage;      ///< selected voltage
@@ -266,8 +266,8 @@
     void DrawNavGadget(void);
     void DrawModeButtons(void);
     void DrawKeypadEnabled(bool enable = false);
-    void DrawButton(rect_t r, bool pressed, SG_Mode mode, bool enable = false, int label=0);
-    void DrawWaveform(rect_t r, SG_Mode mode, color_t color, bool drawPure = false);    // pure ignores, voltage,offset,dutycycle
+    void DrawButton(rect_t r, bool pressed, SG_Waveform mode, bool enable = false, int label=0);
+    void DrawWaveform(rect_t r, SG_Waveform mode, color_t color, bool drawPure = false);    // pure ignores, voltage,offset,dutycycle
     float rangelimit(float value, float minV, float maxV);
     void ShowCyclesControl(void);
     
--- a/SignalGenModel.h	Mon Jan 16 22:57:59 2017 +0000
+++ b/SignalGenModel.h	Sat May 20 19:52:23 2017 +0000
@@ -0,0 +1,5 @@
+//
+//
+// In the transition to an improved architecture, this will be the interface/glue
+// between the DAC driver and the User Interface.
+//
--- a/main.cpp	Mon Jan 16 22:57:59 2017 +0000
+++ b/main.cpp	Sat May 20 19:52:23 2017 +0000
@@ -26,16 +26,6 @@
     wd.Configure(30.0);
     //ini.SetFile("/local/SigGen.ini", 2);
 
-#if 0
-    aout = 0.25;
-    wait_ms(25);
-    aout = 0.50;
-    wait_ms(25);
-    aout = 0.75;
-    wait_ms(25);
-    aout = 1.00;
-    wait_ms(25);
-#endif
     lcd.init(480,272,16, true, true, true);
     while (true)
     {