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:
Mon Jan 16 22:57:59 2017 +0000
Parent:
4:10281ddb673d
Child:
6:1f48212fbaf9
Commit message:
Stable commit before any major refactoring

Changed in this revision

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
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.cpp 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/SignalGenDAC.cpp	Mon Jan 16 21:05:13 2017 +0000
+++ b/SignalGenDAC.cpp	Mon Jan 16 22:57:59 2017 +0000
@@ -3,7 +3,7 @@
 
 DigitalOut led(LED1);
 
-#define PI 3.14159
+#define PI 3.14159      // for the sine-wave
 
 /// The linked list structure used to control the DMA transfer
 ///
@@ -28,17 +28,6 @@
 SignalGenDAC::SignalGenDAC(PinName _aout, float _minV, float _maxV) :
     minV(_minV), maxV(_maxV) {
     aout = new AnalogOut(_aout);
-#if 1
-    #include "mbed.h"
-    aout->write(0.25);
-    wait_ms(25);
-    aout->write(0.50);
-    wait_ms(25);
-    aout->write(0.75);
-    wait_ms(25);
-    aout->write(1.00);
-    wait_ms(25);
-#endif
 }
 
 SignalGenDAC::~SignalGenDAC() {
@@ -68,9 +57,8 @@
     /* Load DMA Channel0 */
     LPC_GPDMACH0->DMACCSrcAddr   = (uint32_t)DACsignal;
     LPC_GPDMACH0->DMACCDestAddr  = (uint32_t)&LPC_DAC->DACR;
-    LPC_GPDMACH0->DMACCLLI       = (uint32_t)&llio;        // Free Running
-    //LPC_GPDMACH0->DMACCLLI       = 0;                     // One-Shot
-    
+    LPC_GPDMACH0->DMACCLLI       = (uint32_t)&llio;
+
     LPC_GPDMACH0->DMACCControl = numSamples   // transfer size (0 - 11) = 64
                   | (0 << 12)         // source burst size (12 - 14) = 1
                   | (0 << 15)         // destination burst size (15 - 17) = 1
@@ -106,13 +94,20 @@
 void SignalGenDAC::Stop(void) {
     printf("Stop()\r\n");
     LPC_GPDMACH0->DMACCLLI       = 0;
+    while (LPC_GPDMACH0->DMACCConfig & 1)
+        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_Mode mode, float _frequency, float _dutycycle, float _voltage, float _offset) {
     int x, dcCount, firstQtr, lastQtr;
+    frequency = _frequency;
+    dutycycle = _dutycycle;
+    voltage = _voltage;
+    offset = _offset;
     float upp = rangelimit(offset + voltage/2, minV, maxV);
     float mid = rangelimit(offset, minV, maxV);
     float low = rangelimit(offset - voltage/2, minV, maxV);
@@ -186,7 +181,9 @@
         DACsignal[x] = ((uint16_t)(VoltSignal[x]/maxV * 1023) << 6);
         printf("%3d, %5.3f, %d\r\n", x, VoltSignal[x], DACsignal[x]);
     }
-    Start(false);
+    if (!isOn) {
+        aout->write(offset / maxV);
+    }
 }
 
 float SignalGenDAC::rangelimit(float value, float min, float max) {
--- a/SignalGenDAC.h	Mon Jan 16 21:05:13 2017 +0000
+++ b/SignalGenDAC.h	Mon Jan 16 22:57:59 2017 +0000
@@ -17,12 +17,15 @@
 public:
 
     /// Constructor, which is used to define the hardware
+    /// 
+    /// The default parameters are based on the mbed LPC1768 micro, which has
+    /// AnalogOut on p18 and uses a 3.3v supply for the A/D reference.
     ///
     /// @param[in] aout is the analog output pin
     /// @param[in] minV is based on the A/D low reference voltage (default 0.0)
-    /// @param[in] maxV is based on the A/D high reference voltage (default 3.0)
+    /// @param[in] maxV is based on the A/D high reference voltage (default 3.3)
     ///
-    SignalGenDAC(PinName aout, float minV = 0.0, float maxV = 3.0);
+    SignalGenDAC(PinName aout = p18, float minV = 0.0, float maxV = 3.3);
 
     /// Destructor
     ///
@@ -59,6 +62,10 @@
 private:
     bool isOn;              // tracks whether the signal is on or off
     AnalogOut * aout;
+    float frequency;        // signal parameters
+    float dutycycle;
+    float voltage;
+    float offset;
     float minV;             // Based on the A/D hardware
     float maxV;             // Based on the A/D hardware
     /// range limit a value.
--- a/SignalGenDisplay.cpp	Mon Jan 16 21:05:13 2017 +0000
+++ b/SignalGenDisplay.cpp	Mon Jan 16 22:57:59 2017 +0000
@@ -63,45 +63,45 @@
 #define BTN_KEYP_Y  53          // Keypad top edge
 
 // Rectangular Zones
-const rect_t UI_START_STOP      = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X + 2 * BTN_W + BTN_S,BTN_KEYP_Y+BTN_H};
-const char * UI_StartLabels[3]  = { "Start", "Stop", "Pulse" };
-const char StartStopKeys[]      = { 'G', 'O', 'P' };
-const rect_t UI_DATA_ENTRY      = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X + 2 * BTN_W + BTN_S,BTN_KEYP_Y+BTN_H};
-const rect_t UI_SCOPE_RECT      = {4,5, 290,160};
+static const rect_t UI_START_STOP      = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X+2*BTN_W+BTN_S,BTN_KEYP_Y+BTN_H};
+static const char * UI_StartLabels[3]  = { "Start", "Stop", "Pulse" };
+static const char StartStopKeys[]      = { 'G', 'O', 'P' };
+static const rect_t UI_DATA_ENTRY      = {BTN_KEYP_X,BTN_KEYP_Y, BTN_KEYP_X+2*BTN_W+BTN_S,BTN_KEYP_Y+BTN_H-2};
+static const rect_t UI_SCOPE_RECT      = {4,5, 290,160};
 
-const rect_t UI_WAVE_RECT       = {4+SC_LEFT_MARGIN,5+SC_TOP_MARGIN, 290-SC_RIGHT_MARGIN,160-SC_BOT_MARGIN};
+static const rect_t UI_WAVE_RECT       = {4+SC_LEFT_MARGIN,5+SC_TOP_MARGIN, 290-SC_RIGHT_MARGIN,160-SC_BOT_MARGIN};
 
-const rect_t Parameters[] = {
+static const rect_t Parameters[] = {
     {4,170, 60,190},            // 'd'uty cycle
     {90,170, 186,190},          // 'f'requency
     {90,200, 186,220},          // 'p'eriod
     {230,170, 290,190},         // 'v'oltage
     {230,200, 290,220}          // 'o'ffset
 };
-const int ParameterCount = sizeof(Parameters)/sizeof(Parameters[0]);
-const char ParameterKeys[] =    { 'd', 'f', 'p', 'v', 'o' };
+static const int ParameterCount = sizeof(Parameters)/sizeof(Parameters[0]);
+static const char ParameterKeys[] =    { 'd', 'f', 'p', 'v', 'o' };
 
-const rect_t UI_PROD_RECT =     {  298,3, 479,51 };
-const rect_t NavToSettings =    {  4,200, 60,220 };
+static const rect_t UI_PROD_RECT =     {  298,3, 479,51 };
+static const rect_t NavToSettings =    {  4,200, 60,220 };
 
 // Mode Buttons
-const rect_t ModeButtons[] = {
+static const rect_t ModeButtons[] = {
     { BTN_MODE_X+0*(BTN_W+BTN_S),BTN_MODE_Y,  BTN_MODE_X+0*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H },
     { BTN_MODE_X+1*(BTN_W+BTN_S),BTN_MODE_Y,  BTN_MODE_X+1*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H },
     { BTN_MODE_X+2*(BTN_W+BTN_S),BTN_MODE_Y,  BTN_MODE_X+2*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H },
     { BTN_MODE_X+3*(BTN_W+BTN_S),BTN_MODE_Y,  BTN_MODE_X+3*(BTN_W+BTN_S)+BTN_W,BTN_MODE_Y+BTN_H },
     { 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 },
 };
-const int ModeCount = sizeof(ModeButtons)/sizeof(ModeButtons[0]);
-SG_Mode UI_ModeList[] = {
+static const int ModeCount = sizeof(ModeButtons)/sizeof(ModeButtons[0]);
+static const SG_Mode UI_ModeList[] = {
     SG_SINE,
     SG_SQUARE,
     SG_TRIANGLE,
     SG_SAWTOOTH,
     SG_USER,
 };
-const char ModeKeys[] = { 'S','Q','T','W','U' };
-const char *ModeNames[] = {
+static const char ModeKeys[] = { 'S','Q','T','W','U' };
+static const char *ModeNames[] = {
     "Sine",
     "Square",
     "Triangle",
@@ -109,7 +109,7 @@
     "User",
 };
 
-const rect_t UI_Keypad[] = {
+static const rect_t UI_Keypad[] = {
     {BTN_KEYP_X+2*(BTN_W+BTN_S),BTN_KEYP_Y+0*(BTN_H+BTN_S), BTN_KEYP_X+2*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+0*(BTN_H+BTN_S)+BTN_H },    // backspace
     {BTN_KEYP_X+0*(BTN_W+BTN_S),BTN_KEYP_Y+1*(BTN_H+BTN_S), BTN_KEYP_X+0*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+1*(BTN_H+BTN_S)+BTN_H },
     {BTN_KEYP_X+1*(BTN_W+BTN_S),BTN_KEYP_Y+1*(BTN_H+BTN_S), BTN_KEYP_X+1*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+1*(BTN_H+BTN_S)+BTN_H },
@@ -127,8 +127,8 @@
     {BTN_KEYP_X+1*(BTN_W+BTN_S),BTN_KEYP_Y+5*(BTN_H+BTN_S), BTN_KEYP_X+1*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+5*(BTN_H+BTN_S)+BTN_H },
     {BTN_KEYP_X+2*(BTN_W+BTN_S),BTN_KEYP_Y+5*(BTN_H+BTN_S), BTN_KEYP_X+2*(BTN_W+BTN_S)+BTN_W,BTN_KEYP_Y+5*(BTN_H+BTN_S)+BTN_H },
 };
-const int KeypadCount = sizeof(UI_Keypad)/sizeof(UI_Keypad[0]);
-const char UI_KeyLabels[] = {
+static const int KeypadCount = sizeof(UI_Keypad)/sizeof(UI_Keypad[0]);
+static const char UI_KeyLabels[] = {
               '\x1B',
     '7', '8', '9',
     '4', '5', '6',
@@ -136,7 +136,7 @@
     '0', '.', '-',
     '\x19', '\x18', '\xB6',
 };
-const char KeyPadKeys[] = { 
+static const char KeyPadKeys[] = { 
               '\x08', 
     '7', '8', '9', 
     '4', '5', '6', 
@@ -169,31 +169,31 @@
 // |                                                                +--------+ |
 // +---------------------------------------------------------------------------+
 
-const point_t suncenter = { 450,85 };
-const rect_t sunray[] = {
+static const point_t suncenter = { 450,85 };
+static const rect_t sunray[] = {
     { 450-2, 85-25, 450+2, 85+25 },
     { 450-25,85-2,  450+25,85+2 }
 };
-const rect_t sungraph = { 450-18,120+0, 450+18,265+0 };
-const rect_t inrgraph = { 450-16,120+2, 450+16,265-2 };
+static const rect_t sungraph = { 450-18,120+0, 450+18,265+0 };
+static const rect_t inrgraph = { 450-16,120+2, 450+16,265-2 };
 
-const rect_t SignalMode =
+static const rect_t SignalMode =
     { 20,50, 20+140,70 };
-const char * SignalModeLabel = "Signal Mode";
+static const char * SignalModeLabel = "Signal Mode";
 
-const rect_t radio_Cycles[] = { 
+static const rect_t radio_Cycles[] = { 
     { 40, 80, 40+120,100 },
     { 40,110, 40+120,130 }
 };
-const int radio_CyclesCount = sizeof(radio_Cycles)/sizeof(radio_Cycles[0]);
-const char * radio_CyclesLabels[] = {
+static const int radio_CyclesCount = sizeof(radio_Cycles)/sizeof(radio_Cycles[0]);
+static const char * PulseModeLabels[] = {
     "Continuous",
     "One-Shot"
 };
 #define UI_CyclesColor              Green
 #define UI_CyclesBackColor          RGB(0,0,0)
 
-// rect_t radio_Cycles[], radio_CyclesCount, char * radio_CyclesLabels[]
+// rect_t radio_Cycles[], radio_CyclesCount, char * PulseModeLabels[]
 
 #define PI 3.1415       // Handy value
 
@@ -363,9 +363,9 @@
         ini.ReadString("Signal", "Offset", buf, sizeof(buf), "1.5");
         offset = atof(buf);
         
-        ini.ReadString("Signal", "Pulse Mode", buf, sizeof(buf), radio_CyclesLabels[0]);
+        ini.ReadString("Signal", "Pulse Mode", buf, sizeof(buf), PulseModeLabels[0]);
         for (int i=0; i<radio_CyclesCount; i++) {
-            if (strcmp(radio_CyclesLabels[i], buf) == 0) {
+            if (strcmp(PulseModeLabels[i], buf) == 0) {
                 pulseMode = i;
                 break;
             }
@@ -404,7 +404,7 @@
     }
 }
 
-// rect_t radio_Cycles[], radio_CyclesCount, char * radio_CyclesLabels[]
+// rect_t radio_Cycles[], radio_CyclesCount, char * PulseModeLabels[]
 
 void SignalGenDisplay::ShowCyclesControl(void) {
     lcd->fillrect(SignalMode, UI_CyclesBackColor);
@@ -417,7 +417,7 @@
         lcd->foreground(UI_CyclesColor);
         lcd->background(UI_CyclesBackColor);
         lcd->SetTextCursor(radio_Cycles[x].p1.x+1,radio_Cycles[x].p1.y+1);
-        lcd->printf("%c %s", (pulseMode == x) ? '\x07' : '\x09', radio_CyclesLabels[x]);
+        lcd->printf("%c %s", (pulseMode == x) ? '\x07' : '\x09', PulseModeLabels[x]);
     }
 }
 
@@ -499,7 +499,7 @@
     printf("    Duty: %f\r\n", dutycycle);
     printf("    Volt: %f\r\n", voltage);
     printf("    Offs: %f\r\n", offset);
-    printf("    Puls: %d - %s\r\n", pulseMode, radio_CyclesLabels[pulseMode]);
+    printf("    Puls: %d - %s\r\n", pulseMode, PulseModeLabels[pulseMode]);
 }
 
 SignalGenDisplay::OM_Changes SignalGenDisplay::Poll(char c) {
@@ -968,9 +968,10 @@
         privDutyCycle = 50;
     }
     privDutyCycleX = privDutyCycle/100.0 * 1*w/2;
+    int cyclesToShow = (pulseMode) ? 1 : 2;
     switch (mode) {
         case SG_SINE:
-            for (int cycle=0; cycle<2; cycle++) {
+            for (int cycle=0; cycle<cyclesToShow; cycle++) {
                 for (x=0; x<=privDutyCycleX; x++) {
                     v = privOffset + privVoltage/2 * sin(x * 1 * PI / privDutyCycleX);
                     v = rangelimit(v, SG_MIN_V, SG_MAX_V);
@@ -986,7 +987,7 @@
             }
             break;
         case SG_SQUARE:
-            for (int cycle=0; cycle<2; cycle++) {
+            for (int cycle=0; cycle<cyclesToShow; cycle++) {
                 loc_t mid = r.p2.y - rangelimit(privOffset, SG_MIN_V, SG_MAX_V) / vRange * h;
                 loc_t upp = r.p2.y - rangelimit(privOffset + privVoltage/2, SG_MIN_V, SG_MAX_V) / vRange * h;
                 loc_t low = r.p2.y - rangelimit(privOffset - privVoltage/2, SG_MIN_V, SG_MAX_V) / vRange * h;
@@ -998,7 +999,7 @@
             }
             break;
         case SG_TRIANGLE:
-            for (int cycle=0; cycle<2; cycle++) {
+            for (int cycle=0; cycle<cyclesToShow; cycle++) {
                 for (x=0; x<=privDutyCycleX; x++) {
                     v = privVoltage * (float)x/privDutyCycleX;
                     if (x < privDutyCycleX/2)
@@ -1021,7 +1022,7 @@
             }
             break;
         case SG_SAWTOOTH:
-            for (int cycle=0; cycle<2; cycle++) {
+            for (int cycle=0; cycle<cyclesToShow; cycle++) {
                 for (x=0; x<=privDutyCycleX; x++) {
                     v = privVoltage/2 * (float)x/privDutyCycleX - privVoltage/2 + privOffset;
                     y = r.p2.y - rangelimit(v, SG_MIN_V, SG_MAX_V) / vRange * h;
@@ -1045,6 +1046,11 @@
             lcd->rect(r.p1.x+5*w/8, y0-a/4, r.p1.x+7*w/8, y0+a/4, color);
             break;
     }
+    if (cyclesToShow != 2) {
+        v = rangelimit(privOffset, SG_MIN_V, SG_MAX_V);
+        y = r.p2.y - 2 * a * v / vRange;
+        lcd->line(r.p1.x + w/2, y, r.p1.x+w,y, color);
+    }
 }
 
 void SignalGenDisplay::ClearScope(void) {
@@ -1269,6 +1275,10 @@
             Changes &= ~ OM_MODE;
             ini.WriteString("Signal", "Waveform", ModeNames[mode]);
         }
+        if (Changes & OM_PULSE) {
+            Changes &= ~ OM_PULSE;
+            ini.WriteString("Signal", "Pulse Mode", PulseModeLabels[pulseMode]);
+        }
         if (Changes & OM_FREQ) {
             Changes &= ~ OM_FREQ;
             snprintf(buf, sizeof(buf),"%5.3f", frequency);
--- a/SignalGenDisplay.h	Mon Jan 16 21:05:13 2017 +0000
+++ b/SignalGenDisplay.h	Mon Jan 16 22:57:59 2017 +0000
@@ -177,14 +177,15 @@
     /// bitmask value, where zero or more bits are set.
     ///
     typedef enum {
-        OM_NONE = 0,    ///< No change in operating mode
-        OM_MODE = 1,    ///< Signal mode changed; Sine, Square, Triangle, Sawtooth, User
-        OM_FREQ = 2,    ///< Change in the frequency
-        OM_PERI = 4,    ///< Change in the period (effectively same as frequency)
-        OM_DUTY = 8,    ///< Change in the duty cycle
-        OM_VOLT = 16,   ///< Change in the peak to peak amplitude
-        OM_OFFS = 32,   ///< Change in the offset voltage
-        OM_BACKL = 64,  ///< Change in the backlight setting
+        OM_NONE     = 0x0000,   ///< No change in operating mode
+        OM_MODE     = 0x0001,   ///< Signal mode changed; Sine, Square, Triangle, Sawtooth, User
+        OM_PULSE    = 0x0002,   ///< Continuous v. Single-shot
+        OM_FREQ     = 0x0004,   ///< Change in the frequency
+        OM_PERI     = 0x0008,   ///< Change in the period (effectively same as frequency)
+        OM_DUTY     = 0x0010,   ///< Change in the duty cycle
+        OM_VOLT     = 0x0020,   ///< Change in the peak to peak amplitude
+        OM_OFFS     = 0x0040,   ///< Change in the offset voltage
+        OM_BACKL    = 0x0080,   ///< Change in the backlight setting
     } OM_Changes;
 
     /// Poll the Signal Generator UI for changes in operation.
@@ -280,4 +281,4 @@
 };
 
 
-#endif // SIGNALGENDISPLAY_H
\ No newline at end of file
+#endif // SIGNALGENVIEW_H
\ No newline at end of file
--- a/main.cpp	Mon Jan 16 21:05:13 2017 +0000
+++ b/main.cpp	Mon Jan 16 22:57:59 2017 +0000
@@ -12,8 +12,7 @@
 
 RawSerial pc(USBTX, USBRX);
 LocalFileSystem local("local");
-//AnalogOut aout(p18);
-SignalGenDAC g_signal(p18);
+SignalGenDAC g_signal;            // defaults to LPC1768 mbed module (p18 and 3.3v)
 SignalGenDisplay ui(&lcd, &g_signal);
 
 Watchdog wd;