Signal Generator

Dependencies:   IniManager RA8875 Watchdog mbed-rtos mbed

Fork of speaker_demo_Analog by jim hamblen

Revision:
2:8f71b71fce1b
Child:
3:d22f3e52d06a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SignalGenDAC.cpp	Sun Jan 15 03:11:22 2017 +0000
@@ -0,0 +1,118 @@
+
+#include "SignalGenDAC.h"
+
+#define PI 3.14159
+
+/// The linked list structure used to control the DMA transfer
+///
+typedef struct {
+    uint32_t  source;     /// start of source area
+    uint32_t  destination;/// start of destination area
+    uint32_t  next;       /// address of next strLLI in chain
+    uint32_t  control;    /// DMACCxControl register
+} LinkListItem_t;    
+
+/// The signal memory, which is DMA sent to the DAC to play the waveform
+///
+float /*signed long*/ signal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0")));
+
+/// The linked list item record, used by the DMA engine to decide how to play
+///
+LinkListItem_t llio __attribute__ ((section("AHBSRAM0")));
+
+
+SignalGenDAC::SignalGenDAC(PinName _aout, float _minV, float _maxV) :
+    minV(_minV), maxV(_maxV) {
+    aout = new AnalogOut(_aout);
+}
+
+SignalGenDAC::~SignalGenDAC() {
+}
+
+void SignalGenDAC::Start(bool oneShot) {
+}
+
+void SignalGenDAC::Stop(void) {
+}
+
+
+void SignalGenDAC::PrepareWaveform(SG_Mode mode, float frequency, float dutycycle, float voltage, float offset) {
+    int x, dcCount, firstQtr, lastQtr;
+    float upp = rangelimit(offset + voltage/2, minV, maxV);
+    float mid = rangelimit(offset, minV, maxV);
+    float low = rangelimit(offset - voltage/2, minV, maxV);
+    float v;
+    int numSamples = 32;    // Ideally, compute this based on the frequency for good resolution
+    dcCount = dutycycle/100.0 * numSamples;
+    firstQtr = dcCount / 2;
+    lastQtr = dcCount + (numSamples - dcCount)/2;
+    
+    // Set the timebased based on the frequency
+    if (isOn) {
+        // stop the signal during the change
+        isOn = false;
+    }
+    switch (mode) {
+        case SG_SINE:
+            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;
+            }
+            break;
+        case SG_SQUARE:
+            for (x=0; x<numSamples; x++) {
+                if (x < dcCount) {
+                    v = rangelimit(offset + voltage/2, minV, maxV);
+                } else {
+                    v = rangelimit(offset - voltage/2, minV, maxV);
+                }
+                signal[x] = v;
+            }
+            break;
+        case SG_TRIANGLE:
+            for (x=0; x<numSamples; x++) {
+                if (x < firstQtr) {
+                    v = (float)x/(firstQtr) * mid + mid;
+                } else if (x < dcCount) {
+                    v = upp - (float)(x-firstQtr)/(dcCount - firstQtr) * mid;
+                } else if (x < lastQtr) {
+                    v = mid - (float)(x-dcCount)/(lastQtr - dcCount) * mid;
+                } else {
+                    v = (float)(x-lastQtr)/(numSamples - lastQtr) * mid;
+                }
+                signal[x] = v;
+            }
+            break;
+        case SG_SAWTOOTH:
+            for (x=0; x<numSamples; x++) {
+                if (x < dcCount) {
+                    v = (float)x/dcCount * (upp - low)/2 + low;
+                } else {
+                    v = (float)(x - dcCount)/(numSamples - dcCount) * (upp - low)/2 + (upp - low)/2;
+                }
+                signal[x] = v;
+            }
+            break;
+        case SG_USER:
+            break;
+    }
+    for (x=0; x<numSamples; x++) {
+        printf("%3d, %5.3f\r\n", x, signal[x]);
+    }
+}
+
+float SignalGenDAC::rangelimit(float value, float min, float max) {
+    if (value < min)
+        return min;
+    else if (value > max)
+        return max;
+    else
+        return value;
+}
+